37 // A decorator is an attribute or property that affects the way a memory access is performed in some way.
38 // There are different groups of decorators. Some have to do with memory ordering, others to do with,
39 // e.g. strength of references, strength of GC barriers, or whether compression should be applied or not.
40 // Some decorators are set at buildtime, such as whether primitives require GC barriers or not, others
41 // at callsites such as whether an access is in the heap or not, and others are resolved at runtime
42 // such as GC-specific barriers and encoding/decoding compressed oops. For more information about what
43 // decorators are available, cf. oops/accessDecorators.hpp.
44 // By pipelining handling of these decorators, the design of the Access API allows separation of concern
45 // over the different orthogonal concerns of decorators, while providing a powerful way of
46 // expressing these orthogonal semantic properties in a unified way.
47 //
48 // == OPERATIONS ==
49 // * load: Load a value from an address.
50 // * load_at: Load a value from an internal pointer relative to a base object.
51 // * store: Store a value at an address.
52 // * store_at: Store a value in an internal pointer relative to a base object.
53 // * atomic_cmpxchg: Atomically compare-and-swap a new value at an address if previous value matched the compared value.
54 // * atomic_cmpxchg_at: Atomically compare-and-swap a new value at an internal pointer address if previous value matched the compared
55 // * atomic_xchg: Atomically swap a new value at an address if previous value matched the compared value.
56 // * atomic_xchg_at: Atomically swap a new value at an internal pointer address if previous value matched the compared value.
57 // * arraycopy: Copy data from one heap array to another heap array.
58 // * clone: Clone the contents of an object to a newly allocated object.
59 // * resolve: Resolve a stable to-space invariant oop that is guaranteed not to relocate its payload until a subsequent thread transi
60 // * equals: Object equality, e.g. when different copies of the same objects are in use (from-space vs. to-space)
61 //
62 // == IMPLEMENTATION ==
63 // Each access goes through the following steps in a template pipeline.
64 // There are essentially 5 steps for each access:
65 // * Step 1: Set default decorators and decay types. This step gets rid of CV qualifiers
66 // and sets default decorators to sensible values.
67 // * Step 2: Reduce types. This step makes sure there is only a single T type and not
68 // multiple types. The P type of the address and T type of the value must
69 // match.
70 // * Step 3: Pre-runtime dispatch. This step checks whether a runtime call can be
71 // avoided, and in that case avoids it (calling raw accesses or
72 // primitive accesses in a build that does not require primitive GC barriers)
73 // * Step 4: Runtime-dispatch. This step performs a runtime dispatch to the corresponding
74 // BarrierSet::AccessBarrier accessor that attaches GC-required barriers
75 // to the access.
76 // * Step 5.a: Barrier resolution. This step is invoked the first time a runtime-dispatch
|
37 // A decorator is an attribute or property that affects the way a memory access is performed in some way.
38 // There are different groups of decorators. Some have to do with memory ordering, others to do with,
39 // e.g. strength of references, strength of GC barriers, or whether compression should be applied or not.
40 // Some decorators are set at buildtime, such as whether primitives require GC barriers or not, others
41 // at callsites such as whether an access is in the heap or not, and others are resolved at runtime
42 // such as GC-specific barriers and encoding/decoding compressed oops. For more information about what
43 // decorators are available, cf. oops/accessDecorators.hpp.
44 // By pipelining handling of these decorators, the design of the Access API allows separation of concern
45 // over the different orthogonal concerns of decorators, while providing a powerful way of
46 // expressing these orthogonal semantic properties in a unified way.
47 //
48 // == OPERATIONS ==
49 // * load: Load a value from an address.
50 // * load_at: Load a value from an internal pointer relative to a base object.
51 // * store: Store a value at an address.
52 // * store_at: Store a value in an internal pointer relative to a base object.
53 // * atomic_cmpxchg: Atomically compare-and-swap a new value at an address if previous value matched the compared value.
54 // * atomic_cmpxchg_at: Atomically compare-and-swap a new value at an internal pointer address if previous value matched the compared
55 // * atomic_xchg: Atomically swap a new value at an address if previous value matched the compared value.
56 // * atomic_xchg_at: Atomically swap a new value at an internal pointer address if previous value matched the compared value.
57 // * arraycopy: Copy data from one heap array to another heap array. The ArrayAccess class has convenience functions for this.
58 // * clone: Clone the contents of an object to a newly allocated object.
59 // * resolve: Resolve a stable to-space invariant oop that is guaranteed not to relocate its payload until a subsequent thread transi
60 // * equals: Object equality, e.g. when different copies of the same objects are in use (from-space vs. to-space)
61 //
62 // == IMPLEMENTATION ==
63 // Each access goes through the following steps in a template pipeline.
64 // There are essentially 5 steps for each access:
65 // * Step 1: Set default decorators and decay types. This step gets rid of CV qualifiers
66 // and sets default decorators to sensible values.
67 // * Step 2: Reduce types. This step makes sure there is only a single T type and not
68 // multiple types. The P type of the address and T type of the value must
69 // match.
70 // * Step 3: Pre-runtime dispatch. This step checks whether a runtime call can be
71 // avoided, and in that case avoids it (calling raw accesses or
72 // primitive accesses in a build that does not require primitive GC barriers)
73 // * Step 4: Runtime-dispatch. This step performs a runtime dispatch to the corresponding
74 // BarrierSet::AccessBarrier accessor that attaches GC-required barriers
75 // to the access.
76 // * Step 5.a: Barrier resolution. This step is invoked the first time a runtime-dispatch
|
112 static void verify_oop_decorators() {
113 const DecoratorSet oop_decorators = AS_DECORATOR_MASK | IN_DECORATOR_MASK |
114 (ON_DECORATOR_MASK ^ ON_UNKNOWN_OOP_REF) | // no unknown oop refs outside of the heap
115 OOP_DECORATOR_MASK;
116 verify_decorators<expected_mo_decorators | oop_decorators>();
117 }
118
119 template <DecoratorSet expected_mo_decorators>
120 static void verify_heap_oop_decorators() {
121 const DecoratorSet heap_oop_decorators = AS_DECORATOR_MASK | ON_DECORATOR_MASK |
122 OOP_DECORATOR_MASK | (IN_DECORATOR_MASK ^
123 (IN_ROOT | IN_CONCURRENT_ROOT)); // no root accesses in the heap
124 verify_decorators<expected_mo_decorators | heap_oop_decorators>();
125 }
126
127 static const DecoratorSet load_mo_decorators = MO_UNORDERED | MO_VOLATILE | MO_RELAXED | MO_ACQUIRE | MO_SEQ_CST;
128 static const DecoratorSet store_mo_decorators = MO_UNORDERED | MO_VOLATILE | MO_RELAXED | MO_RELEASE | MO_SEQ_CST;
129 static const DecoratorSet atomic_xchg_mo_decorators = MO_SEQ_CST;
130 static const DecoratorSet atomic_cmpxchg_mo_decorators = MO_RELAXED | MO_SEQ_CST;
131
132 public:
133 // Primitive heap accesses
134 static inline AccessInternal::LoadAtProxy<decorators> load_at(oop base, ptrdiff_t offset) {
135 verify_primitive_decorators<load_mo_decorators>();
136 return AccessInternal::LoadAtProxy<decorators>(base, offset);
137 }
138
139 template <typename T>
140 static inline void store_at(oop base, ptrdiff_t offset, T value) {
141 verify_primitive_decorators<store_mo_decorators>();
142 AccessInternal::store_at<decorators>(base, offset, value);
143 }
144
145 template <typename T>
146 static inline T atomic_cmpxchg_at(T new_value, oop base, ptrdiff_t offset, T compare_value) {
147 verify_primitive_decorators<atomic_cmpxchg_mo_decorators>();
148 return AccessInternal::atomic_cmpxchg_at<decorators>(new_value, base, offset, compare_value);
149 }
150
151 template <typename T>
152 static inline T atomic_xchg_at(T new_value, oop base, ptrdiff_t offset) {
153 verify_primitive_decorators<atomic_xchg_mo_decorators>();
154 return AccessInternal::atomic_xchg_at<decorators>(new_value, base, offset);
155 }
156
157 template <typename T>
158 static inline void arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, const T* src_raw,
159 arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
160 size_t length) {
161 verify_decorators<ARRAYCOPY_DECORATOR_MASK | IN_HEAP | IN_HEAP_ARRAY |
162 AS_DECORATOR_MASK>();
163 AccessInternal::arraycopy<decorators>(src_obj, src_offset_in_bytes, src_raw,
164 dst_obj, dst_offset_in_bytes, dst_raw,
165 length);
166 }
167
168 // Oop heap accesses
169 static inline AccessInternal::OopLoadAtProxy<decorators> oop_load_at(oop base, ptrdiff_t offset) {
170 verify_heap_oop_decorators<load_mo_decorators>();
171 return AccessInternal::OopLoadAtProxy<decorators>(base, offset);
172 }
173
174 template <typename T>
175 static inline void oop_store_at(oop base, ptrdiff_t offset, T value) {
176 verify_heap_oop_decorators<store_mo_decorators>();
177 typedef typename AccessInternal::OopOrNarrowOop<T>::type OopType;
178 OopType oop_value = value;
179 AccessInternal::store_at<decorators | INTERNAL_VALUE_IS_OOP>(base, offset, oop_value);
180 }
181
182 template <typename T>
183 static inline T oop_atomic_cmpxchg_at(T new_value, oop base, ptrdiff_t offset, T compare_value) {
184 verify_heap_oop_decorators<atomic_cmpxchg_mo_decorators>();
185 typedef typename AccessInternal::OopOrNarrowOop<T>::type OopType;
186 OopType new_oop_value = new_value;
187 OopType compare_oop_value = compare_value;
188 return AccessInternal::atomic_cmpxchg_at<decorators | INTERNAL_VALUE_IS_OOP>(new_oop_value, base, offset, compare_oop_value);
189 }
190
191 template <typename T>
192 static inline T oop_atomic_xchg_at(T new_value, oop base, ptrdiff_t offset) {
193 verify_heap_oop_decorators<atomic_xchg_mo_decorators>();
194 typedef typename AccessInternal::OopOrNarrowOop<T>::type OopType;
195 OopType new_oop_value = new_value;
196 return AccessInternal::atomic_xchg_at<decorators | INTERNAL_VALUE_IS_OOP>(new_oop_value, base, offset);
197 }
198
199 template <typename T>
200 static inline bool oop_arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, const T* src_raw,
201 arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
202 size_t length) {
203 verify_decorators<ARRAYCOPY_DECORATOR_MASK | IN_HEAP | IN_HEAP_ARRAY |
204 AS_DECORATOR_MASK>();
205 return AccessInternal::arraycopy<decorators | INTERNAL_VALUE_IS_OOP>(src_obj, src_offset_in_bytes, src_raw,
206 dst_obj, dst_offset_in_bytes, dst_raw,
207 length);
208 }
209
210 // Clone an object from src to dst
211 static inline void clone(oop src, oop dst, size_t size) {
212 verify_decorators<IN_HEAP>();
213 AccessInternal::clone<decorators>(src, dst, size);
214 }
215
216 // Primitive accesses
217 template <typename P>
218 static inline P load(P* addr) {
219 verify_primitive_decorators<load_mo_decorators>();
220 return AccessInternal::load<decorators, P, P>(addr);
221 }
222
223 template <typename P, typename T>
224 static inline void store(P* addr, T value) {
225 verify_primitive_decorators<store_mo_decorators>();
226 AccessInternal::store<decorators>(addr, value);
227 }
228
|
112 static void verify_oop_decorators() {
113 const DecoratorSet oop_decorators = AS_DECORATOR_MASK | IN_DECORATOR_MASK |
114 (ON_DECORATOR_MASK ^ ON_UNKNOWN_OOP_REF) | // no unknown oop refs outside of the heap
115 OOP_DECORATOR_MASK;
116 verify_decorators<expected_mo_decorators | oop_decorators>();
117 }
118
119 template <DecoratorSet expected_mo_decorators>
120 static void verify_heap_oop_decorators() {
121 const DecoratorSet heap_oop_decorators = AS_DECORATOR_MASK | ON_DECORATOR_MASK |
122 OOP_DECORATOR_MASK | (IN_DECORATOR_MASK ^
123 (IN_ROOT | IN_CONCURRENT_ROOT)); // no root accesses in the heap
124 verify_decorators<expected_mo_decorators | heap_oop_decorators>();
125 }
126
127 static const DecoratorSet load_mo_decorators = MO_UNORDERED | MO_VOLATILE | MO_RELAXED | MO_ACQUIRE | MO_SEQ_CST;
128 static const DecoratorSet store_mo_decorators = MO_UNORDERED | MO_VOLATILE | MO_RELAXED | MO_RELEASE | MO_SEQ_CST;
129 static const DecoratorSet atomic_xchg_mo_decorators = MO_SEQ_CST;
130 static const DecoratorSet atomic_cmpxchg_mo_decorators = MO_RELAXED | MO_SEQ_CST;
131
132 protected:
133 template <typename T>
134 static inline bool oop_arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, const T* src_raw,
135 arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
136 size_t length) {
137 verify_decorators<ARRAYCOPY_DECORATOR_MASK | IN_HEAP | IN_HEAP_ARRAY |
138 AS_DECORATOR_MASK>();
139 return AccessInternal::arraycopy<decorators | INTERNAL_VALUE_IS_OOP>(src_obj, src_offset_in_bytes, src_raw,
140 dst_obj, dst_offset_in_bytes, dst_raw,
141 length);
142 }
143
144 template <typename T>
145 static inline void arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, const T* src_raw,
146 arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
147 size_t length) {
148 verify_decorators<ARRAYCOPY_DECORATOR_MASK | IN_HEAP | IN_HEAP_ARRAY |
149 AS_DECORATOR_MASK>();
150 AccessInternal::arraycopy<decorators>(src_obj, src_offset_in_bytes, src_raw,
151 dst_obj, dst_offset_in_bytes, dst_raw,
152 length);
153 }
154
155 public:
156 // Primitive heap accesses
157 static inline AccessInternal::LoadAtProxy<decorators> load_at(oop base, ptrdiff_t offset) {
158 verify_primitive_decorators<load_mo_decorators>();
159 return AccessInternal::LoadAtProxy<decorators>(base, offset);
160 }
161
162 template <typename T>
163 static inline void store_at(oop base, ptrdiff_t offset, T value) {
164 verify_primitive_decorators<store_mo_decorators>();
165 AccessInternal::store_at<decorators>(base, offset, value);
166 }
167
168 template <typename T>
169 static inline T atomic_cmpxchg_at(T new_value, oop base, ptrdiff_t offset, T compare_value) {
170 verify_primitive_decorators<atomic_cmpxchg_mo_decorators>();
171 return AccessInternal::atomic_cmpxchg_at<decorators>(new_value, base, offset, compare_value);
172 }
173
174 template <typename T>
175 static inline T atomic_xchg_at(T new_value, oop base, ptrdiff_t offset) {
176 verify_primitive_decorators<atomic_xchg_mo_decorators>();
177 return AccessInternal::atomic_xchg_at<decorators>(new_value, base, offset);
178 }
179
180 // Oop heap accesses
181 static inline AccessInternal::OopLoadAtProxy<decorators> oop_load_at(oop base, ptrdiff_t offset) {
182 verify_heap_oop_decorators<load_mo_decorators>();
183 return AccessInternal::OopLoadAtProxy<decorators>(base, offset);
184 }
185
186 template <typename T>
187 static inline void oop_store_at(oop base, ptrdiff_t offset, T value) {
188 verify_heap_oop_decorators<store_mo_decorators>();
189 typedef typename AccessInternal::OopOrNarrowOop<T>::type OopType;
190 OopType oop_value = value;
191 AccessInternal::store_at<decorators | INTERNAL_VALUE_IS_OOP>(base, offset, oop_value);
192 }
193
194 template <typename T>
195 static inline T oop_atomic_cmpxchg_at(T new_value, oop base, ptrdiff_t offset, T compare_value) {
196 verify_heap_oop_decorators<atomic_cmpxchg_mo_decorators>();
197 typedef typename AccessInternal::OopOrNarrowOop<T>::type OopType;
198 OopType new_oop_value = new_value;
199 OopType compare_oop_value = compare_value;
200 return AccessInternal::atomic_cmpxchg_at<decorators | INTERNAL_VALUE_IS_OOP>(new_oop_value, base, offset, compare_oop_value);
201 }
202
203 template <typename T>
204 static inline T oop_atomic_xchg_at(T new_value, oop base, ptrdiff_t offset) {
205 verify_heap_oop_decorators<atomic_xchg_mo_decorators>();
206 typedef typename AccessInternal::OopOrNarrowOop<T>::type OopType;
207 OopType new_oop_value = new_value;
208 return AccessInternal::atomic_xchg_at<decorators | INTERNAL_VALUE_IS_OOP>(new_oop_value, base, offset);
209 }
210
211 // Clone an object from src to dst
212 static inline void clone(oop src, oop dst, size_t size) {
213 verify_decorators<IN_HEAP>();
214 AccessInternal::clone<decorators>(src, dst, size);
215 }
216
217 // Primitive accesses
218 template <typename P>
219 static inline P load(P* addr) {
220 verify_primitive_decorators<load_mo_decorators>();
221 return AccessInternal::load<decorators, P, P>(addr);
222 }
223
224 template <typename P, typename T>
225 static inline void store(P* addr, T value) {
226 verify_primitive_decorators<store_mo_decorators>();
227 AccessInternal::store<decorators>(addr, value);
228 }
229
|
282 };
283
284 // Helper for performing raw accesses (knows only of memory ordering
285 // atomicity decorators as well as compressed oops)
286 template <DecoratorSet decorators = INTERNAL_EMPTY>
287 class RawAccess: public Access<AS_RAW | decorators> {};
288
289 // Helper for performing normal accesses on the heap. These accesses
290 // may resolve an accessor on a GC barrier set
291 template <DecoratorSet decorators = INTERNAL_EMPTY>
292 class HeapAccess: public Access<IN_HEAP | decorators> {};
293
294 // Helper for performing normal accesses in roots. These accesses
295 // may resolve an accessor on a GC barrier set
296 template <DecoratorSet decorators = INTERNAL_EMPTY>
297 class RootAccess: public Access<IN_ROOT | decorators> {};
298
299 // Helper for array access.
300 template <DecoratorSet decorators = INTERNAL_EMPTY>
301 class ArrayAccess: public HeapAccess<IN_HEAP_ARRAY | decorators> {
302 public:
303 template <typename T>
304 static inline void arraycopy(arrayOop src_obj, size_t src_offset_in_bytes,
305 arrayOop dst_obj, size_t dst_offset_in_bytes,
306 size_t length) {
307 HeapAccess<decorators | IN_HEAP_ARRAY>::arraycopy(src_obj, src_offset_in_bytes, (const T*) NULL,
308 dst_obj, dst_offset_in_bytes, (T*) NULL,
309 length);
310 }
311
312 template <typename T>
313 static inline void arraycopy_to_native(arrayOop src_obj, size_t src_offset_in_bytes, T* dst, size_t length) {
314 HeapAccess<decorators | IN_HEAP_ARRAY>::arraycopy(src_obj, src_offset_in_bytes, (const T*) NULL,
315 NULL, 0, dst,
316 length);
317 }
318
319 template <typename T>
320 static inline void arraycopy_from_native(const T* src, arrayOop dst_obj, size_t dst_offset_in_bytes, size_t length) {
321 HeapAccess<decorators | IN_HEAP_ARRAY>::arraycopy(NULL, 0, src, dst_obj, dst_offset_in_bytes, (T*) NULL, length);
322 }
323
324 template <typename T>
325 static inline bool oop_arraycopy(arrayOop src_obj, size_t src_offset_in_bytes,
326 arrayOop dst_obj, size_t dst_offset_in_bytes,
327 size_t length) {
328 return HeapAccess<decorators | IN_HEAP_ARRAY>::oop_arraycopy(src_obj, src_offset_in_bytes, (const T*) NULL,
329 dst_obj, dst_offset_in_bytes, (T*) NULL, length);
330 }
331
332 template <typename T>
333 static inline bool oop_arraycopy_raw(T* src, T* dst, size_t length) {
334 return HeapAccess<decorators | IN_HEAP_ARRAY>::oop_arraycopy(NULL, 0, src, NULL, 0, dst, length);
335 }
336
337 };
338
339 template <DecoratorSet decorators>
340 template <DecoratorSet expected_decorators>
341 void Access<decorators>::verify_decorators() {
342 STATIC_ASSERT((~expected_decorators & decorators) == 0); // unexpected decorator used
343 const DecoratorSet barrier_strength_decorators = decorators & AS_DECORATOR_MASK;
344 STATIC_ASSERT(barrier_strength_decorators == 0 || ( // make sure barrier strength decorators are disjoint if set
345 (barrier_strength_decorators ^ AS_NO_KEEPALIVE) == 0 ||
346 (barrier_strength_decorators ^ AS_DEST_NOT_INITIALIZED) == 0 ||
347 (barrier_strength_decorators ^ AS_RAW) == 0 ||
348 (barrier_strength_decorators ^ AS_NORMAL) == 0
349 ));
350 const DecoratorSet ref_strength_decorators = decorators & ON_DECORATOR_MASK;
351 STATIC_ASSERT(ref_strength_decorators == 0 || ( // make sure ref strength decorators are disjoint if set
352 (ref_strength_decorators ^ ON_STRONG_OOP_REF) == 0 ||
353 (ref_strength_decorators ^ ON_WEAK_OOP_REF) == 0 ||
|
283 };
284
285 // Helper for performing raw accesses (knows only of memory ordering
286 // atomicity decorators as well as compressed oops)
287 template <DecoratorSet decorators = INTERNAL_EMPTY>
288 class RawAccess: public Access<AS_RAW | decorators> {};
289
290 // Helper for performing normal accesses on the heap. These accesses
291 // may resolve an accessor on a GC barrier set
292 template <DecoratorSet decorators = INTERNAL_EMPTY>
293 class HeapAccess: public Access<IN_HEAP | decorators> {};
294
295 // Helper for performing normal accesses in roots. These accesses
296 // may resolve an accessor on a GC barrier set
297 template <DecoratorSet decorators = INTERNAL_EMPTY>
298 class RootAccess: public Access<IN_ROOT | decorators> {};
299
300 // Helper for array access.
301 template <DecoratorSet decorators = INTERNAL_EMPTY>
302 class ArrayAccess: public HeapAccess<IN_HEAP_ARRAY | decorators> {
303 typedef HeapAccess<IN_HEAP_ARRAY | decorators> AccessT;
304 public:
305 template <typename T>
306 static inline void arraycopy(arrayOop src_obj, size_t src_offset_in_bytes,
307 arrayOop dst_obj, size_t dst_offset_in_bytes,
308 size_t length) {
309 AccessT::arraycopy(src_obj, src_offset_in_bytes, reinterpret_cast<const T*>(NULL),
310 dst_obj, dst_offset_in_bytes, reinterpret_cast<T*>(NULL),
311 length);
312 }
313
314 template <typename T>
315 static inline void arraycopy_to_native(arrayOop src_obj, size_t src_offset_in_bytes,
316 T* dst,
317 size_t length) {
318 AccessT::arraycopy(src_obj, src_offset_in_bytes, reinterpret_cast<const T*>(NULL),
319 NULL, 0, dst,
320 length);
321 }
322
323 template <typename T>
324 static inline void arraycopy_from_native(const T* src,
325 arrayOop dst_obj, size_t dst_offset_in_bytes,
326 size_t length) {
327 AccessT::arraycopy(NULL, 0, src,
328 dst_obj, dst_offset_in_bytes, reinterpret_cast<T*>(NULL),
329 length);
330 }
331
332 static inline bool oop_arraycopy(arrayOop src_obj, size_t src_offset_in_bytes,
333 arrayOop dst_obj, size_t dst_offset_in_bytes,
334 size_t length) {
335 return AccessT::oop_arraycopy(src_obj, src_offset_in_bytes, reinterpret_cast<const HeapWord*>(NULL),
336 dst_obj, dst_offset_in_bytes, reinterpret_cast<HeapWord*>(NULL),
337 length);
338 }
339
340 template <typename T>
341 static inline bool oop_arraycopy_raw(T* src, T* dst, size_t length) {
342 return AccessT::oop_arraycopy(NULL, 0, src,
343 NULL, 0, dst,
344 length);
345 }
346
347 };
348
349 template <DecoratorSet decorators>
350 template <DecoratorSet expected_decorators>
351 void Access<decorators>::verify_decorators() {
352 STATIC_ASSERT((~expected_decorators & decorators) == 0); // unexpected decorator used
353 const DecoratorSet barrier_strength_decorators = decorators & AS_DECORATOR_MASK;
354 STATIC_ASSERT(barrier_strength_decorators == 0 || ( // make sure barrier strength decorators are disjoint if set
355 (barrier_strength_decorators ^ AS_NO_KEEPALIVE) == 0 ||
356 (barrier_strength_decorators ^ AS_DEST_NOT_INITIALIZED) == 0 ||
357 (barrier_strength_decorators ^ AS_RAW) == 0 ||
358 (barrier_strength_decorators ^ AS_NORMAL) == 0
359 ));
360 const DecoratorSet ref_strength_decorators = decorators & ON_DECORATOR_MASK;
361 STATIC_ASSERT(ref_strength_decorators == 0 || ( // make sure ref strength decorators are disjoint if set
362 (ref_strength_decorators ^ ON_STRONG_OOP_REF) == 0 ||
363 (ref_strength_decorators ^ ON_WEAK_OOP_REF) == 0 ||
|