< prev index next >

src/hotspot/share/oops/accessBackend.hpp

Print this page
*** 27,10 ***
--- 27,11 ---
  
  #include "gc/shared/barrierSetConfig.hpp"
  #include "memory/allocation.hpp"
  #include "metaprogramming/enableIf.hpp"
  #include "oops/accessDecorators.hpp"
+ #include "oops/inlineKlass.hpp"
  #include "oops/oopsHierarchy.hpp"
  #include "runtime/globals.hpp"
  #include "utilities/debug.hpp"
  #include "utilities/globalDefinitions.hpp"
  

*** 43,10 ***
--- 44,18 ---
    static const bool needs_oop_compress = HasDecorator<decorators, INTERNAL_CONVERT_COMPRESSED_OOP>::value &&
                                           HasDecorator<decorators, INTERNAL_RT_USE_COMPRESSED_OOPS>::value;
    using type = std::conditional_t<needs_oop_compress, narrowOop, oop>;
  };
  
+ // This meta-function returns either oop or narrowOop depending on whether
+ // a back-end needs to consider compressed oops types or not.
+ template <DecoratorSet decorators>
+ struct ValueOopType: AllStatic {
+   static const bool needs_oop_compress = HasDecorator<decorators, INTERNAL_RT_USE_COMPRESSED_OOPS>::value;
+   using type = std::conditional_t<needs_oop_compress, narrowOop, oop>;
+ };
+ 
  namespace AccessInternal {
    enum BarrierType {
      BARRIER_STORE,
      BARRIER_STORE_AT,
      BARRIER_LOAD,

*** 54,11 ***
      BARRIER_ATOMIC_CMPXCHG,
      BARRIER_ATOMIC_CMPXCHG_AT,
      BARRIER_ATOMIC_XCHG,
      BARRIER_ATOMIC_XCHG_AT,
      BARRIER_ARRAYCOPY,
!     BARRIER_CLONE
    };
  
    template <DecoratorSet decorators, typename T>
    struct MustConvertCompressedOop: public std::integral_constant<bool,
      HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value &&
--- 63,12 ---
      BARRIER_ATOMIC_CMPXCHG,
      BARRIER_ATOMIC_CMPXCHG_AT,
      BARRIER_ATOMIC_XCHG,
      BARRIER_ATOMIC_XCHG_AT,
      BARRIER_ARRAYCOPY,
!     BARRIER_CLONE,
+     BARRIER_VALUE_COPY
    };
  
    template <DecoratorSet decorators, typename T>
    struct MustConvertCompressedOop: public std::integral_constant<bool,
      HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value &&

*** 91,19 ***
      typedef T (*load_func_t)(void* addr);
      typedef void (*store_func_t)(void* addr, T value);
      typedef T (*atomic_cmpxchg_func_t)(void* addr, T compare_value, T new_value);
      typedef T (*atomic_xchg_func_t)(void* addr, T new_value);
  
!     typedef bool (*arraycopy_func_t)(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
                                       arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                                       size_t length);
      typedef void (*clone_func_t)(oop src, oop dst, size_t size);
    };
  
    template <DecoratorSet decorators>
    struct AccessFunctionTypes<decorators, void> {
!     typedef bool (*arraycopy_func_t)(arrayOop src_obj, size_t src_offset_in_bytes, void* src,
                                       arrayOop dst_obj, size_t dst_offset_in_bytes, void* dst,
                                       size_t length);
    };
  
    template <DecoratorSet decorators, typename T, BarrierType barrier> struct AccessFunction {};
--- 101,20 ---
      typedef T (*load_func_t)(void* addr);
      typedef void (*store_func_t)(void* addr, T value);
      typedef T (*atomic_cmpxchg_func_t)(void* addr, T compare_value, T new_value);
      typedef T (*atomic_xchg_func_t)(void* addr, T new_value);
  
!     typedef void (*arraycopy_func_t)(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
                                       arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                                       size_t length);
      typedef void (*clone_func_t)(oop src, oop dst, size_t size);
+     typedef void (*value_copy_func_t)(void* src, void* dst, InlineKlass* md, LayoutKind lk);
    };
  
    template <DecoratorSet decorators>
    struct AccessFunctionTypes<decorators, void> {
!     typedef void (*arraycopy_func_t)(arrayOop src_obj, size_t src_offset_in_bytes, void* src,
                                       arrayOop dst_obj, size_t dst_offset_in_bytes, void* dst,
                                       size_t length);
    };
  
    template <DecoratorSet decorators, typename T, BarrierType barrier> struct AccessFunction {};

*** 121,10 ***
--- 132,11 ---
    ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_ATOMIC_CMPXCHG_AT, atomic_cmpxchg_at_func_t);
    ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_ATOMIC_XCHG, atomic_xchg_func_t);
    ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_ATOMIC_XCHG_AT, atomic_xchg_at_func_t);
    ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_ARRAYCOPY, arraycopy_func_t);
    ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_CLONE, clone_func_t);
+   ACCESS_GENERATE_ACCESS_FUNCTION(BARRIER_VALUE_COPY, value_copy_func_t);
  #undef ACCESS_GENERATE_ACCESS_FUNCTION
  
    template <DecoratorSet decorators, typename T, BarrierType barrier_type>
    typename AccessFunction<decorators, T, barrier_type>::type resolve_barrier();
  

*** 146,10 ***
--- 158,12 ---
    void arraycopy_conjoint(T* src, T* dst, size_t length);
    template<typename T>
    void arraycopy_arrayof_conjoint(T* src, T* dst, size_t length);
    template<typename T>
    void arraycopy_conjoint_atomic(T* src, T* dst, size_t length);
+ 
+   void value_copy_internal(void* src, void* dst, size_t length);
  }
  
  // This mask specifies what decorators are relevant for raw accesses. When passing
  // accesses to the raw layer, irrelevant decorators are removed.
  const DecoratorSet RAW_DECORATOR_MASK = INTERNAL_DECORATOR_MASK | MO_DECORATOR_MASK |

*** 285,11 ***
    static inline T atomic_xchg(void* addr, T new_value) {
      return atomic_xchg_internal<decorators>(addr, new_value);
    }
  
    template <typename T>
!   static bool arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
                          arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                          size_t length);
  
    template <typename T>
    static void oop_store(void* addr, T value);
--- 299,11 ---
    static inline T atomic_xchg(void* addr, T new_value) {
      return atomic_xchg_internal<decorators>(addr, new_value);
    }
  
    template <typename T>
!   static void arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
                          arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                          size_t length);
  
    template <typename T>
    static void oop_store(void* addr, T value);

*** 330,15 ***
    static T atomic_xchg_at(oop base, ptrdiff_t offset, T new_value) {
      return atomic_xchg(field_addr(base, offset), new_value);
    }
  
    template <typename T>
!   static bool oop_arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
                              arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                              size_t length);
  
    static void clone(oop src, oop dst, size_t size);
  };
  
  namespace AccessInternal {
    DEBUG_ONLY(void check_access_thread_state());
  #define assert_access_thread_state() DEBUG_ONLY(check_access_thread_state())
--- 344,17 ---
    static T atomic_xchg_at(oop base, ptrdiff_t offset, T new_value) {
      return atomic_xchg(field_addr(base, offset), new_value);
    }
  
    template <typename T>
!   static void oop_arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
                              arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                              size_t length);
  
    static void clone(oop src, oop dst, size_t size);
+   static void value_copy(void* src, void* dst, InlineKlass* md, LayoutKind lk);
+ 
  };
  
  namespace AccessInternal {
    DEBUG_ONLY(void check_access_thread_state());
  #define assert_access_thread_state() DEBUG_ONLY(check_access_thread_state())

*** 504,15 ***
    template <DecoratorSet decorators, typename T>
    struct RuntimeDispatch<decorators, T, BARRIER_ARRAYCOPY>: AllStatic {
      typedef typename AccessFunction<decorators, T, BARRIER_ARRAYCOPY>::type func_t;
      static func_t _arraycopy_func;
  
!     static bool arraycopy_init(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
                                 arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                                 size_t length);
  
!     static inline bool arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
                                   arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                                   size_t length) {
        assert_access_thread_state();
        return _arraycopy_func(src_obj, src_offset_in_bytes, src_raw,
                               dst_obj, dst_offset_in_bytes, dst_raw,
--- 520,15 ---
    template <DecoratorSet decorators, typename T>
    struct RuntimeDispatch<decorators, T, BARRIER_ARRAYCOPY>: AllStatic {
      typedef typename AccessFunction<decorators, T, BARRIER_ARRAYCOPY>::type func_t;
      static func_t _arraycopy_func;
  
!     static void arraycopy_init(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
                                 arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                                 size_t length);
  
!     static inline void arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
                                   arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                                   size_t length) {
        assert_access_thread_state();
        return _arraycopy_func(src_obj, src_offset_in_bytes, src_raw,
                               dst_obj, dst_offset_in_bytes, dst_raw,

*** 531,10 ***
--- 547,22 ---
        assert_access_thread_state();
        _clone_func(src, dst, size);
      }
    };
  
+   template <DecoratorSet decorators, typename T>
+   struct RuntimeDispatch<decorators, T, BARRIER_VALUE_COPY>: AllStatic {
+     typedef typename AccessFunction<decorators, T, BARRIER_VALUE_COPY>::type func_t;
+     static func_t _value_copy_func;
+ 
+     static void value_copy_init(void* src, void* dst, InlineKlass* md, LayoutKind lk);
+ 
+     static inline void value_copy(void* src, void* dst, InlineKlass* md, LayoutKind lk) {
+       _value_copy_func(src, dst, md, lk);
+     }
+   };
+ 
    // Initialize the function pointers to point to the resolving function.
    template <DecoratorSet decorators, typename T>
    typename AccessFunction<decorators, T, BARRIER_STORE>::type
    RuntimeDispatch<decorators, T, BARRIER_STORE>::_store_func = &store_init;
  

*** 572,10 ***
--- 600,14 ---
  
    template <DecoratorSet decorators, typename T>
    typename AccessFunction<decorators, T, BARRIER_CLONE>::type
    RuntimeDispatch<decorators, T, BARRIER_CLONE>::_clone_func = &clone_init;
  
+   template <DecoratorSet decorators, typename T>
+   typename AccessFunction<decorators, T, BARRIER_VALUE_COPY>::type
+   RuntimeDispatch<decorators, T, BARRIER_VALUE_COPY>::_value_copy_func = &value_copy_init;
+ 
    // Step 3: Pre-runtime dispatching.
    // The PreRuntimeDispatch class is responsible for filtering the barrier strength
    // decorators. That is, for AS_RAW, it hardwires the accesses without a runtime
    // dispatch point. Otherwise it goes through a runtime check if hardwiring was
    // not possible.

*** 819,60 ***
        }
      }
  
      template <DecoratorSet decorators, typename T>
      inline static typename EnableIf<
!       HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value, bool>::type
      arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
                arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                size_t length) {
        typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw;
        if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) {
!         return Raw::oop_arraycopy(src_obj, src_offset_in_bytes, src_raw,
!                                   dst_obj, dst_offset_in_bytes, dst_raw,
!                                   length);
        } else {
!         return Raw::arraycopy(src_obj, src_offset_in_bytes, src_raw,
!                               dst_obj, dst_offset_in_bytes, dst_raw,
!                               length);
        }
      }
  
      template <DecoratorSet decorators, typename T>
      inline static typename EnableIf<
!       HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value, bool>::type
      arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
                arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                size_t length) {
        if (UseCompressedOops) {
          const DecoratorSet expanded_decorators = decorators | convert_compressed_oops;
!         return PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw,
!                                                                   dst_obj, dst_offset_in_bytes, dst_raw,
!                                                                   length);
        } else {
          const DecoratorSet expanded_decorators = decorators & ~convert_compressed_oops;
!         return PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw,
!                                                                   dst_obj, dst_offset_in_bytes, dst_raw,
!                                                                   length);
        }
      }
  
      template <DecoratorSet decorators, typename T>
      inline static typename EnableIf<
!       !HasDecorator<decorators, AS_RAW>::value, bool>::type
      arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
                arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                size_t length) {
        if (is_hardwired_primitive<decorators>()) {
          const DecoratorSet expanded_decorators = decorators | AS_RAW;
!         return PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw,
!                                                                   dst_obj, dst_offset_in_bytes, dst_raw,
!                                                                   length);
        } else {
!         return RuntimeDispatch<decorators, T, BARRIER_ARRAYCOPY>::arraycopy(src_obj, src_offset_in_bytes, src_raw,
!                                                                             dst_obj, dst_offset_in_bytes, dst_raw,
!                                                                             length);
        }
      }
  
      template <DecoratorSet decorators>
      inline static typename EnableIf<
--- 851,60 ---
        }
      }
  
      template <DecoratorSet decorators, typename T>
      inline static typename EnableIf<
!       HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value, void>::type
      arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
                arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                size_t length) {
        typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw;
        if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) {
!         Raw::oop_arraycopy(src_obj, src_offset_in_bytes, src_raw,
!                            dst_obj, dst_offset_in_bytes, dst_raw,
!                            length);
        } else {
!         Raw::arraycopy(src_obj, src_offset_in_bytes, src_raw,
!                        dst_obj, dst_offset_in_bytes, dst_raw,
!                        length);
        }
      }
  
      template <DecoratorSet decorators, typename T>
      inline static typename EnableIf<
!       HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value, void>::type
      arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
                arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                size_t length) {
        if (UseCompressedOops) {
          const DecoratorSet expanded_decorators = decorators | convert_compressed_oops;
!         PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw,
!                                                            dst_obj, dst_offset_in_bytes, dst_raw,
!                                                            length);
        } else {
          const DecoratorSet expanded_decorators = decorators & ~convert_compressed_oops;
!         PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw,
!                                                            dst_obj, dst_offset_in_bytes, dst_raw,
!                                                            length);
        }
      }
  
      template <DecoratorSet decorators, typename T>
      inline static typename EnableIf<
!       !HasDecorator<decorators, AS_RAW>::value, void>::type
      arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
                arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                size_t length) {
        if (is_hardwired_primitive<decorators>()) {
          const DecoratorSet expanded_decorators = decorators | AS_RAW;
!         PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw,
!                                                            dst_obj, dst_offset_in_bytes, dst_raw,
!                                                            length);
        } else {
!         RuntimeDispatch<decorators, T, BARRIER_ARRAYCOPY>::arraycopy(src_obj, src_offset_in_bytes, src_raw,
!                                                                      dst_obj, dst_offset_in_bytes, dst_raw,
!                                                                      length);
        }
      }
  
      template <DecoratorSet decorators>
      inline static typename EnableIf<

*** 886,10 ***
--- 918,26 ---
      inline static typename EnableIf<
        !HasDecorator<decorators, AS_RAW>::value>::type
      clone(oop src, oop dst, size_t size) {
        RuntimeDispatch<decorators, oop, BARRIER_CLONE>::clone(src, dst, size);
      }
+ 
+     template <DecoratorSet decorators>
+     inline static typename EnableIf<
+       HasDecorator<decorators, AS_RAW>::value>::type
+     value_copy(void* src, void* dst, InlineKlass* md, LayoutKind lk) {
+       typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw;
+       Raw::value_copy(src, dst, md, lk);
+     }
+ 
+     template <DecoratorSet decorators>
+     inline static typename EnableIf<
+       !HasDecorator<decorators, AS_RAW>::value>::type
+       value_copy(void* src, void* dst, InlineKlass* md, LayoutKind lk) {
+       const DecoratorSet expanded_decorators = decorators;
+       RuntimeDispatch<expanded_decorators, void*, BARRIER_VALUE_COPY>::value_copy(src, dst, md, lk);
+     }
    };
  
    // Step 2: Reduce types.
    // Enforce that for non-oop types, T and P have to be strictly the same.
    // P is the type of the address and T is the type of the values.

*** 1000,37 ***
      const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP;
      return PreRuntimeDispatch::load<expanded_decorators, oop>(addr);
    }
  
    template <DecoratorSet decorators, typename T>
!   inline bool arraycopy_reduce_types(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
                                       arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                                       size_t length) {
!     return PreRuntimeDispatch::arraycopy<decorators>(src_obj, src_offset_in_bytes, src_raw,
!                                                      dst_obj, dst_offset_in_bytes, dst_raw,
!                                                      length);
    }
  
    template <DecoratorSet decorators>
!   inline bool arraycopy_reduce_types(arrayOop src_obj, size_t src_offset_in_bytes, HeapWord* src_raw,
                                       arrayOop dst_obj, size_t dst_offset_in_bytes, HeapWord* dst_raw,
                                       size_t length) {
      const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP;
!     return PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw,
!                                                               dst_obj, dst_offset_in_bytes, dst_raw,
!                                                               length);
    }
  
    template <DecoratorSet decorators>
!   inline bool arraycopy_reduce_types(arrayOop src_obj, size_t src_offset_in_bytes, narrowOop* src_raw,
                                       arrayOop dst_obj, size_t dst_offset_in_bytes, narrowOop* dst_raw,
                                       size_t length) {
      const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP |
                                               INTERNAL_RT_USE_COMPRESSED_OOPS;
!     return PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw,
!                                                               dst_obj, dst_offset_in_bytes, dst_raw,
!                                                               length);
    }
  
    // Step 1: Set default decorators. This step remembers if a type was volatile
    // and then sets the MO_RELAXED decorator by default. Otherwise, a default
    // memory ordering is set for the access, and the implied decorator rules
--- 1048,37 ---
      const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP;
      return PreRuntimeDispatch::load<expanded_decorators, oop>(addr);
    }
  
    template <DecoratorSet decorators, typename T>
!   inline void arraycopy_reduce_types(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
                                       arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                                       size_t length) {
!     PreRuntimeDispatch::arraycopy<decorators>(src_obj, src_offset_in_bytes, src_raw,
!                                               dst_obj, dst_offset_in_bytes, dst_raw,
!                                               length);
    }
  
    template <DecoratorSet decorators>
!   inline void arraycopy_reduce_types(arrayOop src_obj, size_t src_offset_in_bytes, HeapWord* src_raw,
                                       arrayOop dst_obj, size_t dst_offset_in_bytes, HeapWord* dst_raw,
                                       size_t length) {
      const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP;
!     PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw,
!                                                        dst_obj, dst_offset_in_bytes, dst_raw,
!                                                        length);
    }
  
    template <DecoratorSet decorators>
!   inline void arraycopy_reduce_types(arrayOop src_obj, size_t src_offset_in_bytes, narrowOop* src_raw,
                                       arrayOop dst_obj, size_t dst_offset_in_bytes, narrowOop* dst_raw,
                                       size_t length) {
      const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP |
                                               INTERNAL_RT_USE_COMPRESSED_OOPS;
!     PreRuntimeDispatch::arraycopy<expanded_decorators>(src_obj, src_offset_in_bytes, src_raw,
!                                                        dst_obj, dst_offset_in_bytes, dst_raw,
!                                                        length);
    }
  
    // Step 1: Set default decorators. This step remembers if a type was volatile
    // and then sets the MO_RELAXED decorator by default. Otherwise, a default
    // memory ordering is set for the access, and the implied decorator rules

*** 1159,29 ***
                                                INTERNAL_CONVERT_COMPRESSED_OOP : DECORATORS_NONE)>::value;
      return PreRuntimeDispatch::atomic_xchg_at<expanded_decorators>(base, offset, new_decayed_value);
    }
  
    template <DecoratorSet decorators, typename T>
!   inline bool arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, const T* src_raw,
                          arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                          size_t length) {
      STATIC_ASSERT((HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value ||
                     (std::is_same<T, void>::value || std::is_integral<T>::value) ||
                      std::is_floating_point<T>::value)); // arraycopy allows type erased void elements
      using DecayedT = std::decay_t<T>;
      const DecoratorSet expanded_decorators = DecoratorFixup<decorators | IS_ARRAY | IN_HEAP>::value;
!     return arraycopy_reduce_types<expanded_decorators>(src_obj, src_offset_in_bytes, const_cast<DecayedT*>(src_raw),
!                                                        dst_obj, dst_offset_in_bytes, const_cast<DecayedT*>(dst_raw),
!                                                        length);
    }
  
    template <DecoratorSet decorators>
    inline void clone(oop src, oop dst, size_t size) {
      const DecoratorSet expanded_decorators = DecoratorFixup<decorators>::value;
      PreRuntimeDispatch::clone<expanded_decorators>(src, dst, size);
    }
  
    // Infer the type that should be returned from an Access::oop_load.
    template <typename P, DecoratorSet decorators>
    class OopLoadProxy: public StackObj {
    private:
      P *const _addr;
--- 1207,35 ---
                                                INTERNAL_CONVERT_COMPRESSED_OOP : DECORATORS_NONE)>::value;
      return PreRuntimeDispatch::atomic_xchg_at<expanded_decorators>(base, offset, new_decayed_value);
    }
  
    template <DecoratorSet decorators, typename T>
!   inline void arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, const T* src_raw,
                          arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
                          size_t length) {
      STATIC_ASSERT((HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value ||
                     (std::is_same<T, void>::value || std::is_integral<T>::value) ||
                      std::is_floating_point<T>::value)); // arraycopy allows type erased void elements
      using DecayedT = std::decay_t<T>;
      const DecoratorSet expanded_decorators = DecoratorFixup<decorators | IS_ARRAY | IN_HEAP>::value;
!     arraycopy_reduce_types<expanded_decorators>(src_obj, src_offset_in_bytes, const_cast<DecayedT*>(src_raw),
!                                                 dst_obj, dst_offset_in_bytes, const_cast<DecayedT*>(dst_raw),
!                                                 length);
    }
  
    template <DecoratorSet decorators>
    inline void clone(oop src, oop dst, size_t size) {
      const DecoratorSet expanded_decorators = DecoratorFixup<decorators>::value;
      PreRuntimeDispatch::clone<expanded_decorators>(src, dst, size);
    }
  
+   template <DecoratorSet decorators>
+   inline void value_copy(void* src, void* dst, InlineKlass* md, LayoutKind lk) {
+     const DecoratorSet expanded_decorators = DecoratorFixup<decorators>::value;
+     PreRuntimeDispatch::value_copy<expanded_decorators>(src, dst, md, lk);
+   }
+ 
    // Infer the type that should be returned from an Access::oop_load.
    template <typename P, DecoratorSet decorators>
    class OopLoadProxy: public StackObj {
    private:
      P *const _addr;
< prev index next >