diff --git a/common_interfaces/heap/heap_allocator.h b/common_interfaces/heap/heap_allocator.h index 0ac0955b8bc8201a6e44ab54aa09ed610919e1a8..5c2a969e181d5e623a34ddb7805f46961f8ca445 100644 --- a/common_interfaces/heap/heap_allocator.h +++ b/common_interfaces/heap/heap_allocator.h @@ -39,6 +39,9 @@ public: static Address AllocateRegion(); static Address AllocatePinnedRegion(); static Address AllocateLargeRegion(size_t size); + + static void PinObject(Address obj); + static void UnpinObject(Address obj); }; } // namespace panda #endif // COMMON_INTERFACES_HEAP_ALLOCATOR_H diff --git a/static_core/runtime/include/mem/allocator.h b/static_core/runtime/include/mem/allocator.h index a5909f198fca3733a82f5803aec53e49a4dad6cf..6d6e852a2ff6afcc0960be4913b791be876d2797 100644 --- a/static_core/runtime/include/mem/allocator.h +++ b/static_core/runtime/include/mem/allocator.h @@ -686,9 +686,9 @@ public: return false; } - void PinObject([[maybe_unused]] ObjectHeader *object) final {} + void PinObject([[maybe_unused]] ObjectHeader *object) override {} - void UnpinObject([[maybe_unused]] ObjectHeader *object) final {} + void UnpinObject([[maybe_unused]] ObjectHeader *object) override {} const std::vector &GetYoungSpaceMemRanges() final { diff --git a/static_core/runtime/mem/gc/cmc-gc-adapter/cmc-allocator-adapter.cpp b/static_core/runtime/mem/gc/cmc-gc-adapter/cmc-allocator-adapter.cpp index e58ce7376da8621fcdbef34f779089c2badf54b7..a3ecef25ea2b5c467a3be39b188dced21059c0f5 100644 --- a/static_core/runtime/mem/gc/cmc-gc-adapter/cmc-allocator-adapter.cpp +++ b/static_core/runtime/mem/gc/cmc-gc-adapter/cmc-allocator-adapter.cpp @@ -55,6 +55,22 @@ void *CMCObjectAllocatorAdapter::AllocateNonMovable( #endif } +template +void CMCObjectAllocatorAdapter::PinObject([[maybe_unused]] ObjectHeader *object) +{ +#if defined(ARK_HYBRID) + panda::HeapAllocator::PinObject((panda::Address)object); +#endif +} + +template +void CMCObjectAllocatorAdapter::UnpinObject([[maybe_unused]] ObjectHeader *object) +{ +#if defined(ARK_HYBRID) + panda::HeapAllocator::UnpinObject((panda::Address)object); +#endif +} + template class CMCObjectAllocatorAdapter; template class CMCObjectAllocatorAdapter; template class CMCObjectAllocatorAdapter; diff --git a/static_core/runtime/mem/gc/cmc-gc-adapter/cmc-allocator-adapter.h b/static_core/runtime/mem/gc/cmc-gc-adapter/cmc-allocator-adapter.h index 91d65be1a585b41d646fe5963ae6e4f8de207d2e..67cbbf8cf39691f6dd29fa68299a57a6984a750b 100644 --- a/static_core/runtime/mem/gc/cmc-gc-adapter/cmc-allocator-adapter.h +++ b/static_core/runtime/mem/gc/cmc-gc-adapter/cmc-allocator-adapter.h @@ -38,6 +38,9 @@ public: [[nodiscard]] void *AllocateNonMovable(size_t size, Alignment align, ark::ManagedThread *thread, ObjectAllocatorBase::ObjMemInitPolicy objInit) override; + + void PinObject([[maybe_unused]] ObjectHeader *object) override; + void UnpinObject([[maybe_unused]] ObjectHeader *object) override; }; } // namespace ark::mem diff --git a/static_core/runtime/mem/gc/cmc-gc-adapter/cmc-gc-adapter.cpp b/static_core/runtime/mem/gc/cmc-gc-adapter/cmc-gc-adapter.cpp index 0e9f8f5520d588cfcec77bd2ed9fdc189caa8872..6af155d3ad5b6c1af07aa558b15c3c5afa418d24 100644 --- a/static_core/runtime/mem/gc/cmc-gc-adapter/cmc-gc-adapter.cpp +++ b/static_core/runtime/mem/gc/cmc-gc-adapter/cmc-gc-adapter.cpp @@ -68,6 +68,10 @@ void CMCGCAdapter::InitGCBitsForAllocationInTLAB([[maybe_unused] template bool CMCGCAdapter::Trigger([[maybe_unused]] PandaUniquePtr task) { +#ifdef ARK_HYBRID + panda::BaseRuntime::RequestGC(panda::GcType::FULL); + return true; +#endif return false; } diff --git a/static_core/runtime/mem/gc/cmc-gc-adapter/cmc-gc-adapter.h b/static_core/runtime/mem/gc/cmc-gc-adapter/cmc-gc-adapter.h index c1f2e7f1393ec19fe57043f22940165fda50ee63..ae9c3cd59c8ced96b26c1bf4961e817852e2855f 100644 --- a/static_core/runtime/mem/gc/cmc-gc-adapter/cmc-gc-adapter.h +++ b/static_core/runtime/mem/gc/cmc-gc-adapter/cmc-gc-adapter.h @@ -42,7 +42,7 @@ public: bool IsPinningSupported() const final { - return false; + return true; } void InitGCBits(ark::ObjectHeader *objHeader) override; diff --git a/static_core/tools/ark_js_napi_cli/BUILD.gn b/static_core/tools/ark_js_napi_cli/BUILD.gn index b1116c15cc067c551069a0ce40155d296b45cf8e..43f8f82cf93f66b13b9d81a8daaa46745875a12b 100755 --- a/static_core/tools/ark_js_napi_cli/BUILD.gn +++ b/static_core/tools/ark_js_napi_cli/BUILD.gn @@ -95,8 +95,12 @@ template("host_hybridtest_action") { action("${_target_name_}") { testonly = true script = "tests/test_runner.py" + _test_list = rebase_path("tests/test_list.txt") + if (ark_hybrid) { + _test_list = rebase_path("tests/test_list_hybrid.txt") + } args = [ - "--tests-list=" + rebase_path("tests/test_list.txt"), + "--tests-list=$_test_list", "--build-dir=" + rebase_path("$root_out_dir"), "--tests-dir=" + rebase_path("tests"), ] diff --git a/static_core/tools/ark_js_napi_cli/tests/cmc_gc_object_pinning.ts b/static_core/tools/ark_js_napi_cli/tests/cmc_gc_object_pinning.ts new file mode 100644 index 0000000000000000000000000000000000000000..6444d0f7e70b6421f250fcae9caa4988fda7ed24 --- /dev/null +++ b/static_core/tools/ark_js_napi_cli/tests/cmc_gc_object_pinning.ts @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This test check basic cases of interop objects +// are not collected by normal GC + +globalThis.test = {}; +globalThis.test.etsVm = requireNapiPreview('ets_interop_js_napi', true); +if (!globalThis.test.etsVm.createRuntime({ + 'log-level': 'debug', + 'load-runtimes': 'ets', + 'boot-panda-files': 'etsstdlib.abc:gc_test_sts_common.abc', + 'gc-trigger-type': 'heap-trigger', + 'compiler-enable-jit': 'false', + 'interpreter-type': 'cpp', + 'coroutine-workers-count': '1', + 'gc-type': 'cmc-gc', +})) { + throw new Error('Failed to create ETS runtime'); +} + +function main(): void { + const ObjectPinningTest = globalThis.test.etsVm.getFunction('LPandaGC/ETSGLOBAL;', 'ObjectPinningTest'); + ObjectPinningTest(); +} +main(); diff --git a/static_core/tools/ark_js_napi_cli/tests/ets/gc_test_sts_common.ets b/static_core/tools/ark_js_napi_cli/tests/ets/gc_test_sts_common.ets index 83d9d9aac9cc518a59ed0125f0e99dfdaa8b9fdc..33b6547b945c15c74b2f805a67989aa550eeaec9 100644 --- a/static_core/tools/ark_js_napi_cli/tests/ets/gc_test_sts_common.ets +++ b/static_core/tools/ark_js_napi_cli/tests/ets/gc_test_sts_common.ets @@ -126,3 +126,32 @@ class PandaBaseClass { } } } + +function FillCurrentRegion() { + for (let i = 0; i < 10000; i++) { + let obj: Object = new Object(); + } +} + +function RunGC() { + let gc_id = GC.startGC(GC.Cause.FULL); + assertTrue(gc_id != -1, "startGC failed"); +} + +function ObjectPinningTest(): int { + let obj: Object = new Object(); + let addr_before_gc: long = GC.getObjectAddress(obj); + GC.pinObject(obj); + FillCurrentRegion(); + RunGC() + let addr_after_gc_1: long = GC.getObjectAddress(obj); + assertEQ(addr_before_gc, addr_after_gc_1, "Pinned object must has a fixed address"); + + GC.unpinObject(obj); + RunGC() + RunGC() + let addr_after_gc_2: long = GC.getObjectAddress(obj); + assertNE(addr_before_gc, addr_after_gc_2, "Unpinned object must be moved"); + + return 0 +} diff --git a/static_core/tools/ark_js_napi_cli/tests/test_list_hybrid.txt b/static_core/tools/ark_js_napi_cli/tests/test_list_hybrid.txt new file mode 100644 index 0000000000000000000000000000000000000000..fd8fa3a2815a6b5f82e7f26b09850bfd8dbb4b69 --- /dev/null +++ b/static_core/tools/ark_js_napi_cli/tests/test_list_hybrid.txt @@ -0,0 +1 @@ +cmc_gc_object_pinning.ts, gc_test_sts_common.ets