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 
21 namespace panda::ecmascript {
22 void (*Jit::initJitCompiler_)(JSRuntimeOptions options) = nullptr;
23 bool(*Jit::jitCompile_)(void*, JitTask*) = nullptr;
24 bool(*Jit::jitFinalize_)(void*, JitTask*) = nullptr;
25 void*(*Jit::createJitCompilerTask_)(JitTask*) = nullptr;
26 void(*Jit::deleteJitCompile_)(void*) = nullptr;
27 void *Jit::libHandle_ = nullptr;
28 
GetInstance()29 Jit *Jit::GetInstance()
30 {
31     static Jit instance_;
32     return &instance_;
33 }
34 
SetJitEnablePostFork(EcmaVM *vm, const std::string &bundleName)35 void 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 
SwitchProfileStubs(EcmaVM *vm)61 void 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 
ConfigOptions(EcmaVM *vm) const85 void 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 
ConfigJit(EcmaVM *vm)119 void Jit::ConfigJit(EcmaVM *vm)
120 {
121     SwitchProfileStubs(vm);
122     ConfigOptions(vm);
123     ConfigJitFortOptions(vm);
124 }
125 
ConfigJitFortOptions(EcmaVM *vm)126 void Jit::ConfigJitFortOptions(EcmaVM *vm)
127 {
128     SetDisableCodeSign(vm->GetJSOptions().GetDisableCodeSign());
129     SetEnableJitFort(vm->GetJSOptions().GetEnableJitFort());
130     SetEnableAsyncCopyToFort(vm->GetJSOptions().GetEnableAsyncCopyToFort());
131 }
132 
SetEnableOrDisable(const JSRuntimeOptions &options, bool isEnableFastJit, bool isEnableBaselineJit)133 void 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 
Destroy()182 void 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 
IsEnableFastJit() const200 bool Jit::IsEnableFastJit() const
201 {
202     return fastJitEnable_;
203 }
204 
IsEnableBaselineJit() const205 bool Jit::IsEnableBaselineJit() const
206 {
207     return baselineJitEnable_;
208 }
209 
IsEnableJitFort() const210 bool Jit::IsEnableJitFort() const
211 {
212     return isEnableJitFort_;
213 }
214 
SetEnableJitFort(bool isEnableJitFort)215 void Jit::SetEnableJitFort(bool isEnableJitFort)
216 {
217     isEnableJitFort_ = isEnableJitFort;
218 }
219 
IsDisableCodeSign() const220 bool Jit::IsDisableCodeSign() const
221 {
222     return isDisableCodeSign_;
223 }
224 
SetDisableCodeSign(bool isDisableCodeSign)225 void Jit::SetDisableCodeSign(bool isDisableCodeSign)
226 {
227     isDisableCodeSign_ = isDisableCodeSign;
228 }
229 
IsEnableAsyncCopyToFort() const230 bool Jit::IsEnableAsyncCopyToFort() const
231 {
232     return isEnableAsyncCopyToFort_;
233 }
234 
SetEnableAsyncCopyToFort(bool isEnableAsyncCopyToFort)235 void Jit::SetEnableAsyncCopyToFort(bool isEnableAsyncCopyToFort)
236 {
237     isEnableAsyncCopyToFort_ = isEnableAsyncCopyToFort;
238 }
239 
Initialize()240 void 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 
~Jit()290 Jit::~Jit()
291 {
292 }
293 
SupportJIT(JSHandle<JSFunction> &jsFunction, [[maybe_unused]] EcmaVM *vm, CompilerTier tier) const294 bool 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 
DeleteJitCompile(void *compiler)328 void Jit::DeleteJitCompile(void *compiler)
329 {
330     deleteJitCompile_(compiler);
331 }
332 
CountInterpExecFuncs(JSHandle<JSFunction> &jsFunction)333 void 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 
Compile(EcmaVM *vm, JSHandle<JSFunction> &jsFunction, CompilerTier tier, int32_t offset, JitCompileMode mode)346 void 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 
RequestInstallCode(std::shared_ptr<JitTask> jitTask)438 void 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 
CheckJitCompileStatus(JSHandle<JSFunction> &jsFunction, const CString &methodName, CompilerTier tier)452 bool 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 
GetRunningTaskCnt(EcmaVM *vm)491 uint32_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 
InstallTasks(JSThread *jsThread)506 void 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 
JitCompile(void *compiler, JitTask *jitTask)522 bool Jit::JitCompile(void *compiler, JitTask *jitTask)
523 {
524     ASSERT(jitCompile_ != nullptr);
525     return jitCompile_(compiler, jitTask);
526 }
527 
JitFinalize(void *compiler, JitTask *jitTask)528 bool Jit::JitFinalize(void *compiler, JitTask *jitTask)
529 {
530     ASSERT(jitFinalize_ != nullptr);
531     return jitFinalize_(compiler, jitTask);
532 }
533 
CreateJitCompilerTask(JitTask *jitTask)534 void *Jit::CreateJitCompilerTask(JitTask *jitTask)
535 {
536     ASSERT(createJitCompilerTask_ != nullptr);
537     return createJitCompilerTask_(jitTask);
538 }
539 
ClearTask(const std::function<bool(Task *task)> &checkClear)540 void 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 
ClearTask(EcmaContext *ecmaContext)550 void 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 
ClearTaskWithVm(EcmaVM *vm)558 void 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 
IncJitTaskCnt(JSThread *thread)578 void Jit::IncJitTaskCnt(JSThread *thread)
579 {
580     LockHolder holder(threadTaskInfoLock_);
581     ThreadTaskInfo &info = threadTaskInfo_[thread];
582     info.jitTaskCnt_.fetch_add(1);
583 }
584 
DecJitTaskCnt(JSThread *thread)585 void 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 
CheckMechineCodeSpaceMemory(JSThread *thread, int remainSize)595 void 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 
ChangeTaskPoolState(bool inBackground)605 void 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 
~TimeScope()616 Jit::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