Path: blob/master/src/hotspot/share/oops/accessBackend.hpp
40951 views
/*1* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_OOPS_ACCESSBACKEND_HPP25#define SHARE_OOPS_ACCESSBACKEND_HPP2627#include "gc/shared/barrierSetConfig.hpp"28#include "memory/allocation.hpp"29#include "metaprogramming/conditional.hpp"30#include "metaprogramming/decay.hpp"31#include "metaprogramming/enableIf.hpp"32#include "metaprogramming/integralConstant.hpp"33#include "metaprogramming/isFloatingPoint.hpp"34#include "metaprogramming/isIntegral.hpp"35#include "metaprogramming/isPointer.hpp"36#include "metaprogramming/isSame.hpp"37#include "metaprogramming/isVolatile.hpp"38#include "oops/accessDecorators.hpp"39#include "oops/oopsHierarchy.hpp"40#include "runtime/globals.hpp"41#include "utilities/debug.hpp"42#include "utilities/globalDefinitions.hpp"434445// This metafunction returns either oop or narrowOop depending on whether46// an access needs to use compressed oops or not.47template <DecoratorSet decorators>48struct HeapOopType: AllStatic {49static const bool needs_oop_compress = HasDecorator<decorators, INTERNAL_CONVERT_COMPRESSED_OOP>::value &&50HasDecorator<decorators, INTERNAL_RT_USE_COMPRESSED_OOPS>::value;51typedef typename Conditional<needs_oop_compress, narrowOop, oop>::type type;52};5354namespace AccessInternal {55enum BarrierType {56BARRIER_STORE,57BARRIER_STORE_AT,58BARRIER_LOAD,59BARRIER_LOAD_AT,60BARRIER_ATOMIC_CMPXCHG,61BARRIER_ATOMIC_CMPXCHG_AT,62BARRIER_ATOMIC_XCHG,63BARRIER_ATOMIC_XCHG_AT,64BARRIER_ARRAYCOPY,65BARRIER_CLONE,66BARRIER_RESOLVE67};6869template <DecoratorSet decorators, typename T>70struct MustConvertCompressedOop: public IntegralConstant<bool,71HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value &&72IsSame<typename HeapOopType<decorators>::type, narrowOop>::value &&73IsSame<T, oop>::value> {};7475// This metafunction returns an appropriate oop type if the value is oop-like76// and otherwise returns the same type T.77template <DecoratorSet decorators, typename T>78struct EncodedType: AllStatic {79typedef typename Conditional<80HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value,81typename HeapOopType<decorators>::type, T>::type type;82};8384template <DecoratorSet decorators>85inline typename HeapOopType<decorators>::type*86oop_field_addr(oop base, ptrdiff_t byte_offset) {87return reinterpret_cast<typename HeapOopType<decorators>::type*>(88reinterpret_cast<intptr_t>((void*)base) + byte_offset);89}9091// This metafunction returns whether it is possible for a type T to require92// locking to support wide atomics or not.93template <typename T>94#ifdef SUPPORTS_NATIVE_CX895struct PossiblyLockedAccess: public IntegralConstant<bool, false> {};96#else97struct PossiblyLockedAccess: public IntegralConstant<bool, (sizeof(T) > 4)> {};98#endif99100template <DecoratorSet decorators, typename T>101struct AccessFunctionTypes {102typedef T (*load_at_func_t)(oop base, ptrdiff_t offset);103typedef void (*store_at_func_t)(oop base, ptrdiff_t offset, T value);104typedef T (*atomic_cmpxchg_at_func_t)(oop base, ptrdiff_t offset, T compare_value, T new_value);105typedef T (*atomic_xchg_at_func_t)(oop base, ptrdiff_t offset, T new_value);106107typedef T (*load_func_t)(void* addr);108typedef void (*store_func_t)(void* addr, T value);109typedef T (*atomic_cmpxchg_func_t)(void* addr, T compare_value, T new_value);110typedef T (*atomic_xchg_func_t)(void* addr, T new_value);111112typedef bool (*arraycopy_func_t)(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,113arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,114size_t length);115typedef void (*clone_func_t)(oop src, oop dst, size_t size);116typedef oop (*resolve_func_t)(oop obj);117};118119template <DecoratorSet decorators>120struct AccessFunctionTypes<decorators, void> {121typedef bool (*arraycopy_func_t)(arrayOop src_obj, size_t src_offset_in_bytes, void* src,122arrayOop dst_obj, size_t dst_offset_in_bytes, void* dst,123size_t length);124};125126template <DecoratorSet decorators, typename T, BarrierType barrier> struct AccessFunction {};127128#define ACCESS_GENERATE_ACCESS_FUNCTION(bt, func) \129template <DecoratorSet decorators, typename T> \130struct AccessFunction<decorators, T, bt>: AllStatic{ \131typedef typename AccessFunctionTypes<decorators, T>::func type; \132}133ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_STORE, store_func_t);134ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_STORE_AT, store_at_func_t);135ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_LOAD, load_func_t);136ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_LOAD_AT, load_at_func_t);137ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_ATOMIC_CMPXCHG, atomic_cmpxchg_func_t);138ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_ATOMIC_CMPXCHG_AT, atomic_cmpxchg_at_func_t);139ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_ATOMIC_XCHG, atomic_xchg_func_t);140ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_ATOMIC_XCHG_AT, atomic_xchg_at_func_t);141ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_ARRAYCOPY, arraycopy_func_t);142ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_CLONE, clone_func_t);143ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_RESOLVE, resolve_func_t);144#undef ACCESS_GENERATE_ACCESS_FUNCTION145146template <DecoratorSet decorators, typename T, BarrierType barrier_type>147typename AccessFunction<decorators, T, barrier_type>::type resolve_barrier();148149template <DecoratorSet decorators, typename T, BarrierType barrier_type>150typename AccessFunction<decorators, T, barrier_type>::type resolve_oop_barrier();151152class AccessLocker {153public:154AccessLocker();155~AccessLocker();156};157bool wide_atomic_needs_locking();158159void* field_addr(oop base, ptrdiff_t offset);160161// Forward calls to Copy:: in the cpp file to reduce dependencies and allow162// faster build times, given how frequently included access is.163void arraycopy_arrayof_conjoint_oops(void* src, void* dst, size_t length);164void arraycopy_conjoint_oops(oop* src, oop* dst, size_t length);165void arraycopy_conjoint_oops(narrowOop* src, narrowOop* dst, size_t length);166167void arraycopy_disjoint_words(void* src, void* dst, size_t length);168void arraycopy_disjoint_words_atomic(void* src, void* dst, size_t length);169170template<typename T>171void arraycopy_conjoint(T* src, T* dst, size_t length);172template<typename T>173void arraycopy_arrayof_conjoint(T* src, T* dst, size_t length);174template<typename T>175void arraycopy_conjoint_atomic(T* src, T* dst, size_t length);176}177178// This mask specifies what decorators are relevant for raw accesses. When passing179// accesses to the raw layer, irrelevant decorators are removed.180const DecoratorSet RAW_DECORATOR_MASK = INTERNAL_DECORATOR_MASK | MO_DECORATOR_MASK |181ARRAYCOPY_DECORATOR_MASK | IS_NOT_NULL;182183// The RawAccessBarrier performs raw accesses with additional knowledge of184// memory ordering, so that OrderAccess/Atomic is called when necessary.185// It additionally handles compressed oops, and hence is not completely "raw"186// strictly speaking.187template <DecoratorSet decorators>188class RawAccessBarrier: public AllStatic {189protected:190static inline void* field_addr(oop base, ptrdiff_t byte_offset) {191return AccessInternal::field_addr(base, byte_offset);192}193194protected:195// Only encode if INTERNAL_VALUE_IS_OOP196template <DecoratorSet idecorators, typename T>197static inline typename EnableIf<198AccessInternal::MustConvertCompressedOop<idecorators, T>::value,199typename HeapOopType<idecorators>::type>::type200encode_internal(T value);201202template <DecoratorSet idecorators, typename T>203static inline typename EnableIf<204!AccessInternal::MustConvertCompressedOop<idecorators, T>::value, T>::type205encode_internal(T value) {206return value;207}208209template <typename T>210static inline typename AccessInternal::EncodedType<decorators, T>::type211encode(T value) {212return encode_internal<decorators, T>(value);213}214215// Only decode if INTERNAL_VALUE_IS_OOP216template <DecoratorSet idecorators, typename T>217static inline typename EnableIf<218AccessInternal::MustConvertCompressedOop<idecorators, T>::value, T>::type219decode_internal(typename HeapOopType<idecorators>::type value);220221template <DecoratorSet idecorators, typename T>222static inline typename EnableIf<223!AccessInternal::MustConvertCompressedOop<idecorators, T>::value, T>::type224decode_internal(T value) {225return value;226}227228template <typename T>229static inline T decode(typename AccessInternal::EncodedType<decorators, T>::type value) {230return decode_internal<decorators, T>(value);231}232233protected:234template <DecoratorSet ds, typename T>235static typename EnableIf<236HasDecorator<ds, MO_SEQ_CST>::value, T>::type237load_internal(void* addr);238239template <DecoratorSet ds, typename T>240static typename EnableIf<241HasDecorator<ds, MO_ACQUIRE>::value, T>::type242load_internal(void* addr);243244template <DecoratorSet ds, typename T>245static typename EnableIf<246HasDecorator<ds, MO_RELAXED>::value, T>::type247load_internal(void* addr);248249template <DecoratorSet ds, typename T>250static inline typename EnableIf<251HasDecorator<ds, MO_UNORDERED>::value, T>::type252load_internal(void* addr) {253return *reinterpret_cast<T*>(addr);254}255256template <DecoratorSet ds, typename T>257static typename EnableIf<258HasDecorator<ds, MO_SEQ_CST>::value>::type259store_internal(void* addr, T value);260261template <DecoratorSet ds, typename T>262static typename EnableIf<263HasDecorator<ds, MO_RELEASE>::value>::type264store_internal(void* addr, T value);265266template <DecoratorSet ds, typename T>267static typename EnableIf<268HasDecorator<ds, MO_RELAXED>::value>::type269store_internal(void* addr, T value);270271template <DecoratorSet ds, typename T>272static inline typename EnableIf<273HasDecorator<ds, MO_UNORDERED>::value>::type274store_internal(void* addr, T value) {275*reinterpret_cast<T*>(addr) = value;276}277278template <DecoratorSet ds, typename T>279static typename EnableIf<280HasDecorator<ds, MO_SEQ_CST>::value, T>::type281atomic_cmpxchg_internal(void* addr, T compare_value, T new_value);282283template <DecoratorSet ds, typename T>284static typename EnableIf<285HasDecorator<ds, MO_RELAXED>::value, T>::type286atomic_cmpxchg_internal(void* addr, T compare_value, T new_value);287288template <DecoratorSet ds, typename T>289static typename EnableIf<290HasDecorator<ds, MO_SEQ_CST>::value, T>::type291atomic_xchg_internal(void* addr, T new_value);292293// The following *_locked mechanisms serve the purpose of handling atomic operations294// that are larger than a machine can handle, and then possibly opt for using295// a slower path using a mutex to perform the operation.296297template <DecoratorSet ds, typename T>298static inline typename EnableIf<299!AccessInternal::PossiblyLockedAccess<T>::value, T>::type300atomic_cmpxchg_maybe_locked(void* addr, T compare_value, T new_value) {301return atomic_cmpxchg_internal<ds>(addr, compare_value, new_value);302}303304template <DecoratorSet ds, typename T>305static typename EnableIf<306AccessInternal::PossiblyLockedAccess<T>::value, T>::type307atomic_cmpxchg_maybe_locked(void* addr, T compare_value, T new_value);308309template <DecoratorSet ds, typename T>310static inline typename EnableIf<311!AccessInternal::PossiblyLockedAccess<T>::value, T>::type312atomic_xchg_maybe_locked(void* addr, T new_value) {313return atomic_xchg_internal<ds>(addr, new_value);314}315316template <DecoratorSet ds, typename T>317static typename EnableIf<318AccessInternal::PossiblyLockedAccess<T>::value, T>::type319atomic_xchg_maybe_locked(void* addr, T new_value);320321public:322template <typename T>323static inline void store(void* addr, T value) {324store_internal<decorators>(addr, value);325}326327template <typename T>328static inline T load(void* addr) {329return load_internal<decorators, T>(addr);330}331332template <typename T>333static inline T atomic_cmpxchg(void* addr, T compare_value, T new_value) {334return atomic_cmpxchg_maybe_locked<decorators>(addr, compare_value, new_value);335}336337template <typename T>338static inline T atomic_xchg(void* addr, T new_value) {339return atomic_xchg_maybe_locked<decorators>(addr, new_value);340}341342template <typename T>343static bool arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,344arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,345size_t length);346347template <typename T>348static void oop_store(void* addr, T value);349template <typename T>350static void oop_store_at(oop base, ptrdiff_t offset, T value);351352template <typename T>353static T oop_load(void* addr);354template <typename T>355static T oop_load_at(oop base, ptrdiff_t offset);356357template <typename T>358static T oop_atomic_cmpxchg(void* addr, T compare_value, T new_value);359template <typename T>360static T oop_atomic_cmpxchg_at(oop base, ptrdiff_t offset, T compare_value, T new_value);361362template <typename T>363static T oop_atomic_xchg(void* addr, T new_value);364template <typename T>365static T oop_atomic_xchg_at(oop base, ptrdiff_t offset, T new_value);366367template <typename T>368static void store_at(oop base, ptrdiff_t offset, T value) {369store(field_addr(base, offset), value);370}371372template <typename T>373static T load_at(oop base, ptrdiff_t offset) {374return load<T>(field_addr(base, offset));375}376377template <typename T>378static T atomic_cmpxchg_at(oop base, ptrdiff_t offset, T compare_value, T new_value) {379return atomic_cmpxchg(field_addr(base, offset), compare_value, new_value);380}381382template <typename T>383static T atomic_xchg_at(oop base, ptrdiff_t offset, T new_value) {384return atomic_xchg(field_addr(base, offset), new_value);385}386387template <typename T>388static bool oop_arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,389arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,390size_t length);391392static void clone(oop src, oop dst, size_t size);393394static oop resolve(oop obj) { return obj; }395};396397// Below is the implementation of the first 4 steps of the template pipeline:398// * Step 1: Set default decorators and decay types. This step gets rid of CV qualifiers399// and sets default decorators to sensible values.400// * Step 2: Reduce types. This step makes sure there is only a single T type and not401// multiple types. The P type of the address and T type of the value must402// match.403// * Step 3: Pre-runtime dispatch. This step checks whether a runtime call can be404// avoided, and in that case avoids it (calling raw accesses or405// primitive accesses in a build that does not require primitive GC barriers)406// * Step 4: Runtime-dispatch. This step performs a runtime dispatch to the corresponding407// BarrierSet::AccessBarrier accessor that attaches GC-required barriers408// to the access.409410namespace AccessInternal {411template <typename T>412struct OopOrNarrowOopInternal: AllStatic {413typedef oop type;414};415416template <>417struct OopOrNarrowOopInternal<narrowOop>: AllStatic {418typedef narrowOop type;419};420421// This metafunction returns a canonicalized oop/narrowOop type for a passed422// in oop-like types passed in from oop_* overloads where the user has sworn423// that the passed in values should be oop-like (e.g. oop, oopDesc*, arrayOop,424// narrowOoop, instanceOopDesc*, and random other things).425// In the oop_* overloads, it must hold that if the passed in type T is not426// narrowOop, then it by contract has to be one of many oop-like types implicitly427// convertible to oop, and hence returns oop as the canonical oop type.428// If it turns out it was not, then the implicit conversion to oop will fail429// to compile, as desired.430template <typename T>431struct OopOrNarrowOop: AllStatic {432typedef typename OopOrNarrowOopInternal<typename Decay<T>::type>::type type;433};434435inline void* field_addr(oop base, ptrdiff_t byte_offset) {436return reinterpret_cast<void*>(reinterpret_cast<intptr_t>((void*)base) + byte_offset);437}438// Step 4: Runtime dispatch439// The RuntimeDispatch class is responsible for performing a runtime dispatch of the440// accessor. This is required when the access either depends on whether compressed oops441// is being used, or it depends on which GC implementation was chosen (e.g. requires GC442// barriers). The way it works is that a function pointer initially pointing to an443// accessor resolution function gets called for each access. Upon first invocation,444// it resolves which accessor to be used in future invocations and patches the445// function pointer to this new accessor.446447template <DecoratorSet decorators, typename T, BarrierType type>448struct RuntimeDispatch: AllStatic {};449450template <DecoratorSet decorators, typename T>451struct RuntimeDispatch<decorators, T, BARRIER_STORE>: AllStatic {452typedef typename AccessFunction<decorators, T, BARRIER_STORE>::type func_t;453static func_t _store_func;454455static void store_init(void* addr, T value);456457static inline void store(void* addr, T value) {458_store_func(addr, value);459}460};461462template <DecoratorSet decorators, typename T>463struct RuntimeDispatch<decorators, T, BARRIER_STORE_AT>: AllStatic {464typedef typename AccessFunction<decorators, T, BARRIER_STORE_AT>::type func_t;465static func_t _store_at_func;466467static void store_at_init(oop base, ptrdiff_t offset, T value);468469static inline void store_at(oop base, ptrdiff_t offset, T value) {470_store_at_func(base, offset, value);471}472};473474template <DecoratorSet decorators, typename T>475struct RuntimeDispatch<decorators, T, BARRIER_LOAD>: AllStatic {476typedef typename AccessFunction<decorators, T, BARRIER_LOAD>::type func_t;477static func_t _load_func;478479static T load_init(void* addr);480481static inline T load(void* addr) {482return _load_func(addr);483}484};485486template <DecoratorSet decorators, typename T>487struct RuntimeDispatch<decorators, T, BARRIER_LOAD_AT>: AllStatic {488typedef typename AccessFunction<decorators, T, BARRIER_LOAD_AT>::type func_t;489static func_t _load_at_func;490491static T load_at_init(oop base, ptrdiff_t offset);492493static inline T load_at(oop base, ptrdiff_t offset) {494return _load_at_func(base, offset);495}496};497498template <DecoratorSet decorators, typename T>499struct RuntimeDispatch<decorators, T, BARRIER_ATOMIC_CMPXCHG>: AllStatic {500typedef typename AccessFunction<decorators, T, BARRIER_ATOMIC_CMPXCHG>::type func_t;501static func_t _atomic_cmpxchg_func;502503static T atomic_cmpxchg_init(void* addr, T compare_value, T new_value);504505static inline T atomic_cmpxchg(void* addr, T compare_value, T new_value) {506return _atomic_cmpxchg_func(addr, compare_value, new_value);507}508};509510template <DecoratorSet decorators, typename T>511struct RuntimeDispatch<decorators, T, BARRIER_ATOMIC_CMPXCHG_AT>: AllStatic {512typedef typename AccessFunction<decorators, T, BARRIER_ATOMIC_CMPXCHG_AT>::type func_t;513static func_t _atomic_cmpxchg_at_func;514515static T atomic_cmpxchg_at_init(oop base, ptrdiff_t offset, T compare_value, T new_value);516517static inline T atomic_cmpxchg_at(oop base, ptrdiff_t offset, T compare_value, T new_value) {518return _atomic_cmpxchg_at_func(base, offset, compare_value, new_value);519}520};521522template <DecoratorSet decorators, typename T>523struct RuntimeDispatch<decorators, T, BARRIER_ATOMIC_XCHG>: AllStatic {524typedef typename AccessFunction<decorators, T, BARRIER_ATOMIC_XCHG>::type func_t;525static func_t _atomic_xchg_func;526527static T atomic_xchg_init(void* addr, T new_value);528529static inline T atomic_xchg(void* addr, T new_value) {530return _atomic_xchg_func(addr, new_value);531}532};533534template <DecoratorSet decorators, typename T>535struct RuntimeDispatch<decorators, T, BARRIER_ATOMIC_XCHG_AT>: AllStatic {536typedef typename AccessFunction<decorators, T, BARRIER_ATOMIC_XCHG_AT>::type func_t;537static func_t _atomic_xchg_at_func;538539static T atomic_xchg_at_init(oop base, ptrdiff_t offset, T new_value);540541static inline T atomic_xchg_at(oop base, ptrdiff_t offset, T new_value) {542return _atomic_xchg_at_func(base, offset, new_value);543}544};545546template <DecoratorSet decorators, typename T>547struct RuntimeDispatch<decorators, T, BARRIER_ARRAYCOPY>: AllStatic {548typedef typename AccessFunction<decorators, T, BARRIER_ARRAYCOPY>::type func_t;549static func_t _arraycopy_func;550551static bool arraycopy_init(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,552arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,553size_t length);554555static inline bool arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,556arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,557size_t length) {558return _arraycopy_func(src_obj, src_offset_in_bytes, src_raw,559dst_obj, dst_offset_in_bytes, dst_raw,560length);561}562};563564template <DecoratorSet decorators, typename T>565struct RuntimeDispatch<decorators, T, BARRIER_CLONE>: AllStatic {566typedef typename AccessFunction<decorators, T, BARRIER_CLONE>::type func_t;567static func_t _clone_func;568569static void clone_init(oop src, oop dst, size_t size);570571static inline void clone(oop src, oop dst, size_t size) {572_clone_func(src, dst, size);573}574};575576template <DecoratorSet decorators, typename T>577struct RuntimeDispatch<decorators, T, BARRIER_RESOLVE>: AllStatic {578typedef typename AccessFunction<decorators, T, BARRIER_RESOLVE>::type func_t;579static func_t _resolve_func;580581static oop resolve_init(oop obj);582583static inline oop resolve(oop obj) {584return _resolve_func(obj);585}586};587588// Initialize the function pointers to point to the resolving function.589template <DecoratorSet decorators, typename T>590typename AccessFunction<decorators, T, BARRIER_STORE>::type591RuntimeDispatch<decorators, T, BARRIER_STORE>::_store_func = &store_init;592593template <DecoratorSet decorators, typename T>594typename AccessFunction<decorators, T, BARRIER_STORE_AT>::type595RuntimeDispatch<decorators, T, BARRIER_STORE_AT>::_store_at_func = &store_at_init;596597template <DecoratorSet decorators, typename T>598typename AccessFunction<decorators, T, BARRIER_LOAD>::type599RuntimeDispatch<decorators, T, BARRIER_LOAD>::_load_func = &load_init;600601template <DecoratorSet decorators, typename T>602typename AccessFunction<decorators, T, BARRIER_LOAD_AT>::type603RuntimeDispatch<decorators, T, BARRIER_LOAD_AT>::_load_at_func = &load_at_init;604605template <DecoratorSet decorators, typename T>606typename AccessFunction<decorators, T, BARRIER_ATOMIC_CMPXCHG>::type607RuntimeDispatch<decorators, T, BARRIER_ATOMIC_CMPXCHG>::_atomic_cmpxchg_func = &atomic_cmpxchg_init;608609template <DecoratorSet decorators, typename T>610typename AccessFunction<decorators, T, BARRIER_ATOMIC_CMPXCHG_AT>::type611RuntimeDispatch<decorators, T, BARRIER_ATOMIC_CMPXCHG_AT>::_atomic_cmpxchg_at_func = &atomic_cmpxchg_at_init;612613template <DecoratorSet decorators, typename T>614typename AccessFunction<decorators, T, BARRIER_ATOMIC_XCHG>::type615RuntimeDispatch<decorators, T, BARRIER_ATOMIC_XCHG>::_atomic_xchg_func = &atomic_xchg_init;616617template <DecoratorSet decorators, typename T>618typename AccessFunction<decorators, T, BARRIER_ATOMIC_XCHG_AT>::type619RuntimeDispatch<decorators, T, BARRIER_ATOMIC_XCHG_AT>::_atomic_xchg_at_func = &atomic_xchg_at_init;620621template <DecoratorSet decorators, typename T>622typename AccessFunction<decorators, T, BARRIER_ARRAYCOPY>::type623RuntimeDispatch<decorators, T, BARRIER_ARRAYCOPY>::_arraycopy_func = &arraycopy_init;624625template <DecoratorSet decorators, typename T>626typename AccessFunction<decorators, T, BARRIER_CLONE>::type627RuntimeDispatch<decorators, T, BARRIER_CLONE>::_clone_func = &clone_init;628629template <DecoratorSet decorators, typename T>630typename AccessFunction<decorators, T, BARRIER_RESOLVE>::type631RuntimeDispatch<decorators, T, BARRIER_RESOLVE>::_resolve_func = &resolve_init;632633// Step 3: Pre-runtime dispatching.634// The PreRuntimeDispatch class is responsible for filtering the barrier strength635// decorators. That is, for AS_RAW, it hardwires the accesses without a runtime636// dispatch point. Otherwise it goes through a runtime check if hardwiring was637// not possible.638struct PreRuntimeDispatch: AllStatic {639template<DecoratorSet decorators>640struct CanHardwireRaw: public IntegralConstant<641bool,642!HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value || // primitive access643!HasDecorator<decorators, INTERNAL_CONVERT_COMPRESSED_OOP>::value || // don't care about compressed oops (oop* address)644HasDecorator<decorators, INTERNAL_RT_USE_COMPRESSED_OOPS>::value> // we can infer we use compressed oops (narrowOop* address)645{};646647static const DecoratorSet convert_compressed_oops = INTERNAL_RT_USE_COMPRESSED_OOPS | INTERNAL_CONVERT_COMPRESSED_OOP;648649template<DecoratorSet decorators>650static bool is_hardwired_primitive() {651return !HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value;652}653654template <DecoratorSet decorators, typename T>655inline static typename EnableIf<656HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value>::type657store(void* addr, T value) {658typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw;659if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) {660Raw::oop_store(addr, value);661} else {662Raw::store(addr, value);663}664}665666template <DecoratorSet decorators, typename T>667inline static typename EnableIf<668HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value>::type669store(void* addr, T value) {670if (UseCompressedOops) {671const DecoratorSet expanded_decorators = decorators | convert_compressed_oops;672PreRuntimeDispatch::store<expanded_decorators>(addr, value);673} else {674const DecoratorSet expanded_decorators = decorators & ~convert_compressed_oops;675PreRuntimeDispatch::store<expanded_decorators>(addr, value);676}677}678679template <DecoratorSet decorators, typename T>680inline static typename EnableIf<681!HasDecorator<decorators, AS_RAW>::value>::type682store(void* addr, T value) {683if (is_hardwired_primitive<decorators>()) {684const DecoratorSet expanded_decorators = decorators | AS_RAW;685PreRuntimeDispatch::store<expanded_decorators>(addr, value);686} else {687RuntimeDispatch<decorators, T, BARRIER_STORE>::store(addr, value);688}689}690691template <DecoratorSet decorators, typename T>692inline static typename EnableIf<693HasDecorator<decorators, AS_RAW>::value>::type694store_at(oop base, ptrdiff_t offset, T value) {695store<decorators>(field_addr(base, offset), value);696}697698template <DecoratorSet decorators, typename T>699inline static typename EnableIf<700!HasDecorator<decorators, AS_RAW>::value>::type701store_at(oop base, ptrdiff_t offset, T value) {702if (is_hardwired_primitive<decorators>()) {703const DecoratorSet expanded_decorators = decorators | AS_RAW;704PreRuntimeDispatch::store_at<expanded_decorators>(base, offset, value);705} else {706RuntimeDispatch<decorators, T, BARRIER_STORE_AT>::store_at(base, offset, value);707}708}709710template <DecoratorSet decorators, typename T>711inline static typename EnableIf<712HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value, T>::type713load(void* addr) {714typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw;715if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) {716return Raw::template oop_load<T>(addr);717} else {718return Raw::template load<T>(addr);719}720}721722template <DecoratorSet decorators, typename T>723inline static typename EnableIf<724HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value, T>::type725load(void* addr) {726if (UseCompressedOops) {727const DecoratorSet expanded_decorators = decorators | convert_compressed_oops;728return PreRuntimeDispatch::load<expanded_decorators, T>(addr);729} else {730const DecoratorSet expanded_decorators = decorators & ~convert_compressed_oops;731return PreRuntimeDispatch::load<expanded_decorators, T>(addr);732}733}734735template <DecoratorSet decorators, typename T>736inline static typename EnableIf<737!HasDecorator<decorators, AS_RAW>::value, T>::type738load(void* addr) {739if (is_hardwired_primitive<decorators>()) {740const DecoratorSet expanded_decorators = decorators | AS_RAW;741return PreRuntimeDispatch::load<expanded_decorators, T>(addr);742} else {743return RuntimeDispatch<decorators, T, BARRIER_LOAD>::load(addr);744}745}746747template <DecoratorSet decorators, typename T>748inline static typename EnableIf<749HasDecorator<decorators, AS_RAW>::value, T>::type750load_at(oop base, ptrdiff_t offset) {751return load<decorators, T>(field_addr(base, offset));752}753754template <DecoratorSet decorators, typename T>755inline static typename EnableIf<756!HasDecorator<decorators, AS_RAW>::value, T>::type757load_at(oop base, ptrdiff_t offset) {758if (is_hardwired_primitive<decorators>()) {759const DecoratorSet expanded_decorators = decorators | AS_RAW;760return PreRuntimeDispatch::load_at<expanded_decorators, T>(base, offset);761} else {762return RuntimeDispatch<decorators, T, BARRIER_LOAD_AT>::load_at(base, offset);763}764}765766template <DecoratorSet decorators, typename T>767inline static typename EnableIf<768HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value, T>::type769atomic_cmpxchg(void* addr, T compare_value, T new_value) {770typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw;771if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) {772return Raw::oop_atomic_cmpxchg(addr, compare_value, new_value);773} else {774return Raw::atomic_cmpxchg(addr, compare_value, new_value);775}776}777778template <DecoratorSet decorators, typename T>779inline static typename EnableIf<780HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value, T>::type781atomic_cmpxchg(void* addr, T compare_value, T new_value) {782if (UseCompressedOops) {783const DecoratorSet expanded_decorators = decorators | convert_compressed_oops;784return PreRuntimeDispatch::atomic_cmpxchg<expanded_decorators>(addr, compare_value, new_value);785} else {786const DecoratorSet expanded_decorators = decorators & ~convert_compressed_oops;787return PreRuntimeDispatch::atomic_cmpxchg<expanded_decorators>(addr, compare_value, new_value);788}789}790791template <DecoratorSet decorators, typename T>792inline static typename EnableIf<793!HasDecorator<decorators, AS_RAW>::value, T>::type794atomic_cmpxchg(void* addr, T compare_value, T new_value) {795if (is_hardwired_primitive<decorators>()) {796const DecoratorSet expanded_decorators = decorators | AS_RAW;797return PreRuntimeDispatch::atomic_cmpxchg<expanded_decorators>(addr, compare_value, new_value);798} else {799return RuntimeDispatch<decorators, T, BARRIER_ATOMIC_CMPXCHG>::atomic_cmpxchg(addr, compare_value, new_value);800}801}802803template <DecoratorSet decorators, typename T>804inline static typename EnableIf<805HasDecorator<decorators, AS_RAW>::value, T>::type806atomic_cmpxchg_at(oop base, ptrdiff_t offset, T compare_value, T new_value) {807return atomic_cmpxchg<decorators>(field_addr(base, offset), compare_value, new_value);808}809810template <DecoratorSet decorators, typename T>811inline static typename EnableIf<812!HasDecorator<decorators, AS_RAW>::value, T>::type813atomic_cmpxchg_at(oop base, ptrdiff_t offset, T compare_value, T new_value) {814if (is_hardwired_primitive<decorators>()) {815const DecoratorSet expanded_decorators = decorators | AS_RAW;816return PreRuntimeDispatch::atomic_cmpxchg_at<expanded_decorators>(base, offset, compare_value, new_value);817} else {818return RuntimeDispatch<decorators, T, BARRIER_ATOMIC_CMPXCHG_AT>::atomic_cmpxchg_at(base, offset, compare_value, new_value);819}820}821822template <DecoratorSet decorators, typename T>823inline static typename EnableIf<824HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value, T>::type825atomic_xchg(void* addr, T new_value) {826typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw;827if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) {828return Raw::oop_atomic_xchg(addr, new_value);829} else {830return Raw::atomic_xchg(addr, new_value);831}832}833834template <DecoratorSet decorators, typename T>835inline static typename EnableIf<836HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value, T>::type837atomic_xchg(void* addr, T new_value) {838if (UseCompressedOops) {839const DecoratorSet expanded_decorators = decorators | convert_compressed_oops;840return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(addr, new_value);841} else {842const DecoratorSet expanded_decorators = decorators & ~convert_compressed_oops;843return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(addr, new_value);844}845}846847template <DecoratorSet decorators, typename T>848inline static typename EnableIf<849!HasDecorator<decorators, AS_RAW>::value, T>::type850atomic_xchg(void* addr, T new_value) {851if (is_hardwired_primitive<decorators>()) {852const DecoratorSet expanded_decorators = decorators | AS_RAW;853return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(addr, new_value);854} else {855return RuntimeDispatch<decorators, T, BARRIER_ATOMIC_XCHG>::atomic_xchg(addr, new_value);856}857}858859template <DecoratorSet decorators, typename T>860inline static typename EnableIf<861HasDecorator<decorators, AS_RAW>::value, T>::type862atomic_xchg_at(oop base, ptrdiff_t offset, T new_value) {863return atomic_xchg<decorators>(field_addr(base, offset), new_value);864}865866template <DecoratorSet decorators, typename T>867inline static typename EnableIf<868!HasDecorator<decorators, AS_RAW>::value, T>::type869atomic_xchg_at(oop base, ptrdiff_t offset, T new_value) {870if (is_hardwired_primitive<decorators>()) {871const DecoratorSet expanded_decorators = decorators | AS_RAW;872return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(base, offset, new_value);873} else {874return RuntimeDispatch<decorators, T, BARRIER_ATOMIC_XCHG_AT>::atomic_xchg_at(base, offset, new_value);875}876}877878template <DecoratorSet decorators, typename T>879inline static typename EnableIf<880HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value, bool>::type881arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,882arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,883size_t length) {884typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw;885if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) {886return Raw::oop_arraycopy(src_obj, src_offset_in_bytes, src_raw,887dst_obj, dst_offset_in_bytes, dst_raw,888length);889} else {890return Raw::arraycopy(src_obj, src_offset_in_bytes, src_raw,891dst_obj, dst_offset_in_bytes, dst_raw,892length);893}894}895896template <DecoratorSet decorators, typename T>897inline static typename EnableIf<898HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value, bool>::type899arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,900arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,901size_t length) {902if (UseCompressedOops) {903const DecoratorSet expanded_decorators = decorators | convert_compressed_oops;904return PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw,905dst_obj, dst_offset_in_bytes, dst_raw,906length);907} else {908const DecoratorSet expanded_decorators = decorators & ~convert_compressed_oops;909return PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw,910dst_obj, dst_offset_in_bytes, dst_raw,911length);912}913}914915template <DecoratorSet decorators, typename T>916inline static typename EnableIf<917!HasDecorator<decorators, AS_RAW>::value, bool>::type918arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,919arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,920size_t length) {921if (is_hardwired_primitive<decorators>()) {922const DecoratorSet expanded_decorators = decorators | AS_RAW;923return PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw,924dst_obj, dst_offset_in_bytes, dst_raw,925length);926} else {927return RuntimeDispatch<decorators, T, BARRIER_ARRAYCOPY>::arraycopy(src_obj, src_offset_in_bytes, src_raw,928dst_obj, dst_offset_in_bytes, dst_raw,929length);930}931}932933template <DecoratorSet decorators>934inline static typename EnableIf<935HasDecorator<decorators, AS_RAW>::value>::type936clone(oop src, oop dst, size_t size) {937typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw;938Raw::clone(src, dst, size);939}940941template <DecoratorSet decorators>942inline static typename EnableIf<943!HasDecorator<decorators, AS_RAW>::value>::type944clone(oop src, oop dst, size_t size) {945RuntimeDispatch<decorators, oop, BARRIER_CLONE>::clone(src, dst, size);946}947};948949// Step 2: Reduce types.950// Enforce that for non-oop types, T and P have to be strictly the same.951// P is the type of the address and T is the type of the values.952// As for oop types, it is allow to send T in {narrowOop, oop} and953// P in {narrowOop, oop, HeapWord*}. The following rules apply according to954// the subsequent table. (columns are P, rows are T)955// | | HeapWord | oop | narrowOop |956// | oop | rt-comp | hw-none | hw-comp |957// | narrowOop | x | x | hw-none |958//959// x means not allowed960// rt-comp means it must be checked at runtime whether the oop is compressed.961// hw-none means it is statically known the oop will not be compressed.962// hw-comp means it is statically known the oop will be compressed.963964template <DecoratorSet decorators, typename T>965inline void store_reduce_types(T* addr, T value) {966PreRuntimeDispatch::store<decorators>(addr, value);967}968969template <DecoratorSet decorators>970inline void store_reduce_types(narrowOop* addr, oop value) {971const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP |972INTERNAL_RT_USE_COMPRESSED_OOPS;973PreRuntimeDispatch::store<expanded_decorators>(addr, value);974}975976template <DecoratorSet decorators>977inline void store_reduce_types(narrowOop* addr, narrowOop value) {978const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP |979INTERNAL_RT_USE_COMPRESSED_OOPS;980PreRuntimeDispatch::store<expanded_decorators>(addr, value);981}982983template <DecoratorSet decorators>984inline void store_reduce_types(HeapWord* addr, oop value) {985const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP;986PreRuntimeDispatch::store<expanded_decorators>(addr, value);987}988989template <DecoratorSet decorators, typename T>990inline T atomic_cmpxchg_reduce_types(T* addr, T compare_value, T new_value) {991return PreRuntimeDispatch::atomic_cmpxchg<decorators>(addr, compare_value, new_value);992}993994template <DecoratorSet decorators>995inline oop atomic_cmpxchg_reduce_types(narrowOop* addr, oop compare_value, oop new_value) {996const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP |997INTERNAL_RT_USE_COMPRESSED_OOPS;998return PreRuntimeDispatch::atomic_cmpxchg<expanded_decorators>(addr, compare_value, new_value);999}10001001template <DecoratorSet decorators>1002inline narrowOop atomic_cmpxchg_reduce_types(narrowOop* addr, narrowOop compare_value, narrowOop new_value) {1003const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP |1004INTERNAL_RT_USE_COMPRESSED_OOPS;1005return PreRuntimeDispatch::atomic_cmpxchg<expanded_decorators>(addr, compare_value, new_value);1006}10071008template <DecoratorSet decorators>1009inline oop atomic_cmpxchg_reduce_types(HeapWord* addr,1010oop compare_value,1011oop new_value) {1012const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP;1013return PreRuntimeDispatch::atomic_cmpxchg<expanded_decorators>(addr, compare_value, new_value);1014}10151016template <DecoratorSet decorators, typename T>1017inline T atomic_xchg_reduce_types(T* addr, T new_value) {1018const DecoratorSet expanded_decorators = decorators;1019return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(addr, new_value);1020}10211022template <DecoratorSet decorators>1023inline oop atomic_xchg_reduce_types(narrowOop* addr, oop new_value) {1024const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP |1025INTERNAL_RT_USE_COMPRESSED_OOPS;1026return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(addr, new_value);1027}10281029template <DecoratorSet decorators>1030inline narrowOop atomic_xchg_reduce_types(narrowOop* addr, narrowOop new_value) {1031const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP |1032INTERNAL_RT_USE_COMPRESSED_OOPS;1033return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(addr, new_value);1034}10351036template <DecoratorSet decorators>1037inline oop atomic_xchg_reduce_types(HeapWord* addr, oop new_value) {1038const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP;1039return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(addr, new_value);1040}10411042template <DecoratorSet decorators, typename T>1043inline T load_reduce_types(T* addr) {1044return PreRuntimeDispatch::load<decorators, T>(addr);1045}10461047template <DecoratorSet decorators, typename T>1048inline typename OopOrNarrowOop<T>::type load_reduce_types(narrowOop* addr) {1049const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP |1050INTERNAL_RT_USE_COMPRESSED_OOPS;1051return PreRuntimeDispatch::load<expanded_decorators, typename OopOrNarrowOop<T>::type>(addr);1052}10531054template <DecoratorSet decorators, typename T>1055inline oop load_reduce_types(HeapWord* addr) {1056const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP;1057return PreRuntimeDispatch::load<expanded_decorators, oop>(addr);1058}10591060template <DecoratorSet decorators, typename T>1061inline bool arraycopy_reduce_types(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,1062arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,1063size_t length) {1064return PreRuntimeDispatch::arraycopy<decorators>(src_obj, src_offset_in_bytes, src_raw,1065dst_obj, dst_offset_in_bytes, dst_raw,1066length);1067}10681069template <DecoratorSet decorators>1070inline bool arraycopy_reduce_types(arrayOop src_obj, size_t src_offset_in_bytes, HeapWord* src_raw,1071arrayOop dst_obj, size_t dst_offset_in_bytes, HeapWord* dst_raw,1072size_t length) {1073const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP;1074return PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw,1075dst_obj, dst_offset_in_bytes, dst_raw,1076length);1077}10781079template <DecoratorSet decorators>1080inline bool arraycopy_reduce_types(arrayOop src_obj, size_t src_offset_in_bytes, narrowOop* src_raw,1081arrayOop dst_obj, size_t dst_offset_in_bytes, narrowOop* dst_raw,1082size_t length) {1083const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP |1084INTERNAL_RT_USE_COMPRESSED_OOPS;1085return PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw,1086dst_obj, dst_offset_in_bytes, dst_raw,1087length);1088}10891090// Step 1: Set default decorators. This step remembers if a type was volatile1091// and then sets the MO_RELAXED decorator by default. Otherwise, a default1092// memory ordering is set for the access, and the implied decorator rules1093// are applied to select sensible defaults for decorators that have not been1094// explicitly set. For example, default object referent strength is set to strong.1095// This step also decays the types passed in (e.g. getting rid of CV qualifiers1096// and references from the types). This step also perform some type verification1097// that the passed in types make sense.10981099template <DecoratorSet decorators, typename T>1100static void verify_types(){1101// If this fails to compile, then you have sent in something that is1102// not recognized as a valid primitive type to a primitive Access function.1103STATIC_ASSERT((HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value || // oops have already been validated1104(IsPointer<T>::value || IsIntegral<T>::value) ||1105IsFloatingPoint<T>::value)); // not allowed primitive type1106}11071108template <DecoratorSet decorators, typename P, typename T>1109inline void store(P* addr, T value) {1110verify_types<decorators, T>();1111typedef typename Decay<P>::type DecayedP;1112typedef typename Decay<T>::type DecayedT;1113DecayedT decayed_value = value;1114// If a volatile address is passed in but no memory ordering decorator,1115// set the memory ordering to MO_RELAXED by default.1116const DecoratorSet expanded_decorators = DecoratorFixup<1117(IsVolatile<P>::value && !HasDecorator<decorators, MO_DECORATOR_MASK>::value) ?1118(MO_RELAXED | decorators) : decorators>::value;1119store_reduce_types<expanded_decorators>(const_cast<DecayedP*>(addr), decayed_value);1120}11211122template <DecoratorSet decorators, typename T>1123inline void store_at(oop base, ptrdiff_t offset, T value) {1124verify_types<decorators, T>();1125typedef typename Decay<T>::type DecayedT;1126DecayedT decayed_value = value;1127const DecoratorSet expanded_decorators = DecoratorFixup<decorators |1128(HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value ?1129INTERNAL_CONVERT_COMPRESSED_OOP : DECORATORS_NONE)>::value;1130PreRuntimeDispatch::store_at<expanded_decorators>(base, offset, decayed_value);1131}11321133template <DecoratorSet decorators, typename P, typename T>1134inline T load(P* addr) {1135verify_types<decorators, T>();1136typedef typename Decay<P>::type DecayedP;1137typedef typename Conditional<HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value,1138typename OopOrNarrowOop<T>::type,1139typename Decay<T>::type>::type DecayedT;1140// If a volatile address is passed in but no memory ordering decorator,1141// set the memory ordering to MO_RELAXED by default.1142const DecoratorSet expanded_decorators = DecoratorFixup<1143(IsVolatile<P>::value && !HasDecorator<decorators, MO_DECORATOR_MASK>::value) ?1144(MO_RELAXED | decorators) : decorators>::value;1145return load_reduce_types<expanded_decorators, DecayedT>(const_cast<DecayedP*>(addr));1146}11471148template <DecoratorSet decorators, typename T>1149inline T load_at(oop base, ptrdiff_t offset) {1150verify_types<decorators, T>();1151typedef typename Conditional<HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value,1152typename OopOrNarrowOop<T>::type,1153typename Decay<T>::type>::type DecayedT;1154// Expand the decorators (figure out sensible defaults)1155// Potentially remember if we need compressed oop awareness1156const DecoratorSet expanded_decorators = DecoratorFixup<decorators |1157(HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value ?1158INTERNAL_CONVERT_COMPRESSED_OOP : DECORATORS_NONE)>::value;1159return PreRuntimeDispatch::load_at<expanded_decorators, DecayedT>(base, offset);1160}11611162template <DecoratorSet decorators, typename P, typename T>1163inline T atomic_cmpxchg(P* addr, T compare_value, T new_value) {1164verify_types<decorators, T>();1165typedef typename Decay<P>::type DecayedP;1166typedef typename Decay<T>::type DecayedT;1167DecayedT new_decayed_value = new_value;1168DecayedT compare_decayed_value = compare_value;1169const DecoratorSet expanded_decorators = DecoratorFixup<1170(!HasDecorator<decorators, MO_DECORATOR_MASK>::value) ?1171(MO_SEQ_CST | decorators) : decorators>::value;1172return atomic_cmpxchg_reduce_types<expanded_decorators>(const_cast<DecayedP*>(addr),1173compare_decayed_value,1174new_decayed_value);1175}11761177template <DecoratorSet decorators, typename T>1178inline T atomic_cmpxchg_at(oop base, ptrdiff_t offset, T compare_value, T new_value) {1179verify_types<decorators, T>();1180typedef typename Decay<T>::type DecayedT;1181DecayedT new_decayed_value = new_value;1182DecayedT compare_decayed_value = compare_value;1183// Determine default memory ordering1184const DecoratorSet expanded_decorators = DecoratorFixup<1185(!HasDecorator<decorators, MO_DECORATOR_MASK>::value) ?1186(MO_SEQ_CST | decorators) : decorators>::value;1187// Potentially remember that we need compressed oop awareness1188const DecoratorSet final_decorators = expanded_decorators |1189(HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value ?1190INTERNAL_CONVERT_COMPRESSED_OOP : DECORATORS_NONE);1191return PreRuntimeDispatch::atomic_cmpxchg_at<final_decorators>(base, offset, compare_decayed_value,1192new_decayed_value);1193}11941195template <DecoratorSet decorators, typename P, typename T>1196inline T atomic_xchg(P* addr, T new_value) {1197verify_types<decorators, T>();1198typedef typename Decay<P>::type DecayedP;1199typedef typename Decay<T>::type DecayedT;1200DecayedT new_decayed_value = new_value;1201// atomic_xchg is only available in SEQ_CST flavour.1202const DecoratorSet expanded_decorators = DecoratorFixup<decorators | MO_SEQ_CST>::value;1203return atomic_xchg_reduce_types<expanded_decorators>(const_cast<DecayedP*>(addr),1204new_decayed_value);1205}12061207template <DecoratorSet decorators, typename T>1208inline T atomic_xchg_at(oop base, ptrdiff_t offset, T new_value) {1209verify_types<decorators, T>();1210typedef typename Decay<T>::type DecayedT;1211DecayedT new_decayed_value = new_value;1212// atomic_xchg is only available in SEQ_CST flavour.1213const DecoratorSet expanded_decorators = DecoratorFixup<decorators | MO_SEQ_CST |1214(HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value ?1215INTERNAL_CONVERT_COMPRESSED_OOP : DECORATORS_NONE)>::value;1216return PreRuntimeDispatch::atomic_xchg_at<expanded_decorators>(base, offset, new_decayed_value);1217}12181219template <DecoratorSet decorators, typename T>1220inline bool arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, const T* src_raw,1221arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,1222size_t length) {1223STATIC_ASSERT((HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value ||1224(IsSame<T, void>::value || IsIntegral<T>::value) ||1225IsFloatingPoint<T>::value)); // arraycopy allows type erased void elements1226typedef typename Decay<T>::type DecayedT;1227const DecoratorSet expanded_decorators = DecoratorFixup<decorators | IS_ARRAY | IN_HEAP>::value;1228return arraycopy_reduce_types<expanded_decorators>(src_obj, src_offset_in_bytes, const_cast<DecayedT*>(src_raw),1229dst_obj, dst_offset_in_bytes, const_cast<DecayedT*>(dst_raw),1230length);1231}12321233template <DecoratorSet decorators>1234inline void clone(oop src, oop dst, size_t size) {1235const DecoratorSet expanded_decorators = DecoratorFixup<decorators>::value;1236PreRuntimeDispatch::clone<expanded_decorators>(src, dst, size);1237}12381239// Infer the type that should be returned from an Access::oop_load.1240template <typename P, DecoratorSet decorators>1241class OopLoadProxy: public StackObj {1242private:1243P *const _addr;1244public:1245OopLoadProxy(P* addr) : _addr(addr) {}12461247inline operator oop() {1248return load<decorators | INTERNAL_VALUE_IS_OOP, P, oop>(_addr);1249}12501251inline operator narrowOop() {1252return load<decorators | INTERNAL_VALUE_IS_OOP, P, narrowOop>(_addr);1253}12541255template <typename T>1256inline bool operator ==(const T& other) const {1257return load<decorators | INTERNAL_VALUE_IS_OOP, P, T>(_addr) == other;1258}12591260template <typename T>1261inline bool operator !=(const T& other) const {1262return load<decorators | INTERNAL_VALUE_IS_OOP, P, T>(_addr) != other;1263}1264};12651266// Infer the type that should be returned from an Access::load_at.1267template <DecoratorSet decorators>1268class LoadAtProxy: public StackObj {1269private:1270const oop _base;1271const ptrdiff_t _offset;1272public:1273LoadAtProxy(oop base, ptrdiff_t offset) : _base(base), _offset(offset) {}12741275template <typename T>1276inline operator T() const {1277return load_at<decorators, T>(_base, _offset);1278}12791280template <typename T>1281inline bool operator ==(const T& other) const { return load_at<decorators, T>(_base, _offset) == other; }12821283template <typename T>1284inline bool operator !=(const T& other) const { return load_at<decorators, T>(_base, _offset) != other; }1285};12861287// Infer the type that should be returned from an Access::oop_load_at.1288template <DecoratorSet decorators>1289class OopLoadAtProxy: public StackObj {1290private:1291const oop _base;1292const ptrdiff_t _offset;1293public:1294OopLoadAtProxy(oop base, ptrdiff_t offset) : _base(base), _offset(offset) {}12951296inline operator oop() const {1297return load_at<decorators | INTERNAL_VALUE_IS_OOP, oop>(_base, _offset);1298}12991300inline operator narrowOop() const {1301return load_at<decorators | INTERNAL_VALUE_IS_OOP, narrowOop>(_base, _offset);1302}13031304template <typename T>1305inline bool operator ==(const T& other) const {1306return load_at<decorators | INTERNAL_VALUE_IS_OOP, T>(_base, _offset) == other;1307}13081309template <typename T>1310inline bool operator !=(const T& other) const {1311return load_at<decorators | INTERNAL_VALUE_IS_OOP, T>(_base, _offset) != other;1312}1313};1314}13151316#endif // SHARE_OOPS_ACCESSBACKEND_HPP131713181319