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 "oops/oopsHierarchy.hpp" 29 #include "utilities/traits/decay.hpp" 30 31 // = GENERAL = 32 // Access is an API for performing memory accesses to the heap. Each access can have a number of "decorators". 33 // A decorator is an attribute or property that affects the way a memory access is performed in some way. 34 // There are different groups of decorators. Some have to do with memory ordering, others to do with 35 // e.g. strength of references, strength of GC barriers or whether compression should be applied or not. 36 // Some decorators are set at buildtime, such as whether primitives require GC barriers or not, others 37 // at callsites such as whether an access is in the heap or not, and others are resolved at runtime 38 // such as GC-specific barriers and encoding/decoding compressed oops. 39 // By pipelining handling of these decorators, the design of the Access API allows separation of concern 40 // over the different orthogonal concerns of decorators, while providing a powerful unified way of 41 // expressing these orthogonal properties in a unified way. 42 43 // = THE PIPELINE = 44 // The design of accesses going through the Access interface consists of the following stages: 45 // 1. The interface connecting inferred types into AccessInternal. 46 // It uses proxy classes to infer return types when necessary. 47 // 2. Type decaying. This stage gets rid of CV qualifiers and reference types. 48 // It additionally sets volatile decorators for volatile accesses. 49 // 3. Type reduction. This stage merges the type of the address with the type of the value 50 // This might entail infering compressed oops need to be converted. 51 // 4. Decorator rule inferring. This stage adds decorators according to well defined rules. 52 // 5. Add buildtime decorators with buildtime capabilities 53 // 6. Figure out if a dynamic dispatch is necessary, and potentially hardwire basic and raw accesses 54 // 7. If not hardwired, make a dynamic dispatch through a function pointer that resolves itself at runtime 55 // The resolved function pointer is looked up in accessConfigure.inline.hpp 56 // 8. GC barriers can override any not hardwired access calls in the resolved barriers 57 58 // == OPERATIONS == 59 // * load: Load a value from an address. 60 // * load_at: Load a value from an internal pointer relative to a base object. 61 // * store: Store a value at an address. 62 // * store_at: Store a value in an internal pointer relative to a base object. 63 // * cas: Atomically Compare-And-Swap a new value at an address if previous value matched the compared value. 64 // * cas_at: Atomically Compare-And-Swap a new value at an internal pointer address if previous value matched the compared value. 65 // * swap: Atomically swap a new value at an address if previous value matched the compared value. 66 // * swap_at: Atomically swap a new value at an internal pointer address if previous value matched the compared value. 67 68 // == MEMORY ORDERING == 69 // The memory ordering decorators can be described in the following way: 70 // === Decorator Rules === 71 // The different types of memory ordering guarantees have a strict order of strength. 72 // Explicitly specifying the stronger ordering implies that the guarantees of the weaker 73 // property holds too. 74 // The following rules are applied to enforce this: 75 // * MO_SEQ_CST -> MO_ACQUIRE 76 // * MO_SEQ_CST -> MO_RELEASE 77 // * MO_ACQUIRE -> MO_ATOMIC 78 // * MO_RELEASE -> MO_ATOMIC 79 // * MO_ATOMIC -> MO_VOLATILE 80 // * !MO_VOLATILE -> MO_RELAXED 81 // === Stores === 82 // * MO_SEQ_CST: Sequentially consistent stores. 83 // - The stores are observed in the same order by MO_SEQ_CST loads on other processors 84 // - Preceding loads and stores in program order are not reordered with subsequent loads and stores in program order. 85 // - Guarantees from releasing stores hold. 86 // * MO_RELEASE: Releasing stores. 87 // - The releasing store will make its preceding memory accesses observable to memory accesses 88 // subsequent to an acquiring load observing this releasing store. 89 // - Guarantees from relaxed stores hold. 90 // * MO_ATOMIC: Relaxed atomic stores. 91 // - The stores are atomic. 92 // - Guarantees from volatile stores hold. 93 // * MO_VOLATILE: Volatile stores. 94 // - The stores are not reordered by the compiler (but possibly the HW) w.r.t. other 95 // volatile accesses in program order (but possibly non-volatile accesses). 96 // * MO_RELAXED (Default): No guarantees 97 // - The compiler and hardware are free to reorder aggressively. And they will. 98 // === Loads === 99 // * MO_SEQ_CST: Sequentially consistent loads. 100 // - These loads observe MO_SEQ_CST stores in the same order on other processors 101 // - Preceding loads and stores in program order are not reordered with subsequent loads and stores in program order. 102 // - Guarantees from acquiring loads hold. 103 // * MO_ACQUIRE: Acquiring loads. 104 // - An acquiring load will make subsequent memory accesses observe the memory accesses 105 // preceding the releasing store that the acquiring load observed. 106 // - Guarantees from relaxed stores hold. 107 // * MO_ATOMIC: Relaxed atomic loads. 108 // - The stores are atomic. 109 // - Guarantees from volatile stores hold. 110 // * MO_VOLATILE: Volatile loads. 111 // - The loads are not reordered by the compiler (but possibly the HW) w.r.t. other 112 // volatile accesses in program order (but possibly non-volatile accesses). 113 // * MO_RELAXED (Default): No guarantees 114 // - The compiler and hardware are free to reorder aggressively. And they will. 115 // === CAS === 116 // * MO_SEQ_CST: Sequentially consistent CAS. 117 // - Guarantees from MO_SEQ_CST loads and MO_SEQ_CST stores hold unconditionally. 118 // * MO_ATOMIC: Atomic but relaxed CAS. 119 // - Guarantees from MO_ATOMIC loads and MO_ATOMIC stores hold unconditionally. 120 // === Swap === 121 // * MO_SEQ_CST: Sequentially consistent swap. 122 // - Guarantees from MO_SEQ_CST loads and MO_SEQ_CST stores hold. 123 // * MO_ATOMIC: Atomic but relaxed CAS. 124 // - Guarantees from MO_ATOMIC loads and MO_ATOMIC stores hold. 125 // 126 // == GC DECORATORS == 127 // These decorators describe GC-related properties. 128 // === Access Location === 129 // Accesses can take place on in e.g. the heap, old or young generation and different native roots. 130 // The location is important to the GC as it may imply different actions. The following decorators are used: 131 // * ACCESS_ON_HEAP: The access is performed in the heap. Many barriers such as card marking will 132 // be omitted if this decorator is not set. 133 // * ACCESS_ON_NMETHOD: The access is performed on an nmethod. This decorator may be recognized by GCs 134 // that track references from nmethods to the heap in special ways. 135 // * ACCESS_ON_YOUNG: The access is guaranteed to be performed on an object in the young generation 136 // (if the GC is generational). Recognizing this decorator potentially allows eliding unnecessary GC 137 // barriers on such young objects. 138 // Default: EMPTY_DECORATOR 139 // === Heap Access Type === 140 // * ACCESS_ON_ARRAY: The access is performed on a heap allocated array. This is sometimes a special case 141 // for some GCs. 142 // === Reference Strength === 143 // These decorators only apply to accesses on oop-like types (oop/narrowOop). 144 // * GC_ACCESS_ON_STRONG: Memory access is performed on a strongly reachable reference. 145 // * GC_ACCESS_ON_WEAK: The memory access is performed on a weakly reachable reference. 146 // * GC_ACCESS_ON_PHANTOM: The memory access is performed on a phantomly reachable reference. 147 // * Default (no explicit reference strength specified): GC_ACCESS_ON_STRONG 148 // === Barrier Strength === 149 // * ACCESS_RAW: The access will translate into a raw memory access, hence ignoring all concerns 150 // except memory ordering. This will bypass all runtime checks in the pipeline. 151 // * ACCESS_BASIC: The accesses will ignore all GC-specific concerns except compressed oops, hence 152 // bypassing as much as possible in the normal pipeline in the most efficient way possible. 153 // - Accesses on oop* translate to raw memory accesses without runtime checks 154 // - Accesses on narrowOop* translate to encoded/decoded memory accesses without runtime checks 155 // - Accesses on HeapWord* translate to a runtime check choosing one of the above 156 // - Accesses on other types translate to raw memory accesses without runtime checks 157 // * ACCESS_WEAK: The barrier is weak, meaning that it will not perform GC bookkeeping such as keeping references 158 // alive, regardless of the type of reference being accessed. It will however perform the memory access 159 // in a consistent way w.r.t. e.g. concurrent compaction if applicable, so that the right field is being 160 // accessed. 161 // Default: Normal accesses do not specify any of the decorators above. They will be resolved at runtime 162 // according to the needs of the GC. If a GC requiring barriers on primitives is used, even primitive 163 // types will have their accessors resolved at runtime. 164 // Use of this decorator is for GC-specific code where hardwiring is possible, but should not be used in runtime code. 165 // == VALUE DECORATORS == 166 // * VALUE_NOT_NULL: This property can make certain barriers faster such as compressing oops. 167 // * DEST_NOT_INITIALIZED: This property can be important to e.g. SATB barriers by marking that the previous value 168 // uninitialized nonsense rather than a real value. 169 170 typedef uint64_t DecoratorSet; 171 172 enum Decorator { 173 EMPTY_DECORATOR = UCONST64(0), 174 DECORATOR_DEFAULT = EMPTY_DECORATOR, 175 BT_BARRIER_ON_PRIMITIVES = UCONST64(1) << 0, 176 BT_HAS_BUILDTIME_DECORATOR = UCONST64(1) << 1, 177 178 // Runtime decorators 179 RT_USE_COMPRESSED_OOPS = UCONST64(1) << 2, 180 RT_HAS_RUNTIME_DECORATOR = UCONST64(1) << 3, 181 182 // Memory ordering decorators 183 MO_RELAXED = UCONST64(1) << 4, 184 MO_VOLATILE = UCONST64(1) << 5, 185 MO_ATOMIC = UCONST64(1) << 6, 186 MO_ACQUIRE = UCONST64(1) << 7, 187 MO_RELEASE = UCONST64(1) << 8, 188 MO_SEQ_CST = UCONST64(1) << 9, 189 190 // Access decorators 191 ACCESS_RAW = UCONST64(1) << 10, // Raw accesses with specified memory semantics 192 ACCESS_BASIC = UCONST64(1) << 11, // Includes compressed oops 193 ACCESS_WEAK = UCONST64(1) << 12, // Do not keep alive 194 195 // Actor decorators 196 ACCESS_BY_MUTATOR = UCONST64(1) << 13, 197 ACCESS_BY_STW_GC = UCONST64(1) << 14, 198 ACCESS_BY_CONCURRENT_GC = UCONST64(1) << 15, 199 200 // GC decorators 201 GC_ACCESS_ON_STRONG = UCONST64(1) << 16, 202 GC_ACCESS_ON_WEAK = UCONST64(1) << 17, 203 GC_ACCESS_ON_PHANTOM = UCONST64(1) << 18, 204 205 ACCESS_ON_HEAP = UCONST64(1) << 19, 206 ACCESS_ON_ROOT = UCONST64(1) << 20, 207 ACCESS_ON_YOUNG = UCONST64(1) << 21, 208 ACCESS_ON_ARRAY = UCONST64(1) << 22, 209 ACCESS_ON_ANONYMOUS = UCONST64(1) << 23, 210 ACCESS_ON_NMETHOD = UCONST64(1) << 24, 211 ACCESS_ON_KLASS = UCONST64(1) << 25, 212 213 // Barriers for compressed oops 214 GC_CONVERT_COMPRESSED_OOP = UCONST64(1) << 26, 215 216 // Value decorators 217 VALUE_NOT_NULL = UCONST64(1) << 27, 218 VALUE_IS_OOP = UCONST64(1) << 28, 219 220 // Destination address decorators 221 DEST_NOT_INITIALIZED = UCONST64(1) << 29, 222 DEST_COVARIANT = UCONST64(1) << 30, 223 DEST_CONTRAVARIANT = UCONST64(1) << 31, 224 DEST_CONJOINT = UCONST64(1) << 32, 225 DEST_DISJOINT = UCONST64(1) << 33, 226 COPY_ARRAYOF = UCONST64(1) << 34, 227 228 ACCESS_ARRAYCOPY = UCONST64(1) << 35, 229 ACCESS_ATOMIC = UCONST64(1) << 36, 230 ACCESS_ALIGNED = UCONST64(1) << 37, 231 232 DECORATOR_END = ACCESS_ALIGNED 233 }; 234 235 template <DecoratorSet decorators, Decorator decorator> 236 struct HasDecorator { 237 enum { 238 value = (decorators & (DecoratorSet)decorator) != 0 239 }; 240 }; 241 242 template <DecoratorSet set1, DecoratorSet set2> 243 struct DecoratorIntersection { 244 enum { 245 value = set1 & set2 246 }; 247 }; 248 249 template <DecoratorSet decorators> 250 struct DecoratorTest { 251 enum { 252 HAS_BUILDTIME_DECORATOR = HasDecorator<decorators, BT_HAS_BUILDTIME_DECORATOR>::value, 253 HAS_RUNTIME_DECORATOR = HasDecorator<decorators, RT_HAS_RUNTIME_DECORATOR>::value, 254 HAS_BARRIER_ON_PRIMITIVES = HasDecorator<decorators, BT_BARRIER_ON_PRIMITIVES>::value, 255 HAS_USE_COMPRESSED_OOPS = HasDecorator<decorators, RT_USE_COMPRESSED_OOPS>::value, 256 257 HAS_ACCESS_RAW = HasDecorator<decorators, ACCESS_RAW>::value, 258 HAS_ACCESS_BASIC = HasDecorator<decorators, ACCESS_BASIC>::value, 259 HAS_ACCESS_WEAK = HasDecorator<decorators, ACCESS_WEAK>::value, 260 261 HAS_ACCESS_ON_HEAP = HasDecorator<decorators, ACCESS_ON_HEAP>::value, 262 HAS_ACCESS_ON_ARRAY = HasDecorator<decorators, ACCESS_ON_ARRAY>::value, 263 HAS_ACCESS_ON_NMETHOD = HasDecorator<decorators, ACCESS_ON_NMETHOD>::value, 264 HAS_ACCESS_ON_KLASS = HasDecorator<decorators, ACCESS_ON_KLASS>::value, 265 HAS_ACCESS_ON_ROOT = HasDecorator<decorators, ACCESS_ON_ROOT>::value, 266 HAS_ACCESS_ON_ANONYMOUS = HasDecorator<decorators, ACCESS_ON_ANONYMOUS>::value, 267 HAS_ACCESS_ON_YOUNG = HasDecorator<decorators, ACCESS_ON_YOUNG>::value, 268 269 HAS_MO_RELAXED = HasDecorator<decorators, MO_RELAXED>::value, 270 HAS_MO_VOLATILE = HasDecorator<decorators, MO_VOLATILE>::value, 271 HAS_MO_ATOMIC = HasDecorator<decorators, MO_ATOMIC>::value, 272 HAS_MO_ACQUIRE = HasDecorator<decorators, MO_ACQUIRE>::value, 273 HAS_MO_RELEASE = HasDecorator<decorators, MO_RELEASE>::value, 274 HAS_MO_SEQ_CST = HasDecorator<decorators, MO_SEQ_CST>::value, 275 276 HAS_GC_CONVERT_COMPRESSED_OOP = HasDecorator<decorators, GC_CONVERT_COMPRESSED_OOP>::value, 277 278 NEEDS_OOP_COMPRESS = DecoratorTest<decorators>::HAS_GC_CONVERT_COMPRESSED_OOP && DecoratorTest<decorators>::HAS_USE_COMPRESSED_OOPS, 279 280 HAS_GC_ACCESS_ON_STRONG = HasDecorator<decorators, GC_ACCESS_ON_STRONG>::value, 281 HAS_GC_ACCESS_ON_WEAK = HasDecorator<decorators, GC_ACCESS_ON_WEAK>::value, 282 HAS_GC_ACCESS_ON_PHANTOM = HasDecorator<decorators, GC_ACCESS_ON_PHANTOM>::value, 283 284 IS_ON_STRONG = HAS_GC_ACCESS_ON_STRONG, 285 IS_ON_WEAK = HAS_GC_ACCESS_ON_WEAK, 286 IS_ON_PHANTOM = HAS_GC_ACCESS_ON_PHANTOM, 287 IS_ON_REFERENCE = HAS_GC_ACCESS_ON_WEAK || HAS_GC_ACCESS_ON_PHANTOM, 288 IS_WEAK_ACCESS = HAS_ACCESS_WEAK, 289 290 HAS_DEST_CONJOINT = HasDecorator<decorators, DEST_CONJOINT>::value, 291 HAS_DEST_DISJOINT = HasDecorator<decorators, DEST_DISJOINT>::value, 292 HAS_DEST_COVARIANT = HasDecorator<decorators, DEST_COVARIANT>::value, 293 HAS_DEST_CONTRAVARIANT = HasDecorator<decorators, DEST_CONTRAVARIANT>::value, 294 HAS_DEST_NOT_INITIALIZED = HasDecorator<decorators, DEST_NOT_INITIALIZED>::value, 295 296 HAS_COPY_ARRAYOF = HasDecorator<decorators, COPY_ARRAYOF>::value, 297 298 HAS_ACCESS_ATOMIC = HasDecorator<decorators, ACCESS_ATOMIC>::value, 299 HAS_VALUE_NOT_NULL = HasDecorator<decorators, VALUE_NOT_NULL>::value, 300 HAS_VALUE_IS_OOP = HasDecorator<decorators, VALUE_IS_OOP>::value 301 }; 302 }; 303 304 namespace AccessInternal { 305 template <typename T> 306 struct OopOrNarrowOopInternal { 307 typedef oop type; 308 }; 309 310 template <> 311 struct OopOrNarrowOopInternal<narrowOop> { 312 typedef narrowOop type; 313 }; 314 315 template <typename T> 316 struct OopOrNarrowOop { 317 typedef typename OopOrNarrowOopInternal<typename Decay<T>::type>::type type; 318 }; 319 320 inline void* field_addr(void* base, ptrdiff_t byte_offset) { 321 return (void*)(intptr_t(base) + byte_offset); 322 } 323 324 template <DecoratorSet decorators, typename P, typename T> 325 void store(P* addr, T value); 326 327 template <DecoratorSet decorators, typename P, typename T> 328 void store_at(P base, ptrdiff_t offset, T value); 329 330 template <DecoratorSet decorators, typename P, typename T> 331 T load(P* addr); 332 333 template <DecoratorSet decorators, typename P, typename T> 334 T load_at(P base, ptrdiff_t offset); 335 336 template <DecoratorSet decorators, typename P, typename T> 337 T cas(T new_value, P* addr, T compare_value); 338 339 template <DecoratorSet decorators, typename P, typename T> 340 T cas_at(T new_value, P base, ptrdiff_t offset, T compare_value); 341 342 template <DecoratorSet decorators, typename P, typename T> 343 T swap(T new_value, P* addr); 344 345 template <DecoratorSet decorators, typename P, typename T> 346 T swap_at(T new_value, P base, ptrdiff_t offset); 347 348 template <DecoratorSet decorators, typename T> 349 bool copy(arrayOop src_obj, arrayOop dst_obj, T *src, T *dst, size_t length); 350 351 template <DecoratorSet decorators> 352 void clone(oop src, oop dst, size_t size); 353 354 template <typename P, DecoratorSet decorators> 355 class LoadProxy { 356 private: 357 P *const _addr; 358 public: 359 LoadProxy(P* addr) : _addr(addr) {} 360 361 template <typename T> 362 inline operator T() { 363 return load<decorators, P, T>(_addr); 364 } 365 366 inline operator P() { 367 return load<decorators, P, P>(_addr); 368 } 369 }; 370 371 template <typename P, DecoratorSet decorators> 372 class LoadAtProxy { 373 private: 374 const P _base; 375 const ptrdiff_t _offset; 376 public: 377 LoadAtProxy(P base, ptrdiff_t offset) : _base(base), _offset(offset) {} 378 379 template <typename T> 380 inline operator T() { 381 return load_at<decorators, P, T>(_base, _offset); 382 } 383 }; 384 } 385 386 template <DecoratorSet decorators = EMPTY_DECORATOR> 387 class Access: public AllStatic { 388 public: 389 template <typename P, typename T> 390 static inline void store(P* addr, T value) { 391 AccessInternal::store<decorators, P, T>(addr, value); 392 } 393 394 template <typename P, typename T> 395 static inline void oop_store(P* addr, T value) { 396 AccessInternal::store<decorators | VALUE_IS_OOP, P, T>(addr, value); 397 } 398 399 template <typename P, typename T> 400 static inline void store_at(P base, ptrdiff_t offset, T value) { 401 AccessInternal::store_at<decorators, P, T>(base, offset, value); 402 } 403 404 template <typename P, typename T> 405 static inline void oop_store_at(P base, ptrdiff_t offset, T value) { 406 AccessInternal::store_at<decorators | VALUE_IS_OOP, P, T>(base, offset, value); 407 } 408 409 template <typename P> 410 static inline AccessInternal::LoadProxy<P, decorators> load(P* addr) { 411 return AccessInternal::LoadProxy<P, decorators>(addr); 412 } 413 414 template <typename P> 415 static inline AccessInternal::LoadProxy<P, decorators | VALUE_IS_OOP> oop_load(P* addr) { 416 return AccessInternal::LoadProxy<P, decorators | VALUE_IS_OOP>(addr); 417 } 418 419 template <typename P> 420 static inline AccessInternal::LoadAtProxy<P, decorators> load_at(P base, ptrdiff_t offset) { 421 return AccessInternal::LoadAtProxy<P, decorators>(base, offset); 422 } 423 424 template <typename P> 425 static inline AccessInternal::LoadAtProxy<P, decorators | VALUE_IS_OOP> oop_load_at(P base, ptrdiff_t offset) { 426 return AccessInternal::LoadAtProxy<P, decorators | VALUE_IS_OOP>(base, offset); 427 } 428 429 template <typename P, typename T> 430 static inline T cas(T new_value, P* addr, T compare_value) { 431 return AccessInternal::cas<decorators, P, T>(new_value, addr, compare_value); 432 } 433 434 template <typename P, typename T> 435 static inline T oop_cas(T new_value, P* addr, T compare_value) { 436 return AccessInternal::cas<decorators | VALUE_IS_OOP, P, T>(new_value, addr, compare_value); 437 } 438 439 template <typename P, typename T> 440 static inline T cas_at(T new_value, P base, ptrdiff_t offset, T compare_value) { 441 return AccessInternal::cas_at<decorators, P, T>(new_value, base, offset, compare_value); 442 } 443 444 template <typename P, typename T> 445 static inline T oop_cas_at(T new_value, P base, ptrdiff_t offset, T compare_value) { 446 return AccessInternal::cas_at<decorators | VALUE_IS_OOP, P, T>(new_value, base, offset, compare_value); 447 } 448 449 template <typename P, typename T> 450 static inline T swap(T new_value, P* addr) { 451 return AccessInternal::swap<decorators, P, T>(new_value, addr); 452 } 453 454 template <typename P, typename T> 455 static inline T oop_swap(T new_value, P* addr) { 456 return AccessInternal::swap<decorators | VALUE_IS_OOP, P, T>(new_value, addr); 457 } 458 459 template <typename P, typename T> 460 static inline T swap_at(T new_value, P base, ptrdiff_t offset) { 461 return AccessInternal::swap_at<decorators, P, T>(new_value, base, offset); 462 } 463 464 template <typename P, typename T> 465 static inline T oop_swap_at(T new_value, P base, ptrdiff_t offset) { 466 return AccessInternal::swap_at<decorators | VALUE_IS_OOP, P, T>(new_value, base, offset); 467 } 468 469 template <typename T> 470 static inline bool copy(arrayOop src_obj, arrayOop dst_obj, T *src, T *dst, size_t length) { 471 return AccessInternal::copy<decorators, T>(src_obj, dst_obj, src, dst, length); 472 } 473 474 template <typename T> 475 static inline bool oop_copy(arrayOop src_obj, arrayOop dst_obj, T *src, T *dst, size_t length) { 476 return AccessInternal::copy<decorators | VALUE_IS_OOP, T>(src_obj, dst_obj, src, dst, length); 477 } 478 479 static inline void clone(oop src, oop dst, size_t size) { 480 AccessInternal::clone<decorators>(src, dst, size); 481 } 482 }; 483 484 template <DecoratorSet decorators = EMPTY_DECORATOR> 485 class RawAccess: public Access<ACCESS_RAW | decorators> {}; 486 487 template <DecoratorSet decorators = EMPTY_DECORATOR> 488 class BasicAccess: public Access<ACCESS_BASIC | decorators> {}; 489 490 template <DecoratorSet decorators = EMPTY_DECORATOR> 491 class HeapAccess: public Access<ACCESS_ON_HEAP | decorators> { 492 enum { 493 CLASS_DECORATORS = ACCESS_ON_HEAP | decorators 494 }; 495 typedef Access<CLASS_DECORATORS> ClassAccess; 496 public: 497 // Constrain base pointers to always be an oop for heap accesses 498 template <typename T> 499 static inline void store_at(oop base, ptrdiff_t offset, T value) { 500 ClassAccess::store_at(base, offset, value); 501 } 502 503 template <typename T> 504 static inline void oop_store_at(oop base, ptrdiff_t offset, T value) { 505 ClassAccess::oop_store_at(base, offset, (typename AccessInternal::OopOrNarrowOop<T>::type)value); 506 } 507 508 static inline AccessInternal::LoadAtProxy<oop, CLASS_DECORATORS> 509 load_at(oop base, ptrdiff_t offset) { 510 return ClassAccess::load_at(base, offset); 511 } 512 513 static inline AccessInternal::LoadAtProxy<oop, CLASS_DECORATORS | VALUE_IS_OOP> 514 oop_load_at(oop base, ptrdiff_t offset) { 515 return ClassAccess::oop_load_at(base, offset); 516 } 517 518 template <typename T> 519 static inline T cas_at(T new_value, oop base, ptrdiff_t offset, T compare_value) { 520 return ClassAccess::cas_at(new_value, base, offset, compare_value); 521 } 522 523 template <typename T> 524 static inline T oop_cas_at(T new_value, oop base, ptrdiff_t offset, T compare_value) { 525 return ClassAccess::oop_cas_at((typename AccessInternal::OopOrNarrowOop<T>::type)new_value, base, 526 offset, (typename AccessInternal::OopOrNarrowOop<T>::type)compare_value); 527 } 528 529 template <typename T> 530 static inline T swap_at(T new_value, oop base, ptrdiff_t offset) { 531 return ClassAccess::swap_at(new_value, base, offset); 532 } 533 534 template <typename T> 535 static inline T oop_swap_at(T new_value, oop base, ptrdiff_t offset) { 536 return ClassAccess::oop_swap_at((typename AccessInternal::OopOrNarrowOop<T>::type)new_value, base, offset); 537 } 538 }; 539 540 template <DecoratorSet decorators = EMPTY_DECORATOR> 541 class RootAccess: public Access<ACCESS_ON_ROOT | decorators> { 542 }; 543 544 template <DecoratorSet decorators = EMPTY_DECORATOR> 545 class NMethodAccess: private RootAccess<ACCESS_ON_NMETHOD | decorators> { 546 public: 547 // Only supported access on nmethods for now 548 static inline void oop_store_at(nmethod* base, ptrdiff_t offset, oop value) { 549 AccessInternal::store_at<ACCESS_ON_NMETHOD | VALUE_IS_OOP, nmethod*, oop>(base, offset, value); 550 } 551 }; 552 553 template <DecoratorSet decorators = EMPTY_DECORATOR> 554 class KlassAccess: private RootAccess<ACCESS_ON_KLASS | decorators> { 555 public: 556 // Only supported access on Klass for now 557 static inline void oop_store_at(Klass* base, ptrdiff_t offset, oop value) { 558 AccessInternal::store_at<ACCESS_ON_KLASS | VALUE_IS_OOP, Klass*, oop>(base, offset, value); 559 } 560 }; 561 562 #endif // SHARE_VM_RUNTIME_ACCESS_HPP