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