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