|
1 /* |
|
2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. |
|
8 * |
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 * version 2 for more details (a copy is included in the LICENSE file that |
|
13 * accompanied this code). |
|
14 * |
|
15 * You should have received a copy of the GNU General Public License version |
|
16 * 2 along with this work; if not, write to the Free Software Foundation, |
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 * |
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
20 * or visit www.oracle.com if you need additional information or have any |
|
21 * questions. |
|
22 * |
|
23 */ |
|
24 |
|
25 #ifndef SHARE_VM_RUNTIME_ACCESS_HPP |
|
26 #define SHARE_VM_RUNTIME_ACCESS_HPP |
|
27 |
|
28 #include "memory/allocation.hpp" |
|
29 #include "metaprogramming/decay.hpp" |
|
30 #include "metaprogramming/integralConstant.hpp" |
|
31 #include "oops/oopsHierarchy.hpp" |
|
32 #include "utilities/debug.hpp" |
|
33 #include "utilities/globalDefinitions.hpp" |
|
34 |
|
35 // = GENERAL = |
|
36 // Access is an API for performing accesses with declarative semantics. Each access can have a number of "decorators". |
|
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. |
|
43 // By pipelining handling of these decorators, the design of the Access API allows separation of concern |
|
44 // over the different orthogonal concerns of decorators, while providing a powerful way of |
|
45 // expressing these orthogonal semantic properties in a unified way. |
|
46 |
|
47 // == OPERATIONS == |
|
48 // * load: Load a value from an address. |
|
49 // * load_at: Load a value from an internal pointer relative to a base object. |
|
50 // * store: Store a value at an address. |
|
51 // * store_at: Store a value in an internal pointer relative to a base object. |
|
52 // * atomic_cmpxchg: Atomically compare-and-swap a new value at an address if previous value matched the compared value. |
|
53 // * atomic_cmpxchg_at: Atomically compare-and-swap a new value at an internal pointer address if previous value matched the compared value. |
|
54 // * atomic_xchg: Atomically swap a new value at an address if previous value matched the compared value. |
|
55 // * atomic_xchg_at: Atomically swap a new value at an internal pointer address if previous value matched the compared value. |
|
56 // * arraycopy: Copy data from one heap array to another heap array. |
|
57 // * clone: Clone the contents of an object to a newly allocated object. |
|
58 |
|
59 typedef uint64_t DecoratorSet; |
|
60 |
|
61 // == Internal Decorators - do not use == |
|
62 // * INTERNAL_EMPTY: This is the name for the empty decorator set (in absence of other decorators). |
|
63 // * INTERNAL_CONVERT_COMPRESSED_OOPS: This is an oop access that will require converting an oop |
|
64 // to a narrowOop or vice versa, if UseCompressedOops is known to be set. |
|
65 // * INTERNAL_VALUE_IS_OOP: Remember that the involved access is on oop rather than primitive. |
|
66 const DecoratorSet INTERNAL_EMPTY = UCONST64(0); |
|
67 const DecoratorSet INTERNAL_CONVERT_COMPRESSED_OOP = UCONST64(1) << 1; |
|
68 const DecoratorSet INTERNAL_VALUE_IS_OOP = UCONST64(1) << 2; |
|
69 |
|
70 // == Internal build-time Decorators == |
|
71 // * INTERNAL_BT_BARRIER_ON_PRIMITIVES: This is set in the barrierSetConfig.hpp file. |
|
72 const DecoratorSet INTERNAL_BT_BARRIER_ON_PRIMITIVES = UCONST64(1) << 3; |
|
73 |
|
74 // == Internal run-time Decorators == |
|
75 // * INTERNAL_RT_USE_COMPRESSED_OOPS: This decorator will be set in runtime resolved |
|
76 // access backends iff UseCompressedOops is true. |
|
77 const DecoratorSet INTERNAL_RT_USE_COMPRESSED_OOPS = UCONST64(1) << 4; |
|
78 |
|
79 const DecoratorSet INTERNAL_DECORATOR_MASK = INTERNAL_CONVERT_COMPRESSED_OOP | INTERNAL_VALUE_IS_OOP | |
|
80 INTERNAL_BT_BARRIER_ON_PRIMITIVES | INTERNAL_RT_USE_COMPRESSED_OOPS; |
|
81 |
|
82 // == Memory Ordering Decorators == |
|
83 // The memory ordering decorators can be described in the following way: |
|
84 // === Decorator Rules === |
|
85 // The different types of memory ordering guarantees have a strict order of strength. |
|
86 // Explicitly specifying the stronger ordering implies that the guarantees of the weaker |
|
87 // property holds too. The names come from the C++11 atomic operations, and typically |
|
88 // have a JMM equivalent property. |
|
89 // The equivalence may be viewed like this: |
|
90 // MO_UNORDERED is equivalent to JMM plain. |
|
91 // MO_VOLATILE has no equivalence in JMM, because it's a C++ thing. |
|
92 // MO_RELAXED is equivalent to JMM opaque. |
|
93 // MO_ACQUIRE is equivalent to JMM acquire. |
|
94 // MO_RELEASE is equivalent to JMM release. |
|
95 // MO_SEQ_CST is equivalent to JMM volatile. |
|
96 // |
|
97 // === Stores === |
|
98 // * MO_UNORDERED (Default): No guarantees. |
|
99 // - The compiler and hardware are free to reorder aggressively. And they will. |
|
100 // * MO_VOLATILE: Volatile stores (in the C++ sense). |
|
101 // - The stores are not reordered by the compiler (but possibly the HW) w.r.t. other |
|
102 // volatile accesses in program order (but possibly non-volatile accesses). |
|
103 // * MO_RELAXED: Relaxed atomic stores. |
|
104 // - The stores are atomic. |
|
105 // - Guarantees from volatile stores hold. |
|
106 // * MO_RELEASE: Releasing stores. |
|
107 // - The releasing store will make its preceding memory accesses observable to memory accesses |
|
108 // subsequent to an acquiring load observing this releasing store. |
|
109 // - Guarantees from relaxed stores hold. |
|
110 // * MO_SEQ_CST: Sequentially consistent stores. |
|
111 // - The stores are observed in the same order by MO_SEQ_CST loads on other processors |
|
112 // - Preceding loads and stores in program order are not reordered with subsequent loads and stores in program order. |
|
113 // - Guarantees from releasing stores hold. |
|
114 // === Loads === |
|
115 // * MO_UNORDERED (Default): No guarantees |
|
116 // - The compiler and hardware are free to reorder aggressively. And they will. |
|
117 // * MO_VOLATILE: Volatile loads (in the C++ sense). |
|
118 // - The loads are not reordered by the compiler (but possibly the HW) w.r.t. other |
|
119 // volatile accesses in program order (but possibly non-volatile accesses). |
|
120 // * MO_RELAXED: Relaxed atomic loads. |
|
121 // - The stores are atomic. |
|
122 // - Guarantees from volatile loads hold. |
|
123 // * MO_ACQUIRE: Acquiring loads. |
|
124 // - An acquiring load will make subsequent memory accesses observe the memory accesses |
|
125 // preceding the releasing store that the acquiring load observed. |
|
126 // - Guarantees from relaxed loads hold. |
|
127 // * MO_SEQ_CST: Sequentially consistent loads. |
|
128 // - These loads observe MO_SEQ_CST stores in the same order on other processors |
|
129 // - Preceding loads and stores in program order are not reordered with subsequent loads and stores in program order. |
|
130 // - Guarantees from acquiring loads hold. |
|
131 // === Atomic Cmpxchg === |
|
132 // * MO_RELAXED: Atomic but relaxed cmpxchg. |
|
133 // - Guarantees from MO_RELAXED loads and MO_RELAXED stores hold unconditionally. |
|
134 // * MO_SEQ_CST: Sequentially consistent cmpxchg. |
|
135 // - Guarantees from MO_SEQ_CST loads and MO_SEQ_CST stores hold unconditionally. |
|
136 // === Atomic Xchg === |
|
137 // * MO_RELAXED: Atomic but relaxed atomic xchg. |
|
138 // - Guarantees from MO_RELAXED loads and MO_RELAXED stores hold. |
|
139 // * MO_SEQ_CST: Sequentially consistent xchg. |
|
140 // - Guarantees from MO_SEQ_CST loads and MO_SEQ_CST stores hold. |
|
141 const DecoratorSet MO_UNORDERED = UCONST64(1) << 5; |
|
142 const DecoratorSet MO_VOLATILE = UCONST64(1) << 6; |
|
143 const DecoratorSet MO_RELAXED = UCONST64(1) << 7; |
|
144 const DecoratorSet MO_ACQUIRE = UCONST64(1) << 8; |
|
145 const DecoratorSet MO_RELEASE = UCONST64(1) << 9; |
|
146 const DecoratorSet MO_SEQ_CST = UCONST64(1) << 10; |
|
147 const DecoratorSet MO_DECORATOR_MASK = MO_UNORDERED | MO_VOLATILE | MO_RELAXED | |
|
148 MO_ACQUIRE | MO_RELEASE | MO_SEQ_CST; |
|
149 |
|
150 // === Barrier Strength Decorators === |
|
151 // * AS_RAW: The access will translate into a raw memory access, hence ignoring all semantic concerns |
|
152 // except memory ordering and compressed oops. This will bypass runtime function pointer dispatching |
|
153 // in the pipeline and hardwire to raw accesses without going trough the GC access barriers. |
|
154 // - Accesses on oop* translate to raw memory accesses without runtime checks |
|
155 // - Accesses on narrowOop* translate to encoded/decoded memory accesses without runtime checks |
|
156 // - Accesses on HeapWord* translate to a runtime check choosing one of the above |
|
157 // - Accesses on other types translate to raw memory accesses without runtime checks |
|
158 // * AS_NO_KEEPALIVE: The barrier is used only on oop references and will not keep any involved objects |
|
159 // alive, regardless of the type of reference being accessed. It will however perform the memory access |
|
160 // in a consistent way w.r.t. e.g. concurrent compaction, so that the right field is being accessed, |
|
161 // or maintain, e.g. intergenerational or interregional pointers if applicable. This should be used with |
|
162 // extreme caution in isolated scopes. |
|
163 // * AS_NORMAL: The accesses will be resolved to an accessor on the BarrierSet class, giving the |
|
164 // responsibility of performing the access and what barriers to be performed to the GC. This is the default. |
|
165 // Note that primitive accesses will only be resolved on the barrier set if the appropriate build-time |
|
166 // decorator for enabling primitive barriers is enabled for the build. |
|
167 const DecoratorSet AS_RAW = UCONST64(1) << 11; |
|
168 const DecoratorSet AS_NO_KEEPALIVE = UCONST64(1) << 12; |
|
169 const DecoratorSet AS_NORMAL = UCONST64(1) << 13; |
|
170 const DecoratorSet AS_DECORATOR_MASK = AS_RAW | AS_NO_KEEPALIVE | AS_NORMAL; |
|
171 |
|
172 // === Reference Strength Decorators === |
|
173 // These decorators only apply to accesses on oop-like types (oop/narrowOop). |
|
174 // * ON_STRONG_OOP_REF: Memory access is performed on a strongly reachable reference. |
|
175 // * ON_WEAK_OOP_REF: The memory access is performed on a weakly reachable reference. |
|
176 // * ON_PHANTOM_OOP_REF: The memory access is performed on a phantomly reachable reference. |
|
177 // This is the same ring of strength as jweak and weak oops in the VM. |
|
178 // * ON_UNKNOWN_OOP_REF: The memory access is performed on a reference of unknown strength. |
|
179 // This could for example come from the unsafe API. |
|
180 // * Default (no explicit reference strength specified): ON_STRONG_OOP_REF |
|
181 const DecoratorSet ON_STRONG_OOP_REF = UCONST64(1) << 14; |
|
182 const DecoratorSet ON_WEAK_OOP_REF = UCONST64(1) << 15; |
|
183 const DecoratorSet ON_PHANTOM_OOP_REF = UCONST64(1) << 16; |
|
184 const DecoratorSet ON_UNKNOWN_OOP_REF = UCONST64(1) << 17; |
|
185 const DecoratorSet ON_DECORATOR_MASK = ON_STRONG_OOP_REF | ON_WEAK_OOP_REF | |
|
186 ON_PHANTOM_OOP_REF | ON_UNKNOWN_OOP_REF; |
|
187 |
|
188 // === Access Location === |
|
189 // Accesses can take place in, e.g. the heap, old or young generation and different native roots. |
|
190 // The location is important to the GC as it may imply different actions. The following decorators are used: |
|
191 // * IN_HEAP: The access is performed in the heap. Many barriers such as card marking will |
|
192 // be omitted if this decorator is not set. |
|
193 // * IN_HEAP_ARRAY: The access is performed on a heap allocated array. This is sometimes a special case |
|
194 // for some GCs, and implies that it is an IN_HEAP. |
|
195 // * IN_ROOT: The access is performed in an off-heap data structure pointing into the Java heap. |
|
196 // * IN_CONCURRENT_ROOT: The access is performed in an off-heap data structure pointing into the Java heap, |
|
197 // but is notably not scanned during safepoints. This is sometimes a special case for some GCs and |
|
198 // implies that it is also an IN_ROOT. |
|
199 const DecoratorSet IN_HEAP = UCONST64(1) << 18; |
|
200 const DecoratorSet IN_HEAP_ARRAY = UCONST64(1) << 19; |
|
201 const DecoratorSet IN_ROOT = UCONST64(1) << 20; |
|
202 const DecoratorSet IN_CONCURRENT_ROOT = UCONST64(1) << 21; |
|
203 const DecoratorSet IN_DECORATOR_MASK = IN_HEAP | IN_HEAP_ARRAY | |
|
204 IN_ROOT | IN_CONCURRENT_ROOT; |
|
205 |
|
206 // == Value Decorators == |
|
207 // * OOP_NOT_NULL: This property can make certain barriers faster such as compressing oops. |
|
208 const DecoratorSet OOP_NOT_NULL = UCONST64(1) << 22; |
|
209 const DecoratorSet OOP_DECORATOR_MASK = OOP_NOT_NULL; |
|
210 |
|
211 // == Arraycopy Decorators == |
|
212 // * ARRAYCOPY_DEST_NOT_INITIALIZED: This property can be important to e.g. SATB barriers by |
|
213 // marking that the previous value uninitialized nonsense rather than a real value. |
|
214 // * ARRAYCOPY_CHECKCAST: This property means that the class of the objects in source |
|
215 // are not guaranteed to be subclasses of the class of the destination array. This requires |
|
216 // a check-cast barrier during the copying operation. If this is not set, it is assumed |
|
217 // that the array is covariant: (the source array type is-a destination array type) |
|
218 // * ARRAYCOPY_DISJOINT: This property means that it is known that the two array ranges |
|
219 // are disjoint. |
|
220 // * ARRAYCOPY_ARRAYOF: The copy is in the arrayof form. |
|
221 // * ARRAYCOPY_ATOMIC: The accesses have to be atomic over the size of its elements. |
|
222 // * ARRAYCOPY_ALIGNED: The accesses have to be aligned on a HeapWord. |
|
223 const DecoratorSet ARRAYCOPY_DEST_NOT_INITIALIZED = UCONST64(1) << 24; |
|
224 const DecoratorSet ARRAYCOPY_CHECKCAST = UCONST64(1) << 25; |
|
225 const DecoratorSet ARRAYCOPY_DISJOINT = UCONST64(1) << 26; |
|
226 const DecoratorSet ARRAYCOPY_ARRAYOF = UCONST64(1) << 27; |
|
227 const DecoratorSet ARRAYCOPY_ATOMIC = UCONST64(1) << 28; |
|
228 const DecoratorSet ARRAYCOPY_ALIGNED = UCONST64(1) << 29; |
|
229 const DecoratorSet ARRAYCOPY_DECORATOR_MASK = ARRAYCOPY_DEST_NOT_INITIALIZED | |
|
230 ARRAYCOPY_CHECKCAST | ARRAYCOPY_DISJOINT | |
|
231 ARRAYCOPY_DISJOINT | ARRAYCOPY_ARRAYOF | |
|
232 ARRAYCOPY_ATOMIC | ARRAYCOPY_ALIGNED; |
|
233 |
|
234 // The HasDecorator trait can help at compile-time determining whether a decorator set |
|
235 // has an intersection with a certain other decorator set |
|
236 template <DecoratorSet decorators, DecoratorSet decorator> |
|
237 struct HasDecorator: public IntegralConstant<bool, (decorators & decorator) != 0> {}; |
|
238 |
|
239 namespace AccessInternal { |
|
240 template <typename T> |
|
241 struct OopOrNarrowOopInternal: AllStatic { |
|
242 typedef oop type; |
|
243 }; |
|
244 |
|
245 template <> |
|
246 struct OopOrNarrowOopInternal<narrowOop>: AllStatic { |
|
247 typedef narrowOop type; |
|
248 }; |
|
249 |
|
250 // This metafunction returns a canonicalized oop/narrowOop type for a passed |
|
251 // in oop-like types passed in from oop_* overloads where the user has sworn |
|
252 // that the passed in values should be oop-like (e.g. oop, oopDesc*, arrayOop, |
|
253 // narrowOoop, instanceOopDesc*, and random other things). |
|
254 // In the oop_* overloads, it must hold that if the passed in type T is not |
|
255 // narrowOop, then it by contract has to be one of many oop-like types implicitly |
|
256 // convertible to oop, and hence returns oop as the canonical oop type. |
|
257 // If it turns out it was not, then the implicit conversion to oop will fail |
|
258 // to compile, as desired. |
|
259 template <typename T> |
|
260 struct OopOrNarrowOop: AllStatic { |
|
261 typedef typename OopOrNarrowOopInternal<typename Decay<T>::type>::type type; |
|
262 }; |
|
263 |
|
264 inline void* field_addr(oop base, ptrdiff_t byte_offset) { |
|
265 return reinterpret_cast<void*>(reinterpret_cast<intptr_t>((void*)base) + byte_offset); |
|
266 } |
|
267 |
|
268 template <DecoratorSet decorators, typename T> |
|
269 void store_at(oop base, ptrdiff_t offset, T value); |
|
270 |
|
271 template <DecoratorSet decorators, typename T> |
|
272 T load_at(oop base, ptrdiff_t offset); |
|
273 |
|
274 template <DecoratorSet decorators, typename T> |
|
275 T atomic_cmpxchg_at(T new_value, oop base, ptrdiff_t offset, T compare_value); |
|
276 |
|
277 template <DecoratorSet decorators, typename T> |
|
278 T atomic_xchg_at(T new_value, oop base, ptrdiff_t offset); |
|
279 |
|
280 template <DecoratorSet decorators, typename P, typename T> |
|
281 void store(P* addr, T value); |
|
282 |
|
283 template <DecoratorSet decorators, typename P, typename T> |
|
284 T load(P* addr); |
|
285 |
|
286 template <DecoratorSet decorators, typename P, typename T> |
|
287 T atomic_cmpxchg(T new_value, P* addr, T compare_value); |
|
288 |
|
289 template <DecoratorSet decorators, typename P, typename T> |
|
290 T atomic_xchg(T new_value, P* addr); |
|
291 |
|
292 template <DecoratorSet decorators, typename T> |
|
293 bool arraycopy(arrayOop src_obj, arrayOop dst_obj, T *src, T *dst, size_t length); |
|
294 |
|
295 template <DecoratorSet decorators> |
|
296 void clone(oop src, oop dst, size_t size); |
|
297 |
|
298 // Infer the type that should be returned from a load. |
|
299 template <typename P, DecoratorSet decorators> |
|
300 class LoadProxy: public StackObj { |
|
301 private: |
|
302 P *const _addr; |
|
303 public: |
|
304 LoadProxy(P* addr) : _addr(addr) {} |
|
305 |
|
306 template <typename T> |
|
307 inline operator T() { |
|
308 return load<decorators, P, T>(_addr); |
|
309 } |
|
310 |
|
311 inline operator P() { |
|
312 return load<decorators, P, P>(_addr); |
|
313 } |
|
314 }; |
|
315 |
|
316 // Infer the type that should be returned from a load_at. |
|
317 template <DecoratorSet decorators> |
|
318 class LoadAtProxy: public StackObj { |
|
319 private: |
|
320 const oop _base; |
|
321 const ptrdiff_t _offset; |
|
322 public: |
|
323 LoadAtProxy(oop base, ptrdiff_t offset) : _base(base), _offset(offset) {} |
|
324 |
|
325 template <typename T> |
|
326 inline operator T() const { |
|
327 return load_at<decorators, T>(_base, _offset); |
|
328 } |
|
329 }; |
|
330 } |
|
331 |
|
332 template <DecoratorSet decorators = INTERNAL_EMPTY> |
|
333 class Access: public AllStatic { |
|
334 // This function asserts that if an access gets passed in a decorator outside |
|
335 // of the expected_decorators, then something is wrong. It additionally checks |
|
336 // the consistency of the decorators so that supposedly disjoint decorators are indeed |
|
337 // disjoint. For example, an access can not be both in heap and on root at the |
|
338 // same time. |
|
339 template <DecoratorSet expected_decorators> |
|
340 static void verify_decorators(); |
|
341 |
|
342 template <DecoratorSet expected_mo_decorators> |
|
343 static void verify_primitive_decorators() { |
|
344 const DecoratorSet primitive_decorators = (AS_DECORATOR_MASK ^ AS_NO_KEEPALIVE) | IN_HEAP | |
|
345 IN_HEAP_ARRAY | MO_DECORATOR_MASK; |
|
346 verify_decorators<expected_mo_decorators | primitive_decorators>(); |
|
347 } |
|
348 |
|
349 template <DecoratorSet expected_mo_decorators> |
|
350 static void verify_oop_decorators() { |
|
351 const DecoratorSet oop_decorators = AS_DECORATOR_MASK | IN_DECORATOR_MASK | |
|
352 (ON_DECORATOR_MASK ^ ON_UNKNOWN_OOP_REF) | // no unknown oop refs outside of the heap |
|
353 OOP_DECORATOR_MASK | MO_DECORATOR_MASK; |
|
354 verify_decorators<expected_mo_decorators | oop_decorators>(); |
|
355 } |
|
356 |
|
357 template <DecoratorSet expected_mo_decorators> |
|
358 static void verify_heap_oop_decorators() { |
|
359 const DecoratorSet heap_oop_decorators = AS_DECORATOR_MASK | ON_DECORATOR_MASK | |
|
360 OOP_DECORATOR_MASK | (IN_DECORATOR_MASK ^ |
|
361 (IN_ROOT ^ IN_CONCURRENT_ROOT)) | // no root accesses in the heap |
|
362 MO_DECORATOR_MASK; |
|
363 verify_decorators<expected_mo_decorators | heap_oop_decorators>(); |
|
364 } |
|
365 |
|
366 static const DecoratorSet load_mo_decorators = MO_UNORDERED | MO_VOLATILE | MO_RELAXED | MO_ACQUIRE | MO_SEQ_CST; |
|
367 static const DecoratorSet store_mo_decorators = MO_UNORDERED | MO_VOLATILE | MO_RELAXED | MO_RELEASE | MO_SEQ_CST; |
|
368 static const DecoratorSet atomic_xchg_mo_decorators = MO_SEQ_CST; |
|
369 static const DecoratorSet atomic_cmpxchg_mo_decorators = MO_RELAXED | MO_SEQ_CST; |
|
370 |
|
371 public: |
|
372 // Primitive heap accesses |
|
373 static inline AccessInternal::LoadAtProxy<decorators> load_at(oop base, ptrdiff_t offset) { |
|
374 verify_primitive_decorators<load_mo_decorators>(); |
|
375 return AccessInternal::LoadAtProxy<decorators>(base, offset); |
|
376 } |
|
377 |
|
378 template <typename T> |
|
379 static inline void store_at(oop base, ptrdiff_t offset, T value) { |
|
380 verify_primitive_decorators<store_mo_decorators>(); |
|
381 AccessInternal::store_at<decorators>(base, offset, value); |
|
382 } |
|
383 |
|
384 template <typename T> |
|
385 static inline T atomic_cmpxchg_at(T new_value, oop base, ptrdiff_t offset, T compare_value) { |
|
386 verify_primitive_decorators<atomic_cmpxchg_mo_decorators>(); |
|
387 return AccessInternal::atomic_cmpxchg_at<decorators>(new_value, base, offset, compare_value); |
|
388 } |
|
389 |
|
390 template <typename T> |
|
391 static inline T atomic_xchg_at(T new_value, oop base, ptrdiff_t offset) { |
|
392 verify_primitive_decorators<atomic_xchg_mo_decorators>(); |
|
393 return AccessInternal::atomic_xchg_at<decorators>(new_value, base, offset); |
|
394 } |
|
395 |
|
396 template <typename T> |
|
397 static inline bool arraycopy(arrayOop src_obj, arrayOop dst_obj, T *src, T *dst, size_t length) { |
|
398 verify_decorators<ARRAYCOPY_DECORATOR_MASK | IN_HEAP | |
|
399 AS_DECORATOR_MASK>(); |
|
400 return AccessInternal::arraycopy<decorators>(src_obj, dst_obj, src, dst, length); |
|
401 } |
|
402 |
|
403 // Oop heap accesses |
|
404 static inline AccessInternal::LoadAtProxy<decorators | INTERNAL_VALUE_IS_OOP> oop_load_at(oop base, ptrdiff_t offset) { |
|
405 verify_heap_oop_decorators<load_mo_decorators>(); |
|
406 return AccessInternal::LoadAtProxy<decorators | INTERNAL_VALUE_IS_OOP>(base, offset); |
|
407 } |
|
408 |
|
409 template <typename T> |
|
410 static inline void oop_store_at(oop base, ptrdiff_t offset, T value) { |
|
411 verify_heap_oop_decorators<store_mo_decorators>(); |
|
412 typedef typename AccessInternal::OopOrNarrowOop<T>::type OopType; |
|
413 OopType oop_value = value; |
|
414 AccessInternal::store_at<decorators | INTERNAL_VALUE_IS_OOP>(base, offset, oop_value); |
|
415 } |
|
416 |
|
417 template <typename T> |
|
418 static inline T oop_atomic_cmpxchg_at(T new_value, oop base, ptrdiff_t offset, T compare_value) { |
|
419 verify_heap_oop_decorators<atomic_cmpxchg_mo_decorators>(); |
|
420 typedef typename AccessInternal::OopOrNarrowOop<T>::type OopType; |
|
421 OopType new_oop_value = new_value; |
|
422 OopType compare_oop_value = compare_value; |
|
423 return AccessInternal::atomic_cmpxchg_at<decorators | INTERNAL_VALUE_IS_OOP>(new_oop_value, base, offset, compare_oop_value); |
|
424 } |
|
425 |
|
426 template <typename T> |
|
427 static inline T oop_atomic_xchg_at(T new_value, oop base, ptrdiff_t offset) { |
|
428 verify_heap_oop_decorators<atomic_xchg_mo_decorators>(); |
|
429 typedef typename AccessInternal::OopOrNarrowOop<T>::type OopType; |
|
430 OopType new_oop_value = new_value; |
|
431 return AccessInternal::atomic_xchg_at<decorators | INTERNAL_VALUE_IS_OOP>(new_oop_value, base, offset); |
|
432 } |
|
433 |
|
434 template <typename T> |
|
435 static inline bool oop_arraycopy(arrayOop src_obj, arrayOop dst_obj, T *src, T *dst, size_t length) { |
|
436 verify_decorators<ARRAYCOPY_DECORATOR_MASK | IN_HEAP | AS_DECORATOR_MASK>(); |
|
437 return AccessInternal::arraycopy<decorators | INTERNAL_VALUE_IS_OOP>(src_obj, dst_obj, src, dst, length); |
|
438 } |
|
439 |
|
440 // Clone an object from src to dst |
|
441 static inline void clone(oop src, oop dst, size_t size) { |
|
442 verify_decorators<IN_HEAP>(); |
|
443 AccessInternal::clone<decorators>(src, dst, size); |
|
444 } |
|
445 |
|
446 // Primitive accesses |
|
447 template <typename P> |
|
448 static inline P load(P* addr) { |
|
449 verify_primitive_decorators<load_mo_decorators>(); |
|
450 return AccessInternal::load<decorators, P, P>(addr); |
|
451 } |
|
452 |
|
453 template <typename P, typename T> |
|
454 static inline void store(P* addr, T value) { |
|
455 verify_primitive_decorators<store_mo_decorators>(); |
|
456 AccessInternal::store<decorators>(addr, value); |
|
457 } |
|
458 |
|
459 template <typename P, typename T> |
|
460 static inline T atomic_cmpxchg(T new_value, P* addr, T compare_value) { |
|
461 verify_primitive_decorators<atomic_cmpxchg_mo_decorators>(); |
|
462 return AccessInternal::atomic_cmpxchg<decorators>(new_value, addr, compare_value); |
|
463 } |
|
464 |
|
465 template <typename P, typename T> |
|
466 static inline T atomic_xchg(T new_value, P* addr) { |
|
467 verify_primitive_decorators<atomic_xchg_mo_decorators>(); |
|
468 return AccessInternal::atomic_xchg<decorators>(new_value, addr); |
|
469 } |
|
470 |
|
471 // Oop accesses |
|
472 template <typename P> |
|
473 static inline AccessInternal::LoadProxy<P, decorators | INTERNAL_VALUE_IS_OOP> oop_load(P* addr) { |
|
474 verify_oop_decorators<load_mo_decorators>(); |
|
475 return AccessInternal::LoadProxy<P, decorators | INTERNAL_VALUE_IS_OOP>(addr); |
|
476 } |
|
477 |
|
478 template <typename P, typename T> |
|
479 static inline void oop_store(P* addr, T value) { |
|
480 verify_oop_decorators<store_mo_decorators>(); |
|
481 typedef typename AccessInternal::OopOrNarrowOop<T>::type OopType; |
|
482 OopType oop_value = value; |
|
483 AccessInternal::store<decorators | INTERNAL_VALUE_IS_OOP>(addr, oop_value); |
|
484 } |
|
485 |
|
486 template <typename P, typename T> |
|
487 static inline T oop_atomic_cmpxchg(T new_value, P* addr, T compare_value) { |
|
488 verify_oop_decorators<atomic_cmpxchg_mo_decorators>(); |
|
489 typedef typename AccessInternal::OopOrNarrowOop<T>::type OopType; |
|
490 OopType new_oop_value = new_value; |
|
491 OopType compare_oop_value = compare_value; |
|
492 return AccessInternal::atomic_cmpxchg<decorators | INTERNAL_VALUE_IS_OOP>(new_oop_value, addr, compare_oop_value); |
|
493 } |
|
494 |
|
495 template <typename P, typename T> |
|
496 static inline T oop_atomic_xchg(T new_value, P* addr) { |
|
497 verify_oop_decorators<atomic_xchg_mo_decorators>(); |
|
498 typedef typename AccessInternal::OopOrNarrowOop<T>::type OopType; |
|
499 OopType new_oop_value = new_value; |
|
500 return AccessInternal::atomic_xchg<decorators | INTERNAL_VALUE_IS_OOP>(new_oop_value, addr); |
|
501 } |
|
502 }; |
|
503 |
|
504 // Helper for performing raw accesses (knows only of memory ordering |
|
505 // atomicity decorators as well as compressed oops) |
|
506 template <DecoratorSet decorators = INTERNAL_EMPTY> |
|
507 class RawAccess: public Access<AS_RAW | decorators> {}; |
|
508 |
|
509 // Helper for performing normal accesses on the heap. These accesses |
|
510 // may resolve an accessor on a GC barrier set |
|
511 template <DecoratorSet decorators = INTERNAL_EMPTY> |
|
512 class HeapAccess: public Access<IN_HEAP | decorators> {}; |
|
513 |
|
514 // Helper for performing normal accesses in roots. These accesses |
|
515 // may resolve an accessor on a GC barrier set |
|
516 template <DecoratorSet decorators = INTERNAL_EMPTY> |
|
517 class RootAccess: public Access<IN_ROOT | decorators> {}; |
|
518 |
|
519 #endif // SHARE_VM_RUNTIME_ACCESS_HPP |