| 1 | /* | 
| 2 |  * Copyright (c) 2017, 2018, 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_OOPS_ACCESSBACKEND_HPP | 
| 26 | #define SHARE_OOPS_ACCESSBACKEND_HPP | 
| 27 |  | 
| 28 | #include "gc/shared/barrierSetConfig.hpp" | 
| 29 | #include "memory/allocation.hpp" | 
| 30 | #include "metaprogramming/conditional.hpp" | 
| 31 | #include "metaprogramming/decay.hpp" | 
| 32 | #include "metaprogramming/enableIf.hpp" | 
| 33 | #include "metaprogramming/integralConstant.hpp" | 
| 34 | #include "metaprogramming/isFloatingPoint.hpp" | 
| 35 | #include "metaprogramming/isIntegral.hpp" | 
| 36 | #include "metaprogramming/isPointer.hpp" | 
| 37 | #include "metaprogramming/isSame.hpp" | 
| 38 | #include "metaprogramming/isVolatile.hpp" | 
| 39 | #include "oops/accessDecorators.hpp" | 
| 40 | #include "oops/oopsHierarchy.hpp" | 
| 41 | #include "utilities/debug.hpp" | 
| 42 | #include "utilities/globalDefinitions.hpp" | 
| 43 |  | 
| 44 |  | 
| 45 | // This metafunction returns either oop or narrowOop depending on whether | 
| 46 | // an access needs to use compressed oops or not. | 
| 47 | template <DecoratorSet decorators> | 
| 48 | struct HeapOopType: AllStatic { | 
| 49 |   static const bool needs_oop_compress = HasDecorator<decorators, INTERNAL_CONVERT_COMPRESSED_OOP>::value && | 
| 50 |                                          HasDecorator<decorators, INTERNAL_RT_USE_COMPRESSED_OOPS>::value; | 
| 51 |   typedef typename Conditional<needs_oop_compress, narrowOop, oop>::type type; | 
| 52 | }; | 
| 53 |  | 
| 54 | namespace AccessInternal { | 
| 55 |   enum BarrierType { | 
| 56 |     BARRIER_STORE, | 
| 57 |     BARRIER_STORE_AT, | 
| 58 |     BARRIER_LOAD, | 
| 59 |     BARRIER_LOAD_AT, | 
| 60 |     BARRIER_ATOMIC_CMPXCHG, | 
| 61 |     BARRIER_ATOMIC_CMPXCHG_AT, | 
| 62 |     BARRIER_ATOMIC_XCHG, | 
| 63 |     BARRIER_ATOMIC_XCHG_AT, | 
| 64 |     BARRIER_ARRAYCOPY, | 
| 65 |     BARRIER_CLONE, | 
| 66 |     BARRIER_RESOLVE, | 
| 67 |     BARRIER_EQUALS | 
| 68 |   }; | 
| 69 |  | 
| 70 |   template <DecoratorSet decorators, typename T> | 
| 71 |   struct MustConvertCompressedOop: public IntegralConstant<bool, | 
| 72 |     HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value && | 
| 73 |     IsSame<typename HeapOopType<decorators>::type, narrowOop>::value && | 
| 74 |     IsSame<T, oop>::value> {}; | 
| 75 |  | 
| 76 |   // This metafunction returns an appropriate oop type if the value is oop-like | 
| 77 |   // and otherwise returns the same type T. | 
| 78 |   template <DecoratorSet decorators, typename T> | 
| 79 |   struct EncodedType: AllStatic { | 
| 80 |     typedef typename Conditional< | 
| 81 |       HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value, | 
| 82 |       typename HeapOopType<decorators>::type, T>::type type; | 
| 83 |   }; | 
| 84 |  | 
| 85 |   template <DecoratorSet decorators> | 
| 86 |   inline typename HeapOopType<decorators>::type* | 
| 87 |   oop_field_addr(oop base, ptrdiff_t byte_offset) { | 
| 88 |     return reinterpret_cast<typename HeapOopType<decorators>::type*>( | 
| 89 |              reinterpret_cast<intptr_t>((void*)base) + byte_offset); | 
| 90 |   } | 
| 91 |  | 
| 92 |   // This metafunction returns whether it is possible for a type T to require | 
| 93 |   // locking to support wide atomics or not. | 
| 94 |   template <typename T> | 
| 95 | #ifdef SUPPORTS_NATIVE_CX8 | 
| 96 |   struct PossiblyLockedAccess: public IntegralConstant<bool, false> {}; | 
| 97 | #else | 
| 98 |   struct PossiblyLockedAccess: public IntegralConstant<bool, (sizeof(T) > 4)> {}; | 
| 99 | #endif | 
| 100 |  | 
| 101 |   template <DecoratorSet decorators, typename T> | 
| 102 |   struct AccessFunctionTypes { | 
| 103 |     typedef T (*load_at_func_t)(oop base, ptrdiff_t offset); | 
| 104 |     typedef void (*store_at_func_t)(oop base, ptrdiff_t offset, T value); | 
| 105 |     typedef T (*atomic_cmpxchg_at_func_t)(T new_value, oop base, ptrdiff_t offset, T compare_value); | 
| 106 |     typedef T (*atomic_xchg_at_func_t)(T new_value, oop base, ptrdiff_t offset); | 
| 107 |  | 
| 108 |     typedef T (*load_func_t)(void* addr); | 
| 109 |     typedef void (*store_func_t)(void* addr, T value); | 
| 110 |     typedef T (*atomic_cmpxchg_func_t)(T new_value, void* addr, T compare_value); | 
| 111 |     typedef T (*atomic_xchg_func_t)(T new_value, void* addr); | 
| 112 |  | 
| 113 |     typedef bool (*arraycopy_func_t)(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, | 
| 114 |                                      arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, | 
| 115 |                                      size_t length); | 
| 116 |     typedef void (*clone_func_t)(oop src, oop dst, size_t size); | 
| 117 |     typedef oop (*resolve_func_t)(oop obj); | 
| 118 |     typedef bool (*equals_func_t)(oop o1, oop o2); | 
| 119 |   }; | 
| 120 |  | 
| 121 |   template <DecoratorSet decorators> | 
| 122 |   struct AccessFunctionTypes<decorators, void> { | 
| 123 |     typedef bool (*arraycopy_func_t)(arrayOop src_obj, size_t src_offset_in_bytes, void* src, | 
| 124 |                                      arrayOop dst_obj, size_t dst_offset_in_bytes, void* dst, | 
| 125 |                                      size_t length); | 
| 126 |   }; | 
| 127 |  | 
| 128 |   template <DecoratorSet decorators, typename T, BarrierType barrier> struct AccessFunction {}; | 
| 129 |  | 
| 130 | #define ACCESS_GENERATE_ACCESS_FUNCTION(bt, func)                   \ | 
| 131 |   template <DecoratorSet decorators, typename T>                    \ | 
| 132 |   struct AccessFunction<decorators, T, bt>: AllStatic{              \ | 
| 133 |     typedef typename AccessFunctionTypes<decorators, T>::func type; \ | 
| 134 |   } | 
| 135 |   ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_STORE, store_func_t); | 
| 136 |   ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_STORE_AT, store_at_func_t); | 
| 137 |   ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_LOAD, load_func_t); | 
| 138 |   ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_LOAD_AT, load_at_func_t); | 
| 139 |   ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_ATOMIC_CMPXCHG, atomic_cmpxchg_func_t); | 
| 140 |   ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_ATOMIC_CMPXCHG_AT, atomic_cmpxchg_at_func_t); | 
| 141 |   ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_ATOMIC_XCHG, atomic_xchg_func_t); | 
| 142 |   ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_ATOMIC_XCHG_AT, atomic_xchg_at_func_t); | 
| 143 |   ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_ARRAYCOPY, arraycopy_func_t); | 
| 144 |   ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_CLONE, clone_func_t); | 
| 145 |   ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_RESOLVE, resolve_func_t); | 
| 146 |   ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_EQUALS, equals_func_t); | 
| 147 | #undef ACCESS_GENERATE_ACCESS_FUNCTION | 
| 148 |  | 
| 149 |   template <DecoratorSet decorators, typename T, BarrierType barrier_type> | 
| 150 |   typename AccessFunction<decorators, T, barrier_type>::type resolve_barrier(); | 
| 151 |  | 
| 152 |   template <DecoratorSet decorators, typename T, BarrierType barrier_type> | 
| 153 |   typename AccessFunction<decorators, T, barrier_type>::type resolve_oop_barrier(); | 
| 154 |  | 
| 155 |   class AccessLocker { | 
| 156 |   public: | 
| 157 |     AccessLocker(); | 
| 158 |     ~AccessLocker(); | 
| 159 |   }; | 
| 160 |   bool wide_atomic_needs_locking(); | 
| 161 |  | 
| 162 |   void* field_addr(oop base, ptrdiff_t offset); | 
| 163 |  | 
| 164 |   // Forward calls to Copy:: in the cpp file to reduce dependencies and allow | 
| 165 |   // faster build times, given how frequently included access is. | 
| 166 |   void arraycopy_arrayof_conjoint_oops(void* src, void* dst, size_t length); | 
| 167 |   void arraycopy_conjoint_oops(oop* src, oop* dst, size_t length); | 
| 168 |   void arraycopy_conjoint_oops(narrowOop* src, narrowOop* dst, size_t length); | 
| 169 |  | 
| 170 |   void arraycopy_disjoint_words(void* src, void* dst, size_t length); | 
| 171 |   void arraycopy_disjoint_words_atomic(void* src, void* dst, size_t length); | 
| 172 |  | 
| 173 |   template<typename T> | 
| 174 |   void arraycopy_conjoint(T* src, T* dst, size_t length); | 
| 175 |   template<typename T> | 
| 176 |   void arraycopy_arrayof_conjoint(T* src, T* dst, size_t length); | 
| 177 |   template<typename T> | 
| 178 |   void arraycopy_conjoint_atomic(T* src, T* dst, size_t length); | 
| 179 | } | 
| 180 |  | 
| 181 | // This mask specifies what decorators are relevant for raw accesses. When passing | 
| 182 | // accesses to the raw layer, irrelevant decorators are removed. | 
| 183 | const DecoratorSet RAW_DECORATOR_MASK = INTERNAL_DECORATOR_MASK | MO_DECORATOR_MASK | | 
| 184 |                                         ARRAYCOPY_DECORATOR_MASK | IS_NOT_NULL; | 
| 185 |  | 
| 186 | // The RawAccessBarrier performs raw accesses with additional knowledge of | 
| 187 | // memory ordering, so that OrderAccess/Atomic is called when necessary. | 
| 188 | // It additionally handles compressed oops, and hence is not completely "raw" | 
| 189 | // strictly speaking. | 
| 190 | template <DecoratorSet decorators> | 
| 191 | class RawAccessBarrier: public AllStatic { | 
| 192 | protected: | 
| 193 |   static inline void* field_addr(oop base, ptrdiff_t byte_offset) { | 
| 194 |     return AccessInternal::field_addr(base, byte_offset); | 
| 195 |   } | 
| 196 |  | 
| 197 | protected: | 
| 198 |   // Only encode if INTERNAL_VALUE_IS_OOP | 
| 199 |   template <DecoratorSet idecorators, typename T> | 
| 200 |   static inline typename EnableIf< | 
| 201 |     AccessInternal::MustConvertCompressedOop<idecorators, T>::value, | 
| 202 |     typename HeapOopType<idecorators>::type>::type | 
| 203 |   encode_internal(T value); | 
| 204 |  | 
| 205 |   template <DecoratorSet idecorators, typename T> | 
| 206 |   static inline typename EnableIf< | 
| 207 |     !AccessInternal::MustConvertCompressedOop<idecorators, T>::value, T>::type | 
| 208 |   encode_internal(T value) { | 
| 209 |     return value; | 
| 210 |   } | 
| 211 |  | 
| 212 |   template <typename T> | 
| 213 |   static inline typename AccessInternal::EncodedType<decorators, T>::type | 
| 214 |   encode(T value) { | 
| 215 |     return encode_internal<decorators, T>(value); | 
| 216 |   } | 
| 217 |  | 
| 218 |   // Only decode if INTERNAL_VALUE_IS_OOP | 
| 219 |   template <DecoratorSet idecorators, typename T> | 
| 220 |   static inline typename EnableIf< | 
| 221 |     AccessInternal::MustConvertCompressedOop<idecorators, T>::value, T>::type | 
| 222 |   decode_internal(typename HeapOopType<idecorators>::type value); | 
| 223 |  | 
| 224 |   template <DecoratorSet idecorators, typename T> | 
| 225 |   static inline typename EnableIf< | 
| 226 |     !AccessInternal::MustConvertCompressedOop<idecorators, T>::value, T>::type | 
| 227 |   decode_internal(T value) { | 
| 228 |     return value; | 
| 229 |   } | 
| 230 |  | 
| 231 |   template <typename T> | 
| 232 |   static inline T decode(typename AccessInternal::EncodedType<decorators, T>::type value) { | 
| 233 |     return decode_internal<decorators, T>(value); | 
| 234 |   } | 
| 235 |  | 
| 236 | protected: | 
| 237 |   template <DecoratorSet ds, typename T> | 
| 238 |   static typename EnableIf< | 
| 239 |     HasDecorator<ds, MO_SEQ_CST>::value, T>::type | 
| 240 |   load_internal(void* addr); | 
| 241 |  | 
| 242 |   template <DecoratorSet ds, typename T> | 
| 243 |   static typename EnableIf< | 
| 244 |     HasDecorator<ds, MO_ACQUIRE>::value, T>::type | 
| 245 |   load_internal(void* addr); | 
| 246 |  | 
| 247 |   template <DecoratorSet ds, typename T> | 
| 248 |   static typename EnableIf< | 
| 249 |     HasDecorator<ds, MO_RELAXED>::value, T>::type | 
| 250 |   load_internal(void* addr); | 
| 251 |  | 
| 252 |   template <DecoratorSet ds, typename T> | 
| 253 |   static inline typename EnableIf< | 
| 254 |     HasDecorator<ds, MO_VOLATILE>::value, T>::type | 
| 255 |   load_internal(void* addr) { | 
| 256 |     return *reinterpret_cast<const volatile T*>(addr); | 
| 257 |   } | 
| 258 |  | 
| 259 |   template <DecoratorSet ds, typename T> | 
| 260 |   static inline typename EnableIf< | 
| 261 |     HasDecorator<ds, MO_UNORDERED>::value, T>::type | 
| 262 |   load_internal(void* addr) { | 
| 263 |     return *reinterpret_cast<T*>(addr); | 
| 264 |   } | 
| 265 |  | 
| 266 |   template <DecoratorSet ds, typename T> | 
| 267 |   static typename EnableIf< | 
| 268 |     HasDecorator<ds, MO_SEQ_CST>::value>::type | 
| 269 |   store_internal(void* addr, T value); | 
| 270 |  | 
| 271 |   template <DecoratorSet ds, typename T> | 
| 272 |   static typename EnableIf< | 
| 273 |     HasDecorator<ds, MO_RELEASE>::value>::type | 
| 274 |   store_internal(void* addr, T value); | 
| 275 |  | 
| 276 |   template <DecoratorSet ds, typename T> | 
| 277 |   static typename EnableIf< | 
| 278 |     HasDecorator<ds, MO_RELAXED>::value>::type | 
| 279 |   store_internal(void* addr, T value); | 
| 280 |  | 
| 281 |   template <DecoratorSet ds, typename T> | 
| 282 |   static inline typename EnableIf< | 
| 283 |     HasDecorator<ds, MO_VOLATILE>::value>::type | 
| 284 |   store_internal(void* addr, T value) { | 
| 285 |     (void)const_cast<T&>(*reinterpret_cast<volatile T*>(addr) = value); | 
| 286 |   } | 
| 287 |  | 
| 288 |   template <DecoratorSet ds, typename T> | 
| 289 |   static inline typename EnableIf< | 
| 290 |     HasDecorator<ds, MO_UNORDERED>::value>::type | 
| 291 |   store_internal(void* addr, T value) { | 
| 292 |     *reinterpret_cast<T*>(addr) = value; | 
| 293 |   } | 
| 294 |  | 
| 295 |   template <DecoratorSet ds, typename T> | 
| 296 |   static typename EnableIf< | 
| 297 |     HasDecorator<ds, MO_SEQ_CST>::value, T>::type | 
| 298 |   atomic_cmpxchg_internal(T new_value, void* addr, T compare_value); | 
| 299 |  | 
| 300 |   template <DecoratorSet ds, typename T> | 
| 301 |   static typename EnableIf< | 
| 302 |     HasDecorator<ds, MO_RELAXED>::value, T>::type | 
| 303 |   atomic_cmpxchg_internal(T new_value, void* addr, T compare_value); | 
| 304 |  | 
| 305 |   template <DecoratorSet ds, typename T> | 
| 306 |   static typename EnableIf< | 
| 307 |     HasDecorator<ds, MO_SEQ_CST>::value, T>::type | 
| 308 |   atomic_xchg_internal(T new_value, void* addr); | 
| 309 |  | 
| 310 |   // The following *_locked mechanisms serve the purpose of handling atomic operations | 
| 311 |   // that are larger than a machine can handle, and then possibly opt for using | 
| 312 |   // a slower path using a mutex to perform the operation. | 
| 313 |  | 
| 314 |   template <DecoratorSet ds, typename T> | 
| 315 |   static inline typename EnableIf< | 
| 316 |     !AccessInternal::PossiblyLockedAccess<T>::value, T>::type | 
| 317 |   atomic_cmpxchg_maybe_locked(T new_value, void* addr, T compare_value) { | 
| 318 |     return atomic_cmpxchg_internal<ds>(new_value, addr, compare_value); | 
| 319 |   } | 
| 320 |  | 
| 321 |   template <DecoratorSet ds, typename T> | 
| 322 |   static typename EnableIf< | 
| 323 |     AccessInternal::PossiblyLockedAccess<T>::value, T>::type | 
| 324 |   atomic_cmpxchg_maybe_locked(T new_value, void* addr, T compare_value); | 
| 325 |  | 
| 326 |   template <DecoratorSet ds, typename T> | 
| 327 |   static inline typename EnableIf< | 
| 328 |     !AccessInternal::PossiblyLockedAccess<T>::value, T>::type | 
| 329 |   atomic_xchg_maybe_locked(T new_value, void* addr) { | 
| 330 |     return atomic_xchg_internal<ds>(new_value, addr); | 
| 331 |   } | 
| 332 |  | 
| 333 |   template <DecoratorSet ds, typename T> | 
| 334 |   static typename EnableIf< | 
| 335 |     AccessInternal::PossiblyLockedAccess<T>::value, T>::type | 
| 336 |   atomic_xchg_maybe_locked(T new_value, void* addr); | 
| 337 |  | 
| 338 | public: | 
| 339 |   template <typename T> | 
| 340 |   static inline void store(void* addr, T value) { | 
| 341 |     store_internal<decorators>(addr, value); | 
| 342 |   } | 
| 343 |  | 
| 344 |   template <typename T> | 
| 345 |   static inline T load(void* addr) { | 
| 346 |     return load_internal<decorators, T>(addr); | 
| 347 |   } | 
| 348 |  | 
| 349 |   template <typename T> | 
| 350 |   static inline T atomic_cmpxchg(T new_value, void* addr, T compare_value) { | 
| 351 |     return atomic_cmpxchg_maybe_locked<decorators>(new_value, addr, compare_value); | 
| 352 |   } | 
| 353 |  | 
| 354 |   template <typename T> | 
| 355 |   static inline T atomic_xchg(T new_value, void* addr) { | 
| 356 |     return atomic_xchg_maybe_locked<decorators>(new_value, addr); | 
| 357 |   } | 
| 358 |  | 
| 359 |   template <typename T> | 
| 360 |   static bool arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, | 
| 361 |                         arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, | 
| 362 |                         size_t length); | 
| 363 |  | 
| 364 |   template <typename T> | 
| 365 |   static void oop_store(void* addr, T value); | 
| 366 |   template <typename T> | 
| 367 |   static void oop_store_at(oop base, ptrdiff_t offset, T value); | 
| 368 |  | 
| 369 |   template <typename T> | 
| 370 |   static T oop_load(void* addr); | 
| 371 |   template <typename T> | 
| 372 |   static T oop_load_at(oop base, ptrdiff_t offset); | 
| 373 |  | 
| 374 |   template <typename T> | 
| 375 |   static T oop_atomic_cmpxchg(T new_value, void* addr, T compare_value); | 
| 376 |   template <typename T> | 
| 377 |   static T oop_atomic_cmpxchg_at(T new_value, oop base, ptrdiff_t offset, T compare_value); | 
| 378 |  | 
| 379 |   template <typename T> | 
| 380 |   static T oop_atomic_xchg(T new_value, void* addr); | 
| 381 |   template <typename T> | 
| 382 |   static T oop_atomic_xchg_at(T new_value, oop base, ptrdiff_t offset); | 
| 383 |  | 
| 384 |   template <typename T> | 
| 385 |   static void store_at(oop base, ptrdiff_t offset, T value) { | 
| 386 |     store(field_addr(base, offset), value); | 
| 387 |   } | 
| 388 |  | 
| 389 |   template <typename T> | 
| 390 |   static T load_at(oop base, ptrdiff_t offset) { | 
| 391 |     return load<T>(field_addr(base, offset)); | 
| 392 |   } | 
| 393 |  | 
| 394 |   template <typename T> | 
| 395 |   static T atomic_cmpxchg_at(T new_value, oop base, ptrdiff_t offset, T compare_value) { | 
| 396 |     return atomic_cmpxchg(new_value, field_addr(base, offset), compare_value); | 
| 397 |   } | 
| 398 |  | 
| 399 |   template <typename T> | 
| 400 |   static T atomic_xchg_at(T new_value, oop base, ptrdiff_t offset) { | 
| 401 |     return atomic_xchg(new_value, field_addr(base, offset)); | 
| 402 |   } | 
| 403 |  | 
| 404 |   template <typename T> | 
| 405 |   static bool oop_arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, | 
| 406 |                             arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, | 
| 407 |                             size_t length); | 
| 408 |  | 
| 409 |   static void clone(oop src, oop dst, size_t size); | 
| 410 |  | 
| 411 |   static oop resolve(oop obj) { return obj; } | 
| 412 |  | 
| 413 |   static bool equals(oop o1, oop o2) { return (void*)o1 == (void*)o2; } | 
| 414 | }; | 
| 415 |  | 
| 416 | // Below is the implementation of the first 4 steps of the template pipeline: | 
| 417 | // * Step 1: Set default decorators and decay types. This step gets rid of CV qualifiers | 
| 418 | //           and sets default decorators to sensible values. | 
| 419 | // * Step 2: Reduce types. This step makes sure there is only a single T type and not | 
| 420 | //           multiple types. The P type of the address and T type of the value must | 
| 421 | //           match. | 
| 422 | // * Step 3: Pre-runtime dispatch. This step checks whether a runtime call can be | 
| 423 | //           avoided, and in that case avoids it (calling raw accesses or | 
| 424 | //           primitive accesses in a build that does not require primitive GC barriers) | 
| 425 | // * Step 4: Runtime-dispatch. This step performs a runtime dispatch to the corresponding | 
| 426 | //           BarrierSet::AccessBarrier accessor that attaches GC-required barriers | 
| 427 | //           to the access. | 
| 428 |  | 
| 429 | namespace AccessInternal { | 
| 430 |   template <typename T> | 
| 431 |   struct OopOrNarrowOopInternal: AllStatic { | 
| 432 |     typedef oop type; | 
| 433 |   }; | 
| 434 |  | 
| 435 |   template <> | 
| 436 |   struct OopOrNarrowOopInternal<narrowOop>: AllStatic { | 
| 437 |     typedef narrowOop type; | 
| 438 |   }; | 
| 439 |  | 
| 440 |   // This metafunction returns a canonicalized oop/narrowOop type for a passed | 
| 441 |   // in oop-like types passed in from oop_* overloads where the user has sworn | 
| 442 |   // that the passed in values should be oop-like (e.g. oop, oopDesc*, arrayOop, | 
| 443 |   // narrowOoop, instanceOopDesc*, and random other things). | 
| 444 |   // In the oop_* overloads, it must hold that if the passed in type T is not | 
| 445 |   // narrowOop, then it by contract has to be one of many oop-like types implicitly | 
| 446 |   // convertible to oop, and hence returns oop as the canonical oop type. | 
| 447 |   // If it turns out it was not, then the implicit conversion to oop will fail | 
| 448 |   // to compile, as desired. | 
| 449 |   template <typename T> | 
| 450 |   struct OopOrNarrowOop: AllStatic { | 
| 451 |     typedef typename OopOrNarrowOopInternal<typename Decay<T>::type>::type type; | 
| 452 |   }; | 
| 453 |  | 
| 454 |   inline void* field_addr(oop base, ptrdiff_t byte_offset) { | 
| 455 |     return reinterpret_cast<void*>(reinterpret_cast<intptr_t>((void*)base) + byte_offset); | 
| 456 |   } | 
| 457 |   // Step 4: Runtime dispatch | 
| 458 |   // The RuntimeDispatch class is responsible for performing a runtime dispatch of the | 
| 459 |   // accessor. This is required when the access either depends on whether compressed oops | 
| 460 |   // is being used, or it depends on which GC implementation was chosen (e.g. requires GC | 
| 461 |   // barriers). The way it works is that a function pointer initially pointing to an | 
| 462 |   // accessor resolution function gets called for each access. Upon first invocation, | 
| 463 |   // it resolves which accessor to be used in future invocations and patches the | 
| 464 |   // function pointer to this new accessor. | 
| 465 |  | 
| 466 |   template <DecoratorSet decorators, typename T, BarrierType type> | 
| 467 |   struct RuntimeDispatch: AllStatic {}; | 
| 468 |  | 
| 469 |   template <DecoratorSet decorators, typename T> | 
| 470 |   struct RuntimeDispatch<decorators, T, BARRIER_STORE>: AllStatic { | 
| 471 |     typedef typename AccessFunction<decorators, T, BARRIER_STORE>::type func_t; | 
| 472 |     static func_t _store_func; | 
| 473 |  | 
| 474 |     static void store_init(void* addr, T value); | 
| 475 |  | 
| 476 |     static inline void store(void* addr, T value) { | 
| 477 |       _store_func(addr, value); | 
| 478 |     } | 
| 479 |   }; | 
| 480 |  | 
| 481 |   template <DecoratorSet decorators, typename T> | 
| 482 |   struct RuntimeDispatch<decorators, T, BARRIER_STORE_AT>: AllStatic { | 
| 483 |     typedef typename AccessFunction<decorators, T, BARRIER_STORE_AT>::type func_t; | 
| 484 |     static func_t _store_at_func; | 
| 485 |  | 
| 486 |     static void store_at_init(oop base, ptrdiff_t offset, T value); | 
| 487 |  | 
| 488 |     static inline void store_at(oop base, ptrdiff_t offset, T value) { | 
| 489 |       _store_at_func(base, offset, value); | 
| 490 |     } | 
| 491 |   }; | 
| 492 |  | 
| 493 |   template <DecoratorSet decorators, typename T> | 
| 494 |   struct RuntimeDispatch<decorators, T, BARRIER_LOAD>: AllStatic { | 
| 495 |     typedef typename AccessFunction<decorators, T, BARRIER_LOAD>::type func_t; | 
| 496 |     static func_t _load_func; | 
| 497 |  | 
| 498 |     static T load_init(void* addr); | 
| 499 |  | 
| 500 |     static inline T load(void* addr) { | 
| 501 |       return _load_func(addr); | 
| 502 |     } | 
| 503 |   }; | 
| 504 |  | 
| 505 |   template <DecoratorSet decorators, typename T> | 
| 506 |   struct RuntimeDispatch<decorators, T, BARRIER_LOAD_AT>: AllStatic { | 
| 507 |     typedef typename AccessFunction<decorators, T, BARRIER_LOAD_AT>::type func_t; | 
| 508 |     static func_t _load_at_func; | 
| 509 |  | 
| 510 |     static T load_at_init(oop base, ptrdiff_t offset); | 
| 511 |  | 
| 512 |     static inline T load_at(oop base, ptrdiff_t offset) { | 
| 513 |       return _load_at_func(base, offset); | 
| 514 |     } | 
| 515 |   }; | 
| 516 |  | 
| 517 |   template <DecoratorSet decorators, typename T> | 
| 518 |   struct RuntimeDispatch<decorators, T, BARRIER_ATOMIC_CMPXCHG>: AllStatic { | 
| 519 |     typedef typename AccessFunction<decorators, T, BARRIER_ATOMIC_CMPXCHG>::type func_t; | 
| 520 |     static func_t _atomic_cmpxchg_func; | 
| 521 |  | 
| 522 |     static T atomic_cmpxchg_init(T new_value, void* addr, T compare_value); | 
| 523 |  | 
| 524 |     static inline T atomic_cmpxchg(T new_value, void* addr, T compare_value) { | 
| 525 |       return _atomic_cmpxchg_func(new_value, addr, compare_value); | 
| 526 |     } | 
| 527 |   }; | 
| 528 |  | 
| 529 |   template <DecoratorSet decorators, typename T> | 
| 530 |   struct RuntimeDispatch<decorators, T, BARRIER_ATOMIC_CMPXCHG_AT>: AllStatic { | 
| 531 |     typedef typename AccessFunction<decorators, T, BARRIER_ATOMIC_CMPXCHG_AT>::type func_t; | 
| 532 |     static func_t _atomic_cmpxchg_at_func; | 
| 533 |  | 
| 534 |     static T atomic_cmpxchg_at_init(T new_value, oop base, ptrdiff_t offset, T compare_value); | 
| 535 |  | 
| 536 |     static inline T atomic_cmpxchg_at(T new_value, oop base, ptrdiff_t offset, T compare_value) { | 
| 537 |       return _atomic_cmpxchg_at_func(new_value, base, offset, compare_value); | 
| 538 |     } | 
| 539 |   }; | 
| 540 |  | 
| 541 |   template <DecoratorSet decorators, typename T> | 
| 542 |   struct RuntimeDispatch<decorators, T, BARRIER_ATOMIC_XCHG>: AllStatic { | 
| 543 |     typedef typename AccessFunction<decorators, T, BARRIER_ATOMIC_XCHG>::type func_t; | 
| 544 |     static func_t _atomic_xchg_func; | 
| 545 |  | 
| 546 |     static T atomic_xchg_init(T new_value, void* addr); | 
| 547 |  | 
| 548 |     static inline T atomic_xchg(T new_value, void* addr) { | 
| 549 |       return _atomic_xchg_func(new_value, addr); | 
| 550 |     } | 
| 551 |   }; | 
| 552 |  | 
| 553 |   template <DecoratorSet decorators, typename T> | 
| 554 |   struct RuntimeDispatch<decorators, T, BARRIER_ATOMIC_XCHG_AT>: AllStatic { | 
| 555 |     typedef typename AccessFunction<decorators, T, BARRIER_ATOMIC_XCHG_AT>::type func_t; | 
| 556 |     static func_t _atomic_xchg_at_func; | 
| 557 |  | 
| 558 |     static T atomic_xchg_at_init(T new_value, oop base, ptrdiff_t offset); | 
| 559 |  | 
| 560 |     static inline T atomic_xchg_at(T new_value, oop base, ptrdiff_t offset) { | 
| 561 |       return _atomic_xchg_at_func(new_value, base, offset); | 
| 562 |     } | 
| 563 |   }; | 
| 564 |  | 
| 565 |   template <DecoratorSet decorators, typename T> | 
| 566 |   struct RuntimeDispatch<decorators, T, BARRIER_ARRAYCOPY>: AllStatic { | 
| 567 |     typedef typename AccessFunction<decorators, T, BARRIER_ARRAYCOPY>::type func_t; | 
| 568 |     static func_t _arraycopy_func; | 
| 569 |  | 
| 570 |     static bool arraycopy_init(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, | 
| 571 |                                arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, | 
| 572 |                                size_t length); | 
| 573 |  | 
| 574 |     static inline bool arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, | 
| 575 |                                  arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, | 
| 576 |                                  size_t length) { | 
| 577 |       return _arraycopy_func(src_obj, src_offset_in_bytes, src_raw, | 
| 578 |                              dst_obj, dst_offset_in_bytes, dst_raw, | 
| 579 |                              length); | 
| 580 |     } | 
| 581 |   }; | 
| 582 |  | 
| 583 |   template <DecoratorSet decorators, typename T> | 
| 584 |   struct RuntimeDispatch<decorators, T, BARRIER_CLONE>: AllStatic { | 
| 585 |     typedef typename AccessFunction<decorators, T, BARRIER_CLONE>::type func_t; | 
| 586 |     static func_t _clone_func; | 
| 587 |  | 
| 588 |     static void clone_init(oop src, oop dst, size_t size); | 
| 589 |  | 
| 590 |     static inline void clone(oop src, oop dst, size_t size) { | 
| 591 |       _clone_func(src, dst, size); | 
| 592 |     } | 
| 593 |   }; | 
| 594 |  | 
| 595 |   template <DecoratorSet decorators, typename T> | 
| 596 |   struct RuntimeDispatch<decorators, T, BARRIER_RESOLVE>: AllStatic { | 
| 597 |     typedef typename AccessFunction<decorators, T, BARRIER_RESOLVE>::type func_t; | 
| 598 |     static func_t _resolve_func; | 
| 599 |  | 
| 600 |     static oop resolve_init(oop obj); | 
| 601 |  | 
| 602 |     static inline oop resolve(oop obj) { | 
| 603 |       return _resolve_func(obj); | 
| 604 |     } | 
| 605 |   }; | 
| 606 |  | 
| 607 |   template <DecoratorSet decorators, typename T> | 
| 608 |   struct RuntimeDispatch<decorators, T, BARRIER_EQUALS>: AllStatic { | 
| 609 |     typedef typename AccessFunction<decorators, T, BARRIER_EQUALS>::type func_t; | 
| 610 |     static func_t _equals_func; | 
| 611 |  | 
| 612 |     static bool equals_init(oop o1, oop o2); | 
| 613 |  | 
| 614 |     static inline bool equals(oop o1, oop o2) { | 
| 615 |       return _equals_func(o1, o2); | 
| 616 |     } | 
| 617 |   }; | 
| 618 |  | 
| 619 |   // Initialize the function pointers to point to the resolving function. | 
| 620 |   template <DecoratorSet decorators, typename T> | 
| 621 |   typename AccessFunction<decorators, T, BARRIER_STORE>::type | 
| 622 |   RuntimeDispatch<decorators, T, BARRIER_STORE>::_store_func = &store_init; | 
| 623 |  | 
| 624 |   template <DecoratorSet decorators, typename T> | 
| 625 |   typename AccessFunction<decorators, T, BARRIER_STORE_AT>::type | 
| 626 |   RuntimeDispatch<decorators, T, BARRIER_STORE_AT>::_store_at_func = &store_at_init; | 
| 627 |  | 
| 628 |   template <DecoratorSet decorators, typename T> | 
| 629 |   typename AccessFunction<decorators, T, BARRIER_LOAD>::type | 
| 630 |   RuntimeDispatch<decorators, T, BARRIER_LOAD>::_load_func = &load_init; | 
| 631 |  | 
| 632 |   template <DecoratorSet decorators, typename T> | 
| 633 |   typename AccessFunction<decorators, T, BARRIER_LOAD_AT>::type | 
| 634 |   RuntimeDispatch<decorators, T, BARRIER_LOAD_AT>::_load_at_func = &load_at_init; | 
| 635 |  | 
| 636 |   template <DecoratorSet decorators, typename T> | 
| 637 |   typename AccessFunction<decorators, T, BARRIER_ATOMIC_CMPXCHG>::type | 
| 638 |   RuntimeDispatch<decorators, T, BARRIER_ATOMIC_CMPXCHG>::_atomic_cmpxchg_func = &atomic_cmpxchg_init; | 
| 639 |  | 
| 640 |   template <DecoratorSet decorators, typename T> | 
| 641 |   typename AccessFunction<decorators, T, BARRIER_ATOMIC_CMPXCHG_AT>::type | 
| 642 |   RuntimeDispatch<decorators, T, BARRIER_ATOMIC_CMPXCHG_AT>::_atomic_cmpxchg_at_func = &atomic_cmpxchg_at_init; | 
| 643 |  | 
| 644 |   template <DecoratorSet decorators, typename T> | 
| 645 |   typename AccessFunction<decorators, T, BARRIER_ATOMIC_XCHG>::type | 
| 646 |   RuntimeDispatch<decorators, T, BARRIER_ATOMIC_XCHG>::_atomic_xchg_func = &atomic_xchg_init; | 
| 647 |  | 
| 648 |   template <DecoratorSet decorators, typename T> | 
| 649 |   typename AccessFunction<decorators, T, BARRIER_ATOMIC_XCHG_AT>::type | 
| 650 |   RuntimeDispatch<decorators, T, BARRIER_ATOMIC_XCHG_AT>::_atomic_xchg_at_func = &atomic_xchg_at_init; | 
| 651 |  | 
| 652 |   template <DecoratorSet decorators, typename T> | 
| 653 |   typename AccessFunction<decorators, T, BARRIER_ARRAYCOPY>::type | 
| 654 |   RuntimeDispatch<decorators, T, BARRIER_ARRAYCOPY>::_arraycopy_func = &arraycopy_init; | 
| 655 |  | 
| 656 |   template <DecoratorSet decorators, typename T> | 
| 657 |   typename AccessFunction<decorators, T, BARRIER_CLONE>::type | 
| 658 |   RuntimeDispatch<decorators, T, BARRIER_CLONE>::_clone_func = &clone_init; | 
| 659 |  | 
| 660 |   template <DecoratorSet decorators, typename T> | 
| 661 |   typename AccessFunction<decorators, T, BARRIER_RESOLVE>::type | 
| 662 |   RuntimeDispatch<decorators, T, BARRIER_RESOLVE>::_resolve_func = &resolve_init; | 
| 663 |  | 
| 664 |   template <DecoratorSet decorators, typename T> | 
| 665 |   typename AccessFunction<decorators, T, BARRIER_EQUALS>::type | 
| 666 |   RuntimeDispatch<decorators, T, BARRIER_EQUALS>::_equals_func = &equals_init; | 
| 667 |  | 
| 668 |   // Step 3: Pre-runtime dispatching. | 
| 669 |   // The PreRuntimeDispatch class is responsible for filtering the barrier strength | 
| 670 |   // decorators. That is, for AS_RAW, it hardwires the accesses without a runtime | 
| 671 |   // dispatch point. Otherwise it goes through a runtime check if hardwiring was | 
| 672 |   // not possible. | 
| 673 |   struct PreRuntimeDispatch: AllStatic { | 
| 674 |     template<DecoratorSet decorators> | 
| 675 |     struct CanHardwireRaw: public IntegralConstant< | 
| 676 |       bool, | 
| 677 |       !HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value || // primitive access | 
| 678 |       !HasDecorator<decorators, INTERNAL_CONVERT_COMPRESSED_OOP>::value || // don't care about compressed oops (oop* address) | 
| 679 |       HasDecorator<decorators, INTERNAL_RT_USE_COMPRESSED_OOPS>::value> // we can infer we use compressed oops (narrowOop* address) | 
| 680 |     {}; | 
| 681 |  | 
| 682 |     static const DecoratorSet convert_compressed_oops = INTERNAL_RT_USE_COMPRESSED_OOPS | INTERNAL_CONVERT_COMPRESSED_OOP; | 
| 683 |  | 
| 684 |     template<DecoratorSet decorators> | 
| 685 |     static bool is_hardwired_primitive() { | 
| 686 |       return !HasDecorator<decorators, INTERNAL_BT_BARRIER_ON_PRIMITIVES>::value && | 
| 687 |              !HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value; | 
| 688 |     } | 
| 689 |  | 
| 690 |     template <DecoratorSet decorators, typename T> | 
| 691 |     inline static typename EnableIf< | 
| 692 |       HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value>::type | 
| 693 |     store(void* addr, T value) { | 
| 694 |       typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw; | 
| 695 |       if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) { | 
| 696 |         Raw::oop_store(addr, value); | 
| 697 |       } else { | 
| 698 |         Raw::store(addr, value); | 
| 699 |       } | 
| 700 |     } | 
| 701 |  | 
| 702 |     template <DecoratorSet decorators, typename T> | 
| 703 |     inline static typename EnableIf< | 
| 704 |       HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value>::type | 
| 705 |     store(void* addr, T value) { | 
| 706 |       if (UseCompressedOops) { | 
| 707 |         const DecoratorSet expanded_decorators = decorators | convert_compressed_oops; | 
| 708 |         PreRuntimeDispatch::store<expanded_decorators>(addr, value); | 
| 709 |       } else { | 
| 710 |         const DecoratorSet expanded_decorators = decorators & ~convert_compressed_oops; | 
| 711 |         PreRuntimeDispatch::store<expanded_decorators>(addr, value); | 
| 712 |       } | 
| 713 |     } | 
| 714 |  | 
| 715 |     template <DecoratorSet decorators, typename T> | 
| 716 |     inline static typename EnableIf< | 
| 717 |       !HasDecorator<decorators, AS_RAW>::value>::type | 
| 718 |     store(void* addr, T value) { | 
| 719 |       if (is_hardwired_primitive<decorators>()) { | 
| 720 |         const DecoratorSet expanded_decorators = decorators | AS_RAW; | 
| 721 |         PreRuntimeDispatch::store<expanded_decorators>(addr, value); | 
| 722 |       } else { | 
| 723 |         RuntimeDispatch<decorators, T, BARRIER_STORE>::store(addr, value); | 
| 724 |       } | 
| 725 |     } | 
| 726 |  | 
| 727 |     template <DecoratorSet decorators, typename T> | 
| 728 |     inline static typename EnableIf< | 
| 729 |       HasDecorator<decorators, AS_RAW>::value>::type | 
| 730 |     store_at(oop base, ptrdiff_t offset, T value) { | 
| 731 |       store<decorators>(field_addr(base, offset), value); | 
| 732 |     } | 
| 733 |  | 
| 734 |     template <DecoratorSet decorators, typename T> | 
| 735 |     inline static typename EnableIf< | 
| 736 |       !HasDecorator<decorators, AS_RAW>::value>::type | 
| 737 |     store_at(oop base, ptrdiff_t offset, T value) { | 
| 738 |       if (is_hardwired_primitive<decorators>()) { | 
| 739 |         const DecoratorSet expanded_decorators = decorators | AS_RAW; | 
| 740 |         PreRuntimeDispatch::store_at<expanded_decorators>(base, offset, value); | 
| 741 |       } else { | 
| 742 |         RuntimeDispatch<decorators, T, BARRIER_STORE_AT>::store_at(base, offset, value); | 
| 743 |       } | 
| 744 |     } | 
| 745 |  | 
| 746 |     template <DecoratorSet decorators, typename T> | 
| 747 |     inline static typename EnableIf< | 
| 748 |       HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value, T>::type | 
| 749 |     load(void* addr) { | 
| 750 |       typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw; | 
| 751 |       if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) { | 
| 752 |         return Raw::template oop_load<T>(addr); | 
| 753 |       } else { | 
| 754 |         return Raw::template load<T>(addr); | 
| 755 |       } | 
| 756 |     } | 
| 757 |  | 
| 758 |     template <DecoratorSet decorators, typename T> | 
| 759 |     inline static typename EnableIf< | 
| 760 |       HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value, T>::type | 
| 761 |     load(void* addr) { | 
| 762 |       if (UseCompressedOops) { | 
| 763 |         const DecoratorSet expanded_decorators = decorators | convert_compressed_oops; | 
| 764 |         return PreRuntimeDispatch::load<expanded_decorators, T>(addr); | 
| 765 |       } else { | 
| 766 |         const DecoratorSet expanded_decorators = decorators & ~convert_compressed_oops; | 
| 767 |         return PreRuntimeDispatch::load<expanded_decorators, T>(addr); | 
| 768 |       } | 
| 769 |     } | 
| 770 |  | 
| 771 |     template <DecoratorSet decorators, typename T> | 
| 772 |     inline static typename EnableIf< | 
| 773 |       !HasDecorator<decorators, AS_RAW>::value, T>::type | 
| 774 |     load(void* addr) { | 
| 775 |       if (is_hardwired_primitive<decorators>()) { | 
| 776 |         const DecoratorSet expanded_decorators = decorators | AS_RAW; | 
| 777 |         return PreRuntimeDispatch::load<expanded_decorators, T>(addr); | 
| 778 |       } else { | 
| 779 |         return RuntimeDispatch<decorators, T, BARRIER_LOAD>::load(addr); | 
| 780 |       } | 
| 781 |     } | 
| 782 |  | 
| 783 |     template <DecoratorSet decorators, typename T> | 
| 784 |     inline static typename EnableIf< | 
| 785 |       HasDecorator<decorators, AS_RAW>::value, T>::type | 
| 786 |     load_at(oop base, ptrdiff_t offset) { | 
| 787 |       return load<decorators, T>(field_addr(base, offset)); | 
| 788 |     } | 
| 789 |  | 
| 790 |     template <DecoratorSet decorators, typename T> | 
| 791 |     inline static typename EnableIf< | 
| 792 |       !HasDecorator<decorators, AS_RAW>::value, T>::type | 
| 793 |     load_at(oop base, ptrdiff_t offset) { | 
| 794 |       if (is_hardwired_primitive<decorators>()) { | 
| 795 |         const DecoratorSet expanded_decorators = decorators | AS_RAW; | 
| 796 |         return PreRuntimeDispatch::load_at<expanded_decorators, T>(base, offset); | 
| 797 |       } else { | 
| 798 |         return RuntimeDispatch<decorators, T, BARRIER_LOAD_AT>::load_at(base, offset); | 
| 799 |       } | 
| 800 |     } | 
| 801 |  | 
| 802 |     template <DecoratorSet decorators, typename T> | 
| 803 |     inline static typename EnableIf< | 
| 804 |       HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value, T>::type | 
| 805 |     atomic_cmpxchg(T new_value, void* addr, T compare_value) { | 
| 806 |       typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw; | 
| 807 |       if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) { | 
| 808 |         return Raw::oop_atomic_cmpxchg(new_value, addr, compare_value); | 
| 809 |       } else { | 
| 810 |         return Raw::atomic_cmpxchg(new_value, addr, compare_value); | 
| 811 |       } | 
| 812 |     } | 
| 813 |  | 
| 814 |     template <DecoratorSet decorators, typename T> | 
| 815 |     inline static typename EnableIf< | 
| 816 |       HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value, T>::type | 
| 817 |     atomic_cmpxchg(T new_value, void* addr, T compare_value) { | 
| 818 |       if (UseCompressedOops) { | 
| 819 |         const DecoratorSet expanded_decorators = decorators | convert_compressed_oops; | 
| 820 |         return PreRuntimeDispatch::atomic_cmpxchg<expanded_decorators>(new_value, addr, compare_value); | 
| 821 |       } else { | 
| 822 |         const DecoratorSet expanded_decorators = decorators & ~convert_compressed_oops; | 
| 823 |         return PreRuntimeDispatch::atomic_cmpxchg<expanded_decorators>(new_value, addr, compare_value); | 
| 824 |       } | 
| 825 |     } | 
| 826 |  | 
| 827 |     template <DecoratorSet decorators, typename T> | 
| 828 |     inline static typename EnableIf< | 
| 829 |       !HasDecorator<decorators, AS_RAW>::value, T>::type | 
| 830 |     atomic_cmpxchg(T new_value, void* addr, T compare_value) { | 
| 831 |       if (is_hardwired_primitive<decorators>()) { | 
| 832 |         const DecoratorSet expanded_decorators = decorators | AS_RAW; | 
| 833 |         return PreRuntimeDispatch::atomic_cmpxchg<expanded_decorators>(new_value, addr, compare_value); | 
| 834 |       } else { | 
| 835 |         return RuntimeDispatch<decorators, T, BARRIER_ATOMIC_CMPXCHG>::atomic_cmpxchg(new_value, addr, compare_value); | 
| 836 |       } | 
| 837 |     } | 
| 838 |  | 
| 839 |     template <DecoratorSet decorators, typename T> | 
| 840 |     inline static typename EnableIf< | 
| 841 |       HasDecorator<decorators, AS_RAW>::value, T>::type | 
| 842 |     atomic_cmpxchg_at(T new_value, oop base, ptrdiff_t offset, T compare_value) { | 
| 843 |       return atomic_cmpxchg<decorators>(new_value, field_addr(base, offset), compare_value); | 
| 844 |     } | 
| 845 |  | 
| 846 |     template <DecoratorSet decorators, typename T> | 
| 847 |     inline static typename EnableIf< | 
| 848 |       !HasDecorator<decorators, AS_RAW>::value, T>::type | 
| 849 |     atomic_cmpxchg_at(T new_value, oop base, ptrdiff_t offset, T compare_value) { | 
| 850 |       if (is_hardwired_primitive<decorators>()) { | 
| 851 |         const DecoratorSet expanded_decorators = decorators | AS_RAW; | 
| 852 |         return PreRuntimeDispatch::atomic_cmpxchg_at<expanded_decorators>(new_value, base, offset, compare_value); | 
| 853 |       } else { | 
| 854 |         return RuntimeDispatch<decorators, T, BARRIER_ATOMIC_CMPXCHG_AT>::atomic_cmpxchg_at(new_value, base, offset, compare_value); | 
| 855 |       } | 
| 856 |     } | 
| 857 |  | 
| 858 |     template <DecoratorSet decorators, typename T> | 
| 859 |     inline static typename EnableIf< | 
| 860 |       HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value, T>::type | 
| 861 |     atomic_xchg(T new_value, void* addr) { | 
| 862 |       typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw; | 
| 863 |       if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) { | 
| 864 |         return Raw::oop_atomic_xchg(new_value, addr); | 
| 865 |       } else { | 
| 866 |         return Raw::atomic_xchg(new_value, addr); | 
| 867 |       } | 
| 868 |     } | 
| 869 |  | 
| 870 |     template <DecoratorSet decorators, typename T> | 
| 871 |     inline static typename EnableIf< | 
| 872 |       HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value, T>::type | 
| 873 |     atomic_xchg(T new_value, void* addr) { | 
| 874 |       if (UseCompressedOops) { | 
| 875 |         const DecoratorSet expanded_decorators = decorators | convert_compressed_oops; | 
| 876 |         return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(new_value, addr); | 
| 877 |       } else { | 
| 878 |         const DecoratorSet expanded_decorators = decorators & ~convert_compressed_oops; | 
| 879 |         return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(new_value, addr); | 
| 880 |       } | 
| 881 |     } | 
| 882 |  | 
| 883 |     template <DecoratorSet decorators, typename T> | 
| 884 |     inline static typename EnableIf< | 
| 885 |       !HasDecorator<decorators, AS_RAW>::value, T>::type | 
| 886 |     atomic_xchg(T new_value, void* addr) { | 
| 887 |       if (is_hardwired_primitive<decorators>()) { | 
| 888 |         const DecoratorSet expanded_decorators = decorators | AS_RAW; | 
| 889 |         return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(new_value, addr); | 
| 890 |       } else { | 
| 891 |         return RuntimeDispatch<decorators, T, BARRIER_ATOMIC_XCHG>::atomic_xchg(new_value, addr); | 
| 892 |       } | 
| 893 |     } | 
| 894 |  | 
| 895 |     template <DecoratorSet decorators, typename T> | 
| 896 |     inline static typename EnableIf< | 
| 897 |       HasDecorator<decorators, AS_RAW>::value, T>::type | 
| 898 |     atomic_xchg_at(T new_value, oop base, ptrdiff_t offset) { | 
| 899 |       return atomic_xchg<decorators>(new_value, field_addr(base, offset)); | 
| 900 |     } | 
| 901 |  | 
| 902 |     template <DecoratorSet decorators, typename T> | 
| 903 |     inline static typename EnableIf< | 
| 904 |       !HasDecorator<decorators, AS_RAW>::value, T>::type | 
| 905 |     atomic_xchg_at(T new_value, oop base, ptrdiff_t offset) { | 
| 906 |       if (is_hardwired_primitive<decorators>()) { | 
| 907 |         const DecoratorSet expanded_decorators = decorators | AS_RAW; | 
| 908 |         return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(new_value, base, offset); | 
| 909 |       } else { | 
| 910 |         return RuntimeDispatch<decorators, T, BARRIER_ATOMIC_XCHG_AT>::atomic_xchg_at(new_value, base, offset); | 
| 911 |       } | 
| 912 |     } | 
| 913 |  | 
| 914 |     template <DecoratorSet decorators, typename T> | 
| 915 |     inline static typename EnableIf< | 
| 916 |       HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value, bool>::type | 
| 917 |     arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, | 
| 918 |               arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, | 
| 919 |               size_t length) { | 
| 920 |       typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw; | 
| 921 |       if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) { | 
| 922 |         return Raw::oop_arraycopy(src_obj, src_offset_in_bytes, src_raw, | 
| 923 |                                   dst_obj, dst_offset_in_bytes, dst_raw, | 
| 924 |                                   length); | 
| 925 |       } else { | 
| 926 |         return Raw::arraycopy(src_obj, src_offset_in_bytes, src_raw, | 
| 927 |                               dst_obj, dst_offset_in_bytes, dst_raw, | 
| 928 |                               length); | 
| 929 |       } | 
| 930 |     } | 
| 931 |  | 
| 932 |     template <DecoratorSet decorators, typename T> | 
| 933 |     inline static typename EnableIf< | 
| 934 |       HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value, bool>::type | 
| 935 |     arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, | 
| 936 |               arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, | 
| 937 |               size_t length) { | 
| 938 |       if (UseCompressedOops) { | 
| 939 |         const DecoratorSet expanded_decorators = decorators | convert_compressed_oops; | 
| 940 |         return PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw, | 
| 941 |                                                                   dst_obj, dst_offset_in_bytes, dst_raw, | 
| 942 |                                                                   length); | 
| 943 |       } else { | 
| 944 |         const DecoratorSet expanded_decorators = decorators & ~convert_compressed_oops; | 
| 945 |         return PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw, | 
| 946 |                                                                   dst_obj, dst_offset_in_bytes, dst_raw, | 
| 947 |                                                                   length); | 
| 948 |       } | 
| 949 |     } | 
| 950 |  | 
| 951 |     template <DecoratorSet decorators, typename T> | 
| 952 |     inline static typename EnableIf< | 
| 953 |       !HasDecorator<decorators, AS_RAW>::value, bool>::type | 
| 954 |     arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, | 
| 955 |               arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, | 
| 956 |               size_t length) { | 
| 957 |       if (is_hardwired_primitive<decorators>()) { | 
| 958 |         const DecoratorSet expanded_decorators = decorators | AS_RAW; | 
| 959 |         return PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw, | 
| 960 |                                                                   dst_obj, dst_offset_in_bytes, dst_raw, | 
| 961 |                                                                   length); | 
| 962 |       } else { | 
| 963 |         return RuntimeDispatch<decorators, T, BARRIER_ARRAYCOPY>::arraycopy(src_obj, src_offset_in_bytes, src_raw, | 
| 964 |                                                                             dst_obj, dst_offset_in_bytes, dst_raw, | 
| 965 |                                                                             length); | 
| 966 |       } | 
| 967 |     } | 
| 968 |  | 
| 969 |     template <DecoratorSet decorators> | 
| 970 |     inline static typename EnableIf< | 
| 971 |       HasDecorator<decorators, AS_RAW>::value>::type | 
| 972 |     clone(oop src, oop dst, size_t size) { | 
| 973 |       typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw; | 
| 974 |       Raw::clone(src, dst, size); | 
| 975 |     } | 
| 976 |  | 
| 977 |     template <DecoratorSet decorators> | 
| 978 |     inline static typename EnableIf< | 
| 979 |       !HasDecorator<decorators, AS_RAW>::value>::type | 
| 980 |     clone(oop src, oop dst, size_t size) { | 
| 981 |       RuntimeDispatch<decorators, oop, BARRIER_CLONE>::clone(src, dst, size); | 
| 982 |     } | 
| 983 |  | 
| 984 |     template <DecoratorSet decorators> | 
| 985 |     inline static typename EnableIf< | 
| 986 |       HasDecorator<decorators, INTERNAL_BT_TO_SPACE_INVARIANT>::value, oop>::type | 
| 987 |     resolve(oop obj) { | 
| 988 |       typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw; | 
| 989 |       return Raw::resolve(obj); | 
| 990 |     } | 
| 991 |  | 
| 992 |     template <DecoratorSet decorators> | 
| 993 |     inline static typename EnableIf< | 
| 994 |       !HasDecorator<decorators, INTERNAL_BT_TO_SPACE_INVARIANT>::value, oop>::type | 
| 995 |     resolve(oop obj) { | 
| 996 |       return RuntimeDispatch<decorators, oop, BARRIER_RESOLVE>::resolve(obj); | 
| 997 |     } | 
| 998 |  | 
| 999 |     template <DecoratorSet decorators> | 
| 1000 |     inline static typename EnableIf< | 
| 1001 |       HasDecorator<decorators, AS_RAW>::value || HasDecorator<decorators, INTERNAL_BT_TO_SPACE_INVARIANT>::value, bool>::type | 
| 1002 |     equals(oop o1, oop o2) { | 
| 1003 |       typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw; | 
| 1004 |       return Raw::equals(o1, o2); | 
| 1005 |     } | 
| 1006 |  | 
| 1007 |     template <DecoratorSet decorators> | 
| 1008 |     inline static typename EnableIf< | 
| 1009 |       !HasDecorator<decorators, AS_RAW>::value && !HasDecorator<decorators, INTERNAL_BT_TO_SPACE_INVARIANT>::value, bool>::type | 
| 1010 |     equals(oop o1, oop o2) { | 
| 1011 |       return RuntimeDispatch<decorators, oop, BARRIER_EQUALS>::equals(o1, o2); | 
| 1012 |     } | 
| 1013 |   }; | 
| 1014 |  | 
| 1015 |   // Step 2: Reduce types. | 
| 1016 |   // Enforce that for non-oop types, T and P have to be strictly the same. | 
| 1017 |   // P is the type of the address and T is the type of the values. | 
| 1018 |   // As for oop types, it is allow to send T in {narrowOop, oop} and | 
| 1019 |   // P in {narrowOop, oop, HeapWord*}. The following rules apply according to | 
| 1020 |   // the subsequent table. (columns are P, rows are T) | 
| 1021 |   // |           | HeapWord  |   oop   | narrowOop | | 
| 1022 |   // |   oop     |  rt-comp  | hw-none |  hw-comp  | | 
| 1023 |   // | narrowOop |     x     |    x    |  hw-none  | | 
| 1024 |   // | 
| 1025 |   // x means not allowed | 
| 1026 |   // rt-comp means it must be checked at runtime whether the oop is compressed. | 
| 1027 |   // hw-none means it is statically known the oop will not be compressed. | 
| 1028 |   // hw-comp means it is statically known the oop will be compressed. | 
| 1029 |  | 
| 1030 |   template <DecoratorSet decorators, typename T> | 
| 1031 |   inline void store_reduce_types(T* addr, T value) { | 
| 1032 |     PreRuntimeDispatch::store<decorators>(addr, value); | 
| 1033 |   } | 
| 1034 |  | 
| 1035 |   template <DecoratorSet decorators> | 
| 1036 |   inline void store_reduce_types(narrowOop* addr, oop value) { | 
| 1037 |     const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP | | 
| 1038 |                                              INTERNAL_RT_USE_COMPRESSED_OOPS; | 
| 1039 |     PreRuntimeDispatch::store<expanded_decorators>(addr, value); | 
| 1040 |   } | 
| 1041 |  | 
| 1042 |   template <DecoratorSet decorators> | 
| 1043 |   inline void store_reduce_types(narrowOop* addr, narrowOop value) { | 
| 1044 |     const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP | | 
| 1045 |                                              INTERNAL_RT_USE_COMPRESSED_OOPS; | 
| 1046 |     PreRuntimeDispatch::store<expanded_decorators>(addr, value); | 
| 1047 |   } | 
| 1048 |  | 
| 1049 |   template <DecoratorSet decorators> | 
| 1050 |   inline void store_reduce_types(HeapWord* addr, oop value) { | 
| 1051 |     const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP; | 
| 1052 |     PreRuntimeDispatch::store<expanded_decorators>(addr, value); | 
| 1053 |   } | 
| 1054 |  | 
| 1055 |   template <DecoratorSet decorators, typename T> | 
| 1056 |   inline T atomic_cmpxchg_reduce_types(T new_value, T* addr, T compare_value) { | 
| 1057 |     return PreRuntimeDispatch::atomic_cmpxchg<decorators>(new_value, addr, compare_value); | 
| 1058 |   } | 
| 1059 |  | 
| 1060 |   template <DecoratorSet decorators> | 
| 1061 |   inline oop atomic_cmpxchg_reduce_types(oop new_value, narrowOop* addr, oop compare_value) { | 
| 1062 |     const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP | | 
| 1063 |                                              INTERNAL_RT_USE_COMPRESSED_OOPS; | 
| 1064 |     return PreRuntimeDispatch::atomic_cmpxchg<expanded_decorators>(new_value, addr, compare_value); | 
| 1065 |   } | 
| 1066 |  | 
| 1067 |   template <DecoratorSet decorators> | 
| 1068 |   inline narrowOop atomic_cmpxchg_reduce_types(narrowOop new_value, narrowOop* addr, narrowOop compare_value) { | 
| 1069 |     const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP | | 
| 1070 |                                              INTERNAL_RT_USE_COMPRESSED_OOPS; | 
| 1071 |     return PreRuntimeDispatch::atomic_cmpxchg<expanded_decorators>(new_value, addr, compare_value); | 
| 1072 |   } | 
| 1073 |  | 
| 1074 |   template <DecoratorSet decorators> | 
| 1075 |   inline oop atomic_cmpxchg_reduce_types(oop new_value, | 
| 1076 |                                          HeapWord* addr, | 
| 1077 |                                          oop compare_value) { | 
| 1078 |     const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP; | 
| 1079 |     return PreRuntimeDispatch::atomic_cmpxchg<expanded_decorators>(new_value, addr, compare_value); | 
| 1080 |   } | 
| 1081 |  | 
| 1082 |   template <DecoratorSet decorators, typename T> | 
| 1083 |   inline T atomic_xchg_reduce_types(T new_value, T* addr) { | 
| 1084 |     const DecoratorSet expanded_decorators = decorators; | 
| 1085 |     return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(new_value, addr); | 
| 1086 |   } | 
| 1087 |  | 
| 1088 |   template <DecoratorSet decorators> | 
| 1089 |   inline oop atomic_xchg_reduce_types(oop new_value, narrowOop* addr) { | 
| 1090 |     const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP | | 
| 1091 |                                              INTERNAL_RT_USE_COMPRESSED_OOPS; | 
| 1092 |     return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(new_value, addr); | 
| 1093 |   } | 
| 1094 |  | 
| 1095 |   template <DecoratorSet decorators> | 
| 1096 |   inline narrowOop atomic_xchg_reduce_types(narrowOop new_value, narrowOop* addr) { | 
| 1097 |     const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP | | 
| 1098 |                                              INTERNAL_RT_USE_COMPRESSED_OOPS; | 
| 1099 |     return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(new_value, addr); | 
| 1100 |   } | 
| 1101 |  | 
| 1102 |   template <DecoratorSet decorators> | 
| 1103 |   inline oop atomic_xchg_reduce_types(oop new_value, HeapWord* addr) { | 
| 1104 |     const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP; | 
| 1105 |     return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(new_value, addr); | 
| 1106 |   } | 
| 1107 |  | 
| 1108 |   template <DecoratorSet decorators, typename T> | 
| 1109 |   inline T load_reduce_types(T* addr) { | 
| 1110 |     return PreRuntimeDispatch::load<decorators, T>(addr); | 
| 1111 |   } | 
| 1112 |  | 
| 1113 |   template <DecoratorSet decorators, typename T> | 
| 1114 |   inline typename OopOrNarrowOop<T>::type load_reduce_types(narrowOop* addr) { | 
| 1115 |     const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP | | 
| 1116 |                                              INTERNAL_RT_USE_COMPRESSED_OOPS; | 
| 1117 |     return PreRuntimeDispatch::load<expanded_decorators, typename OopOrNarrowOop<T>::type>(addr); | 
| 1118 |   } | 
| 1119 |  | 
| 1120 |   template <DecoratorSet decorators, typename T> | 
| 1121 |   inline oop load_reduce_types(HeapWord* addr) { | 
| 1122 |     const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP; | 
| 1123 |     return PreRuntimeDispatch::load<expanded_decorators, oop>(addr); | 
| 1124 |   } | 
| 1125 |  | 
| 1126 |   template <DecoratorSet decorators, typename T> | 
| 1127 |   inline bool arraycopy_reduce_types(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, | 
| 1128 |                                      arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, | 
| 1129 |                                      size_t length) { | 
| 1130 |     return PreRuntimeDispatch::arraycopy<decorators>(src_obj, src_offset_in_bytes, src_raw, | 
| 1131 |                                                      dst_obj, dst_offset_in_bytes, dst_raw, | 
| 1132 |                                                      length); | 
| 1133 |   } | 
| 1134 |  | 
| 1135 |   template <DecoratorSet decorators> | 
| 1136 |   inline bool arraycopy_reduce_types(arrayOop src_obj, size_t src_offset_in_bytes, HeapWord* src_raw, | 
| 1137 |                                      arrayOop dst_obj, size_t dst_offset_in_bytes, HeapWord* dst_raw, | 
| 1138 |                                      size_t length) { | 
| 1139 |     const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP; | 
| 1140 |     return PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw, | 
| 1141 |                                                               dst_obj, dst_offset_in_bytes, dst_raw, | 
| 1142 |                                                               length); | 
| 1143 |   } | 
| 1144 |  | 
| 1145 |   template <DecoratorSet decorators> | 
| 1146 |   inline bool arraycopy_reduce_types(arrayOop src_obj, size_t src_offset_in_bytes, narrowOop* src_raw, | 
| 1147 |                                      arrayOop dst_obj, size_t dst_offset_in_bytes, narrowOop* dst_raw, | 
| 1148 |                                      size_t length) { | 
| 1149 |     const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP | | 
| 1150 |                                              INTERNAL_RT_USE_COMPRESSED_OOPS; | 
| 1151 |     return PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw, | 
| 1152 |                                                               dst_obj, dst_offset_in_bytes, dst_raw, | 
| 1153 |                                                               length); | 
| 1154 |   } | 
| 1155 |  | 
| 1156 |   // Step 1: Set default decorators. This step remembers if a type was volatile | 
| 1157 |   // and then sets the MO_VOLATILE decorator by default. Otherwise, a default | 
| 1158 |   // memory ordering is set for the access, and the implied decorator rules | 
| 1159 |   // are applied to select sensible defaults for decorators that have not been | 
| 1160 |   // explicitly set. For example, default object referent strength is set to strong. | 
| 1161 |   // This step also decays the types passed in (e.g. getting rid of CV qualifiers | 
| 1162 |   // and references from the types). This step also perform some type verification | 
| 1163 |   // that the passed in types make sense. | 
| 1164 |  | 
| 1165 |   template <DecoratorSet decorators, typename T> | 
| 1166 |   static void verify_types(){ | 
| 1167 |     // If this fails to compile, then you have sent in something that is | 
| 1168 |     // not recognized as a valid primitive type to a primitive Access function. | 
| 1169 |     STATIC_ASSERT((HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value || // oops have already been validated | 
| 1170 |                    (IsPointer<T>::value || IsIntegral<T>::value) || | 
| 1171 |                     IsFloatingPoint<T>::value)); // not allowed primitive type | 
| 1172 |   } | 
| 1173 |  | 
| 1174 |   template <DecoratorSet decorators, typename P, typename T> | 
| 1175 |   inline void store(P* addr, T value) { | 
| 1176 |     verify_types<decorators, T>(); | 
| 1177 |     typedef typename Decay<P>::type DecayedP; | 
| 1178 |     typedef typename Decay<T>::type DecayedT; | 
| 1179 |     DecayedT decayed_value = value; | 
| 1180 |     // If a volatile address is passed in but no memory ordering decorator, | 
| 1181 |     // set the memory ordering to MO_VOLATILE by default. | 
| 1182 |     const DecoratorSet expanded_decorators = DecoratorFixup< | 
| 1183 |       (IsVolatile<P>::value && !HasDecorator<decorators, MO_DECORATOR_MASK>::value) ? | 
| 1184 |       (MO_VOLATILE | decorators) : decorators>::value; | 
| 1185 |     store_reduce_types<expanded_decorators>(const_cast<DecayedP*>(addr), decayed_value); | 
| 1186 |   } | 
| 1187 |  | 
| 1188 |   template <DecoratorSet decorators, typename T> | 
| 1189 |   inline void store_at(oop base, ptrdiff_t offset, T value) { | 
| 1190 |     verify_types<decorators, T>(); | 
| 1191 |     typedef typename Decay<T>::type DecayedT; | 
| 1192 |     DecayedT decayed_value = value; | 
| 1193 |     const DecoratorSet expanded_decorators = DecoratorFixup<decorators | | 
| 1194 |                                              (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value ? | 
| 1195 |                                               INTERNAL_CONVERT_COMPRESSED_OOP : DECORATORS_NONE)>::value; | 
| 1196 |     PreRuntimeDispatch::store_at<expanded_decorators>(base, offset, decayed_value); | 
| 1197 |   } | 
| 1198 |  | 
| 1199 |   template <DecoratorSet decorators, typename P, typename T> | 
| 1200 |   inline T load(P* addr) { | 
| 1201 |     verify_types<decorators, T>(); | 
| 1202 |     typedef typename Decay<P>::type DecayedP; | 
| 1203 |     typedef typename Conditional<HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value, | 
| 1204 |                                  typename OopOrNarrowOop<T>::type, | 
| 1205 |                                  typename Decay<T>::type>::type DecayedT; | 
| 1206 |     // If a volatile address is passed in but no memory ordering decorator, | 
| 1207 |     // set the memory ordering to MO_VOLATILE by default. | 
| 1208 |     const DecoratorSet expanded_decorators = DecoratorFixup< | 
| 1209 |       (IsVolatile<P>::value && !HasDecorator<decorators, MO_DECORATOR_MASK>::value) ? | 
| 1210 |       (MO_VOLATILE | decorators) : decorators>::value; | 
| 1211 |     return load_reduce_types<expanded_decorators, DecayedT>(const_cast<DecayedP*>(addr)); | 
| 1212 |   } | 
| 1213 |  | 
| 1214 |   template <DecoratorSet decorators, typename T> | 
| 1215 |   inline T load_at(oop base, ptrdiff_t offset) { | 
| 1216 |     verify_types<decorators, T>(); | 
| 1217 |     typedef typename Conditional<HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value, | 
| 1218 |                                  typename OopOrNarrowOop<T>::type, | 
| 1219 |                                  typename Decay<T>::type>::type DecayedT; | 
| 1220 |     // Expand the decorators (figure out sensible defaults) | 
| 1221 |     // Potentially remember if we need compressed oop awareness | 
| 1222 |     const DecoratorSet expanded_decorators = DecoratorFixup<decorators | | 
| 1223 |                                              (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value ? | 
| 1224 |                                               INTERNAL_CONVERT_COMPRESSED_OOP : DECORATORS_NONE)>::value; | 
| 1225 |     return PreRuntimeDispatch::load_at<expanded_decorators, DecayedT>(base, offset); | 
| 1226 |   } | 
| 1227 |  | 
| 1228 |   template <DecoratorSet decorators, typename P, typename T> | 
| 1229 |   inline T atomic_cmpxchg(T new_value, P* addr, T compare_value) { | 
| 1230 |     verify_types<decorators, T>(); | 
| 1231 |     typedef typename Decay<P>::type DecayedP; | 
| 1232 |     typedef typename Decay<T>::type DecayedT; | 
| 1233 |     DecayedT new_decayed_value = new_value; | 
| 1234 |     DecayedT compare_decayed_value = compare_value; | 
| 1235 |     const DecoratorSet expanded_decorators = DecoratorFixup< | 
| 1236 |       (!HasDecorator<decorators, MO_DECORATOR_MASK>::value) ? | 
| 1237 |       (MO_SEQ_CST | decorators) : decorators>::value; | 
| 1238 |     return atomic_cmpxchg_reduce_types<expanded_decorators>(new_decayed_value, | 
| 1239 |                                                             const_cast<DecayedP*>(addr), | 
| 1240 |                                                             compare_decayed_value); | 
| 1241 |   } | 
| 1242 |  | 
| 1243 |   template <DecoratorSet decorators, typename T> | 
| 1244 |   inline T atomic_cmpxchg_at(T new_value, oop base, ptrdiff_t offset, T compare_value) { | 
| 1245 |     verify_types<decorators, T>(); | 
| 1246 |     typedef typename Decay<T>::type DecayedT; | 
| 1247 |     DecayedT new_decayed_value = new_value; | 
| 1248 |     DecayedT compare_decayed_value = compare_value; | 
| 1249 |     // Determine default memory ordering | 
| 1250 |     const DecoratorSet expanded_decorators = DecoratorFixup< | 
| 1251 |       (!HasDecorator<decorators, MO_DECORATOR_MASK>::value) ? | 
| 1252 |       (MO_SEQ_CST | decorators) : decorators>::value; | 
| 1253 |     // Potentially remember that we need compressed oop awareness | 
| 1254 |     const DecoratorSet final_decorators = expanded_decorators | | 
| 1255 |                                           (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value ? | 
| 1256 |                                            INTERNAL_CONVERT_COMPRESSED_OOP : DECORATORS_NONE); | 
| 1257 |     return PreRuntimeDispatch::atomic_cmpxchg_at<final_decorators>(new_decayed_value, base, | 
| 1258 |                                                                    offset, compare_decayed_value); | 
| 1259 |   } | 
| 1260 |  | 
| 1261 |   template <DecoratorSet decorators, typename P, typename T> | 
| 1262 |   inline T atomic_xchg(T new_value, P* addr) { | 
| 1263 |     verify_types<decorators, T>(); | 
| 1264 |     typedef typename Decay<P>::type DecayedP; | 
| 1265 |     typedef typename Decay<T>::type DecayedT; | 
| 1266 |     DecayedT new_decayed_value = new_value; | 
| 1267 |     // atomic_xchg is only available in SEQ_CST flavour. | 
| 1268 |     const DecoratorSet expanded_decorators = DecoratorFixup<decorators | MO_SEQ_CST>::value; | 
| 1269 |     return atomic_xchg_reduce_types<expanded_decorators>(new_decayed_value, | 
| 1270 |                                                          const_cast<DecayedP*>(addr)); | 
| 1271 |   } | 
| 1272 |  | 
| 1273 |   template <DecoratorSet decorators, typename T> | 
| 1274 |   inline T atomic_xchg_at(T new_value, oop base, ptrdiff_t offset) { | 
| 1275 |     verify_types<decorators, T>(); | 
| 1276 |     typedef typename Decay<T>::type DecayedT; | 
| 1277 |     DecayedT new_decayed_value = new_value; | 
| 1278 |     // atomic_xchg is only available in SEQ_CST flavour. | 
| 1279 |     const DecoratorSet expanded_decorators = DecoratorFixup<decorators | MO_SEQ_CST | | 
| 1280 |                                              (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value ? | 
| 1281 |                                               INTERNAL_CONVERT_COMPRESSED_OOP : DECORATORS_NONE)>::value; | 
| 1282 |     return PreRuntimeDispatch::atomic_xchg_at<expanded_decorators>(new_decayed_value, base, offset); | 
| 1283 |   } | 
| 1284 |  | 
| 1285 |   template <DecoratorSet decorators, typename T> | 
| 1286 |   inline bool arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, const T* src_raw, | 
| 1287 |                         arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, | 
| 1288 |                         size_t length) { | 
| 1289 |     STATIC_ASSERT((HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value || | 
| 1290 |                    (IsSame<T, void>::value || IsIntegral<T>::value) || | 
| 1291 |                     IsFloatingPoint<T>::value)); // arraycopy allows type erased void elements | 
| 1292 |     typedef typename Decay<T>::type DecayedT; | 
| 1293 |     const DecoratorSet expanded_decorators = DecoratorFixup<decorators | IS_ARRAY | IN_HEAP>::value; | 
| 1294 |     return arraycopy_reduce_types<expanded_decorators>(src_obj, src_offset_in_bytes, const_cast<DecayedT*>(src_raw), | 
| 1295 |                                                        dst_obj, dst_offset_in_bytes, const_cast<DecayedT*>(dst_raw), | 
| 1296 |                                                        length); | 
| 1297 |   } | 
| 1298 |  | 
| 1299 |   template <DecoratorSet decorators> | 
| 1300 |   inline void clone(oop src, oop dst, size_t size) { | 
| 1301 |     const DecoratorSet expanded_decorators = DecoratorFixup<decorators>::value; | 
| 1302 |     PreRuntimeDispatch::clone<expanded_decorators>(src, dst, size); | 
| 1303 |   } | 
| 1304 |  | 
| 1305 |   template <DecoratorSet decorators> | 
| 1306 |   inline oop resolve(oop obj) { | 
| 1307 |     const DecoratorSet expanded_decorators = DecoratorFixup<decorators>::value; | 
| 1308 |     return PreRuntimeDispatch::resolve<expanded_decorators>(obj); | 
| 1309 |   } | 
| 1310 |  | 
| 1311 |   template <DecoratorSet decorators> | 
| 1312 |   inline bool equals(oop o1, oop o2) { | 
| 1313 |     const DecoratorSet expanded_decorators = DecoratorFixup<decorators>::value; | 
| 1314 |     return PreRuntimeDispatch::equals<expanded_decorators>(o1, o2); | 
| 1315 |   } | 
| 1316 |  | 
| 1317 |   // Infer the type that should be returned from an Access::oop_load. | 
| 1318 |   template <typename P, DecoratorSet decorators> | 
| 1319 |   class OopLoadProxy: public StackObj { | 
| 1320 |   private: | 
| 1321 |     P *const _addr; | 
| 1322 |   public: | 
| 1323 |     OopLoadProxy(P* addr) : _addr(addr) {} | 
| 1324 |  | 
| 1325 |     inline operator oop() { | 
| 1326 |       return load<decorators | INTERNAL_VALUE_IS_OOP, P, oop>(_addr); | 
| 1327 |     } | 
| 1328 |  | 
| 1329 |     inline operator narrowOop() { | 
| 1330 |       return load<decorators | INTERNAL_VALUE_IS_OOP, P, narrowOop>(_addr); | 
| 1331 |     } | 
| 1332 |  | 
| 1333 |     template <typename T> | 
| 1334 |     inline bool operator ==(const T& other) const { | 
| 1335 |       return load<decorators | INTERNAL_VALUE_IS_OOP, P, T>(_addr) == other; | 
| 1336 |     } | 
| 1337 |  | 
| 1338 |     template <typename T> | 
| 1339 |     inline bool operator !=(const T& other) const { | 
| 1340 |       return load<decorators | INTERNAL_VALUE_IS_OOP, P, T>(_addr) != other; | 
| 1341 |     } | 
| 1342 |   }; | 
| 1343 |  | 
| 1344 |   // Infer the type that should be returned from an Access::load_at. | 
| 1345 |   template <DecoratorSet decorators> | 
| 1346 |   class LoadAtProxy: public StackObj { | 
| 1347 |   private: | 
| 1348 |     const oop _base; | 
| 1349 |     const ptrdiff_t _offset; | 
| 1350 |   public: | 
| 1351 |     LoadAtProxy(oop base, ptrdiff_t offset) : _base(base), _offset(offset) {} | 
| 1352 |  | 
| 1353 |     template <typename T> | 
| 1354 |     inline operator T() const { | 
| 1355 |       return load_at<decorators, T>(_base, _offset); | 
| 1356 |     } | 
| 1357 |  | 
| 1358 |     template <typename T> | 
| 1359 |     inline bool operator ==(const T& other) const { return load_at<decorators, T>(_base, _offset) == other; } | 
| 1360 |  | 
| 1361 |     template <typename T> | 
| 1362 |     inline bool operator !=(const T& other) const { return load_at<decorators, T>(_base, _offset) != other; } | 
| 1363 |   }; | 
| 1364 |  | 
| 1365 |   // Infer the type that should be returned from an Access::oop_load_at. | 
| 1366 |   template <DecoratorSet decorators> | 
| 1367 |   class OopLoadAtProxy: public StackObj { | 
| 1368 |   private: | 
| 1369 |     const oop _base; | 
| 1370 |     const ptrdiff_t _offset; | 
| 1371 |   public: | 
| 1372 |     OopLoadAtProxy(oop base, ptrdiff_t offset) : _base(base), _offset(offset) {} | 
| 1373 |  | 
| 1374 |     inline operator oop() const { | 
| 1375 |       return load_at<decorators | INTERNAL_VALUE_IS_OOP, oop>(_base, _offset); | 
| 1376 |     } | 
| 1377 |  | 
| 1378 |     inline operator narrowOop() const { | 
| 1379 |       return load_at<decorators | INTERNAL_VALUE_IS_OOP, narrowOop>(_base, _offset); | 
| 1380 |     } | 
| 1381 |  | 
| 1382 |     template <typename T> | 
| 1383 |     inline bool operator ==(const T& other) const { | 
| 1384 |       return load_at<decorators | INTERNAL_VALUE_IS_OOP, T>(_base, _offset) == other; | 
| 1385 |     } | 
| 1386 |  | 
| 1387 |     template <typename T> | 
| 1388 |     inline bool operator !=(const T& other) const { | 
| 1389 |       return load_at<decorators | INTERNAL_VALUE_IS_OOP, T>(_base, _offset) != other; | 
| 1390 |     } | 
| 1391 |   }; | 
| 1392 | } | 
| 1393 |  | 
| 1394 | #endif // SHARE_OOPS_ACCESSBACKEND_HPP | 
| 1395 |  |