# HG changeset patch # User rkennke # Date 1520934886 -3600 # Tue Mar 13 10:54:46 2018 +0100 # Node ID 28b8a080fc87424903a475ee3ce6da946bfc63f1 # Parent 74518f9ca4b46597aba65bbe5540c4f6e52ab674 8198445: Access API for primitive/native arraycopy Reviewed-by: pliden, eosterlund, dholmes diff --git a/src/hotspot/share/c1/c1_Runtime1.cpp b/src/hotspot/share/c1/c1_Runtime1.cpp --- a/src/hotspot/share/c1/c1_Runtime1.cpp +++ b/src/hotspot/share/c1/c1_Runtime1.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1402,13 +1402,7 @@ Klass* klass_oop = src->klass(); if (klass_oop != dst->klass()) return ac_failed; TypeArrayKlass* klass = TypeArrayKlass::cast(klass_oop); - const int l2es = klass->log2_element_size(); - const int ihs = klass->array_header_in_bytes() / wordSize; - char* src_addr = (char*) ((oopDesc**)src + ihs) + (src_pos << l2es); - char* dst_addr = (char*) ((oopDesc**)dst + ihs) + (dst_pos << l2es); - // Potential problem: memmove is not guaranteed to be word atomic - // Revisit in Merlin - memmove(dst_addr, src_addr, length << l2es); + klass->copy_array(arrayOop(src), src_pos, arrayOop(dst), dst_pos, length, Thread::current()); return ac_ok; } else if (src->is_objArray() && dst->is_objArray()) { if (UseCompressedOops) { 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 @@ -189,8 +189,8 @@ } template - static bool arraycopy_in_heap(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { - return Raw::arraycopy(src_obj, dst_obj, src, dst, length); + 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); } // Heap oop accesses. These accessors get resolved when 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 @@ -402,10 +402,10 @@ } template - static inline bool arraycopy(arrayOop src_obj, arrayOop dst_obj, T *src, T *dst, size_t length) { + static inline void arraycopy(arrayOop src_obj, arrayOop dst_obj, T *src, T *dst, size_t length) { verify_decorators(); - return AccessInternal::arraycopy(src_obj, dst_obj, src, dst, length); + AccessInternal::arraycopy(src_obj, dst_obj, src, dst, length); } // Oop heap accesses 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 @@ -139,7 +139,8 @@ struct PostRuntimeDispatch: public AllStatic { template static bool access_barrier(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { - return GCBarrierType::arraycopy_in_heap(src_obj, dst_obj, src, dst, length); + GCBarrierType::arraycopy_in_heap(src_obj, dst_obj, src, dst, length); + return true; } template @@ -763,7 +764,7 @@ HasDecorator::value, bool>::type arraycopy(arrayOop src_obj, arrayOop dst_obj, T *src, T* dst, size_t length) { typedef RawAccessBarrier Raw; - return Raw::arraycopy(src, dst, length); + return Raw::arraycopy(src_obj, dst_obj, src, dst, length); } template @@ -1077,7 +1078,9 @@ template inline bool arraycopy(arrayOop src_obj, arrayOop dst_obj, T *src, T *dst, size_t length) { - verify_types(); + 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 ? 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 @@ -153,6 +153,13 @@ } template<> + void arraycopy_conjoint(void* src, void* dst, size_t length) { + Copy::conjoint_jbytes(reinterpret_cast(src), + reinterpret_cast(dst), + length); + } + + template<> void arraycopy_conjoint_atomic(jbyte* src, jbyte* dst, size_t length) { Copy::conjoint_jbytes_atomic(src, dst, length); } @@ -171,4 +178,9 @@ void arraycopy_conjoint_atomic(jlong* src, jlong* dst, size_t length) { Copy::conjoint_jlongs_atomic(src, dst, length); } + + template<> + void arraycopy_conjoint_atomic(void* src, void* dst, size_t length) { + Copy::conjoint_memory_atomic(src, dst, length); + } } 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 @@ -104,6 +104,11 @@ typedef oop (*resolve_func_t)(oop obj); }; + template + struct AccessFunctionTypes { + typedef bool (*arraycopy_func_t)(arrayOop src_obj, arrayOop dst_obj, void* src, void* dst, size_t length); + }; + template struct AccessFunction {}; #define ACCESS_GENERATE_ACCESS_FUNCTION(bt, func) \ @@ -335,7 +340,7 @@ } template - static bool arraycopy(T* src, T* dst, size_t length); + static bool arraycopy(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length); template static void oop_store(void* addr, T value); 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,7 +118,7 @@ template template inline bool RawAccessBarrier::oop_arraycopy(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { - return arraycopy(src, dst, length); + return arraycopy(src_obj, dst_obj, src, dst, length); } template @@ -257,7 +257,7 @@ template static inline typename EnableIf< HasDecorator::value>::type - arraycopy(T* src, T* dst, size_t length) { + arraycopy(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { // 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); @@ -271,7 +271,7 @@ template static inline typename EnableIf< !HasDecorator::value>::type - arraycopy(T* src, T* dst, size_t length) { + arraycopy(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { if (HasDecorator::value) { AccessInternal::arraycopy_arrayof_conjoint(src, dst, length); } else if (HasDecorator::value && sizeof(T) == HeapWordSize) { @@ -289,12 +289,23 @@ } } } + + template + static inline typename EnableIf< + !HasDecorator::value>::type + arraycopy(arrayOop src_obj, arrayOop dst_obj, void* src, void* dst, size_t length) { + if (HasDecorator::value) { + AccessInternal::arraycopy_conjoint_atomic(src, dst, length); + } else { + AccessInternal::arraycopy_conjoint(src, dst, length); + } + } }; template template -inline bool RawAccessBarrier::arraycopy(T* src, T* dst, size_t length) { - RawAccessBarrierArrayCopy::arraycopy(src, dst, length); +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); return true; } 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; - char* src = (char*) ((oop*)s + ihs) + ((size_t)src_pos << l2es); - char* dst = (char*) ((oop*)d + ihs) + ((size_t)dst_pos << l2es); - Copy::conjoint_memory_atomic(src, dst, (size_t)length << l2es); + 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); }