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