From 01811ab7fc32ff13373a7c69bc2ca32b207ecb05 Mon Sep 17 00:00:00 2001 From: Artem Udovichenko Date: Fri, 11 Jul 2025 20:34:21 +0300 Subject: [PATCH] Add context switch API Change-Id: I380ca00ab39fabcb83db95ff39dbd698e235d354 Signed-off-by: Artem Udovichenko --- BUILD.gn | 1 + ecmascript/ecma_context.cpp | 166 ++++---------------------- ecmascript/ecma_context.h | 79 +++++++----- ecmascript/ecma_handle_scope.cpp | 38 +++--- ecmascript/napi/include/jsnapi_expo.h | 7 ++ ecmascript/napi/jsnapi_expo.cpp | 25 ++++ 6 files changed, 126 insertions(+), 190 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index 4d3ecef248..089e841257 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -807,6 +807,7 @@ ecma_source = [ "ecmascript/dfx/vm_thread_control.cpp", "ecmascript/dump.cpp", "ecmascript/ecma_context.cpp", + "ecmascript/handle_storage.cpp", "ecmascript/ecma_handle_scope.cpp", "ecmascript/ecma_string.cpp", "ecmascript/ecma_string_table.cpp", diff --git a/ecmascript/ecma_context.cpp b/ecmascript/ecma_context.cpp index f967db0055..ea26f534db 100644 --- a/ecmascript/ecma_context.cpp +++ b/ecmascript/ecma_context.cpp @@ -51,6 +51,8 @@ EcmaContext::EcmaContext(JSThread *thread) factory_(vm_->GetFactory()), aotFileManager_(vm_->GetAOTFileManager()) { + handleStorageList_.emplace_back(); + handleStorage_ = &handleStorageList_.back(); } /* static */ @@ -131,20 +133,8 @@ bool EcmaContext::Initialize() EcmaContext::~EcmaContext() { - for (auto n : handleStorageNodes_) { - delete n; - } - handleStorageNodes_.clear(); - currentHandleStorageIndex_ = -1; - handleScopeStorageNext_ = handleScopeStorageEnd_ = nullptr; - - for (auto n : primitiveStorageNodes_) { - delete n; - } - primitiveStorageNodes_.clear(); - currentPrimitiveStorageIndex_ = -1; - primitiveScopeStorageNext_ = primitiveScopeStorageEnd_ = nullptr; - + handleStorage_ = nullptr; + handleStorageList_.clear(); if (vm_->IsEnableBaselineJit() || vm_->IsEnableFastJit()) { // clear jit task vm_->GetJit()->ClearTask(this); @@ -886,15 +876,11 @@ void EcmaContext::Iterate(RootVisitor &v) regExpParserCache_->Clear(); } IterateMegaIC(v); - if (!vm_->GetJSOptions().EnableGlobalLeakCheck() && currentHandleStorageIndex_ != -1) { + if (!vm_->GetJSOptions().EnableGlobalLeakCheck()) { // IterateHandle when disableGlobalLeakCheck. OHOS_HITRACE("CMCGC::VisitRootHandleStorage"); - int32_t nid = currentHandleStorageIndex_; - for (int32_t i = 0; i <= nid; ++i) { - auto node = handleStorageNodes_.at(i); - auto start = node->data(); - auto end = (i != nid) ? &(node->data()[NODE_BLOCK_SIZE]) : handleScopeStorageNext_; - v.VisitRangeRoot(Root::ROOT_HANDLE, ObjectSlot(ToUintPtr(start)), ObjectSlot(ToUintPtr(end))); + for (HandleStorage &storage : handleStorageList_) { + storage.Iterate(v); } } @@ -929,127 +915,6 @@ void EcmaContext::Iterate(RootVisitor &v) v.VisitRangeRoot(Root::ROOT_VM, start, end); } -size_t EcmaContext::IterateHandle(RootVisitor &visitor) -{ - // EnableGlobalLeakCheck. - size_t handleCount = 0; - if (currentHandleStorageIndex_ != -1) { - int32_t nid = currentHandleStorageIndex_; - for (int32_t i = 0; i <= nid; ++i) { - auto node = handleStorageNodes_.at(i); - auto start = node->data(); - auto end = (i != nid) ? &(node->data()[NODE_BLOCK_SIZE]) : handleScopeStorageNext_; - visitor.VisitRangeRoot(Root::ROOT_HANDLE, ObjectSlot(ToUintPtr(start)), ObjectSlot(ToUintPtr(end))); - handleCount += (ToUintPtr(end) - ToUintPtr(start)) / sizeof(JSTaggedType); - } - } - return handleCount; -} - -uintptr_t *EcmaContext::ExpandHandleStorage() -{ - uintptr_t *result = nullptr; - int32_t lastIndex = static_cast(handleStorageNodes_.size()) - 1; - if (currentHandleStorageIndex_ == lastIndex) { - auto n = new std::array(); - handleStorageNodes_.push_back(n); - currentHandleStorageIndex_++; - result = reinterpret_cast(&n->data()[0]); - handleScopeStorageEnd_ = &n->data()[NODE_BLOCK_SIZE]; - } else { - currentHandleStorageIndex_++; - auto lastNode = handleStorageNodes_[currentHandleStorageIndex_]; - result = reinterpret_cast(&lastNode->data()[0]); - handleScopeStorageEnd_ = &lastNode->data()[NODE_BLOCK_SIZE]; - } - - return result; -} - -void EcmaContext::ShrinkHandleStorage(int prevIndex) -{ - currentHandleStorageIndex_ = prevIndex; - int32_t lastIndex = static_cast(handleStorageNodes_.size()) - 1; -#if ECMASCRIPT_ENABLE_ZAP_MEM - uintptr_t size = ToUintPtr(handleScopeStorageEnd_) - ToUintPtr(handleScopeStorageNext_); - if (currentHandleStorageIndex_ != -1) { - if (memset_s(handleScopeStorageNext_, size, 0, size) != EOK) { - LOG_FULL(FATAL) << "memset_s failed"; - UNREACHABLE(); - } - } - for (int32_t i = currentHandleStorageIndex_ + 1; i < lastIndex; i++) { - if (memset_s(handleStorageNodes_[i], - NODE_BLOCK_SIZE * sizeof(JSTaggedType), 0, - NODE_BLOCK_SIZE * sizeof(JSTaggedType)) != - EOK) { - LOG_FULL(FATAL) << "memset_s failed"; - UNREACHABLE(); - } - } -#endif - - if (lastIndex > MIN_HANDLE_STORAGE_SIZE && currentHandleStorageIndex_ < MIN_HANDLE_STORAGE_SIZE) { - for (int i = MIN_HANDLE_STORAGE_SIZE; i < lastIndex; i++) { - auto node = handleStorageNodes_.back(); - delete node; - handleStorageNodes_.pop_back(); - } - } -} - -uintptr_t *EcmaContext::ExpandPrimitiveStorage() -{ - uintptr_t *result = nullptr; - int32_t lastIndex = static_cast(primitiveStorageNodes_.size()) - 1; - if (currentPrimitiveStorageIndex_ == lastIndex) { - auto n = new std::array(); - primitiveStorageNodes_.push_back(n); - currentPrimitiveStorageIndex_++; - result = reinterpret_cast(&n->data()[0]); - primitiveScopeStorageEnd_ = &n->data()[NODE_BLOCK_SIZE]; - } else { - currentPrimitiveStorageIndex_++; - auto lastNode = primitiveStorageNodes_[currentPrimitiveStorageIndex_]; - result = reinterpret_cast(&lastNode->data()[0]); - primitiveScopeStorageEnd_ = &lastNode->data()[NODE_BLOCK_SIZE]; - } - - return result; -} - -void EcmaContext::ShrinkPrimitiveStorage(int prevIndex) -{ - currentPrimitiveStorageIndex_ = prevIndex; - int32_t lastIndex = static_cast(primitiveStorageNodes_.size()) - 1; -#if ECMASCRIPT_ENABLE_ZAP_MEM - uintptr_t size = ToUintPtr(primitiveScopeStorageEnd_) - ToUintPtr(primitiveScopeStorageNext_); - if (currentPrimitiveStorageIndex_ != -1) { - if (memset_s(primitiveScopeStorageNext_, size, 0, size) != EOK) { - LOG_FULL(FATAL) << "memset_s failed"; - UNREACHABLE(); - } - } - for (int32_t i = currentPrimitiveStorageIndex_ + 1; i < lastIndex; i++) { - if (memset_s(primitiveStorageNodes_[i], - NODE_BLOCK_SIZE * sizeof(JSTaggedType), 0, - NODE_BLOCK_SIZE * sizeof(JSTaggedType)) != - EOK) { - LOG_FULL(FATAL) << "memset_s failed"; - UNREACHABLE(); - } - } -#endif - - if (lastIndex > MIN_PRIMITIVE_STORAGE_SIZE && currentPrimitiveStorageIndex_ < MIN_PRIMITIVE_STORAGE_SIZE) { - for (int i = MIN_PRIMITIVE_STORAGE_SIZE; i < lastIndex; i++) { - auto node = primitiveStorageNodes_.back(); - delete node; - primitiveStorageNodes_.pop_back(); - } - } -} - void EcmaContext::LoadStubFile() { std::string stubFile = ""; @@ -1207,4 +1072,21 @@ void EcmaContext::AddToKeptObjects(JSHandle value) linkedSet = LinkedHashSet::Add(thread_, linkedSet, value); globalEnv->SetWeakRefKeepObjects(thread_, linkedSet); } + +HandleStorage* EcmaContext::CreateHandleStorage() +{ + handleStorageList_.emplace_back(); + return &handleStorageList_.back(); +} + +void EcmaContext::DeleteHandleStorage(HandleStorage *storage) +{ + ASSERT(handleStorage_ != storage); + auto it = std::find_if(handleStorageList_.begin(), handleStorageList_.end(), [storage] (const HandleStorage &elem) { + return &elem == storage; + }); + ASSERT(it != handleStorageList_.end()); + handleStorageList_.erase(it); +} + } // namespace panda::ecmascript diff --git a/ecmascript/ecma_context.h b/ecmascript/ecma_context.h index 85ee325c73..fb3afbe8ad 100644 --- a/ecmascript/ecma_context.h +++ b/ecmascript/ecma_context.h @@ -31,6 +31,7 @@ #include "ecmascript/patch/patch_loader.h" #include "ecmascript/stackmap/ark_stackmap.h" #include "ecmascript/waiter_list.h" +#include "ecmascript/handle_storage.h" #include "global_handle_collection.h" #include "libpandafile/file.h" @@ -393,59 +394,91 @@ public: JSTaggedType *GetHandleScopeStorageNext() const { - return handleScopeStorageNext_; + return handleStorage_->GetHandleScopeStorageNext(); } void SetHandleScopeStorageNext(JSTaggedType *value) { - handleScopeStorageNext_ = value; + handleStorage_->SetHandleScopeStorageNext(value); } JSTaggedType *GetHandleScopeStorageEnd() const { - return handleScopeStorageEnd_; + return handleStorage_->GetHandleScopeStorageEnd(); } void SetHandleScopeStorageEnd(JSTaggedType *value) { - handleScopeStorageEnd_ = value; + handleStorage_->SetHandleScopeStorageEnd(value); } int GetCurrentHandleStorageIndex() const { - return currentHandleStorageIndex_; + return handleStorage_->GetCurrentHandleStorageIndex(); } JSTaggedType *GetPrimitiveScopeStorageNext() const { - return primitiveScopeStorageNext_; + return handleStorage_->GetPrimitiveScopeStorageNext(); } void SetPrimitiveScopeStorageNext(JSTaggedType *value) { - primitiveScopeStorageNext_ = value; + handleStorage_->SetPrimitiveScopeStorageNext(value); } JSTaggedType *GetPrimitiveScopeStorageEnd() const { - return primitiveScopeStorageEnd_; + return handleStorage_->GetPrimitiveScopeStorageEnd(); } void SetPrimitiveScopeStorageEnd(JSTaggedType *value) { - primitiveScopeStorageEnd_ = value; + handleStorage_->SetPrimitiveScopeStorageEnd(value); } int GetCurrentPrimitiveStorageIndex() const { - return currentPrimitiveStorageIndex_; + return handleStorage_->GetCurrentPrimitiveStorageIndex(); } - size_t IterateHandle(RootVisitor &visitor); - uintptr_t *ExpandHandleStorage(); - void ShrinkHandleStorage(int prevIndex); - uintptr_t *ExpandPrimitiveStorage(); - void ShrinkPrimitiveStorage(int prevIndex); + size_t IterateHandle(RootVisitor &visitor) + { + return handleStorage_->Iterate(visitor); + } + + uintptr_t *ExpandHandleStorage() + { + return handleStorage_->ExpandHandleStorage(); + } + + void ShrinkHandleStorage(int prevIndex) + { + handleStorage_->ShrinkHandleStorage(prevIndex); + } + + uintptr_t *ExpandPrimitiveStorage() + { + return handleStorage_->ExpandPrimitiveStorage(); + } + + void ShrinkPrimitiveStorage(int prevIndex) + { + handleStorage_->ShrinkPrimitiveStorage(prevIndex); + } + + HandleStorage *GetHandleStorage() + { + return handleStorage_; + } + + void SetCurrentHandleStorage(HandleStorage *storage) + { + handleStorage_ = storage; + } + + HandleStorage* CreateHandleStorage(); + void DeleteHandleStorage(HandleStorage *storage); PropertiesCache *GetPropertiesCache() const { @@ -671,20 +704,8 @@ private: ModuleLogger *moduleLogger_ {nullptr}; - // Handlescope - static const uint32_t NODE_BLOCK_SIZE_LOG2 = 10; - static const uint32_t NODE_BLOCK_SIZE = 1U << NODE_BLOCK_SIZE_LOG2; - static constexpr int32_t MIN_HANDLE_STORAGE_SIZE = 2; - JSTaggedType *handleScopeStorageNext_ {nullptr}; - JSTaggedType *handleScopeStorageEnd_ {nullptr}; - std::vector *> handleStorageNodes_ {}; - int32_t currentHandleStorageIndex_ {-1}; - // PrimitveScope - static constexpr int32_t MIN_PRIMITIVE_STORAGE_SIZE = 2; - JSTaggedType *primitiveScopeStorageNext_ {nullptr}; - JSTaggedType *primitiveScopeStorageEnd_ {nullptr}; - std::vector *> primitiveStorageNodes_ {}; - int32_t currentPrimitiveStorageIndex_ {-1}; + HandleStorage *handleStorage_; + CList handleStorageList_; GlobalEnvConstants globalConst_; // Join Stack diff --git a/ecmascript/ecma_handle_scope.cpp b/ecmascript/ecma_handle_scope.cpp index c5fd6db01f..797e91018c 100644 --- a/ecmascript/ecma_handle_scope.cpp +++ b/ecmascript/ecma_handle_scope.cpp @@ -36,16 +36,16 @@ EcmaHandleScope::EcmaHandleScope(JSThread *thread) : thread_(thread) void EcmaHandleScope::OpenHandleScope(EcmaContext *context) { - prevNext_ = context->handleScopeStorageNext_; - prevEnd_ = context->handleScopeStorageEnd_; - prevHandleStorageIndex_ = context->currentHandleStorageIndex_; + prevNext_ = context->GetHandleScopeStorageNext(); + prevEnd_ = context->GetHandleScopeStorageEnd(); + prevHandleStorageIndex_ = context->GetCurrentHandleStorageIndex(); } void EcmaHandleScope::OpenPrimitiveScope(EcmaContext *context) { - prevPrimitiveNext_ = context->primitiveScopeStorageNext_; - prevPrimitiveEnd_ = context->primitiveScopeStorageEnd_; - prevPrimitiveStorageIndex_ = context->currentPrimitiveStorageIndex_; + prevPrimitiveNext_ = context->GetPrimitiveScopeStorageNext(); + prevPrimitiveEnd_ = context->GetPrimitiveScopeStorageEnd(); + prevPrimitiveStorageIndex_ = context->GetCurrentPrimitiveStorageIndex(); } EcmaHandleScope::~EcmaHandleScope() @@ -63,18 +63,18 @@ EcmaHandleScope::~EcmaHandleScope() void EcmaHandleScope::CloseHandleScope(EcmaContext *context) { - context->handleScopeStorageNext_ = prevNext_; - if (context->handleScopeStorageEnd_ != prevEnd_) { - context->handleScopeStorageEnd_ = prevEnd_; + context->SetHandleScopeStorageNext(prevNext_); + if (context->GetHandleScopeStorageEnd() != prevEnd_) { + context->SetHandleScopeStorageEnd(prevEnd_); context->ShrinkHandleStorage(prevHandleStorageIndex_); } } void EcmaHandleScope::ClosePrimitiveScope(EcmaContext *context) { - context->primitiveScopeStorageNext_ = prevPrimitiveNext_; - if (context->primitiveScopeStorageEnd_ != prevPrimitiveEnd_) { - context->primitiveScopeStorageEnd_ = prevPrimitiveEnd_; + context->SetPrimitiveScopeStorageNext(prevPrimitiveNext_); + if (context->GetPrimitiveScopeStorageEnd() != prevPrimitiveEnd_) { + context->SetPrimitiveScopeStorageEnd(prevPrimitiveEnd_); context->ShrinkPrimitiveStorage(prevPrimitiveStorageIndex_); } } @@ -91,8 +91,8 @@ uintptr_t EcmaHandleScope::NewHandle(JSThread *thread, JSTaggedType value) // Handle is a kind of GC_ROOT, and should only directly hold Obejct or Primitive, not a weak reference. ASSERT(!JSTaggedValue(value).IsWeak()); auto context = thread->GetCurrentEcmaContext(); - auto result = context->handleScopeStorageNext_; - if (result == context->handleScopeStorageEnd_) { + auto result = context->GetHandleScopeStorageNext(); + if (result == context->GetHandleScopeStorageEnd()) { result = reinterpret_cast(context->ExpandHandleStorage()); } #if ECMASCRIPT_ENABLE_NEW_HANDLE_CHECK @@ -103,7 +103,7 @@ uintptr_t EcmaHandleScope::NewHandle(JSThread *thread, JSTaggedType value) } #endif // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - context->handleScopeStorageNext_ = result + 1; + context->SetHandleScopeStorageNext(result + 1); *result = value; #if defined(ENABLE_LOCAL_HANDLE_LEAK_DETECT) EcmaVM *vm = thread->GetEcmaVM(); @@ -119,8 +119,8 @@ uintptr_t EcmaHandleScope::NewPrimitiveHandle(JSThread *thread, JSTaggedType val { CHECK_NO_HANDLE_ALLOC; auto context = thread->GetCurrentEcmaContext(); - auto result = context->primitiveScopeStorageNext_; - if (result == context->primitiveScopeStorageEnd_) { + auto result = context->GetPrimitiveScopeStorageNext(); + if (result == context->GetPrimitiveScopeStorageEnd()) { result = reinterpret_cast(context->ExpandPrimitiveStorage()); } #if ECMASCRIPT_ENABLE_NEW_HANDLE_CHECK @@ -131,7 +131,7 @@ uintptr_t EcmaHandleScope::NewPrimitiveHandle(JSThread *thread, JSTaggedType val } #endif // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - context->primitiveScopeStorageNext_ = result + 1; + context->SetPrimitiveScopeStorageNext(result + 1); *result = value; #if defined(ENABLE_LOCAL_HANDLE_LEAK_DETECT) EcmaVM *vm = thread->GetEcmaVM(); @@ -142,4 +142,4 @@ uintptr_t EcmaHandleScope::NewPrimitiveHandle(JSThread *thread, JSTaggedType val #endif // ENABLE_LOCAL_HANDLE_LEAK_DETECT return reinterpret_cast(result); } -} // namespace panda::ecmascript \ No newline at end of file +} // namespace panda::ecmascript diff --git a/ecmascript/napi/include/jsnapi_expo.h b/ecmascript/napi/include/jsnapi_expo.h index d22362cc65..9228f5958b 100644 --- a/ecmascript/napi/include/jsnapi_expo.h +++ b/ecmascript/napi/include/jsnapi_expo.h @@ -1634,8 +1634,15 @@ public: // context static EcmaContext *CreateJSContext(EcmaVM *vm); static void SwitchCurrentContext(EcmaVM *vm, EcmaContext *context); + static EcmaContext *GetCurrentJSContext(EcmaVM *vm); static void DestroyJSContext(EcmaVM *vm, EcmaContext *context); + // handles + static void *CreateHandleStorage(EcmaVM *vm); + static void *GetCurrentHandleStorage(EcmaVM *vm); + static void SwitchHandleStorage(EcmaVM *vm, void *storage); + static void DestroyHandleStorage(EcmaVM *vm, void *storage); + // context execute static bool ExecuteInContext(EcmaVM *vm, const std::string &fileName, const std::string &entry, bool needUpdate = false); diff --git a/ecmascript/napi/jsnapi_expo.cpp b/ecmascript/napi/jsnapi_expo.cpp index 189c307a93..075f6106d5 100644 --- a/ecmascript/napi/jsnapi_expo.cpp +++ b/ecmascript/napi/jsnapi_expo.cpp @@ -4608,6 +4608,11 @@ EcmaContext *JSNApi::CreateJSContext(EcmaVM *vm) return EcmaContext::CreateAndInitialize(thread); } +EcmaContext *JSNApi::GetCurrentJSContext(EcmaVM *vm) +{ + return vm->GetJSThread()->GetCurrentEcmaContext(); +} + void JSNApi::SwitchCurrentContext(EcmaVM *vm, EcmaContext *context) { JSThread *thread = vm->GetJSThread(); @@ -4622,6 +4627,26 @@ void JSNApi::DestroyJSContext(EcmaVM *vm, EcmaContext *context) EcmaContext::CheckAndDestroy(thread, context); } +void *JSNApi::CreateHandleStorage(EcmaVM *vm) +{ + return vm->GetJSThread()->GetCurrentEcmaContext()->CreateHandleStorage(); +} + +void *JSNApi::GetCurrentHandleStorage(EcmaVM *vm) +{ + return vm->GetJSThread()->GetCurrentEcmaContext()->GetHandleStorage(); +} + +void JSNApi::SwitchHandleStorage(EcmaVM *vm, void *storage) +{ + vm->GetJSThread()->GetCurrentEcmaContext()->SetCurrentHandleStorage(reinterpret_cast(storage)); +} + +void JSNApi::DestroyHandleStorage(EcmaVM *vm, void *storage) +{ + vm->GetJSThread()->GetCurrentEcmaContext()->DeleteHandleStorage(reinterpret_cast(storage)); +} + EcmaVM *JSNApi::CreateEcmaVM(const JSRuntimeOptions &options) { return EcmaVM::Create(options); -- Gitee