From a7740aac7c8086670dd7ef6fc91f474bbb806394 Mon Sep 17 00:00:00 2001 From: Howard Roark Date: Tue, 9 Sep 2025 14:53:47 +0800 Subject: [PATCH] Update refs in StdCoreObjectCopyTo on Safepoint Test: build Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/ICX43J Signed-off-by: Howard Roark --- .../runtime/intrinsics/std_core_Arrays.cpp | 77 +++++++++++++------ .../unit-tests/unit-tests-ignored-TSAN.txt | 3 - 2 files changed, 52 insertions(+), 28 deletions(-) diff --git a/static_core/plugins/ets/runtime/intrinsics/std_core_Arrays.cpp b/static_core/plugins/ets/runtime/intrinsics/std_core_Arrays.cpp index ae7f182aa6..78dcb6f532 100644 --- a/static_core/plugins/ets/runtime/intrinsics/std_core_Arrays.cpp +++ b/static_core/plugins/ets/runtime/intrinsics/std_core_Arrays.cpp @@ -148,7 +148,7 @@ static void MemAtomicCopyReadBarrier(mem::GCBarrierSet *barrierSet, const void * } template -static auto GetCopy([[maybe_unused]] void *srcAddr) +static auto GetCopy([[maybe_unused]] const void *srcAddr) { #ifdef ARK_HYBRID auto *readBarrierSet = Thread::GetCurrent()->GetBarrierSet(); @@ -166,6 +166,30 @@ static auto GetCopy([[maybe_unused]] void *srcAddr) #endif } +namespace { +template +struct ObjectArrayHandle final { + EtsHandle &array; + int32_t start; + + void *GetBasePtr() + { + return array.GetPtr(); + } + + [[nodiscard]] static size_t GetElementOffset(size_t index) + { + constexpr uint32_t OFFSET = ark::coretypes::Array::GetDataOffset(); + return OFFSET + index * sizeof(T); + } + + T *GetStartPtr() + { + return static_cast(ToVoidPtr(ToUintPtr(array->GetCoreType()->GetData()) + start * sizeof(T))); + } +}; +} // namespace + // Performance measurement on the device demonstrates that COPIED_BETWEEN_SAFEPOINT_THRESHOLD object pointers // are copied in 0.07-0.1 ms. static constexpr size_t COPIED_BETWEEN_SAFEPOINT_THRESHOLD = 100000UL; @@ -177,13 +201,13 @@ static void CopyForward(T *src, T *dst, size_t length, Copy copy, PutSP putSafep for (size_t j = i * COPIED_BETWEEN_SAFEPOINT_THRESHOLD; j < (i + 1) * COPIED_BETWEEN_SAFEPOINT_THRESHOLD; ++j) { copy(&src[j], &dst[j]); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) } - putSafepoint(i * COPIED_BETWEEN_SAFEPOINT_THRESHOLD, COPIED_BETWEEN_SAFEPOINT_THRESHOLD); + putSafepoint(src, dst, i * COPIED_BETWEEN_SAFEPOINT_THRESHOLD, COPIED_BETWEEN_SAFEPOINT_THRESHOLD); } size_t batchesFinalIdx = (length / COPIED_BETWEEN_SAFEPOINT_THRESHOLD) * COPIED_BETWEEN_SAFEPOINT_THRESHOLD; for (size_t i = batchesFinalIdx; i < length; ++i) { copy(&src[i], &dst[i]); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) } - putSafepoint(batchesFinalIdx, length - batchesFinalIdx); + putSafepoint(src, dst, batchesFinalIdx, length - batchesFinalIdx); } template @@ -193,33 +217,32 @@ static void CopyBackward(T *src, T *dst, size_t length, Copy copy, PutSP putSafe for (size_t i = length; i > batchesStartIdx; --i) { copy(&src[i - 1], &dst[i - 1]); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) } - putSafepoint(batchesStartIdx, length - batchesStartIdx); + putSafepoint(src, dst, batchesStartIdx, length - batchesStartIdx); for (size_t i = length / COPIED_BETWEEN_SAFEPOINT_THRESHOLD; i > 0; --i) { for (size_t j = i * COPIED_BETWEEN_SAFEPOINT_THRESHOLD; j > (i - 1) * COPIED_BETWEEN_SAFEPOINT_THRESHOLD; --j) { copy(&src[j - 1], &dst[j - 1]); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) } - putSafepoint((i - 1) * COPIED_BETWEEN_SAFEPOINT_THRESHOLD, COPIED_BETWEEN_SAFEPOINT_THRESHOLD); + putSafepoint(src, dst, (i - 1) * COPIED_BETWEEN_SAFEPOINT_THRESHOLD, COPIED_BETWEEN_SAFEPOINT_THRESHOLD); } } -static void PostWrite(ManagedThread *thread, EtsHandle dstArray, size_t dstStart, size_t length) +template +static void PostWrite(ManagedThread *thread, ObjectArrayHandle dstArray, size_t start, size_t length) { auto *barrierSet = thread->GetBarrierSet(); if (barrierSet->GetPostType() != ark::mem::BarrierType::POST_WRB_NONE) { - constexpr uint32_t OFFSET = ark::coretypes::Array::GetDataOffset(); - const uint32_t size = length * sizeof(ObjectPointerType); - barrierSet->PostBarrier(dstArray.GetPtr(), OFFSET + dstStart * sizeof(ObjectPointerType), size); + const uint32_t size = length * sizeof(T); + barrierSet->PostBarrier(dstArray.GetBasePtr(), ObjectArrayHandle::GetElementOffset(start), size); } } template -static void RefCopy(ManagedThread *thread, EtsHandle dstArray, void *srcAddr, void *dstAddr, - int32_t length) +static void RefCopy(ManagedThread *thread, ObjectArrayHandle srcArray, ObjectArrayHandle dstArray, int32_t length) { - auto *src = static_cast(srcAddr); - auto *dst = static_cast(dstAddr); - bool backwards = reinterpret_cast(srcAddr) < reinterpret_cast(dstAddr); - auto copy = GetCopy(srcAddr); + auto *src = srcArray.GetStartPtr(); + auto *dst = dstArray.GetStartPtr(); + bool backwards = reinterpret_cast(src) < reinterpret_cast(dst); + auto copy = GetCopy(src); if constexpr (NEED_PRE_WRITE_BARRIER) { auto *barrierSet = thread->GetBarrierSet(); @@ -230,10 +253,15 @@ static void RefCopy(ManagedThread *thread, EtsHandle dstArray, voi } copy(srcPtr, dstPtr); }; - auto putSafepoint = [&usePreBarrier, barrierSet, dstArray, thread](size_t dstStart, size_t count) { - PostWrite(thread, dstArray, dstStart, count); + auto putSafepoint = [&usePreBarrier, barrierSet, srcArray, dstArray, thread](T *&src, T *&dst, size_t start, + size_t count) mutable { + PostWrite(thread, dstArray, start, count); ark::interpreter::RuntimeInterface::Safepoint(thread); usePreBarrier = barrierSet->IsPreBarrierEnabled(); + // If GC suspends worker during RefCopy execution, it may move the arrays pointed by *srcPtr and *dstPtr + // to different memory locations; therefore, the new array addresses should be re-read. + src = srcArray.GetStartPtr(); + dst = dstArray.GetStartPtr(); }; if (backwards) { CopyBackward(src, dst, length, copyWithBarriers, putSafepoint); @@ -241,9 +269,13 @@ static void RefCopy(ManagedThread *thread, EtsHandle dstArray, voi CopyForward(src, dst, length, copyWithBarriers, putSafepoint); } } else { - auto putSafepoint = [thread, dstArray](size_t dstStart, size_t count) { - PostWrite(thread, dstArray, dstStart, count); + auto putSafepoint = [srcArray, dstArray, thread](T *&src, T *&dst, size_t start, size_t count) mutable { + PostWrite(thread, dstArray, start, count); ark::interpreter::RuntimeInterface::Safepoint(thread); + // If GC suspends worker during RefCopy execution, it may move the arrays pointed by *srcPtr and *dstPtr + // to different memory locations; therefore, the new array addresses should be re-read. + src = srcArray.GetStartPtr(); + dst = dstArray.GetStartPtr(); }; if (backwards) { CopyBackward(src, dst, length, copy, putSafepoint); @@ -277,12 +309,7 @@ void StdCoreCopyToForObjects(EtsCharArray *src, EtsCharArray *dst, int32_t dstSt return; } - auto srcAddr = ToVoidPtr(ToUintPtr(srcArray->GetCoreType()->GetData()) + srcStart * sizeof(ObjectPointerType)); - auto dstAddr = ToVoidPtr(ToUintPtr(dstArray->GetCoreType()->GetData()) + dstStart * sizeof(ObjectPointerType)); - - TSAN_ANNOTATE_IGNORE_WRITES_BEGIN(); - RefCopy(coroutine, dstArray, srcAddr, dstAddr, length); - TSAN_ANNOTATE_IGNORE_WRITES_END(); + RefCopy(coroutine, {srcArray, srcStart}, {dstArray, dstStart}, length); } extern "C" void StdCoreObjectCopyTo(EtsCharArray *src, EtsCharArray *dst, int32_t dstStart, int32_t srcStart, diff --git a/static_core/plugins/ets/tests/test-lists/unit-tests/unit-tests-ignored-TSAN.txt b/static_core/plugins/ets/tests/test-lists/unit-tests/unit-tests-ignored-TSAN.txt index 73e45f7a74..336e61c648 100644 --- a/static_core/plugins/ets/tests/test-lists/unit-tests/unit-tests-ignored-TSAN.txt +++ b/static_core/plugins/ets/tests/test-lists/unit-tests/unit-tests-ignored-TSAN.txt @@ -1,9 +1,6 @@ # 29297 ets-common-tests/intrinsics/map_set.ets -# 29298 -ets-common-tests/intrinsics/copyTo.ets - # 29320 ets-common-tests/intrinsics/isSafeInteger.ets ets-common-tests/intrinsics/uint8clampedarray_join.ets -- Gitee