--- /dev/null 2017-03-07 11:44:12.271151064 +0100 +++ new/src/share/vm/runtime/access.inline.hpp 2017-04-25 16:46:38.431170893 +0200 @@ -0,0 +1,1224 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_RUNTIME_ACCESS_INLINE_HPP +#define SHARE_VM_RUNTIME_ACCESS_INLINE_HPP + +#include "gc/shared/barrierSet.inline.hpp" +#include "runtime/access.hpp" +#include "runtime/accessBackend.hpp" +#include "runtime/atomic.hpp" +#include "runtime/orderAccess.inline.hpp" + +namespace AccessInternal { + + template + class AccessBarrierResolver: public AllStatic { + public: + static void* resolve_barrier(); + }; + + template + class CloneAccessBarrierResolver: public AllStatic { + public: + static void* resolve_barrier(); + }; + + template + struct DispatcherFactory: public AllStatic { + static void* resolve_barrier_gc() { + return AccessBarrierResolver::resolve_barrier(); + } + + static void* resolve_barrier_post_rt(); + + static void* resolve_barrier_rt() { + if (UseCompressedOops) { + return DispatcherFactory::resolve_barrier_post_rt(); + } else { + return DispatcherFactory::resolve_barrier_post_rt(); + } + } + + static void* resolve_barrier() { + return resolve_barrier_rt(); + } + }; + + template + struct CloneDispatcherFactory: public AllStatic { + static void* resolve_barrier_gc() { + return CloneAccessBarrierResolver::resolve_barrier(); + } + + static void* resolve_barrier_rt() { + if (UseCompressedOops) { + return CloneDispatcherFactory::resolve_barrier_gc(); + } else { + return CloneDispatcherFactory::resolve_barrier_gc(); + } + } + + static void* resolve_barrier() { + return resolve_barrier_rt(); + } + }; + + template + struct CloneRuntimeDispatch { + typedef void (*clone_func_t)(oop src, oop dst, size_t size); + + static void clone_init(oop src, oop dst, size_t size) { + _clone_func = (clone_func_t)CloneDispatcherFactory::resolve_barrier(); + _clone_func(src, dst, size); + } + + static clone_func_t _clone_func; + + static inline void clone(oop src, oop dst, size_t size) { + return _clone_func(src, dst, size); + } + }; + + template + struct RuntimeDispatch { + static void store_init(void* addr, T value) { + _store_func = (typename AccessFunctionTypes::store_func_t)DispatcherFactory::resolve_barrier(); + _store_func(addr, value); + } + + static void store_at_init(typename BaseType::type base, ptrdiff_t offset, T value) { + _store_at_func = (typename AccessFunctionTypes::store_at_func_t)DispatcherFactory::resolve_barrier(); + _store_at_func(base, offset, value); + } + + static T load_init(void* addr) { + _load_func = (typename AccessFunctionTypes::load_func_t)DispatcherFactory::resolve_barrier(); + return _load_func(addr); + } + + static T load_at_init(typename BaseType::type base, ptrdiff_t offset) { + _load_at_func = (typename AccessFunctionTypes::load_at_func_t)DispatcherFactory::resolve_barrier(); + return _load_at_func(base, offset); + } + + static T cas_init(T new_value, void* addr, T compare_value) { + _cas_func = (typename AccessFunctionTypes::cas_func_t)DispatcherFactory::resolve_barrier(); + return _cas_func(new_value, addr, compare_value); + } + + static T cas_at_init(T new_value, typename BaseType::type base, ptrdiff_t offset, T compare_value) { + _cas_at_func = (typename AccessFunctionTypes::cas_at_func_t)DispatcherFactory::resolve_barrier(); + return _cas_at_func(new_value, base, offset, compare_value); + } + + static T swap_init(T new_value, void* addr) { + _swap_func = (typename AccessFunctionTypes::swap_func_t)DispatcherFactory::resolve_barrier(); + return _swap_func(new_value, addr); + } + + static T swap_at_init(T new_value, typename BaseType::type base, ptrdiff_t offset) { + _swap_at_func = (typename AccessFunctionTypes::swap_at_func_t)DispatcherFactory::resolve_barrier(); + return _swap_at_func(new_value, base, offset); + } + + static bool copy_init(arrayOop src_obj, arrayOop dst_obj, T *src, T* dst, size_t length) { + _copy_func = (typename AccessFunctionTypes::copy_func_t)DispatcherFactory::resolve_barrier(); + return _copy_func(src_obj, dst_obj, src, dst, length); + } + + static typename AccessFunctionTypes::store_func_t _store_func; + static typename AccessFunctionTypes::store_at_func_t _store_at_func; + static typename AccessFunctionTypes::load_func_t _load_func; + static typename AccessFunctionTypes::load_at_func_t _load_at_func; + static typename AccessFunctionTypes::cas_func_t _cas_func; + static typename AccessFunctionTypes::cas_at_func_t _cas_at_func; + static typename AccessFunctionTypes::swap_func_t _swap_func; + static typename AccessFunctionTypes::swap_at_func_t _swap_at_func; + static typename AccessFunctionTypes::copy_func_t _copy_func; + + static inline void store(void* addr, T value) { + _store_func(addr, value); + } + + static inline void store_at(void* base, ptrdiff_t offset, T value) { + _store_at_func((typename BaseType::type)base, offset, value); + } + + static inline T load(void* addr) { + return _load_func(addr); + } + + static inline T load_at(void* base, ptrdiff_t offset) { + return _load_at_func((typename BaseType::type)base, offset); + } + + static inline T cas(T new_value, void* addr, T compare_value) { + return _cas_func(new_value, addr, compare_value); + } + + static inline T cas_at(T new_value, void* base, ptrdiff_t offset, T compare_value) { + return _cas_at_func(new_value, (typename BaseType::type)base, offset, compare_value); + } + + static inline T swap(T new_value, void* addr) { + return _swap_func(new_value, addr); + } + + static inline T swap_at(T new_value, void* base, ptrdiff_t offset) { + return _swap_at_func(new_value, (typename BaseType::type)base, offset); + } + + static inline bool copy(arrayOop src_obj, arrayOop dst_obj, T *src, T* dst, size_t length) { + return _copy_func(src_obj, dst_obj, src, dst, length); + } + }; + + template + struct PreRuntimeDispatch { + typedef RawAccessBarrier::value> Raw; + typedef BasicAccessBarrier::value> Basic; + + enum { + CAN_HARDWIRE_BASIC = DecoratorTest::HAS_USE_COMPRESSED_OOPS == DecoratorTest::HAS_GC_CONVERT_COMPRESSED_OOP + }; + + template + inline static typename EnableIf::HAS_ACCESS_RAW || DecoratorTest::HAS_ACCESS_BASIC, void>::type store(void* addr, T value) { + if (DecoratorTest::HAS_ACCESS_RAW) { + Raw::template store(addr, value); + } else if (DecoratorTest::HAS_ACCESS_BASIC) { + if (!DecoratorTest::HAS_VALUE_IS_OOP) { + Basic::template store(addr, value); + } else if (CAN_HARDWIRE_BASIC) { + Basic::template oop_store(addr, value); + } else if (UseCompressedOops) { + const DecoratorSet expanded_decorators = decorators | RT_USE_COMPRESSED_OOPS; + PreRuntimeDispatch::template store(addr, value); + } else { + const DecoratorSet expanded_decorators = decorators & ~GC_CONVERT_COMPRESSED_OOP; + PreRuntimeDispatch::template store(addr, value); + } + } + } + + template + inline static typename EnableIf::HAS_ACCESS_RAW && !DecoratorTest::HAS_ACCESS_BASIC, void>::type store(void* addr, T value) { + if (!DecoratorTest::HAS_BARRIER_ON_PRIMITIVES && !DecoratorTest::HAS_VALUE_IS_OOP) { + const DecoratorSet expanded_decorators = decorators | ACCESS_RAW; + PreRuntimeDispatch::template store(addr, value); + } else { + RuntimeDispatch::store(addr, value); + } + } + + template + inline static typename EnableIf::HAS_ACCESS_RAW || DecoratorTest::HAS_ACCESS_BASIC, void>::type store_at(void* base, ptrdiff_t offset, T value) { + if (DecoratorTest::HAS_ACCESS_RAW) { + Raw::template store(field_addr(base, offset), value); + } else if (DecoratorTest::HAS_ACCESS_BASIC) { + store(field_addr(base, offset), value); + } + } + + template + inline static typename EnableIf::HAS_ACCESS_RAW && !DecoratorTest::HAS_ACCESS_BASIC, void>::type store_at(void* base, ptrdiff_t offset, T value) { + if (!DecoratorTest::HAS_BARRIER_ON_PRIMITIVES && !DecoratorTest::HAS_VALUE_IS_OOP) { + const DecoratorSet expanded_decorators = decorators | ACCESS_RAW; + PreRuntimeDispatch::template store_at(base, offset, value); + } else { + RuntimeDispatch::store_at(base, offset, value); + } + } + + template + inline static typename EnableIf::HAS_ACCESS_RAW || DecoratorTest::HAS_ACCESS_BASIC, T>::type load(void* addr) { + if (DecoratorTest::HAS_ACCESS_RAW) { + return Raw::template load(addr); + } else if (DecoratorTest::HAS_ACCESS_BASIC) { + if (!DecoratorTest::HAS_VALUE_IS_OOP) { + return Basic::template load(addr); + } else if (CAN_HARDWIRE_BASIC) { + return Basic::template oop_load(addr); + } else if (UseCompressedOops) { + const DecoratorSet expanded_decorators = decorators | RT_USE_COMPRESSED_OOPS; + return PreRuntimeDispatch::template load(addr); + } else { + const DecoratorSet expanded_decorators = decorators & ~GC_CONVERT_COMPRESSED_OOP; + return PreRuntimeDispatch::template load(addr); + } + } + } + + template + inline static typename EnableIf::HAS_ACCESS_RAW && !DecoratorTest::HAS_ACCESS_BASIC, T>::type load(void* addr) { + if (!DecoratorTest::HAS_BARRIER_ON_PRIMITIVES && !DecoratorTest::HAS_VALUE_IS_OOP) { + const DecoratorSet expanded_decorators = decorators | ACCESS_RAW; + return PreRuntimeDispatch::template load(addr); + } else { + return RuntimeDispatch::load(addr); + } + } + + template + inline static typename EnableIf::HAS_ACCESS_RAW || DecoratorTest::HAS_ACCESS_BASIC, T>::type load_at(void* base, ptrdiff_t offset) { + if (DecoratorTest::HAS_ACCESS_RAW) { + return Raw::template load(field_addr(base, offset)); + } else if (DecoratorTest::HAS_ACCESS_BASIC) { + return load(field_addr(base, offset)); + } + } + + template + inline static typename EnableIf::HAS_ACCESS_RAW && !DecoratorTest::HAS_ACCESS_BASIC, T>::type load_at(void* base, ptrdiff_t offset) { + if (!DecoratorTest::HAS_BARRIER_ON_PRIMITIVES && !DecoratorTest::HAS_VALUE_IS_OOP) { + const DecoratorSet expanded_decorators = decorators | ACCESS_RAW; + return PreRuntimeDispatch::template load_at(base, offset); + } else { + return RuntimeDispatch::load_at(base, offset); + } + } + + template + inline static T cas(T new_value, void* addr, T compare_value) { + if (DecoratorTest::HAS_ACCESS_RAW) { + return Raw::template cas(new_value, addr, compare_value); + } else if (DecoratorTest::HAS_ACCESS_BASIC) { + if (!DecoratorTest::HAS_VALUE_IS_OOP) { + return Basic::template cas(new_value, addr, compare_value); + } else if (CAN_HARDWIRE_BASIC) { + return Basic::template oop_cas(new_value, addr, compare_value); + } else if (UseCompressedOops) { + const DecoratorSet expanded_decorators = decorators | RT_USE_COMPRESSED_OOPS; + return PreRuntimeDispatch::template cas(new_value, addr, compare_value); + } else { + const DecoratorSet expanded_decorators = decorators & ~GC_CONVERT_COMPRESSED_OOP; + return PreRuntimeDispatch::template cas(new_value, addr, compare_value); + } + } else if (!DecoratorTest::HAS_BARRIER_ON_PRIMITIVES && !DecoratorTest::HAS_VALUE_IS_OOP) { + return Raw::template cas(new_value, addr, compare_value); + } else { + return RuntimeDispatch::cas(new_value, addr, compare_value); + } + } + + template + inline static T cas_at(T new_value, void* base, ptrdiff_t offset, T compare_value) { + if (DecoratorTest::HAS_ACCESS_RAW) { + return Raw::template cas(new_value, field_addr(base, offset), compare_value); + } else if (DecoratorTest::HAS_ACCESS_BASIC) { + return cas(new_value, field_addr(base, offset), compare_value); + } else if (!DecoratorTest::HAS_BARRIER_ON_PRIMITIVES && !DecoratorTest::HAS_VALUE_IS_OOP) { + return Raw::template cas(new_value, field_addr(base, offset), compare_value); + } else { + return RuntimeDispatch::cas_at(new_value, base, offset, compare_value); + } + } + + template + inline static T swap(T new_value, void* addr) { + if (DecoratorTest::HAS_ACCESS_RAW) { + return Raw::template swap(new_value, addr); + } else if (DecoratorTest::HAS_ACCESS_BASIC) { + if (!DecoratorTest::HAS_VALUE_IS_OOP) { + return Basic::template swap(new_value, addr); + } else if (CAN_HARDWIRE_BASIC) { + return Basic::template oop_swap(new_value, addr); + } else if (UseCompressedOops) { + const DecoratorSet expanded_decorators = decorators | RT_USE_COMPRESSED_OOPS; + return PreRuntimeDispatch::template swap(new_value, addr); + } else { + const DecoratorSet expanded_decorators = decorators & ~GC_CONVERT_COMPRESSED_OOP; + return PreRuntimeDispatch::template swap(new_value, addr); + } + } else if (!DecoratorTest::HAS_BARRIER_ON_PRIMITIVES && !DecoratorTest::HAS_VALUE_IS_OOP) { + return Raw::template swap(new_value, addr); + } else { + return RuntimeDispatch::swap(new_value, addr); + } + } + + template + inline static T swap_at(T new_value, void* base, ptrdiff_t offset) { + if (DecoratorTest::HAS_ACCESS_RAW) { + return Raw::template swap(new_value, field_addr(base, offset)); + } else if (DecoratorTest::HAS_ACCESS_BASIC) { + return swap(new_value, field_addr(base, offset)); + } else if (!DecoratorTest::HAS_BARRIER_ON_PRIMITIVES && !DecoratorTest::HAS_VALUE_IS_OOP) { + return Raw::template swap(new_value, field_addr(base, offset)); + } else { + return RuntimeDispatch::swap_at(new_value, base, offset); + } + } + + template + inline static bool copy(arrayOop src_obj, arrayOop dst_obj, T *src, T* dst, size_t length) { + if (DecoratorTest::HAS_ACCESS_RAW) { + return Raw::template copy(src, dst, length); + } else if (DecoratorTest::HAS_ACCESS_BASIC) { + if (!DecoratorTest::HAS_VALUE_IS_OOP) { + return Basic::template copy(src_obj, dst_obj, src, dst, length); + } else { + return Basic::template oop_copy(src_obj, dst_obj, src, dst, length); + } + } else if (!DecoratorTest::HAS_BARRIER_ON_PRIMITIVES && !DecoratorTest::HAS_VALUE_IS_OOP) { + return Raw::template copy(src, dst, length); + } else { + return RuntimeDispatch::copy(src_obj, dst_obj, src, dst, length); + } + } + + template + inline static void clone(oop src, oop dst, size_t size) { + if (DecoratorTest::HAS_ACCESS_RAW) { + return Raw::clone(src, dst, size); + } else if (DecoratorTest::HAS_ACCESS_BASIC) { + return Basic::clone(src, dst, size); + } else { + return CloneRuntimeDispatch::clone(src, dst, size); + } + } + }; + + template + struct BuildtimeDispatch { + template + static void store(void* addr, T value); + template + static void store_at(void* base, ptrdiff_t offset, T value); + template + static T load(void* addr); + template + static T load_at(void* base, ptrdiff_t offset); + template + static T cas(T new_value, void* addr, T compare_value); + template + static T cas_at(T new_value, void* base, ptrdiff_t offset, T compare_value); + template + static T swap(T new_value, void* addr); + template + static T swap_at(T new_value, void* base, ptrdiff_t offset); + template + static bool copy(arrayOop src_obj, arrayOop dst_obj, T *src, T* dst, size_t length); + static void clone(oop src, oop dst, size_t size); + }; + + /** + * This class adds implied properties that follow according to decorator rules + */ + template + struct DecoratorFixup { + enum { + ref_strong_default = input_decorators | ((!DecoratorTest::HAS_GC_ACCESS_ON_PHANTOM + && !DecoratorTest::HAS_GC_ACCESS_ON_WEAK) ? GC_ACCESS_ON_STRONG : EMPTY_DECORATOR) + }; + enum { + seqcst_release = ref_strong_default | (DecoratorTest::HAS_MO_SEQ_CST ? MO_RELEASE : EMPTY_DECORATOR) + }; + enum { + seqcst_acquire = seqcst_release | (DecoratorTest::HAS_MO_SEQ_CST ? MO_ACQUIRE : EMPTY_DECORATOR) + }; + enum { + release_atomic = seqcst_acquire | (DecoratorTest::HAS_MO_RELEASE ? MO_ATOMIC : EMPTY_DECORATOR) + }; + enum { + acquire_atomic = release_atomic | (DecoratorTest::HAS_MO_ACQUIRE ? MO_ATOMIC : EMPTY_DECORATOR) + }; + enum { + atomic_volatile = acquire_atomic | (DecoratorTest::HAS_MO_ATOMIC ? MO_VOLATILE : EMPTY_DECORATOR) + }; + enum { + novolatile_relaxed = atomic_volatile | (!DecoratorTest::HAS_MO_VOLATILE ? MO_RELAXED : EMPTY_DECORATOR) + }; + enum { + relaxed_root = novolatile_relaxed | ((DecoratorTest::HAS_VALUE_IS_OOP && + (DecoratorTest::HAS_ACCESS_ON_NMETHOD || + DecoratorTest::HAS_ACCESS_ON_KLASS)) ? + ACCESS_ON_ROOT : EMPTY_DECORATOR) + }; + enum { + value = relaxed_root + }; + }; + + // Only let invocations where P and T are the same through + template + inline typename EnableIf::value, void>::type + store_reduce_types(P* addr, T value) { + BuildtimeDispatch::template store((void*)addr, value); + } + + template + inline typename EnableIf::value, void>::type + store_reduce_types(narrowOop* addr, oop value) { + const DecoratorSet expanded_decorators = decorators | GC_CONVERT_COMPRESSED_OOP | RT_USE_COMPRESSED_OOPS; + BuildtimeDispatch::template store((void*)addr, value); + } + + template + inline typename EnableIf::value, void>::type + store_reduce_types(HeapWord* addr, oop value) { + const DecoratorSet expanded_decorators = decorators | GC_CONVERT_COMPRESSED_OOP; + BuildtimeDispatch::template store((void*)addr, value); + } + + // If the decayed pointer and value types are the same, we decay their types and + // send them to the next stage in the pipeline + template + inline void store_decay_types(P* addr, T value) { + typedef typename Decay

::type DecayedP; + typedef typename Decay::type DecayedT; + const DecoratorSet expanded_decorators = IsVolatile

::value ? DecoratorFixup::value : decorators; + store_reduce_types((DecayedP*)addr, (DecayedT)value); + } + + template + void store_at_reduce_types(P base, ptrdiff_t offset, T value); + + template + inline void store_at_decay_types(P base, ptrdiff_t offset, T value) { + typedef typename Decay

::type DecayedP; + typedef typename Decay::type DecayedT; + store_at_reduce_types((DecayedP)base, offset, (DecayedT)value); + } + + template + T cas_at_reduce_types(T new_value, P base, ptrdiff_t offset, T compare_value); + + template + inline T cas_at_decay_types(T new_value, P base, ptrdiff_t offset, T compare_value) { + typedef typename Decay

::type DecayedP; + typedef typename Decay::type DecayedT; + const DecoratorSet memory_ordering = !DecoratorTest::HAS_MO_SEQ_CST ? MO_ATOMIC : MO_SEQ_CST; + const DecoratorSet expanded_decorators = DecoratorFixup::value; + return cas_at_reduce_types((DecayedT)new_value, (DecayedP)base, offset, (DecayedT)compare_value); + } + + template + inline typename EnableIf::value, T>::type cas_reduce_types(T new_value, P* addr, T compare_value) { + return BuildtimeDispatch::template cas(new_value, (void*)addr, compare_value); + } + + template + inline typename EnableIf::value, oop>::type cas_reduce_types(oop new_value, narrowOop* addr, oop compare_value) { + const DecoratorSet expanded_decorators = decorators | GC_CONVERT_COMPRESSED_OOP | RT_USE_COMPRESSED_OOPS; + return BuildtimeDispatch::template cas(new_value, (void*)addr, compare_value); + } + + template + inline typename EnableIf::value, oop>::type cas_reduce_types(oop new_value, HeapWord* addr, oop compare_value) { + const DecoratorSet expanded_decorators = decorators | GC_CONVERT_COMPRESSED_OOP; + return BuildtimeDispatch::template cas(new_value, (void*)addr, compare_value); + } + + template + inline T cas_decay_types(T new_value, P* addr, T compare_value) { + typedef typename Decay

::type DecayedP; + typedef typename Decay::type DecayedT; + const DecoratorSet memory_ordering = !DecoratorTest::HAS_MO_SEQ_CST ? MO_ATOMIC : MO_SEQ_CST; + const DecoratorSet expanded_decorators = DecoratorFixup::value; + return (T)cas_reduce_types((DecayedT)new_value, (DecayedP*)addr, (DecayedT)compare_value); + } + + template + inline T swap_at_reduce_types(T new_value, P base, ptrdiff_t offset); + + template + inline T swap_at_decay_types(T new_value, P base, ptrdiff_t offset) { + typedef typename Decay::type DecayedT; + typedef typename Decay

::type DecayedP; + const DecoratorSet expanded_decorators = DecoratorFixup::value; + return swap_at_reduce_types((DecayedT)new_value, (DecayedP)base, offset); + } + + template + inline typename EnableIf::value, T>::type swap_reduce_types(T new_value, P* addr) { + return BuildtimeDispatch::template swap(new_value, (void*)addr); + } + + template + inline typename EnableIf::value, oop>::type swap_reduce_types(oop new_value, narrowOop* addr) { + const DecoratorSet expanded_decorators = decorators | GC_CONVERT_COMPRESSED_OOP | RT_USE_COMPRESSED_OOPS; + return BuildtimeDispatch::template swap(new_value, (void*)addr); + } + + template + inline typename EnableIf::value, oop>::type + swap_reduce_types(oop new_value, HeapWord* addr) { + const DecoratorSet expanded_decorators = decorators | GC_CONVERT_COMPRESSED_OOP; + return BuildtimeDispatch::template swap(new_value, (void*)addr); + } + + template + inline T swap_decay_types(T new_value, P* addr) { + typedef typename Decay

::type DecayedP; + typedef typename Decay::type DecayedT; + const DecoratorSet expanded_decorators = DecoratorFixup::value; + return (T)swap_reduce_types((DecayedT)new_value, (DecayedP*)addr); + } + + template + inline typename EnableIf::HAS_VALUE_IS_OOP, bool>::type copy_reduce_types(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { + return BuildtimeDispatch::template copy(src_obj, dst_obj, src, dst, length); + } + + template + inline typename EnableIf::HAS_VALUE_IS_OOP, bool>::type copy_reduce_types(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { + return BuildtimeDispatch::template copy(src_obj, dst_obj, src, dst, length); + } + + template + inline bool copy_decay_types(arrayOop src_obj, arrayOop dst_obj, T *src, T *dst, size_t length) { + typedef typename Decay::type DecayedT; + return copy_reduce_types::value, DecayedT>(src_obj, dst_obj, (DecayedT*)src, (DecayedT*)dst, length); + } + + template + inline typename EnableIf::value, T>::type load_reduce_types(P* addr) { + return BuildtimeDispatch::template load((void*)addr); + } + + template + inline typename EnableIf::value, oop>::type load_reduce_types(narrowOop* addr) { + const DecoratorSet expanded_decorators = decorators | GC_CONVERT_COMPRESSED_OOP | RT_USE_COMPRESSED_OOPS; + return BuildtimeDispatch::template load((void*)addr); + } + + template + inline typename EnableIf::value, oop>::type load_reduce_types(HeapWord* addr) { + const DecoratorSet expanded_decorators = decorators | GC_CONVERT_COMPRESSED_OOP; + return BuildtimeDispatch::template load((void*)addr); + } + + // If the decayed pointer and value types are the same, we decay their types and + // send them to the next stage in the pipeline + template + inline T load_decay_types(P* addr) { + typedef typename Decay

::type DecayedP; + typedef typename TypeIf::HAS_VALUE_IS_OOP, + typename OopOrNarrowOop::type, typename Decay::type>::type DecayedT; + const DecoratorSet expanded_decorators = IsVolatile

::value ? DecoratorFixup::value : decorators; + return (T)load_reduce_types((DecayedP*)addr); + } + + template + class DispatchLoadAtReduceTypes { + public: + static T load_at(P base, ptrdiff_t offset); + }; + + template + inline T load_at_decay_types(P base, ptrdiff_t offset) { + typedef typename Decay

::type DecayedP; + typedef typename TypeIf::HAS_VALUE_IS_OOP, + typename OopOrNarrowOop::type, typename Decay::type>::type DecayedT; + return (T)DispatchLoadAtReduceTypes::load_at((DecayedP)base, offset); + } + + + template + inline void store(P* addr, T value) { + store_decay_types::value, P, T>(addr, value); + } + + template + inline void store_at(P base, ptrdiff_t offset, T value) { + store_at_decay_types::value, P, T>(base, offset, value); + } + + template + inline T load(P* addr) { + return load_decay_types::value, P, T>(addr); + } + + template + inline T load_at(P base, ptrdiff_t offset) { + return load_at_decay_types::value, P, T>(base, offset); + } + + template + inline T cas(T new_value, P* addr, T compare_value) { + return cas_decay_types::value, P, T>(new_value, addr, compare_value); + } + + template + inline T cas_at(T new_value, P base, ptrdiff_t offset, T compare_value) { + return cas_at_decay_types::value, P, T>(new_value, base, offset, compare_value); + } + + template + inline T swap(T new_value, P* addr) { + return swap_decay_types::value, P, T>(new_value, addr); + } + + template + inline T swap_at(T new_value, P base, ptrdiff_t offset) { + return swap_at_decay_types::value, P, T>(new_value, base, offset); + } + + template + inline bool copy(arrayOop src_obj, arrayOop dst_obj, T *src, T *dst, size_t length) { + return copy_decay_types::value, T>(src_obj, dst_obj, src, dst, length); + } + + template + inline void clone(oop src, oop dst, size_t size) { + BuildtimeDispatch::value>::clone(src, dst, size); + } + + template + typename AccessFunctionTypes::store_func_t RuntimeDispatch::_store_func = &store_init; + + template + typename AccessFunctionTypes::store_at_func_t RuntimeDispatch::_store_at_func = &store_at_init; + + template + typename AccessFunctionTypes::load_func_t RuntimeDispatch::_load_func = &load_init; + + template + typename AccessFunctionTypes::load_at_func_t RuntimeDispatch::_load_at_func = &load_at_init; + + template + typename AccessFunctionTypes::cas_func_t RuntimeDispatch::_cas_func = &cas_init; + + template + typename AccessFunctionTypes::cas_at_func_t RuntimeDispatch::_cas_at_func = &cas_at_init; + + template + typename AccessFunctionTypes::swap_func_t RuntimeDispatch::_swap_func = &swap_init; + + template + typename AccessFunctionTypes::swap_at_func_t RuntimeDispatch::_swap_at_func = &swap_at_init; + + template + typename AccessFunctionTypes::copy_func_t RuntimeDispatch::_copy_func = ©_init; + + template + typename CloneRuntimeDispatch::clone_func_t CloneRuntimeDispatch::_clone_func = &clone_init; +} + +template +template +inline typename EnableIf::value, T>::type +BasicAccessBarrier::decode_internal(typename EncodedType::type value) { + if (DecoratorTest::HAS_VALUE_NOT_NULL) { + return oopDesc::decode_heap_oop_not_null(value); + } else { + return oopDesc::decode_heap_oop(value); + } +} + +template +template +inline typename EnableIf::value, + typename EncodedType::type>::type +BasicAccessBarrier::encode_internal(T value) { + if (DecoratorTest::HAS_VALUE_NOT_NULL) { + return oopDesc::encode_heap_oop_not_null(value); + } else { + return oopDesc::encode_heap_oop(value); + } +} + +template +template +inline void BasicAccessBarrier::oop_store(void* addr, T value) { + typedef typename EncodedType::type Encoded; + Encoded encoded = encode(value); + Raw::template store((Encoded*)addr, encoded); +} + +template +template +inline void BasicAccessBarrier::oop_store_at(void* base, ptrdiff_t offset, T value) { + oop_store(field_addr(base, offset), value); +} + +template +template +inline T BasicAccessBarrier::oop_load(void* addr) { + typedef typename EncodedType::type Encoded; + Encoded encoded = Raw::template load((Encoded*)addr); + return decode(encoded); +} + +template +template +inline T BasicAccessBarrier::oop_load_at(void* base, ptrdiff_t offset) { + return oop_load(field_addr(base, offset)); +} + +template +template +inline T BasicAccessBarrier::oop_cas(T new_value, void* addr, T compare_value) { + typedef typename EncodedType::type Encoded; + Encoded encoded_new = encode(new_value); + Encoded encoded_compare = encode(compare_value); + Encoded encoded_result = Raw::template cas(encoded_new, (Encoded*)addr, encoded_compare); + return decode(encoded_result); +} + +template +template +inline T BasicAccessBarrier::oop_cas_at(T new_value, void* base, ptrdiff_t offset, T compare_value) { + return oop_cas(new_value, field_addr(base, offset), compare_value); +} + +template +template +inline T BasicAccessBarrier::oop_swap(T new_value, void* addr) { + typedef typename EncodedType::type Encoded; + Encoded encoded_new = encode(new_value); + Encoded encoded_result = Raw::template swap(encoded_new, (Encoded*)addr); + return decode(encoded_result); +} + +template +template +inline T BasicAccessBarrier::oop_swap_at(T new_value, void* base, ptrdiff_t offset) { + return oop_swap(new_value, field_addr(base, offset)); +} + +template +template +inline bool BasicAccessBarrier::oop_copy(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { + if (IsSame::value) { + if (DecoratorTest::NEEDS_OOP_COMPRESS) { + return Raw::template copy((narrowOop*)src, (narrowOop*)dst, length); + } else { + return Raw::template copy((oop*)src, (oop*)dst, length); + } + } else { + return Raw::template copy(src, dst, length); + } +} + +template +inline void BasicAccessBarrier::clone(oop src, oop dst, size_t size) { + Raw::clone(src, dst, size); +} + +template +template +inline typename EnableIf::value, void>::type +RawAccessBarrier::atomic_store(void* addr, T value) { + Atomic::store_ptr((void*)value, (volatile void*)addr); +} + +template +template +inline typename EnableIf::value, void>::type +RawAccessBarrier::atomic_store(void* addr, T value) { + Atomic::store(IntegerType::cast_to_signed(value), (volatile typename IntegerType::signed_type*)addr); +} + +template +template +inline typename EnableIf::value, void>::type +RawAccessBarrier::release_store(void* addr, T value) { + OrderAccess::release_store_ptr((volatile void*)addr, (void*)value); +} + +template +template +inline typename EnableIf::value, void>::type +RawAccessBarrier::release_store(void* addr, T value) { + OrderAccess::release_store((volatile typename IntegerType::signed_type*)addr, IntegerType::cast_to_signed(value)); +} + +template +template +typename EnableIf::value, void>::type +RawAccessBarrier::release_store_fence(void* addr, T value) { + OrderAccess::release_store_ptr_fence((volatile void*)addr, (void*)value); +} + +template +template +inline typename EnableIf::value, void>::type +RawAccessBarrier::release_store_fence(void* addr, T value) { + OrderAccess::release_store_fence((volatile typename IntegerType::signed_type*)addr, IntegerType::cast_to_signed(value)); +} + +template +template +inline typename EnableIf::value, T>::type +RawAccessBarrier::atomic_load(void* addr) { + return (T)Atomic::load_ptr((volatile void*)addr); +} + +template +template +inline typename EnableIf::value, T>::type +RawAccessBarrier::atomic_load(void* addr) { + return (T)Atomic::load((volatile typename IntegerType::signed_type*)addr); +} + +template +template +inline typename EnableIf::value, T>::type +RawAccessBarrier::load_acquire(void* addr) { + return (T)OrderAccess::load_ptr_acquire((volatile void*)addr); +} + +template +template +inline typename EnableIf::value, T>::type +RawAccessBarrier::load_acquire(void* addr) { + return (T)OrderAccess::load_acquire((volatile typename IntegerType::signed_type*)addr); +} + +template +template +inline typename EnableIf::value, T>::type +RawAccessBarrier::fence_load_acquire(void* addr) { + if (support_IRIW_for_not_multiple_copy_atomic_cpu) { + OrderAccess::fence(); + } + return (T)OrderAccess::load_ptr_acquire((volatile void*)addr); +} + +template +template +inline typename EnableIf::value, T>::type +RawAccessBarrier::fence_load_acquire(void* addr) { + if (support_IRIW_for_not_multiple_copy_atomic_cpu) { + OrderAccess::fence(); + } + return (T)OrderAccess::load_acquire((volatile typename IntegerType::signed_type*)addr); +} + +template +template +inline typename EnableIf::value, T>::type +RawAccessBarrier::cas_relaxed(T new_value, void* addr, T compare_value) { + return (T)Atomic::cmpxchg_ptr((void*)new_value, + (volatile void*)addr, + (void*)compare_value, + memory_order_relaxed); +} + +template +template +inline typename EnableIf::value, T>::type +RawAccessBarrier::cas_relaxed(T new_value, void* addr, T compare_value) { + return (T)Atomic::cmpxchg((typename IntegerType::signed_type)new_value, + (volatile typename IntegerType::signed_type*)addr, + (typename IntegerType::signed_type)compare_value, + memory_order_relaxed); +} + +template +template +inline typename EnableIf::value, T>::type +RawAccessBarrier::cas_seq_cst(T new_value, void* addr, T compare_value) { + return (T)Atomic::cmpxchg_ptr((void*)new_value, + (volatile void*)addr, + (void*)compare_value, + memory_order_conservative); +} + +template +template +inline typename EnableIf::value, T>::type +RawAccessBarrier::cas_seq_cst(T new_value, void* addr, T compare_value) { + return (T)Atomic::cmpxchg((typename IntegerType::signed_type)new_value, + (volatile typename IntegerType::signed_type*)addr, + (typename IntegerType::signed_type)compare_value, + memory_order_conservative); +} + +template +template +inline typename EnableIf::value, T>::type +RawAccessBarrier::swap_seq_cst(T new_value, void* addr) { + return (T)Atomic::xchg_ptr((void*)new_value, + (volatile void*)addr); +} + +template +template +inline typename EnableIf::value, T>::type +RawAccessBarrier::swap_seq_cst(T new_value, void* addr) { + return (T)Atomic::xchg((typename IntegerType::signed_type)new_value, + (volatile typename IntegerType::signed_type*)addr); +} + +template +template +inline typename EnableIf::value, T>::type +RawAccessBarrier::load_maybe_locked(void* addr) { + STATIC_ASSERT(DecoratorTest::HAS_ACCESS_ON_ANONYMOUS); // why else? + if (AccessInternal::wide_atomic_needs_locking()) { + return load_not_locked(addr); + } else { + return (T)AccessInternal::load_locked(addr); + } +} + +template +template +inline typename EnableIf::value, void>::type +RawAccessBarrier::store_maybe_locked(void* addr, T value) { + STATIC_ASSERT(DecoratorTest::HAS_ACCESS_ON_ANONYMOUS); // why else? + if (AccessInternal::wide_atomic_needs_locking()) { + store_not_locked(addr, value); + } else { + AccessInternal::store_locked(addr, IntegerType::cast_to_signed(value)); + } +} + +template +template +inline typename EnableIf::value, T>::type +RawAccessBarrier::swap_maybe_locked(T new_value, void* addr) { + STATIC_ASSERT(DecoratorTest::HAS_ACCESS_ON_ANONYMOUS); // why else? + if (AccessInternal::wide_atomic_needs_locking()) { + return swap_not_locked(new_value, addr); + } else { + return (T)AccessInternal::swap_locked(IntegerType::cast_to_signed(new_value), addr); + } +} + +template +template +inline typename EnableIf::value, T>::type +RawAccessBarrier::cas_maybe_locked(T new_value, void* addr, T compare_value) { + STATIC_ASSERT(DecoratorTest::HAS_ACCESS_ON_ANONYMOUS); // why else? + if (AccessInternal::wide_atomic_needs_locking()) { + return cas_not_locked(new_value, addr, compare_value); + } else { + return (T)AccessInternal::cas_locked(IntegerType::cast_to_signed(new_value), addr, + IntegerType::cast_to_signed(compare_value)); + } +} + +class RawAccessBarrierCopy: public AllStatic { +public: + template + static inline typename EnableIf::HAS_VALUE_IS_OOP && + !IsSame::value, void>::type + copy(T* src, T* dst, size_t length) { + if (DecoratorTest::HAS_COPY_ARRAYOF) { + AccessInternal::copy_arrayof_conjoint_oops((void*)src, (void*)dst, length); + } else { + AccessInternal::copy_conjoint_oops((void*)src, (void*)dst, length); + } + } + + template + static inline typename EnableIf::HAS_VALUE_IS_OOP || + IsSame::value, void>::type + copy(T* src, T* dst, size_t length) { + if (DecoratorTest::HAS_DEST_CONJOINT) { + if (DecoratorTest::HAS_ACCESS_ATOMIC) { + AccessInternal::copy_conjoint_memory_atomic((void*)src, (void*)dst, sizeof(T) * length); + } else { + AccessInternal::copy_conjoint_jbytes((void*)src, (void*)dst, sizeof(T) * length); + } + } else { + if (DecoratorTest::HAS_ACCESS_ATOMIC) { + AccessInternal::copy_conjoint_memory_atomic((void*)src, (void*)dst, sizeof(T) * length); + } else if (sizeof(T) == HeapWordSize) { + AccessInternal::copy_disjoint_words((void*)src, (void*)dst, sizeof(T) * length); + } else { + AccessInternal::copy_conjoint_jbytes((void*)src, (void*)dst, sizeof(T) * length); + } + } + } +}; + +template +template +inline typename EnableIf::value, bool>::type +RawAccessBarrier::copy(T* src, T* dst, size_t length) { + RawAccessBarrierCopy::copy(src, dst, length); + return true; +} + +template +inline void RawAccessBarrier::clone(oop src, oop dst, size_t size) { + assert(MinObjAlignmentInBytes >= BytesPerLong, "objects misaligned"); + AccessInternal::copy_conjoint_jlongs_atomic((void*)src, (void*)dst, + (size_t)align_object_size(size) / HeapWordsPerLong); + // Clear the header + dst->init_mark(); +} + +namespace AccessInternal { + // The first time a barrier needs to be resolved at runtime, it needs + // to link it against the GC being used to patch a function pointer + // directing subsequent memory accesses to the resolved barrier + template + void* AccessBarrierResolver::resolve_barrier() { + return BarrierSet::barrier_set()->resolve_barrier(); + } + + template + void* CloneAccessBarrierResolver::resolve_barrier() { + return BarrierSet::barrier_set()->resolve_clone_barrier(); + } + + template + class PostRTDispatch: public AllStatic { + enum { + resolve_compressed_oops = type == BARRIER_COPY && DecoratorTest::HAS_VALUE_IS_OOP && + IsSame::value + }; + + template + static typename EnableIf::type resolve_barrier_internal() { + if (DecoratorTest::NEEDS_OOP_COMPRESS) { + return DispatcherFactory::resolve_barrier_gc(); + } else { + return DispatcherFactory::resolve_barrier_gc(); + } + } + + template + static typename EnableIf::type resolve_barrier_internal() { + return DispatcherFactory::resolve_barrier_gc(); + } + public: + static void* resolve_barrier() { + return resolve_barrier_internal(); + } + }; + + template + inline void* DispatcherFactory::resolve_barrier_post_rt() { + return PostRTDispatch::resolve_barrier(); + } + + template + template + inline void BuildtimeDispatch::store(void* addr, T value) { + const DecoratorSet expanded_decorators = decorators | BT_BUILDTIME_DECORATORS | BT_HAS_BUILDTIME_DECORATOR; + PreRuntimeDispatch::template store(addr, value); + } + + template + template + inline void BuildtimeDispatch::store_at(void* base, ptrdiff_t offset, T value) { + const DecoratorSet expanded_decorators = decorators | BT_BUILDTIME_DECORATORS | BT_HAS_BUILDTIME_DECORATOR; + PreRuntimeDispatch::template store_at(base, offset, value); + } + + template + template + inline T BuildtimeDispatch::load(void* addr) { + const DecoratorSet expanded_decorators = decorators | BT_BUILDTIME_DECORATORS | BT_HAS_BUILDTIME_DECORATOR; + return PreRuntimeDispatch::template load(addr); + } + + template + template + inline T BuildtimeDispatch::load_at(void* base, ptrdiff_t offset) { + const DecoratorSet expanded_decorators = decorators | BT_BUILDTIME_DECORATORS | BT_HAS_BUILDTIME_DECORATOR; + return PreRuntimeDispatch::template load_at(base, offset); + } + + template + template + inline T BuildtimeDispatch::cas(T new_value, void* addr, T compare_value) { + const DecoratorSet expanded_decorators = decorators | BT_BUILDTIME_DECORATORS | BT_HAS_BUILDTIME_DECORATOR; + return PreRuntimeDispatch::template cas(new_value, addr, compare_value); + } + + template + template + inline T BuildtimeDispatch::cas_at(T new_value, void* base, ptrdiff_t offset, T compare_value) { + const DecoratorSet expanded_decorators = decorators | BT_BUILDTIME_DECORATORS | BT_HAS_BUILDTIME_DECORATOR; + return PreRuntimeDispatch::template cas_at(new_value, base, offset, compare_value); + } + + template + template + inline T BuildtimeDispatch::swap(T new_value, void* addr) { + const DecoratorSet expanded_decorators = decorators | BT_BUILDTIME_DECORATORS | BT_HAS_BUILDTIME_DECORATOR; + return PreRuntimeDispatch::template swap(new_value, addr); + } + + template + template + inline T BuildtimeDispatch::swap_at(T new_value, void* base, ptrdiff_t offset) { + const DecoratorSet expanded_decorators = decorators | BT_BUILDTIME_DECORATORS | BT_HAS_BUILDTIME_DECORATOR; + return PreRuntimeDispatch::template swap_at(new_value, base, offset); + } + + template + template + inline bool BuildtimeDispatch::copy(arrayOop src_obj, arrayOop dst_obj, T *src, T* dst, size_t length) { + const DecoratorSet expanded_decorators = decorators | BT_BUILDTIME_DECORATORS | BT_HAS_BUILDTIME_DECORATOR; + return PreRuntimeDispatch::template copy(src_obj, dst_obj, src, dst, length); + } + + template + inline void BuildtimeDispatch::clone(oop src, oop dst, size_t size) { + const DecoratorSet expanded_decorators = decorators | BT_BUILDTIME_DECORATORS | BT_HAS_BUILDTIME_DECORATOR; + PreRuntimeDispatch::template clone(src, dst, size); + } + + template + inline void store_at_reduce_types(P base, ptrdiff_t offset, T value) { + const DecoratorSet expanded_decorators = DecoratorFixup::value; + const DecoratorSet final_decorators = expanded_decorators | + ((DecoratorTest::HAS_VALUE_IS_OOP && + !DecoratorTest::HAS_ACCESS_ON_ROOT) ? + GC_CONVERT_COMPRESSED_OOP : EMPTY_DECORATOR); + BuildtimeDispatch::template store_at((void*)base, offset, value); + } + + template + inline T DispatchLoadAtReduceTypes::load_at(P base, ptrdiff_t offset) { + const DecoratorSet expanded_decorators = DecoratorFixup::value; + const DecoratorSet final_decorators = expanded_decorators | + ((DecoratorTest::HAS_VALUE_IS_OOP && + !DecoratorTest::HAS_ACCESS_ON_ROOT) ? + GC_CONVERT_COMPRESSED_OOP : EMPTY_DECORATOR); + return BuildtimeDispatch::template load_at((void*)base, offset); + } + + template + inline T cas_at_reduce_types(T new_value, P base, ptrdiff_t offset, T compare_value) { + const DecoratorSet expanded_decorators = DecoratorFixup::value; + const DecoratorSet final_decorators = expanded_decorators | + ((DecoratorTest::HAS_VALUE_IS_OOP && + !DecoratorTest::HAS_ACCESS_ON_ROOT) ? + GC_CONVERT_COMPRESSED_OOP : EMPTY_DECORATOR); + return BuildtimeDispatch::template cas_at(new_value, (void*)base, offset, compare_value); + } + + template + inline T swap_at_reduce_types(T new_value, P base, ptrdiff_t offset) { + const DecoratorSet expanded_decorators = DecoratorFixup::value; + const DecoratorSet final_decorators = expanded_decorators | + ((DecoratorTest::HAS_VALUE_IS_OOP && + !DecoratorTest::HAS_ACCESS_ON_ROOT) ? + GC_CONVERT_COMPRESSED_OOP : EMPTY_DECORATOR); + return BuildtimeDispatch::template swap_at(new_value, (void*)base, offset); + } +} + +#endif // SHARE_VM_RUNTIME_ACCESS_INLINE_HPP