# HG changeset patch # User rkennke # Date 1523468338 -7200 # Wed Apr 11 19:38:58 2018 +0200 # Node ID 16a329c7f25853294ab50ee30557b4a55b806fb5 # Parent 6a880e57685653c68836eb59ef2ba19ed313e6d3 8198285: More consistent Access API for arraycopy diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -310,7 +310,7 @@ Handle h_obj = basic_create(length, is_latin1, CHECK_NH); if (length > 0) { if (!has_multibyte) { - strncpy((char*)value(h_obj())->byte_at_addr(0), utf8_str, length); + HeapAccess<>::arraycopy(NULL, 0, reinterpret_cast(utf8_str), value(h_obj()), typeArrayOopDesc::element_offset(0), NULL, length); } else if (is_latin1) { UTF8::convert_to_unicode(utf8_str, value(h_obj())->byte_at_addr(0), length); } else { @@ -356,7 +356,7 @@ Handle h_obj = basic_create(length, is_latin1, CHECK_NH); if (length > 0) { if (!has_multibyte) { - strncpy((char*)value(h_obj())->byte_at_addr(0), utf8_str, length); + HeapAccess<>::arraycopy(NULL, 0, reinterpret_cast(utf8_str), value(h_obj()), typeArrayOopDesc::element_offset(0), NULL, length); } else if (is_latin1) { UTF8::convert_to_unicode(utf8_str, value(h_obj())->byte_at_addr(0), length); } else { diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -106,8 +106,8 @@ assert(src != NULL, "No Manifest data"); typeArrayOop buf = oopFactory::new_byteArray(size, CHECK_(empty)); typeArrayHandle bufhandle(THREAD, buf); - char* dst = (char*)(buf->byte_at_addr(0)); - memcpy(dst, src, (size_t)size); + HeapAccess<>::arraycopy(NULL, 0, reinterpret_cast(src), + buf, typeArrayOopDesc::element_offset(0), NULL, size); JavaValue result(T_VOID); JavaCalls::call_special(&result, bais, bais_klass, diff --git a/src/hotspot/share/gc/shared/barrierSet.hpp b/src/hotspot/share/gc/shared/barrierSet.hpp --- a/src/hotspot/share/gc/shared/barrierSet.hpp +++ b/src/hotspot/share/gc/shared/barrierSet.hpp @@ -183,8 +183,8 @@ } template - static void arraycopy_in_heap(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { - Raw::arraycopy(src_obj, dst_obj, src, dst, length); + static void arraycopy_in_heap(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) { + Raw::arraycopy(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length); } // Heap oop accesses. These accessors get resolved when @@ -227,8 +227,8 @@ } template - static bool oop_arraycopy_in_heap(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { - return Raw::oop_arraycopy(src_obj, dst_obj, src, dst, length); + static bool oop_arraycopy_in_heap(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) { + return Raw::oop_arraycopy(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length); } // Off-heap oop accesses. These accessors get resolved when diff --git a/src/hotspot/share/gc/shared/modRefBarrierSet.hpp b/src/hotspot/share/gc/shared/modRefBarrierSet.hpp --- a/src/hotspot/share/gc/shared/modRefBarrierSet.hpp +++ b/src/hotspot/share/gc/shared/modRefBarrierSet.hpp @@ -79,7 +79,7 @@ static oop oop_atomic_xchg_in_heap(oop new_value, T* addr); template - static bool oop_arraycopy_in_heap(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length); + static bool oop_arraycopy_in_heap(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 void clone_in_heap(oop src, oop dst, size_t size); diff --git a/src/hotspot/share/gc/shared/modRefBarrierSet.inline.hpp b/src/hotspot/share/gc/shared/modRefBarrierSet.inline.hpp --- a/src/hotspot/share/gc/shared/modRefBarrierSet.inline.hpp +++ b/src/hotspot/share/gc/shared/modRefBarrierSet.inline.hpp @@ -91,35 +91,39 @@ template template inline bool ModRefBarrierSet::AccessBarrier:: -oop_arraycopy_in_heap(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { +oop_arraycopy_in_heap(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) { BarrierSetT *bs = barrier_set_cast(barrier_set()); + src_raw = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw); + dst_raw = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw); + if (!HasDecorator::value) { // Optimized covariant case - bs->write_ref_array_pre(dst, length, + bs->write_ref_array_pre(dst_raw, length, HasDecorator::value); - Raw::oop_arraycopy(src_obj, dst_obj, src, dst, length); - bs->write_ref_array((HeapWord*)dst, length); + Raw::oop_arraycopy(NULL, 0, src_raw, NULL, 0, dst_raw, length); + bs->write_ref_array((HeapWord*)dst_raw, length); } else { + assert(dst_obj != NULL, "better have an actual oop"); Klass* bound = objArrayOop(dst_obj)->element_klass(); - T* from = src; + T* from = const_cast(src_raw); T* end = from + length; - for (T* p = dst; from < end; from++, p++) { + for (T* p = dst_raw; from < end; from++, p++) { T element = *from; if (oopDesc::is_instanceof_or_null(CompressedOops::decode(element), bound)) { bs->template write_ref_field_pre(p); *p = element; } else { // We must do a barrier to cover the partial copy. - const size_t pd = pointer_delta(p, dst, (size_t)heapOopSize); + const size_t pd = pointer_delta(p, dst_raw, (size_t)heapOopSize); // pointer delta is scaled to number of elements (length field in // objArrayOop) which we assume is 32 bit. assert(pd == (size_t)(int)pd, "length field overflow"); - bs->write_ref_array((HeapWord*)dst, pd); + bs->write_ref_array((HeapWord*)dst_raw, pd); return false; } } - bs->write_ref_array((HeapWord*)dst, length); + bs->write_ref_array((HeapWord*)dst_raw, length); } return true; } diff --git a/src/hotspot/share/oops/access.hpp b/src/hotspot/share/oops/access.hpp --- a/src/hotspot/share/oops/access.hpp +++ b/src/hotspot/share/oops/access.hpp @@ -156,10 +156,10 @@ } template - static inline void arraycopy(arrayOop src_obj, arrayOop dst_obj, T *src, T *dst, size_t length) { + static 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) { verify_decorators(); - AccessInternal::arraycopy(src_obj, dst_obj, src, dst, length); + AccessInternal::arraycopy(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length); } // Oop heap accesses @@ -194,9 +194,9 @@ } template - static inline bool oop_arraycopy(arrayOop src_obj, arrayOop dst_obj, T *src, T *dst, size_t length) { + static inline bool oop_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) { verify_decorators(); - return AccessInternal::arraycopy(src_obj, dst_obj, src, dst, length); + return AccessInternal::arraycopy(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length); } // Clone an object from src to dst diff --git a/src/hotspot/share/oops/access.inline.hpp b/src/hotspot/share/oops/access.inline.hpp --- a/src/hotspot/share/oops/access.inline.hpp +++ b/src/hotspot/share/oops/access.inline.hpp @@ -123,17 +123,16 @@ template struct PostRuntimeDispatch: public AllStatic { template - static bool access_barrier(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { - GCBarrierType::arraycopy_in_heap(src_obj, dst_obj, src, dst, length); + static bool access_barrier(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) { + GCBarrierType::arraycopy_in_heap(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length); return true; } template - static bool oop_access_barrier(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { + static bool oop_access_barrier(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) { typedef typename HeapOopType::type OopType; - return GCBarrierType::oop_arraycopy_in_heap(src_obj, dst_obj, - reinterpret_cast(src), - reinterpret_cast(dst), length); + return GCBarrierType::oop_arraycopy_in_heap(src_obj, src_offset_in_bytes, reinterpret_cast(src_raw), + dst_obj, dst_offset_in_bytes, reinterpret_cast(dst_raw), length); } }; @@ -337,10 +336,10 @@ } template - bool RuntimeDispatch::arraycopy_init(arrayOop src_obj, arrayOop dst_obj, T *src, T* dst, size_t length) { + bool RuntimeDispatch::arraycopy_init(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) { func_t function = BarrierResolver::resolve_barrier(); _arraycopy_func = function; - return function(src_obj, dst_obj, src, dst, length); + return function(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length); } template diff --git a/src/hotspot/share/oops/accessBackend.cpp b/src/hotspot/share/oops/accessBackend.cpp --- a/src/hotspot/share/oops/accessBackend.cpp +++ b/src/hotspot/share/oops/accessBackend.cpp @@ -105,11 +105,21 @@ } template<> + void arraycopy_conjoint(jboolean* src, jboolean* dst, size_t length) { + Copy::conjoint_jbytes(reinterpret_cast(src), reinterpret_cast(dst), length); + } + + template<> void arraycopy_conjoint(jbyte* src, jbyte* dst, size_t length) { Copy::conjoint_jbytes(src, dst, length); } template<> + void arraycopy_conjoint(jchar* src, jchar* dst, size_t length) { + Copy::conjoint_jshorts_atomic(reinterpret_cast(src), reinterpret_cast(dst), length); + } + + template<> void arraycopy_conjoint(jshort* src, jshort* dst, size_t length) { Copy::conjoint_jshorts_atomic(src, dst, length); } @@ -120,11 +130,21 @@ } template<> + void arraycopy_conjoint(jfloat* src, jfloat* dst, size_t length) { + Copy::conjoint_jints_atomic(reinterpret_cast(src), reinterpret_cast(dst), length); + } + + template<> void arraycopy_conjoint(jlong* src, jlong* dst, size_t length) { Copy::conjoint_jlongs_atomic(src, dst, length); } template<> + void arraycopy_conjoint(jdouble* src, jdouble* dst, size_t length) { + Copy::conjoint_jlongs_atomic(reinterpret_cast(src), reinterpret_cast(dst), length); + } + + template<> void arraycopy_arrayof_conjoint(jbyte* src, jbyte* dst, size_t length) { Copy::arrayof_conjoint_jbytes(reinterpret_cast(src), reinterpret_cast(dst), diff --git a/src/hotspot/share/oops/accessBackend.hpp b/src/hotspot/share/oops/accessBackend.hpp --- a/src/hotspot/share/oops/accessBackend.hpp +++ b/src/hotspot/share/oops/accessBackend.hpp @@ -110,7 +110,7 @@ typedef T (*atomic_cmpxchg_func_t)(T new_value, void* addr, T compare_value); typedef T (*atomic_xchg_func_t)(T new_value, void* addr); - typedef bool (*arraycopy_func_t)(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length); + typedef bool (*arraycopy_func_t)(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); typedef void (*clone_func_t)(oop src, oop dst, size_t size); typedef oop (*resolve_func_t)(oop obj); typedef bool (*equals_func_t)(oop o1, oop o2); @@ -118,7 +118,7 @@ template struct AccessFunctionTypes { - typedef bool (*arraycopy_func_t)(arrayOop src_obj, arrayOop dst_obj, void* src, void* dst, size_t length); + typedef bool (*arraycopy_func_t)(arrayOop src_obj, size_t src_offset_in_bytes, const void* src, arrayOop dst_obj, size_t dst_offset_in_bytes, void* dst, size_t length); }; template struct AccessFunction {}; @@ -353,7 +353,7 @@ } template - static bool arraycopy(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length); + static 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); template static void oop_store(void* addr, T value); @@ -396,7 +396,7 @@ } template - static bool oop_arraycopy(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length); + static bool oop_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 void clone(oop src, oop dst, size_t size); @@ -559,10 +559,10 @@ typedef typename AccessFunction::type func_t; static func_t _arraycopy_func; - static bool arraycopy_init(arrayOop src_obj, arrayOop dst_obj, T *src, T* dst, size_t length); + static bool arraycopy_init(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 inline bool arraycopy(arrayOop src_obj, arrayOop dst_obj, T *src, T* dst, size_t length) { - return _arraycopy_func(src_obj, dst_obj, src, dst, length); + static 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) { + return _arraycopy_func(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length); } }; @@ -900,37 +900,37 @@ template inline static typename EnableIf< HasDecorator::value && CanHardwireRaw::value, bool>::type - arraycopy(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { + 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) { typedef RawAccessBarrier Raw; if (HasDecorator::value) { - return Raw::oop_arraycopy(src_obj, dst_obj, src, dst, length); + 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, dst_obj, src, dst, length); + return Raw::arraycopy(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length); } } template inline static typename EnableIf< HasDecorator::value && !CanHardwireRaw::value, bool>::type - arraycopy(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { + 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) { if (UseCompressedOops) { const DecoratorSet expanded_decorators = decorators | convert_compressed_oops; - return PreRuntimeDispatch::arraycopy(src_obj, dst_obj, src, dst, length); + return PreRuntimeDispatch::arraycopy(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(src_obj, dst_obj, src, dst, length); + return PreRuntimeDispatch::arraycopy(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length); } } template inline static typename EnableIf< !HasDecorator::value, bool>::type - arraycopy(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { + 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) { if (is_hardwired_primitive()) { const DecoratorSet expanded_decorators = decorators | AS_RAW; - return PreRuntimeDispatch::arraycopy(src_obj, dst_obj, src, dst, length); + return PreRuntimeDispatch::arraycopy(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length); } else { - return RuntimeDispatch::arraycopy(src_obj, dst_obj, src, dst, length); + return RuntimeDispatch::arraycopy(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length); } } @@ -1117,21 +1117,21 @@ } template - inline bool arraycopy_reduce_types(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { - return PreRuntimeDispatch::arraycopy(src_obj, dst_obj, src, dst, length); + inline bool arraycopy_reduce_types(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) { + return PreRuntimeDispatch::arraycopy(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length); } template - inline bool arraycopy_reduce_types(arrayOop src_obj, arrayOop dst_obj, HeapWord* src, HeapWord* dst, size_t length) { + inline bool arraycopy_reduce_types(arrayOop src_obj, size_t src_offset_in_bytes, const 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(src_obj, dst_obj, src, dst, length); + return PreRuntimeDispatch::arraycopy(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length); } template - inline bool arraycopy_reduce_types(arrayOop src_obj, arrayOop dst_obj, narrowOop* src, narrowOop* dst, size_t length) { + inline bool arraycopy_reduce_types(arrayOop src_obj, size_t src_offset_in_bytes, const 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(src_obj, dst_obj, src, dst, length); + return PreRuntimeDispatch::arraycopy(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 @@ -1264,15 +1264,14 @@ } template - inline bool arraycopy(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { + 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::value || (IsSame::value || IsIntegral::value) || IsFloatingPoint::value)); // arraycopy allows type erased void elements typedef typename Decay::type DecayedT; const DecoratorSet expanded_decorators = DecoratorFixup::value; - return arraycopy_reduce_types(src_obj, dst_obj, - const_cast(src), - const_cast(dst), + return arraycopy_reduce_types(src_obj, src_offset_in_bytes, const_cast(src_raw), + dst_obj, dst_offset_in_bytes, const_cast(dst_raw), length); } diff --git a/src/hotspot/share/oops/accessBackend.inline.hpp b/src/hotspot/share/oops/accessBackend.inline.hpp --- a/src/hotspot/share/oops/accessBackend.inline.hpp +++ b/src/hotspot/share/oops/accessBackend.inline.hpp @@ -118,8 +118,8 @@ template template -inline bool RawAccessBarrier::oop_arraycopy(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { - return arraycopy(src_obj, dst_obj, src, dst, length); +inline bool RawAccessBarrier::oop_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) { + return arraycopy(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length); } template @@ -247,35 +247,43 @@ template static inline typename EnableIf< HasDecorator::value>::type - arraycopy(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { + 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) { + + src_raw = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw); + dst_raw = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw); + // We do not check for ARRAYCOPY_ATOMIC for oops, because they are unconditionally always atomic. if (HasDecorator::value) { - AccessInternal::arraycopy_arrayof_conjoint_oops(src, dst, length); + AccessInternal::arraycopy_arrayof_conjoint_oops(const_cast(src_raw), dst_raw, length); } else { typedef typename HeapOopType::type OopType; - AccessInternal::arraycopy_conjoint_oops(reinterpret_cast(src), - reinterpret_cast(dst), length); + AccessInternal::arraycopy_conjoint_oops(reinterpret_cast(const_cast(src_raw)), + reinterpret_cast(dst_raw), length); } } template static inline typename EnableIf< !HasDecorator::value>::type - arraycopy(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { + 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) { + + src_raw = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw); + dst_raw = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw); + if (HasDecorator::value) { - AccessInternal::arraycopy_arrayof_conjoint(src, dst, length); + AccessInternal::arraycopy_arrayof_conjoint(const_cast(src_raw), dst_raw, length); } else if (HasDecorator::value && sizeof(T) == HeapWordSize) { // There is only a disjoint optimization for word granularity copying if (HasDecorator::value) { - AccessInternal::arraycopy_disjoint_words_atomic(src, dst, length); + AccessInternal::arraycopy_disjoint_words_atomic(const_cast(src_raw), dst_raw, length); } else { - AccessInternal::arraycopy_disjoint_words(src, dst, length); + AccessInternal::arraycopy_disjoint_words(const_cast(src_raw), dst_raw, length); } } else { if (HasDecorator::value) { - AccessInternal::arraycopy_conjoint_atomic(src, dst, length); + AccessInternal::arraycopy_conjoint_atomic(const_cast(src_raw), dst_raw, length); } else { - AccessInternal::arraycopy_conjoint(src, dst, length); + AccessInternal::arraycopy_conjoint(const_cast(src_raw), dst_raw, length); } } } @@ -283,19 +291,23 @@ template static inline typename EnableIf< !HasDecorator::value>::type - arraycopy(arrayOop src_obj, arrayOop dst_obj, void* src, void* dst, size_t length) { + arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, const void* src_raw, arrayOop dst_obj, size_t dst_offset_in_bytes, void* dst_raw, size_t length) { + + src_raw = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw); + dst_raw = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw); + if (HasDecorator::value) { - AccessInternal::arraycopy_conjoint_atomic(src, dst, length); + AccessInternal::arraycopy_conjoint_atomic(const_cast(src_raw), dst_raw, length); } else { - AccessInternal::arraycopy_conjoint(src, dst, length); + AccessInternal::arraycopy_conjoint(const_cast(src_raw), dst_raw, length); } } }; template template -inline bool RawAccessBarrier::arraycopy(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { - RawAccessBarrierArrayCopy::arraycopy(src_obj, dst_obj, src, dst, length); +inline bool RawAccessBarrier::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) { + RawAccessBarrierArrayCopy::arraycopy(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length); return true; } diff --git a/src/hotspot/share/oops/arrayOop.hpp b/src/hotspot/share/oops/arrayOop.hpp --- a/src/hotspot/share/oops/arrayOop.hpp +++ b/src/hotspot/share/oops/arrayOop.hpp @@ -88,6 +88,18 @@ inline void* base(BasicType type) const; inline void* base_raw(BasicType type) const; // GC barrier invariant + template + static T* obj_offset_to_raw(arrayOop obj, size_t offset_in_bytes, T* raw) { + if (obj != NULL) { + assert(raw == NULL, "either raw or in-heap"); + char* base = reinterpret_cast((void*) obj); + raw = reinterpret_cast(base + offset_in_bytes); + } else { + assert(raw != NULL, "either raw or in-heap"); + } + return raw; + } + // Tells whether index is within bounds. bool is_within_bounds(int index) const { return 0 <= index && index < length(); } diff --git a/src/hotspot/share/oops/objArrayKlass.cpp b/src/hotspot/share/oops/objArrayKlass.cpp --- a/src/hotspot/share/oops/objArrayKlass.cpp +++ b/src/hotspot/share/oops/objArrayKlass.cpp @@ -218,23 +218,23 @@ } // Either oop or narrowOop depending on UseCompressedOops. -template void ObjArrayKlass::do_copy(arrayOop s, T* src, - arrayOop d, T* dst, int length, TRAPS) { +template void ObjArrayKlass::do_copy(arrayOop s, size_t src_offset, + arrayOop d, size_t dst_offset, int length, TRAPS) { if (oopDesc::equals(s, d)) { // since source and destination are equal we do not need conversion checks. assert(length > 0, "sanity check"); - HeapAccess<>::oop_arraycopy(s, d, src, dst, length); + HeapAccess<>::oop_arraycopy(s, src_offset, NULL, d, dst_offset, NULL, length); } else { // We have to make sure all elements conform to the destination array Klass* bound = ObjArrayKlass::cast(d->klass())->element_klass(); Klass* stype = ObjArrayKlass::cast(s->klass())->element_klass(); if (stype == bound || stype->is_subtype_of(bound)) { // elements are guaranteed to be subtypes, so no check necessary - HeapAccess::oop_arraycopy(s, d, src, dst, length); + HeapAccess::oop_arraycopy(s, src_offset, NULL, d, dst_offset, NULL, length); } else { // slow case: need individual subtype checks // note: don't use obj_at_put below because it includes a redundant store check - if (!HeapAccess::oop_arraycopy(s, d, src, dst, length)) { + if (!HeapAccess::oop_arraycopy(s, src_offset, NULL, d, dst_offset, NULL, length)) { THROW(vmSymbols::java_lang_ArrayStoreException()); } } @@ -267,13 +267,17 @@ return; } if (UseCompressedOops) { - narrowOop* const src = objArrayOop(s)->obj_at_addr(src_pos); - narrowOop* const dst = objArrayOop(d)->obj_at_addr(dst_pos); - do_copy(s, src, d, dst, length, CHECK); + size_t src_offset = (size_t) objArrayOopDesc::obj_at_offset(src_pos); + size_t dst_offset = (size_t) objArrayOopDesc::obj_at_offset(dst_pos); + assert(arrayOopDesc::obj_offset_to_raw(s, src_offset, NULL) == objArrayOop(s)->obj_at_addr(src_pos), "sanity"); + assert(arrayOopDesc::obj_offset_to_raw(d, dst_offset, NULL) == objArrayOop(d)->obj_at_addr(dst_pos), "sanity"); + do_copy(s, src_offset, d, dst_offset, length, CHECK); } else { - oop* const src = objArrayOop(s)->obj_at_addr(src_pos); - oop* const dst = objArrayOop(d)->obj_at_addr(dst_pos); - do_copy (s, src, d, dst, length, CHECK); + size_t src_offset = (size_t) objArrayOopDesc::obj_at_offset(src_pos); + size_t dst_offset = (size_t) objArrayOopDesc::obj_at_offset(dst_pos); + assert(arrayOopDesc::obj_offset_to_raw(s, src_offset, NULL) == objArrayOop(s)->obj_at_addr(src_pos), "sanity"); + assert(arrayOopDesc::obj_offset_to_raw(d, dst_offset, NULL) == objArrayOop(d)->obj_at_addr(dst_pos), "sanity"); + do_copy (s, src_offset, d, dst_offset, length, CHECK); } } diff --git a/src/hotspot/share/oops/objArrayKlass.hpp b/src/hotspot/share/oops/objArrayKlass.hpp --- a/src/hotspot/share/oops/objArrayKlass.hpp +++ b/src/hotspot/share/oops/objArrayKlass.hpp @@ -87,8 +87,9 @@ private: // Either oop or narrowOop depending on UseCompressedOops. // must be called from within ObjArrayKlass.cpp - template void do_copy(arrayOop s, T* src, arrayOop d, - T* dst, int length, TRAPS); + template void do_copy(arrayOop s, size_t src_offset, + arrayOop d, size_t dst_offset, + int length, TRAPS); protected: // Returns the ObjArrayKlass for n'th dimension. virtual Klass* array_klass_impl(bool or_null, int n, TRAPS); diff --git a/src/hotspot/share/oops/typeArrayKlass.cpp b/src/hotspot/share/oops/typeArrayKlass.cpp --- a/src/hotspot/share/oops/typeArrayKlass.cpp +++ b/src/hotspot/share/oops/typeArrayKlass.cpp @@ -152,9 +152,9 @@ // This is an attempt to make the copy_array fast. int l2es = log2_element_size(); int ihs = array_header_in_bytes() / wordSize; - void* src = (char*) (s->base(element_type())) + ((size_t)src_pos << l2es); - void* dst = (char*) (d->base(element_type())) + ((size_t)dst_pos << l2es); - HeapAccess::arraycopy(s, d, src, dst, (size_t)length << l2es); + size_t src_offset = arrayOopDesc::base_offset_in_bytes(element_type()) + ((size_t)src_pos << l2es); + size_t dst_offset = arrayOopDesc::base_offset_in_bytes(element_type()) + ((size_t)dst_pos << l2es); + HeapAccess::arraycopy(s, src_offset, NULL, d, dst_offset, NULL, (size_t)length << l2es); } diff --git a/src/hotspot/share/oops/typeArrayOop.hpp b/src/hotspot/share/oops/typeArrayOop.hpp --- a/src/hotspot/share/oops/typeArrayOop.hpp +++ b/src/hotspot/share/oops/typeArrayOop.hpp @@ -32,12 +32,22 @@ // It is used for arrays of {characters, singles, doubles, bytes, shorts, integers, longs} #include +namespace TypeToBT { + template BasicType to_basic_type(); + template<> inline BasicType to_basic_type() { return T_BOOLEAN; } + template<> inline BasicType to_basic_type() { return T_BYTE; } + template<> inline BasicType to_basic_type() { return T_CHAR; } + template<> inline BasicType to_basic_type() { return T_SHORT; } + template<> inline BasicType to_basic_type() { return T_INT; } + template<> inline BasicType to_basic_type() { return T_LONG; } + template<> inline BasicType to_basic_type() { return T_FLOAT; } + template<> inline BasicType to_basic_type() { return T_DOUBLE; } +}; + class typeArrayOopDesc : public arrayOopDesc { private: - template - static ptrdiff_t element_offset(BasicType bt, int index) { - return arrayOopDesc::base_offset_in_bytes(bt) + sizeof(T) * index; - } + template + static BasicType bt() { return TypeToBT::to_basic_type(); } protected: jchar* char_base() const; @@ -52,6 +62,11 @@ friend class TypeArrayKlass; public: + template + static ptrdiff_t element_offset(int index) { + return arrayOopDesc::base_offset_in_bytes(bt()) + sizeof(T) * index; + } + jbyte* byte_at_addr(int which) const; jboolean* bool_at_addr(int which) const; jchar* char_at_addr(int which) const; diff --git a/src/hotspot/share/oops/typeArrayOop.inline.hpp b/src/hotspot/share/oops/typeArrayOop.inline.hpp --- a/src/hotspot/share/oops/typeArrayOop.inline.hpp +++ b/src/hotspot/share/oops/typeArrayOop.inline.hpp @@ -90,92 +90,92 @@ } inline jbyte typeArrayOopDesc::byte_at(int which) const { - ptrdiff_t offset = element_offset(T_BYTE, which); + ptrdiff_t offset = element_offset(which); return HeapAccess::load_at(as_oop(), offset); } inline void typeArrayOopDesc::byte_at_put(int which, jbyte contents) { - ptrdiff_t offset = element_offset(T_BYTE, which); + ptrdiff_t offset = element_offset(which); HeapAccess::store_at(as_oop(), offset, contents); } inline jboolean typeArrayOopDesc::bool_at(int which) const { - ptrdiff_t offset = element_offset(T_BOOLEAN, which); + ptrdiff_t offset = element_offset(which); return HeapAccess::load_at(as_oop(), offset); } inline void typeArrayOopDesc::bool_at_put(int which, jboolean contents) { - ptrdiff_t offset = element_offset(T_BOOLEAN, which); + ptrdiff_t offset = element_offset(which); HeapAccess::store_at(as_oop(), offset, jboolean(contents & 1)); } inline jchar typeArrayOopDesc::char_at(int which) const { - ptrdiff_t offset = element_offset(T_CHAR, which); + ptrdiff_t offset = element_offset(which); return HeapAccess::load_at(as_oop(), offset); } inline void typeArrayOopDesc::char_at_put(int which, jchar contents) { - ptrdiff_t offset = element_offset(T_CHAR, which); + ptrdiff_t offset = element_offset(which); HeapAccess::store_at(as_oop(), offset, contents); } inline jint typeArrayOopDesc::int_at(int which) const { - ptrdiff_t offset = element_offset(T_INT, which); + ptrdiff_t offset = element_offset(which); return HeapAccess::load_at(as_oop(), offset); } inline void typeArrayOopDesc::int_at_put(int which, jint contents) { - ptrdiff_t offset = element_offset(T_INT, which); + ptrdiff_t offset = element_offset(which); HeapAccess::store_at(as_oop(), offset, contents); } inline jshort typeArrayOopDesc::short_at(int which) const { - ptrdiff_t offset = element_offset(T_SHORT, which); + ptrdiff_t offset = element_offset(which); return HeapAccess::load_at(as_oop(), offset); } inline void typeArrayOopDesc::short_at_put(int which, jshort contents) { - ptrdiff_t offset = element_offset(T_SHORT, which); + ptrdiff_t offset = element_offset(which); HeapAccess::store_at(as_oop(), offset, contents); } inline jushort typeArrayOopDesc::ushort_at(int which) const { - ptrdiff_t offset = element_offset(T_SHORT, which); + ptrdiff_t offset = element_offset(which); return HeapAccess::load_at(as_oop(), offset); } inline void typeArrayOopDesc::ushort_at_put(int which, jushort contents) { - ptrdiff_t offset = element_offset(T_SHORT, which); + ptrdiff_t offset = element_offset(which); HeapAccess::store_at(as_oop(), offset, contents); } inline jlong typeArrayOopDesc::long_at(int which) const { - ptrdiff_t offset = element_offset(T_LONG, which); + ptrdiff_t offset = element_offset(which); return HeapAccess::load_at(as_oop(), offset); } inline void typeArrayOopDesc::long_at_put(int which, jlong contents) { - ptrdiff_t offset = element_offset(T_LONG, which); + ptrdiff_t offset = element_offset(which); HeapAccess::store_at(as_oop(), offset, contents); } inline jfloat typeArrayOopDesc::float_at(int which) const { - ptrdiff_t offset = element_offset(T_FLOAT, which); + ptrdiff_t offset = element_offset(which); return HeapAccess::load_at(as_oop(), offset); } inline void typeArrayOopDesc::float_at_put(int which, jfloat contents) { - ptrdiff_t offset = element_offset(T_FLOAT, which); + ptrdiff_t offset = element_offset(which); HeapAccess::store_at(as_oop(), offset, contents); } inline jdouble typeArrayOopDesc::double_at(int which) const { - ptrdiff_t offset = element_offset(T_DOUBLE, which); + ptrdiff_t offset = element_offset(which); return HeapAccess::load_at(as_oop(), offset); } inline void typeArrayOopDesc::double_at_put(int which, jdouble contents) { - ptrdiff_t offset = element_offset(T_DOUBLE, which); + ptrdiff_t offset = element_offset(which); HeapAccess::store_at(as_oop(), offset, contents); } inline jbyte typeArrayOopDesc::byte_at_acquire(int which) const { - ptrdiff_t offset = element_offset(T_BYTE, which); + ptrdiff_t offset = element_offset(which); return HeapAccess::load_at(as_oop(), offset); } inline void typeArrayOopDesc::release_byte_at_put(int which, jbyte contents) { - ptrdiff_t offset = element_offset(T_BYTE, which); + ptrdiff_t offset = element_offset(which); HeapAccess::store_at(as_oop(), offset, contents); } @@ -184,20 +184,20 @@ // casting #ifdef _LP64 inline Symbol* typeArrayOopDesc::symbol_at(int which) const { - ptrdiff_t offset = element_offset(T_LONG, which); + ptrdiff_t offset = element_offset(which); return (Symbol*)(jlong) HeapAccess::load_at(as_oop(), offset); } inline void typeArrayOopDesc::symbol_at_put(int which, Symbol* contents) { - ptrdiff_t offset = element_offset(T_LONG, which); + ptrdiff_t offset = element_offset(which); HeapAccess::store_at(as_oop(), offset, (jlong)contents); } #else inline Symbol* typeArrayOopDesc::symbol_at(int which) const { - ptrdiff_t offset = element_offset(T_INT, which); + ptrdiff_t offset = element_offset(which); return (Symbol*)(jint) HeapAccess::load_at(as_oop(), offset); } inline void typeArrayOopDesc::symbol_at_put(int which, Symbol* contents) { - ptrdiff_t offset = element_offset(T_INT, which); + ptrdiff_t offset = element_offset(which); HeapAccess::store_at(as_oop(), offset, (jint)contents); } #endif // _LP64 diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp --- a/src/hotspot/share/opto/runtime.cpp +++ b/src/hotspot/share/opto/runtime.cpp @@ -397,9 +397,9 @@ ResourceMark rm; jint len = dims->length(); assert(len > 0, "Dimensions array should contain data"); - jint *j_dims = typeArrayOop(dims)->int_at_addr(0); jint *c_dims = NEW_RESOURCE_ARRAY(jint, len); - Copy::conjoint_jints_atomic(j_dims, c_dims, len); + HeapAccess<>::arraycopy(dims, typeArrayOopDesc::element_offset(0), NULL, + NULL, 0, c_dims, len); Handle holder(THREAD, elem_type->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(elem_type)->multi_allocate(len, c_dims, THREAD); diff --git a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp --- a/src/hotspot/share/prims/jni.cpp +++ b/src/hotspot/share/prims/jni.cpp @@ -2465,7 +2465,8 @@ if (buf != NULL) { if (s_len > 0) { if (!is_latin1) { - memcpy(buf, s_value->char_at_addr(0), sizeof(jchar)*s_len); + HeapAccess<>::arraycopy(s_value, (size_t) typeArrayOopDesc::element_offset(0), NULL, + NULL, 0, buf, s_len); } else { for (int i = 0; i < s_len; i++) { buf[i] = ((jchar) s_value->byte_at(i)) & 0xff; @@ -2721,7 +2722,8 @@ result = NEW_C_HEAP_ARRAY_RETURN_NULL(ElementType, len, mtInternal); \ if (result != NULL) { \ /* copy the array to the c chunk */ \ - memcpy(result, a->Tag##_at_addr(0), sizeof(ElementType)*len); \ + HeapAccess<>::arraycopy(a, typeArrayOopDesc::element_offset(0), NULL, \ + NULL, 0, result, len); \ if (isCopy) { \ *isCopy = JNI_TRUE; \ } \ @@ -2770,7 +2772,7 @@ int len = a->length(); \ if (len != 0) { /* Empty array: nothing to free or copy. */ \ if ((mode == 0) || (mode == JNI_COMMIT)) { \ - memcpy(a->Tag##_at_addr(0), buf, sizeof(ElementType)*len); \ + HeapAccess<>::arraycopy(NULL, 0, buf, a, typeArrayOopDesc::element_offset(0), NULL, len); \ } \ if ((mode == 0) || (mode == JNI_ABORT)) { \ FreeHeap(buf); \ @@ -2821,10 +2823,7 @@ THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \ } else { \ if (len > 0) { \ - int sc = TypeArrayKlass::cast(src->klass())->log2_element_size(); \ - memcpy((u_char*) buf, \ - (u_char*) src->Tag##_at_addr(start), \ - len << sc); \ + HeapAccess<>::arraycopy(src, typeArrayOopDesc::element_offset(start), NULL, NULL, 0, buf, len); \ } \ } \ JNI_END @@ -2871,10 +2870,7 @@ THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \ } else { \ if (len > 0) { \ - int sc = TypeArrayKlass::cast(dst->klass())->log2_element_size(); \ - memcpy((u_char*) dst->Tag##_at_addr(start), \ - (u_char*) buf, \ - len << sc); \ + HeapAccess<>::arraycopy(NULL, 0, buf, dst, typeArrayOopDesc::element_offset(start), NULL, len); \ } \ } \ JNI_END @@ -3110,7 +3106,8 @@ typeArrayOop s_value = java_lang_String::value(s); bool is_latin1 = java_lang_String::is_latin1(s); if (!is_latin1) { - memcpy(buf, s_value->char_at_addr(start), sizeof(jchar)*len); + HeapAccess<>::arraycopy(s_value, typeArrayOopDesc::element_offset(start), NULL, + NULL, 0, buf, len); } else { for (int i = 0; i < len; i++) { buf[i] = ((jchar) s_value->byte_at(i + start)) & 0xff; diff --git a/src/hotspot/share/prims/unsafe.cpp b/src/hotspot/share/prims/unsafe.cpp --- a/src/hotspot/share/prims/unsafe.cpp +++ b/src/hotspot/share/prims/unsafe.cpp @@ -762,8 +762,8 @@ // caller responsible to free it: *temp_alloc = class_bytes; - jbyte* array_base = typeArrayOop(JNIHandles::resolve_non_null(data))->byte_at_addr(0); - Copy::conjoint_jbytes(array_base, class_bytes, length); + HeapAccess<>::arraycopy(arrayOop(JNIHandles::resolve_non_null(data)), typeArrayOopDesc::element_offset(0), NULL, + NULL, 0, reinterpret_cast(class_bytes), length); objArrayHandle cp_patches_h; if (cp_patches_jh != NULL) { diff --git a/src/hotspot/share/runtime/stubRoutines.cpp b/src/hotspot/share/runtime/stubRoutines.cpp --- a/src/hotspot/share/runtime/stubRoutines.cpp +++ b/src/hotspot/share/runtime/stubRoutines.cpp @@ -410,7 +410,7 @@ SharedRuntime::_oop_array_copy_ctr++; // Slow-path oop array copy #endif // !PRODUCT assert(count != 0, "count should be non-zero"); - HeapAccess<>::oop_arraycopy(NULL, NULL, (HeapWord*)src, (HeapWord*)dest, count); + HeapAccess<>::oop_arraycopy(NULL, 0, (HeapWord*)src, NULL, 0, (HeapWord*)dest, count); JRT_END JRT_LEAF(void, StubRoutines::oop_copy_uninit(oop* src, oop* dest, size_t count)) @@ -418,7 +418,7 @@ SharedRuntime::_oop_array_copy_ctr++; // Slow-path oop array copy #endif // !PRODUCT assert(count != 0, "count should be non-zero"); - HeapAccess::oop_arraycopy(NULL, NULL, (HeapWord*)src, (HeapWord*)dest, count); + HeapAccess::oop_arraycopy(NULL, 0, (HeapWord*)src, NULL, 0, (HeapWord*)dest, count); JRT_END JRT_LEAF(void, StubRoutines::arrayof_jbyte_copy(HeapWord* src, HeapWord* dest, size_t count)) @@ -454,7 +454,7 @@ SharedRuntime::_oop_array_copy_ctr++; // Slow-path oop array copy #endif // !PRODUCT assert(count != 0, "count should be non-zero"); - HeapAccess::oop_arraycopy(NULL, NULL, src, dest, count); + HeapAccess::oop_arraycopy(NULL, 0, src, NULL, 0, dest, count); JRT_END JRT_LEAF(void, StubRoutines::arrayof_oop_copy_uninit(HeapWord* src, HeapWord* dest, size_t count)) @@ -462,7 +462,7 @@ SharedRuntime::_oop_array_copy_ctr++; // Slow-path oop array copy #endif // !PRODUCT assert(count != 0, "count should be non-zero"); - HeapAccess::oop_arraycopy(NULL, NULL, src, dest, count); + HeapAccess::oop_arraycopy(NULL, 0, src, NULL, 0, dest, count); JRT_END address StubRoutines::select_fill_function(BasicType t, bool aligned, const char* &name) {