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