1/*
2 * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "ecmascript/jit/jit.h"
17#include "ecmascript/jit/jit_task.h"
18#include "ecmascript/dfx/vmstat/jit_warmup_profiler.h"
19#include "ecmascript/ohos/jit_tools.h"
20
21namespace panda::ecmascript {
22void (*Jit::initJitCompiler_)(JSRuntimeOptions options) = nullptr;
23bool(*Jit::jitCompile_)(void*, JitTask*) = nullptr;
24bool(*Jit::jitFinalize_)(void*, JitTask*) = nullptr;
25void*(*Jit::createJitCompilerTask_)(JitTask*) = nullptr;
26void(*Jit::deleteJitCompile_)(void*) = nullptr;
27void *Jit::libHandle_ = nullptr;
28
29Jit *Jit::GetInstance()
30{
31    static Jit instance_;
32    return &instance_;
33}
34
35void Jit::SetJitEnablePostFork(EcmaVM *vm, const std::string &bundleName)
36{
37    JSRuntimeOptions &options = vm->GetJSOptions();
38    bool jitEnable = ohos::JitTools::GetJitEscapeDisable() || !AotCrashInfo::IsJitEscape();
39    jitEnable &= ohos::EnableAotJitListHelper::GetInstance()->IsEnableJit(bundleName);
40    jitEnable &= !vm->GetJSOptions().GetAOTHasException();
41    if (jitEnable) {
42        bool isEnableFastJit = options.IsEnableJIT() && options.GetEnableAsmInterpreter();
43        bool isEnableBaselineJit = options.IsEnableBaselineJIT() && options.GetEnableAsmInterpreter();
44
45        options.SetEnableJitFrame(ohos::JitTools::GetJitFrameEnable());
46        options.SetEnableAPPJIT(true);
47        // for app threshold
48        uint32_t defaultSize = 3000;
49        uint32_t threshold = ohos::JitTools::GetJitHotnessThreshold(defaultSize);
50        options.SetJitHotnessThreshold(threshold);
51        bundleName_ = bundleName;
52        isEnableAppPGO_ = pgo::PGOProfilerManager::GetInstance()->IsEnable();
53
54        SetEnableOrDisable(options, isEnableFastJit, isEnableBaselineJit);
55        if (fastJitEnable_ || baselineJitEnable_) {
56            ConfigJit(vm);
57        }
58    }
59}
60
61void Jit::SwitchProfileStubs(EcmaVM *vm)
62{
63    JSThread *thread = vm->GetAssociatedJSThread();
64    JSRuntimeOptions &options = vm->GetJSOptions();
65    std::shared_ptr<PGOProfiler> pgoProfiler = vm->GetPGOProfiler();
66    if (!options.IsEnableJITPGO() || pgoProfiler == nullptr || (isApp_ && !isEnableAppPGO_)) {
67        thread->SwitchJitProfileStubs(false);
68        options.SetEnableJITPGO(false);
69    } else {
70        // if not enable aot pgo
71        if (!pgo::PGOProfilerManager::GetInstance()->IsEnable()) {
72            // disable dump
73            options.SetEnableProfileDump(false);
74            SetProfileNeedDump(false);
75            // enable profiler
76            options.SetEnablePGOProfiler(true);
77            pgoProfiler->Reset(true);
78            // switch pgo stub
79            thread->SwitchJitProfileStubs(true);
80        }
81        pgoProfiler->InitJITProfiler();
82    }
83}
84
85void Jit::ConfigOptions(EcmaVM *vm) const
86{
87    JSRuntimeOptions &options = vm->GetJSOptions();
88
89    options.SetEnableAPPJIT(isApp_);
90    options.SetEnableProfileDump(isProfileNeedDump_);
91
92    bool jitEnableLitecg = ohos::JitTools::IsJitEnableLitecg(options.IsCompilerEnableLiteCG());
93    options.SetCompilerEnableLiteCG(jitEnableLitecg);
94
95    uint8_t jitCallThreshold = ohos::JitTools::GetJitCallThreshold(options.GetJitCallThreshold());
96    options.SetJitCallThreshold(jitCallThreshold);
97
98    uint32_t jitHotnessThreshold = GetHotnessThreshold();
99    options.SetJitHotnessThreshold(jitHotnessThreshold);
100
101    bool jitDisableCodeSign = ohos::JitTools::GetCodeSignDisable(options.GetDisableCodeSign());
102    options.SetDisableCodeSign(jitDisableCodeSign);
103
104    bool jitEnableJitFort = ohos::JitTools::GetEnableJitFort(options.GetEnableJitFort());
105    options.SetEnableJitFort(jitEnableJitFort);
106
107    bool jitEnableAsyncCopyToFort = ohos::JitTools::GetEnableAsyncCopyToFort(options.GetEnableAsyncCopyToFort());
108    options.SetEnableAsyncCopyToFort(jitEnableAsyncCopyToFort);
109
110    vm->SetEnableJitLogSkip(ohos::JitTools::GetSkipJitLogEnable());
111
112    LOG_JIT(INFO) << "enable jit bundle:" << bundleName_ <<
113        ", litecg:" << jitEnableLitecg <<
114        ", call threshold:" << static_cast<int>(jitCallThreshold) <<
115        ", hotness threshold:" << jitHotnessThreshold <<
116        ", disable codesigner:" << jitDisableCodeSign;
117}
118
119void Jit::ConfigJit(EcmaVM *vm)
120{
121    SwitchProfileStubs(vm);
122    ConfigOptions(vm);
123    ConfigJitFortOptions(vm);
124}
125
126void Jit::ConfigJitFortOptions(EcmaVM *vm)
127{
128    SetDisableCodeSign(vm->GetJSOptions().GetDisableCodeSign());
129    SetEnableJitFort(vm->GetJSOptions().GetEnableJitFort());
130    SetEnableAsyncCopyToFort(vm->GetJSOptions().GetEnableAsyncCopyToFort());
131}
132
133void Jit::SetEnableOrDisable(const JSRuntimeOptions &options, bool isEnableFastJit, bool isEnableBaselineJit)
134{
135    LockHolder holder(setEnableLock_);
136
137    bool needInitialize = false;
138    if (!isEnableFastJit) {
139        fastJitEnable_ = false;
140    } else {
141        needInitialize = true;
142    }
143    if (!isEnableBaselineJit) {
144        baselineJitEnable_ = false;
145    } else {
146        needInitialize = true;
147    }
148    if (!needInitialize) {
149        return;
150    }
151    if (!initialized_) {
152        Initialize();
153    }
154    if (initialized_) {
155        bool jitEnable = false;
156        if (isEnableFastJit && !fastJitEnable_) {
157            fastJitEnable_ = true;
158            jitEnable = true;
159        }
160        if (isEnableBaselineJit && !baselineJitEnable_) {
161            baselineJitEnable_ = true;
162            jitEnable = true;
163        }
164        if (jitEnable) {
165            jitDfx_ = JitDfx::GetInstance();
166            jitDfx_->Init(options, bundleName_);
167
168            isApp_ = options.IsEnableAPPJIT();
169            hotnessThreshold_ = options.GetJitHotnessThreshold();
170            initJitCompiler_(options);
171            bool enableCodeSign = !ohos::JitTools::GetCodeSignDisable(options.GetDisableCodeSign());
172            bool shouldCompileMain =
173                options.IsEnableForceJitCompileMain() || options.IsEnableForceBaselineCompileMain();
174            if (enableCodeSign && shouldCompileMain) {
175                JitFort::InitJitFortResource();
176            }
177            JitTaskpool::GetCurrentTaskpool()->Initialize(enableCodeSign && !shouldCompileMain);
178        }
179    }
180}
181
182void Jit::Destroy()
183{
184    if (!initialized_) {
185        return;
186    }
187
188    LockHolder holder(setEnableLock_);
189
190    JitTaskpool::GetCurrentTaskpool()->Destroy();
191    initialized_ = false;
192    fastJitEnable_ = false;
193    baselineJitEnable_ = false;
194    if (libHandle_ != nullptr) {
195        CloseLib(libHandle_);
196        libHandle_ = nullptr;
197    }
198}
199
200bool Jit::IsEnableFastJit() const
201{
202    return fastJitEnable_;
203}
204
205bool Jit::IsEnableBaselineJit() const
206{
207    return baselineJitEnable_;
208}
209
210bool Jit::IsEnableJitFort() const
211{
212    return isEnableJitFort_;
213}
214
215void Jit::SetEnableJitFort(bool isEnableJitFort)
216{
217    isEnableJitFort_ = isEnableJitFort;
218}
219
220bool Jit::IsDisableCodeSign() const
221{
222    return isDisableCodeSign_;
223}
224
225void Jit::SetDisableCodeSign(bool isDisableCodeSign)
226{
227    isDisableCodeSign_ = isDisableCodeSign;
228}
229
230bool Jit::IsEnableAsyncCopyToFort() const
231{
232    return isEnableAsyncCopyToFort_;
233}
234
235void Jit::SetEnableAsyncCopyToFort(bool isEnableAsyncCopyToFort)
236{
237    isEnableAsyncCopyToFort_ = isEnableAsyncCopyToFort;
238}
239
240void Jit::Initialize()
241{
242    static const std::string CREATEJITCOMPILETASK = "CreateJitCompilerTask";
243    static const std::string JITCOMPILEINIT = "InitJitCompiler";
244    static const std::string JITCOMPILE = "JitCompile";
245    static const std::string JITFINALIZE = "JitFinalize";
246    static const std::string DELETEJITCOMPILE = "DeleteJitCompile";
247    static const std::string LIBARK_JSOPTIMIZER = "libark_jsoptimizer.so";
248
249    libHandle_ = LoadLib(LIBARK_JSOPTIMIZER);
250    if (libHandle_ == nullptr) {
251        char *error = LoadLibError();
252        LOG_JIT(ERROR) << "jit dlopen libark_jsoptimizer.so failed, as:" <<
253            ((error == nullptr) ? "unknown error" : error);
254        return;
255    }
256
257    initJitCompiler_ = reinterpret_cast<void(*)(JSRuntimeOptions)>(FindSymbol(libHandle_, JITCOMPILEINIT.c_str()));
258    if (initJitCompiler_ == nullptr) {
259        LOG_JIT(ERROR) << "jit can't find symbol initJitCompiler";
260        return;
261    }
262    jitCompile_ = reinterpret_cast<bool(*)(void*, JitTask*)>(FindSymbol(libHandle_, JITCOMPILE.c_str()));
263    if (jitCompile_ == nullptr) {
264        LOG_JIT(ERROR) << "jit can't find symbol jitCompile";
265        return;
266    }
267
268    jitFinalize_ = reinterpret_cast<bool(*)(void*, JitTask*)>(FindSymbol(libHandle_, JITFINALIZE.c_str()));
269    if (jitFinalize_ == nullptr) {
270        LOG_JIT(ERROR) << "jit can't find symbol jitFinalize";
271        return;
272    }
273
274    createJitCompilerTask_ = reinterpret_cast<void*(*)(JitTask*)>(FindSymbol(libHandle_,
275        CREATEJITCOMPILETASK.c_str()));
276    if (createJitCompilerTask_ == nullptr) {
277        LOG_JIT(ERROR) << "jit can't find symbol createJitCompilertask";
278        return;
279    }
280
281    deleteJitCompile_ = reinterpret_cast<void(*)(void*)>(FindSymbol(libHandle_, DELETEJITCOMPILE.c_str()));
282    if (deleteJitCompile_ == nullptr) {
283        LOG_JIT(ERROR) << "jit can't find symbol deleteJitCompile";
284        return;
285    }
286    initialized_= true;
287    return;
288}
289
290Jit::~Jit()
291{
292}
293
294bool Jit::SupportJIT(JSHandle<JSFunction> &jsFunction, [[maybe_unused]] EcmaVM *vm, CompilerTier tier) const
295{
296    Method *method = Method::Cast(jsFunction->GetMethod().GetTaggedObject());
297    if (jsFunction.GetTaggedValue().IsJSSharedFunction()) {
298        LOG_JIT(DEBUG) << "method does not support compile shared function:" <<
299            method->GetRecordNameStr() + "." + method->GetMethodName();
300        return false;
301    }
302
303    FunctionKind kind = method->GetFunctionKind();
304    switch (kind) {
305        case FunctionKind::NORMAL_FUNCTION:
306        case FunctionKind::GETTER_FUNCTION:
307        case FunctionKind::SETTER_FUNCTION:
308        case FunctionKind::ARROW_FUNCTION:
309        case FunctionKind::BASE_CONSTRUCTOR:
310        case FunctionKind::CLASS_CONSTRUCTOR:
311        case FunctionKind::DERIVED_CONSTRUCTOR:
312        case FunctionKind::NONE_FUNCTION:
313            return true;
314        default:
315            break;
316    }
317    std::stringstream msgStr;
318    msgStr << "method does not support jit:" << method->GetRecordNameStr() + "." + method->GetMethodName() <<
319     ", kind:" << static_cast<int>(kind);
320    if (tier == CompilerTier::BASELINE) {
321        LOG_BASELINEJIT(DEBUG) << msgStr.str();
322    } else {
323        LOG_JIT(DEBUG) << msgStr.str();
324    }
325    return false;
326}
327
328void Jit::DeleteJitCompile(void *compiler)
329{
330    deleteJitCompile_(compiler);
331}
332
333void Jit::CountInterpExecFuncs(JSHandle<JSFunction> &jsFunction)
334{
335    Method *method = Method::Cast(jsFunction->GetMethod().GetTaggedObject());
336    auto jSPandaFile = method->GetJSPandaFile();
337    ASSERT(jSPandaFile != nullptr);
338    CString fileDesc = jSPandaFile->GetJSPandaFileDesc();
339    CString methodInfo = fileDesc + ":" + method->GetRecordNameStr() + "." + CString(method->GetMethodName());
340    auto &profMap = JitWarmupProfiler::GetInstance()->profMap_;
341    if (profMap.find(methodInfo) == profMap.end()) {
342        profMap.insert({methodInfo, false});
343    }
344}
345
346void Jit::Compile(EcmaVM *vm, JSHandle<JSFunction> &jsFunction, CompilerTier tier,
347                  int32_t offset, JitCompileMode mode)
348{
349    auto jit = Jit::GetInstance();
350    if ((!jit->IsEnableBaselineJit() && tier == CompilerTier::BASELINE) ||
351        (!jit->IsEnableFastJit() && tier == CompilerTier::FAST)) {
352        return;
353    }
354
355    if (!vm->IsEnableOsr() && offset != MachineCode::INVALID_OSR_OFFSET) {
356        return;
357    }
358
359    Method *method = Method::Cast(jsFunction->GetMethod().GetTaggedObject());
360    auto jSPandaFile = method->GetJSPandaFile();
361    ASSERT(jSPandaFile != nullptr);
362    CString fileDesc = jSPandaFile->GetJSPandaFileDesc();
363    CString methodName = fileDesc + ":" + method->GetRecordNameStr() + "." + CString(method->GetMethodName());
364    uint32_t codeSize = method->GetCodeSize();
365    CString methodInfo = methodName + ", bytecode size:" + ToCString(codeSize);
366    ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, ConvertToStdString("JIT::Compile:" + methodInfo));
367
368    uint32_t maxSize = 9000;
369    if (vm->GetJSOptions().IsEnableJitFastCompile()) {
370        maxSize = 15; // 15 is method codesize threshold during fast compiling
371    }
372    if (codeSize > maxSize && !(vm->GetJSOptions().IsEnableForceJitCompileMain() && mode == SYNC)) {
373        if (tier == CompilerTier::BASELINE) {
374            LOG_BASELINEJIT(DEBUG) << "skip jit task, as too large:" << methodInfo;
375        } else {
376            LOG_JIT(DEBUG) << "skip jit task, as too large:" << methodInfo;
377        }
378
379        return;
380    }
381    if (vm->IsEnableOsr() && offset != MachineCode::INVALID_OSR_OFFSET && method->HasCatchBlock()) {
382        LOG_JIT(DEBUG) << "skip jit task, as osr does not support catch blocks: " << methodInfo;
383        return;
384    }
385
386    CString msg = "compile method:" + methodInfo + ", in work thread";
387    TimeScope scope(vm, msg, tier, true, true);
388    if (vm->GetJSThread()->IsMachineCodeLowMemory()) {
389        if (tier == CompilerTier::BASELINE) {
390            LOG_BASELINEJIT(DEBUG) << "skip jit task, as low code memory:" << methodInfo;
391        } else {
392            LOG_JIT(DEBUG) << "skip jit task, as low code memory:" << methodInfo;
393        }
394
395        return;
396    }
397    if (!jit->SupportJIT(jsFunction, vm, tier)) {
398        return;
399    }
400    bool needCompile = jit->CheckJitCompileStatus(jsFunction, methodName, tier);
401    if (!needCompile) {
402        return;
403    }
404
405    // using hole value to indecate compiling. todo: reset when failed
406    if (tier == CompilerTier::FAST) {
407        jsFunction->SetMachineCode(vm->GetJSThread(), JSTaggedValue::Hole());
408        jit->GetJitDfx()->SetTriggerCount(false);
409    } else {
410        ASSERT(tier == CompilerTier::BASELINE);
411        jsFunction->SetBaselineCode(vm->GetJSThread(), JSTaggedValue::Hole());
412        jit->GetJitDfx()->SetTriggerCount(true);
413    }
414
415    {
416        JitTaskpool::GetCurrentTaskpool()->WaitForJitTaskPoolReady();
417        EcmaVM *compilerVm = JitTaskpool::GetCurrentTaskpool()->GetCompilerVm();
418        std::shared_ptr<JitTask> jitTask = std::make_shared<JitTask>(vm->GetJSThread(),
419            // avoid check fail when enable multi-thread check
420            compilerVm->GetJSThreadNoCheck(),
421            jit, jsFunction, tier, methodName, offset, vm->GetJSThread()->GetThreadId(), mode);
422
423        jitTask->PrepareCompile();
424        JitTaskpool::GetCurrentTaskpool()->PostTask(
425            std::make_unique<JitTask::AsyncTask>(jitTask, vm->GetJSThread()->GetThreadId()));
426        if (mode == SYNC) {
427            // sync mode, also compile in taskpool as litecg unsupport parallel compile,
428            // wait task compile finish then install code
429            jitTask->WaitFinish();
430            jitTask->InstallCode();
431        }
432        int spendTime = scope.TotalSpentTimeInMicroseconds();
433        jitTask->SetMainThreadCompilerTime(spendTime);
434        jit->GetJitDfx()->RecordSpentTimeAndPrintStatsLogInJsThread(spendTime);
435    }
436}
437
438void Jit::RequestInstallCode(std::shared_ptr<JitTask> jitTask)
439{
440    LockHolder holder(threadTaskInfoLock_);
441    ThreadTaskInfo &info = threadTaskInfo_[jitTask->GetHostThread()];
442    if (info.skipInstallTask_) {
443        return;
444    }
445    info.installJitTasks_.push_back(jitTask);
446
447    // set
448    jitTask->GetHostThread()->SetInstallMachineCode(true);
449    jitTask->GetHostThread()->SetCheckSafePointStatus();
450}
451
452bool Jit::CheckJitCompileStatus(JSHandle<JSFunction> &jsFunction,
453                                const CString &methodName, CompilerTier tier)
454{
455    if (tier == CompilerTier::FAST &&
456        jsFunction->GetMachineCode() == JSTaggedValue::Hole()) {
457        LOG_JIT(DEBUG) << "skip method, as it compiling:" << methodName;
458#if ECMASCRIPT_ENABLE_JIT_WARMUP_PROFILER
459        auto &profMap = JitWarmupProfiler::GetInstance()->profMap_;
460        if (profMap.find(methodName) != profMap.end()) {
461            profMap.erase(methodName);
462        }
463#endif
464        return false;
465    }
466
467    if (tier == CompilerTier::BASELINE &&
468        jsFunction->GetBaselineCode() == JSTaggedValue::Hole()) {
469        LOG_BASELINEJIT(DEBUG) << "skip method, as it compiling:" << methodName;
470        return false;
471    }
472
473    if (tier == CompilerTier::FAST && jsFunction->IsCompiledCode()) {
474        JSTaggedValue machineCode = jsFunction->GetMachineCode();
475        if (machineCode.IsMachineCodeObject() &&
476            MachineCode::Cast(machineCode.GetTaggedObject())->GetOSROffset() == MachineCode::INVALID_OSR_OFFSET) {
477            LOG_JIT(DEBUG) << "skip method, as it has been jit compiled:" << methodName;
478            return false;
479        }
480        return true;
481    }
482
483    if (tier == CompilerTier::BASELINE &&
484        jsFunction->GetBaselineCode() != JSTaggedValue::Undefined()) {
485        LOG_BASELINEJIT(DEBUG) << "skip method, as it has been jit compiled:" << methodName;
486        return false;
487    }
488    return true;
489}
490
491uint32_t Jit::GetRunningTaskCnt(EcmaVM *vm)
492{
493    uint32_t cnt = 0;
494    JitTaskpool::GetCurrentTaskpool()->ForEachTask([&cnt, &vm](Task *task) {
495        JitTask::AsyncTask *asyncTask = static_cast<JitTask::AsyncTask*>(task);
496        if (asyncTask->GetHostVM() == vm) {
497            cnt ++;
498        }
499    });
500    LockHolder holder(threadTaskInfoLock_);
501    ThreadTaskInfo &info = threadTaskInfo_[vm->GetJSThread()];
502    auto &taskQueue = info.installJitTasks_;
503    return taskQueue.size() + cnt;
504}
505
506void Jit::InstallTasks(JSThread *jsThread)
507{
508    LockHolder holder(threadTaskInfoLock_);
509    ThreadTaskInfo &info = threadTaskInfo_[jsThread];
510    auto &taskQueue = info.installJitTasks_;
511
512    ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, ConvertToStdString("Jit::InstallTasks count:" + ToCString(taskQueue.size())));
513
514    for (auto it = taskQueue.begin(); it != taskQueue.end(); it++) {
515        std::shared_ptr<JitTask> task = *it;
516        // check task state
517        task->InstallCode();
518    }
519    taskQueue.clear();
520}
521
522bool Jit::JitCompile(void *compiler, JitTask *jitTask)
523{
524    ASSERT(jitCompile_ != nullptr);
525    return jitCompile_(compiler, jitTask);
526}
527
528bool Jit::JitFinalize(void *compiler, JitTask *jitTask)
529{
530    ASSERT(jitFinalize_ != nullptr);
531    return jitFinalize_(compiler, jitTask);
532}
533
534void *Jit::CreateJitCompilerTask(JitTask *jitTask)
535{
536    ASSERT(createJitCompilerTask_ != nullptr);
537    return createJitCompilerTask_(jitTask);
538}
539
540void Jit::ClearTask(const std::function<bool(Task *task)> &checkClear)
541{
542    JitTaskpool::GetCurrentTaskpool()->ForEachTask([&checkClear](Task *task) {
543        JitTask::AsyncTask *asyncTask = static_cast<JitTask::AsyncTask*>(task);
544        if (checkClear(asyncTask)) {
545            asyncTask->Terminated();
546        }
547    });
548}
549
550void Jit::ClearTask(EcmaContext *ecmaContext)
551{
552    ClearTask([ecmaContext](Task *task) {
553        JitTask::AsyncTask *asyncTask = static_cast<JitTask::AsyncTask*>(task);
554        return ecmaContext == asyncTask->GetEcmaContext();
555    });
556}
557
558void Jit::ClearTaskWithVm(EcmaVM *vm)
559{
560    ClearTask([vm](Task *task) {
561        JitTask::AsyncTask *asyncTask = static_cast<JitTask::AsyncTask*>(task);
562        return vm == asyncTask->GetHostVM();
563    });
564
565    {
566        LockHolder holder(threadTaskInfoLock_);
567        ThreadTaskInfo &info = threadTaskInfo_[vm->GetJSThread()];
568        info.skipInstallTask_ = true;
569        auto &taskQueue = info.installJitTasks_;
570        taskQueue.clear();
571
572        if (info.jitTaskCnt_.load() != 0) {
573            info.jitTaskCntCv_.Wait(&threadTaskInfoLock_);
574        }
575    }
576}
577
578void Jit::IncJitTaskCnt(JSThread *thread)
579{
580    LockHolder holder(threadTaskInfoLock_);
581    ThreadTaskInfo &info = threadTaskInfo_[thread];
582    info.jitTaskCnt_.fetch_add(1);
583}
584
585void Jit::DecJitTaskCnt(JSThread *thread)
586{
587    LockHolder holder(threadTaskInfoLock_);
588    ThreadTaskInfo &info = threadTaskInfo_[thread];
589    uint32_t old = info.jitTaskCnt_.fetch_sub(1);
590    if (old == 1) {
591        info.jitTaskCntCv_.Signal();
592    }
593}
594
595void Jit::CheckMechineCodeSpaceMemory(JSThread *thread, int remainSize)
596{
597    if (!thread->IsMachineCodeLowMemory()) {
598        return;
599    }
600    if (remainSize > MIN_CODE_SPACE_SIZE) {
601        thread->SetMachineCodeLowMemory(false);
602    }
603}
604
605void Jit::ChangeTaskPoolState(bool inBackground)
606{
607    if (fastJitEnable_ || baselineJitEnable_) {
608        if (inBackground) {
609            JitTaskpool::GetCurrentTaskpool()->SetThreadPriority(PriorityMode::BACKGROUND);
610        } else {
611            JitTaskpool::GetCurrentTaskpool()->SetThreadPriority(PriorityMode::FOREGROUND);
612        }
613    }
614}
615
616Jit::TimeScope::~TimeScope()
617{
618    if (!outPutLog_) {
619        return;
620    }
621    if (isDebugLevel_) {
622        if (tier_ == CompilerTier::BASELINE) {
623            LOG_BASELINEJIT(DEBUG) << message_ << ": " << TotalSpentTime() << "ms";
624            return;
625        }
626        ASSERT(tier_ == CompilerTier::FAST);
627        LOG_JIT(DEBUG) << message_ << ": " << TotalSpentTime() << "ms";
628    } else {
629        if (tier_ == CompilerTier::BASELINE) {
630            LOG_BASELINEJIT(INFO) << message_ << ": " << TotalSpentTime() << "ms";
631            return;
632        }
633        ASSERT(tier_ == CompilerTier::FAST);
634        auto bundleName = vm_->GetBundleName();
635        if (vm_->GetEnableJitLogSkip() && bundleName != "" && message_.find(bundleName) == std::string::npos) {
636            return;
637        }
638        LOG_JIT(INFO) << message_ << ": " << TotalSpentTime() << "ms";
639    }
640}
641}  // namespace panda::ecmascript
642