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