diff --git a/BUILD.gn b/BUILD.gn index 9567f8e6868954aaa48fddbbcab8816377255516..9ae3406c6e67187e68e2ba94697173c2e6098e1b 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1053,8 +1053,6 @@ ecma_source = [ "ecmascript/mem/shared_heap/shared_full_gc.cpp", "ecmascript/mem/shared_heap/shared_gc_marker.cpp", "ecmascript/mem/shared_heap/shared_space.cpp", - "ecmascript/mem/unified_gc/unified_gc.cpp", - "ecmascript/mem/unified_gc/unified_gc_marker.cpp", "ecmascript/mem/space.cpp", "ecmascript/mem/sparse_space.cpp", "ecmascript/mem/tagged_object.cpp", @@ -1191,6 +1189,18 @@ if (enable_next_optimization) { ecma_source += [ "ecmascript/base/json_stringifier.cpp" ] } +# supported for hybrid +ecma_source += [ + "ecmascript/cross_vm/unified_gc/unified_gc.cpp", + "ecmascript/cross_vm/unified_gc/unified_gc_marker.cpp", + "ecmascript/cross_vm/builtins_gc_hybrid.cpp", + "ecmascript/cross_vm/heap_hybrid.cpp", + "ecmascript/cross_vm/jsnapi_expo_hybrid.cpp", + "ecmascript/cross_vm/object_factory_hybrid.cpp", + "ecmascript/cross_vm/ecma_vm_hybrid.cpp", + "ecmascript/cross_vm/js_thread_hybrid.cpp" +] + hitrace_scope_source = [] if (is_ohos && is_standard_system && enable_hitrace) { hitrace_scope_source += [ "ecmascript/jobs/hitrace_scope.cpp" ] diff --git a/ecmascript/builtins/builtins.cpp b/ecmascript/builtins/builtins.cpp index 55286307ce530c020f2ff00bf7a9d6b36046ff77..964fac54f4c1b0ea0cf9789670508ae2ebfe20fa 100644 --- a/ecmascript/builtins/builtins.cpp +++ b/ecmascript/builtins/builtins.cpp @@ -3720,6 +3720,12 @@ JSHandle Builtins::InitializeGcBuiltins(const JSHandle &env SetFunction(env, builtins, entry.GetName(), entry.GetEntrypoint(), entry.GetLength(), entry.GetBuiltinStubId()); } + + for (const base::BuiltinFunctionEntry &entry: builtins::BuiltinsGc::GetGcFunctionsHybrid()) { + SetFunction(env, builtins, entry.GetName(), entry.GetEntrypoint(), + entry.GetLength(), entry.GetBuiltinStubId()); + } + return builtins; } diff --git a/ecmascript/builtins/builtins_gc.cpp b/ecmascript/builtins/builtins_gc.cpp index cf79367ea992f1b59022f59f6b72936f2a47e117..7c817538a4758395decfa388a6d8110f2f7a8da6 100644 --- a/ecmascript/builtins/builtins_gc.cpp +++ b/ecmascript/builtins/builtins_gc.cpp @@ -100,18 +100,6 @@ JSTaggedValue BuiltinsGc::RegisterNativeFree(EcmaRuntimeCallInfo *info) return JSTaggedValue::Undefined(); } -JSTaggedValue BuiltinsGc::ClearWeakRefForTest(EcmaRuntimeCallInfo *info) -{ - RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread()); - ASSERT(info); - JSThread *thread = info->GetThread(); - if (!((thread)->GetEcmaVM()->GetJSOptions().IsOpenArkTools())) { - return JSTaggedValue::Undefined(); - } - EcmaVM::ClearKeptObjects(thread); - return JSTaggedValue::Undefined(); -} - JSTaggedValue BuiltinsGc::WaitForFinishGC(EcmaRuntimeCallInfo *info) { RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread()); @@ -270,7 +258,8 @@ TriggerGCType BuiltinsGc::StringToGcType(JSThread *thread, JSTaggedValue cause) if (JSTaggedValue::StrictEqual(thread, thread->GlobalConstants()->GetAppSpawnSharedFullGcCause(), cause)) { return APPSPAWN_SHARED_FULL_GC; } - if (JSTaggedValue::StrictEqual(thread, thread->GlobalConstants()->GetUnifiedGcCause(), cause)) { + if (Runtime::GetInstance()->IsHybridVm() && + JSTaggedValue::StrictEqual(thread, thread->GlobalConstants()->GetUnifiedGcCause(), cause)) { return UNIFIED_GC; } return GC_TYPE_LAST; diff --git a/ecmascript/builtins/builtins_gc.h b/ecmascript/builtins/builtins_gc.h index 78c921b83ec810aab3795365ebe6e1f4ed91dbfc..7fca50ee8613361ee38a589fcbf9657407c19474 100644 --- a/ecmascript/builtins/builtins_gc.h +++ b/ecmascript/builtins/builtins_gc.h @@ -16,6 +16,8 @@ #ifndef ECMASCRIPT_BUILTINS_BUILTINS_GC_H #define ECMASCRIPT_BUILTINS_BUILTINS_GC_H +#include "ecmascript/cross_vm/builtins_gc_hybrid.h" + #include "ecmascript/base/builtins_base.h" #include "ecmascript/js_thread.h" @@ -38,8 +40,6 @@ public: static JSTaggedValue WaitForFinishGC(EcmaRuntimeCallInfo *info); - static JSTaggedValue ClearWeakRefForTest(EcmaRuntimeCallInfo *info); - static JSTaggedValue StartGC(EcmaRuntimeCallInfo *info); static JSTaggedValue AllocateArrayObject(EcmaRuntimeCallInfo *info); @@ -49,6 +49,8 @@ public: return Span(GC_FUNCTIONS); } + BUILDINSGC_PUBLIC_HYBRID_EXTENSION() + private: #define BUILTINS_GC_FUNCTION_ENTRY(name, method, length, id) \ base::BuiltinFunctionEntry::Create(name, BuiltinsGc::method, length, BUILTINS_STUB_ID(id)), @@ -68,8 +70,9 @@ private: BUILTINS_GC_FUNCTION_ENTRY("waitForFinishGC", WaitForFinishGC, 1, INVALID) BUILTINS_GC_FUNCTION_ENTRY("startGC", StartGC, 3, INVALID) BUILTINS_GC_FUNCTION_ENTRY("allocateArrayObject", AllocateArrayObject, 1, INVALID) - BUILTINS_GC_FUNCTION_ENTRY("clearWeakRefForTest", ClearWeakRefForTest, 1, INVALID) }; + + BUILTINSGC_PUBLIC_FUNCTION_ENTRY_HYBRID_EXTENSION(); #undef BUILTINS_GC_FUNCTION_ENTRY static void WaitAndHandleConcurrentMarkingFinished(Heap *heap); diff --git a/ecmascript/cross_vm/builtins_gc_hybrid.cpp b/ecmascript/cross_vm/builtins_gc_hybrid.cpp new file mode 100644 index 0000000000000000000000000000000000000000..27bbef6263335c61361b39678a516eb96e829a15 --- /dev/null +++ b/ecmascript/cross_vm/builtins_gc_hybrid.cpp @@ -0,0 +1,32 @@ +/* +* 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. +*/ + +#include "ecmascript/builtins/builtins_gc.h" +#include "ecmascript/builtins/builtins_ark_tools.h" + +namespace panda::ecmascript::builtins { + +JSTaggedValue BuiltinsGc::ClearWeakRefForTest(EcmaRuntimeCallInfo *info) +{ + RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread()); + ASSERT(info); + JSThread *thread = info->GetThread(); + if (!((thread)->GetEcmaVM()->GetJSOptions().IsOpenArkTools())) { + return JSTaggedValue::Undefined(); + } + EcmaVM::ClearKeptObjects(thread); + return JSTaggedValue::Undefined(); +} +} // namespace panda::ecmascript::builtins diff --git a/ecmascript/cross_vm/builtins_gc_hybrid.h b/ecmascript/cross_vm/builtins_gc_hybrid.h new file mode 100644 index 0000000000000000000000000000000000000000..0fb9c65649dbb232a57b6a5f3637086dea0eaa84 --- /dev/null +++ b/ecmascript/cross_vm/builtins_gc_hybrid.h @@ -0,0 +1,31 @@ +/* +* 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. +*/ +#ifndef ECMASCRIPT_CROSS_VM_BUILTINS_GC_HYBRID_H +#define ECMASCRIPT_CROSS_VM_BUILTINS_GC_HYBRID_H + +#define BUILDINSGC_PUBLIC_HYBRID_EXTENSION() \ + static JSTaggedValue ClearWeakRefForTest(EcmaRuntimeCallInfo *info); \ + static Span GetGcFunctionsHybrid() \ + { \ + return Span(GC_FUNCTIONS_HYBRID); \ + } + +#define BUILTINSGC_PUBLIC_FUNCTION_ENTRY_HYBRID_EXTENSION() \ + static constexpr std::array GC_FUNCTIONS_HYBRID = { \ + BUILTINS_GC_FUNCTION_ENTRY("clearWeakRefForTest", ClearWeakRefForTest, 1, INVALID) \ + } + + +#endif // ECMASCRIPT_CROSS_VM_BUILTINS_GC_HYBRID_H \ No newline at end of file diff --git a/ecmascript/cross_vm/cross_vm_operator.cpp b/ecmascript/cross_vm/cross_vm_operator.cpp index 80cf3ca94749ff95521bb5df9b24570192337d34..6e98db4949de66abe55cac3099bf6be2dcd2a456 100644 --- a/ecmascript/cross_vm/cross_vm_operator.cpp +++ b/ecmascript/cross_vm/cross_vm_operator.cpp @@ -15,10 +15,11 @@ #include "ecmascript/cross_vm/cross_vm_operator.h" +#include "ecmascript/cross_vm/unified_gc/unified_gc_marker.h" +#include "ecmascript/cross_vm/heap_hybrid-inl.h" +#include "ecmascript/cross_vm/unified_gc/unified_gc.h" #include "ecmascript/ecma_vm.h" #include "ecmascript/mem/heap-inl.h" -#include "ecmascript/mem/unified_gc/unified_gc.h" -#include "ecmascript/mem/unified_gc/unified_gc_marker.h" namespace panda::ecmascript { diff --git a/ecmascript/cross_vm/daemon_task_hybrid-inl.h b/ecmascript/cross_vm/daemon_task_hybrid-inl.h new file mode 100644 index 0000000000000000000000000000000000000000..d1ef0893982b7a965999f7610fef01e1ce498f9d --- /dev/null +++ b/ecmascript/cross_vm/daemon_task_hybrid-inl.h @@ -0,0 +1,36 @@ +/* +* 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. +*/ +#ifndef ECMASCRIPT_CROSS_VM_DAEMON_TASK_HYBRID_H +#define ECMASCRIPT_CROSS_VM_DAEMON_TASK_HYBRID_H + +#include "ecmascript/daemon/daemon_task.h" +#include "ecmascript/daemon/daemon_thread.h" +#include "ecmascript/mem/heap.h" + +namespace panda::ecmascript { + +template +void TriggerUnifiedGCMarkTaskRunner() +{ + SharedHeap::GetInstance()->StartUnifiedGCMark(gcType, gcReason); +} + +template +TriggerUnifiedGCMarkTask::TriggerUnifiedGCMarkTask(JSThread *thread) + : DaemonTask(thread, DaemonTaskType::TRIGGER_UNIFIED_GC_MARK, DaemonTaskGroup::GC_GROUP, + &TriggerUnifiedGCMarkTaskRunner) {} + +} // namespace panda::ecmascript +#endif // ECMASCRIPT_CROSS_VM_DAEMON_TASK_HYBRID_H diff --git a/ecmascript/cross_vm/ecma_global_storage_hybrid.h b/ecmascript/cross_vm/ecma_global_storage_hybrid.h new file mode 100644 index 0000000000000000000000000000000000000000..594d8aaca235411ad03991aefa9b7b15c86b2ba1 --- /dev/null +++ b/ecmascript/cross_vm/ecma_global_storage_hybrid.h @@ -0,0 +1,33 @@ +/* +* 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. +*/ +#ifndef ECMASCRIPT_CROSS_VM_ECMA_GLOBAL_STORAGE_HYBRID_H +#define ECMASCRIPT_CROSS_VM_ECMA_GLOBAL_STORAGE_HYBRID_H + +#define ECMAGLOBALSTORAGE_PUBLIC_HYBRID_EXTENSION() \ + void SetNodeKind(NodeKind nodeKind) \ + { \ + nodeKind_ = nodeKind; \ + } \ + NodeKind GetNodeKind() \ + { \ + return nodeKind_; \ + } + +#define ECMAGLOBALSTORAGE_PRIVATE_HYBRID_EXTENSION() \ + NodeKind nodeKind_ {NodeKind::NORMAL_NODE}; \ + NodeList *topXRefGlobalNodes_ {nullptr}; \ + NodeList *lastXRefGlobalNodes_ {nullptr}; \ + NodeList *xRefFreeListNodes_ {nullptr} +#endif // ECMASCRIPT_CROSS_VM_ECMA_GLOBAL_STORAGE_HYBRID_H diff --git a/ecmascript/cross_vm/ecma_vm_hybrid.cpp b/ecmascript/cross_vm/ecma_vm_hybrid.cpp new file mode 100644 index 0000000000000000000000000000000000000000..95f31be52247d1b37ebfccab90bc161577df7216 --- /dev/null +++ b/ecmascript/cross_vm/ecma_vm_hybrid.cpp @@ -0,0 +1,39 @@ +/* +* 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. +*/ + +#include "ecmascript/cross_vm/ecma_vm_hybrid.h" +#include "ecmascript/ecma_vm.h" +#include "ecmascript/object_factory.h" +#include "ecmascript/mem/heap.h" +#include "ecmascript/runtime.h" +#include "ecmascript/global_env_constants-inl.h" + +namespace panda::ecmascript { +void EcmaVM::CreateHybridParam() +{ + if (Runtime::GetInstance()->IsHybridVm()) { +#ifdef PANDA_JS_ETS_HYBRID_MODE + crossVMOperator_ = new CrossVMOperator(this); +#endif + JSHClass *hClass = JSHClass::Cast(thread_->GlobalConstants()->GetHClassClass().GetTaggedObject()); + JSHandle ecmaHclass = factory_->NewEcmaHClass(hClass, JSObject::SIZE, JSType::JS_XREF_OBJECT); + CacheToGlobalConstants(ecmaHclass.GetTaggedValue(), ConstantIndex::XREF_OBJECT_HCLASS_INDEX); + + heap_->CreateUnifiedGCMarker(); + SharedHeap::GetInstance()->CreateUnifiedGC(); + thread_->SetupXRefFields(); + } +} +} // namespace panda::ecmascript diff --git a/ecmascript/cross_vm/ecma_vm_hybrid.h b/ecmascript/cross_vm/ecma_vm_hybrid.h new file mode 100644 index 0000000000000000000000000000000000000000..9098b5e82cd2c722f7608e9d50dae6288ca0d299 --- /dev/null +++ b/ecmascript/cross_vm/ecma_vm_hybrid.h @@ -0,0 +1,32 @@ +/* +* 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. +*/ +#ifndef ECMASCRIPT_CROSS_VM_ECMA_VM_HYBRID_H +#define ECMASCRIPT_CROSS_VM_ECMA_VM_HYBRID_H + +#define ECMAVM_PUBLIC_HYBRID_MODE_EXTENSION() \ + CrossVMOperator* GetCrossVMOperator() const \ + { \ + return crossVMOperator_; \ + } + +#define ECMAVM_PUBLIC_HYBRID_EXTENSION() \ + void CreateHybridParam() + +#define ECMAVM_PROTECTED_HYBRID_EXTENSION() \ + void PrintJSErrorInfo(const JSHandle &exceptionInfo) const + +#define ECMAVM_PRIVATE_HYBRID_EXTENSION() \ + CrossVMOperator* crossVMOperator_ {nullptr} +#endif // ECMASCRIPT_CROSS_VM_ECMA_VM_HYBRID_H diff --git a/ecmascript/cross_vm/global_env_constants_hybrid.h b/ecmascript/cross_vm/global_env_constants_hybrid.h new file mode 100644 index 0000000000000000000000000000000000000000..944fa7174db34f1427010967da4948fae9941bed --- /dev/null +++ b/ecmascript/cross_vm/global_env_constants_hybrid.h @@ -0,0 +1,25 @@ +/* +* 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. +*/ +#ifndef ECMASCRIPT_CROSS_VM_GLOBAL_ENV_CONSTANTS_HYBRID_H +#define ECMASCRIPT_CROSS_VM_GLOBAL_ENV_CONSTANTS_HYBRID_H + +#define SHARED_GLOBAL_ENV_CONSTANT_STRING_HYBRID(V) \ + V(ProxyNapiWrapperString, PROXY_NAPI_WRAPPER_INDEX, "_proxynapiwrapper") \ + V(UnifiedGcCause, UNIFIED_GC_CAUSE, "unified") + +#define GLOBAL_ENV_CONSTANT_CLASS_HYBRID(V) \ + V(JSTaggedValue, XRefObjectClass, XREF_OBJECT_HCLASS_INDEX, ecma_roots_class) + +#endif // ECMASCRIPT_CROSS_VM_GLOBAL_ENV_CONSTANTS_HYBRID_H diff --git a/ecmascript/cross_vm/heap_hybrid-inl.h b/ecmascript/cross_vm/heap_hybrid-inl.h new file mode 100644 index 0000000000000000000000000000000000000000..c6ab12bd2d6c28ea2f890d5b1e491fbfe929ed28 --- /dev/null +++ b/ecmascript/cross_vm/heap_hybrid-inl.h @@ -0,0 +1,30 @@ +/* +* 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. +*/ +#ifndef ECMASCRIPT_CROSS_VM_HEAP_HYBRID_INL_H +#define ECMASCRIPT_CROSS_VM_HEAP_HYBRID_INL_H + +#include "ecmascript/cross_vm/heap_hybrid.h" +#include "ecmascript/mem/heap.h" +#include "ecmascript/cross_vm/daemon_task_hybrid-inl.h" + +namespace panda::ecmascript { + template + bool SharedHeap::TriggerUnifiedGCMark(JSThread *thread) const + { + ASSERT(gcType == TriggerGCType::UNIFIED_GC && gcReason == GCReason::CROSSREF_CAUSE); + return DaemonThread::GetInstance()->CheckAndPostTask(TriggerUnifiedGCMarkTask(thread)); + } +} // namespace panda::ecmascript +#endif // ECMASCRIPT_CROSS_VM_HEAP_HYBRID_INL_H diff --git a/ecmascript/cross_vm/heap_hybrid.cpp b/ecmascript/cross_vm/heap_hybrid.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4e42513d885a7a26c52d533ca44eb1fbd07de507 --- /dev/null +++ b/ecmascript/cross_vm/heap_hybrid.cpp @@ -0,0 +1,94 @@ +/* +* 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. +*/ + +#include "ecmascript/mem/heap.h" +#include "ecmascript/cross_vm/unified_gc/unified_gc.h" +#include "ecmascript/cross_vm/unified_gc/unified_gc_marker.h" +#include "ecmascript/checkpoint/thread_state_transition.h" +#include "ecmascript/mem/concurrent_sweeper.h" +#include "ecmascript/mem/verification.h" + +namespace panda::ecmascript { +void SharedHeap::StartUnifiedGCMark([[maybe_unused]]TriggerGCType gcType, [[maybe_unused]]GCReason gcReason) +{ + ASSERT(gcType == TriggerGCType::UNIFIED_GC && gcReason == GCReason::CROSSREF_CAUSE); + ASSERT(JSThread::GetCurrent() == dThread_); + { + ThreadManagedScope runningScope(dThread_); + SuspendAllScope scope(dThread_); + Runtime *runtime = Runtime::GetInstance(); + std::vector recurScopes; + // The approximate size is enough, because even if some thread creates and registers after here, it will keep + // waiting in transition to RUNNING state before JSThread::SetReadyForGCIterating. + recurScopes.reserve(runtime->ApproximateThreadListSize()); + runtime->GCIterateThreadList([&recurScopes](JSThread *thread) { + Heap *heap = const_cast(thread->GetEcmaVM()->GetHeap()); + recurScopes.emplace_back(heap, HeapType::LOCAL_HEAP); + }); +#ifdef PANDA_JS_ETS_HYBRID_MODE + if (!unifiedGC_->StartXGCBarrier()) { + unifiedGC_->SetInterruptUnifiedGC(false); + dThread_->FinishRunningTask(); + return; + } +#endif // PANDA_JS_ETS_HYBRID_MODE + runtime->GCIterateThreadList([gcType](JSThread *thread) { + Heap *heap = const_cast(thread->GetEcmaVM()->GetHeap()); + if (UNLIKELY(heap->ShouldVerifyHeap())) { // LCOV_EXCL_BR_LINE + // pre unified gc heap verify + LOG_ECMA(DEBUG) << "pre unified gc heap verify"; + heap->ProcessSharedGCRSetWorkList(); + Verification(heap, VerifyKind::VERIFY_PRE_GC).VerifyAll(); + } + heap->SetGCType(gcType); + }); + unifiedGC_->RunPhases(); + runtime->GCIterateThreadList([](JSThread *thread) { + Heap *heap = const_cast(thread->GetEcmaVM()->GetHeap()); + if (UNLIKELY(heap->ShouldVerifyHeap())) { // LCOV_EXCL_BR_LINE + // post unified gc heap verify + LOG_ECMA(DEBUG) << "post unified gc heap verify"; + Verification(heap, VerifyKind::VERIFY_POST_GC).VerifyAll(); + } + }); +#ifdef PANDA_JS_ETS_HYBRID_MODE + unifiedGC_->FinishXGCBarrier(); +#endif // PANDA_JS_ETS_HYBRID_MODE + } +} + +void SharedHeap::CreateUnifiedGC() +{ + unifiedGC_ = new UnifiedGC(); +} + +void Heap::UnifiedGCPrepare() +{ + WaitRunningTaskFinished(); + sweeper_->EnsureAllTaskFinished(); + WaitClearTaskFinished(); +} + +void Heap::CreateUnifiedGCMarker() +{ + unifiedGCMarker_ = new UnifiedGCMarker(this); +} + +uint32_t BaseHeap::GetRunningTaskCount() +{ + LockHolder holder(waitTaskFinishedMutex_); + return runningTaskCount_; +} +} // namespace panda::ecmascript diff --git a/ecmascript/cross_vm/heap_hybrid.h b/ecmascript/cross_vm/heap_hybrid.h new file mode 100644 index 0000000000000000000000000000000000000000..6e27421b298aa422288b722b93afbba07835afac --- /dev/null +++ b/ecmascript/cross_vm/heap_hybrid.h @@ -0,0 +1,55 @@ +/* +* 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. +*/ +#ifndef ECMASCRIPT_CROSS_VM_HEAP_HYBRID_H +#define ECMASCRIPT_CROSS_VM_HEAP_HYBRID_H + +#define BASEHEAP_PUBLIC_HYBRID_EXTENSION() \ + void SetGCType(TriggerGCType gcType) \ + { \ + gcType_ = gcType; \ + } \ + uint32_t GetRunningTaskCount() + +#define SHAREDHEAP_PUBLIC_HYBRID_EXTENSION() \ + UnifiedGC *GetUnifiedGC() const \ + { \ + return unifiedGC_; \ + } \ + template \ + bool TriggerUnifiedGCMark(JSThread *thread) const; \ + void StartUnifiedGCMark(TriggerGCType gcType, GCReason gcReason); \ + void CreateUnifiedGC() + + +#define SHAREDHEAP_PRIVATE_HYBRID_EXTENSION() \ + UnifiedGC *unifiedGC_ {nullptr} + + +#define HEAP_PUBLIC_HYBRID_EXTENSION() \ + void UnifiedGCPrepare(); \ + UnifiedGCMarker *GetUnifiedGCMarker() const \ + { \ + return unifiedGCMarker_; \ + } \ + bool IsUnifiedGC() const \ + { \ + return gcType_ == TriggerGCType::UNIFIED_GC; \ + } \ + void CreateUnifiedGCMarker() + +#define HEAP_PRIVATE_HYBRID_EXTENSION() \ + UnifiedGCMarker *unifiedGCMarker_ {nullptr} + +#endif // ECMASCRIPT_CROSS_VM_HEAP_HYBRID_H diff --git a/ecmascript/cross_vm/js_hclass_hybrid.h b/ecmascript/cross_vm/js_hclass_hybrid.h new file mode 100644 index 0000000000000000000000000000000000000000..b5a0eb522d916b8a8edc38061435c59818f394c6 --- /dev/null +++ b/ecmascript/cross_vm/js_hclass_hybrid.h @@ -0,0 +1,24 @@ +/* +* 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. +*/ +#ifndef ECMASCRIPT_CROSS_VM_JS_HCLASS_HYBRID_H +#define ECMASCRIPT_CROSS_VM_JS_HCLASS_HYBRID_H + +#define JSHCLASS_PUBLIC_HYBRID_EXTENSION() \ + inline bool IsJSXRefObject() const \ + { \ + return GetObjectType() == JSType::JS_XREF_OBJECT; \ + } + +#endif // ECMASCRIPT_CROSS_VM_JS_HCLASS_HYBRID_H diff --git a/ecmascript/cross_vm/js_tagged_value_hybrid-inl.h b/ecmascript/cross_vm/js_tagged_value_hybrid-inl.h new file mode 100644 index 0000000000000000000000000000000000000000..ac2a3aa82eb20f8752cb0311e9f1e68016b04d62 --- /dev/null +++ b/ecmascript/cross_vm/js_tagged_value_hybrid-inl.h @@ -0,0 +1,27 @@ +/* +* 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. +*/ +#ifndef ECMASCRIPT_CROSS_VM_JS_TAGGED_VALUE_HYBRID_INL_H +#define ECMASCRIPT_CROSS_VM_JS_TAGGED_VALUE_HYBRID_INL_H + +#include "ecmascript/js_tagged_value.h" + +namespace panda::ecmascript { + + inline bool JSTaggedValue::IsJSXRefObject() const + { + return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSXRefObject(); + } +} +#endif // ECMASCRIPT_CROSS_VM_JS_HCLASS_HYBRID_H diff --git a/ecmascript/cross_vm/js_tagged_value_hybrid.h b/ecmascript/cross_vm/js_tagged_value_hybrid.h new file mode 100644 index 0000000000000000000000000000000000000000..2dddea3aa5dfb6bb129ad1721a6694819c1ed60b --- /dev/null +++ b/ecmascript/cross_vm/js_tagged_value_hybrid.h @@ -0,0 +1,20 @@ +/* +* 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. +*/ +#ifndef ECMASCRIPT_CROSS_VM_JS_TAGGED_VALUE_HYBRID_H +#define ECMASCRIPT_CROSS_VM_JS_TAGGED_VALUE_HYBRID_H + +#define JSTAGGEDVALUE_PUBLIC_HYBRID_EXTENSION() \ + bool IsJSXRefObject() const +#endif // ECMASCRIPT_CROSS_VM_JS_HCLASS_HYBRID_H diff --git a/ecmascript/cross_vm/js_thread_hybrid.cpp b/ecmascript/cross_vm/js_thread_hybrid.cpp new file mode 100644 index 0000000000000000000000000000000000000000..be9654976e2d49377b880674cfa5d59cb59f355a --- /dev/null +++ b/ecmascript/cross_vm/js_thread_hybrid.cpp @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#include "ecmascript/js_thread.h" +#include "ecmascript/ecma_global_storage.h" +#include "ecmascript/ecma_vm.h" + +namespace panda::ecmascript { + + void JSThread::SetupXRefFields() + { + if (!vm_->GetJSOptions().EnableGlobalLeakCheck()) { + newXRefGlobalHandle_ = [this](JSTaggedType value) { + return globalStorage_->NewGlobalHandle(value); + }; + disposeXRefGlobalHandle_ = [this](uintptr_t nodeAddr) { + globalStorage_->DisposeGlobalHandle(nodeAddr); + }; + setNodeKind_ = [this](NodeKind nodeKind) { globalStorage_->SetNodeKind(nodeKind); }; + } else { + newXRefGlobalHandle_ = [this](JSTaggedType value) { + return globalDebugStorage_->NewGlobalHandle(value); + }; + disposeXRefGlobalHandle_ = [this](uintptr_t nodeAddr) { + globalDebugStorage_->DisposeGlobalHandle(nodeAddr); + }; + setNodeKind_ = [this](NodeKind nodeKind) { globalDebugStorage_->SetNodeKind(nodeKind); }; + } + } +} \ No newline at end of file diff --git a/ecmascript/cross_vm/js_thread_hybrid.h b/ecmascript/cross_vm/js_thread_hybrid.h new file mode 100644 index 0000000000000000000000000000000000000000..f8b1dffcecaba05b714146ba5f2b0b531e3dd664 --- /dev/null +++ b/ecmascript/cross_vm/js_thread_hybrid.h @@ -0,0 +1,45 @@ +/* +* 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. +*/ +#ifndef ECMASCRIPT_CROSS_VM_JS_THREAD_HYBRID_H +#define ECMASCRIPT_CROSS_VM_JS_THREAD_HYBRID_H + +#define JSTHREAD_PUBLIC_HYBRID_EXTENSION() \ + inline uintptr_t NewXRefGlobalHandle(JSTaggedType value) \ + { \ + return newXRefGlobalHandle_(value); \ + } \ + inline void DisposeXRefGlobalHandle(uintptr_t nodeAddr) \ + { \ + disposeXRefGlobalHandle_(nodeAddr); \ + } \ + inline void SetNodeKind(NodeKind nodeKind) \ + { \ + setNodeKind_(nodeKind); \ + } \ + void SetStackStart(uint64_t stackStart) \ + { \ + glueData_.stackStart_ = stackStart; \ + } \ + void SetStackLimit(uint64_t stackLimit) \ + { \ + glueData_.stackLimit_ = stackLimit; \ + } \ + void SetupXRefFields() + +#define JSTHREAD_PRIVATE_HYBRID_EXTENSION() \ + std::function newXRefGlobalHandle_; \ + std::function disposeXRefGlobalHandle_; \ + std::function setNodeKind_ +#endif // ECMASCRIPT_CROSS_VM_JS_THREAD_HYBRID_H \ No newline at end of file diff --git a/ecmascript/cross_vm/jsnapi_expo_hybrid.cpp b/ecmascript/cross_vm/jsnapi_expo_hybrid.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f641ecebcb6ed1e0d530ca3601bd6b10cdcb5360 --- /dev/null +++ b/ecmascript/cross_vm/jsnapi_expo_hybrid.cpp @@ -0,0 +1,157 @@ +/* +* 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. +*/ +#include "ecmascript/napi/include/jsnapi_expo.h" + +#include "ecmascript/checkpoint/thread_state_transition.h" +#include "ecmascript/ecma_global_storage.h" +#include "ecmascript/module/napi_module_loader.h" +#include "ecmascript/module/module_path_helper.h" +#include "ecmascript/napi/jsnapi_helper.h" +#include "ecmascript/napi/include/jsnapi.h" +#include "ecmascript/global_env.h" + +namespace panda { +using ecmascript::JSTaggedValue; +template +using JSHandle = ecmascript::JSHandle; + +using ModulePathHelper = ecmascript::ModulePathHelper; +using ecmascript::ObjectFactory; + +Local StringRef::GetProxyNapiWrapperString(const EcmaVM *vm) +{ + // Omit exception check because ark calls here may not + // cause side effect even pending exception exists. + CROSS_THREAD_CHECK(vm); + ecmascript::ThreadManagedScope managedScope(thread); + JSHandle proxyNapiWapperString = thread->GlobalConstants()->GetHandledProxyNapiWrapperString(); + return JSNApiHelper::ToLocal(proxyNapiWapperString); +} + +Local ObjectRef::NewJSXRefObject(const EcmaVM *vm) +{ + CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm)); + ecmascript::ThreadManagedScope managedScope(thread); + ObjectFactory *factory = vm->GetFactory(); + JSHandle object(factory->NewJSXRefObject()); + return JSNApiHelper::ToLocal(object); +} + +void JSNApi::SetStackInfo(const EcmaVM *vm, const panda::StackInfo &info) +{ + JSThread *thread = vm->GetJSThread(); + thread->SetStackStart(info.stackStart); + thread->SetStackLimit(info.stackStart - info.stackSize); +} + +panda::StackInfo JSNApi::GetStackInfo(const EcmaVM *vm) +{ + JSThread *thread = vm->GetJSThread(); + size_t stackStart = thread->GetStackStart(); + size_t stackSize = stackStart - thread->GetStackLimit(); + return {stackStart, stackSize}; +} + +uintptr_t JSNApi::GetXRefGlobalHandleAddr(const EcmaVM *vm, uintptr_t localAddress) +{ + CROSS_THREAD_CHECK(vm); + if (localAddress == 0) { + return 0; + } + ecmascript::ThreadManagedScope scope(thread); + JSTaggedType value = *(reinterpret_cast(localAddress)); + return thread->NewXRefGlobalHandle(value); +} + + +void JSNApi::DisposeXRefGlobalHandleAddr(const EcmaVM *vm, uintptr_t addr) +{ + CROSS_THREAD_CHECK(vm); + if (addr == 0 || !reinterpret_cast(addr)->IsUsing()) { + return; + } + thread->DisposeXRefGlobalHandle(addr); +} + +#ifdef PANDA_JS_ETS_HYBRID_MODE +void JSNApi::MarkFromObject(const EcmaVM *vm, uintptr_t addr) +{ + if (addr == 0 || !reinterpret_cast(addr)->IsUsing()) { + return; + } + JSTaggedType value = *(reinterpret_cast(addr)); + vm->GetCrossVMOperator()->MarkFromObject(value); +} + +bool JSNApi::IsObjectAlive(const EcmaVM *vm, uintptr_t addr) +{ + if (addr == 0 || !reinterpret_cast(addr)->IsUsing()) { + return false; + } + JSTaggedType value = *(reinterpret_cast(addr)); + return vm->GetCrossVMOperator()->IsObjectAlive(value); +} + +bool JSNApi::IsValidHeapObject(const EcmaVM *vm, uintptr_t addr) +{ + if (addr == 0 || !reinterpret_cast(addr)->IsUsing()) { + return false; + } + JSTaggedType value = *(reinterpret_cast(addr)); + return vm->GetCrossVMOperator()->IsValidHeapObject(value); +} +#endif // PANDA_JS_ETS_HYBRID_MODE + +Local JSNApi::GetModuleNameSpaceWithPath(const EcmaVM *vm, const char *path) +{ + CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm)); + auto [filePath, recordName] = ModulePathHelper::ResolvePath(path); + ecmascript::ThreadManagedScope managedScope(thread); + JSHandle moduleNamespace = + ecmascript::NapiModuleLoader::LoadModuleNameSpaceFromFile(thread, recordName, filePath); + return JSNApiHelper::ToLocal(moduleNamespace); +} + +std::pair JSNApi::ResolveOhmUrl(std::string ohmUrl) +{ + return ModulePathHelper::ResolveOhmUrl(ohmUrl); +} + +#ifdef PANDA_JS_ETS_HYBRID_MODE +void HandshakeHelper::DoHandshake([[maybe_unused]] EcmaVM *vm, void *stsIface, void **ecmaIface) +{ + ecmascript::CrossVMOperator::DoHandshake(vm, stsIface, ecmaIface); +} +#endif // PANDA_JS_ETS_HYBRID_MODE + +void JSNApi::InitHybridVMEnv(EcmaVM *vm) +{ + auto instance = ecmascript::Runtime::GetInstance(); + ASSERT(instance != nullptr); + + CROSS_THREAD_AND_EXCEPTION_CHECK(vm); + ecmascript::ThreadManagedScope managedScope(thread); + + instance->SetHybridVm(true); + ecmascript::ObjectFactory *factory = vm->GetFactory(); + JSHandle env = vm->GetGlobalEnv(); + if (env->GetInterfaceTypeSymbol().GetTaggedValue().IsUndefined()) { + JSHandle interfaceTypeSymbol(factory->NewPrivateNameSymbolWithChar("interfaceType")); + env->SetInterfaceTypeSymbol(thread, interfaceTypeSymbol.GetTaggedValue()); + } + vm->CreateHybridParam(); +} + +} // namespace panda diff --git a/ecmascript/cross_vm/jsnapi_expo_hybrid.h b/ecmascript/cross_vm/jsnapi_expo_hybrid.h new file mode 100644 index 0000000000000000000000000000000000000000..a8bbe8b3574cf8bb1f1120e2a619c9ff1f0c4ca5 --- /dev/null +++ b/ecmascript/cross_vm/jsnapi_expo_hybrid.h @@ -0,0 +1,113 @@ +/* +* 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. +*/ +#ifndef ECMASCRIPT_CROSS_VM_JS_NAPI_EXPO_HYBRID_H +#define ECMASCRIPT_CROSS_VM_JS_NAPI_EXPO_HYBRID_H +#include +#include "ecmascript/base/aligned_struct.h" + +#define GLOBAL_PUBLIC_HYBRID_EXTENSION() \ + template \ + void CreateXRefGloablReference(const EcmaVM *vm, const Local ¤t); \ + /* This method must be called before Global is released.*/ \ + void FreeGlobalHandleAddr(); \ + void FreeXRefGlobalHandleAddr(); \ + void MarkFromObject(); \ + bool IsObjectAlive() const; \ + bool IsValidHeapObject() const + +#define OBJECTREF_PUBLIC_HYBRID_EXTENSION() \ + static Local NewJSXRefObject(const EcmaVM *vm) + +#define STRINGREF_PUBLIC_HYBRID_EXTENSION() \ + static Local GetProxyNapiWrapperString(const EcmaVM *vm) + +#define JSNAPI_PUBLIC_HYBRID_EXTENSION() \ + static void SetStackInfo(const EcmaVM *vm, const panda::StackInfo &info); \ + static panda::StackInfo GetStackInfo(const EcmaVM *vm); \ + static Local GetModuleNameSpaceWithPath(const EcmaVM *vm, const char *path); \ + static std::pair ResolveOhmUrl(std::string ohmUrl); \ + static void SetHostResolveBufferTracker(EcmaVM *vm, std::function cb); \ + static bool IsObjectAlive(const EcmaVM *vm, uintptr_t addr); \ + static bool IsValidHeapObject(const EcmaVM *vm, uintptr_t addr); \ + static void InitHybridVMEnv(EcmaVM *vm) + +#define JSNAPI_PRIVATE_HYBRID_EXTENSION() \ + static uintptr_t GetXRefGlobalHandleAddr(const EcmaVM *vm, uintptr_t localAddress); \ + static void DisposeXRefGlobalHandleAddr(const EcmaVM *vm, uintptr_t addr) + +#define JSNAPI_PRIVATE_HYBRID_MODE_EXTENSION() \ + static void MarkFromObject(const EcmaVM *vm, uintptr_t addr, std::function &visitor); \ + static void MarkFromObject(const EcmaVM *vm, uintptr_t addr) + +#define GLOBAL_PUBLIC_DEF_HYBRID_EXTENSION() \ + template \ + template \ + void Global::CreateXRefGloablReference(const EcmaVM *vm, const Local ¤t) \ + { \ + vm_ = vm; \ + if (!current.IsEmpty()) { \ + address_ = JSNApi::GetXRefGlobalHandleAddr(vm_, reinterpret_cast(*current));\ + } \ + } \ + template \ + void Global::FreeXRefGlobalHandleAddr() \ + { \ + if (address_ == 0) { \ + return; \ + } \ + JSNApi::DisposeXRefGlobalHandleAddr(vm_, address_); \ + address_ = 0; \ + } + +#define GLOBAL_PUBLIC_DEF_HYBRID_MODE_EXTENSION() \ + template \ + void Global::MarkFromObject() \ + { \ + if (address_ == 0) { \ + return; \ + } \ + JSNApi::MarkFromObject(vm_, address_); \ + } \ + template \ + bool Global::IsObjectAlive() const \ + { \ + if (address_ == 0) { \ + return false ; \ + } \ + return JSNApi::IsObjectAlive(vm_, address_); \ + } \ + template \ + bool Global::IsValidHeapObject() const \ + { \ + if (address_ == 0) { \ + return false; \ + } \ + return JSNApi::IsValidHeapObject(vm_, address_); \ + } + +namespace panda { +namespace ecmascript { + class EcmaVM; +} +using EcmaVM = ecmascript::EcmaVM; +#ifdef PANDA_JS_ETS_HYBRID_MODE +class PUBLIC_API HandshakeHelper final { + public: + static void DoHandshake(EcmaVM *vm, void *stsiface, void **ecmaiface); +}; +#endif // PANDA_JS_ETS_HYBRID_MODE +} +#endif // ECMASCRIPT_CROSS_VM_JS_NAPI_EXPO_HYBRID_H diff --git a/ecmascript/cross_vm/object_factory_hybrid.cpp b/ecmascript/cross_vm/object_factory_hybrid.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ee20863947029eac5f0f922f3eb10b14499a18f1 --- /dev/null +++ b/ecmascript/cross_vm/object_factory_hybrid.cpp @@ -0,0 +1,26 @@ +/* +* 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. +*/ +#include "ecmascript/object_factory.h" +#include "ecmascript/global_env_constants.h" +#include "ecmascript/dfx/native_module_failure_info.h" + +namespace panda::ecmascript { +JSHandle ObjectFactory::NewJSXRefObject() +{ + JSHandle jsXRefHClass = JSHandle::Cast(thread_->GlobalConstants()->GetHandledXRefObjectClass()); + JSHandle object(NewJSObject(jsXRefHClass)); + return object; +} +} // namespace panda::ecmascript diff --git a/ecmascript/cross_vm/object_factory_hybrid.h b/ecmascript/cross_vm/object_factory_hybrid.h new file mode 100644 index 0000000000000000000000000000000000000000..4b2e0187557e936c072aee512ccf232a07ebcc9f --- /dev/null +++ b/ecmascript/cross_vm/object_factory_hybrid.h @@ -0,0 +1,20 @@ +/* +* 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. +*/ +#ifndef ECMASCRIPT_CROSS_VM_OBJECT_FACTORY_HYBRID_H +#define ECMASCRIPT_CROSS_VM_OBJECT_FACTORY_HYBRID_H + +#define OBJECTFACTORY_PUBLIC_HYBRID_EXTENSION() \ + JSHandle PUBLIC_API NewJSXRefObject() +#endif // ECMASCRIPT_CROSS_VM_OBJECT_FACTORY_HYBRID_H diff --git a/ecmascript/mem/unified_gc/unified_gc.cpp b/ecmascript/cross_vm/unified_gc/unified_gc.cpp similarity index 96% rename from ecmascript/mem/unified_gc/unified_gc.cpp rename to ecmascript/cross_vm/unified_gc/unified_gc.cpp index 11939a04a3ab2cf4f7c77ff036b105a64e9a242f..c702af57c9e98b754b307a19051d0f4ffb0ead7b 100644 --- a/ecmascript/mem/unified_gc/unified_gc.cpp +++ b/ecmascript/cross_vm/unified_gc/unified_gc.cpp @@ -13,11 +13,12 @@ * limitations under the License. */ -#include "ecmascript/mem/unified_gc/unified_gc.h" +#include "ecmascript/cross_vm/unified_gc/unified_gc.h" #include "ecmascript/mem/concurrent_marker.h" -#include "ecmascript/mem/unified_gc/unified_gc_marker.h" #include "ecmascript/mem/verification.h" +#include "ecmascript/mem/heap.h" +#include "ecmascript/cross_vm/unified_gc/unified_gc_marker.h" namespace panda::ecmascript { #ifdef PANDA_JS_ETS_HYBRID_MODE diff --git a/ecmascript/mem/unified_gc/unified_gc.h b/ecmascript/cross_vm/unified_gc/unified_gc.h similarity index 100% rename from ecmascript/mem/unified_gc/unified_gc.h rename to ecmascript/cross_vm/unified_gc/unified_gc.h diff --git a/ecmascript/mem/unified_gc/unified_gc_marker-inl.h b/ecmascript/cross_vm/unified_gc/unified_gc_marker-inl.h similarity index 95% rename from ecmascript/mem/unified_gc/unified_gc_marker-inl.h rename to ecmascript/cross_vm/unified_gc/unified_gc_marker-inl.h index ce0d2336b95a3c8706c74439b16517ed220ba494..b321bfab2bad042b867a7fbe909d913753d9af2e 100644 --- a/ecmascript/mem/unified_gc/unified_gc_marker-inl.h +++ b/ecmascript/cross_vm/unified_gc/unified_gc_marker-inl.h @@ -17,7 +17,10 @@ #define ECMASCRIPT_MEM_UNIFIED_GC_UNIFIED_GC_MARKER_INL_H #include "ecmascript/js_thread.h" -#include "ecmascript/mem/unified_gc/unified_gc_marker.h" +#include "ecmascript/cross_vm/unified_gc/unified_gc_marker.h" +#include "ecmascript/cross_vm/work_manager_hybrid-inl.h" +#include "ecmascript/cross_vm/daemon_task_hybrid-inl.h" +#include "ecmascript/cross_vm/js_tagged_value_hybrid-inl.h" #include "ecmascript/layout_info.h" #include "ecmascript/mem/work_manager-inl.h" diff --git a/ecmascript/mem/unified_gc/unified_gc_marker.cpp b/ecmascript/cross_vm/unified_gc/unified_gc_marker.cpp similarity index 97% rename from ecmascript/mem/unified_gc/unified_gc_marker.cpp rename to ecmascript/cross_vm/unified_gc/unified_gc_marker.cpp index 188c4b1e0906a625e51eecfe9e0a5923d3bf5f37..6c641e54ea85760f4c0ee0e44d230bda3ba21740 100644 --- a/ecmascript/mem/unified_gc/unified_gc_marker.cpp +++ b/ecmascript/cross_vm/unified_gc/unified_gc_marker.cpp @@ -13,9 +13,9 @@ * limitations under the License. */ +#include "ecmascript/cross_vm/unified_gc/unified_gc_marker-inl.h" #include "ecmascript/checkpoint/thread_state_transition.h" #include "ecmascript/mem/concurrent_marker.h" -#include "ecmascript/mem/unified_gc/unified_gc_marker-inl.h" #include "ecmascript/mem/verification.h" namespace panda::ecmascript { diff --git a/ecmascript/mem/unified_gc/unified_gc_marker.h b/ecmascript/cross_vm/unified_gc/unified_gc_marker.h similarity index 100% rename from ecmascript/mem/unified_gc/unified_gc_marker.h rename to ecmascript/cross_vm/unified_gc/unified_gc_marker.h diff --git a/ecmascript/cross_vm/verification_hybrid.h b/ecmascript/cross_vm/verification_hybrid.h new file mode 100644 index 0000000000000000000000000000000000000000..95b9b26a12dea743a478ff9ed31bd3781552026f --- /dev/null +++ b/ecmascript/cross_vm/verification_hybrid.h @@ -0,0 +1,21 @@ +/* +* 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. +*/ +#ifndef ECMASCRIPT_CROSS_VERIFICATION_HYBRID_H +#define ECMASCRIPT_CROSS_VERIFICATION_HYBRID_H + +#define VERIFYOBJECTVISITOR_PRIVATE_HYBRID_EXTENSION() \ + void VerifyMarkUnified(TaggedObject *obj, ObjectSlot slot, TaggedObject *value) const + +#endif // ECMASCRIPT_CROSS_VERIFICATION_HYBRID_H \ No newline at end of file diff --git a/ecmascript/cross_vm/work_manager_hybrid-inl.h b/ecmascript/cross_vm/work_manager_hybrid-inl.h new file mode 100644 index 0000000000000000000000000000000000000000..fdeafddf761e48ae40eade01f467c6de3fdc078d --- /dev/null +++ b/ecmascript/cross_vm/work_manager_hybrid-inl.h @@ -0,0 +1,35 @@ +/* +* 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. +*/ +#ifndef ECMASCRIPT_CROSS_VM_WORK_MANAGER_INL_H +#define ECMASCRIPT_CROSS_VM_WORK_MANAGER_INL_H + +#include "ecmascript/mem/work_manager.h" + +#include "ecmascript/mem/incremental_marker.h" +#include "ecmascript/mem/tlab_allocator-inl.h" + +namespace panda::ecmascript { + void WorkManager::PushObjectToGlobal(TaggedObject *object) + { + WorkNode *tempNode = AllocateWorkNode(); + ASSERT(tempNode != nullptr); + tempNode->PushObject(ToUintPtr(object)); + workStack_.Push(tempNode); + if (heap_->IsParallelGCEnabled() && heap_->CheckCanDistributeTask() && !heap_->IsMarking()) { + heap_->PostParallelGCTask(parallelGCTaskPhase_); + } + } +} // namespace panda::ecmascript +#endif // ECMASCRIPT_CROSS_VM_WORK_MANAGER_HYBRID_H diff --git a/ecmascript/cross_vm/work_manager_hybrid.h b/ecmascript/cross_vm/work_manager_hybrid.h new file mode 100644 index 0000000000000000000000000000000000000000..1e0e614167cb6b680f3e4becd2c67a769eaf32ee --- /dev/null +++ b/ecmascript/cross_vm/work_manager_hybrid.h @@ -0,0 +1,20 @@ +/* +* 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. +*/ +#ifndef ECMASCRIPT_CROSS_VM_WORK_MANAGER_HYBRID_H +#define ECMASCRIPT_CROSS_VM_WORK_MANAGER_HYBRID_H + +#define WORKMANAGER_PUBLIC_HYBRID_EXTENSION() \ + void PushObjectToGlobal(TaggedObject *object) +#endif // ECMASCRIPT_CROSS_VM_WORK_MANAGER_HYBRID_H diff --git a/ecmascript/daemon/daemon_task-inl.h b/ecmascript/daemon/daemon_task-inl.h index 6ed420f24a4eba4633578d1c1112a188e7e5cece..a6efb0caf9c21fdfe2186251ea3cd9148e428143 100644 --- a/ecmascript/daemon/daemon_task-inl.h +++ b/ecmascript/daemon/daemon_task-inl.h @@ -44,17 +44,6 @@ TriggerCollectGarbageTask::TriggerCollectGarbageTask(JSThread : DaemonTask(thread, DaemonTaskType::TRIGGER_COLLECT_GARBAGE, DaemonTaskGroup::GC_GROUP, &TriggerCollectGarbageTaskRunner) {} -template -void TriggerUnifiedGCMarkTaskRunner() -{ - SharedHeap::GetInstance()->StartUnifiedGCMark(gcType, gcReason); -} - -template -TriggerUnifiedGCMarkTask::TriggerUnifiedGCMarkTask(JSThread *thread) - : DaemonTask(thread, DaemonTaskType::TRIGGER_UNIFIED_GC_MARK, DaemonTaskGroup::GC_GROUP, - &TriggerUnifiedGCMarkTaskRunner) {} - inline void TerminateDaemonTaskRunner() { DaemonThread *thread = DaemonThread::GetInstance(); diff --git a/ecmascript/daemon/daemon_task.h b/ecmascript/daemon/daemon_task.h index 0b8d6acaef9a9d444df9d15aef01befd8d38744d..829d5634d06be196e45f2f1f956c8fa1fa5e70ca 100644 --- a/ecmascript/daemon/daemon_task.h +++ b/ecmascript/daemon/daemon_task.h @@ -89,7 +89,6 @@ class TriggerCollectGarbageTask : public DaemonTask { public: explicit TriggerCollectGarbageTask(JSThread *thread); }; - template class TriggerUnifiedGCMarkTask : public DaemonTask { public: diff --git a/ecmascript/ecma_global_storage.h b/ecmascript/ecma_global_storage.h index 5771c92d6f3db3d667b642cd9b9805cf43124d19..9db5a1b1311df5c8e16ca88495252803c43aed8e 100644 --- a/ecmascript/ecma_global_storage.h +++ b/ecmascript/ecma_global_storage.h @@ -16,6 +16,8 @@ #ifndef ECMASCRIPT_ECMA_GLOBAL_STORAGE_H #define ECMASCRIPT_ECMA_GLOBAL_STORAGE_H +#include "ecmascript/cross_vm/ecma_global_storage_hybrid.h" + #include "ecmascript/js_thread.h" #include "ecmascript/mem/native_area_allocator.h" #include "ecmascript/mem/c_containers.h" @@ -511,20 +513,10 @@ public: IterateNodeList(callback, topWeakGlobalNodes_); } - void SetNodeKind(NodeKind nodeKind) - { - nodeKind_ = nodeKind; - } - - NodeKind GetNodeKind() - { - return nodeKind_; - } - + ECMAGLOBALSTORAGE_PUBLIC_HYBRID_EXTENSION() private: NO_COPY_SEMANTIC(EcmaGlobalStorage); NO_MOVE_SEMANTIC(EcmaGlobalStorage); - template inline void DisposeGlobalHandleInner(S *node, NodeList **freeList, NodeList **topNodes, NodeList **lastNodes) @@ -598,19 +590,15 @@ private: } [[maybe_unused]] JSThread *thread_ {nullptr}; - NodeKind nodeKind_ {NodeKind::NORMAL_NODE}; NativeAreaAllocator *allocator_ {nullptr}; NodeList *topGlobalNodes_ {nullptr}; NodeList *lastGlobalNodes_ {nullptr}; NodeList *freeListNodes_ {nullptr}; - NodeList *topXRefGlobalNodes_ {nullptr}; - NodeList *lastXRefGlobalNodes_ {nullptr}; - NodeList *xRefFreeListNodes_ {nullptr}; - NodeList *topWeakGlobalNodes_ {nullptr}; NodeList *lastWeakGlobalNodes_ {nullptr}; NodeList *weakFreeListNodes_ {nullptr}; + ECMAGLOBALSTORAGE_PRIVATE_HYBRID_EXTENSION(); }; } // namespace panda::ecmascript #endif // ECMASCRIPT_ECMA_GLOBAL_STORAGE_H diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index 6365f8406c13f7c6cb217bd5625d146bcd046dbf..62d3f974495ed82674e7bf155785e5593bb927ae 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -339,7 +339,10 @@ bool EcmaVM::Initialize() heap_ = new Heap(this); heap_->Initialize(); #ifdef PANDA_JS_ETS_HYBRID_MODE - crossVMOperator_ = new CrossVMOperator(this); + if (Runtime::GetInstance()->IsHybridVm()) { + crossVMOperator_ = new CrossVMOperator(this); + } + #endif // PANDA_JS_ETS_HYBRID_MODE gcStats_ = chunk_.New(heap_, options_.GetLongPauseTime()); gcKeyStats_ = chunk_.New(heap_, gcStats_); @@ -501,7 +504,7 @@ EcmaVM::~EcmaVM() } #ifdef PANDA_JS_ETS_HYBRID_MODE - if (crossVMOperator_ != nullptr) { + if (Runtime::GetInstance()->IsHybridVm() && crossVMOperator_ != nullptr) { delete crossVMOperator_; crossVMOperator_ = nullptr; } diff --git a/ecmascript/ecma_vm.h b/ecmascript/ecma_vm.h index 3e128cf2cf4f50264b291cf0b64daa3d3965550e..9e2fc03b596bf059af3c9288a431b313b956a943 100644 --- a/ecmascript/ecma_vm.h +++ b/ecmascript/ecma_vm.h @@ -16,6 +16,8 @@ #ifndef ECMASCRIPT_ECMA_VM_H #define ECMASCRIPT_ECMA_VM_H +#include "ecmascript/cross_vm/ecma_vm_hybrid.h" + #include #ifdef PANDA_JS_ETS_HYBRID_MODE @@ -1331,15 +1333,12 @@ public: } #ifdef PANDA_JS_ETS_HYBRID_MODE - CrossVMOperator* GetCrossVMOperator() const - { - return crossVMOperator_; - } -#endif // PANDA_JS_ETS_HYBRID_MODE + ECMAVM_PUBLIC_HYBRID_MODE_EXTENSION() +#endif /* PANDA_JS_ETS_HYBRID_MODE */ + ECMAVM_PUBLIC_HYBRID_EXTENSION(); protected: - - void PrintJSErrorInfo(const JSHandle &exceptionInfo) const; + ECMAVM_PROTECTED_HYBRID_EXTENSION(); private: void ClearBufferData(); @@ -1550,13 +1549,7 @@ private: JSTaggedValue registerSymbols_ {JSTaggedValue::Hole()}; JSTaggedValue microJobQueue_ {JSTaggedValue::Hole()}; std::atomic isProcessingPendingJob_{false}; - std::unordered_map dataViewTypeTable_; - -#ifdef PANDA_JS_ETS_HYBRID_MODE - CrossVMOperator* crossVMOperator_ {nullptr}; -#endif // PANDA_JS_ETS_HYBRID_MODE - #if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT // Stats for Thread-State-Transition and String-Table Locks bool isCollectingScopeLockStats_ = false; @@ -1622,6 +1615,9 @@ private: // store Application versionCode uint32_t applicationVersionCode_ {0}; +#ifdef PANDA_JS_ETS_HYBRID_MODE + ECMAVM_PRIVATE_HYBRID_EXTENSION(); +#endif /* PANDA_JS_ETS_HYBRID_MODE */ }; } // namespace ecmascript } // namespace panda diff --git a/ecmascript/global_env_constants.cpp b/ecmascript/global_env_constants.cpp index e0ef402f5e9d6df38391451bb7e936a37dfedf97..da1b2c02efdfdad1b1797e7d96a35a72ffd5d012 100644 --- a/ecmascript/global_env_constants.cpp +++ b/ecmascript/global_env_constants.cpp @@ -449,8 +449,10 @@ void GlobalEnvConstants::InitRootsClassesPartTwo(JSHClass *hClass, ObjectFactory JSType::JS_API_LIGHT_WEIGHT_SET_ITERATOR)); SetConstant(ConstantIndex::JS_API_BITVECTOR_ITERATOR_CLASS_INDEX, factory->NewEcmaHClass(hClass, JSAPIBitVectorIterator::SIZE, JSType::JS_API_BITVECTOR_ITERATOR)); - SetConstant(ConstantIndex::XREF_OBJECT_HCLASS_INDEX, - factory->NewEcmaHClass(hClass, JSObject::SIZE, JSType::JS_XREF_OBJECT)); + if (Runtime::GetInstance()->IsHybridVm()) { + SetConstant(ConstantIndex::XREF_OBJECT_HCLASS_INDEX, + factory->NewEcmaHClass(hClass, JSObject::SIZE, JSType::JS_XREF_OBJECT)); + } } void GlobalEnvConstants::InitRootsClasses(ObjectFactory *factory) diff --git a/ecmascript/global_env_constants.h b/ecmascript/global_env_constants.h index da4320cd0e40927e1a858a1c7d4ca631edc58f33..4f2e5e7bc962f61d9deedbef655062d47e8e877e 100644 --- a/ecmascript/global_env_constants.h +++ b/ecmascript/global_env_constants.h @@ -15,12 +15,12 @@ #ifndef ECMASCRIPT_GLOBAL_ENV_CONSTANTS_H #define ECMASCRIPT_GLOBAL_ENV_CONSTANTS_H - #include #include "ecmascript/compiler/builtins/builtins_call_signature_list.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/mem/visitor.h" #include "libpandabase/macros.h" +#include "ecmascript/cross_vm/global_env_constants_hybrid.h" namespace panda::ecmascript { // Forward Declaration @@ -143,9 +143,9 @@ class ObjectFactory; V(JSTaggedValue, JSAPITreeMapIteratorClass, JS_API_TREE_MAP_ITERATOR_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, JSAPITreeSetIteratorClass, JS_API_TREE_SET_ITERATOR_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, ObjectClass, OBJECT_HCLASS_INDEX, initial_object_hclass) \ - V(JSTaggedValue, XRefObjectClass, XREF_OBJECT_HCLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, ClassPrototypeClass, CLASS_PROTOTYPE_HCLASS_INDEX, ecma_roots_class) \ - V(JSTaggedValue, ClassConstructorClass, CLASS_CONSTRUCTOR_HCLASS_INDEX, ecma_roots_class) + V(JSTaggedValue, ClassConstructorClass, CLASS_CONSTRUCTOR_HCLASS_INDEX, ecma_roots_class) \ + GLOBAL_ENV_CONSTANT_CLASS_HYBRID(V) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define GLOBAL_ENV_CONSTANT_SPECIAL(V) \ @@ -461,7 +461,6 @@ class ObjectFactory; V(CjsExportsString, CJS_EXPORTS_INDEX, "exports") \ V(CjsCacheString, CJS_CACHE_INDEX, "_cache") \ V(NapiWrapperString, NAPI_WRAPPER_INDEX, "_napiwrapper") \ - V(ProxyNapiWrapperString, PROXY_NAPI_WRAPPER_INDEX, "_proxynapiwrapper") \ /* for require native module */ \ V(RequireNativeModuleString, REQUIRE_NATIVE_MOUDULE_FUNC_INDEX, "requireNativeModule") \ V(RequireNapiString, REQUIRE_NAPI_FUNC_INDEX, "requireNapi") \ @@ -497,10 +496,10 @@ class ObjectFactory; V(SharedPartialGcCause, SHARED_PARTIAL_GC_CAUSE, "shared_partial") \ V(SharedFullGcCause, SHARED_FULL_GC_CAUSE, "shared_full") \ V(AppSpawnSharedFullGcCause, APP_SPAWN_SHARED_FULL_GC_CAUSE, "app_spawn_shared_full") \ - V(UnifiedGcCause, UNIFIED_GC_CAUSE, "unified") \ V(SymbolLeftParentheses, SYMBOL_LEFT_PARENTHESES, "Symbol(") \ V(InteropJsNapiString, INTEROP_JS_NAPI, "ets_interop_js_napi") \ - V(GetModuleString, GET_MODULE, "getModule") + V(GetModuleString, GET_MODULE, "getModule") \ + SHARED_GLOBAL_ENV_CONSTANT_STRING_HYBRID(V) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define SHARED_GLOBAL_ENV_CONSTANT_ACCESSOR(V) \ diff --git a/ecmascript/js_hclass.h b/ecmascript/js_hclass.h index 5b4acbc7f29c14b16251264e7d5143bf51f48187..349a7c948c8d4bf4b7d265bd23875ecb475f03d8 100644 --- a/ecmascript/js_hclass.h +++ b/ecmascript/js_hclass.h @@ -16,6 +16,8 @@ #ifndef ECMASCRIPT_JS_HCLASS_H #define ECMASCRIPT_JS_HCLASS_H +#include "ecmascript/cross_vm/js_hclass_hybrid.h" + #include "ecmascript/ecma_macros.h" #include "ecmascript/elements.h" #include "ecmascript/js_tagged_value.h" @@ -1657,11 +1659,6 @@ public: return GetObjectType() == JSType::JS_PROMISE; } - inline bool IsJSXRefObject() const - { - return GetObjectType() == JSType::JS_XREF_OBJECT; - } - inline bool IsResolvingFunctionsRecord() const { return GetObjectType() == JSType::RESOLVING_FUNCTIONS_RECORD; @@ -2172,6 +2169,7 @@ public: bool isFunction = false); static JSHandle CreateSConstructorHClass(JSThread *thread, const std::vector &descs); static JSHandle CreateSPrototypeHClass(JSThread *thread, const std::vector &descs); + JSHCLASS_PUBLIC_HYBRID_EXTENSION() private: diff --git a/ecmascript/js_tagged_value-inl.h b/ecmascript/js_tagged_value-inl.h index f4676e7a34ce342d7a8edd6033a6c9bfdd646b20..f07aaee73a09f6988a22e11b953e17b754fa0683 100644 --- a/ecmascript/js_tagged_value-inl.h +++ b/ecmascript/js_tagged_value-inl.h @@ -405,11 +405,6 @@ inline bool JSTaggedValue::IsJSPromise() const return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSPromise(); } -inline bool JSTaggedValue::IsJSXRefObject() const -{ - return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSXRefObject(); -} - inline bool JSTaggedValue::IsRecord() const { return IsHeapObject() && GetTaggedObject()->GetClass()->IsRecord(); diff --git a/ecmascript/js_tagged_value.h b/ecmascript/js_tagged_value.h index 5c5de0460dbcf4f3ff8ce01843a23dff56c12386..c42a4fe93c44d55f1a50dd0e9590cbaa73966b26 100644 --- a/ecmascript/js_tagged_value.h +++ b/ecmascript/js_tagged_value.h @@ -21,6 +21,7 @@ #include "ecmascript/mem/c_string.h" #include "ecmascript/mem/mem_common.h" #include "ecmascript/js_tagged_value_internals.h" +#include "ecmascript/cross_vm/js_tagged_value_hybrid.h" namespace panda::ecmascript { class JSArray; @@ -640,7 +641,6 @@ public: bool IsAsyncGeneratorObject() const; bool IsAsyncFuncObject() const; bool IsJSPromise() const; - bool IsJSXRefObject() const; bool IsRecord() const; bool IsPromiseReaction() const; bool IsProgram() const; @@ -786,7 +786,7 @@ public: value.Dump(THREAD_ARG_PLACEHOLDER, os); // Dump() will handle nullptr as current thread return os; } - + JSTAGGEDVALUE_PUBLIC_HYBRID_EXTENSION(); private: JSTaggedType value_; diff --git a/ecmascript/js_thread.cpp b/ecmascript/js_thread.cpp index 8b3327e1f876181eff02f5e77a5369ef90a20f80..3954be1aeac6a9bd4fff1106de2502d69e53ba73 100644 --- a/ecmascript/js_thread.cpp +++ b/ecmascript/js_thread.cpp @@ -168,43 +168,47 @@ JSThread::JSThread(EcmaVM *vm) : id_(os::thread::GetCurrentThreadId()), vm_(vm) newGlobalHandle_ = [this](JSTaggedType value) { return globalStorage_->NewGlobalHandle(value); }; - newXRefGlobalHandle_ = [this](JSTaggedType value) { - return globalStorage_->NewGlobalHandle(value); - }; disposeGlobalHandle_ = [this](uintptr_t nodeAddr) { globalStorage_->DisposeGlobalHandle(nodeAddr); }; - disposeXRefGlobalHandle_ = [this](uintptr_t nodeAddr) { - globalStorage_->DisposeGlobalHandle(nodeAddr); - }; + if (Runtime::GetInstance()->IsHybridVm()) { + newXRefGlobalHandle_ = [this](JSTaggedType value) { + return globalStorage_->NewGlobalHandle(value); + }; + disposeXRefGlobalHandle_ = [this](uintptr_t nodeAddr) { + globalStorage_->DisposeGlobalHandle(nodeAddr); + }; + setNodeKind_ = [this](NodeKind nodeKind) { globalStorage_->SetNodeKind(nodeKind); }; + } setWeak_ = [this](uintptr_t nodeAddr, void *ref, WeakClearCallback freeGlobalCallBack, WeakClearCallback nativeFinalizeCallBack) { return globalStorage_->SetWeak(nodeAddr, ref, freeGlobalCallBack, nativeFinalizeCallBack); }; clearWeak_ = [this](uintptr_t nodeAddr) { return globalStorage_->ClearWeak(nodeAddr); }; isWeak_ = [this](uintptr_t addr) { return globalStorage_->IsWeak(addr); }; - setNodeKind_ = [this](NodeKind nodeKind) { globalStorage_->SetNodeKind(nodeKind); }; } else { globalDebugStorage_ = chunk->New>(this, vm->GetNativeAreaAllocator()); newGlobalHandle_ = [this](JSTaggedType value) { return globalDebugStorage_->NewGlobalHandle(value); }; - newXRefGlobalHandle_ = [this](JSTaggedType value) { - return globalDebugStorage_->NewGlobalHandle(value); - }; disposeGlobalHandle_ = [this](uintptr_t nodeAddr) { globalDebugStorage_->DisposeGlobalHandle(nodeAddr); }; - disposeXRefGlobalHandle_ = [this](uintptr_t nodeAddr) { - globalDebugStorage_->DisposeGlobalHandle(nodeAddr); - }; setWeak_ = [this](uintptr_t nodeAddr, void *ref, WeakClearCallback freeGlobalCallBack, WeakClearCallback nativeFinalizeCallBack) { return globalDebugStorage_->SetWeak(nodeAddr, ref, freeGlobalCallBack, nativeFinalizeCallBack); }; clearWeak_ = [this](uintptr_t nodeAddr) { return globalDebugStorage_->ClearWeak(nodeAddr); }; isWeak_ = [this](uintptr_t addr) { return globalDebugStorage_->IsWeak(addr); }; - setNodeKind_ = [this](NodeKind nodeKind) { globalDebugStorage_->SetNodeKind(nodeKind); }; + if (Runtime::GetInstance()->IsHybridVm()) { + newXRefGlobalHandle_ = [this](JSTaggedType value) { + return globalDebugStorage_->NewGlobalHandle(value); + }; + disposeXRefGlobalHandle_ = [this](uintptr_t nodeAddr) { + globalDebugStorage_->DisposeGlobalHandle(nodeAddr); + }; + setNodeKind_ = [this](NodeKind nodeKind) { globalDebugStorage_->SetNodeKind(nodeKind); }; + } } vmThreadControl_ = new VmThreadControl(this); SetBCStubStatus(BCStubStatus::NORMAL_BC_STUB); diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index 8373458b39d45d523790d62772d75ffa9a2c0cc8..2d194bcb4227bad5f0c764f170953e16b8e5f573 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -41,6 +41,7 @@ #include "common_interfaces/base_runtime.h" #include "common_interfaces/thread/base_thread.h" #include "common_interfaces/thread/thread_holder.h" +#include "ecmascript/cross_vm/js_thread_hybrid.h" #if defined(ENABLE_FFRT_INTERFACES) #include "ffrt.h" @@ -923,21 +924,11 @@ public: return newGlobalHandle_(value); } - inline uintptr_t NewXRefGlobalHandle(JSTaggedType value) - { - return newXRefGlobalHandle_(value); - } - inline void DisposeGlobalHandle(uintptr_t nodeAddr) { disposeGlobalHandle_(nodeAddr); } - inline void DisposeXRefGlobalHandle(uintptr_t nodeAddr) - { - disposeXRefGlobalHandle_(nodeAddr); - } - inline uintptr_t SetWeak(uintptr_t nodeAddr, void *ref = nullptr, WeakClearCallback freeGlobalCallBack = nullptr, WeakClearCallback nativeFinalizeCallBack = nullptr) { @@ -954,11 +945,6 @@ public: return isWeak_(addr); } - inline void SetNodeKind(NodeKind nodeKind) - { - setNodeKind_(nodeKind); - } - void EnableCrossThreadExecution() { glueData_.allowCrossThreadExecution_ = true; @@ -1592,16 +1578,6 @@ public: }; STATIC_ASSERT_EQ_ARCH(sizeof(GlueData), GlueData::SizeArch32, GlueData::SizeArch64); - void SetStackStart(uint64_t stackStart) - { - glueData_.stackStart_ = stackStart; - } - - void SetStackLimit(uint64_t stackLimit) - { - glueData_.stackLimit_ = stackLimit; - } - JSTaggedValue GetSingleCharTable() const { ASSERT(glueData_.globalConst_->GetSingleCharTable() != JSTaggedValue::Hole()); @@ -1989,7 +1965,7 @@ public: << "---------------------------------------------------------"; ClearMegaStat(); } - + JSTHREAD_PUBLIC_HYBRID_EXTENSION(); protected: void SetThreadId() { @@ -2062,14 +2038,11 @@ private: EcmaGlobalStorage *globalDebugStorage_ {nullptr}; int32_t stackTraceFd_ {-1}; std::function newGlobalHandle_; - std::function newXRefGlobalHandle_; std::function disposeGlobalHandle_; - std::function disposeXRefGlobalHandle_; std::function setWeak_; std::function clearWeak_; std::function isWeak_; - std::function setNodeKind_; NativePointerTaskCallback asyncCleanTaskCb_ {nullptr}; WeakFinalizeTaskCallback finalizeTaskCallback_ {nullptr}; uint32_t globalNumberCount_ {0}; @@ -2133,6 +2106,7 @@ private: bool isInConcurrentScope_ {false}; JSTaggedValue hotReloadDependInfo_ {JSTaggedValue::Undefined()}; + JSTHREAD_PRIVATE_HYBRID_EXTENSION(); friend class GlobalHandleCollection; friend class EcmaVM; diff --git a/ecmascript/mem/dynamic_object_operator.cpp b/ecmascript/mem/dynamic_object_operator.cpp index e1f0f1add294093a654ed406ac09a9812965893c..368ff6114c3fe6a589c74d7b5f837e925c5f0204 100644 --- a/ecmascript/mem/dynamic_object_operator.cpp +++ b/ecmascript/mem/dynamic_object_operator.cpp @@ -15,6 +15,7 @@ #include "ecmascript/mem/dynamic_object_operator.h" #include "ecmascript/mem/object_xray.h" +#include "ecmascript/cross_vm/js_tagged_value_hybrid-inl.h" namespace panda::ecmascript { diff --git a/ecmascript/mem/heap-inl.h b/ecmascript/mem/heap-inl.h index 9e8a240e598de21840705aa576d64fdb9a39c411..5584b0122c9d9f23a603ed6f729fd723425dc48a 100644 --- a/ecmascript/mem/heap-inl.h +++ b/ecmascript/mem/heap-inl.h @@ -22,6 +22,7 @@ #include "ecmascript/base/config.h" #include "ecmascript/mem/heap.h" +#include "ecmascript/cross_vm/daemon_task_hybrid-inl.h" #include "ecmascript/base/block_hook_scope.h" #include "ecmascript/daemon/daemon_task-inl.h" #include "ecmascript/dfx/hprof/heap_tracker.h" @@ -1287,13 +1288,6 @@ void SharedHeap::PostGCTaskForTest(JSThread *thread) } } -template -bool SharedHeap::TriggerUnifiedGCMark(JSThread *thread) const -{ - ASSERT(gcType == TriggerGCType::UNIFIED_GC && gcReason == GCReason::CROSSREF_CAUSE); - return DaemonThread::GetInstance()->CheckAndPostTask(TriggerUnifiedGCMarkTask(thread)); -} - static void SwapBackAndPop(NativePointerList &vec, NativePointerList::iterator &iter) { *iter = vec.back(); diff --git a/ecmascript/mem/heap.cpp b/ecmascript/mem/heap.cpp index 44f31725f1baeb0d9ab51dbda2bd30a859e10ba7..d4fa6e42181734bbad41de3a33245a6b0c4b9084 100644 --- a/ecmascript/mem/heap.cpp +++ b/ecmascript/mem/heap.cpp @@ -30,8 +30,8 @@ #include "ecmascript/mem/shared_heap/shared_gc.h" #include "ecmascript/mem/shared_heap/shared_full_gc.h" #include "ecmascript/mem/shared_heap/shared_concurrent_marker.h" -#include "ecmascript/mem/unified_gc/unified_gc.h" -#include "ecmascript/mem/unified_gc/unified_gc_marker.h" +#include "ecmascript/cross_vm/unified_gc/unified_gc.h" +#include "ecmascript/cross_vm/unified_gc/unified_gc_marker.h" #include "ecmascript/mem/verification.h" #include "ecmascript/runtime_call_id.h" #include "ecmascript/jit/jit.h" @@ -310,7 +310,7 @@ void SharedHeap::Destroy() delete sharedMemController_; sharedMemController_ = nullptr; } - if (unifiedGC_ != nullptr) { + if (Runtime::GetInstance()->IsHybridVm() && unifiedGC_ != nullptr) { delete unifiedGC_; unifiedGC_ = nullptr; } @@ -333,7 +333,9 @@ void SharedHeap::PostInitialization(const GlobalEnvConstants *globalEnvConstants sharedGC_ = new SharedGC(this); sEvacuator_ = new SharedGCEvacuator(this); sharedFullGC_ = new SharedFullGC(this); - unifiedGC_ = new UnifiedGC(); + if (Runtime::GetInstance()->IsHybridVm()) { + unifiedGC_ = new UnifiedGC(); + } } void SharedHeap::PostGCMarkingTask(SharedParallelMarkPhase sharedTaskPhase) @@ -836,54 +838,6 @@ void SharedHeap::DumpHeapSnapshotBeforeOOM([[maybe_unused]]bool isFullGC, [[mayb #endif // ECMASCRIPT_SUPPORT_SNAPSHOT } -void SharedHeap::StartUnifiedGCMark([[maybe_unused]]TriggerGCType gcType, [[maybe_unused]]GCReason gcReason) -{ - ASSERT(gcType == TriggerGCType::UNIFIED_GC && gcReason == GCReason::CROSSREF_CAUSE); - ASSERT(JSThread::GetCurrent() == dThread_); - { - ThreadManagedScope runningScope(dThread_); - SuspendAllScope scope(dThread_); - Runtime *runtime = Runtime::GetInstance(); - std::vector recurScopes; - // The approximate size is enough, because even if some thread creates and registers after here, it will keep - // waiting in transition to RUNNING state before JSThread::SetReadyForGCIterating. - recurScopes.reserve(runtime->ApproximateThreadListSize()); - runtime->GCIterateThreadList([&recurScopes](JSThread *thread) { - Heap *heap = const_cast(thread->GetEcmaVM()->GetHeap()); - recurScopes.emplace_back(heap, HeapType::LOCAL_HEAP); - }); -#ifdef PANDA_JS_ETS_HYBRID_MODE - if (!unifiedGC_->StartXGCBarrier()) { - unifiedGC_->SetInterruptUnifiedGC(false); - dThread_->FinishRunningTask(); - return; - } -#endif // PANDA_JS_ETS_HYBRID_MODE - runtime->GCIterateThreadList([gcType](JSThread *thread) { - Heap *heap = const_cast(thread->GetEcmaVM()->GetHeap()); - if (UNLIKELY(heap->ShouldVerifyHeap())) { // LCOV_EXCL_BR_LINE - // pre unified gc heap verify - LOG_ECMA(DEBUG) << "pre unified gc heap verify"; - heap->ProcessSharedGCRSetWorkList(); - Verification(heap, VerifyKind::VERIFY_PRE_GC).VerifyAll(); - } - heap->SetGCType(gcType); - }); - unifiedGC_->RunPhases(); - runtime->GCIterateThreadList([](JSThread *thread) { - Heap *heap = const_cast(thread->GetEcmaVM()->GetHeap()); - if (UNLIKELY(heap->ShouldVerifyHeap())) { // LCOV_EXCL_BR_LINE - // post unified gc heap verify - LOG_ECMA(DEBUG) << "post unified gc heap verify"; - Verification(heap, VerifyKind::VERIFY_POST_GC).VerifyAll(); - } - }); -#ifdef PANDA_JS_ETS_HYBRID_MODE - unifiedGC_->FinishXGCBarrier(); -#endif // PANDA_JS_ETS_HYBRID_MODE - } -} - Heap::Heap(EcmaVM *ecmaVm) : BaseHeap(ecmaVm->GetEcmaParamConfiguration()), ecmaVm_(ecmaVm), thread_(ecmaVm->GetJSThread()), sHeap_(SharedHeap::GetInstance()) {} @@ -973,7 +927,9 @@ void Heap::Initialize() EnableConcurrentMarkType::CONFIG_DISABLE); nonMovableMarker_ = new NonMovableMarker(this); compressGCMarker_ = new CompressGCMarker(this); - unifiedGCMarker_ = new UnifiedGCMarker(this); + if (Runtime::GetInstance()->IsHybridVm()) { + unifiedGCMarker_ = new UnifiedGCMarker(this); + } evacuator_ = new ParallelEvacuator(this); incrementalMarker_ = new IncrementalMarker(this); gcListeners_.reserve(16U); @@ -1176,7 +1132,7 @@ void Heap::Destroy() delete compressGCMarker_; compressGCMarker_ = nullptr; } - if (unifiedGCMarker_ != nullptr) { + if (Runtime::GetInstance()->IsHybridVm() && unifiedGCMarker_ != nullptr) { delete unifiedGCMarker_; unifiedGCMarker_ = nullptr; } @@ -1194,13 +1150,6 @@ void Heap::Prepare() WaitClearTaskFinished(); } -void Heap::UnifiedGCPrepare() -{ - WaitRunningTaskFinished(); - sweeper_->EnsureAllTaskFinished(); - WaitClearTaskFinished(); -} - void Heap::GetHeapPrepare() { // Ensure local and shared heap prepared. @@ -2914,7 +2863,9 @@ void Heap::UpdateWorkManager(WorkManager *workManager) incrementalMarker_->workManager_ = workManager; nonMovableMarker_->workManager_ = workManager; compressGCMarker_->workManager_ = workManager; - unifiedGCMarker_->workManager_ = workManager; + if (Runtime::GetInstance()->IsHybridVm()) { + unifiedGCMarker_->workManager_ = workManager; + } partialGC_->workManager_ = workManager; } @@ -3070,12 +3021,6 @@ void BaseHeap::WaitRunningTaskFinished() } } -uint32_t BaseHeap::GetRunningTaskCount() -{ - LockHolder holder(waitTaskFinishedMutex_); - return runningTaskCount_; -} - bool BaseHeap::CheckCanDistributeTask() { LockHolder holder(waitTaskFinishedMutex_); diff --git a/ecmascript/mem/heap.h b/ecmascript/mem/heap.h index 0d9cc442fc2c9526d48e4c4205e2de1eb9c5cb48..b93f12a419aafed14ccbc1c4cf0c53c24cf04ea4 100644 --- a/ecmascript/mem/heap.h +++ b/ecmascript/mem/heap.h @@ -29,6 +29,7 @@ #include "ecmascript/mem/visitor.h" #include "ecmascript/mem/work_manager.h" #include "ecmascript/napi/include/jsnapi_expo.h" +#include "ecmascript/cross_vm/heap_hybrid.h" namespace panda::test { class GCTest_CallbackTask_Test; @@ -220,11 +221,6 @@ public: return markType_ == MarkType::MARK_FULL; } - void SetGCType(TriggerGCType gcType) - { - gcType_ = gcType; - } - TriggerGCType GetGCType() const { return gcType_; @@ -357,7 +353,6 @@ public: void IncreaseTaskCount(); void ReduceTaskCount(); void WaitRunningTaskFinished(); - uint32_t GetRunningTaskCount(); void WaitClearTaskFinished(); void ThrowOutOfMemoryError(JSThread *thread, size_t size, std::string functionName, bool NonMovableObjNearOOM = false); @@ -380,6 +375,8 @@ public: } #endif + BASEHEAP_PUBLIC_HYBRID_EXTENSION(); + protected: void FatalOutOfMemoryError(size_t size, std::string functionName); @@ -663,11 +660,6 @@ public: return sSweeper_; } - UnifiedGC *GetUnifiedGC() const - { - return unifiedGC_; - } - bool IsParallelGCEnabled() const { return parallelGC_; @@ -920,12 +912,10 @@ public: } void CheckInHeapProfiler(); - - void StartUnifiedGCMark(TriggerGCType gcType, GCReason gcReason); - template - bool TriggerUnifiedGCMark(JSThread *thread) const; void SetGCThreadQosPriority(common::PriorityMode mode); + SHAREDHEAP_PUBLIC_HYBRID_EXTENSION(); + private: void ProcessAllGCListeners(); void CollectGarbageFinish(bool inDaemon, TriggerGCType gcType); @@ -987,7 +977,6 @@ private: SharedGCMarker *sharedGCMarker_ {nullptr}; SharedGCMovableMarker *sharedGCMovableMarker_ {nullptr}; SharedMemController *sharedMemController_ {nullptr}; - UnifiedGC *unifiedGC_ {nullptr}; size_t growingFactor_ {0}; size_t growingStep_ {0}; size_t incNativeSizeTriggerSharedCM_ {0}; @@ -998,6 +987,7 @@ private: bool inHeapProfiler_ {false}; NativePointerList sharedNativePointerList_; std::mutex sNativePointerListMutex_; + SHAREDHEAP_PRIVATE_HYBRID_EXTENSION(); }; class Heap : public BaseHeap { @@ -1009,7 +999,6 @@ public: void Initialize(); void Destroy() override; void Prepare(); - void UnifiedGCPrepare(); void GetHeapPrepare(); void ResetLargeCapacity(); void Resume(TriggerGCType gcType); @@ -1140,11 +1129,6 @@ public: return compressGCMarker_; } - UnifiedGCMarker *GetUnifiedGCMarker() const - { - return unifiedGCMarker_; - } - EcmaVM *GetEcmaVM() const { return ecmaVm_; @@ -1685,11 +1669,6 @@ public: return gcType_ == TriggerGCType::YOUNG_GC; } - bool IsUnifiedGC() const - { - return gcType_ == TriggerGCType::UNIFIED_GC; - } - void CheckNonMovableSpaceOOM(); void DumpHeapSnapshotBeforeOOM(bool isFullGC = true); std::tuple CalCallSiteInfo(uintptr_t retAddr) const; @@ -1718,6 +1697,7 @@ public: } void UpdateHeapStatsAfterGC(TriggerGCType gcType) override; + HEAP_PUBLIC_HYBRID_EXTENSION(); private: void CollectGarbageImpl(TriggerGCType gcType, GCReason reason = GCReason::OTHER); @@ -1918,7 +1898,6 @@ private: */ Marker *nonMovableMarker_ {nullptr}; Marker *compressGCMarker_ {nullptr}; - UnifiedGCMarker *unifiedGCMarker_ {nullptr}; // Work manager managing the tasks mostly generated in the GC mark phase. WorkManager *workManager_ {nullptr}; @@ -1988,6 +1967,7 @@ private: NativePointerList nativePointerList_; NativePointerList concurrentNativePointerList_; + HEAP_PRIVATE_HYBRID_EXTENSION(); friend panda::test::HProfTestHelper; friend panda::test::GCTest_CallbackTask_Test; diff --git a/ecmascript/mem/verification.h b/ecmascript/mem/verification.h index fa64c2ccbada7fc5f0151ce1edac75e97d7c7b59..9efd29e32801f8e66d8b62d5dcd898760b58093f 100644 --- a/ecmascript/mem/verification.h +++ b/ecmascript/mem/verification.h @@ -23,6 +23,7 @@ #include "ecmascript/mem/object_xray.h" #include "ecmascript/mem/mem.h" #include "ecmascript/mem/slots.h" +#include "ecmascript/cross_vm/verification_hybrid.h" namespace panda::ecmascript { static constexpr uint32_t INVALID_THRESHOLD = 0x40000; @@ -69,13 +70,13 @@ public: } private: + VERIFYOBJECTVISITOR_PRIVATE_HYBRID_EXTENSION(); void VisitAllObjects(TaggedObject *obj); void VerifyObjectSlotLegal(ObjectSlot slot, TaggedObject *obj) const; void VerifyHeapObjectSlotLegal(ObjectSlot slot, JSTaggedValue value, TaggedObject *obj) const; void VerifyMarkYoung(TaggedObject *obj, ObjectSlot slot, TaggedObject *value) const; void VerifyEvacuateYoung(TaggedObject *obj, ObjectSlot slot, TaggedObject *value) const; void VerifyMarkFull(TaggedObject *obj, ObjectSlot slot, TaggedObject *value) const; - void VerifyMarkUnified(TaggedObject *obj, ObjectSlot slot, TaggedObject *value) const; void VerifyEvacuateOld(TaggedObject *obj, ObjectSlot slot, TaggedObject *value) const; void VerifyEvacuateFull(TaggedObject *obj, ObjectSlot slot, TaggedObject *value) const; void VerifySharedRSetPostFullGC(TaggedObject *obj, ObjectSlot slot, TaggedObject *value) const; diff --git a/ecmascript/mem/work_manager-inl.h b/ecmascript/mem/work_manager-inl.h index cfba4e41fb7bc606706000bf306ccd020f236d39..5cfce667c1b4ffb37bfc4e9c610ccf2fe3eea44b 100644 --- a/ecmascript/mem/work_manager-inl.h +++ b/ecmascript/mem/work_manager-inl.h @@ -222,21 +222,6 @@ WorkManager::~WorkManager() } } -// PushObjectToGlobal should be called by MarkFromObejct in STS GC thread. To avoid data race with ArkTS GC -// thread(DaemonThread), new a WorkNode and push it to global work stack. Other GC thread(in Taskpool) and -// DaemonThread will get node from global work stack and continue mark. Global work stack have mutex in push -// and pop, so it will not have data race. -void WorkManager::PushObjectToGlobal(TaggedObject *object) -{ - WorkNode *tempNode = AllocateWorkNode(); - ASSERT(tempNode != nullptr); - tempNode->PushObject(ToUintPtr(object)); - workStack_.Push(tempNode); - if (heap_->IsParallelGCEnabled() && heap_->CheckCanDistributeTask() && !heap_->IsMarking()) { - heap_->PostParallelGCTask(parallelGCTaskPhase_); - } -} - size_t WorkManager::Finish() { size_t aliveSize = 0; diff --git a/ecmascript/mem/work_manager.h b/ecmascript/mem/work_manager.h index dabab393c9c1d85fc3a3b2690698bb90788b22bb..ad56431a46abdfedcf89452bbec9adfe50ca4f84 100644 --- a/ecmascript/mem/work_manager.h +++ b/ecmascript/mem/work_manager.h @@ -20,6 +20,7 @@ #include "ecmascript/mem/mark_stack.h" #include "ecmascript/mem/slots.h" #include "ecmascript/mem/work_space_chunk.h" +#include "ecmascript/cross_vm/work_manager_hybrid.h" namespace panda::ecmascript { using SlotNeedUpdate = std::pair; @@ -263,8 +264,6 @@ public: inline size_t Finish() override; inline void Finish(size_t &aliveSize, size_t &promotedSize); - inline void PushObjectToGlobal(TaggedObject *object); - inline uint32_t GetTotalThreadNum() { return threadNum_; @@ -279,7 +278,7 @@ public: { return &works_.at(threadId); } - + WORKMANAGER_PUBLIC_HYBRID_EXTENSION(); private: NO_COPY_SEMANTIC(WorkManager); NO_MOVE_SEMANTIC(WorkManager); diff --git a/ecmascript/napi/include/jsnapi_expo.h b/ecmascript/napi/include/jsnapi_expo.h index 2a0c787ee6c4065dab9e4a22a6890fadb2e4bd70..837b419716c2cfad0b9b648ed162bcf216c8eb3d 100644 --- a/ecmascript/napi/include/jsnapi_expo.h +++ b/ecmascript/napi/include/jsnapi_expo.h @@ -31,6 +31,7 @@ #include "ecmascript/common.h" #include "ecmascript/module/js_module_execute_type.h" #include "ecmascript/napi/include/jsnapi_internals.h" +#include "ecmascript/cross_vm/jsnapi_expo_hybrid.h" #ifndef NDEBUG #include "libpandabase/utils/debug.h" @@ -473,16 +474,6 @@ public: address_ = 0; } - template - void CreateXRefGloablReference(const EcmaVM *vm, const Local ¤t); - - // This method must be called before Global is released. - void FreeGlobalHandleAddr(); - void FreeXRefGlobalHandleAddr(); - void MarkFromObject(); - bool IsObjectAlive() const; - bool IsValidHeapObject() const; - inline T *operator*() const { return GetAddress(); @@ -512,6 +503,8 @@ public: return vm_; } + // This method must be called before Global is released. + GLOBAL_PUBLIC_HYBRID_EXTENSION(); private: inline T *GetAddress() const { @@ -844,7 +837,6 @@ public: } static Local New(const EcmaVM *vm); static uintptr_t NewObject(const EcmaVM *vm); - static Local NewJSXRefObject(const EcmaVM *vm); static Local NewS(const EcmaVM *vm); static Local NewWithProperties(const EcmaVM *vm, size_t propertyCount, const Local *keys, const PropertyAttribute *attributes); @@ -900,6 +892,7 @@ public: void *nativePointer = nullptr, NativePointerCallback callBack = nullptr, void *data = nullptr, size_t nativeBindingsize = 0); + OBJECTREF_PUBLIC_HYBRID_EXTENSION(); }; using FunctionCallback = Local(*)(JsiRuntimeCallInfo*); @@ -1061,8 +1054,8 @@ public: uint32_t WriteLatin1(const EcmaVM *vm, char *buffer, uint32_t length); uint32_t WriteLatin1WithoutSwitchState(const EcmaVM *vm, char *buffer, uint32_t length); static Local GetNapiWrapperString(const EcmaVM *vm); - static Local GetProxyNapiWrapperString(const EcmaVM *vm); Local EncodeIntoUint8Array(const EcmaVM *vm); + STRINGREF_PUBLIC_HYBRID_EXTENSION(); }; class PUBLIC_API PromiseRejectInfo { @@ -1689,8 +1682,6 @@ public: static EcmaVM *CreateJSVM(const RuntimeOption &option); static void DestroyJSVM(EcmaVM *ecmaVm); - static void SetStackInfo(const EcmaVM *vm, const panda::StackInfo &info); - static panda::StackInfo GetStackInfo(const EcmaVM *vm); static void RegisterUncatchableErrorHandler(EcmaVM *ecmaVm, const UncatchableErrorHandler &handler); // aot load @@ -1730,8 +1721,6 @@ public: const std::string &module_path); static Local GetModuleNameSpaceWithModuleInfoForHybridApp(EcmaVM *vm, const std::string &file, const std::string &module_path); - static Local GetModuleNameSpaceWithPath(const EcmaVM *vm, const char *path); - static std::pair ResolveOhmUrl(std::string ohmUrl); /* * Execute panda file from secure mem. secure memory lifecycle managed externally. @@ -1823,8 +1812,6 @@ public: static void SetCancelTimerCallback(EcmaVM *vm, CancelTimerCallback callback); static void NotifyEnvInitialized(EcmaVM *vm); static void SetReleaseSecureMemCallback(ReleaseSecureMemCallback releaseSecureMemFunc); - static void SetHostResolveBufferTracker(EcmaVM *vm, std::function cb); static void PandaFileSerialize(const EcmaVM *vm); static void ModuleSerialize(const EcmaVM *vm); static void ModuleDeserialize(EcmaVM *vm, const uint32_t appVersion); @@ -1922,8 +1909,6 @@ public: static void NotifyTaskFinished(const EcmaVM *vm); static bool IsMultiThreadCheckEnabled(const EcmaVM *vm); static uint32_t GetCurrentThreadId(); - static bool IsObjectAlive(const EcmaVM *vm, uintptr_t addr); - static bool IsValidHeapObject(const EcmaVM *vm, uintptr_t addr); //set VM apiVersion static void SetVMAPIVersion(EcmaVM *vm, const int32_t apiVersion); @@ -1938,8 +1923,8 @@ public: static void SwitchContext(const EcmaVM *vm, const Local &context); // 1.2runtime interface info static Local GetImplements(const EcmaVM *vm, Local instance); - static void InitHybridVMEnv(const EcmaVM *vm); - + + JSNAPI_PUBLIC_HYBRID_EXTENSION(); private: static bool isForked_; static bool CreateRuntime(const RuntimeOption &option); @@ -1948,7 +1933,6 @@ private: static uintptr_t GetHandleAddr(const EcmaVM *vm, uintptr_t localAddress); static uintptr_t GetGlobalHandleAddr(const EcmaVM *vm, uintptr_t localAddress); - static uintptr_t GetXRefGlobalHandleAddr(const EcmaVM *vm, uintptr_t localAddress); static uintptr_t SetWeak(const EcmaVM *vm, uintptr_t localAddress); static uintptr_t SetWeakCallback(const EcmaVM *vm, uintptr_t localAddress, void *ref, WeakRefClearCallBack freeGlobalCallBack, @@ -1956,10 +1940,6 @@ private: static uintptr_t ClearWeak(const EcmaVM *vm, uintptr_t localAddress); static bool IsWeak(const EcmaVM *vm, uintptr_t localAddress); static void DisposeGlobalHandleAddr(const EcmaVM *vm, uintptr_t addr); - static void DisposeXRefGlobalHandleAddr(const EcmaVM *vm, uintptr_t addr); -#ifdef PANDA_JS_ETS_HYBRID_MODE - static void MarkFromObject(const EcmaVM *vm, uintptr_t addr); -#endif // PANDA_JS_ETS_HYBRID_MODE static bool IsSerializationTimeoutCheckEnabled(const EcmaVM *vm); static void GenerateTimeoutTraceIfNeeded(const EcmaVM *vm, std::chrono::system_clock::time_point &start, @@ -1972,6 +1952,10 @@ private: template friend class Local; friend class test::JSNApiTests; + JSNAPI_PRIVATE_HYBRID_EXTENSION(); +#ifdef PANDA_JS_ETS_HYBRID_MODE + JSNAPI_PRIVATE_HYBRID_MODE_EXTENSION(); +#endif // PANDA_JS_ETS_HYBRID_MODE }; class PUBLIC_API ProxyRef : public ObjectRef { @@ -2190,60 +2174,9 @@ Local::Local(const EcmaVM *vm, const Global ¤t) address_ = JSNApi::GetHandleAddr(vm, reinterpret_cast(*current)); } +GLOBAL_PUBLIC_DEF_HYBRID_EXTENSION(); #ifdef PANDA_JS_ETS_HYBRID_MODE -class PUBLIC_API HandshakeHelper final { - public: - static void DoHandshake(EcmaVM *vm, void *stsiface, void **ecmaiface); -}; -#endif // PANDA_JS_ETS_HYBRID_MODE - -template -template -void Global::CreateXRefGloablReference(const EcmaVM *vm, const Local ¤t) -{ - vm_ = vm; - if (!current.IsEmpty()) { - address_ = JSNApi::GetXRefGlobalHandleAddr(vm_, reinterpret_cast(*current)); - } -} - -template -void Global::FreeXRefGlobalHandleAddr() -{ - if (address_ == 0) { - return; - } - JSNApi::DisposeXRefGlobalHandleAddr(vm_, address_); - address_ = 0; -} - -#ifdef PANDA_JS_ETS_HYBRID_MODE - template - void Global::MarkFromObject() - { - if (address_ == 0) { - return; - } - JSNApi::MarkFromObject(vm_, address_); - } - - template - bool Global::IsObjectAlive() const - { - if (address_ == 0) { - return false ; - } - return JSNApi::IsObjectAlive(vm_, address_); - } - - template - bool Global::IsValidHeapObject() const - { - if (address_ == 0) { - return false; - } - return JSNApi::IsValidHeapObject(vm_, address_); - } + GLOBAL_PUBLIC_DEF_HYBRID_MODE_EXTENSION(); #endif // PANDA_JS_ETS_HYBRID_MODE } // namespace panda -#endif +#endif \ No newline at end of file diff --git a/ecmascript/napi/jsnapi_expo.cpp b/ecmascript/napi/jsnapi_expo.cpp index 52adbe41f671393f4dff73c67596ffc7926eb824..30bb35bfef1e395d5aba25e0f1f39e7d12cad00e 100644 --- a/ecmascript/napi/jsnapi_expo.cpp +++ b/ecmascript/napi/jsnapi_expo.cpp @@ -2382,17 +2382,6 @@ Local StringRef::GetNapiWrapperString(const EcmaVM *vm) return JSNApiHelper::ToLocal(napiWrapperString); } -Local StringRef::GetProxyNapiWrapperString(const EcmaVM *vm) -{ - // Omit exception check because ark calls here may not - // cause side effect even pending exception exists. - CROSS_THREAD_CHECK(vm); - ecmascript::ThreadManagedScope managedScope(thread); - JSHandle proxyNapiWapperString = thread->GlobalConstants()->GetHandledProxyNapiWrapperString(); - return JSNApiHelper::ToLocal(proxyNapiWapperString); -} - - Local StringRef::EncodeIntoUint8Array(const EcmaVM *vm) { CROSS_THREAD_CHECK(vm); @@ -2640,15 +2629,6 @@ Local ObjectRef::New(const EcmaVM *vm) return JSNApiHelper::ToLocal(object); } -Local ObjectRef::NewJSXRefObject(const EcmaVM *vm) -{ - CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm)); - ecmascript::ThreadManagedScope managedScope(thread); - ObjectFactory *factory = vm->GetFactory(); - JSHandle object(factory->NewJSXRefObject()); - return JSNApiHelper::ToLocal(object); -} - uintptr_t ObjectRef::NewObject(const EcmaVM *vm) { CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, @@ -2905,23 +2885,6 @@ Local JSNApi::GetImplements(const EcmaVM *vm, Local inst return JSNApiHelper::ToLocal(implementRet); } -void JSNApi::InitHybridVMEnv(const EcmaVM *vm) -{ - auto instance = ecmascript::Runtime::GetInstance(); - ASSERT(instance != nullptr); - - CROSS_THREAD_AND_EXCEPTION_CHECK(vm); - ecmascript::ThreadManagedScope managedScope(thread); - - instance->SetHybridVm(true); - ObjectFactory *factory = vm->GetFactory(); - JSHandle env = vm->GetGlobalEnv(); - if (env->GetInterfaceTypeSymbol().GetTaggedValue().IsUndefined()) { - JSHandle interfaceTypeSymbol(factory->NewPrivateNameSymbolWithChar("interfaceType")); - env->SetInterfaceTypeSymbol(thread, interfaceTypeSymbol.GetTaggedValue()); - } -} - bool ObjectRef::Set(const EcmaVM *vm, uint32_t key, Local value) { CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false); @@ -4889,21 +4852,6 @@ void JSNApi::DestroyJSVM(EcmaVM *ecmaVm) EcmaVM::Destroy(ecmaVm); } -void JSNApi::SetStackInfo(const EcmaVM *vm, const panda::StackInfo &info) -{ - JSThread *thread = vm->GetJSThread(); - thread->SetStackStart(info.stackStart); - thread->SetStackLimit(info.stackStart - info.stackSize); -} - -panda::StackInfo JSNApi::GetStackInfo(const EcmaVM *vm) -{ - JSThread *thread = vm->GetJSThread(); - size_t stackStart = thread->GetStackStart(); - size_t stackSize = stackStart - thread->GetStackLimit(); - return {stackStart, stackSize}; -} - void JSNApi::RegisterUncatchableErrorHandler(EcmaVM *ecmaVm, const UncatchableErrorHandler &handler) { ecmaVm->RegisterUncatchableErrorHandler(handler); @@ -5958,17 +5906,6 @@ uintptr_t JSNApi::GetGlobalHandleAddr(const EcmaVM *vm, uintptr_t localAddress) return thread->NewGlobalHandle(value); } -uintptr_t JSNApi::GetXRefGlobalHandleAddr(const EcmaVM *vm, uintptr_t localAddress) -{ - CROSS_THREAD_CHECK(vm); - if (localAddress == 0) { - return 0; - } - ecmascript::ThreadManagedScope scope(thread); - JSTaggedType value = *(reinterpret_cast(localAddress)); - return thread->NewXRefGlobalHandle(value); -} - int JSNApi::GetStartRealTime(const EcmaVM *vm) { ecmascript::ThreadManagedScope scope(vm->GetJSThread()); @@ -6090,44 +6027,6 @@ void JSNApi::DisposeGlobalHandleAddr(const EcmaVM *vm, uintptr_t addr) thread->DisposeGlobalHandle(addr); } -void JSNApi::DisposeXRefGlobalHandleAddr(const EcmaVM *vm, uintptr_t addr) -{ - CROSS_THREAD_CHECK(vm); - if (addr == 0 || !reinterpret_cast(addr)->IsUsing()) { - return; - } - thread->DisposeXRefGlobalHandle(addr); -} - -#ifdef PANDA_JS_ETS_HYBRID_MODE -void JSNApi::MarkFromObject(const EcmaVM *vm, uintptr_t addr) -{ - if (addr == 0 || !reinterpret_cast(addr)->IsUsing()) { - return; - } - JSTaggedType value = *(reinterpret_cast(addr)); - vm->GetCrossVMOperator()->MarkFromObject(value); -} - -bool JSNApi::IsObjectAlive(const EcmaVM *vm, uintptr_t addr) -{ - if (addr == 0 || !reinterpret_cast(addr)->IsUsing()) { - return false; - } - JSTaggedType value = *(reinterpret_cast(addr)); - return vm->GetCrossVMOperator()->IsObjectAlive(value); -} - -bool JSNApi::IsValidHeapObject(const EcmaVM *vm, uintptr_t addr) -{ - if (addr == 0 || !reinterpret_cast(addr)->IsUsing()) { - return false; - } - JSTaggedType value = *(reinterpret_cast(addr)); - return vm->GetCrossVMOperator()->IsValidHeapObject(value); -} -#endif // PANDA_JS_ETS_HYBRID_MODE - void *JSNApi::InterOpSerializeValue([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] Local value, [[maybe_unused]] Local transfer, [[maybe_unused]] Local cloneList, [[maybe_unused]] bool defaultTransfer, [[maybe_unused]] bool defaultCloneShared) @@ -6710,21 +6609,6 @@ Local JSNApi::GetModuleNameSpaceWithModuleInfoForHybridApp(EcmaVM *vm return JSNApi::GetModuleNameSpaceWithModuleInfo(vm, file, module_path); } -Local JSNApi::GetModuleNameSpaceWithPath(const EcmaVM *vm, const char *path) -{ - CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm)); - auto [filePath, recordName] = ModulePathHelper::ResolvePath(path); - ecmascript::ThreadManagedScope managedScope(thread); - JSHandle moduleNamespace = - ecmascript::NapiModuleLoader::LoadModuleNameSpaceFromFile(thread, recordName, filePath); - return JSNApiHelper::ToLocal(moduleNamespace); -} - -std::pair JSNApi::ResolveOhmUrl(std::string ohmUrl) -{ - return ModulePathHelper::ResolveOhmUrl(ohmUrl); -} - // ---------------------------------- Promise ------------------------------------- Local PromiseRef::Catch(const EcmaVM *vm, Local handler) { @@ -7138,12 +7022,4 @@ bool ExternalStringCache::HasCachedString([[maybe_unused]] const EcmaVM *vm, uin return instance->HasCachedString(propertyIndex); } -#ifdef PANDA_JS_ETS_HYBRID_MODE -void HandshakeHelper::DoHandshake([[maybe_unused]] EcmaVM *vm, void *stsIface, void **ecmaIface) -{ - ecmascript::CrossVMOperator::DoHandshake(vm, stsIface, ecmaIface); -} -#endif // PANDA_JS_ETS_HYBRID_MODE - - } // namespace panda diff --git a/ecmascript/napi/test/jsnapi_third_tests.cpp b/ecmascript/napi/test/jsnapi_third_tests.cpp index b236732c6b235a3cfe07d3b3368b10e54d40cfc5..3d946e7b92e93b6db6e6f77e4b66a2df87ec0fae 100644 --- a/ecmascript/napi/test/jsnapi_third_tests.cpp +++ b/ecmascript/napi/test/jsnapi_third_tests.cpp @@ -1705,6 +1705,7 @@ HWTEST_F_L0(JSNApiTests, JSNApi_SwitchContext001) HWTEST_F_L0(JSNApiTests, XRefGlobalHandleAddr) { + JSNApi::InitHybridVMEnv(vm_); JSHandle weakRefArray = vm_->GetFactory()->NewTaggedArray(2, JSTaggedValue::Hole()); uintptr_t xRefArrayAddress; vm_->SetEnableForceGC(false); diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index fc4329139f03329b74fa8d4b4ff7524709dbcbca..8286f0df9b24512ed8598dd4ca95ec2984c64721 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -510,13 +510,6 @@ JSHandle ObjectFactory::NewJSObject(const JSHandle &jshclass return obj; } -JSHandle ObjectFactory::NewJSXRefObject() -{ - JSHandle jsXRefHClass = JSHandle::Cast(thread_->GlobalConstants()->GetHandledXRefObjectClass()); - JSHandle object(NewJSObject(jsXRefHClass)); - return object; -} - JSHandle ObjectFactory::CloneProperties(const JSHandle &old) { uint32_t newLength = old->GetLength(); diff --git a/ecmascript/object_factory.h b/ecmascript/object_factory.h index 6460f3594b378c7e38f55dc0b5eaf157ccc1548d..6294421f7e0b4319949a6f05e14b34e3d3651406 100644 --- a/ecmascript/object_factory.h +++ b/ecmascript/object_factory.h @@ -36,6 +36,7 @@ #include "ecmascript/tagged_array.h" #include "ecmascript/byte_array.h" #include "ecmascript/pgo_profiler/pgo_extra_profiler.h" +#include "ecmascript/cross_vm/object_factory_hybrid.h" namespace panda::ecmascript { struct MethodLiteral; @@ -667,7 +668,7 @@ public: JSHandle PUBLIC_API NewJSObject(const JSHandle &jshclass); // used for creating JSXRefObject - JSHandle PUBLIC_API NewJSXRefObject(); + OBJECTFACTORY_PUBLIC_HYBRID_EXTENSION(); // used for creating jshclass in Builtins, Function, Class_Linker JSHandle NewEcmaHClass(uint32_t size, JSType type, const JSHandle &prototype); diff --git a/ecmascript/tests/test_helper.h b/ecmascript/tests/test_helper.h index 410d4de6ef5ee27ea8ecf79c3d8c4cf83f61a598..dd3e04d9ce0af34b2d2a3f2330427cd8a2b19130 100644 --- a/ecmascript/tests/test_helper.h +++ b/ecmascript/tests/test_helper.h @@ -204,6 +204,7 @@ public: thread->ManagedCodeBegin(); scope = new EcmaHandleScope(thread); } + JSNApi::InitHybridVMEnv(thread->GetEcmaVM()); } void TearDown() override diff --git a/ecmascript/tests/unified_gc_test.cpp b/ecmascript/tests/unified_gc_test.cpp index 7bc01f392d664998d59b880ffb821af3aa09b8f5..f9251f0a272f651c4221280a6f7669f91e73f9bb 100644 --- a/ecmascript/tests/unified_gc_test.cpp +++ b/ecmascript/tests/unified_gc_test.cpp @@ -16,7 +16,7 @@ #include "ecmascript/tests/unified_gc_test_helper.h" #include "ecmascript/mem/concurrent_marker.h" #include "ecmascript/mem/region-inl.h" -#include "ecmascript/mem/unified_gc/unified_gc_marker.h" +#include "ecmascript/cross_vm/unified_gc/unified_gc_marker.h" using namespace panda::ecmascript;