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