• 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_task.h"
17 #include "ecmascript/base/config.h"
18 #include "common_components/heap/heap_manager.h"
19 #include "ecmascript/jspandafile/program_object.h"
20 #include "ecmascript/ohos/jit_tools.h"
21 #include "ecmascript/compiler/jit_compilation_env.h"
22 #include "ecmascript/platform/file.h"
23 
24 namespace panda::ecmascript {
25 
GetCurrentTaskpool()26 JitTaskpool *JitTaskpool::GetCurrentTaskpool()
27 {
28     static JitTaskpool *taskpool = new JitTaskpool();
29     return taskpool;
30 }
31 
TheMostSuitableThreadNum(uint32_t threadNum) const32 uint32_t JitTaskpool::TheMostSuitableThreadNum([[maybe_unused]]uint32_t threadNum) const
33 {
34     return 1;
35 }
36 
JitTask(JSThread * hostThread,JSThread * compilerThread,Jit * jit,JSHandle<JSFunction> & jsFunction,CompilerTier tier,CString & methodName,int32_t offset,JitCompileMode mode)37 JitTask::JitTask(JSThread *hostThread, JSThread *compilerThread, Jit *jit, JSHandle<JSFunction> &jsFunction,
38     CompilerTier tier, CString &methodName, int32_t offset, JitCompileMode mode)
39     : hostThread_(hostThread),
40     compilerThread_(compilerThread),
41     jit_(jit),
42     jsFunction_(jsFunction),
43     compilerTask_(nullptr),
44     state_(CompileState::SUCCESS),
45     compilerTier_(tier),
46     methodName_(methodName),
47     offset_(offset),
48     jitCompileMode_(mode),
49     runState_(RunState::INIT)
50 {
51     jit->IncJitTaskCnt(hostThread);
52     dependencies_ = new kungfu::LazyDeoptAllDependencies();
53     sustainingJSHandle_ = std::make_unique<SustainingJSHandle>(hostThread->GetEcmaVM());
54 }
55 
PrepareCompile()56 void JitTask::PrepareCompile()
57 {
58     CloneProfileTypeInfo();
59     SustainingJSHandles();
60     compilerTask_ = jit_->CreateJitCompilerTask(this);
61 
62     Method *method = Method::Cast(jsFunction_->GetMethod(hostThread_).GetTaggedObject());
63     JSTaggedValue constpool = method->GetConstantPool(hostThread_);
64     if (!ConstantPool::CheckUnsharedConstpool(constpool)) {
65         hostThread_->GetEcmaVM()->FindOrCreateUnsharedConstpool(constpool);
66     }
67 
68     SetRunState(RunState::INIT);
69 }
70 
Optimize()71 void JitTask::Optimize()
72 {
73     ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "JIT::Compiler frontend", "");
74     bool res = jit_->JitCompile(compilerTask_, this);
75     if (!res) {
76         SetCompileFailed();
77     }
78 }
79 
Finalize()80 void JitTask::Finalize()
81 {
82     if (!IsCompileSuccess()) {
83         return;
84     }
85 
86     ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "JIT::Compiler backend", "");
87     bool res = jit_->JitFinalize(compilerTask_, this);
88     if (!res) {
89         SetCompileFailed();
90     }
91 }
92 
InstallOsrCode(JSHandle<MachineCode> & codeObj)93 void JitTask::InstallOsrCode(JSHandle<MachineCode> &codeObj)
94 {
95     auto profile = jsFunction_->GetProfileTypeInfo(hostThread_);
96     if (profile.IsUndefined()) {
97         LOG_JIT(DEBUG) << "[OSR] Empty profile for installing code:" << GetMethodName();
98         return;
99     }
100     jsFunction_->SetIsCompiledFastCall(codeObj->GetIsFastCall());
101     JSHandle<ProfileTypeInfo> profileInfoHandle =
102         JSHandle<ProfileTypeInfo>::Cast(JSHandle<JSTaggedValue>(hostThread_, profile));
103     uint32_t slotId = profileInfoHandle->GetIcSlotToOsrLength() - 1; // 1 : get last slot
104     auto profileData = profileInfoHandle->Get(hostThread_, slotId);
105     auto factory = hostThread_->GetEcmaVM()->GetFactory();
106     if (!profileData.IsTaggedArray()) {
107         const uint32_t initLen = 1;
108         JSHandle<TaggedArray> newArr = factory->NewTaggedArray(initLen);
109         newArr->Set(hostThread_, 0, codeObj.GetTaggedValue());
110         profileInfoHandle->Set(hostThread_, slotId, newArr.GetTaggedValue());
111         LOG_JIT(DEBUG) << "[OSR] Install machine code:" << GetMethodName()
112                        << ", code address: " << reinterpret_cast<void*>(codeObj->GetFuncAddr())
113                        << ", index: " << newArr->GetLength() - 1;
114         return;
115     }
116     JSHandle<TaggedArray> arr(hostThread_, profileData);
117     JSHandle<TaggedArray> newArr = factory->NewTaggedArray(arr->GetLength() + 1);  // 1 : added for current codeObj
118     uint32_t i = 0;
119     for (; i < arr->GetLength(); i++) {
120         newArr->Set(hostThread_, i, arr->Get(hostThread_, i));
121     }
122     newArr->Set(hostThread_, i, codeObj.GetTaggedValue());
123     profileInfoHandle->Set(hostThread_, slotId, newArr.GetTaggedValue());
124     LOG_JIT(DEBUG) << "[OSR] Install machine code:" << GetMethodName()
125                    << ", code address: " << reinterpret_cast<void*>(codeObj->GetFuncAddr())
126                    << ", index: " << newArr->GetLength() - 1;
127     return;
128 }
129 
ComputeAlignedSizes(MachineCodeDesc & desc)130 static void ComputeAlignedSizes(MachineCodeDesc &desc)
131 {
132     desc.funcEntryDesSizeAlign = AlignUp(desc.funcEntryDesSize, MachineCode::TEXT_ALIGN);
133     desc.stackMapSizeAlign = AlignUp(desc.stackMapOrOffsetTableSize, MachineCode::DATA_ALIGN);
134     desc.heapConstantTableSizeAlign = AlignUp(desc.heapConstantTableSize, MachineCode::DATA_ALIGN);
135     desc.rodataSizeBeforeTextAlign = AlignUp(desc.rodataSizeBeforeText, MachineCode::TEXT_ALIGN);
136 
137     if (desc.codeType == MachineCodeType::BASELINE_CODE) {
138         desc.codeSizeAlign = Jit::GetInstance()->IsEnableJitFort() ?
139             AlignUp(desc.codeSize, MachineCode::TEXT_ALIGN) :
140             AlignUp(desc.codeSize, MachineCode::DATA_ALIGN);
141         return;
142     }
143 
144     // FastJit
145     if (Jit::GetInstance()->IsEnableJitFort()) {
146         // align for multiple instruction blocks installed in JitFort
147         if (desc.rodataSizeAfterText) {
148             desc.codeSizeAlign = AlignUp(desc.codeSize, MachineCode::DATA_ALIGN);
149             desc.rodataSizeAfterTextAlign = AlignUp(desc.rodataSizeAfterText, MachineCode::TEXT_ALIGN);
150         } else {
151             desc.codeSizeAlign = AlignUp(desc.codeSize, MachineCode::TEXT_ALIGN);
152         }
153     } else {
154         desc.codeSizeAlign = AlignUp(desc.codeSize, MachineCode::DATA_ALIGN);
155         desc.rodataSizeAfterTextAlign = AlignUp(desc.rodataSizeAfterText, MachineCode::DATA_ALIGN);
156     }
157 }
158 
ComputePayLoadSize(MachineCodeDesc & codeDesc)159 size_t JitTask::ComputePayLoadSize(MachineCodeDesc &codeDesc)
160 {
161     ComputeAlignedSizes(codeDesc);
162     if (codeDesc.codeType == MachineCodeType::BASELINE_CODE) {
163         // only code section in BaselineCode
164         if (Jit::GetInstance()->IsEnableJitFort()) {
165             size_t payLoadSize = codeDesc.stackMapSizeAlign + codeDesc.codeSizeAlign;
166             size_t allocSize = AlignUp(payLoadSize + MachineCode::SIZE,
167                 static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT));
168             codeDesc.instructionsSize = codeDesc.codeSizeAlign;
169             LOG_JIT(DEBUG) << "InstallCode:: MachineCode Object size to allocate: "
170                 << allocSize << " (instruction size): " << codeDesc.codeSizeAlign;
171             if (allocSize > g_maxRegularHeapObjectSize) {
172                 return payLoadSize;
173             } else {
174                 // regular sized machine code object instructions are installed in separate jit fort space
175                 return payLoadSize - codeDesc.codeSizeAlign;
176             }
177         } else {
178             return codeDesc.stackMapSizeAlign + codeDesc.codeSizeAlign;
179         }
180     }
181 
182     ASSERT(codeDesc.codeType == MachineCodeType::FAST_JIT_CODE);
183     if (Jit::GetInstance()->IsEnableJitFort()) {
184         // instructionsSize: size of JIT generated native instructions
185         // payLoadSize: size of JIT generated output including native code
186         size_t instructionsSize =
187             codeDesc.rodataSizeBeforeTextAlign + codeDesc.codeSizeAlign + codeDesc.rodataSizeAfterTextAlign;
188         size_t payLoadSize = codeDesc.funcEntryDesSizeAlign + instructionsSize +
189                              codeDesc.stackMapSizeAlign + codeDesc.heapConstantTableSizeAlign;
190         size_t allocSize = AlignUp(payLoadSize + MachineCode::SIZE,
191             static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT));
192         LOG_JIT(DEBUG) << "InstallCode:: MachineCode Object size to allocate: "
193             << allocSize << " (instruction size): " << instructionsSize;
194 
195         codeDesc.instructionsSize = instructionsSize;
196         if (allocSize > g_maxRegularHeapObjectSize) {
197             //
198             // A Huge machine code object is consisted of contiguous 256Kb aligned blocks.
199             // With JitFort, a huge machine code object starts with a page aligned mutable area
200             // (that holds Region and MachineCode object header, FuncEntryDesc and StackMap), followed
201             // by a page aligned nonmutable (JitFort space) area of JIT generated native instructions.
202             // i.e.
203             // mutableSize = align up to PageSize
204             //     (sizeof(Region) + HUGE_OBJECT_BITSET_SIZE +MachineCode::SIZE + payLoadSize - instructionsSize)
205             // immutableSize = instructionsSize (native page boundary aligned)
206             // See comments at HugeMachineCodeSpace::Allocate()
207             //
208             codeDesc.isHugeObj = true;
209             return payLoadSize;
210         } else {
211             // regular sized machine code object instructions are installed in separate jit fort space
212             return payLoadSize - instructionsSize;
213         }
214     } else {
215         return codeDesc.funcEntryDesSizeAlign + codeDesc.rodataSizeBeforeTextAlign + codeDesc.codeSizeAlign +
216                codeDesc.rodataSizeAfterTextAlign + codeDesc.stackMapSizeAlign + codeDesc.heapConstantTableSizeAlign;
217     }
218 }
219 
DumpJitCode(const JSThread * thread,JSHandle<MachineCode> & machineCode,JSHandle<Method> & method)220 void DumpJitCode(const JSThread *thread, JSHandle<MachineCode> &machineCode, JSHandle<Method> &method)
221 {
222     if (!ohos::JitTools::GetJitDumpObjEanble()) {
223         return;
224     }
225     JsJitDumpElf jitDumpElf;
226     jitDumpElf.Init();
227     char *funcAddr = reinterpret_cast<char *>(machineCode->GetFuncAddr());
228     size_t len = machineCode->GetTextSize();
229     std::vector<uint8> vec(len);
230     if (memmove_s(vec.data(), len, funcAddr, len) != EOK) {
231         LOG_JIT(DEBUG) << "Fail to get machineCode on function addr: " << funcAddr;
232     }
233     jitDumpElf.AppendData(vec);
234     const char *filename =  method->GetMethodName(thread);
235     std::string fileName = std::string(filename);
236     uintptr_t addr = machineCode->GetFuncAddr();
237     fileName = fileName + "_" + std::to_string(addr) + "+" + std::to_string(len);
238     jitDumpElf.AppendSymbolToSymTab(0, 0, len, std::string(filename));
239     std::string realOutPath;
240     std::string sanboxPath = panda::os::file::File::GetExtendedFilePath(AotCrashInfo::GetSandBoxPath());
241     if (!ecmascript::RealPath(sanboxPath, realOutPath, false)) {
242         return;
243     }
244     std::string outFile = realOutPath + "/" + std::string(fileName);
245     if (!ecmascript::FileExist(outFile.c_str())) {
246         return;
247     }
248     int fd = open(outFile.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0644);
249     FdsanExchangeOwnerTag(reinterpret_cast<fd_t>(fd));
250     jitDumpElf.WriteJitElfFile(fd);
251     Close(reinterpret_cast<fd_t>(fd));
252 }
253 
FillHeapConstantTable(JSHandle<MachineCode> & machineCodeObj,const MachineCodeDesc & codeDesc)254 static void FillHeapConstantTable(JSHandle<MachineCode> &machineCodeObj, const MachineCodeDesc &codeDesc)
255 {
256     if (codeDesc.heapConstantTableAddr == 0) {
257         return;
258     }
259     ASSERT(!g_isEnableCMCGC);
260     uint64_t *heapConstantTableAddr = reinterpret_cast<uint64_t*>(machineCodeObj->GetHeapConstantTableAddress());
261     JSHandle<JSTaggedValue> *heapConstantTableInCodeDesc =
262         reinterpret_cast<JSHandle<JSTaggedValue>*>(codeDesc.heapConstantTableAddr);
263 
264     uint64_t constTableSlotNum = codeDesc.heapConstantTableSize / sizeof(uint64_t);
265     LOG_JIT(DEBUG) << "constant table size: " << constTableSlotNum << "\n";
266     for (uint64_t i = 0; i < constTableSlotNum; ++i) {
267         JSHandle<JSTaggedValue> heapObj = heapConstantTableInCodeDesc[i];
268         heapConstantTableAddr[i] = heapObj->GetRawData();
269         Region *heapObjRegion = Region::ObjectAddressToRange(heapObj->GetRawData());
270         Region *curMachineCodeObjRegion =
271             Region::ObjectAddressToRange(machineCodeObj.GetTaggedValue().GetRawHeapObject());
272         if (heapObjRegion->InYoungSpace()) {
273             curMachineCodeObjRegion->InsertOldToNewRSet(reinterpret_cast<uintptr_t>(&(heapConstantTableAddr[i])));
274         } else if (heapObjRegion->InSharedHeap()) {
275             curMachineCodeObjRegion->InsertLocalToShareRSet(reinterpret_cast<uintptr_t>(&(heapConstantTableAddr[i])));
276         }
277     }
278 }
279 
280 // This should only be entered from hostVM, i.e., execution jsthread
InstallCode()281 void JitTask::InstallCode()
282 {
283     if (!IsCompileSuccess()) {
284         return;
285     }
286     [[maybe_unused]] EcmaHandleScope handleScope(hostThread_);
287     JSHandle<Method> methodHandle(hostThread_, Method::Cast(jsFunction_->GetMethod(hostThread_).GetTaggedObject()));
288     size_t size = ComputePayLoadSize(codeDesc_);
289     codeDesc_.isAsyncCompileMode = IsAsyncTask();
290 
291     if (!kungfu::LazyDeoptAllDependencies::Commit(
292         GetDependencies(), hostThread_, jsFunction_.GetTaggedValue())) {
293         return;
294     }
295 
296     JSHandle<MachineCode> machineCodeObj;
297     if (Jit::GetInstance()->IsEnableJitFort()) {
298         // skip install if JitFort out of memory
299         TaggedObject *machineCode = hostThread_->GetEcmaVM()->GetFactory()->NewMachineCodeObject(size, codeDesc_);
300         if (machineCode == nullptr) {
301             LOG_JIT(DEBUG) << "InstallCode skipped. NewMachineCode NULL for size " << size;
302             if (hostThread_->HasPendingException()) {
303                 hostThread_->SetMachineCodeLowMemory(true);
304                 hostThread_->ClearException();
305             }
306             return;
307         }
308         machineCodeObj = hostThread_->GetEcmaVM()->GetFactory()->SetMachineCodeObjectData(
309             machineCode, size, codeDesc_, methodHandle);
310     } else {
311         machineCodeObj = hostThread_->GetEcmaVM()->GetFactory()->NewMachineCodeObject(
312             size, codeDesc_, methodHandle);
313     }
314     if (machineCodeObj.GetAddress() == ToUintPtr(nullptr)) {
315         // skip install
316         return;
317     }
318     machineCodeObj->SetOSROffset(offset_);
319     FillHeapConstantTable(machineCodeObj, codeDesc_);
320 
321     if (hostThread_->HasPendingException()) {
322         // check is oom exception
323         hostThread_->SetMachineCodeLowMemory(true);
324         hostThread_->ClearException();
325     }
326 
327     if (IsOsrTask()) {
328         InstallOsrCode(machineCodeObj);
329     } else {
330         InstallCodeByCompilerTier(machineCodeObj, methodHandle);
331     }
332 
333     // sometimes get ILL_ILLOPC error if i-cache  not flushed for Jit code
334     uintptr_t codeAddr = machineCodeObj->GetFuncAddr();
335     uintptr_t codeAddrEnd = codeAddr + machineCodeObj->GetInstructionsSize();
336     __builtin___clear_cache(reinterpret_cast<char *>(codeAddr), reinterpret_cast<char*>(codeAddrEnd));
337 
338     if (Jit::GetInstance()->IsEnableJitFort()) {
339         if (g_isEnableCMCGC) {
340             common::BaseRuntime::GetInstance()->GetHeapManager().MarkJitFortMemInstalled(
341                 codeDesc_.isHugeObj ? nullptr : hostThread_, machineCodeObj.GetObject<MachineCode>());
342         } else {
343             if (!codeDesc_.isHugeObj) {
344                 const Heap *heap = this->GetHostThread()->GetEcmaVM()->GetHeap();
345                 heap->GetMachineCodeSpace()->MarkJitFortMemInstalled(machineCodeObj.GetObject<MachineCode>());
346             }
347         }
348     }
349 
350     if (compilerTier_.IsFast()) {
351         jsFunction_->SetJitCompilingFlag(false);
352         jsFunction_->SetJitHotnessCnt(hostThread_, 0);
353     } else {
354         ASSERT(compilerTier_.IsBaseLine());
355         jsFunction_->SetBaselinejitCompilingFlag(false);
356     }
357 }
358 
InstallCodeByCompilerTier(JSHandle<MachineCode> & machineCodeObj,JSHandle<Method> & methodHandle)359 void JitTask::InstallCodeByCompilerTier(JSHandle<MachineCode> &machineCodeObj,
360     JSHandle<Method> &methodHandle)
361 {
362     uintptr_t codeAddr = machineCodeObj->GetFuncAddr();
363     if (compilerTier_.IsFast()) {
364         jsFunction_->SetCompiledFuncEntry(codeAddr, machineCodeObj->GetIsFastCall());
365         methodHandle->SetDeoptThreshold(hostThread_->GetEcmaVM()->GetJSOptions().GetDeoptThreshold());
366         jsFunction_->SetMachineCode(hostThread_, machineCodeObj);
367         jsFunction_->SetJitMachineCodeCache(hostThread_, machineCodeObj);
368         uintptr_t codeAddrEnd = codeAddr + machineCodeObj->GetInstructionsSize();
369         LOG_JIT(DEBUG) <<"Install fast jit machine code:" << GetMethodName() << ", code range:" <<
370             reinterpret_cast<void*>(codeAddr) <<"--" << reinterpret_cast<void*>(codeAddrEnd);
371 #if ECMASCRIPT_ENABLE_JIT_WARMUP_PROFILER
372         auto &profMap = JitWarmupProfiler::GetInstance()->profMap_;
373         if (profMap.find(GetMethodName()) != profMap.end()) {
374             profMap[GetMethodName()] = true;
375         }
376 #endif
377     } else {
378         ASSERT(compilerTier_.IsBaseLine());
379         methodHandle->SetDeoptThreshold(hostThread_->GetEcmaVM()->GetJSOptions().GetDeoptThreshold());
380         jsFunction_->SetBaselineCode(hostThread_, machineCodeObj);
381         LOG_BASELINEJIT(DEBUG) <<"Install baseline jit machine code:" << GetMethodName();
382     }
383 }
384 
SustainingJSHandles()385 void JitTask::SustainingJSHandles()
386 {
387     // transfer to sustaining handle
388     JSHandle<JSFunction> sustainingJsFunctionHandle = sustainingJSHandle_->NewHandle(jsFunction_);
389     SetJsFunction(sustainingJsFunctionHandle);
390 
391     JSHandle<ProfileTypeInfo> profileTypeInfo = sustainingJSHandle_->NewHandle(profileTypeInfo_);
392     SetProfileTypeInfo(profileTypeInfo);
393 }
394 
ReleaseSustainingJSHandle()395 void JitTask::ReleaseSustainingJSHandle()
396 {
397     // in abort case, vm exit before task finish, release by explict
398     sustainingJSHandle_ = nullptr;
399 }
400 
CloneProfileTypeInfo()401 void JitTask::CloneProfileTypeInfo()
402 {
403     [[maybe_unused]] EcmaHandleScope handleScope(hostThread_);
404 
405     Method *method = Method::Cast(jsFunction_->GetMethod(hostThread_).GetTaggedObject());
406     uint32_t slotSize = method->GetSlotSize();
407     JSTaggedValue profileTypeInfoVal = jsFunction_->GetProfileTypeInfo(hostThread_);
408     JSHandle<ProfileTypeInfo> newProfileTypeInfo;
409     ObjectFactory *factory = hostThread_->GetEcmaVM()->GetFactory();
410     if (profileTypeInfoVal.IsUndefined() || slotSize == 0) {
411         slotSize = slotSize == 0 ? 1 : slotSize; // there's no profiletypeinfo, just generate a temp profiletypeinfo
412         newProfileTypeInfo = factory->NewProfileTypeInfo(slotSize);
413     } else {
414         JSHandle<ProfileTypeInfo> profileTypeInfo(hostThread_,
415             ProfileTypeInfo::Cast(profileTypeInfoVal.GetTaggedObject()));
416         newProfileTypeInfo = factory->NewProfileTypeInfo(slotSize);
417         for (uint32_t i = 0; i < slotSize; i++) {
418             JSTaggedValue value = profileTypeInfo->Get(hostThread_, i);
419             newProfileTypeInfo->Set(hostThread_, i, value);
420         }
421     }
422     SetProfileTypeInfo(newProfileTypeInfo);
423 }
424 
~JitTask()425 JitTask::~JitTask()
426 {
427     ReleaseSustainingJSHandle();
428     jit_->DeleteJitCompilerTask(compilerTask_);
429     jit_->DecJitTaskCnt(hostThread_);
430     ASSERT(dependencies_ != nullptr);
431     delete dependencies_;
432     dependencies_ = nullptr;
433 }
434 
WaitFinish()435 void JitTask::WaitFinish()
436 {
437     LockHolder lock(runStateMutex_);
438     if (!IsFinish()) {
439         runStateCondition_.Wait(&runStateMutex_);
440     }
441 }
442 
Run(uint32_t threadIndex)443 bool JitTask::AsyncTask::Run([[maybe_unused]] uint32_t threadIndex)
444 {
445     if (IsTerminate() || !jitTask_->GetHostThread()->GetEcmaVM()->IsInitialized()) {
446         return false;
447     }
448     DISALLOW_HEAP_ACCESS;
449 
450     CString info = "compile method:" + jitTask_->GetMethodName();
451     ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK,
452         ConvertToStdString("JIT::Compile:" + info).c_str(), "");
453 
454     AsyncTaskRunScope asyncTaskRunScope(jitTask_.get());
455 
456     if (jitTask_->GetJsFunction().GetAddress() == 0) {
457         // for unit test
458     } else {
459         info = info + ", in jit thread";
460         Jit::TimeScope scope(jitTask_->GetHostThread()->GetEcmaVM(), info, jitTask_->GetCompilerTier());
461 
462         jitTask_->Optimize();
463         jitTask_->Finalize();
464 
465         // info main thread compile complete
466         if (!jitTask_->IsCompileSuccess()) {
467             return false;
468         }
469 
470         if (jitTask_->IsAsyncTask()) {
471             jitTask_->jit_->RequestInstallCode(jitTask_);
472         }
473 
474         MachineCodeDesc codeDesc = jitTask_->GetMachineCodeDesc();
475         size_t instrSize = codeDesc.codeSizeAlign + codeDesc.rodataSizeBeforeTextAlign
476                            + codeDesc.rodataSizeAfterTextAlign;
477         CString sizeInfo = ": text size: ";
478         sizeInfo.append(std::to_string(instrSize)).append("bytes");
479         scope.appendMessage(sizeInfo);
480 
481         int compilerTime = scope.TotalSpentTimeInMicroseconds();
482         JitDfx::GetInstance()->RecordSpentTimeAndPrintStatsLogInJitThread(compilerTime, jitTask_->methodName_,
483             jitTask_->compilerTier_.IsBaseLine(), jitTask_->mainThreadCompileTime_);
484     }
485     return true;
486 }
487 
AsyncTaskRunScope(JitTask * jitTask)488 JitTask::AsyncTask::AsyncTaskRunScope::AsyncTaskRunScope(JitTask *jitTask)
489 {
490     jitTask_ = jitTask;
491     jitTask_->SetRunState(RunState::RUNNING);
492     JSThread *compilerThread = jitTask_->GetCompilerThread();
493     ASSERT(compilerThread->IsJitThread());
494     JitThread *jitThread = static_cast<JitThread*>(compilerThread);
495     jitvm_ = jitThread->GetJitVM();
496     jitvm_->SetHostVM(jitTask_->GetHostThread());
497     jitThread->SetCurrentTask(jitTask);
498 }
499 
~AsyncTaskRunScope()500 JitTask::AsyncTask::AsyncTaskRunScope::~AsyncTaskRunScope()
501 {
502     JSThread *compilerThread = jitTask_->GetCompilerThread();
503     JitThread *jitThread = static_cast<JitThread*>(compilerThread);
504     jitThread->SetCurrentTask(nullptr);
505     jitvm_->ReSetHostVM();
506     jitTask_->SetRunStateFinish();
507 }
508 }  // namespace panda::ecmascript
509