Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef vm_SharedMem_h
8 : #define vm_SharedMem_h
9 :
10 : #include "mozilla/TypeTraits.h"
11 :
12 : template<typename T>
13 : class SharedMem
14 : {
15 : // static_assert(mozilla::IsPointer<T>::value,
16 : // "SharedMem encapsulates pointer types");
17 :
18 : enum Sharedness {
19 : IsUnshared,
20 : IsShared
21 : };
22 :
23 : T ptr_;
24 : #ifdef DEBUG
25 : Sharedness sharedness_;
26 : #endif
27 :
28 0 : SharedMem(T ptr, Sharedness sharedness)
29 : : ptr_(ptr)
30 : #ifdef DEBUG
31 0 : , sharedness_(sharedness)
32 : #endif
33 0 : {}
34 :
35 : public:
36 : // Create a SharedMem<T> that is an unshared nullptr.
37 : SharedMem()
38 : : ptr_(nullptr)
39 : #ifdef DEBUG
40 : , sharedness_(IsUnshared)
41 : #endif
42 : {}
43 :
44 : // Create a SharedMem<T> that's shared/unshared in the same way as
45 : // "forSharedness".
46 0 : SharedMem(T ptr, const SharedMem& forSharedness)
47 : : ptr_(ptr)
48 : #ifdef DEBUG
49 0 : , sharedness_(forSharedness.sharedness_)
50 : #endif
51 0 : {}
52 :
53 : // Create a SharedMem<T> that's marked as shared.
54 0 : static SharedMem shared(void* p) {
55 0 : return SharedMem(static_cast<T>(p), IsShared);
56 : }
57 :
58 : // Create a SharedMem<T> that's marked as unshared.
59 0 : static SharedMem unshared(void* p) {
60 0 : return SharedMem(static_cast<T>(p), IsUnshared);
61 : }
62 :
63 : SharedMem& operator =(const SharedMem& that) {
64 : ptr_ = that.ptr_;
65 : #ifdef DEBUG
66 : sharedness_ = that.sharedness_;
67 : #endif
68 : return *this;
69 : }
70 :
71 : // Reinterpret-cast the pointer to type U, preserving sharedness.
72 : // Eg, "obj->dataPointerEither().cast<uint8_t*>()" yields a SharedMem<uint8_t*>.
73 : template<typename U>
74 0 : inline SharedMem<U> cast() const {
75 : #ifdef DEBUG
76 0 : MOZ_ASSERT(asValue() % sizeof(mozilla::Conditional<mozilla::IsVoid<typename mozilla::RemovePointer<U>::Type>::value,
77 : char,
78 : typename mozilla::RemovePointer<U>::Type>) == 0);
79 0 : if (sharedness_ == IsUnshared)
80 0 : return SharedMem<U>::unshared(unwrap());
81 : #endif
82 0 : return SharedMem<U>::shared(unwrap());
83 : }
84 :
85 0 : explicit operator bool() { return ptr_ != nullptr; }
86 :
87 0 : SharedMem operator +(size_t offset) {
88 0 : return SharedMem(ptr_ + offset, *this);
89 : }
90 :
91 0 : SharedMem operator -(size_t offset) {
92 0 : return SharedMem(ptr_ - offset, *this);
93 : }
94 :
95 : SharedMem operator ++() {
96 : ptr_++;
97 : return *this;
98 : }
99 :
100 0 : SharedMem operator ++(int) {
101 0 : SharedMem<T> result(*this);
102 0 : ptr_++;
103 0 : return result;
104 : }
105 :
106 : SharedMem operator --() {
107 : ptr_--;
108 : return *this;
109 : }
110 :
111 : SharedMem operator --(int) {
112 : SharedMem<T> result(*this);
113 : ptr_--;
114 : return result;
115 : }
116 :
117 0 : uintptr_t asValue() const {
118 0 : return reinterpret_cast<uintptr_t>(ptr_);
119 : }
120 :
121 : // Cast to char*, add nbytes, and cast back to T. Simplifies code in a few places.
122 0 : SharedMem addBytes(size_t nbytes) {
123 : MOZ_ASSERT(nbytes % sizeof(mozilla::Conditional<mozilla::IsVoid<typename mozilla::RemovePointer<T>::Type>::value,
124 : char,
125 : typename mozilla::RemovePointer<T>::Type>) == 0);
126 0 : return SharedMem(reinterpret_cast<T>(reinterpret_cast<char*>(ptr_) + nbytes), *this);
127 : }
128 :
129 0 : T unwrap() const {
130 0 : return ptr_;
131 : }
132 :
133 0 : T unwrapUnshared() const {
134 0 : MOZ_ASSERT(sharedness_ == IsUnshared);
135 0 : return ptr_;
136 : }
137 :
138 0 : uintptr_t unwrapValue() const {
139 0 : return reinterpret_cast<uintptr_t>(ptr_);
140 : }
141 : };
142 :
143 : template<typename T>
144 : inline bool
145 0 : operator >=(const SharedMem<T>& a, const SharedMem<T>& b)
146 : {
147 0 : return a.unwrap() >= b.unwrap();
148 : }
149 :
150 : template<typename T>
151 : inline bool
152 0 : operator >=(const void* a, const SharedMem<T>& b)
153 : {
154 0 : return a >= b.unwrap();
155 : }
156 :
157 : template<typename T>
158 : inline bool
159 0 : operator ==(const void* a, const SharedMem<T>& b)
160 : {
161 0 : return a == b.unwrap();
162 : }
163 :
164 : template<typename T>
165 : inline bool
166 : operator ==(const SharedMem<T>& a, decltype(nullptr) b)
167 : {
168 : return a.unwrap() == b;
169 : }
170 :
171 : template<typename T>
172 : inline bool
173 0 : operator ==(const SharedMem<T>& a, const SharedMem<T>& b)
174 : {
175 0 : return a.unwrap() == b.unwrap();
176 : }
177 :
178 : template<typename T>
179 : inline bool
180 : operator !=(const SharedMem<T>& a, decltype(nullptr) b)
181 : {
182 : return a.unwrap() != b;
183 : }
184 :
185 : template<typename T>
186 : inline bool
187 0 : operator !=(const SharedMem<T>& a, const SharedMem<T>& b)
188 : {
189 0 : return a.unwrap() != b.unwrap();
190 : }
191 :
192 : template<typename T>
193 : inline bool
194 0 : operator >(const SharedMem<T>& a, const SharedMem<T>& b)
195 : {
196 0 : return a.unwrap() > b.unwrap();
197 : }
198 :
199 : template<typename T>
200 : inline bool
201 0 : operator >(const void* a, const SharedMem<T>& b)
202 : {
203 0 : return a > b.unwrap();
204 : }
205 :
206 : template<typename T>
207 : inline bool
208 0 : operator <=(const SharedMem<T>& a, const SharedMem<T>& b)
209 : {
210 0 : return a.unwrap() <= b.unwrap();
211 : }
212 :
213 : template<typename T>
214 : inline bool
215 0 : operator <=(const void* a, const SharedMem<T>& b)
216 : {
217 0 : return a <= b.unwrap();
218 : }
219 :
220 : template<typename T>
221 : inline bool
222 0 : operator <(const void* a, const SharedMem<T>& b)
223 : {
224 0 : return a < b.unwrap();
225 : }
226 :
227 : #endif // vm_SharedMem_h
|