• 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 #ifndef PANDA_RUNTIME_COMPILER_H_
16 #define PANDA_RUNTIME_COMPILER_H_
17 
18 #include "compiler/compile_method.h"
19 #include "compiler/compiler_task_runner.h"
20 #include "compiler/optimizer/ir/runtime_interface.h"
21 #include "libpandabase/mem/code_allocator.h"
22 #include "libpandabase/os/mutex.h"
23 #include "runtime/entrypoints/entrypoints.h"
24 #include "runtime/include/hclass.h"
25 #include "runtime/include/compiler_interface.h"
26 #include "runtime/include/coretypes/array.h"
27 #include "runtime/include/coretypes/tagged_value.h"
28 #include "runtime/include/locks.h"
29 #include "runtime/include/mem/panda_containers.h"
30 #include "runtime/include/method.h"
31 #include "runtime/include/runtime_options.h"
32 #include "runtime/interpreter/frame.h"
33 #include "runtime/mem/gc/gc_barrier_set.h"
34 #include "runtime/mem/tlab.h"
35 #include "runtime/compiler_thread_pool_worker.h"
36 #include "runtime/compiler_task_manager_worker.h"
37 #include "runtime/include/thread.h"
38 
39 #include "runtime/osr.h"
40 
41 namespace ark {
42 
43 using compiler::RuntimeInterface;
44 using compiler::UnresolvedTypesInterface;
45 
MethodCast(RuntimeInterface::MethodPtr method)46 inline ark::Method *MethodCast(RuntimeInterface::MethodPtr method)
47 {
48     return static_cast<ark::Method *>(method);
49 }
50 
51 struct ScopedMutatorLock : public os::memory::ReadLockHolder<MutatorLock> {
ScopedMutatorLockScopedMutatorLock52     ScopedMutatorLock() : os::memory::ReadLockHolder<MutatorLock>(*PandaVM::GetCurrent()->GetMutatorLock()) {}
53 };
54 
55 class PANDA_PUBLIC_API ClassHierarchyAnalysisWrapper : public compiler::IClassHierarchyAnalysis {
56 public:
GetSingleImplementation(RuntimeInterface::MethodPtr method)57     RuntimeInterface::MethodPtr GetSingleImplementation(RuntimeInterface::MethodPtr method) override
58     {
59         return static_cast<Method *>(method)->GetSingleImplementation();
60     }
IsSingleImplementation(RuntimeInterface::MethodPtr method)61     bool IsSingleImplementation(RuntimeInterface::MethodPtr method) override
62     {
63         return static_cast<Method *>(method)->HasSingleImplementation();
64     }
65     void AddDependency(RuntimeInterface::MethodPtr callee, RuntimeInterface::MethodPtr caller) override;
66 };
67 
68 class PANDA_PUBLIC_API InlineCachesWrapper : public compiler::InlineCachesInterface {
69 public:
70     CallKind GetClasses(RuntimeInterface::MethodPtr m, uintptr_t pc,
71                         ArenaVector<RuntimeInterface::ClassPtr> *classes) override;
72 };
73 
74 class PANDA_PUBLIC_API UnresolvedTypesWrapper : public UnresolvedTypesInterface {
75 public:
76     bool AddTableSlot(RuntimeInterface::MethodPtr method, uint32_t typeId, SlotKind kind) override;
77     uintptr_t GetTableSlot(RuntimeInterface::MethodPtr method, uint32_t typeId, SlotKind kind) const override;
78 
79 private:
80     PandaMap<RuntimeInterface::MethodPtr, PandaMap<std::pair<uint32_t, SlotKind>, uintptr_t>> slots_;
81 };
82 
83 class PANDA_PUBLIC_API PandaRuntimeInterface : public RuntimeInterface {
84 public:
GetRuntimeEntry()85     void *GetRuntimeEntry() override
86     {
87         return nullptr;
88     }
89 
GetCha()90     compiler::IClassHierarchyAnalysis *GetCha() override
91     {
92         return &cha_;
93     }
94 
GetInlineCaches()95     compiler::InlineCachesInterface *GetInlineCaches() override
96     {
97         return &inlineCaches_;
98     }
99 
GetUnresolvedTypes()100     compiler::UnresolvedTypesInterface *GetUnresolvedTypes() override
101     {
102         return &unresolvedTypes_;
103     }
104 
GetReturnReasonOk()105     unsigned GetReturnReasonOk() const override
106     {
107         return static_cast<unsigned>(CompilerInterface::ReturnReason::RET_OK);
108     }
GetReturnReasonDeopt()109     unsigned GetReturnReasonDeopt() const override
110     {
111         return static_cast<unsigned>(CompilerInterface::ReturnReason::RET_DEOPTIMIZATION);
112     }
113 
ClassCast(ClassPtr cls)114     ark::Class *ClassCast(ClassPtr cls) const
115     {
116         return static_cast<ark::Class *>(cls);
117     }
118 
GetStackOverflowCheckOffset()119     size_t GetStackOverflowCheckOffset() const override
120     {
121         return ManagedThread::GetStackOverflowCheckOffset();
122     }
123 
124     /**********************************************************************************/
125     /// Binary file information
GetBinaryFileForMethod(MethodPtr method)126     BinaryFilePtr GetBinaryFileForMethod(MethodPtr method) const override
127     {
128         return const_cast<panda_file::File *>(MethodCast(method)->GetPandaFile());
129     }
130 
131     MethodId ResolveMethodIndex(MethodPtr parentMethod, MethodIndex index) const override;
132 
133     FieldId ResolveFieldIndex(MethodPtr parentMethod, FieldIndex index) const override;
134 
135     IdType ResolveTypeIndex(MethodPtr parentMethod, TypeIndex index) const override;
136 
137     /**********************************************************************************/
138     /// Method information
139     MethodPtr GetMethodById(MethodPtr parentMethod, MethodId id) const override;
140 
141     MethodId GetMethodId(MethodPtr method) const override;
142 
143     IntrinsicId GetIntrinsicId([[maybe_unused]] MethodPtr method) const override;
144 
145     uint64_t GetUniqMethodId(MethodPtr method) const override;
146 
147     MethodPtr ResolveVirtualMethod(ClassPtr cls, MethodPtr method) const override;
148 
149     MethodPtr ResolveInterfaceMethod(ClassPtr cls, MethodPtr method) const override;
150 
GetMethodReturnType(MethodPtr method)151     compiler::DataType::Type GetMethodReturnType(MethodPtr method) const override
152     {
153         return ToCompilerType(MethodCast(method)->GetEffectiveReturnType());
154     }
155 
156     IdType GetMethodReturnTypeId(MethodPtr method) const override;
157     IdType GetMethodArgReferenceTypeId(MethodPtr method, uint16_t num) const override;
158 
GetMethodTotalArgumentType(MethodPtr method,size_t index)159     compiler::DataType::Type GetMethodTotalArgumentType(MethodPtr method, size_t index) const override
160     {
161         return ToCompilerType(MethodCast(method)->GetEffectiveArgType(index));
162     }
GetMethodTotalArgumentsCount(MethodPtr method)163     size_t GetMethodTotalArgumentsCount(MethodPtr method) const override
164     {
165         return MethodCast(method)->GetNumArgs();
166     }
167 
168     bool IsMemoryBarrierRequired(MethodPtr method) const override;
169 
170     compiler::DataType::Type GetMethodReturnType(MethodPtr parentMethod, MethodId id) const override;
171 
172     compiler::DataType::Type GetMethodArgumentType(MethodPtr parentMethod, MethodId id, size_t index) const override;
173 
174     size_t GetMethodArgumentsCount(MethodPtr parentMethod, MethodId id) const override;
GetMethodArgumentsCount(MethodPtr method)175     size_t GetMethodArgumentsCount(MethodPtr method) const override
176     {
177         return MethodCast(method)->GetNumArgs();
178     }
GetMethodRegistersCount(MethodPtr method)179     size_t GetMethodRegistersCount(MethodPtr method) const override
180     {
181         return MethodCast(method)->GetNumVregs();
182     }
GetMethodCode(MethodPtr method)183     const uint8_t *GetMethodCode(MethodPtr method) const override
184     {
185         return MethodCast(method)->GetInstructions();
186     }
GetMethodCodeSize(MethodPtr method)187     size_t GetMethodCodeSize(MethodPtr method) const override
188     {
189         return MethodCast(method)->GetCodeSize();
190     }
GetMethodSourceLanguage(MethodPtr method)191     SourceLanguage GetMethodSourceLanguage(MethodPtr method) const override
192     {
193         return static_cast<SourceLanguage>(MethodCast(method)->GetClass()->GetSourceLang());
194     }
SetCompiledEntryPoint(MethodPtr method,void * ep)195     void SetCompiledEntryPoint(MethodPtr method, void *ep) override
196     {
197         MethodCast(method)->SetCompiledEntryPoint(ep);
198     }
TrySetOsrCode(MethodPtr method,void * ep)199     bool TrySetOsrCode(MethodPtr method, void *ep) override
200     {
201         ScopedMutatorLock lock;
202         // Ignore OSR code if method was deoptimized during OSR compilation
203         if (!static_cast<const Method *>(method)->HasCompiledCode()) {
204             return false;
205         }
206         CompilerInterface *compiler = Thread::GetCurrent()->GetVM()->GetCompiler();
207         ASSERT(compiler->GetOsrCode(static_cast<const Method *>(method)) == nullptr);
208         compiler->SetOsrCode(static_cast<const Method *>(method), ep);
209         return true;
210     }
GetOsrCode(MethodPtr method)211     void *GetOsrCode(MethodPtr method) override
212     {
213         return Thread::GetCurrent()->GetVM()->GetCompiler()->GetOsrCode(static_cast<const Method *>(method));
214     }
HasCompiledCode(MethodPtr method)215     bool HasCompiledCode(MethodPtr method) override
216     {
217         return MethodCast(method)->HasCompiledCode();
218     }
219 
IsInstantiable(ClassPtr klass)220     bool IsInstantiable(ClassPtr klass) const override
221     {
222         return ClassCast(klass)->IsInstantiable();
223     }
224 
GetAccessFlagAbstractMask()225     uint32_t GetAccessFlagAbstractMask() const override
226     {
227         return ark::ACC_ABSTRACT;
228     }
229 
GetVTableIndex(MethodPtr method)230     uint32_t GetVTableIndex(MethodPtr method) const override
231     {
232         return MethodCast(method)->GetVTableIndex();
233     }
234 
GetClassIdForField(MethodPtr method,size_t fieldId)235     size_t GetClassIdForField(MethodPtr method, size_t fieldId) const override
236     {
237         auto fda =
238             panda_file::FieldDataAccessor(*MethodCast(method)->GetPandaFile(), panda_file::File::EntityId(fieldId));
239         return fda.GetClassId().GetOffset();
240     }
241 
GetClassIdForField(FieldPtr field)242     size_t GetClassIdForField(FieldPtr field) const override
243     {
244         return FieldCast(field)->GetClass()->GetFileId().GetOffset();
245     }
246 
247     ClassPtr GetClassForField(FieldPtr field) const override;
248 
GetClassIdForMethod(MethodPtr method)249     uint32_t GetClassIdForMethod(MethodPtr method) const override
250     {
251         auto mda = panda_file::MethodDataAccessor(*MethodCast(method)->GetPandaFile(), MethodCast(method)->GetFileId());
252         return mda.GetClassId().GetOffset();
253     }
254 
GetClassIdForMethod(MethodPtr parentMethod,size_t methodId)255     uint32_t GetClassIdForMethod(MethodPtr parentMethod, size_t methodId) const override
256     {
257         auto mda = panda_file::MethodDataAccessor(*MethodCast(parentMethod)->GetPandaFile(),
258                                                   panda_file::File::EntityId(methodId));
259         return mda.GetClassId().GetOffset();
260     }
261 
GetUniqClassId(ClassPtr klass)262     uint64_t GetUniqClassId(ClassPtr klass) const override
263     {
264         return ClassCast(klass)->GetUniqId();
265     }
266 
267     bool HasNativeException(MethodPtr method) const override;
268 
269     bool IsNecessarySwitchThreadState(MethodPtr method) const override;
270 
271     uint8_t GetStackReferenceMask() const override;
272 
273     bool CanNativeMethodUseObjects(MethodPtr method) const override;
274 
275     bool IsMethodExternal(MethodPtr parentMethod, MethodPtr calleeMethod) const override;
276 
277     bool IsClassExternal(MethodPtr method, ClassPtr calleeClass) const override;
278 
IsMethodIntrinsic(MethodPtr method)279     bool IsMethodIntrinsic(MethodPtr method) const override
280     {
281         return MethodCast(method)->IsIntrinsic();
282     }
283 
IsMethodAbstract(MethodPtr method)284     bool IsMethodAbstract(MethodPtr method) const override
285     {
286         return MethodCast(method)->IsAbstract();
287     }
288 
289     bool IsMethodIntrinsic(MethodPtr parentMethod, MethodId id) const override;
290 
IsMethodFinal(MethodPtr method)291     bool IsMethodFinal(MethodPtr method) const override
292     {
293         return MethodCast(method)->IsFinal();
294     }
295 
296     bool IsMethodStatic(MethodPtr parentMethod, MethodId id) const override;
297     bool IsMethodStatic(MethodPtr method) const override;
298 
IsMethodCanBeInlined(MethodPtr method)299     bool IsMethodCanBeInlined(MethodPtr method) const override
300     {
301         auto methodPtr = MethodCast(method);
302         const auto &options = Runtime::GetCurrent()->GetOptions();
303         if (verifier::VerificationModeFromString(options.GetVerificationMode()) ==
304                 verifier::VerificationMode::ON_THE_FLY &&
305             methodPtr->GetVerificationStage() != Method::VerificationStage::VERIFIED_OK) {
306             return false;
307         }
308         return !(methodPtr->IsIntrinsic() || methodPtr->IsNative() || methodPtr->IsAbstract());
309     }
310 
311     bool IsMethodNativeApi(MethodPtr method) const override;
312 
GetMethodNativePointer(MethodPtr method)313     void *GetMethodNativePointer(MethodPtr method) const override
314     {
315         auto *methodPtr = MethodCast(method);
316         return methodPtr->GetNativePointer();
317     }
318 
319     bool IsMethodStaticConstructor([[maybe_unused]] MethodPtr method) const override;
320 
GetFileName(MethodPtr method)321     std::string GetFileName(MethodPtr method) const override
322     {
323         return MethodCast(method)->GetPandaFile()->GetFilename();
324     }
325 
GetFullFileName(MethodPtr method)326     std::string GetFullFileName(MethodPtr method) const override
327     {
328         return MethodCast(method)->GetPandaFile()->GetFullFileName();
329     }
330 
GetClassNameFromMethod(MethodPtr method)331     std::string GetClassNameFromMethod(MethodPtr method) const override
332     {
333         ScopedMutatorLock lock;
334         return MethodCast(method)->GetClass()->GetName();
335     }
336 
GetClassName(ClassPtr cls)337     std::string GetClassName(ClassPtr cls) const override
338     {
339         ScopedMutatorLock lock;
340         return ClassCast(cls)->GetName();
341     }
342 
GetMethodName(MethodPtr method)343     std::string GetMethodName(MethodPtr method) const override
344     {
345         return utf::Mutf8AsCString(MethodCast(method)->GetName().data);
346     }
347 
GetLineNumberAndSourceFile(MethodPtr method,uint32_t pc)348     std::string GetLineNumberAndSourceFile(MethodPtr method, uint32_t pc) const override
349     {
350         return std::string(MethodCast(method)->GetLineNumberAndSourceFile(pc));
351     }
352 
GetBranchTakenCounter(MethodPtr method,uint32_t pc)353     int64_t GetBranchTakenCounter(MethodPtr method, uint32_t pc) const override
354     {
355         return MethodCast(method)->GetBranchTakenCounter(pc);
356     }
357 
GetBranchNotTakenCounter(MethodPtr method,uint32_t pc)358     int64_t GetBranchNotTakenCounter(MethodPtr method, uint32_t pc) const override
359     {
360         return MethodCast(method)->GetBranchNotTakenCounter(pc);
361     }
362 
GetThrowTakenCounter(MethodPtr method,uint32_t pc)363     int64_t GetThrowTakenCounter(MethodPtr method, uint32_t pc) const override
364     {
365         return MethodCast(method)->GetThrowTakenCounter(pc);
366     }
367 
GetMethodFullName(MethodPtr method,bool withSignature)368     std::string GetMethodFullName(MethodPtr method, bool withSignature) const override
369     {
370         return std::string(MethodCast(method)->GetFullName(withSignature));
371     }
372 
GetClass(MethodPtr method)373     ClassPtr GetClass(MethodPtr method) const override
374     {
375         ScopedMutatorLock lock;
376         return reinterpret_cast<ClassPtr>(MethodCast(method)->GetClass());
377     }
378 
379     std::string GetBytecodeString(MethodPtr method, uintptr_t pc) const override;
380 
381     ark::pandasm::LiteralArray GetLiteralArray(MethodPtr method, LiteralArrayId id) const override;
382 
383     bool IsInterfaceMethod(MethodPtr parentMethod, MethodId id) const override;
384 
385     bool IsInterfaceMethod(MethodPtr method) const override;
386 
IsInstanceConstructor(MethodPtr method)387     bool IsInstanceConstructor(MethodPtr method) const override
388     {
389         return MethodCast(method)->IsInstanceConstructor();
390     }
391 
IsDestroyed(MethodPtr method)392     bool IsDestroyed(MethodPtr method) const override
393     {
394         return MethodCast(method)->IsDestroyed();
395     }
396 
397     bool CanThrowException(MethodPtr method) const override;
398 
399     uint32_t FindCatchBlock(MethodPtr method, ClassPtr cls, uint32_t pc) const override;
400     Method *GetMethod(MethodPtr caller, RuntimeInterface::IdType id) const;
401 
402     /**********************************************************************************/
403     /// Thread information
404     ::ark::mem::BarrierType GetPreType() const override;
405 
406     ::ark::mem::BarrierType GetPostType() const override;
407 
408     ::ark::mem::BarrierOperand GetBarrierOperand(::ark::mem::BarrierPosition barrierPosition,
409                                                  std::string_view operandName) const override;
410 
411     /**********************************************************************************/
412     /// Array information
413     uint32_t GetArrayElementSize(MethodPtr method, IdType id) const override;
414 
415     uint32_t GetMaxArrayLength(ClassPtr klass) const override;
416 
417     uintptr_t GetPointerToConstArrayData(MethodPtr method, IdType id) const override;
418 
419     size_t GetOffsetToConstArrayData(MethodPtr method, IdType id) const override;
420 
421     ClassPtr GetArrayU16Class(MethodPtr method) const override;
422     ClassPtr GetArrayU8Class(MethodPtr method) const override;
423     /**********************************************************************************/
424     /// String information
IsCompressedStringsEnabled()425     bool IsCompressedStringsEnabled() const override
426     {
427         return ark::coretypes::String::GetCompressedStringsEnabled();
428     }
429 
430     ObjectPointerType GetNonMovableString(MethodPtr method, StringId id) const override;
431 
432     ClassPtr GetStringClass(MethodPtr method, uint32_t *typeId) const override;
433     ClassPtr GetNumberClass(MethodPtr method, const char *name, uint32_t *typeId) const override;
434 
GetStringValue(MethodPtr method,size_t id)435     std::string GetStringValue(MethodPtr method, size_t id) const override
436     {
437         ScopedMutatorLock lock;
438         panda_file::File::EntityId cid(id);
439         auto *pf = MethodCast(method)->GetPandaFile();
440         return utf::Mutf8AsCString(pf->GetStringData(cid).data);
441     }
442 
443     /**********************************************************************************/
444     /// TLAB information
445     size_t GetTLABMaxSize() const override;
446 
GetTLABAlignment()447     size_t GetTLABAlignment() const override
448     {
449         return DEFAULT_ALIGNMENT_IN_BYTES;
450     }
451 
IsTrackTlabAlloc()452     bool IsTrackTlabAlloc() const override
453     {
454         return ark::mem::PANDA_TRACK_TLAB_ALLOCATIONS ||
455                Logger::IsLoggingOn(Logger::Level::DEBUG, Logger::Component::MM_OBJECT_EVENTS);
456     }
457 
458     /**********************************************************************************/
459     /// Object information
460     ClassPtr GetClass(MethodPtr method, IdType id) const override;
461 
462     compiler::ClassType GetClassType(MethodPtr method, IdType id) const override;
463     compiler::ClassType GetClassType(ClassPtr klassPtr) const override;
464 
465     bool IsArrayClass(MethodPtr method, IdType id) const override;
466 
467     bool IsStringClass(MethodPtr method, IdType id) const override;
468 
IsArrayClass(ClassPtr cls)469     bool IsArrayClass(ClassPtr cls) const override
470     {
471         return ClassCast(cls)->IsArrayClass();
472     }
473 
474     ClassPtr GetArrayElementClass(ClassPtr cls) const override;
475 
476     bool CheckStoreArray(ClassPtr arrayCls, ClassPtr strCls) const override;
477 
478     bool IsAssignableFrom(ClassPtr cls1, ClassPtr cls2) const override;
479 
GetObjectHashedStatusBitNum()480     size_t GetObjectHashedStatusBitNum() const override
481     {
482         static_assert(MarkWord::MarkWordRepresentation::STATUS_SIZE == 2);
483         static_assert(MarkWord::MarkWordRepresentation::STATUS_HASHED == 2);
484         // preconditions above allow just check one bit
485         return MarkWord::MarkWordRepresentation::STATUS_SHIFT + 1;
486     }
487 
GetObjectHashShift()488     size_t GetObjectHashShift() const override
489     {
490         return MarkWord::MarkWordRepresentation::HASH_SHIFT;
491     }
492 
GetObjectHashMask()493     size_t GetObjectHashMask() const override
494     {
495         return MarkWord::MarkWordRepresentation::HASH_MASK;
496     }
497 
GetStringCtorType(MethodPtr ctorMethod)498     compiler::StringCtorType GetStringCtorType(MethodPtr ctorMethod) const override
499     {
500         return (std::strcmp(utf::Mutf8AsCString(MethodCast(ctorMethod)->GetRefArgType(1).data), "[C") == 0)
501                    ? compiler::StringCtorType::CHAR_ARRAY
502                    : compiler::StringCtorType::STRING;
503     }
504 
505     /**********************************************************************************/
506     /// Class information
GetClassInitializedValue()507     uint8_t GetClassInitializedValue() const override
508     {
509         return static_cast<uint8_t>(ark::Class::State::INITIALIZED);
510     }
511 
512     std::optional<IdType> FindClassIdInFile(MethodPtr method, ClassPtr cls) const;
513     IdType GetClassIdWithinFile(MethodPtr method, ClassPtr cls) const override;
514     IdType GetLiteralArrayClassIdWithinFile(MethodPtr method, panda_file::LiteralTag tag) const override;
515     bool CanUseTlabForClass(ClassPtr klass) const override;
516 
GetClassSize(ClassPtr klass)517     size_t GetClassSize(ClassPtr klass) const override
518     {
519         return ClassCast(klass)->GetObjectSize();
520     }
521 
522     bool CanScalarReplaceObject(ClassPtr klass) const override;
523 
524     /**********************************************************************************/
525     /// Field information
526 
527     FieldPtr ResolveField(MethodPtr method, size_t id, bool isStatic, bool allowExternal, uint32_t *classId) override;
528     compiler::DataType::Type GetFieldType(FieldPtr field) const override;
529     compiler::DataType::Type GetArrayComponentType(ClassPtr klass) const override;
530     compiler::DataType::Type GetFieldTypeById(MethodPtr parentMethod, IdType id) const override;
531     IdType GetFieldValueTypeId(MethodPtr method, IdType id) const override;
532     size_t GetFieldOffset(FieldPtr field) const override;
533     FieldPtr GetFieldByOffset(size_t offset) const override;
534     uintptr_t GetFieldClass(FieldPtr field) const override;
535     bool IsFieldVolatile(FieldPtr field) const override;
536     bool IsFieldFinal(FieldPtr field) const override;
537     bool IsFieldReadonly(FieldPtr field) const override;
538     bool HasFieldMetadata(FieldPtr field) const override;
539     uint64_t GetStaticFieldIntegerValue(FieldPtr fieldPtr) const override;
540     double GetStaticFieldFloatValue(FieldPtr fieldPtr) const override;
541 
GetFieldName(FieldPtr field)542     std::string GetFieldName(FieldPtr field) const override
543     {
544         return utf::Mutf8AsCString(FieldCast(field)->GetName().data);
545     }
546 
FieldCast(FieldPtr field)547     ark::Field *FieldCast(FieldPtr field) const
548     {
549         ASSERT(HasFieldMetadata(field));
550         return static_cast<ark::Field *>(field);
551     }
552 
553     FieldId GetFieldId(FieldPtr field) const override;
554     Field *GetField(MethodPtr method, RuntimeInterface::IdType id, bool isStatic) const;
555 
556     /**********************************************************************************/
557     /// Type information
558 
559     PandaRuntimeInterface::ClassPtr ResolveType(MethodPtr method, size_t id) const override;
560 
561     bool IsClassInitialized(uintptr_t klass) const override;
562 
IsClassFinal(ClassPtr klass)563     bool IsClassFinal(ClassPtr klass) const override
564     {
565         return ClassCast(klass)->IsFinal();
566     }
567 
IsInterface(ClassPtr klass)568     bool IsInterface(ClassPtr klass) const override
569     {
570         return ClassCast(klass)->IsInterface();
571     }
572 
573     uintptr_t GetManagedType(uintptr_t klass) const override;
574 
TypeCast(uintptr_t klass)575     ark::Class *TypeCast(uintptr_t klass) const
576     {
577         return reinterpret_cast<ark::Class *>(klass);
578     }
579 
GetReferenceTypeMask()580     uint8_t GetReferenceTypeMask() const override
581     {
582         return static_cast<uint8_t>(panda_file::Type::TypeId::REFERENCE);
583     }
584 
585     /**********************************************************************************/
586     /// Entrypoints
587     uintptr_t GetIntrinsicAddress(bool runtimeCall, SourceLanguage lang, IntrinsicId id) const override;
588 
589     /**********************************************************************************/
590     /// Dynamic object information
591 
592     uint32_t GetFunctionTargetOffset(Arch arch) const override;
593 
GetDynamicPrimitiveUndefined()594     uint64_t GetDynamicPrimitiveUndefined() const override
595     {
596         return static_cast<uint64_t>(coretypes::TaggedValue::Undefined().GetRawData());
597     }
598 
GetDynamicPrimitiveFalse()599     uint64_t GetDynamicPrimitiveFalse() const override
600     {
601         return static_cast<uint64_t>(coretypes::TaggedValue::False().GetRawData());
602     }
603 
GetDynamicPrimitiveTrue()604     uint64_t GetDynamicPrimitiveTrue() const override
605     {
606         return static_cast<uint64_t>(coretypes::TaggedValue::True().GetRawData());
607     }
608 
609     uint32_t GetNativePointerTargetOffset(Arch arch) const override;
610 
611     bool HasSafepointDuringCall() const override;
612 
613     bool IsGcValidForFastPath(SourceLanguage lang) const;
614 
615     ThreadPtr CreateCompilerThread() override;
616 
617     void DestroyCompilerThread([[maybe_unused]] ThreadPtr thread) override;
618 
SetCurrentThread(ThreadPtr thread)619     void SetCurrentThread(ThreadPtr thread) const override
620     {
621         ASSERT(thread != Thread::GetCurrent());
622         Thread::SetCurrent(static_cast<ark::Thread *>(thread));
623     }
624 
GetCurrentThread()625     ThreadPtr GetCurrentThread() const override
626     {
627         return Thread::GetCurrent();
628     }
629 
630 private:
ToCompilerType(panda_file::Type type)631     static compiler::DataType::Type ToCompilerType(panda_file::Type type)
632     {
633         switch (type.GetId()) {
634             case panda_file::Type::TypeId::VOID:
635                 return compiler::DataType::VOID;
636             case panda_file::Type::TypeId::U1:
637                 return compiler::DataType::BOOL;
638             case panda_file::Type::TypeId::I8:
639                 return compiler::DataType::INT8;
640             case panda_file::Type::TypeId::U8:
641                 return compiler::DataType::UINT8;
642             case panda_file::Type::TypeId::I16:
643                 return compiler::DataType::INT16;
644             case panda_file::Type::TypeId::U16:
645                 return compiler::DataType::UINT16;
646             case panda_file::Type::TypeId::I32:
647                 return compiler::DataType::INT32;
648             case panda_file::Type::TypeId::U32:
649                 return compiler::DataType::UINT32;
650             case panda_file::Type::TypeId::I64:
651                 return compiler::DataType::INT64;
652             case panda_file::Type::TypeId::U64:
653                 return compiler::DataType::UINT64;
654             case panda_file::Type::TypeId::F32:
655                 return compiler::DataType::FLOAT32;
656             case panda_file::Type::TypeId::F64:
657                 return compiler::DataType::FLOAT64;
658             case panda_file::Type::TypeId::REFERENCE:
659                 return compiler::DataType::REFERENCE;
660             case panda_file::Type::TypeId::TAGGED:
661                 return compiler::DataType::ANY;
662             default:
663                 break;
664         }
665         UNREACHABLE();
666     }
667 
668 private:
669     ClassHierarchyAnalysisWrapper cha_;
670     InlineCachesWrapper inlineCaches_;
671     UnresolvedTypesWrapper unresolvedTypes_;
672 };
673 
674 class Compiler : public CompilerInterface {
675 public:
Compiler(CodeAllocator * codeAllocator,mem::InternalAllocatorPtr internalAllocator,const RuntimeOptions & options,mem::MemStatsType * memStats,compiler::RuntimeInterface * runtimeIface)676     explicit Compiler(CodeAllocator *codeAllocator, mem::InternalAllocatorPtr internalAllocator,
677                       const RuntimeOptions &options, mem::MemStatsType *memStats,
678                       compiler::RuntimeInterface *runtimeIface)
679         : codeAllocator_(codeAllocator),
680           internalAllocator_(internalAllocator),
681           gdbDebugInfoAllocator_(ark::SpaceType::SPACE_TYPE_COMPILER, memStats),
682           runtimeIface_(runtimeIface)
683     {
684         noAsyncJit_ = options.IsNoAsyncJit();
685         if (options.IsArkAot()) {
686             return;
687         }
688 
689         if (!Runtime::IsTaskManagerUsed() || noAsyncJit_) {
690             compilerWorker_ =
691                 internalAllocator_->New<CompilerThreadPoolWorker>(internalAllocator_, this, noAsyncJit_, options);
692         } else {
693             compilerWorker_ = internalAllocator_->New<CompilerTaskManagerWorker>(internalAllocator_, this);
694         }
695         InitializeWorker();
696         if (compiler::g_options.WasSetCompilerDumpJitStatsCsv()) {
697             jitStats_ = internalAllocator_->New<compiler::JITStats>(internalAllocator_);
698         }
699     }
700 
PreZygoteFork()701     void PreZygoteFork() override
702     {
703         FinalizeWorker();
704     }
705 
PostZygoteFork()706     void PostZygoteFork() override
707     {
708         InitializeWorker();
709     }
710 
FinalizeWorker()711     void FinalizeWorker() override
712     {
713         if (compilerWorker_ != nullptr) {
714             compilerWorker_->FinalizeWorker();
715         }
716     }
717 
718     void JoinWorker() override;
719 
720     bool IsCompilationExpired(Method *method, bool isOsr);
721 
~Compiler()722     ~Compiler() override
723     {
724         // We need to join thread first if runtime initialization fails and Destroy is not called
725         FinalizeWorker();
726         if (compilerWorker_ != nullptr) {
727             internalAllocator_->Delete(compilerWorker_);
728             compilerWorker_ = nullptr;
729         }
730         internalAllocator_->Delete(jitStats_);
731     }
732 
733     bool CompileMethod(Method *method, uintptr_t bytecodeOffset, bool osr, TaggedValue func) override;
734 
AddTask(CompilerTask && ctx,TaggedValue func)735     virtual void AddTask(CompilerTask &&ctx, [[maybe_unused]] TaggedValue func)
736     {
737         compilerWorker_->AddTask(std::move(ctx));
738     }
739 
740     template <compiler::TaskRunnerMode RUNNER_MODE>
741     void CompileMethodLocked(compiler::CompilerTaskRunner<RUNNER_MODE> taskRunner);
742 
743     /// Basic method, which starts compilation. Do not use.
744     template <compiler::TaskRunnerMode RUNNER_MODE>
745     void StartCompileMethod(compiler::CompilerTaskRunner<RUNNER_MODE> taskRunner);
746 
ScaleThreadPool(size_t numberOfThreads)747     void ScaleThreadPool(size_t numberOfThreads)
748     {
749         // Required for testing
750         ASSERT(GetThreadPool() != nullptr);
751         GetThreadPool()->Scale(numberOfThreads);
752     }
753 
GetOsrCode(const Method * method)754     void *GetOsrCode(const Method *method) override
755     {
756         return osrCodeMap_.Get(method);
757     }
758 
SetOsrCode(const Method * method,void * ptr)759     void SetOsrCode(const Method *method, void *ptr) override
760     {
761         osrCodeMap_.Set(method, ptr);
762     }
763 
RemoveOsrCode(const Method * method)764     void RemoveOsrCode(const Method *method) override
765     {
766         osrCodeMap_.Remove(method);
767     }
768 
SetNoAsyncJit(bool v)769     void SetNoAsyncJit(bool v) override
770     {
771         noAsyncJit_ = v;
772     }
773 
IsNoAsyncJit()774     bool IsNoAsyncJit() override
775     {
776         return noAsyncJit_;
777     }
778 
GetRuntimeInterface()779     compiler::RuntimeInterface *GetRuntimeInterface()
780     {
781         return runtimeIface_;
782     }
783 
784 protected:
GetInternalAllocator()785     mem::InternalAllocatorPtr GetInternalAllocator()
786     {
787         return internalAllocator_;
788     }
789 
GetThreadPool()790     ThreadPool<CompilerTask, CompilerProcessor, Compiler *> *GetThreadPool()
791     {
792         ASSERT(!Runtime::IsTaskManagerUsed() || noAsyncJit_);
793         if (compilerWorker_ != nullptr) {
794             return static_cast<CompilerThreadPoolWorker *>(compilerWorker_)->GetThreadPool();
795         }
796         return nullptr;
797     }
798 
799 private:
InitializeWorker()800     void InitializeWorker()
801     {
802         if (compilerWorker_ != nullptr) {
803             compilerWorker_->InitializeWorker();
804         }
805     }
806 
807     CodeAllocator *codeAllocator_;
808     OsrCodeMap osrCodeMap_;
809     mem::InternalAllocatorPtr internalAllocator_;
810     // This allocator is used for GDB debug structures in context of JIT unwind info.
811     ArenaAllocator gdbDebugInfoAllocator_;
812     compiler::RuntimeInterface *runtimeIface_;
813     // The lock is used for compiler thread synchronization
814     os::memory::Mutex compilationLock_;
815     bool noAsyncJit_;
816     CompilerWorker *compilerWorker_ {nullptr};
817     compiler::JITStats *jitStats_ {nullptr};
818     NO_COPY_SEMANTIC(Compiler);
819     NO_MOVE_SEMANTIC(Compiler);
820 };
821 
822 #ifndef PANDA_PRODUCT_BUILD
823 uint8_t CompileMethodImpl(coretypes::String *fullMethodName, panda_file::SourceLang sourceLang);
824 #endif
825 
826 }  // namespace ark
827 
828 #endif  // PANDA_RUNTIME_COMPILER_H_
829