14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/js_thread.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include "ecmascript/runtime.h"
194514f5e3Sopenharmony_ci#include "ecmascript/debugger/js_debugger_manager.h"
204514f5e3Sopenharmony_ci#include "ecmascript/js_object-inl.h"
214514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value.h"
224514f5e3Sopenharmony_ci#include "ecmascript/runtime_call_id.h"
234514f5e3Sopenharmony_ci#include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
244514f5e3Sopenharmony_ci
254514f5e3Sopenharmony_ci#if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS) && !defined(PANDA_TARGET_IOS)
264514f5e3Sopenharmony_ci#include <sys/resource.h>
274514f5e3Sopenharmony_ci#endif
284514f5e3Sopenharmony_ci
294514f5e3Sopenharmony_ci#if defined(ENABLE_EXCEPTION_BACKTRACE)
304514f5e3Sopenharmony_ci#include "ecmascript/platform/backtrace.h"
314514f5e3Sopenharmony_ci#endif
324514f5e3Sopenharmony_ci#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
334514f5e3Sopenharmony_ci#include "ecmascript/dfx/cpu_profiler/cpu_profiler.h"
344514f5e3Sopenharmony_ci#endif
354514f5e3Sopenharmony_ci#include "ecmascript/dfx/vm_thread_control.h"
364514f5e3Sopenharmony_ci#include "ecmascript/ecma_global_storage.h"
374514f5e3Sopenharmony_ci#include "ecmascript/ic/properties_cache.h"
384514f5e3Sopenharmony_ci#include "ecmascript/interpreter/interpreter.h"
394514f5e3Sopenharmony_ci#include "ecmascript/mem/concurrent_marker.h"
404514f5e3Sopenharmony_ci#include "ecmascript/platform/file.h"
414514f5e3Sopenharmony_ci#include "ecmascript/jit/jit.h"
424514f5e3Sopenharmony_ci
434514f5e3Sopenharmony_cinamespace panda::ecmascript {
444514f5e3Sopenharmony_ciusing CommonStubCSigns = panda::ecmascript::kungfu::CommonStubCSigns;
454514f5e3Sopenharmony_ciusing BytecodeStubCSigns = panda::ecmascript::kungfu::BytecodeStubCSigns;
464514f5e3Sopenharmony_ci
474514f5e3Sopenharmony_cithread_local JSThread *currentThread = nullptr;
484514f5e3Sopenharmony_ci
494514f5e3Sopenharmony_ciJSThread *JSThread::GetCurrent()
504514f5e3Sopenharmony_ci{
514514f5e3Sopenharmony_ci    return currentThread;
524514f5e3Sopenharmony_ci}
534514f5e3Sopenharmony_ci
544514f5e3Sopenharmony_ci// static
554514f5e3Sopenharmony_civoid JSThread::RegisterThread(JSThread *jsThread)
564514f5e3Sopenharmony_ci{
574514f5e3Sopenharmony_ci    Runtime::GetInstance()->RegisterThread(jsThread);
584514f5e3Sopenharmony_ci    // If it is not true, we created a new thread for future fork
594514f5e3Sopenharmony_ci    if (currentThread == nullptr) {
604514f5e3Sopenharmony_ci        currentThread = jsThread;
614514f5e3Sopenharmony_ci        jsThread->UpdateState(ThreadState::NATIVE);
624514f5e3Sopenharmony_ci    }
634514f5e3Sopenharmony_ci}
644514f5e3Sopenharmony_ci
654514f5e3Sopenharmony_civoid JSThread::UnregisterThread(JSThread *jsThread)
664514f5e3Sopenharmony_ci{
674514f5e3Sopenharmony_ci    if (currentThread == jsThread) {
684514f5e3Sopenharmony_ci        jsThread->UpdateState(ThreadState::TERMINATED);
694514f5e3Sopenharmony_ci        currentThread = nullptr;
704514f5e3Sopenharmony_ci    } else {
714514f5e3Sopenharmony_ci        // We have created this JSThread instance but hadn't forked it.
724514f5e3Sopenharmony_ci        ASSERT(jsThread->GetState() == ThreadState::CREATED);
734514f5e3Sopenharmony_ci        jsThread->UpdateState(ThreadState::TERMINATED);
744514f5e3Sopenharmony_ci    }
754514f5e3Sopenharmony_ci    Runtime::GetInstance()->UnregisterThread(jsThread);
764514f5e3Sopenharmony_ci}
774514f5e3Sopenharmony_ci
784514f5e3Sopenharmony_ci// static
794514f5e3Sopenharmony_ciJSThread *JSThread::Create(EcmaVM *vm)
804514f5e3Sopenharmony_ci{
814514f5e3Sopenharmony_ci    auto jsThread = new JSThread(vm);
824514f5e3Sopenharmony_ci
834514f5e3Sopenharmony_ci    AsmInterParsedOption asmInterOpt = vm->GetJSOptions().GetAsmInterParsedOption();
844514f5e3Sopenharmony_ci    if (asmInterOpt.enableAsm) {
854514f5e3Sopenharmony_ci        jsThread->EnableAsmInterpreter();
864514f5e3Sopenharmony_ci    }
874514f5e3Sopenharmony_ci
884514f5e3Sopenharmony_ci    jsThread->nativeAreaAllocator_ = vm->GetNativeAreaAllocator();
894514f5e3Sopenharmony_ci    jsThread->heapRegionAllocator_ = vm->GetHeapRegionAllocator();
904514f5e3Sopenharmony_ci    // algin with 16
914514f5e3Sopenharmony_ci    size_t maxStackSize = vm->GetEcmaParamConfiguration().GetMaxStackSize();
924514f5e3Sopenharmony_ci    jsThread->glueData_.frameBase_ = static_cast<JSTaggedType *>(
934514f5e3Sopenharmony_ci        vm->GetNativeAreaAllocator()->Allocate(sizeof(JSTaggedType) * maxStackSize));
944514f5e3Sopenharmony_ci    jsThread->glueData_.currentFrame_ = jsThread->glueData_.frameBase_ + maxStackSize;
954514f5e3Sopenharmony_ci    EcmaInterpreter::InitStackFrame(jsThread);
964514f5e3Sopenharmony_ci
974514f5e3Sopenharmony_ci    jsThread->glueData_.stackLimit_ = GetAsmStackLimit();
984514f5e3Sopenharmony_ci    jsThread->glueData_.stackStart_ = GetCurrentStackPosition();
994514f5e3Sopenharmony_ci    jsThread->glueData_.isEnableElementsKind_ = vm->IsEnableElementsKind();
1004514f5e3Sopenharmony_ci    jsThread->glueData_.isEnableForceIC_ = ecmascript::pgo::PGOProfilerManager::GetInstance()->IsEnableForceIC();
1014514f5e3Sopenharmony_ci    jsThread->SetThreadId();
1024514f5e3Sopenharmony_ci
1034514f5e3Sopenharmony_ci    RegisterThread(jsThread);
1044514f5e3Sopenharmony_ci    return jsThread;
1054514f5e3Sopenharmony_ci}
1064514f5e3Sopenharmony_ci
1074514f5e3Sopenharmony_ciJSThread::JSThread(EcmaVM *vm) : id_(os::thread::GetCurrentThreadId()), vm_(vm)
1084514f5e3Sopenharmony_ci{
1094514f5e3Sopenharmony_ci    auto chunk = vm->GetChunk();
1104514f5e3Sopenharmony_ci    if (!vm_->GetJSOptions().EnableGlobalLeakCheck()) {
1114514f5e3Sopenharmony_ci        globalStorage_ = chunk->New<EcmaGlobalStorage<Node>>(this, vm->GetNativeAreaAllocator());
1124514f5e3Sopenharmony_ci        newGlobalHandle_ = [this](JSTaggedType value) { return globalStorage_->NewGlobalHandle(value); };
1134514f5e3Sopenharmony_ci        disposeGlobalHandle_ = [this](uintptr_t nodeAddr) { globalStorage_->DisposeGlobalHandle(nodeAddr); };
1144514f5e3Sopenharmony_ci        setWeak_ = [this](uintptr_t nodeAddr, void *ref, WeakClearCallback freeGlobalCallBack,
1154514f5e3Sopenharmony_ci                        WeakClearCallback nativeFinalizeCallBack) {
1164514f5e3Sopenharmony_ci            return globalStorage_->SetWeak(nodeAddr, ref, freeGlobalCallBack, nativeFinalizeCallBack);
1174514f5e3Sopenharmony_ci        };
1184514f5e3Sopenharmony_ci        clearWeak_ = [this](uintptr_t nodeAddr) { return globalStorage_->ClearWeak(nodeAddr); };
1194514f5e3Sopenharmony_ci        isWeak_ = [this](uintptr_t addr) { return globalStorage_->IsWeak(addr); };
1204514f5e3Sopenharmony_ci    } else {
1214514f5e3Sopenharmony_ci        globalDebugStorage_ = chunk->New<EcmaGlobalStorage<DebugNode>>(this, vm->GetNativeAreaAllocator());
1224514f5e3Sopenharmony_ci        newGlobalHandle_ = [this](JSTaggedType value) { return globalDebugStorage_->NewGlobalHandle(value); };
1234514f5e3Sopenharmony_ci        disposeGlobalHandle_ = [this](uintptr_t nodeAddr) { globalDebugStorage_->DisposeGlobalHandle(nodeAddr); };
1244514f5e3Sopenharmony_ci        setWeak_ = [this](uintptr_t nodeAddr, void *ref, WeakClearCallback freeGlobalCallBack,
1254514f5e3Sopenharmony_ci                        WeakClearCallback nativeFinalizeCallBack) {
1264514f5e3Sopenharmony_ci            return globalDebugStorage_->SetWeak(nodeAddr, ref, freeGlobalCallBack, nativeFinalizeCallBack);
1274514f5e3Sopenharmony_ci        };
1284514f5e3Sopenharmony_ci        clearWeak_ = [this](uintptr_t nodeAddr) { return globalDebugStorage_->ClearWeak(nodeAddr); };
1294514f5e3Sopenharmony_ci        isWeak_ = [this](uintptr_t addr) { return globalDebugStorage_->IsWeak(addr); };
1304514f5e3Sopenharmony_ci    }
1314514f5e3Sopenharmony_ci    vmThreadControl_ = new VmThreadControl(this);
1324514f5e3Sopenharmony_ci    SetBCStubStatus(BCStubStatus::NORMAL_BC_STUB);
1334514f5e3Sopenharmony_ci}
1344514f5e3Sopenharmony_ci
1354514f5e3Sopenharmony_ciJSThread::JSThread(EcmaVM *vm, ThreadType threadType) : id_(os::thread::GetCurrentThreadId()),
1364514f5e3Sopenharmony_ci                                                        vm_(vm), threadType_(threadType)
1374514f5e3Sopenharmony_ci{
1384514f5e3Sopenharmony_ci    ASSERT(threadType == ThreadType::JIT_THREAD);
1394514f5e3Sopenharmony_ci    // jit thread no need GCIterating
1404514f5e3Sopenharmony_ci    readyForGCIterating_ = false;
1414514f5e3Sopenharmony_ci    RegisterThread(this);
1424514f5e3Sopenharmony_ci};
1434514f5e3Sopenharmony_ci
1444514f5e3Sopenharmony_ciJSThread::JSThread(ThreadType threadType) : threadType_(threadType)
1454514f5e3Sopenharmony_ci{
1464514f5e3Sopenharmony_ci    ASSERT(threadType == ThreadType::DAEMON_THREAD);
1474514f5e3Sopenharmony_ci    // daemon thread no need GCIterating
1484514f5e3Sopenharmony_ci    readyForGCIterating_ = false;
1494514f5e3Sopenharmony_ci}
1504514f5e3Sopenharmony_ci
1514514f5e3Sopenharmony_ciJSThread::~JSThread()
1524514f5e3Sopenharmony_ci{
1534514f5e3Sopenharmony_ci    readyForGCIterating_ = false;
1544514f5e3Sopenharmony_ci    if (globalStorage_ != nullptr) {
1554514f5e3Sopenharmony_ci        GetEcmaVM()->GetChunk()->Delete(globalStorage_);
1564514f5e3Sopenharmony_ci        globalStorage_ = nullptr;
1574514f5e3Sopenharmony_ci    }
1584514f5e3Sopenharmony_ci    if (globalDebugStorage_ != nullptr) {
1594514f5e3Sopenharmony_ci        GetEcmaVM()->GetChunk()->Delete(globalDebugStorage_);
1604514f5e3Sopenharmony_ci        globalDebugStorage_ = nullptr;
1614514f5e3Sopenharmony_ci    }
1624514f5e3Sopenharmony_ci
1634514f5e3Sopenharmony_ci    for (auto item : contexts_) {
1644514f5e3Sopenharmony_ci        GetNativeAreaAllocator()->Free(item->GetFrameBase(), sizeof(JSTaggedType) *
1654514f5e3Sopenharmony_ci            vm_->GetEcmaParamConfiguration().GetMaxStackSize());
1664514f5e3Sopenharmony_ci        item->SetFrameBase(nullptr);
1674514f5e3Sopenharmony_ci        delete item;
1684514f5e3Sopenharmony_ci    }
1694514f5e3Sopenharmony_ci    contexts_.clear();
1704514f5e3Sopenharmony_ci    GetNativeAreaAllocator()->FreeArea(regExpCache_);
1714514f5e3Sopenharmony_ci
1724514f5e3Sopenharmony_ci    glueData_.frameBase_ = nullptr;
1734514f5e3Sopenharmony_ci    nativeAreaAllocator_ = nullptr;
1744514f5e3Sopenharmony_ci    heapRegionAllocator_ = nullptr;
1754514f5e3Sopenharmony_ci    regExpCache_ = nullptr;
1764514f5e3Sopenharmony_ci    if (vmThreadControl_ != nullptr) {
1774514f5e3Sopenharmony_ci        delete vmThreadControl_;
1784514f5e3Sopenharmony_ci        vmThreadControl_ = nullptr;
1794514f5e3Sopenharmony_ci    }
1804514f5e3Sopenharmony_ci    // DaemonThread will be unregistered when the binding std::thread release.
1814514f5e3Sopenharmony_ci    if (!IsDaemonThread()) {
1824514f5e3Sopenharmony_ci        UnregisterThread(this);
1834514f5e3Sopenharmony_ci    }
1844514f5e3Sopenharmony_ci}
1854514f5e3Sopenharmony_ci
1864514f5e3Sopenharmony_ciThreadId JSThread::GetCurrentThreadId()
1874514f5e3Sopenharmony_ci{
1884514f5e3Sopenharmony_ci    return GetCurrentThreadOrTaskId();
1894514f5e3Sopenharmony_ci}
1904514f5e3Sopenharmony_ci
1914514f5e3Sopenharmony_civoid JSThread::SetException(JSTaggedValue exception)
1924514f5e3Sopenharmony_ci{
1934514f5e3Sopenharmony_ci    glueData_.exception_ = exception;
1944514f5e3Sopenharmony_ci#if defined(ENABLE_EXCEPTION_BACKTRACE)
1954514f5e3Sopenharmony_ci    if (vm_->GetJSOptions().EnableExceptionBacktrace()) {
1964514f5e3Sopenharmony_ci        LOG_ECMA(INFO) << "SetException:" << exception.GetRawData();
1974514f5e3Sopenharmony_ci        std::ostringstream stack;
1984514f5e3Sopenharmony_ci        Backtrace(stack);
1994514f5e3Sopenharmony_ci        LOG_ECMA(INFO) << stack.str();
2004514f5e3Sopenharmony_ci    }
2014514f5e3Sopenharmony_ci#endif
2024514f5e3Sopenharmony_ci}
2034514f5e3Sopenharmony_ci
2044514f5e3Sopenharmony_civoid JSThread::ClearException()
2054514f5e3Sopenharmony_ci{
2064514f5e3Sopenharmony_ci    glueData_.exception_ = JSTaggedValue::Hole();
2074514f5e3Sopenharmony_ci}
2084514f5e3Sopenharmony_ci
2094514f5e3Sopenharmony_civoid JSThread::SetEnableForceIC(bool isEnableForceIC)
2104514f5e3Sopenharmony_ci{
2114514f5e3Sopenharmony_ci    glueData_.isEnableForceIC_ = isEnableForceIC;
2124514f5e3Sopenharmony_ci}
2134514f5e3Sopenharmony_ci
2144514f5e3Sopenharmony_cibool JSThread::IsEnableForceIC() const
2154514f5e3Sopenharmony_ci{
2164514f5e3Sopenharmony_ci    return glueData_.isEnableForceIC_;
2174514f5e3Sopenharmony_ci}
2184514f5e3Sopenharmony_ci
2194514f5e3Sopenharmony_ciJSTaggedValue JSThread::GetCurrentLexenv() const
2204514f5e3Sopenharmony_ci{
2214514f5e3Sopenharmony_ci    FrameHandler frameHandler(this);
2224514f5e3Sopenharmony_ci    return frameHandler.GetEnv();
2234514f5e3Sopenharmony_ci}
2244514f5e3Sopenharmony_ci
2254514f5e3Sopenharmony_ciJSTaggedValue JSThread::GetCurrentFunction() const
2264514f5e3Sopenharmony_ci{
2274514f5e3Sopenharmony_ci    FrameHandler frameHandler(this);
2284514f5e3Sopenharmony_ci    return frameHandler.GetFunction();
2294514f5e3Sopenharmony_ci}
2304514f5e3Sopenharmony_ci
2314514f5e3Sopenharmony_ciconst JSTaggedType *JSThread::GetCurrentFrame() const
2324514f5e3Sopenharmony_ci{
2334514f5e3Sopenharmony_ci    if (IsAsmInterpreter()) {
2344514f5e3Sopenharmony_ci        return GetLastLeaveFrame();
2354514f5e3Sopenharmony_ci    }
2364514f5e3Sopenharmony_ci    return GetCurrentSPFrame();
2374514f5e3Sopenharmony_ci}
2384514f5e3Sopenharmony_ci
2394514f5e3Sopenharmony_civoid JSThread::SetCurrentFrame(JSTaggedType *sp)
2404514f5e3Sopenharmony_ci{
2414514f5e3Sopenharmony_ci    if (IsAsmInterpreter()) {
2424514f5e3Sopenharmony_ci        return SetLastLeaveFrame(sp);
2434514f5e3Sopenharmony_ci    }
2444514f5e3Sopenharmony_ci    return SetCurrentSPFrame(sp);
2454514f5e3Sopenharmony_ci}
2464514f5e3Sopenharmony_ci
2474514f5e3Sopenharmony_ciconst JSTaggedType *JSThread::GetCurrentInterpretedFrame() const
2484514f5e3Sopenharmony_ci{
2494514f5e3Sopenharmony_ci    if (IsAsmInterpreter()) {
2504514f5e3Sopenharmony_ci        auto frameHandler = FrameHandler(this);
2514514f5e3Sopenharmony_ci        return frameHandler.GetSp();
2524514f5e3Sopenharmony_ci    }
2534514f5e3Sopenharmony_ci    return GetCurrentSPFrame();
2544514f5e3Sopenharmony_ci}
2554514f5e3Sopenharmony_ci
2564514f5e3Sopenharmony_civoid JSThread::InvokeWeakNodeFreeGlobalCallBack()
2574514f5e3Sopenharmony_ci{
2584514f5e3Sopenharmony_ci    while (!weakNodeFreeGlobalCallbacks_.empty()) {
2594514f5e3Sopenharmony_ci        auto callbackPair = weakNodeFreeGlobalCallbacks_.back();
2604514f5e3Sopenharmony_ci        weakNodeFreeGlobalCallbacks_.pop_back();
2614514f5e3Sopenharmony_ci        ASSERT(callbackPair.first != nullptr && callbackPair.second != nullptr);
2624514f5e3Sopenharmony_ci        auto callback = callbackPair.first;
2634514f5e3Sopenharmony_ci        (*callback)(callbackPair.second);
2644514f5e3Sopenharmony_ci    }
2654514f5e3Sopenharmony_ci}
2664514f5e3Sopenharmony_ci
2674514f5e3Sopenharmony_civoid JSThread::InvokeWeakNodeNativeFinalizeCallback()
2684514f5e3Sopenharmony_ci{
2694514f5e3Sopenharmony_ci    // the second callback may lead to another GC, if this, return directly;
2704514f5e3Sopenharmony_ci    if (runningNativeFinalizeCallbacks_) {
2714514f5e3Sopenharmony_ci        return;
2724514f5e3Sopenharmony_ci    }
2734514f5e3Sopenharmony_ci    runningNativeFinalizeCallbacks_ = true;
2744514f5e3Sopenharmony_ci    ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "InvokeNativeFinalizeCallbacks num:"
2754514f5e3Sopenharmony_ci        + std::to_string(weakNodeNativeFinalizeCallbacks_.size()));
2764514f5e3Sopenharmony_ci    while (!weakNodeNativeFinalizeCallbacks_.empty()) {
2774514f5e3Sopenharmony_ci        auto callbackPair = weakNodeNativeFinalizeCallbacks_.back();
2784514f5e3Sopenharmony_ci        weakNodeNativeFinalizeCallbacks_.pop_back();
2794514f5e3Sopenharmony_ci        ASSERT(callbackPair.first != nullptr && callbackPair.second != nullptr);
2804514f5e3Sopenharmony_ci        auto callback = callbackPair.first;
2814514f5e3Sopenharmony_ci        (*callback)(callbackPair.second);
2824514f5e3Sopenharmony_ci    }
2834514f5e3Sopenharmony_ci    if (finalizeTaskCallback_ != nullptr) {
2844514f5e3Sopenharmony_ci        finalizeTaskCallback_();
2854514f5e3Sopenharmony_ci    }
2864514f5e3Sopenharmony_ci    runningNativeFinalizeCallbacks_ = false;
2874514f5e3Sopenharmony_ci}
2884514f5e3Sopenharmony_ci
2894514f5e3Sopenharmony_cibool JSThread::IsStartGlobalLeakCheck() const
2904514f5e3Sopenharmony_ci{
2914514f5e3Sopenharmony_ci    return GetEcmaVM()->GetJSOptions().IsStartGlobalLeakCheck();
2924514f5e3Sopenharmony_ci}
2934514f5e3Sopenharmony_ci
2944514f5e3Sopenharmony_cibool JSThread::EnableGlobalObjectLeakCheck() const
2954514f5e3Sopenharmony_ci{
2964514f5e3Sopenharmony_ci    return GetEcmaVM()->GetJSOptions().EnableGlobalObjectLeakCheck();
2974514f5e3Sopenharmony_ci}
2984514f5e3Sopenharmony_ci
2994514f5e3Sopenharmony_cibool JSThread::EnableGlobalPrimitiveLeakCheck() const
3004514f5e3Sopenharmony_ci{
3014514f5e3Sopenharmony_ci    return GetEcmaVM()->GetJSOptions().EnableGlobalPrimitiveLeakCheck();
3024514f5e3Sopenharmony_ci}
3034514f5e3Sopenharmony_ci
3044514f5e3Sopenharmony_cibool JSThread::IsInRunningStateOrProfiling() const
3054514f5e3Sopenharmony_ci{
3064514f5e3Sopenharmony_ci    bool result = IsInRunningState();
3074514f5e3Sopenharmony_ci#if defined(ECMASCRIPT_SUPPORT_HEAPPROFILER)
3084514f5e3Sopenharmony_ci    result |= vm_->GetHeapProfile() != nullptr;
3094514f5e3Sopenharmony_ci#endif
3104514f5e3Sopenharmony_ci#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
3114514f5e3Sopenharmony_ci    result |= GetIsProfiling();
3124514f5e3Sopenharmony_ci#endif
3134514f5e3Sopenharmony_ci    return result;
3144514f5e3Sopenharmony_ci}
3154514f5e3Sopenharmony_ci
3164514f5e3Sopenharmony_civoid JSThread::WriteToStackTraceFd(std::ostringstream &buffer) const
3174514f5e3Sopenharmony_ci{
3184514f5e3Sopenharmony_ci    if (stackTraceFd_ < 0) {
3194514f5e3Sopenharmony_ci        return;
3204514f5e3Sopenharmony_ci    }
3214514f5e3Sopenharmony_ci    buffer << std::endl;
3224514f5e3Sopenharmony_ci    DPrintf(reinterpret_cast<fd_t>(stackTraceFd_), buffer.str());
3234514f5e3Sopenharmony_ci    buffer.str("");
3244514f5e3Sopenharmony_ci}
3254514f5e3Sopenharmony_ci
3264514f5e3Sopenharmony_civoid JSThread::SetStackTraceFd(int32_t fd)
3274514f5e3Sopenharmony_ci{
3284514f5e3Sopenharmony_ci    stackTraceFd_ = fd;
3294514f5e3Sopenharmony_ci}
3304514f5e3Sopenharmony_ci
3314514f5e3Sopenharmony_civoid JSThread::CloseStackTraceFd()
3324514f5e3Sopenharmony_ci{
3334514f5e3Sopenharmony_ci    if (stackTraceFd_ != -1) {
3344514f5e3Sopenharmony_ci        FSync(reinterpret_cast<fd_t>(stackTraceFd_));
3354514f5e3Sopenharmony_ci        Close(reinterpret_cast<fd_t>(stackTraceFd_));
3364514f5e3Sopenharmony_ci        stackTraceFd_ = -1;
3374514f5e3Sopenharmony_ci    }
3384514f5e3Sopenharmony_ci}
3394514f5e3Sopenharmony_ci
3404514f5e3Sopenharmony_civoid JSThread::SetJitCodeMap(JSTaggedType exception,  MachineCode* machineCode, std::string &methodName,
3414514f5e3Sopenharmony_ci    uintptr_t offset)
3424514f5e3Sopenharmony_ci{
3434514f5e3Sopenharmony_ci    auto it = jitCodeMaps_.find(exception);
3444514f5e3Sopenharmony_ci    if (it != jitCodeMaps_.end()) {
3454514f5e3Sopenharmony_ci        it->second->push_back(std::make_tuple(machineCode, methodName, offset));
3464514f5e3Sopenharmony_ci    } else {
3474514f5e3Sopenharmony_ci        JitCodeVector *jitCode = new JitCodeVector {std::make_tuple(machineCode, methodName, offset)};
3484514f5e3Sopenharmony_ci        jitCodeMaps_.emplace(exception, jitCode);
3494514f5e3Sopenharmony_ci    }
3504514f5e3Sopenharmony_ci}
3514514f5e3Sopenharmony_ci
3524514f5e3Sopenharmony_civoid JSThread::Iterate(const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
3534514f5e3Sopenharmony_ci    const RootBaseAndDerivedVisitor &derivedVisitor)
3544514f5e3Sopenharmony_ci{
3554514f5e3Sopenharmony_ci    if (!glueData_.exception_.IsHole()) {
3564514f5e3Sopenharmony_ci        visitor(Root::ROOT_VM, ObjectSlot(ToUintPtr(&glueData_.exception_)));
3574514f5e3Sopenharmony_ci    }
3584514f5e3Sopenharmony_ci    rangeVisitor(
3594514f5e3Sopenharmony_ci        Root::ROOT_VM, ObjectSlot(glueData_.builtinEntries_.Begin()), ObjectSlot(glueData_.builtinEntries_.End()));
3604514f5e3Sopenharmony_ci
3614514f5e3Sopenharmony_ci    EcmaContext *tempContext = glueData_.currentContext_;
3624514f5e3Sopenharmony_ci    for (EcmaContext *context : contexts_) {
3634514f5e3Sopenharmony_ci        // visit stack roots
3644514f5e3Sopenharmony_ci        SwitchCurrentContext(context, true);
3654514f5e3Sopenharmony_ci        FrameHandler frameHandler(this);
3664514f5e3Sopenharmony_ci        frameHandler.Iterate(visitor, rangeVisitor, derivedVisitor);
3674514f5e3Sopenharmony_ci        context->Iterate(visitor, rangeVisitor);
3684514f5e3Sopenharmony_ci    }
3694514f5e3Sopenharmony_ci    SwitchCurrentContext(tempContext, true);
3704514f5e3Sopenharmony_ci    // visit tagged handle storage roots
3714514f5e3Sopenharmony_ci    if (vm_->GetJSOptions().EnableGlobalLeakCheck()) {
3724514f5e3Sopenharmony_ci        IterateHandleWithCheck(visitor, rangeVisitor);
3734514f5e3Sopenharmony_ci    } else {
3744514f5e3Sopenharmony_ci        size_t globalCount = 0;
3754514f5e3Sopenharmony_ci        globalStorage_->IterateUsageGlobal([visitor, &globalCount](Node *node) {
3764514f5e3Sopenharmony_ci            JSTaggedValue value(node->GetObject());
3774514f5e3Sopenharmony_ci            if (value.IsHeapObject()) {
3784514f5e3Sopenharmony_ci                visitor(ecmascript::Root::ROOT_HANDLE, ecmascript::ObjectSlot(node->GetObjectAddress()));
3794514f5e3Sopenharmony_ci            }
3804514f5e3Sopenharmony_ci            globalCount++;
3814514f5e3Sopenharmony_ci        });
3824514f5e3Sopenharmony_ci        static bool hasCheckedGlobalCount = false;
3834514f5e3Sopenharmony_ci        static const size_t WARN_GLOBAL_COUNT = 100000;
3844514f5e3Sopenharmony_ci        if (!hasCheckedGlobalCount && globalCount >= WARN_GLOBAL_COUNT) {
3854514f5e3Sopenharmony_ci            LOG_ECMA(WARN) << "Global reference count is " << globalCount << ",It exceed the upper limit 100000!";
3864514f5e3Sopenharmony_ci            hasCheckedGlobalCount = true;
3874514f5e3Sopenharmony_ci        }
3884514f5e3Sopenharmony_ci    }
3894514f5e3Sopenharmony_ci}
3904514f5e3Sopenharmony_civoid JSThread::IterateJitCodeMap(const JitCodeMapVisitor &jitCodeMapVisitor)
3914514f5e3Sopenharmony_ci{
3924514f5e3Sopenharmony_ci    jitCodeMapVisitor(jitCodeMaps_);
3934514f5e3Sopenharmony_ci}
3944514f5e3Sopenharmony_ci
3954514f5e3Sopenharmony_civoid JSThread::IterateHandleWithCheck(const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor)
3964514f5e3Sopenharmony_ci{
3974514f5e3Sopenharmony_ci    size_t handleCount = 0;
3984514f5e3Sopenharmony_ci    for (EcmaContext *context : contexts_) {
3994514f5e3Sopenharmony_ci        handleCount += context->IterateHandle(rangeVisitor);
4004514f5e3Sopenharmony_ci    }
4014514f5e3Sopenharmony_ci
4024514f5e3Sopenharmony_ci    size_t globalCount = 0;
4034514f5e3Sopenharmony_ci    static const int JS_TYPE_LAST = static_cast<int>(JSType::TYPE_LAST);
4044514f5e3Sopenharmony_ci    int typeCount[JS_TYPE_LAST] = { 0 };
4054514f5e3Sopenharmony_ci    int primitiveCount = 0;
4064514f5e3Sopenharmony_ci    bool isStopObjectLeakCheck = EnableGlobalObjectLeakCheck() && !IsStartGlobalLeakCheck() && stackTraceFd_ > 0;
4074514f5e3Sopenharmony_ci    bool isStopPrimitiveLeakCheck = EnableGlobalPrimitiveLeakCheck() && !IsStartGlobalLeakCheck() && stackTraceFd_ > 0;
4084514f5e3Sopenharmony_ci    std::ostringstream buffer;
4094514f5e3Sopenharmony_ci    globalDebugStorage_->IterateUsageGlobal([this, visitor, &globalCount, &typeCount, &primitiveCount,
4104514f5e3Sopenharmony_ci        isStopObjectLeakCheck, isStopPrimitiveLeakCheck, &buffer](DebugNode *node) {
4114514f5e3Sopenharmony_ci        node->MarkCount();
4124514f5e3Sopenharmony_ci        JSTaggedValue value(node->GetObject());
4134514f5e3Sopenharmony_ci        if (value.IsHeapObject()) {
4144514f5e3Sopenharmony_ci            visitor(ecmascript::Root::ROOT_HANDLE, ecmascript::ObjectSlot(node->GetObjectAddress()));
4154514f5e3Sopenharmony_ci            TaggedObject *object = value.GetTaggedObject();
4164514f5e3Sopenharmony_ci            MarkWord word(value.GetTaggedObject());
4174514f5e3Sopenharmony_ci            if (word.IsForwardingAddress()) {
4184514f5e3Sopenharmony_ci                object = word.ToForwardingAddress();
4194514f5e3Sopenharmony_ci            }
4204514f5e3Sopenharmony_ci            typeCount[static_cast<int>(object->GetClass()->GetObjectType())]++;
4214514f5e3Sopenharmony_ci
4224514f5e3Sopenharmony_ci            // Print global information about possible memory leaks.
4234514f5e3Sopenharmony_ci            // You can print the global new stack within the range of the leaked global number.
4244514f5e3Sopenharmony_ci            if (isStopObjectLeakCheck && node->GetGlobalNumber() > 0 && node->GetMarkCount() > 0) {
4254514f5e3Sopenharmony_ci                buffer << "Global maybe leak object address:" << std::hex << object <<
4264514f5e3Sopenharmony_ci                    ", type:" << JSHClass::DumpJSType(JSType(object->GetClass()->GetObjectType())) <<
4274514f5e3Sopenharmony_ci                    ", node address:" << node << ", number:" << std::dec <<  node->GetGlobalNumber() <<
4284514f5e3Sopenharmony_ci                    ", markCount:" << node->GetMarkCount();
4294514f5e3Sopenharmony_ci                WriteToStackTraceFd(buffer);
4304514f5e3Sopenharmony_ci            }
4314514f5e3Sopenharmony_ci        } else {
4324514f5e3Sopenharmony_ci            primitiveCount++;
4334514f5e3Sopenharmony_ci            if (isStopPrimitiveLeakCheck && node->GetGlobalNumber() > 0 && node->GetMarkCount() > 0) {
4344514f5e3Sopenharmony_ci                buffer << "Global maybe leak primitive:" << std::hex << value.GetRawData() <<
4354514f5e3Sopenharmony_ci                    ", node address:" << node << ", number:" << std::dec <<  node->GetGlobalNumber() <<
4364514f5e3Sopenharmony_ci                    ", markCount:" << node->GetMarkCount();
4374514f5e3Sopenharmony_ci                WriteToStackTraceFd(buffer);
4384514f5e3Sopenharmony_ci            }
4394514f5e3Sopenharmony_ci        }
4404514f5e3Sopenharmony_ci        globalCount++;
4414514f5e3Sopenharmony_ci    });
4424514f5e3Sopenharmony_ci
4434514f5e3Sopenharmony_ci    if (isStopObjectLeakCheck || isStopPrimitiveLeakCheck) {
4444514f5e3Sopenharmony_ci        buffer << "Global leak check success!";
4454514f5e3Sopenharmony_ci        WriteToStackTraceFd(buffer);
4464514f5e3Sopenharmony_ci        CloseStackTraceFd();
4474514f5e3Sopenharmony_ci    }
4484514f5e3Sopenharmony_ci    // Determine whether memory leakage by checking handle and global count.
4494514f5e3Sopenharmony_ci    LOG_ECMA(INFO) << "Iterate root handle count:" << handleCount << ", global handle count:" << globalCount;
4504514f5e3Sopenharmony_ci    OPTIONAL_LOG(GetEcmaVM(), INFO) << "Global type Primitive count:" << primitiveCount;
4514514f5e3Sopenharmony_ci    // Print global object type statistic.
4524514f5e3Sopenharmony_ci    static const int MIN_COUNT_THRESHOLD = 50;
4534514f5e3Sopenharmony_ci    for (int i = 0; i < JS_TYPE_LAST; i++) {
4544514f5e3Sopenharmony_ci        if (typeCount[i] > MIN_COUNT_THRESHOLD) {
4554514f5e3Sopenharmony_ci            OPTIONAL_LOG(GetEcmaVM(), INFO) << "Global type " << JSHClass::DumpJSType(JSType(i))
4564514f5e3Sopenharmony_ci                                            << " count:" << typeCount[i];
4574514f5e3Sopenharmony_ci        }
4584514f5e3Sopenharmony_ci    }
4594514f5e3Sopenharmony_ci}
4604514f5e3Sopenharmony_ci
4614514f5e3Sopenharmony_civoid JSThread::IterateWeakEcmaGlobalStorage(const WeakRootVisitor &visitor, GCKind gcKind)
4624514f5e3Sopenharmony_ci{
4634514f5e3Sopenharmony_ci    auto callBack = [this, visitor, gcKind](WeakNode *node) {
4644514f5e3Sopenharmony_ci        JSTaggedValue value(node->GetObject());
4654514f5e3Sopenharmony_ci        if (!value.IsHeapObject()) {
4664514f5e3Sopenharmony_ci            return;
4674514f5e3Sopenharmony_ci        }
4684514f5e3Sopenharmony_ci        auto object = value.GetTaggedObject();
4694514f5e3Sopenharmony_ci        auto fwd = visitor(object);
4704514f5e3Sopenharmony_ci        if (fwd == nullptr) {
4714514f5e3Sopenharmony_ci            // undefind
4724514f5e3Sopenharmony_ci            node->SetObject(JSTaggedValue::Undefined().GetRawData());
4734514f5e3Sopenharmony_ci            auto nativeFinalizeCallback = node->GetNativeFinalizeCallback();
4744514f5e3Sopenharmony_ci            if (nativeFinalizeCallback) {
4754514f5e3Sopenharmony_ci                weakNodeNativeFinalizeCallbacks_.push_back(std::make_pair(nativeFinalizeCallback,
4764514f5e3Sopenharmony_ci                                                                          node->GetReference()));
4774514f5e3Sopenharmony_ci            }
4784514f5e3Sopenharmony_ci            auto freeGlobalCallBack = node->GetFreeGlobalCallback();
4794514f5e3Sopenharmony_ci            if (!freeGlobalCallBack) {
4804514f5e3Sopenharmony_ci                // If no callback, dispose global immediately
4814514f5e3Sopenharmony_ci                DisposeGlobalHandle(ToUintPtr(node));
4824514f5e3Sopenharmony_ci            } else if (gcKind == GCKind::SHARED_GC) {
4834514f5e3Sopenharmony_ci                // For shared GC, free global should defer execute in its own thread
4844514f5e3Sopenharmony_ci                weakNodeFreeGlobalCallbacks_.push_back(std::make_pair(freeGlobalCallBack, node->GetReference()));
4854514f5e3Sopenharmony_ci            } else {
4864514f5e3Sopenharmony_ci                node->CallFreeGlobalCallback();
4874514f5e3Sopenharmony_ci            }
4884514f5e3Sopenharmony_ci        } else if (fwd != object) {
4894514f5e3Sopenharmony_ci            // update
4904514f5e3Sopenharmony_ci            node->SetObject(JSTaggedValue(fwd).GetRawData());
4914514f5e3Sopenharmony_ci        }
4924514f5e3Sopenharmony_ci    };
4934514f5e3Sopenharmony_ci    if (!vm_->GetJSOptions().EnableGlobalLeakCheck()) {
4944514f5e3Sopenharmony_ci        globalStorage_->IterateWeakUsageGlobal(callBack);
4954514f5e3Sopenharmony_ci    } else {
4964514f5e3Sopenharmony_ci        globalDebugStorage_->IterateWeakUsageGlobal(callBack);
4974514f5e3Sopenharmony_ci    }
4984514f5e3Sopenharmony_ci}
4994514f5e3Sopenharmony_ci
5004514f5e3Sopenharmony_civoid JSThread::UpdateJitCodeMapReference(const WeakRootVisitor &visitor)
5014514f5e3Sopenharmony_ci{
5024514f5e3Sopenharmony_ci    auto it = jitCodeMaps_.begin();
5034514f5e3Sopenharmony_ci    while (it != jitCodeMaps_.end()) {
5044514f5e3Sopenharmony_ci        auto obj = reinterpret_cast<TaggedObject *>(it->first);
5054514f5e3Sopenharmony_ci        auto fwd = visitor(obj);
5064514f5e3Sopenharmony_ci        if (fwd == nullptr) {
5074514f5e3Sopenharmony_ci            delete it->second;
5084514f5e3Sopenharmony_ci            it = jitCodeMaps_.erase(it);
5094514f5e3Sopenharmony_ci        } else if (fwd != obj) {
5104514f5e3Sopenharmony_ci            jitCodeMaps_.emplace(JSTaggedValue(fwd).GetRawData(), it->second);
5114514f5e3Sopenharmony_ci            it = jitCodeMaps_.erase(it);
5124514f5e3Sopenharmony_ci        } else {
5134514f5e3Sopenharmony_ci            ++it;
5144514f5e3Sopenharmony_ci        }
5154514f5e3Sopenharmony_ci    }
5164514f5e3Sopenharmony_ci}
5174514f5e3Sopenharmony_ci
5184514f5e3Sopenharmony_cibool JSThread::DoStackOverflowCheck(const JSTaggedType *sp)
5194514f5e3Sopenharmony_ci{
5204514f5e3Sopenharmony_ci    // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
5214514f5e3Sopenharmony_ci    if (UNLIKELY(!IsCrossThreadExecutionEnable() && sp <= glueData_.frameBase_ + RESERVE_STACK_SIZE)) {
5224514f5e3Sopenharmony_ci        vm_->CheckThread();
5234514f5e3Sopenharmony_ci        LOG_ECMA(ERROR) << "Stack overflow! Remaining stack size is: " << (sp - glueData_.frameBase_);
5244514f5e3Sopenharmony_ci        if (LIKELY(!HasPendingException())) {
5254514f5e3Sopenharmony_ci            ObjectFactory *factory = GetEcmaVM()->GetFactory();
5264514f5e3Sopenharmony_ci            JSHandle<JSObject> error = factory->GetJSError(base::ErrorType::RANGE_ERROR,
5274514f5e3Sopenharmony_ci                                                           "Stack overflow!", StackCheck::NO);
5284514f5e3Sopenharmony_ci            SetException(error.GetTaggedValue());
5294514f5e3Sopenharmony_ci        }
5304514f5e3Sopenharmony_ci        return true;
5314514f5e3Sopenharmony_ci    }
5324514f5e3Sopenharmony_ci    return false;
5334514f5e3Sopenharmony_ci}
5344514f5e3Sopenharmony_ci
5354514f5e3Sopenharmony_cibool JSThread::DoStackLimitCheck()
5364514f5e3Sopenharmony_ci{
5374514f5e3Sopenharmony_ci    if (UNLIKELY(!IsCrossThreadExecutionEnable() && GetCurrentStackPosition() < GetStackLimit())) {
5384514f5e3Sopenharmony_ci        vm_->CheckThread();
5394514f5e3Sopenharmony_ci        LOG_ECMA(ERROR) << "Stack overflow! current:" << GetCurrentStackPosition() << " limit:" << GetStackLimit();
5404514f5e3Sopenharmony_ci        if (LIKELY(!HasPendingException())) {
5414514f5e3Sopenharmony_ci            ObjectFactory *factory = GetEcmaVM()->GetFactory();
5424514f5e3Sopenharmony_ci            JSHandle<JSObject> error = factory->GetJSError(base::ErrorType::RANGE_ERROR,
5434514f5e3Sopenharmony_ci                                                           "Stack overflow!", StackCheck::NO);
5444514f5e3Sopenharmony_ci            SetException(error.GetTaggedValue());
5454514f5e3Sopenharmony_ci        }
5464514f5e3Sopenharmony_ci        return true;
5474514f5e3Sopenharmony_ci    }
5484514f5e3Sopenharmony_ci    return false;
5494514f5e3Sopenharmony_ci}
5504514f5e3Sopenharmony_ci
5514514f5e3Sopenharmony_ciuintptr_t *JSThread::ExpandHandleStorage()
5524514f5e3Sopenharmony_ci{
5534514f5e3Sopenharmony_ci    return GetCurrentEcmaContext()->ExpandHandleStorage();
5544514f5e3Sopenharmony_ci}
5554514f5e3Sopenharmony_ci
5564514f5e3Sopenharmony_civoid JSThread::ShrinkHandleStorage(int prevIndex)
5574514f5e3Sopenharmony_ci{
5584514f5e3Sopenharmony_ci    GetCurrentEcmaContext()->ShrinkHandleStorage(prevIndex);
5594514f5e3Sopenharmony_ci}
5604514f5e3Sopenharmony_ci
5614514f5e3Sopenharmony_civoid JSThread::NotifyStableArrayElementsGuardians(JSHandle<JSObject> receiver, StableArrayChangeKind changeKind)
5624514f5e3Sopenharmony_ci{
5634514f5e3Sopenharmony_ci    if (!glueData_.stableArrayElementsGuardians_) {
5644514f5e3Sopenharmony_ci        return;
5654514f5e3Sopenharmony_ci    }
5664514f5e3Sopenharmony_ci    if (!receiver->GetJSHClass()->IsPrototype() && !receiver->IsJSArray()) {
5674514f5e3Sopenharmony_ci        return;
5684514f5e3Sopenharmony_ci    }
5694514f5e3Sopenharmony_ci    auto env = GetEcmaVM()->GetGlobalEnv();
5704514f5e3Sopenharmony_ci    if (receiver.GetTaggedValue() == env->GetObjectFunctionPrototype().GetTaggedValue() ||
5714514f5e3Sopenharmony_ci        receiver.GetTaggedValue() == env->GetArrayPrototype().GetTaggedValue()) {
5724514f5e3Sopenharmony_ci        glueData_.stableArrayElementsGuardians_ = false;
5734514f5e3Sopenharmony_ci        return;
5744514f5e3Sopenharmony_ci    }
5754514f5e3Sopenharmony_ci    if (changeKind == StableArrayChangeKind::PROTO && receiver->IsJSArray()) {
5764514f5e3Sopenharmony_ci        glueData_.stableArrayElementsGuardians_ = false;
5774514f5e3Sopenharmony_ci    }
5784514f5e3Sopenharmony_ci}
5794514f5e3Sopenharmony_ci
5804514f5e3Sopenharmony_civoid JSThread::ResetGuardians()
5814514f5e3Sopenharmony_ci{
5824514f5e3Sopenharmony_ci    glueData_.stableArrayElementsGuardians_ = true;
5834514f5e3Sopenharmony_ci}
5844514f5e3Sopenharmony_ci
5854514f5e3Sopenharmony_civoid JSThread::SetInitialBuiltinHClass(
5864514f5e3Sopenharmony_ci    BuiltinTypeId type, JSHClass *builtinHClass, JSHClass *instanceHClass,
5874514f5e3Sopenharmony_ci    JSHClass *prototypeHClass, JSHClass *prototypeOfPrototypeHClass, JSHClass *extraHClass)
5884514f5e3Sopenharmony_ci{
5894514f5e3Sopenharmony_ci    size_t index = BuiltinHClassEntries::GetEntryIndex(type);
5904514f5e3Sopenharmony_ci    auto &entry = glueData_.builtinHClassEntries_.entries[index];
5914514f5e3Sopenharmony_ci    LOG_ECMA(DEBUG) << "JSThread::SetInitialBuiltinHClass: "
5924514f5e3Sopenharmony_ci                    << "Builtin = " << ToString(type)
5934514f5e3Sopenharmony_ci                    << ", builtinHClass = " << builtinHClass
5944514f5e3Sopenharmony_ci                    << ", instanceHClass = " << instanceHClass
5954514f5e3Sopenharmony_ci                    << ", prototypeHClass = " << prototypeHClass
5964514f5e3Sopenharmony_ci                    << ", prototypeOfPrototypeHClass = " << prototypeOfPrototypeHClass
5974514f5e3Sopenharmony_ci                    << ", extraHClass = " << extraHClass;
5984514f5e3Sopenharmony_ci    entry.builtinHClass = builtinHClass;
5994514f5e3Sopenharmony_ci    entry.instanceHClass = instanceHClass;
6004514f5e3Sopenharmony_ci    entry.prototypeHClass = prototypeHClass;
6014514f5e3Sopenharmony_ci    entry.prototypeOfPrototypeHClass = prototypeOfPrototypeHClass;
6024514f5e3Sopenharmony_ci    entry.extraHClass = extraHClass;
6034514f5e3Sopenharmony_ci}
6044514f5e3Sopenharmony_ci
6054514f5e3Sopenharmony_civoid JSThread::SetInitialBuiltinGlobalHClass(
6064514f5e3Sopenharmony_ci    JSHClass *builtinHClass, GlobalIndex globalIndex)
6074514f5e3Sopenharmony_ci{
6084514f5e3Sopenharmony_ci    auto &map = ctorHclassEntries_;
6094514f5e3Sopenharmony_ci    map[builtinHClass] = globalIndex;
6104514f5e3Sopenharmony_ci}
6114514f5e3Sopenharmony_ci
6124514f5e3Sopenharmony_ciJSHClass *JSThread::GetBuiltinHClass(BuiltinTypeId type) const
6134514f5e3Sopenharmony_ci{
6144514f5e3Sopenharmony_ci    size_t index = BuiltinHClassEntries::GetEntryIndex(type);
6154514f5e3Sopenharmony_ci    return glueData_.builtinHClassEntries_.entries[index].builtinHClass;
6164514f5e3Sopenharmony_ci}
6174514f5e3Sopenharmony_ci
6184514f5e3Sopenharmony_ciJSHClass *JSThread::GetBuiltinInstanceHClass(BuiltinTypeId type) const
6194514f5e3Sopenharmony_ci{
6204514f5e3Sopenharmony_ci    size_t index = BuiltinHClassEntries::GetEntryIndex(type);
6214514f5e3Sopenharmony_ci    return glueData_.builtinHClassEntries_.entries[index].instanceHClass;
6224514f5e3Sopenharmony_ci}
6234514f5e3Sopenharmony_ci
6244514f5e3Sopenharmony_ciJSHClass *JSThread::GetBuiltinExtraHClass(BuiltinTypeId type) const
6254514f5e3Sopenharmony_ci{
6264514f5e3Sopenharmony_ci    size_t index = BuiltinHClassEntries::GetEntryIndex(type);
6274514f5e3Sopenharmony_ci    return glueData_.builtinHClassEntries_.entries[index].extraHClass;
6284514f5e3Sopenharmony_ci}
6294514f5e3Sopenharmony_ci
6304514f5e3Sopenharmony_ciJSHClass *JSThread::GetArrayInstanceHClass(ElementsKind kind, bool isPrototype) const
6314514f5e3Sopenharmony_ci{
6324514f5e3Sopenharmony_ci    auto iter = GetArrayHClassIndexMap().find(kind);
6334514f5e3Sopenharmony_ci    ASSERT(iter != GetArrayHClassIndexMap().end());
6344514f5e3Sopenharmony_ci    auto index = isPrototype ? static_cast<size_t>(iter->second.second) : static_cast<size_t>(iter->second.first);
6354514f5e3Sopenharmony_ci    auto exceptArrayHClass = GlobalConstants()->GetGlobalConstantObject(index);
6364514f5e3Sopenharmony_ci    auto exceptRecvHClass = JSHClass::Cast(exceptArrayHClass.GetTaggedObject());
6374514f5e3Sopenharmony_ci    ASSERT(exceptRecvHClass->IsJSArray());
6384514f5e3Sopenharmony_ci    return exceptRecvHClass;
6394514f5e3Sopenharmony_ci}
6404514f5e3Sopenharmony_ci
6414514f5e3Sopenharmony_ciJSHClass *JSThread::GetBuiltinPrototypeHClass(BuiltinTypeId type) const
6424514f5e3Sopenharmony_ci{
6434514f5e3Sopenharmony_ci    size_t index = BuiltinHClassEntries::GetEntryIndex(type);
6444514f5e3Sopenharmony_ci    return glueData_.builtinHClassEntries_.entries[index].prototypeHClass;
6454514f5e3Sopenharmony_ci}
6464514f5e3Sopenharmony_ci
6474514f5e3Sopenharmony_ciJSHClass *JSThread::GetBuiltinPrototypeOfPrototypeHClass(BuiltinTypeId type) const
6484514f5e3Sopenharmony_ci{
6494514f5e3Sopenharmony_ci    size_t index = BuiltinHClassEntries::GetEntryIndex(type);
6504514f5e3Sopenharmony_ci    return glueData_.builtinHClassEntries_.entries[index].prototypeOfPrototypeHClass;
6514514f5e3Sopenharmony_ci}
6524514f5e3Sopenharmony_ci
6534514f5e3Sopenharmony_cisize_t JSThread::GetBuiltinHClassOffset(BuiltinTypeId type, bool isArch32)
6544514f5e3Sopenharmony_ci{
6554514f5e3Sopenharmony_ci    return GetGlueDataOffset() + GlueData::GetBuiltinHClassOffset(type, isArch32);
6564514f5e3Sopenharmony_ci}
6574514f5e3Sopenharmony_ci
6584514f5e3Sopenharmony_cisize_t JSThread::GetBuiltinPrototypeHClassOffset(BuiltinTypeId type, bool isArch32)
6594514f5e3Sopenharmony_ci{
6604514f5e3Sopenharmony_ci    return GetGlueDataOffset() + GlueData::GetBuiltinPrototypeHClassOffset(type, isArch32);
6614514f5e3Sopenharmony_ci}
6624514f5e3Sopenharmony_ci
6634514f5e3Sopenharmony_civoid JSThread::CheckSwitchDebuggerBCStub()
6644514f5e3Sopenharmony_ci{
6654514f5e3Sopenharmony_ci    auto isDebug = GetEcmaVM()->GetJsDebuggerManager()->IsDebugMode();
6664514f5e3Sopenharmony_ci    if (LIKELY(!isDebug)) {
6674514f5e3Sopenharmony_ci        if (glueData_.bcStubEntries_.Get(0) == glueData_.bcStubEntries_.Get(1)) {
6684514f5e3Sopenharmony_ci            for (size_t i = 0; i < BCStubEntries::BC_HANDLER_COUNT; i++) {
6694514f5e3Sopenharmony_ci                auto stubEntry = glueData_.bcDebuggerStubEntries_.Get(i);
6704514f5e3Sopenharmony_ci                auto debuggerStubEbtry = glueData_.bcStubEntries_.Get(i);
6714514f5e3Sopenharmony_ci                glueData_.bcStubEntries_.Set(i, stubEntry);
6724514f5e3Sopenharmony_ci                glueData_.bcDebuggerStubEntries_.Set(i, debuggerStubEbtry);
6734514f5e3Sopenharmony_ci            }
6744514f5e3Sopenharmony_ci        }
6754514f5e3Sopenharmony_ci    } else {
6764514f5e3Sopenharmony_ci        if (glueData_.bcDebuggerStubEntries_.Get(0) == glueData_.bcDebuggerStubEntries_.Get(1)) {
6774514f5e3Sopenharmony_ci            for (size_t i = 0; i < BCStubEntries::BC_HANDLER_COUNT; i++) {
6784514f5e3Sopenharmony_ci                auto stubEntry = glueData_.bcStubEntries_.Get(i);
6794514f5e3Sopenharmony_ci                auto debuggerStubEbtry = glueData_.bcDebuggerStubEntries_.Get(i);
6804514f5e3Sopenharmony_ci                glueData_.bcDebuggerStubEntries_.Set(i, stubEntry);
6814514f5e3Sopenharmony_ci                glueData_.bcStubEntries_.Set(i, debuggerStubEbtry);
6824514f5e3Sopenharmony_ci            }
6834514f5e3Sopenharmony_ci        }
6844514f5e3Sopenharmony_ci    }
6854514f5e3Sopenharmony_ci}
6864514f5e3Sopenharmony_ci
6874514f5e3Sopenharmony_civoid JSThread::CheckOrSwitchPGOStubs()
6884514f5e3Sopenharmony_ci{
6894514f5e3Sopenharmony_ci    bool isSwitch = false;
6904514f5e3Sopenharmony_ci    if (IsPGOProfilerEnable()) {
6914514f5e3Sopenharmony_ci        if (GetBCStubStatus() == BCStubStatus::NORMAL_BC_STUB) {
6924514f5e3Sopenharmony_ci            SetBCStubStatus(BCStubStatus::PROFILE_BC_STUB);
6934514f5e3Sopenharmony_ci            isSwitch = true;
6944514f5e3Sopenharmony_ci        }
6954514f5e3Sopenharmony_ci    } else {
6964514f5e3Sopenharmony_ci        if (GetBCStubStatus() == BCStubStatus::PROFILE_BC_STUB) {
6974514f5e3Sopenharmony_ci            SetBCStubStatus(BCStubStatus::NORMAL_BC_STUB);
6984514f5e3Sopenharmony_ci            isSwitch = true;
6994514f5e3Sopenharmony_ci        }
7004514f5e3Sopenharmony_ci    }
7014514f5e3Sopenharmony_ci    if (isSwitch) {
7024514f5e3Sopenharmony_ci        Address curAddress;
7034514f5e3Sopenharmony_ci#define SWITCH_PGO_STUB_ENTRY(fromName, toName, ...)                                                        \
7044514f5e3Sopenharmony_ci        curAddress = GetBCStubEntry(BytecodeStubCSigns::ID_##fromName);                                     \
7054514f5e3Sopenharmony_ci        SetBCStubEntry(BytecodeStubCSigns::ID_##fromName, GetBCStubEntry(BytecodeStubCSigns::ID_##toName)); \
7064514f5e3Sopenharmony_ci        SetBCStubEntry(BytecodeStubCSigns::ID_##toName, curAddress);
7074514f5e3Sopenharmony_ci        ASM_INTERPRETER_BC_PROFILER_STUB_LIST(SWITCH_PGO_STUB_ENTRY)
7084514f5e3Sopenharmony_ci#undef SWITCH_PGO_STUB_ENTRY
7094514f5e3Sopenharmony_ci    }
7104514f5e3Sopenharmony_ci}
7114514f5e3Sopenharmony_ci
7124514f5e3Sopenharmony_civoid JSThread::SwitchJitProfileStubs(bool isEnablePgo)
7134514f5e3Sopenharmony_ci{
7144514f5e3Sopenharmony_ci    if (isEnablePgo) {
7154514f5e3Sopenharmony_ci        SetPGOProfilerEnable(true);
7164514f5e3Sopenharmony_ci        CheckOrSwitchPGOStubs();
7174514f5e3Sopenharmony_ci        return;
7184514f5e3Sopenharmony_ci    }
7194514f5e3Sopenharmony_ci    bool isSwitch = false;
7204514f5e3Sopenharmony_ci    if (GetBCStubStatus() == BCStubStatus::NORMAL_BC_STUB) {
7214514f5e3Sopenharmony_ci        SetBCStubStatus(BCStubStatus::JIT_PROFILE_BC_STUB);
7224514f5e3Sopenharmony_ci        isSwitch = true;
7234514f5e3Sopenharmony_ci    }
7244514f5e3Sopenharmony_ci    if (isSwitch) {
7254514f5e3Sopenharmony_ci        Address curAddress;
7264514f5e3Sopenharmony_ci#define SWITCH_PGO_STUB_ENTRY(fromName, toName, ...)                                                        \
7274514f5e3Sopenharmony_ci        curAddress = GetBCStubEntry(BytecodeStubCSigns::ID_##fromName);                                     \
7284514f5e3Sopenharmony_ci        SetBCStubEntry(BytecodeStubCSigns::ID_##fromName, GetBCStubEntry(BytecodeStubCSigns::ID_##toName)); \
7294514f5e3Sopenharmony_ci        SetBCStubEntry(BytecodeStubCSigns::ID_##toName, curAddress);
7304514f5e3Sopenharmony_ci        ASM_INTERPRETER_BC_JIT_PROFILER_STUB_LIST(SWITCH_PGO_STUB_ENTRY)
7314514f5e3Sopenharmony_ci#undef SWITCH_PGO_STUB_ENTRY
7324514f5e3Sopenharmony_ci    }
7334514f5e3Sopenharmony_ci}
7344514f5e3Sopenharmony_ci
7354514f5e3Sopenharmony_civoid JSThread::TerminateExecution()
7364514f5e3Sopenharmony_ci{
7374514f5e3Sopenharmony_ci    // set the TERMINATE_ERROR to exception
7384514f5e3Sopenharmony_ci    ObjectFactory *factory = GetEcmaVM()->GetFactory();
7394514f5e3Sopenharmony_ci    JSHandle<JSObject> error = factory->GetJSError(ErrorType::TERMINATION_ERROR,
7404514f5e3Sopenharmony_ci        "Terminate execution!", StackCheck::NO);
7414514f5e3Sopenharmony_ci    SetException(error.GetTaggedValue());
7424514f5e3Sopenharmony_ci}
7434514f5e3Sopenharmony_ci
7444514f5e3Sopenharmony_civoid JSThread::CheckAndPassActiveBarrier()
7454514f5e3Sopenharmony_ci{
7464514f5e3Sopenharmony_ci    ThreadStateAndFlags oldStateAndFlags;
7474514f5e3Sopenharmony_ci    oldStateAndFlags.asNonvolatileInt = glueData_.stateAndFlags_.asInt;
7484514f5e3Sopenharmony_ci    if ((oldStateAndFlags.asNonvolatileStruct.flags & ThreadFlag::ACTIVE_BARRIER) != 0) {
7494514f5e3Sopenharmony_ci        PassSuspendBarrier();
7504514f5e3Sopenharmony_ci    }
7514514f5e3Sopenharmony_ci}
7524514f5e3Sopenharmony_ci
7534514f5e3Sopenharmony_cibool JSThread::PassSuspendBarrier()
7544514f5e3Sopenharmony_ci{
7554514f5e3Sopenharmony_ci    // Use suspendLock_ to avoid data-race between suspend-all-thread and suspended-threads.
7564514f5e3Sopenharmony_ci    LockHolder lock(suspendLock_);
7574514f5e3Sopenharmony_ci    if (suspendBarrier_ != nullptr) {
7584514f5e3Sopenharmony_ci        suspendBarrier_->PassStrongly();
7594514f5e3Sopenharmony_ci        suspendBarrier_ = nullptr;
7604514f5e3Sopenharmony_ci        ClearFlag(ThreadFlag::ACTIVE_BARRIER);
7614514f5e3Sopenharmony_ci        return true;
7624514f5e3Sopenharmony_ci    }
7634514f5e3Sopenharmony_ci    return false;
7644514f5e3Sopenharmony_ci}
7654514f5e3Sopenharmony_ci
7664514f5e3Sopenharmony_cibool JSThread::CheckSafepoint()
7674514f5e3Sopenharmony_ci{
7684514f5e3Sopenharmony_ci    ResetCheckSafePointStatus();
7694514f5e3Sopenharmony_ci
7704514f5e3Sopenharmony_ci    if (HasTerminationRequest()) {
7714514f5e3Sopenharmony_ci        TerminateExecution();
7724514f5e3Sopenharmony_ci        SetVMTerminated(true);
7734514f5e3Sopenharmony_ci        SetTerminationRequest(false);
7744514f5e3Sopenharmony_ci    }
7754514f5e3Sopenharmony_ci
7764514f5e3Sopenharmony_ci    if (HasSuspendRequest()) {
7774514f5e3Sopenharmony_ci        WaitSuspension();
7784514f5e3Sopenharmony_ci    }
7794514f5e3Sopenharmony_ci
7804514f5e3Sopenharmony_ci    // vmThreadControl_ 's thread_ is current JSThread's this.
7814514f5e3Sopenharmony_ci    if (VMNeedSuspension()) {
7824514f5e3Sopenharmony_ci        vmThreadControl_->SuspendVM();
7834514f5e3Sopenharmony_ci    }
7844514f5e3Sopenharmony_ci    if (HasInstallMachineCode()) {
7854514f5e3Sopenharmony_ci        vm_->GetJit()->InstallTasks(this);
7864514f5e3Sopenharmony_ci        SetInstallMachineCode(false);
7874514f5e3Sopenharmony_ci    }
7884514f5e3Sopenharmony_ci
7894514f5e3Sopenharmony_ci#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
7904514f5e3Sopenharmony_ci    if (needProfiling_.load() && !isProfiling_) {
7914514f5e3Sopenharmony_ci        DFXJSNApi::StartCpuProfilerForFile(vm_, profileName_, CpuProfiler::INTERVAL_OF_INNER_START);
7924514f5e3Sopenharmony_ci        SetNeedProfiling(false);
7934514f5e3Sopenharmony_ci    }
7944514f5e3Sopenharmony_ci#endif // ECMASCRIPT_SUPPORT_CPUPROFILER
7954514f5e3Sopenharmony_ci    bool gcTriggered = false;
7964514f5e3Sopenharmony_ci#ifndef NDEBUG
7974514f5e3Sopenharmony_ci    if (vm_->GetJSOptions().EnableForceGC()) {
7984514f5e3Sopenharmony_ci        GetEcmaVM()->CollectGarbage(TriggerGCType::FULL_GC);
7994514f5e3Sopenharmony_ci        gcTriggered = true;
8004514f5e3Sopenharmony_ci    }
8014514f5e3Sopenharmony_ci#endif
8024514f5e3Sopenharmony_ci    auto heap = const_cast<Heap *>(GetEcmaVM()->GetHeap());
8034514f5e3Sopenharmony_ci    // Handle exit app senstive scene
8044514f5e3Sopenharmony_ci    heap->HandleExitHighSensitiveEvent();
8054514f5e3Sopenharmony_ci
8064514f5e3Sopenharmony_ci    // After concurrent mark finish, should trigger gc here to avoid create much floating garbage
8074514f5e3Sopenharmony_ci    // except in serialize or high sensitive event
8084514f5e3Sopenharmony_ci    if (IsMarkFinished() && heap->GetConcurrentMarker()->IsTriggeredConcurrentMark()
8094514f5e3Sopenharmony_ci        && !heap->GetOnSerializeEvent() && !heap->InSensitiveStatus()) {
8104514f5e3Sopenharmony_ci        heap->SetCanThrowOOMError(false);
8114514f5e3Sopenharmony_ci        heap->GetConcurrentMarker()->HandleMarkingFinished();
8124514f5e3Sopenharmony_ci        heap->SetCanThrowOOMError(true);
8134514f5e3Sopenharmony_ci        gcTriggered = true;
8144514f5e3Sopenharmony_ci    }
8154514f5e3Sopenharmony_ci    return gcTriggered;
8164514f5e3Sopenharmony_ci}
8174514f5e3Sopenharmony_ci
8184514f5e3Sopenharmony_civoid JSThread::CheckJSTaggedType(JSTaggedType value) const
8194514f5e3Sopenharmony_ci{
8204514f5e3Sopenharmony_ci    if (JSTaggedValue(value).IsHeapObject() &&
8214514f5e3Sopenharmony_ci        !GetEcmaVM()->GetHeap()->IsAlive(reinterpret_cast<TaggedObject *>(value))) {
8224514f5e3Sopenharmony_ci        LOG_FULL(FATAL) << "value:" << value << " is invalid!";
8234514f5e3Sopenharmony_ci    }
8244514f5e3Sopenharmony_ci}
8254514f5e3Sopenharmony_ci
8264514f5e3Sopenharmony_cibool JSThread::CpuProfilerCheckJSTaggedType(JSTaggedType value) const
8274514f5e3Sopenharmony_ci{
8284514f5e3Sopenharmony_ci    if (JSTaggedValue(value).IsHeapObject() &&
8294514f5e3Sopenharmony_ci        !GetEcmaVM()->GetHeap()->IsAlive(reinterpret_cast<TaggedObject *>(value))) {
8304514f5e3Sopenharmony_ci        return false;
8314514f5e3Sopenharmony_ci    }
8324514f5e3Sopenharmony_ci    return true;
8334514f5e3Sopenharmony_ci}
8344514f5e3Sopenharmony_ci
8354514f5e3Sopenharmony_ci// static
8364514f5e3Sopenharmony_cisize_t JSThread::GetAsmStackLimit()
8374514f5e3Sopenharmony_ci{
8384514f5e3Sopenharmony_ci#if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS) && !defined(PANDA_TARGET_IOS)
8394514f5e3Sopenharmony_ci    // js stack limit
8404514f5e3Sopenharmony_ci    size_t result = GetCurrentStackPosition() - EcmaParamConfiguration::GetDefalutStackSize();
8414514f5e3Sopenharmony_ci    int ret = -1;
8424514f5e3Sopenharmony_ci    void *stackAddr = nullptr;
8434514f5e3Sopenharmony_ci    size_t size = 0;
8444514f5e3Sopenharmony_ci#if defined(ENABLE_FFRT_INTERFACES)
8454514f5e3Sopenharmony_ci    if (!ffrt_get_current_coroutine_stack(&stackAddr, &size)) {
8464514f5e3Sopenharmony_ci        pthread_attr_t attr;
8474514f5e3Sopenharmony_ci        ret = pthread_getattr_np(pthread_self(), &attr);
8484514f5e3Sopenharmony_ci        if (ret != 0) {
8494514f5e3Sopenharmony_ci            LOG_ECMA(ERROR) << "Get current thread attr failed";
8504514f5e3Sopenharmony_ci            return result;
8514514f5e3Sopenharmony_ci        }
8524514f5e3Sopenharmony_ci        ret = pthread_attr_getstack(&attr, &stackAddr, &size);
8534514f5e3Sopenharmony_ci        if (pthread_attr_destroy(&attr) != 0) {
8544514f5e3Sopenharmony_ci            LOG_ECMA(ERROR) << "Destroy current thread attr failed";
8554514f5e3Sopenharmony_ci        }
8564514f5e3Sopenharmony_ci        if (ret != 0) {
8574514f5e3Sopenharmony_ci            LOG_ECMA(ERROR) << "Get current thread stack size failed";
8584514f5e3Sopenharmony_ci            return result;
8594514f5e3Sopenharmony_ci        }
8604514f5e3Sopenharmony_ci    }
8614514f5e3Sopenharmony_ci#else
8624514f5e3Sopenharmony_ci    pthread_attr_t attr;
8634514f5e3Sopenharmony_ci    ret = pthread_getattr_np(pthread_self(), &attr);
8644514f5e3Sopenharmony_ci    if (ret != 0) {
8654514f5e3Sopenharmony_ci        LOG_ECMA(ERROR) << "Get current thread attr failed";
8664514f5e3Sopenharmony_ci        return result;
8674514f5e3Sopenharmony_ci    }
8684514f5e3Sopenharmony_ci    ret = pthread_attr_getstack(&attr, &stackAddr, &size);
8694514f5e3Sopenharmony_ci    if (pthread_attr_destroy(&attr) != 0) {
8704514f5e3Sopenharmony_ci        LOG_ECMA(ERROR) << "Destroy current thread attr failed";
8714514f5e3Sopenharmony_ci    }
8724514f5e3Sopenharmony_ci    if (ret != 0) {
8734514f5e3Sopenharmony_ci        LOG_ECMA(ERROR) << "Get current thread stack size failed";
8744514f5e3Sopenharmony_ci        return result;
8754514f5e3Sopenharmony_ci    }
8764514f5e3Sopenharmony_ci#endif
8774514f5e3Sopenharmony_ci
8784514f5e3Sopenharmony_ci    bool isMainThread = IsMainThread();
8794514f5e3Sopenharmony_ci    uintptr_t threadStackLimit = reinterpret_cast<uintptr_t>(stackAddr);
8804514f5e3Sopenharmony_ci    uintptr_t threadStackStart = threadStackLimit + size;
8814514f5e3Sopenharmony_ci    if (isMainThread) {
8824514f5e3Sopenharmony_ci        struct rlimit rl;
8834514f5e3Sopenharmony_ci        ret = getrlimit(RLIMIT_STACK, &rl);
8844514f5e3Sopenharmony_ci        if (ret != 0) {
8854514f5e3Sopenharmony_ci            LOG_ECMA(ERROR) << "Get current thread stack size failed";
8864514f5e3Sopenharmony_ci            return result;
8874514f5e3Sopenharmony_ci        }
8884514f5e3Sopenharmony_ci        if (rl.rlim_cur > DEFAULT_MAX_SYSTEM_STACK_SIZE) {
8894514f5e3Sopenharmony_ci            LOG_ECMA(ERROR) << "Get current thread stack size exceed " << DEFAULT_MAX_SYSTEM_STACK_SIZE
8904514f5e3Sopenharmony_ci                            << " : " << rl.rlim_cur;
8914514f5e3Sopenharmony_ci            return result;
8924514f5e3Sopenharmony_ci        }
8934514f5e3Sopenharmony_ci        threadStackLimit = threadStackStart - rl.rlim_cur;
8944514f5e3Sopenharmony_ci    }
8954514f5e3Sopenharmony_ci
8964514f5e3Sopenharmony_ci    if (result < threadStackLimit) {
8974514f5e3Sopenharmony_ci        result = threadStackLimit;
8984514f5e3Sopenharmony_ci    }
8994514f5e3Sopenharmony_ci
9004514f5e3Sopenharmony_ci    LOG_INTERPRETER(DEBUG) << "Current thread stack start: " << reinterpret_cast<void *>(threadStackStart);
9014514f5e3Sopenharmony_ci    LOG_INTERPRETER(DEBUG) << "Used stack before js stack start: "
9024514f5e3Sopenharmony_ci                           << reinterpret_cast<void *>(threadStackStart - GetCurrentStackPosition());
9034514f5e3Sopenharmony_ci    LOG_INTERPRETER(DEBUG) << "Current thread asm stack limit: " << reinterpret_cast<void *>(result);
9044514f5e3Sopenharmony_ci
9054514f5e3Sopenharmony_ci    // To avoid too much times of stack overflow checking, we only check stack overflow before push vregs or
9064514f5e3Sopenharmony_ci    // parameters of variable length. So we need a reserved size of stack to make sure stack won't be overflowed
9074514f5e3Sopenharmony_ci    // when push other data.
9084514f5e3Sopenharmony_ci    result += EcmaParamConfiguration::GetDefaultReservedStackSize();
9094514f5e3Sopenharmony_ci    if (threadStackStart <= result) {
9104514f5e3Sopenharmony_ci        LOG_FULL(FATAL) << "Too small stackSize to run jsvm";
9114514f5e3Sopenharmony_ci    }
9124514f5e3Sopenharmony_ci    return result;
9134514f5e3Sopenharmony_ci#else
9144514f5e3Sopenharmony_ci    return 0;
9154514f5e3Sopenharmony_ci#endif
9164514f5e3Sopenharmony_ci}
9174514f5e3Sopenharmony_ci
9184514f5e3Sopenharmony_cibool JSThread::IsLegalAsmSp(uintptr_t sp) const
9194514f5e3Sopenharmony_ci{
9204514f5e3Sopenharmony_ci    uint64_t bottom = GetStackLimit() - EcmaParamConfiguration::GetDefaultReservedStackSize();
9214514f5e3Sopenharmony_ci    uint64_t top = GetStackStart() + EcmaParamConfiguration::GetAllowedUpperStackDiff();
9224514f5e3Sopenharmony_ci    return (bottom <= sp && sp <= top);
9234514f5e3Sopenharmony_ci}
9244514f5e3Sopenharmony_ci
9254514f5e3Sopenharmony_cibool JSThread::IsLegalThreadSp(uintptr_t sp) const
9264514f5e3Sopenharmony_ci{
9274514f5e3Sopenharmony_ci    uintptr_t bottom = reinterpret_cast<uintptr_t>(glueData_.frameBase_);
9284514f5e3Sopenharmony_ci    size_t maxStackSize = vm_->GetEcmaParamConfiguration().GetMaxStackSize();
9294514f5e3Sopenharmony_ci    uintptr_t top = bottom + maxStackSize;
9304514f5e3Sopenharmony_ci    return (bottom <= sp && sp <= top);
9314514f5e3Sopenharmony_ci}
9324514f5e3Sopenharmony_ci
9334514f5e3Sopenharmony_cibool JSThread::IsLegalSp(uintptr_t sp) const
9344514f5e3Sopenharmony_ci{
9354514f5e3Sopenharmony_ci    return IsLegalAsmSp(sp) || IsLegalThreadSp(sp);
9364514f5e3Sopenharmony_ci}
9374514f5e3Sopenharmony_ci
9384514f5e3Sopenharmony_cibool JSThread::IsMainThread()
9394514f5e3Sopenharmony_ci{
9404514f5e3Sopenharmony_ci#if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS) && !defined(PANDA_TARGET_IOS)
9414514f5e3Sopenharmony_ci    return getpid() == syscall(SYS_gettid);
9424514f5e3Sopenharmony_ci#else
9434514f5e3Sopenharmony_ci    return true;
9444514f5e3Sopenharmony_ci#endif
9454514f5e3Sopenharmony_ci}
9464514f5e3Sopenharmony_ci
9474514f5e3Sopenharmony_civoid JSThread::PushContext(EcmaContext *context)
9484514f5e3Sopenharmony_ci{
9494514f5e3Sopenharmony_ci    const_cast<Heap *>(vm_->GetHeap())->WaitAllTasksFinished();
9504514f5e3Sopenharmony_ci    contexts_.emplace_back(context);
9514514f5e3Sopenharmony_ci
9524514f5e3Sopenharmony_ci    if (!glueData_.currentContext_) {
9534514f5e3Sopenharmony_ci        // The first context in ecma vm.
9544514f5e3Sopenharmony_ci        glueData_.currentContext_ = context;
9554514f5e3Sopenharmony_ci        context->SetFramePointers(const_cast<JSTaggedType *>(GetCurrentSPFrame()),
9564514f5e3Sopenharmony_ci            const_cast<JSTaggedType *>(GetLastLeaveFrame()),
9574514f5e3Sopenharmony_ci            const_cast<JSTaggedType *>(GetLastFp()));
9584514f5e3Sopenharmony_ci        context->SetFrameBase(glueData_.frameBase_);
9594514f5e3Sopenharmony_ci        context->SetStackLimit(glueData_.stackLimit_);
9604514f5e3Sopenharmony_ci        context->SetStackStart(glueData_.stackStart_);
9614514f5e3Sopenharmony_ci    } else {
9624514f5e3Sopenharmony_ci        // algin with 16
9634514f5e3Sopenharmony_ci        size_t maxStackSize = vm_->GetEcmaParamConfiguration().GetMaxStackSize();
9644514f5e3Sopenharmony_ci        context->SetFrameBase(static_cast<JSTaggedType *>(
9654514f5e3Sopenharmony_ci            vm_->GetNativeAreaAllocator()->Allocate(sizeof(JSTaggedType) * maxStackSize)));
9664514f5e3Sopenharmony_ci        context->SetFramePointers(context->GetFrameBase() + maxStackSize, nullptr, nullptr);
9674514f5e3Sopenharmony_ci        context->SetStackLimit(GetAsmStackLimit());
9684514f5e3Sopenharmony_ci        context->SetStackStart(GetCurrentStackPosition());
9694514f5e3Sopenharmony_ci        EcmaInterpreter::InitStackFrame(context);
9704514f5e3Sopenharmony_ci    }
9714514f5e3Sopenharmony_ci}
9724514f5e3Sopenharmony_ci
9734514f5e3Sopenharmony_civoid JSThread::PopContext()
9744514f5e3Sopenharmony_ci{
9754514f5e3Sopenharmony_ci    contexts_.pop_back();
9764514f5e3Sopenharmony_ci    glueData_.currentContext_ = contexts_.back();
9774514f5e3Sopenharmony_ci}
9784514f5e3Sopenharmony_ci
9794514f5e3Sopenharmony_civoid JSThread::SwitchCurrentContext(EcmaContext *currentContext, bool isInIterate)
9804514f5e3Sopenharmony_ci{
9814514f5e3Sopenharmony_ci    ASSERT(std::count(contexts_.begin(), contexts_.end(), currentContext));
9824514f5e3Sopenharmony_ci
9834514f5e3Sopenharmony_ci    glueData_.currentContext_->SetFramePointers(const_cast<JSTaggedType *>(GetCurrentSPFrame()),
9844514f5e3Sopenharmony_ci        const_cast<JSTaggedType *>(GetLastLeaveFrame()),
9854514f5e3Sopenharmony_ci        const_cast<JSTaggedType *>(GetLastFp()));
9864514f5e3Sopenharmony_ci    glueData_.currentContext_->SetFrameBase(glueData_.frameBase_);
9874514f5e3Sopenharmony_ci    glueData_.currentContext_->SetStackLimit(GetStackLimit());
9884514f5e3Sopenharmony_ci    glueData_.currentContext_->SetStackStart(GetStackStart());
9894514f5e3Sopenharmony_ci    glueData_.currentContext_->SetGlobalEnv(GetGlueGlobalEnv());
9904514f5e3Sopenharmony_ci    // When the glueData_.currentContext_ is not fully initialized,glueData_.globalObject_ will be hole.
9914514f5e3Sopenharmony_ci    // Assigning hole to JSGlobalObject could cause a mistake at builtins initalization.
9924514f5e3Sopenharmony_ci    if (!glueData_.globalObject_.IsHole()) {
9934514f5e3Sopenharmony_ci        glueData_.currentContext_->GetGlobalEnv()->SetJSGlobalObject(this, glueData_.globalObject_);
9944514f5e3Sopenharmony_ci    }
9954514f5e3Sopenharmony_ci
9964514f5e3Sopenharmony_ci    SetCurrentSPFrame(currentContext->GetCurrentFrame());
9974514f5e3Sopenharmony_ci    SetLastLeaveFrame(currentContext->GetLeaveFrame());
9984514f5e3Sopenharmony_ci    SetLastFp(currentContext->GetLastFp());
9994514f5e3Sopenharmony_ci    glueData_.frameBase_ = currentContext->GetFrameBase();
10004514f5e3Sopenharmony_ci    glueData_.stackLimit_ = currentContext->GetStackLimit();
10014514f5e3Sopenharmony_ci    glueData_.stackStart_ = currentContext->GetStackStart();
10024514f5e3Sopenharmony_ci    if (!currentContext->GlobalEnvIsHole()) {
10034514f5e3Sopenharmony_ci        SetGlueGlobalEnv(*(currentContext->GetGlobalEnv()));
10044514f5e3Sopenharmony_ci        /**
10054514f5e3Sopenharmony_ci         * GlobalObject has two copies, one in GlueData and one in Context.GlobalEnv, when switch context, will save
10064514f5e3Sopenharmony_ci         * GlobalObject in GlueData to CurrentContext.GlobalEnv(is this nessary?), and then switch to new context,
10074514f5e3Sopenharmony_ci         * save the GlobalObject in NewContext.GlobalEnv to GlueData.
10084514f5e3Sopenharmony_ci         * The initial value of GlobalObject in Context.GlobalEnv is Undefined, but in GlueData is Hole,
10094514f5e3Sopenharmony_ci         * so if two SharedGC happened during the builtins initalization like this, maybe will cause incorrect scene:
10104514f5e3Sopenharmony_ci         *
10114514f5e3Sopenharmony_ci         * Default:
10124514f5e3Sopenharmony_ci         * Slot for GlobalObject:              Context.GlobalEnv            GlueData
10134514f5e3Sopenharmony_ci         * value:                                 Undefined                   Hole
10144514f5e3Sopenharmony_ci         *
10154514f5e3Sopenharmony_ci         * First SharedGC(JSThread::SwitchCurrentContext), Set GlobalObject from Context.GlobalEnv to GlueData:
10164514f5e3Sopenharmony_ci         * Slot for GlobalObject:              Context.GlobalEnv            GlueData
10174514f5e3Sopenharmony_ci         * value:                                 Undefined                 Undefined
10184514f5e3Sopenharmony_ci         *
10194514f5e3Sopenharmony_ci         * Builtins Initialize, Create GlobalObject and Set to Context.GlobalEnv:
10204514f5e3Sopenharmony_ci         * Slot for GlobalObject:              Context.GlobalEnv            GlueData
10214514f5e3Sopenharmony_ci         * value:                                    Obj                    Undefined
10224514f5e3Sopenharmony_ci         *
10234514f5e3Sopenharmony_ci         * Second SharedGC(JSThread::SwitchCurrentContext), Set GlobalObject from GlueData to Context.GlobalEnv:
10244514f5e3Sopenharmony_ci         * Slot for GlobalObject:              Context.GlobalEnv            GlueData
10254514f5e3Sopenharmony_ci         * value:                                 Undefined                 Undefined
10264514f5e3Sopenharmony_ci         *
10274514f5e3Sopenharmony_ci         * So when copy values between Context.GlobalEnv and GlueData, need to check if the value is Hole in GlueData,
10284514f5e3Sopenharmony_ci         * and if is Undefined in Context.GlobalEnv, because the initial value is different.
10294514f5e3Sopenharmony_ci        */
10304514f5e3Sopenharmony_ci        if (!currentContext->GetGlobalEnv()->GetGlobalObject().IsUndefined()) {
10314514f5e3Sopenharmony_ci            SetGlobalObject(currentContext->GetGlobalEnv()->GetGlobalObject());
10324514f5e3Sopenharmony_ci        }
10334514f5e3Sopenharmony_ci    }
10344514f5e3Sopenharmony_ci    if (!isInIterate) {
10354514f5e3Sopenharmony_ci        // If isInIterate is true, it means it is in GC iterate and global variables are no need to change.
10364514f5e3Sopenharmony_ci        glueData_.globalConst_ = const_cast<GlobalEnvConstants *>(currentContext->GlobalConstants());
10374514f5e3Sopenharmony_ci    }
10384514f5e3Sopenharmony_ci
10394514f5e3Sopenharmony_ci    glueData_.currentContext_ = currentContext;
10404514f5e3Sopenharmony_ci}
10414514f5e3Sopenharmony_ci
10424514f5e3Sopenharmony_cibool JSThread::EraseContext(EcmaContext *context)
10434514f5e3Sopenharmony_ci{
10444514f5e3Sopenharmony_ci    const_cast<Heap *>(vm_->GetHeap())->WaitAllTasksFinished();
10454514f5e3Sopenharmony_ci    bool isCurrentContext = false;
10464514f5e3Sopenharmony_ci    auto iter = std::find(contexts_.begin(), contexts_.end(), context);
10474514f5e3Sopenharmony_ci    if (*iter == context) {
10484514f5e3Sopenharmony_ci        if (glueData_.currentContext_ == context) {
10494514f5e3Sopenharmony_ci            isCurrentContext = true;
10504514f5e3Sopenharmony_ci        }
10514514f5e3Sopenharmony_ci        contexts_.erase(iter);
10524514f5e3Sopenharmony_ci        if (isCurrentContext) {
10534514f5e3Sopenharmony_ci            SwitchCurrentContext(contexts_.back());
10544514f5e3Sopenharmony_ci        }
10554514f5e3Sopenharmony_ci        return true;
10564514f5e3Sopenharmony_ci    }
10574514f5e3Sopenharmony_ci    return false;
10584514f5e3Sopenharmony_ci}
10594514f5e3Sopenharmony_ci
10604514f5e3Sopenharmony_civoid JSThread::ClearContextCachedConstantPool()
10614514f5e3Sopenharmony_ci{
10624514f5e3Sopenharmony_ci    for (EcmaContext *context : contexts_) {
10634514f5e3Sopenharmony_ci        context->ClearCachedConstantPool();
10644514f5e3Sopenharmony_ci    }
10654514f5e3Sopenharmony_ci}
10664514f5e3Sopenharmony_ci
10674514f5e3Sopenharmony_ciPropertiesCache *JSThread::GetPropertiesCache() const
10684514f5e3Sopenharmony_ci{
10694514f5e3Sopenharmony_ci    return glueData_.currentContext_->GetPropertiesCache();
10704514f5e3Sopenharmony_ci}
10714514f5e3Sopenharmony_ci
10724514f5e3Sopenharmony_ciconst GlobalEnvConstants *JSThread::GetFirstGlobalConst() const
10734514f5e3Sopenharmony_ci{
10744514f5e3Sopenharmony_ci    return contexts_[0]->GlobalConstants();
10754514f5e3Sopenharmony_ci}
10764514f5e3Sopenharmony_ci
10774514f5e3Sopenharmony_cibool JSThread::IsAllContextsInitialized() const
10784514f5e3Sopenharmony_ci{
10794514f5e3Sopenharmony_ci    return contexts_.back()->IsInitialized();
10804514f5e3Sopenharmony_ci}
10814514f5e3Sopenharmony_ci
10824514f5e3Sopenharmony_cibool JSThread::IsReadyToUpdateDetector() const
10834514f5e3Sopenharmony_ci{
10844514f5e3Sopenharmony_ci    return !GetEnableLazyBuiltins() && IsAllContextsInitialized();
10854514f5e3Sopenharmony_ci}
10864514f5e3Sopenharmony_ci
10874514f5e3Sopenharmony_ciArea *JSThread::GetOrCreateRegExpCache()
10884514f5e3Sopenharmony_ci{
10894514f5e3Sopenharmony_ci    if (regExpCache_ == nullptr) {
10904514f5e3Sopenharmony_ci        regExpCache_ = nativeAreaAllocator_->AllocateArea(MAX_REGEXP_CACHE_SIZE);
10914514f5e3Sopenharmony_ci    }
10924514f5e3Sopenharmony_ci    return regExpCache_;
10934514f5e3Sopenharmony_ci}
10944514f5e3Sopenharmony_ci
10954514f5e3Sopenharmony_civoid JSThread::InitializeBuiltinObject(const std::string& key)
10964514f5e3Sopenharmony_ci{
10974514f5e3Sopenharmony_ci    BuiltinIndex& builtins = BuiltinIndex::GetInstance();
10984514f5e3Sopenharmony_ci    auto index = builtins.GetBuiltinIndex(key);
10994514f5e3Sopenharmony_ci    ASSERT(index != BuiltinIndex::NOT_FOUND);
11004514f5e3Sopenharmony_ci    /*
11014514f5e3Sopenharmony_ci        If using `auto globalObject = GetEcmaVM()->GetGlobalEnv()->GetGlobalObject()` here,
11024514f5e3Sopenharmony_ci        it will cause incorrect result in multi-context environment. For example:
11034514f5e3Sopenharmony_ci
11044514f5e3Sopenharmony_ci        ```ts
11054514f5e3Sopenharmony_ci        let obj = {};
11064514f5e3Sopenharmony_ci        print(obj instanceof Object); // instead of true, will print false
11074514f5e3Sopenharmony_ci        ```
11084514f5e3Sopenharmony_ci    */
11094514f5e3Sopenharmony_ci    auto globalObject = contexts_.back()->GetGlobalEnv()->GetGlobalObject();
11104514f5e3Sopenharmony_ci    auto jsObject = JSHandle<JSObject>(this, globalObject);
11114514f5e3Sopenharmony_ci    auto box = jsObject->GetGlobalPropertyBox(this, key);
11124514f5e3Sopenharmony_ci    if (box == nullptr) {
11134514f5e3Sopenharmony_ci        return;
11144514f5e3Sopenharmony_ci    }
11154514f5e3Sopenharmony_ci    auto& entry = glueData_.builtinEntries_.builtin_[index];
11164514f5e3Sopenharmony_ci    entry.box_ = JSTaggedValue::Cast(box);
11174514f5e3Sopenharmony_ci    auto builtin = JSHandle<JSObject>(this, box->GetValue());
11184514f5e3Sopenharmony_ci    auto hclass = builtin->GetJSHClass();
11194514f5e3Sopenharmony_ci    entry.hClass_ = JSTaggedValue::Cast(hclass);
11204514f5e3Sopenharmony_ci}
11214514f5e3Sopenharmony_ci
11224514f5e3Sopenharmony_civoid JSThread::InitializeBuiltinObject()
11234514f5e3Sopenharmony_ci{
11244514f5e3Sopenharmony_ci    BuiltinIndex& builtins = BuiltinIndex::GetInstance();
11254514f5e3Sopenharmony_ci    for (auto key: builtins.GetBuiltinKeys()) {
11264514f5e3Sopenharmony_ci        InitializeBuiltinObject(key);
11274514f5e3Sopenharmony_ci    }
11284514f5e3Sopenharmony_ci}
11294514f5e3Sopenharmony_ci
11304514f5e3Sopenharmony_cibool JSThread::IsPropertyCacheCleared() const
11314514f5e3Sopenharmony_ci{
11324514f5e3Sopenharmony_ci    for (EcmaContext *context : contexts_) {
11334514f5e3Sopenharmony_ci        if (!context->GetPropertiesCache()->IsCleared()) {
11344514f5e3Sopenharmony_ci            return false;
11354514f5e3Sopenharmony_ci        }
11364514f5e3Sopenharmony_ci    }
11374514f5e3Sopenharmony_ci    return true;
11384514f5e3Sopenharmony_ci}
11394514f5e3Sopenharmony_ci
11404514f5e3Sopenharmony_civoid JSThread::UpdateState(ThreadState newState)
11414514f5e3Sopenharmony_ci{
11424514f5e3Sopenharmony_ci    ThreadState oldState = GetState();
11434514f5e3Sopenharmony_ci    if (oldState == ThreadState::RUNNING && newState != ThreadState::RUNNING) {
11444514f5e3Sopenharmony_ci        TransferFromRunningToSuspended(newState);
11454514f5e3Sopenharmony_ci    } else if (oldState != ThreadState::RUNNING && newState == ThreadState::RUNNING) {
11464514f5e3Sopenharmony_ci        TransferToRunning();
11474514f5e3Sopenharmony_ci    } else {
11484514f5e3Sopenharmony_ci        // Here can be some extra checks...
11494514f5e3Sopenharmony_ci        StoreState(newState);
11504514f5e3Sopenharmony_ci    }
11514514f5e3Sopenharmony_ci}
11524514f5e3Sopenharmony_ci
11534514f5e3Sopenharmony_civoid JSThread::SuspendThread(bool internalSuspend, SuspendBarrier* barrier)
11544514f5e3Sopenharmony_ci{
11554514f5e3Sopenharmony_ci    LockHolder lock(suspendLock_);
11564514f5e3Sopenharmony_ci    if (!internalSuspend) {
11574514f5e3Sopenharmony_ci        // do smth here if we want to combine internal and external suspension
11584514f5e3Sopenharmony_ci    }
11594514f5e3Sopenharmony_ci
11604514f5e3Sopenharmony_ci    uint32_t old_count = suspendCount_++;
11614514f5e3Sopenharmony_ci    if (old_count == 0) {
11624514f5e3Sopenharmony_ci        SetFlag(ThreadFlag::SUSPEND_REQUEST);
11634514f5e3Sopenharmony_ci        SetCheckSafePointStatus();
11644514f5e3Sopenharmony_ci    }
11654514f5e3Sopenharmony_ci
11664514f5e3Sopenharmony_ci    if (barrier != nullptr) {
11674514f5e3Sopenharmony_ci        ASSERT(suspendBarrier_ == nullptr);
11684514f5e3Sopenharmony_ci        suspendBarrier_ = barrier;
11694514f5e3Sopenharmony_ci        SetFlag(ThreadFlag::ACTIVE_BARRIER);
11704514f5e3Sopenharmony_ci        SetCheckSafePointStatus();
11714514f5e3Sopenharmony_ci    }
11724514f5e3Sopenharmony_ci}
11734514f5e3Sopenharmony_ci
11744514f5e3Sopenharmony_civoid JSThread::ResumeThread(bool internalSuspend)
11754514f5e3Sopenharmony_ci{
11764514f5e3Sopenharmony_ci    LockHolder lock(suspendLock_);
11774514f5e3Sopenharmony_ci    if (!internalSuspend) {
11784514f5e3Sopenharmony_ci        // do smth here if we want to combine internal and external suspension
11794514f5e3Sopenharmony_ci    }
11804514f5e3Sopenharmony_ci    if (suspendCount_ > 0) {
11814514f5e3Sopenharmony_ci        suspendCount_--;
11824514f5e3Sopenharmony_ci        if (suspendCount_ == 0) {
11834514f5e3Sopenharmony_ci            ClearFlag(ThreadFlag::SUSPEND_REQUEST);
11844514f5e3Sopenharmony_ci            ResetCheckSafePointStatus();
11854514f5e3Sopenharmony_ci        }
11864514f5e3Sopenharmony_ci    }
11874514f5e3Sopenharmony_ci    suspendCondVar_.Signal();
11884514f5e3Sopenharmony_ci}
11894514f5e3Sopenharmony_ci
11904514f5e3Sopenharmony_civoid JSThread::WaitSuspension()
11914514f5e3Sopenharmony_ci{
11924514f5e3Sopenharmony_ci    constexpr int TIMEOUT = 100;
11934514f5e3Sopenharmony_ci    ThreadState oldState = GetState();
11944514f5e3Sopenharmony_ci    UpdateState(ThreadState::IS_SUSPENDED);
11954514f5e3Sopenharmony_ci    {
11964514f5e3Sopenharmony_ci        ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SuspendTime::WaitSuspension");
11974514f5e3Sopenharmony_ci        LockHolder lock(suspendLock_);
11984514f5e3Sopenharmony_ci        while (suspendCount_ > 0) {
11994514f5e3Sopenharmony_ci            suspendCondVar_.TimedWait(&suspendLock_, TIMEOUT);
12004514f5e3Sopenharmony_ci            // we need to do smth if Runtime is terminating at this point
12014514f5e3Sopenharmony_ci        }
12024514f5e3Sopenharmony_ci        ASSERT(!HasSuspendRequest());
12034514f5e3Sopenharmony_ci    }
12044514f5e3Sopenharmony_ci    UpdateState(oldState);
12054514f5e3Sopenharmony_ci}
12064514f5e3Sopenharmony_ci
12074514f5e3Sopenharmony_civoid JSThread::ManagedCodeBegin()
12084514f5e3Sopenharmony_ci{
12094514f5e3Sopenharmony_ci    ASSERT(!IsInManagedState());
12104514f5e3Sopenharmony_ci    UpdateState(ThreadState::RUNNING);
12114514f5e3Sopenharmony_ci}
12124514f5e3Sopenharmony_ci
12134514f5e3Sopenharmony_civoid JSThread::ManagedCodeEnd()
12144514f5e3Sopenharmony_ci{
12154514f5e3Sopenharmony_ci    ASSERT(IsInManagedState());
12164514f5e3Sopenharmony_ci    UpdateState(ThreadState::NATIVE);
12174514f5e3Sopenharmony_ci}
12184514f5e3Sopenharmony_ci
12194514f5e3Sopenharmony_civoid JSThread::TransferFromRunningToSuspended(ThreadState newState)
12204514f5e3Sopenharmony_ci{
12214514f5e3Sopenharmony_ci    ASSERT(currentThread == this);
12224514f5e3Sopenharmony_ci    StoreSuspendedState(newState);
12234514f5e3Sopenharmony_ci    CheckAndPassActiveBarrier();
12244514f5e3Sopenharmony_ci}
12254514f5e3Sopenharmony_ci
12264514f5e3Sopenharmony_civoid JSThread::TransferToRunning()
12274514f5e3Sopenharmony_ci{
12284514f5e3Sopenharmony_ci    ASSERT(!IsDaemonThread());
12294514f5e3Sopenharmony_ci    ASSERT(currentThread == this);
12304514f5e3Sopenharmony_ci    StoreRunningState(ThreadState::RUNNING);
12314514f5e3Sopenharmony_ci    // Invoke free weak global callback when thread switch to running
12324514f5e3Sopenharmony_ci    if (!weakNodeFreeGlobalCallbacks_.empty()) {
12334514f5e3Sopenharmony_ci        InvokeWeakNodeFreeGlobalCallBack();
12344514f5e3Sopenharmony_ci    }
12354514f5e3Sopenharmony_ci    if (fullMarkRequest_) {
12364514f5e3Sopenharmony_ci        fullMarkRequest_ = const_cast<Heap*>(vm_->GetHeap())->TryTriggerFullMarkBySharedLimit();
12374514f5e3Sopenharmony_ci    }
12384514f5e3Sopenharmony_ci}
12394514f5e3Sopenharmony_ci
12404514f5e3Sopenharmony_civoid JSThread::TransferDaemonThreadToRunning()
12414514f5e3Sopenharmony_ci{
12424514f5e3Sopenharmony_ci    ASSERT(IsDaemonThread());
12434514f5e3Sopenharmony_ci    ASSERT(currentThread == this);
12444514f5e3Sopenharmony_ci    StoreRunningState(ThreadState::RUNNING);
12454514f5e3Sopenharmony_ci}
12464514f5e3Sopenharmony_ci
12474514f5e3Sopenharmony_ciinline void JSThread::StoreState(ThreadState newState)
12484514f5e3Sopenharmony_ci{
12494514f5e3Sopenharmony_ci    while (true) {
12504514f5e3Sopenharmony_ci        ThreadStateAndFlags oldStateAndFlags;
12514514f5e3Sopenharmony_ci        oldStateAndFlags.asNonvolatileInt = glueData_.stateAndFlags_.asInt;
12524514f5e3Sopenharmony_ci
12534514f5e3Sopenharmony_ci        ThreadStateAndFlags newStateAndFlags;
12544514f5e3Sopenharmony_ci        newStateAndFlags.asNonvolatileStruct.flags = oldStateAndFlags.asNonvolatileStruct.flags;
12554514f5e3Sopenharmony_ci        newStateAndFlags.asNonvolatileStruct.state = newState;
12564514f5e3Sopenharmony_ci
12574514f5e3Sopenharmony_ci        bool done = glueData_.stateAndFlags_.asAtomicInt.compare_exchange_weak(oldStateAndFlags.asNonvolatileInt,
12584514f5e3Sopenharmony_ci                                                                               newStateAndFlags.asNonvolatileInt,
12594514f5e3Sopenharmony_ci                                                                               std::memory_order_release);
12604514f5e3Sopenharmony_ci        if (LIKELY(done)) {
12614514f5e3Sopenharmony_ci            break;
12624514f5e3Sopenharmony_ci        }
12634514f5e3Sopenharmony_ci    }
12644514f5e3Sopenharmony_ci}
12654514f5e3Sopenharmony_ci
12664514f5e3Sopenharmony_civoid JSThread::StoreRunningState(ThreadState newState)
12674514f5e3Sopenharmony_ci{
12684514f5e3Sopenharmony_ci    ASSERT(newState == ThreadState::RUNNING);
12694514f5e3Sopenharmony_ci    while (true) {
12704514f5e3Sopenharmony_ci        ThreadStateAndFlags oldStateAndFlags;
12714514f5e3Sopenharmony_ci        oldStateAndFlags.asNonvolatileInt = glueData_.stateAndFlags_.asInt;
12724514f5e3Sopenharmony_ci        ASSERT(oldStateAndFlags.asNonvolatileStruct.state != ThreadState::RUNNING);
12734514f5e3Sopenharmony_ci
12744514f5e3Sopenharmony_ci        if (LIKELY(oldStateAndFlags.asNonvolatileStruct.flags == ThreadFlag::NO_FLAGS)) {
12754514f5e3Sopenharmony_ci            ThreadStateAndFlags newStateAndFlags;
12764514f5e3Sopenharmony_ci            newStateAndFlags.asNonvolatileStruct.flags = oldStateAndFlags.asNonvolatileStruct.flags;
12774514f5e3Sopenharmony_ci            newStateAndFlags.asNonvolatileStruct.state = newState;
12784514f5e3Sopenharmony_ci
12794514f5e3Sopenharmony_ci            if (glueData_.stateAndFlags_.asAtomicInt.compare_exchange_weak(oldStateAndFlags.asNonvolatileInt,
12804514f5e3Sopenharmony_ci                                                                           newStateAndFlags.asNonvolatileInt,
12814514f5e3Sopenharmony_ci                                                                           std::memory_order_release)) {
12824514f5e3Sopenharmony_ci                break;
12834514f5e3Sopenharmony_ci            }
12844514f5e3Sopenharmony_ci        } else if ((oldStateAndFlags.asNonvolatileStruct.flags & ThreadFlag::ACTIVE_BARRIER) != 0) {
12854514f5e3Sopenharmony_ci            PassSuspendBarrier();
12864514f5e3Sopenharmony_ci        } else if ((oldStateAndFlags.asNonvolatileStruct.flags & ThreadFlag::SUSPEND_REQUEST) != 0) {
12874514f5e3Sopenharmony_ci            constexpr int TIMEOUT = 100;
12884514f5e3Sopenharmony_ci            ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SuspendTime::StoreRunningState");
12894514f5e3Sopenharmony_ci            LockHolder lock(suspendLock_);
12904514f5e3Sopenharmony_ci            while (suspendCount_ > 0) {
12914514f5e3Sopenharmony_ci                suspendCondVar_.TimedWait(&suspendLock_, TIMEOUT);
12924514f5e3Sopenharmony_ci            }
12934514f5e3Sopenharmony_ci            ASSERT(!HasSuspendRequest());
12944514f5e3Sopenharmony_ci        }
12954514f5e3Sopenharmony_ci    }
12964514f5e3Sopenharmony_ci}
12974514f5e3Sopenharmony_ci
12984514f5e3Sopenharmony_ciinline void JSThread::StoreSuspendedState(ThreadState newState)
12994514f5e3Sopenharmony_ci{
13004514f5e3Sopenharmony_ci    ASSERT(newState != ThreadState::RUNNING);
13014514f5e3Sopenharmony_ci    StoreState(newState);
13024514f5e3Sopenharmony_ci}
13034514f5e3Sopenharmony_ci
13044514f5e3Sopenharmony_civoid JSThread::PostFork()
13054514f5e3Sopenharmony_ci{
13064514f5e3Sopenharmony_ci    SetThreadId();
13074514f5e3Sopenharmony_ci    if (currentThread == nullptr) {
13084514f5e3Sopenharmony_ci        currentThread = this;
13094514f5e3Sopenharmony_ci        ASSERT(GetState() == ThreadState::CREATED);
13104514f5e3Sopenharmony_ci        UpdateState(ThreadState::NATIVE);
13114514f5e3Sopenharmony_ci    } else {
13124514f5e3Sopenharmony_ci        // We tried to call fork in the same thread
13134514f5e3Sopenharmony_ci        ASSERT(currentThread == this);
13144514f5e3Sopenharmony_ci        ASSERT(GetState() == ThreadState::NATIVE);
13154514f5e3Sopenharmony_ci    }
13164514f5e3Sopenharmony_ci}
13174514f5e3Sopenharmony_ci#ifndef NDEBUG
13184514f5e3Sopenharmony_cibool JSThread::IsInManagedState() const
13194514f5e3Sopenharmony_ci{
13204514f5e3Sopenharmony_ci    ASSERT(this == JSThread::GetCurrent());
13214514f5e3Sopenharmony_ci    return GetState() == ThreadState::RUNNING;
13224514f5e3Sopenharmony_ci}
13234514f5e3Sopenharmony_ci
13244514f5e3Sopenharmony_ciMutatorLock::MutatorLockState JSThread::GetMutatorLockState() const
13254514f5e3Sopenharmony_ci{
13264514f5e3Sopenharmony_ci    return mutatorLockState_;
13274514f5e3Sopenharmony_ci}
13284514f5e3Sopenharmony_ci
13294514f5e3Sopenharmony_civoid JSThread::SetMutatorLockState(MutatorLock::MutatorLockState newState)
13304514f5e3Sopenharmony_ci{
13314514f5e3Sopenharmony_ci    mutatorLockState_ = newState;
13324514f5e3Sopenharmony_ci}
13334514f5e3Sopenharmony_ci#endif
13344514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
1335