# HG changeset patch # Parent 78d797e044841fe663853a3bd58886af1215885d 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, T* dst_raw, size_t length) { + Raw::arraycopy(src_obj, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, src_raw, 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, T* dst_raw, size_t length) { + return Raw::oop_arraycopy(src_obj, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, src_raw, 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, 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, NULL, 0, 0, src_raw, 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 = 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, T* dst_raw, size_t length) { verify_decorators(); - AccessInternal::arraycopy(src_obj, dst_obj, src, dst, length); + AccessInternal::arraycopy(src_obj, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, src_raw, 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, T* dst_raw, size_t length) { verify_decorators(); - return AccessInternal::arraycopy(src_obj, dst_obj, src, dst, length); + return AccessInternal::arraycopy(src_obj, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, src_raw, 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,17 @@ 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, T* dst_raw, size_t length) { + GCBarrierType::arraycopy_in_heap(src_obj, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, src_raw, 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, 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, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, + reinterpret_cast(src_raw), + reinterpret_cast(dst_raw), length); } }; @@ -337,10 +337,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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, 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, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, src_raw, dst_raw, length); } template 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, void* src, 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, T* dst_raw, size_t length) { + return _arraycopy_func(src_obj, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, src_raw, 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, 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, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, src_raw, dst_raw, length); } else { - return Raw::arraycopy(src_obj, dst_obj, src, dst, length); + return Raw::arraycopy(src_obj, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, src_raw, 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, 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, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, src_raw, 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, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, src_raw, 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, 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, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, src_raw, dst_raw, length); } else { - return RuntimeDispatch::arraycopy(src_obj, dst_obj, src, dst, length); + return RuntimeDispatch::arraycopy(src_obj, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, src_raw, 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, T* dst_raw, size_t length) { + return PreRuntimeDispatch::arraycopy(src_obj, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, src_raw, 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, HeapWord* src_raw, 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, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, src_raw, 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, narrowOop* src_raw, 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, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, src_raw, dst_raw, length); } // Step 1: Set default decorators. This step remembers if a type was volatile @@ -1264,15 +1264,15 @@ } template - inline bool arraycopy(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { + inline bool arraycopy(arrayOop src_obj, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, 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, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, + const_cast(src_raw), + 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, T* dst_raw, size_t length) { + return arraycopy(src_obj, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, src_raw, 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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, 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(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(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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, 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(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(src_raw, dst_raw, length); } else { - AccessInternal::arraycopy_disjoint_words(src, dst, length); + AccessInternal::arraycopy_disjoint_words(src_raw, dst_raw, length); } } else { if (HasDecorator::value) { - AccessInternal::arraycopy_conjoint_atomic(src, dst, length); + AccessInternal::arraycopy_conjoint_atomic(src_raw, dst_raw, length); } else { - AccessInternal::arraycopy_conjoint(src, dst, length); + AccessInternal::arraycopy_conjoint(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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, void* src_raw, 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(src_raw, dst_raw, length); } else { - AccessInternal::arraycopy_conjoint(src, dst, length); + AccessInternal::arraycopy_conjoint(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, arrayOop dst_obj, size_t src_offset_in_bytes, size_t dst_offset_in_bytes, T* src_raw, T* dst_raw, size_t length) { + RawAccessBarrierArrayCopy::arraycopy(src_obj, dst_obj, src_offset_in_bytes, dst_offset_in_bytes, src_raw, 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, d, src_offset, dst_offset, NULL, 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, d, src_offset, dst_offset, NULL, 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, d, src_offset, dst_offset, NULL, 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, d, src_offset, dst_offset, NULL, NULL, (size_t)length << l2es); } 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, NULL, 0, 0, (HeapWord*)src, (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, NULL, 0, 0, (HeapWord*)src, (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, NULL, 0, 0, src, 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, NULL, 0, 0, src, dest, count); JRT_END address StubRoutines::select_fill_function(BasicType t, bool aligned, const char* &name) {