1 /**
2 * Copyright (c) 2021-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 "runtime/compiler.h"
17
18 #include "intrinsics.h"
19 #include "libpandafile/bytecode_instruction.h"
20 #include "libpandafile/type_helper.h"
21 #include "runtime/cha.h"
22 #include "runtime/jit/profiling_data.h"
23 #include "runtime/include/class_linker-inl.h"
24 #include "runtime/include/exceptions.h"
25 #include "runtime/include/field.h"
26 #include "runtime/include/runtime.h"
27 #include "runtime/include/thread.h"
28 #include "runtime/include/coretypes/native_pointer.h"
29 #include "runtime/mem/heap_manager.h"
30 #include "compiler/inplace_task_runner.h"
31 #include "compiler/background_task_runner.h"
32
33 namespace ark {
34
35 #ifdef PANDA_COMPILER_DEBUG_INFO
36 namespace compiler {
37 void CleanJitDebugCode();
38 } // namespace compiler
39 #endif
40
41 #include <get_intrinsics.inl>
42
43 class ErrorHandler : public ClassLinkerErrorHandler {
OnError(ClassLinker::Error error,const PandaString & message)44 void OnError([[maybe_unused]] ClassLinker::Error error, [[maybe_unused]] const PandaString &message) override {}
45 };
46
IsCompilationExpired(Method * method,bool isOsr)47 bool Compiler::IsCompilationExpired(Method *method, bool isOsr)
48 {
49 return (isOsr && GetOsrCode(method) != nullptr) || (!isOsr && method->HasCompiledCode());
50 }
51
52 /// Intrinsics fast paths are supported only for G1 GC.
IsGcValidForFastPath(SourceLanguage lang) const53 bool PandaRuntimeInterface::IsGcValidForFastPath(SourceLanguage lang) const
54 {
55 auto runtime = Runtime::GetCurrent();
56 if (lang == SourceLanguage::INVALID) {
57 lang = ManagedThread::GetCurrent()->GetThreadLang();
58 }
59 auto gcType = runtime->GetGCType(runtime->GetOptions(), lang);
60 return gcType == mem::GCType::G1_GC;
61 }
62
ResolveMethodIndex(MethodPtr parentMethod,MethodIndex index) const63 compiler::RuntimeInterface::MethodId PandaRuntimeInterface::ResolveMethodIndex(MethodPtr parentMethod,
64 MethodIndex index) const
65 {
66 return MethodCast(parentMethod)->GetClass()->ResolveMethodIndex(index).GetOffset();
67 }
68
ResolveFieldIndex(MethodPtr parentMethod,FieldIndex index) const69 compiler::RuntimeInterface::FieldId PandaRuntimeInterface::ResolveFieldIndex(MethodPtr parentMethod,
70 FieldIndex index) const
71 {
72 return MethodCast(parentMethod)->GetClass()->ResolveFieldIndex(index).GetOffset();
73 }
74
ResolveTypeIndex(MethodPtr parentMethod,TypeIndex index) const75 compiler::RuntimeInterface::IdType PandaRuntimeInterface::ResolveTypeIndex(MethodPtr parentMethod,
76 TypeIndex index) const
77 {
78 return MethodCast(parentMethod)->GetClass()->ResolveClassIndex(index).GetOffset();
79 }
80
GetMethodById(MethodPtr parentMethod,MethodId id) const81 compiler::RuntimeInterface::MethodPtr PandaRuntimeInterface::GetMethodById(MethodPtr parentMethod, MethodId id) const
82 {
83 ScopedMutatorLock lock;
84 ErrorHandler errorHandler;
85 return Runtime::GetCurrent()->GetClassLinker()->GetMethod(*MethodCast(parentMethod), panda_file::File::EntityId(id),
86 &errorHandler);
87 }
88
GetMethodId(MethodPtr method) const89 compiler::RuntimeInterface::MethodId PandaRuntimeInterface::GetMethodId(MethodPtr method) const
90 {
91 return MethodCast(method)->GetFileId().GetOffset();
92 }
93
GetIntrinsicId(MethodPtr method) const94 compiler::RuntimeInterface::IntrinsicId PandaRuntimeInterface::GetIntrinsicId(MethodPtr method) const
95 {
96 return GetIntrinsicEntryPointId(MethodCast(method)->GetIntrinsic());
97 }
98
GetUniqMethodId(MethodPtr method) const99 uint64_t PandaRuntimeInterface::GetUniqMethodId(MethodPtr method) const
100 {
101 return MethodCast(method)->GetUniqId();
102 }
103
ResolveVirtualMethod(ClassPtr cls,MethodPtr method) const104 compiler::RuntimeInterface::MethodPtr PandaRuntimeInterface::ResolveVirtualMethod(ClassPtr cls, MethodPtr method) const
105 {
106 ScopedMutatorLock lock;
107 ASSERT(method != nullptr);
108 return ClassCast(cls)->ResolveVirtualMethod(MethodCast(method));
109 }
110
ResolveInterfaceMethod(ClassPtr cls,MethodPtr method) const111 compiler::RuntimeInterface::MethodPtr PandaRuntimeInterface::ResolveInterfaceMethod(ClassPtr cls,
112 MethodPtr method) const
113 {
114 ScopedMutatorLock lock;
115 ASSERT(method != nullptr);
116 return ClassCast(cls)->ResolveVirtualMethod(MethodCast(method));
117 }
118
GetMethodReturnTypeId(MethodPtr method) const119 compiler::RuntimeInterface::IdType PandaRuntimeInterface::GetMethodReturnTypeId(MethodPtr method) const
120 {
121 auto *pf = MethodCast(method)->GetPandaFile();
122 panda_file::ProtoDataAccessor pda(*pf,
123 panda_file::MethodDataAccessor::GetProtoId(*pf, MethodCast(method)->GetFileId()));
124 return pda.GetReferenceType(0).GetOffset();
125 }
126
GetMethodArgReferenceTypeId(MethodPtr method,uint16_t num) const127 compiler::RuntimeInterface::IdType PandaRuntimeInterface::GetMethodArgReferenceTypeId(MethodPtr method,
128 uint16_t num) const
129 {
130 auto *pf = MethodCast(method)->GetPandaFile();
131 panda_file::ProtoDataAccessor pda(*pf,
132 panda_file::MethodDataAccessor::GetProtoId(*pf, MethodCast(method)->GetFileId()));
133 return pda.GetReferenceType(num).GetOffset();
134 }
135
GetClass(MethodPtr method,IdType id) const136 compiler::RuntimeInterface::ClassPtr PandaRuntimeInterface::GetClass(MethodPtr method, IdType id) const
137 {
138 ScopedMutatorLock lock;
139 auto *caller = MethodCast(method);
140 LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(*caller);
141 ErrorHandler handler;
142 return Runtime::GetCurrent()->GetClassLinker()->GetExtension(ctx)->GetClass(
143 *caller->GetPandaFile(), panda_file::File::EntityId(id), caller->GetClass()->GetLoadContext(), &handler);
144 }
145
GetStringClass(MethodPtr method) const146 compiler::RuntimeInterface::ClassPtr PandaRuntimeInterface::GetStringClass(MethodPtr method) const
147 {
148 ScopedMutatorLock lock;
149 auto *caller = MethodCast(method);
150 LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(*caller);
151 return Runtime::GetCurrent()->GetClassLinker()->GetExtension(ctx)->GetClassRoot(ClassRoot::STRING);
152 }
153
GetArrayU16Class(MethodPtr method) const154 compiler::RuntimeInterface::ClassPtr PandaRuntimeInterface::GetArrayU16Class(MethodPtr method) const
155 {
156 ScopedMutatorLock lock;
157 auto *caller = MethodCast(method);
158 LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(*caller);
159 return Runtime::GetCurrent()->GetClassLinker()->GetExtension(ctx)->GetClassRoot(ClassRoot::ARRAY_U16);
160 }
161
GetClassType(ClassPtr klassPtr) const162 compiler::ClassType PandaRuntimeInterface::GetClassType(ClassPtr klassPtr) const
163 {
164 if (klassPtr == nullptr) {
165 return compiler::ClassType::UNRESOLVED_CLASS;
166 }
167 auto klass = ClassCast(klassPtr);
168 if (klass == nullptr) {
169 return compiler::ClassType::UNRESOLVED_CLASS;
170 }
171 if (klass->IsObjectClass()) {
172 return compiler::ClassType::OBJECT_CLASS;
173 }
174 if (klass->IsInterface()) {
175 return compiler::ClassType::INTERFACE_CLASS;
176 }
177 if (klass->IsArrayClass()) {
178 auto componentClass = klass->GetComponentType();
179 ASSERT(componentClass != nullptr);
180 if (componentClass->IsObjectClass()) {
181 return compiler::ClassType::ARRAY_OBJECT_CLASS;
182 }
183 if (componentClass->IsPrimitive()) {
184 return compiler::ClassType::FINAL_CLASS;
185 }
186 return compiler::ClassType::ARRAY_CLASS;
187 }
188 if (klass->IsFinal()) {
189 return compiler::ClassType::FINAL_CLASS;
190 }
191 return compiler::ClassType::OTHER_CLASS;
192 }
193
GetClassType(MethodPtr method,IdType id) const194 compiler::ClassType PandaRuntimeInterface::GetClassType(MethodPtr method, IdType id) const
195 {
196 if (method == nullptr) {
197 return compiler::ClassType::UNRESOLVED_CLASS;
198 }
199 ScopedMutatorLock lock;
200 auto *caller = MethodCast(method);
201 LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(*caller);
202 ErrorHandler handler;
203 auto klass = Runtime::GetCurrent()->GetClassLinker()->GetExtension(ctx)->GetClass(
204 *caller->GetPandaFile(), panda_file::File::EntityId(id), caller->GetClass()->GetLoadContext(), &handler);
205 if (klass == nullptr) {
206 return compiler::ClassType::UNRESOLVED_CLASS;
207 }
208 if (klass->IsObjectClass()) {
209 return compiler::ClassType::OBJECT_CLASS;
210 }
211 if (klass->IsInterface()) {
212 return compiler::ClassType::INTERFACE_CLASS;
213 }
214 if (klass->IsArrayClass()) {
215 auto componentClass = klass->GetComponentType();
216 ASSERT(componentClass != nullptr);
217 if (componentClass->IsObjectClass()) {
218 return compiler::ClassType::ARRAY_OBJECT_CLASS;
219 }
220 if (componentClass->IsPrimitive()) {
221 return compiler::ClassType::FINAL_CLASS;
222 }
223 return compiler::ClassType::ARRAY_CLASS;
224 }
225 if (klass->IsFinal()) {
226 return compiler::ClassType::FINAL_CLASS;
227 }
228 return compiler::ClassType::OTHER_CLASS;
229 }
230
IsArrayClass(MethodPtr method,IdType id) const231 bool PandaRuntimeInterface::IsArrayClass(MethodPtr method, IdType id) const
232 {
233 panda_file::File::EntityId cid(id);
234 auto *pf = MethodCast(method)->GetPandaFile();
235 return ClassHelper::IsArrayDescriptor(pf->GetStringData(cid).data);
236 }
237
IsStringClass(MethodPtr method,IdType id) const238 bool PandaRuntimeInterface::IsStringClass(MethodPtr method, IdType id) const
239 {
240 auto cls = GetClass(method, id);
241 if (cls == nullptr) {
242 return false;
243 }
244 return ClassCast(cls)->IsStringClass();
245 }
246
GetArrayElementClass(ClassPtr cls) const247 compiler::RuntimeInterface::ClassPtr PandaRuntimeInterface::GetArrayElementClass(ClassPtr cls) const
248 {
249 ScopedMutatorLock lock;
250 ASSERT(ClassCast(cls)->IsArrayClass());
251 return ClassCast(cls)->GetComponentType();
252 }
253
CheckStoreArray(ClassPtr arrayCls,ClassPtr strCls) const254 bool PandaRuntimeInterface::CheckStoreArray(ClassPtr arrayCls, ClassPtr strCls) const
255 {
256 ASSERT(arrayCls != nullptr);
257 auto *elementClass = ClassCast(arrayCls)->GetComponentType();
258 if (strCls == nullptr) {
259 return elementClass->IsObjectClass();
260 }
261 ASSERT(strCls != nullptr);
262 return elementClass->IsAssignableFrom(ClassCast(strCls));
263 }
264
IsAssignableFrom(ClassPtr cls1,ClassPtr cls2) const265 bool PandaRuntimeInterface::IsAssignableFrom(ClassPtr cls1, ClassPtr cls2) const
266 {
267 ASSERT(cls1 != nullptr);
268 ASSERT(cls2 != nullptr);
269 return ClassCast(cls1)->IsAssignableFrom(ClassCast(cls2));
270 }
271
IsInterfaceMethod(MethodPtr parentMethod,MethodId id) const272 bool PandaRuntimeInterface::IsInterfaceMethod(MethodPtr parentMethod, MethodId id) const
273 {
274 ScopedMutatorLock lock;
275 ErrorHandler handler;
276 auto method = Runtime::GetCurrent()->GetClassLinker()->GetMethod(*MethodCast(parentMethod),
277 panda_file::File::EntityId(id), &handler);
278 return (method->GetClass()->IsInterface() && !method->IsDefaultInterfaceMethod());
279 }
280
CanThrowException(MethodPtr method) const281 bool PandaRuntimeInterface::CanThrowException(MethodPtr method) const
282 {
283 ScopedMutatorLock lock;
284 auto *pandaMethod = MethodCast(method);
285 LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(*pandaMethod);
286 return Runtime::GetCurrent()->GetClassLinker()->GetExtension(ctx)->CanThrowException(pandaMethod);
287 }
288
FindCatchBlock(MethodPtr m,ClassPtr cls,uint32_t pc) const289 uint32_t PandaRuntimeInterface::FindCatchBlock(MethodPtr m, ClassPtr cls, uint32_t pc) const
290 {
291 ScopedMutatorLock lock;
292 return MethodCast(m)->FindCatchBlockInPandaFile(ClassCast(cls), pc);
293 }
294
IsInterfaceMethod(MethodPtr method) const295 bool PandaRuntimeInterface::IsInterfaceMethod(MethodPtr method) const
296 {
297 ScopedMutatorLock lock;
298 return (MethodCast(method)->GetClass()->IsInterface() && !MethodCast(method)->IsDefaultInterfaceMethod());
299 }
300
HasNativeException(MethodPtr method) const301 bool PandaRuntimeInterface::HasNativeException(MethodPtr method) const
302 {
303 if (!MethodCast(method)->IsNative()) {
304 return false;
305 }
306 return CanThrowException(method);
307 }
308
IsMethodExternal(MethodPtr parentMethod,MethodPtr calleeMethod) const309 bool PandaRuntimeInterface::IsMethodExternal(MethodPtr parentMethod, MethodPtr calleeMethod) const
310 {
311 if (calleeMethod == nullptr) {
312 return true;
313 }
314 return MethodCast(parentMethod)->GetPandaFile() != MethodCast(calleeMethod)->GetPandaFile();
315 }
316
GetMethodReturnType(MethodPtr parentMethod,MethodId id) const317 compiler::DataType::Type PandaRuntimeInterface::GetMethodReturnType(MethodPtr parentMethod, MethodId id) const
318 {
319 auto *pf = MethodCast(parentMethod)->GetPandaFile();
320 panda_file::MethodDataAccessor mda(*pf, panda_file::File::EntityId(id));
321 panda_file::ProtoDataAccessor pda(*pf, mda.GetProtoId());
322 return ToCompilerType(panda_file::GetEffectiveType(pda.GetReturnType()));
323 }
324
GetMethodArgumentType(MethodPtr parentMethod,MethodId id,size_t index) const325 compiler::DataType::Type PandaRuntimeInterface::GetMethodArgumentType(MethodPtr parentMethod, MethodId id,
326 size_t index) const
327 {
328 auto *pf = MethodCast(parentMethod)->GetPandaFile();
329 panda_file::MethodDataAccessor mda(*pf, panda_file::File::EntityId(id));
330 panda_file::ProtoDataAccessor pda(*pf, mda.GetProtoId());
331 return ToCompilerType(panda_file::GetEffectiveType(pda.GetArgType(index)));
332 }
333
GetMethodArgumentsCount(MethodPtr parentMethod,MethodId id) const334 size_t PandaRuntimeInterface::GetMethodArgumentsCount(MethodPtr parentMethod, MethodId id) const
335 {
336 auto *pf = MethodCast(parentMethod)->GetPandaFile();
337 panda_file::MethodDataAccessor mda(*pf, panda_file::File::EntityId(id));
338 panda_file::ProtoDataAccessor pda(*pf, mda.GetProtoId());
339 return pda.GetNumArgs();
340 }
341
IsMethodStatic(MethodPtr parentMethod,MethodId id) const342 bool PandaRuntimeInterface::IsMethodStatic(MethodPtr parentMethod, MethodId id) const
343 {
344 auto *pf = MethodCast(parentMethod)->GetPandaFile();
345 panda_file::MethodDataAccessor mda(*pf, panda_file::File::EntityId(id));
346 return mda.IsStatic();
347 }
348
IsMethodStatic(MethodPtr method) const349 bool PandaRuntimeInterface::IsMethodStatic(MethodPtr method) const
350 {
351 return MethodCast(method)->IsStatic();
352 }
353
IsMethodStaticConstructor(MethodPtr method) const354 bool PandaRuntimeInterface::IsMethodStaticConstructor(MethodPtr method) const
355 {
356 return MethodCast(method)->IsStaticConstructor();
357 }
358
IsMemoryBarrierRequired(MethodPtr method) const359 bool PandaRuntimeInterface::IsMemoryBarrierRequired(MethodPtr method) const
360 {
361 if (!MethodCast(method)->IsInstanceConstructor()) {
362 return false;
363 }
364 for (auto &field : MethodCast(method)->GetClass()->GetFields()) {
365 // We insert memory barrier after call to constructor to ensure writes
366 // to final fields will be visible after constructor finishes
367 // Static fields are initialized in runtime entrypoints like InitializeClass,
368 // so barrier is not needed here if they are final
369 if (field.IsFinal() && !field.IsStatic()) {
370 return true;
371 }
372 }
373 return false;
374 }
375
IsMethodIntrinsic(MethodPtr parentMethod,MethodId id) const376 bool PandaRuntimeInterface::IsMethodIntrinsic(MethodPtr parentMethod, MethodId id) const
377 {
378 Method *caller = MethodCast(parentMethod);
379 auto *pf = caller->GetPandaFile();
380 panda_file::MethodDataAccessor mda(*pf, panda_file::File::EntityId(id));
381
382 auto *className = pf->GetStringData(mda.GetClassId()).data;
383 auto *classLinker = Runtime::GetCurrent()->GetClassLinker();
384
385 auto *klass = classLinker->FindLoadedClass(className, caller->GetClass()->GetLoadContext());
386
387 // Class should be loaded during intrinsics initialization
388 if (klass == nullptr) {
389 return false;
390 }
391
392 auto name = pf->GetStringData(mda.GetNameId());
393 bool isArrayClone = ClassHelper::IsArrayDescriptor(className) &&
394 (utf::CompareMUtf8ToMUtf8(name.data, utf::CStringAsMutf8("clone")) == 0);
395 Method::Proto proto(*pf, mda.GetProtoId());
396 auto *method = klass->GetDirectMethod(name.data, proto);
397 if (method == nullptr) {
398 if (isArrayClone) {
399 method = klass->GetClassMethod(name.data, proto);
400 } else {
401 return false;
402 }
403 }
404
405 return method->IsIntrinsic();
406 }
407
GetBytecodeString(MethodPtr method,uintptr_t pc) const408 std::string PandaRuntimeInterface::GetBytecodeString(MethodPtr method, uintptr_t pc) const
409 {
410 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
411 BytecodeInstruction inst(MethodCast(method)->GetInstructions() + pc);
412 std::stringstream ss;
413 ss << inst;
414 return ss.str();
415 }
416
ResolveField(PandaRuntimeInterface::MethodPtr m,size_t id,bool allowExternal,uint32_t * pclassId)417 PandaRuntimeInterface::FieldPtr PandaRuntimeInterface::ResolveField(PandaRuntimeInterface::MethodPtr m, size_t id,
418 bool allowExternal, uint32_t *pclassId)
419 {
420 ScopedMutatorLock lock;
421 ErrorHandler handler;
422 auto method = MethodCast(m);
423 auto pfile = method->GetPandaFile();
424 auto field = Runtime::GetCurrent()->GetClassLinker()->GetField(*method, panda_file::File::EntityId(id), &handler);
425 if (field == nullptr) {
426 return nullptr;
427 }
428 auto klass = field->GetClass();
429 if (pfile == field->GetPandaFile() || allowExternal) {
430 if (pclassId != nullptr) {
431 *pclassId = klass->GetFileId().GetOffset();
432 }
433 return field;
434 }
435
436 auto classId = GetClassIdWithinFile(m, klass);
437 if (classId != 0) {
438 if (pclassId != nullptr) {
439 *pclassId = classId;
440 }
441 return field;
442 }
443 return nullptr;
444 }
445
446 template <typename T>
FillLiteralArrayData(const panda_file::File * pfile,pandasm::LiteralArray * litArray,const panda_file::LiteralTag & tag,const panda_file::LiteralDataAccessor::LiteralValue & value)447 void FillLiteralArrayData(const panda_file::File *pfile, pandasm::LiteralArray *litArray,
448 const panda_file::LiteralTag &tag, const panda_file::LiteralDataAccessor::LiteralValue &value)
449 {
450 panda_file::File::EntityId id(std::get<uint32_t>(value));
451 auto sp = pfile->GetSpanFromId(id);
452 auto len = panda_file::helpers::Read<sizeof(uint32_t)>(&sp);
453
454 for (size_t i = 0; i < len; i++) {
455 pandasm::LiteralArray::Literal lit;
456 lit.tag = tag;
457 lit.value = bit_cast<T>(panda_file::helpers::Read<sizeof(T)>(&sp));
458 litArray->literals.push_back(lit);
459 }
460 }
461
FillLiteralArrayTyped(const panda_file::File * pfile,pandasm::LiteralArray & litArray,const panda_file::LiteralTag & tag,const panda_file::LiteralDataAccessor::LiteralValue & value)462 static void FillLiteralArrayTyped(const panda_file::File *pfile, pandasm::LiteralArray &litArray,
463 const panda_file::LiteralTag &tag,
464 const panda_file::LiteralDataAccessor::LiteralValue &value)
465 {
466 switch (tag) {
467 case panda_file::LiteralTag::ARRAY_U1: {
468 FillLiteralArrayData<bool>(pfile, &litArray, tag, value);
469 break;
470 }
471 case panda_file::LiteralTag::ARRAY_I8:
472 case panda_file::LiteralTag::ARRAY_U8: {
473 FillLiteralArrayData<uint8_t>(pfile, &litArray, tag, value);
474 break;
475 }
476 case panda_file::LiteralTag::ARRAY_I16:
477 case panda_file::LiteralTag::ARRAY_U16: {
478 FillLiteralArrayData<uint16_t>(pfile, &litArray, tag, value);
479 break;
480 }
481 // in the case of ARRAY_STRING, the array stores strings ids
482 case panda_file::LiteralTag::ARRAY_STRING:
483 case panda_file::LiteralTag::ARRAY_I32:
484 case panda_file::LiteralTag::ARRAY_U32: {
485 FillLiteralArrayData<uint32_t>(pfile, &litArray, tag, value);
486 break;
487 }
488 case panda_file::LiteralTag::ARRAY_I64:
489 case panda_file::LiteralTag::ARRAY_U64: {
490 FillLiteralArrayData<uint64_t>(pfile, &litArray, tag, value);
491 break;
492 }
493 case panda_file::LiteralTag::ARRAY_F32: {
494 FillLiteralArrayData<float>(pfile, &litArray, tag, value);
495 break;
496 }
497 case panda_file::LiteralTag::ARRAY_F64: {
498 FillLiteralArrayData<double>(pfile, &litArray, tag, value);
499 break;
500 }
501 case panda_file::LiteralTag::TAGVALUE:
502 case panda_file::LiteralTag::ACCESSOR:
503 case panda_file::LiteralTag::NULLVALUE: {
504 break;
505 }
506 default: {
507 UNREACHABLE();
508 break;
509 }
510 }
511 }
512
GetLiteralArray(MethodPtr m,LiteralArrayId id) const513 ark::pandasm::LiteralArray PandaRuntimeInterface::GetLiteralArray(MethodPtr m, LiteralArrayId id) const
514 {
515 auto method = MethodCast(m);
516 auto pfile = method->GetPandaFile();
517 id = pfile->GetLiteralArrays()[id];
518 pandasm::LiteralArray litArray;
519
520 panda_file::LiteralDataAccessor litArrayAccessor(*pfile, pfile->GetLiteralArraysId());
521
522 litArrayAccessor.EnumerateLiteralVals(
523 panda_file::File::EntityId(id),
524 [&litArray, pfile](const panda_file::LiteralDataAccessor::LiteralValue &value,
525 const panda_file::LiteralTag &tag) { FillLiteralArrayTyped(pfile, litArray, tag, value); });
526
527 return litArray;
528 }
529
FindClassIdInFile(MethodPtr method,ClassPtr cls) const530 std::optional<RuntimeInterface::IdType> PandaRuntimeInterface::FindClassIdInFile(MethodPtr method, ClassPtr cls) const
531 {
532 auto klass = ClassCast(cls);
533 auto pfile = MethodCast(method)->GetPandaFile();
534 auto className = klass->GetName();
535 PandaString storage;
536 auto classId = pfile->GetClassId(ClassHelper::GetDescriptor(utf::CStringAsMutf8(className.c_str()), &storage));
537 if (classId.IsValid() && className == ClassHelper::GetName(pfile->GetStringData(classId).data)) {
538 return std::optional<RuntimeInterface::IdType>(classId.GetOffset());
539 }
540 return std::nullopt;
541 }
542
GetClassIdWithinFile(MethodPtr method,ClassPtr cls) const543 RuntimeInterface::IdType PandaRuntimeInterface::GetClassIdWithinFile(MethodPtr method, ClassPtr cls) const
544 {
545 auto classId = FindClassIdInFile(method, cls);
546 return classId ? classId.value() : 0;
547 }
548
GetLiteralArrayClassIdWithinFile(PandaRuntimeInterface::MethodPtr method,panda_file::LiteralTag tag) const549 RuntimeInterface::IdType PandaRuntimeInterface::GetLiteralArrayClassIdWithinFile(
550 PandaRuntimeInterface::MethodPtr method, panda_file::LiteralTag tag) const
551 {
552 ScopedMutatorLock lock;
553 ErrorHandler handler;
554 auto ctx = Runtime::GetCurrent()->GetLanguageContext(*MethodCast(method));
555 auto cls = Runtime::GetCurrent()->GetClassRootForLiteralTag(
556 *Runtime::GetCurrent()->GetClassLinker()->GetExtension(ctx), tag);
557
558 auto pfile = MethodCast(method)->GetPandaFile();
559 auto className = cls->GetName();
560 for (decltype(auto) classRawId : pfile->GetClasses()) {
561 auto classId = panda_file::File::EntityId(classRawId);
562 if (classId.IsValid() && className == ClassHelper::GetName(pfile->GetStringData(classId).data)) {
563 return classId.GetOffset();
564 }
565 }
566 UNREACHABLE();
567 }
568
CanUseTlabForClass(ClassPtr klass) const569 bool PandaRuntimeInterface::CanUseTlabForClass(ClassPtr klass) const
570 {
571 auto cls = ClassCast(klass);
572 return !Thread::GetCurrent()->GetVM()->GetHeapManager()->IsObjectFinalized(cls) && !cls->IsVariableSize() &&
573 cls->IsInstantiable();
574 }
575
GetTLABMaxSize() const576 size_t PandaRuntimeInterface::GetTLABMaxSize() const
577 {
578 return Thread::GetCurrent()->GetVM()->GetHeapManager()->GetTLABMaxAllocSize();
579 }
580
CanScalarReplaceObject(ClassPtr klass) const581 bool PandaRuntimeInterface::CanScalarReplaceObject(ClassPtr klass) const
582 {
583 auto cls = ClassCast(klass);
584 auto ctx = Runtime::GetCurrent()->GetLanguageContext(*cls);
585 return Runtime::GetCurrent()->GetClassLinker()->GetExtension(ctx)->CanScalarReplaceObject(cls);
586 }
587
ResolveType(PandaRuntimeInterface::MethodPtr method,size_t id) const588 PandaRuntimeInterface::ClassPtr PandaRuntimeInterface::ResolveType(PandaRuntimeInterface::MethodPtr method,
589 size_t id) const
590 {
591 ScopedMutatorLock lock;
592 ErrorHandler handler;
593 auto klass = Runtime::GetCurrent()->GetClassLinker()->GetClass(*MethodCast(method), panda_file::File::EntityId(id),
594 &handler);
595 return klass;
596 }
597
IsClassInitialized(uintptr_t klass) const598 bool PandaRuntimeInterface::IsClassInitialized(uintptr_t klass) const
599 {
600 return TypeCast(klass)->IsInitialized();
601 }
602
GetManagedType(uintptr_t klass) const603 uintptr_t PandaRuntimeInterface::GetManagedType(uintptr_t klass) const
604 {
605 return reinterpret_cast<uintptr_t>(TypeCast(klass)->GetManagedObject());
606 }
607
GetFieldType(FieldPtr field) const608 compiler::DataType::Type PandaRuntimeInterface::GetFieldType(FieldPtr field) const
609 {
610 return ToCompilerType(FieldCast(field)->GetType());
611 }
612
GetArrayComponentType(ClassPtr klass) const613 compiler::DataType::Type PandaRuntimeInterface::GetArrayComponentType(ClassPtr klass) const
614 {
615 return ToCompilerType(ClassCast(klass)->GetComponentType()->GetType());
616 }
617
GetFieldTypeById(MethodPtr parentMethod,IdType id) const618 compiler::DataType::Type PandaRuntimeInterface::GetFieldTypeById(MethodPtr parentMethod, IdType id) const
619 {
620 auto *pf = MethodCast(parentMethod)->GetPandaFile();
621 panda_file::FieldDataAccessor fda(*pf, panda_file::File::EntityId(id));
622 return ToCompilerType(panda_file::Type::GetTypeFromFieldEncoding(fda.GetType()));
623 }
624
GetFieldValueTypeId(MethodPtr method,IdType id) const625 compiler::RuntimeInterface::IdType PandaRuntimeInterface::GetFieldValueTypeId(MethodPtr method, IdType id) const
626 {
627 auto *pf = MethodCast(method)->GetPandaFile();
628 auto typeId = panda_file::FieldDataAccessor::GetTypeId(*pf, panda_file::File::EntityId(id));
629 return typeId.GetOffset();
630 }
631
GetClassForField(FieldPtr field) const632 RuntimeInterface::ClassPtr PandaRuntimeInterface::GetClassForField(FieldPtr field) const
633 {
634 return FieldCast(field)->GetClass();
635 }
636
GetArrayElementSize(MethodPtr method,IdType id) const637 uint32_t PandaRuntimeInterface::GetArrayElementSize(MethodPtr method, IdType id) const
638 {
639 auto *pf = MethodCast(method)->GetPandaFile();
640 auto *descriptor = pf->GetStringData(panda_file::File::EntityId(id)).data;
641 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
642 ASSERT(descriptor[0] == '[');
643 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
644 return Class::GetTypeSize(panda_file::Type::GetTypeIdBySignature(static_cast<char>(descriptor[1])));
645 }
646
GetMaxArrayLength(ClassPtr klass) const647 uint32_t PandaRuntimeInterface::GetMaxArrayLength(ClassPtr klass) const
648 {
649 ScopedMutatorLock lock;
650 if (ClassCast(klass)->IsArrayClass()) {
651 return INT32_MAX / ClassCast(klass)->GetComponentSize();
652 }
653 return INT32_MAX;
654 }
655
GetPointerToConstArrayData(MethodPtr method,IdType id) const656 uintptr_t PandaRuntimeInterface::GetPointerToConstArrayData(MethodPtr method, IdType id) const
657 {
658 auto *pf = MethodCast(method)->GetPandaFile();
659 return Runtime::GetCurrent()->GetPointerToConstArrayData(*pf, pf->GetLiteralArrays()[id]);
660 }
661
GetOffsetToConstArrayData(MethodPtr method,IdType id) const662 size_t PandaRuntimeInterface::GetOffsetToConstArrayData(MethodPtr method, IdType id) const
663 {
664 auto *pf = MethodCast(method)->GetPandaFile();
665 auto offset = Runtime::GetCurrent()->GetPointerToConstArrayData(*pf, pf->GetLiteralArrays()[id]) -
666 reinterpret_cast<uintptr_t>(pf->GetBase());
667 return static_cast<size_t>(offset);
668 }
669
GetFieldOffset(FieldPtr field) const670 size_t PandaRuntimeInterface::GetFieldOffset(FieldPtr field) const
671 {
672 if (!HasFieldMetadata(field)) {
673 return reinterpret_cast<uintptr_t>(field) >> 1U;
674 }
675 return FieldCast(field)->GetOffset();
676 }
677
GetFieldByOffset(size_t offset) const678 RuntimeInterface::FieldPtr PandaRuntimeInterface::GetFieldByOffset(size_t offset) const
679 {
680 ASSERT(MinimumBitsToStore(offset) < std::numeric_limits<uintptr_t>::digits);
681 return reinterpret_cast<FieldPtr>((offset << 1U) | 1U);
682 }
683
GetFieldClass(FieldPtr field) const684 uintptr_t PandaRuntimeInterface::GetFieldClass(FieldPtr field) const
685 {
686 return reinterpret_cast<uintptr_t>(FieldCast(field)->GetClass());
687 }
688
IsFieldVolatile(FieldPtr field) const689 bool PandaRuntimeInterface::IsFieldVolatile(FieldPtr field) const
690 {
691 return FieldCast(field)->IsVolatile();
692 }
693
IsFieldFinal(FieldPtr field) const694 bool PandaRuntimeInterface::IsFieldFinal(FieldPtr field) const
695 {
696 return FieldCast(field)->IsFinal();
697 }
698
IsFieldReadonly(FieldPtr field) const699 bool PandaRuntimeInterface::IsFieldReadonly(FieldPtr field) const
700 {
701 return FieldCast(field)->IsReadonly();
702 }
703
HasFieldMetadata(FieldPtr field) const704 bool PandaRuntimeInterface::HasFieldMetadata(FieldPtr field) const
705 {
706 return (reinterpret_cast<uintptr_t>(field) & 1U) == 0;
707 }
708
GetStaticFieldValue(FieldPtr fieldPtr) const709 uint64_t PandaRuntimeInterface::GetStaticFieldValue(FieldPtr fieldPtr) const
710 {
711 auto *field = FieldCast(fieldPtr);
712 auto type = GetFieldType(fieldPtr);
713 auto klass = field->GetClass();
714 ASSERT(compiler::DataType::GetCommonType(type) == compiler::DataType::INT64);
715 // NB: must be sign-extended for signed types at call-site
716 switch (compiler::DataType::ShiftByType(type, Arch::NONE)) {
717 case 0U:
718 return klass->GetFieldPrimitive<uint8_t>(*field);
719 case 1U:
720 return klass->GetFieldPrimitive<uint16_t>(*field);
721 case 2U:
722 return klass->GetFieldPrimitive<uint32_t>(*field);
723 case 3U:
724 return klass->GetFieldPrimitive<uint64_t>(*field);
725 default:
726 UNREACHABLE();
727 }
728 }
729
GetFieldId(FieldPtr field) const730 RuntimeInterface::FieldId PandaRuntimeInterface::GetFieldId(FieldPtr field) const
731 {
732 return FieldCast(field)->GetFileId().GetOffset();
733 }
734
GetPreType() const735 ark::mem::BarrierType PandaRuntimeInterface::GetPreType() const
736 {
737 return Thread::GetCurrent()->GetBarrierSet()->GetPreType();
738 }
739
GetPostType() const740 ark::mem::BarrierType PandaRuntimeInterface::GetPostType() const
741 {
742 return Thread::GetCurrent()->GetBarrierSet()->GetPostType();
743 }
744
GetBarrierOperand(ark::mem::BarrierPosition barrierPosition,std::string_view operandName) const745 ark::mem::BarrierOperand PandaRuntimeInterface::GetBarrierOperand(ark::mem::BarrierPosition barrierPosition,
746 std::string_view operandName) const
747 {
748 return Thread::GetCurrent()->GetBarrierSet()->GetBarrierOperand(barrierPosition, operandName);
749 }
750
GetFunctionTargetOffset(Arch arch) const751 uint32_t PandaRuntimeInterface::GetFunctionTargetOffset([[maybe_unused]] Arch arch) const
752 {
753 // NOTE(wengchangcheng): return offset of method in JSFunction
754 return 0;
755 }
756
GetNativePointerTargetOffset(Arch arch) const757 uint32_t PandaRuntimeInterface::GetNativePointerTargetOffset(Arch arch) const
758 {
759 return cross_values::GetCoretypesNativePointerExternalPointerOffset(arch);
760 }
761
AddDependency(PandaRuntimeInterface::MethodPtr callee,RuntimeInterface::MethodPtr caller)762 void ClassHierarchyAnalysisWrapper::AddDependency(PandaRuntimeInterface::MethodPtr callee,
763 RuntimeInterface::MethodPtr caller)
764 {
765 Runtime::GetCurrent()->GetCha()->AddDependency(MethodCast(callee), MethodCast(caller));
766 }
767
768 /// With 'no-async-jit' compilation inside of c2i bridge can forced and it can trigger GC
HasSafepointDuringCall() const769 bool PandaRuntimeInterface::HasSafepointDuringCall() const
770 {
771 #ifdef PANDA_PRODUCT_BUILD
772 return false;
773 #else
774 if (Runtime::GetOptions().IsArkAot()) {
775 return false;
776 }
777 return Runtime::GetOptions().IsNoAsyncJit();
778 #endif
779 }
780
CreateCompilerThread()781 RuntimeInterface::ThreadPtr PandaRuntimeInterface::CreateCompilerThread()
782 {
783 ASSERT(Thread::GetCurrent() != nullptr);
784 auto allocator = Runtime::GetCurrent()->GetInternalAllocator();
785 return allocator->New<Thread>(PandaVM::GetCurrent(), Thread::ThreadType::THREAD_TYPE_COMPILER);
786 }
787
DestroyCompilerThread(ThreadPtr thread)788 void PandaRuntimeInterface::DestroyCompilerThread(ThreadPtr thread)
789 {
790 ASSERT(thread != nullptr);
791 auto allocator = Runtime::GetCurrent()->GetInternalAllocator();
792 allocator->Delete(static_cast<Thread *>(thread));
793 }
794
GetClasses(PandaRuntimeInterface::MethodPtr m,uintptr_t pc,ArenaVector<RuntimeInterface::ClassPtr> * classes)795 InlineCachesWrapper::CallKind InlineCachesWrapper::GetClasses(PandaRuntimeInterface::MethodPtr m, uintptr_t pc,
796 ArenaVector<RuntimeInterface::ClassPtr> *classes)
797 {
798 ASSERT(classes != nullptr);
799 classes->clear();
800 auto method = static_cast<Method *>(m);
801 auto profilingData = method->GetProfilingData();
802 if (profilingData == nullptr) {
803 return CallKind::UNKNOWN;
804 }
805 auto ic = profilingData->FindInlineCache(pc);
806 if (ic == nullptr) {
807 return CallKind::UNKNOWN;
808 }
809 auto icClasses = ic->GetClassesCopy();
810 classes->insert(classes->end(), icClasses.begin(), icClasses.end());
811 if (classes->empty()) {
812 return CallKind::UNKNOWN;
813 }
814 if (classes->size() == 1) {
815 return CallKind::MONOMORPHIC;
816 }
817 if (CallSiteInlineCache::IsMegamorphic(reinterpret_cast<Class *>((*classes)[0]))) {
818 return CallKind::MEGAMORPHIC;
819 }
820 return CallKind::POLYMORPHIC;
821 }
822
AddTableSlot(RuntimeInterface::MethodPtr method,uint32_t typeId,SlotKind kind)823 bool UnresolvedTypesWrapper::AddTableSlot(RuntimeInterface::MethodPtr method, uint32_t typeId, SlotKind kind)
824 {
825 std::pair<uint32_t, UnresolvedTypesInterface::SlotKind> key {typeId, kind};
826 if (slots_.find(method) == slots_.end()) {
827 slots_[method][key] = 0;
828 return true;
829 }
830 auto &table = slots_.at(method);
831 if (table.find(key) == table.end()) {
832 table[key] = 0;
833 return true;
834 }
835 return false;
836 }
837
GetTableSlot(RuntimeInterface::MethodPtr method,uint32_t typeId,SlotKind kind) const838 uintptr_t UnresolvedTypesWrapper::GetTableSlot(RuntimeInterface::MethodPtr method, uint32_t typeId, SlotKind kind) const
839 {
840 ASSERT(slots_.find(method) != slots_.end());
841 auto &table = slots_.at(method);
842 ASSERT(table.find({typeId, kind}) != table.end());
843 return reinterpret_cast<uintptr_t>(&table.at({typeId, kind}));
844 }
845
CompileMethod(Method * method,uintptr_t bytecodeOffset,bool osr,TaggedValue func)846 bool Compiler::CompileMethod(Method *method, uintptr_t bytecodeOffset, bool osr, TaggedValue func)
847 {
848 if (method->IsAbstract()) {
849 return false;
850 }
851
852 if (osr && GetOsrCode(method) != nullptr) {
853 ASSERT(method == ManagedThread::GetCurrent()->GetCurrentFrame()->GetMethod());
854 ASSERT(method->HasCompiledCode());
855 return OsrEntry(bytecodeOffset, GetOsrCode(method));
856 }
857 // In case if some thread raise compilation when another already compiled it, we just exit.
858 if (method->HasCompiledCode() && !osr) {
859 return false;
860 }
861 bool ctxOsr = method->HasCompiledCode() ? osr : false;
862 if (method->AtomicSetCompilationStatus(ctxOsr ? Method::COMPILED : Method::NOT_COMPILED, Method::WAITING)) {
863 CompilerTask ctx {method, ctxOsr, ManagedThread::GetCurrent()->GetVM()};
864 AddTask(std::move(ctx), func);
865 }
866 if (noAsyncJit_) {
867 auto status = method->GetCompilationStatus();
868 for (; (status == Method::WAITING) || (status == Method::COMPILATION);
869 status = method->GetCompilationStatus()) {
870 if (compilerWorker_ == nullptr || compilerWorker_->IsWorkerJoined()) {
871 // JIT thread is destroyed, wait makes no sence
872 return false;
873 }
874 auto thread = MTManagedThread::GetCurrent();
875 // NOTE(asoldatov): Remove this workaround for invoking compiler from ECMA VM
876 if (thread != nullptr) {
877 static constexpr uint64_t SLEEP_MS = 10;
878 thread->TimedWait(ThreadStatus::IS_COMPILER_WAITING, SLEEP_MS, 0);
879 }
880 }
881 }
882 return false;
883 }
884
885 template <compiler::TaskRunnerMode RUNNER_MODE>
CompileMethodLocked(compiler::CompilerTaskRunner<RUNNER_MODE> taskRunner)886 void Compiler::CompileMethodLocked(compiler::CompilerTaskRunner<RUNNER_MODE> taskRunner)
887 {
888 os::memory::LockHolder lock(compilationLock_);
889 StartCompileMethod<RUNNER_MODE>(std::move(taskRunner));
890 }
891
892 template <compiler::TaskRunnerMode RUNNER_MODE>
StartCompileMethod(compiler::CompilerTaskRunner<RUNNER_MODE> taskRunner)893 void Compiler::StartCompileMethod(compiler::CompilerTaskRunner<RUNNER_MODE> taskRunner)
894 {
895 ASSERT(runtimeIface_ != nullptr);
896 auto &taskCtx = taskRunner.GetContext();
897 auto *method = taskCtx.GetMethod();
898
899 method->ResetHotnessCounter();
900
901 if (IsCompilationExpired(method, taskCtx.IsOsr())) {
902 ASSERT(!noAsyncJit_);
903 compiler::CompilerTaskRunner<RUNNER_MODE>::EndTask(std::move(taskRunner), false);
904 return;
905 }
906
907 mem::MemStatsType *memStats = taskCtx.GetVM()->GetMemStats();
908
909 auto allocator = std::make_unique<ark::ArenaAllocator>(ark::SpaceType::SPACE_TYPE_COMPILER, memStats);
910 auto localAllocator = std::make_unique<ark::ArenaAllocator>(ark::SpaceType::SPACE_TYPE_COMPILER, memStats, true);
911
912 if constexpr (RUNNER_MODE == compiler::BACKGROUND_MODE) {
913 taskCtx.SetAllocator(std::move(allocator));
914 taskCtx.SetLocalAllocator(std::move(localAllocator));
915 } else {
916 taskCtx.SetAllocator(allocator.get());
917 taskCtx.SetLocalAllocator(localAllocator.get());
918 }
919
920 taskRunner.AddFinalize([](compiler::CompilerContext<RUNNER_MODE> &compilerCtx) {
921 auto *compiledMethod = compilerCtx.GetMethod();
922 auto isCompiled = compilerCtx.GetCompilationStatus();
923 if (isCompiled) {
924 // Check that method was not deoptimized
925 compiledMethod->AtomicSetCompilationStatus(Method::COMPILATION, Method::COMPILED);
926 return;
927 }
928 // If deoptimization occurred during OSR compilation, the compilation returns false.
929 // For the case we need reset compiation status
930 if (compilerCtx.IsOsr()) {
931 compiledMethod->SetCompilationStatus(Method::NOT_COMPILED);
932 return;
933 }
934 // Failure during compilation, should we retry later?
935 compiledMethod->SetCompilationStatus(Method::FAILED);
936 });
937
938 compiler::JITCompileMethod<RUNNER_MODE>(runtimeIface_, codeAllocator_, &gdbDebugInfoAllocator_, jitStats_,
939 std::move(taskRunner));
940 }
941
JoinWorker()942 void Compiler::JoinWorker()
943 {
944 if (compilerWorker_ != nullptr) {
945 compilerWorker_->JoinWorker();
946 }
947 #ifdef PANDA_COMPILER_DEBUG_INFO
948 if (!Runtime::GetOptions().IsArkAot() && compiler::g_options.IsCompilerEmitDebugInfo()) {
949 compiler::CleanJitDebugCode();
950 }
951 #endif
952 }
953
GetNonMovableString(MethodPtr method,StringId id) const954 ObjectPointerType PandaRuntimeInterface::GetNonMovableString(MethodPtr method, StringId id) const
955 {
956 auto vm = Runtime::GetCurrent()->GetPandaVM();
957 auto pf = MethodCast(method)->GetPandaFile();
958 return ToObjPtrType(vm->GetNonMovableString(*pf, panda_file::File::EntityId {id}));
959 }
960
961 #ifndef PANDA_PRODUCT_BUILD
CompileMethodImpl(coretypes::String * fullMethodName,panda_file::SourceLang sourceLang)962 uint8_t CompileMethodImpl(coretypes::String *fullMethodName, panda_file::SourceLang sourceLang)
963 {
964 auto name = ConvertToString(fullMethodName);
965 auto *classLinker = Runtime::GetCurrent()->GetClassLinker();
966
967 size_t pos = name.find_last_of("::");
968 if (pos == std::string_view::npos) {
969 return 1;
970 }
971 auto className = PandaString(name.substr(0, pos - 1));
972 auto methodName = PandaString(name.substr(pos + 1));
973
974 PandaString descriptor;
975 auto classNameBytes = ClassHelper::GetDescriptor(utf::CStringAsMutf8(className.c_str()), &descriptor);
976 auto methodNameBytes = utf::CStringAsMutf8(methodName.c_str());
977
978 ClassLinkerExtension *ext = classLinker->GetExtension(sourceLang);
979 Class *cls = classLinker->GetClass(classNameBytes, true, ext->GetBootContext());
980 if (cls == nullptr) {
981 static constexpr uint8_t CLASS_IS_NULL = 2;
982 return CLASS_IS_NULL;
983 }
984
985 auto method = cls->GetDirectMethod(methodNameBytes);
986 if (method == nullptr) {
987 static constexpr uint8_t METHOD_IS_NULL = 3;
988 return METHOD_IS_NULL;
989 }
990
991 if (method->IsAbstract()) {
992 static constexpr uint8_t ABSTRACT_ERROR = 4;
993 return ABSTRACT_ERROR;
994 }
995 if (method->HasCompiledCode()) {
996 return 0;
997 }
998 auto *compiler = Runtime::GetCurrent()->GetPandaVM()->GetCompiler();
999 auto status = method->GetCompilationStatus();
1000 for (; (status != Method::COMPILED) && (status != Method::FAILED); status = method->GetCompilationStatus()) {
1001 if (status == Method::NOT_COMPILED) {
1002 ASSERT(!method->HasCompiledCode());
1003 compiler->CompileMethod(method, 0, false, TaggedValue::Hole());
1004 }
1005 static constexpr uint64_t SLEEP_MS = 10;
1006 MTManagedThread::GetCurrent()->TimedWait(ThreadStatus::IS_COMPILER_WAITING, SLEEP_MS, 0);
1007 }
1008 static constexpr uint8_t COMPILATION_FAILED = 5;
1009 return (status == Method::COMPILED ? 0 : COMPILATION_FAILED);
1010 }
1011 #endif // PANDA_PRODUCT_BUILD
1012
1013 template void Compiler::CompileMethodLocked<compiler::BACKGROUND_MODE>(
1014 compiler::CompilerTaskRunner<compiler::BACKGROUND_MODE>);
1015 template void Compiler::CompileMethodLocked<compiler::INPLACE_MODE>(
1016 compiler::CompilerTaskRunner<compiler::INPLACE_MODE>);
1017 template void Compiler::StartCompileMethod<compiler::BACKGROUND_MODE>(
1018 compiler::CompilerTaskRunner<compiler::BACKGROUND_MODE>);
1019 template void Compiler::StartCompileMethod<compiler::INPLACE_MODE>(
1020 compiler::CompilerTaskRunner<compiler::INPLACE_MODE>);
1021
1022 } // namespace ark
1023