• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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/optimizer/ir/runtime_interface.h"
20 #include "libpandabase/mem/code_allocator.h"
21 #include "libpandabase/os/mutex.h"
22 #include "runtime/compiler_queue_aged_counter_priority.h"
23 #include "runtime/compiler_queue_interface.h"
24 #include "runtime/compiler_queue_simple.h"
25 #include "runtime/entrypoints/entrypoints.h"
26 #include "runtime/include/hclass.h"
27 #include "runtime/include/compiler_interface.h"
28 #include "runtime/include/coretypes/array.h"
29 #include "runtime/include/coretypes/tagged_value.h"
30 #include "runtime/include/locks.h"
31 #include "runtime/include/mem/panda_containers.h"
32 #include "runtime/include/method.h"
33 #include "runtime/include/runtime_options.h"
34 #include "runtime/interpreter/frame.h"
35 #include "runtime/mem/gc/gc_barrier_set.h"
36 #include "runtime/mem/tlab.h"
37 
38 #include "runtime/thread_pool.h"
39 #include "runtime/osr.h"
40 
41 namespace panda {
42 
43 using compiler::RuntimeInterface;
44 using compiler::UnresolvedTypesInterface;
45 
MethodCast(RuntimeInterface::MethodPtr method)46 inline panda::Method *MethodCast(RuntimeInterface::MethodPtr method)
47 {
48     return static_cast<panda::Method *>(method);
49 }
50 
51 struct ScopedMutatorLock : public os::memory::ReadLockHolder<MutatorLock> {
ScopedMutatorLockScopedMutatorLock52     ScopedMutatorLock() : os::memory::ReadLockHolder<MutatorLock>(*Locks::mutator_lock) {}
53 };
54 
55 class Compiler;
56 
57 class CompilerProcessor : public ProcessorInterface<CompilerTask, Compiler *> {
58 public:
59     explicit CompilerProcessor(Compiler *compiler);
60     bool Process(CompilerTask task) override;
61 
62 private:
63     Compiler *compiler_;
64 };
65 
66 class ClassHierarchyAnalysisWrapper : public compiler::IClassHierarchyAnalysis {
67 public:
GetSingleImplementation(RuntimeInterface::MethodPtr method)68     RuntimeInterface::MethodPtr GetSingleImplementation(RuntimeInterface::MethodPtr method) override
69     {
70         return static_cast<Method *>(method)->GetSingleImplementation();
71     }
IsSingleImplementation(RuntimeInterface::MethodPtr method)72     bool IsSingleImplementation(RuntimeInterface::MethodPtr method) override
73     {
74         return static_cast<Method *>(method)->HasSingleImplementation();
75     }
76     void AddDependency(RuntimeInterface::MethodPtr callee, RuntimeInterface::MethodPtr caller) override;
77 };
78 
79 class InlineCachesWrapper : public compiler::InlineCachesInterface {
80 public:
81     CallKind GetClasses(RuntimeInterface::MethodPtr m, uintptr_t pc,
82                         ArenaVector<RuntimeInterface::ClassPtr> *classes) override;
83 };
84 
85 class UnresolvedTypesWrapper : public UnresolvedTypesInterface {
86 public:
87     bool AddTableSlot(RuntimeInterface::MethodPtr method, uint32_t type_id, SlotKind kind) override;
88     uintptr_t GetTableSlot(RuntimeInterface::MethodPtr method, uint32_t type_id, SlotKind kind) const override;
89 
90 private:
91     PandaMap<RuntimeInterface::MethodPtr, PandaMap<std::pair<uint32_t, SlotKind>, uintptr_t>> slots_;
92 };
93 
94 class PandaRuntimeInterface : public RuntimeInterface {
95 public:
GetRuntimeEntry()96     void *GetRuntimeEntry() override
97     {
98         return nullptr;
99     }
100 
GetCha()101     compiler::IClassHierarchyAnalysis *GetCha() override
102     {
103         return &cha_;
104     }
105 
GetInlineCaches()106     compiler::InlineCachesInterface *GetInlineCaches() override
107     {
108         return &inline_caches_;
109     }
110 
GetUnresolvedTypes()111     compiler::UnresolvedTypesInterface *GetUnresolvedTypes() override
112     {
113         return &unresolved_types_;
114     }
115 
GetReturnReasonOk()116     unsigned GetReturnReasonOk() const override
117     {
118         return static_cast<unsigned>(CompilerInterface::ReturnReason::RET_OK);
119     }
GetReturnReasonDeopt()120     unsigned GetReturnReasonDeopt() const override
121     {
122         return static_cast<unsigned>(CompilerInterface::ReturnReason::RET_DEOPTIMIZATION);
123     }
124 
ClassCast(ClassPtr cls)125     panda::Class *ClassCast(ClassPtr cls) const
126     {
127         return static_cast<panda::Class *>(cls);
128     }
129 
GetStackOverflowCheckOffset()130     size_t GetStackOverflowCheckOffset() const override
131     {
132         return ManagedThread::GetStackOverflowCheckOffset();
133     }
134 
135     /**************************************************************************
136      * Binary file information
137      */
GetBinaryFileForMethod(MethodPtr method)138     BinaryFilePtr GetBinaryFileForMethod(MethodPtr method) const override
139     {
140         return const_cast<panda_file::File *>(MethodCast(method)->GetPandaFile());
141     }
142 
143     MethodId ResolveMethodIndex(MethodPtr parent_method, MethodIndex index) const override;
144 
145     FieldId ResolveFieldIndex(MethodPtr parent_method, FieldIndex index) const override;
146 
147     IdType ResolveTypeIndex(MethodPtr parent_method, TypeIndex index) const override;
148 
149     /**************************************************************************
150      * Method information
151      */
152     MethodPtr GetMethodById(MethodPtr parent_method, MethodId id) const override;
153 
154     MethodId GetMethodId(MethodPtr method) const override;
155 
156     IntrinsicId GetIntrinsicId([[maybe_unused]] MethodPtr method) const override;
157 
158     MethodPtr ResolveVirtualMethod(ClassPtr cls, MethodPtr method) const override;
159 
160     MethodPtr ResolveInterfaceMethod(ClassPtr cls, MethodPtr method) const override;
161 
GetMethodReturnType(MethodPtr method)162     compiler::DataType::Type GetMethodReturnType(MethodPtr method) const override
163     {
164         return ToCompilerType(MethodCast(method)->GetEffectiveReturnType());
165     }
GetMethodTotalArgumentType(MethodPtr method,size_t index)166     compiler::DataType::Type GetMethodTotalArgumentType(MethodPtr method, size_t index) const override
167     {
168         return ToCompilerType(MethodCast(method)->GetEffectiveArgType(index));
169     }
GetMethodTotalArgumentsCount(MethodPtr method)170     size_t GetMethodTotalArgumentsCount(MethodPtr method) const override
171     {
172         return MethodCast(method)->GetNumArgs();
173     }
174 
175     bool IsMemoryBarrierRequired(MethodPtr method) const override;
176 
177     compiler::DataType::Type GetMethodReturnType(MethodPtr parent_method, MethodId id) const override;
178 
179     compiler::DataType::Type GetMethodArgumentType(MethodPtr parent_method, MethodId id, size_t index) const override;
180 
181     size_t GetMethodArgumentsCount(MethodPtr parent_method, MethodId id) const override;
GetMethodArgumentsCount(MethodPtr method)182     size_t GetMethodArgumentsCount(MethodPtr method) const override
183     {
184         return MethodCast(method)->GetNumArgs();
185     }
GetMethodRegistersCount(MethodPtr method)186     size_t GetMethodRegistersCount(MethodPtr method) const override
187     {
188         return MethodCast(method)->GetNumVregs();
189     }
GetMethodCode(MethodPtr method)190     const uint8_t *GetMethodCode(MethodPtr method) const override
191     {
192         return MethodCast(method)->GetInstructions();
193     }
GetMethodCodeSize(MethodPtr method)194     size_t GetMethodCodeSize(MethodPtr method) const override
195     {
196         return MethodCast(method)->GetCodeSize();
197     }
GetMethodSourceLanguage(MethodPtr method)198     compiler::SourceLanguage GetMethodSourceLanguage(MethodPtr method) const override
199     {
200         return static_cast<compiler::SourceLanguage>(MethodCast(method)->GetClass()->GetSourceLang());
201     }
SetCompiledEntryPoint(MethodPtr method,void * ep)202     void SetCompiledEntryPoint(MethodPtr method, void *ep) override
203     {
204         MethodCast(method)->SetCompiledEntryPoint(ep);
205     }
SetOsrCode(MethodPtr method,void * ep)206     void SetOsrCode(MethodPtr method, void *ep) override
207     {
208         CompilerInterface *compiler = Thread::GetCurrent()->GetVM()->GetCompiler();
209         ASSERT(compiler->GetOsrCode(static_cast<const Method *>(method)) == nullptr);
210         compiler->SetOsrCode(static_cast<const Method *>(method), ep);
211     }
GetOsrCode(MethodPtr method)212     void *GetOsrCode(MethodPtr method) override
213     {
214         return Thread::GetCurrent()->GetVM()->GetCompiler()->GetOsrCode(static_cast<const Method *>(method));
215     }
HasCompiledCode(MethodPtr method)216     bool HasCompiledCode(MethodPtr method) override
217     {
218         return MethodCast(method)->HasCompiledCode();
219     }
220 
GetAccessFlagAbstractMask()221     uint32_t GetAccessFlagAbstractMask() const override
222     {
223         return panda::ACC_ABSTRACT;
224     }
225 
GetVTableIndex(MethodPtr method)226     uint32_t GetVTableIndex(MethodPtr method) const override
227     {
228         return MethodCast(method)->GetVTableIndex();
229     }
230 
GetClassIdForField(MethodPtr method,size_t field_id)231     size_t GetClassIdForField(MethodPtr method, size_t field_id) const override
232     {
233         auto fda =
234             panda_file::FieldDataAccessor(*MethodCast(method)->GetPandaFile(), panda_file::File::EntityId(field_id));
235         return fda.GetClassId().GetOffset();
236     }
237 
GetClassIdForField(FieldPtr field)238     size_t GetClassIdForField(FieldPtr field) const override
239     {
240         return FieldCast(field)->GetClass()->GetFileId().GetOffset();
241     }
242 
243     ClassPtr GetClassForField(FieldPtr field) const override;
244 
GetClassIdForMethod(MethodPtr method)245     size_t GetClassIdForMethod(MethodPtr method) const override
246     {
247         auto mda = panda_file::MethodDataAccessor(*MethodCast(method)->GetPandaFile(), MethodCast(method)->GetFileId());
248         return mda.GetClassId().GetOffset();
249     }
250 
GetClassIdForMethod(MethodPtr parent_method,size_t method_id)251     size_t GetClassIdForMethod(MethodPtr parent_method, size_t method_id) const override
252     {
253         auto mda = panda_file::MethodDataAccessor(*MethodCast(parent_method)->GetPandaFile(),
254                                                   panda_file::File::EntityId(method_id));
255         return mda.GetClassId().GetOffset();
256     }
257 
258     bool HasNativeException(MethodPtr method) const override;
259     bool IsMethodExternal(MethodPtr parent_method, MethodPtr callee_method) const override;
260 
IsMethodIntrinsic(MethodPtr method)261     bool IsMethodIntrinsic(MethodPtr method) const override
262     {
263         return MethodCast(method)->IsIntrinsic();
264     }
265 
IsMethodAbstract(MethodPtr method)266     bool IsMethodAbstract(MethodPtr method) const override
267     {
268         return MethodCast(method)->IsAbstract();
269     }
270 
271     bool IsMethodIntrinsic(MethodPtr parent_method, MethodId id) const override;
272 
IsMethodFinal(MethodPtr method)273     bool IsMethodFinal(MethodPtr method) const override
274     {
275         return MethodCast(method)->IsFinal();
276     }
277 
278     bool IsMethodStatic(MethodPtr parent_method, MethodId id) const override;
279     bool IsMethodStatic(MethodPtr method) const override;
280 
IsMethodCanBeInlined(MethodPtr method)281     bool IsMethodCanBeInlined(MethodPtr method) const override
282     {
283         auto method_ptr = MethodCast(method);
284         return !(method_ptr->IsIntrinsic() || method_ptr->IsNative() || method_ptr->IsAbstract());
285     }
286 
287     bool IsMethodStaticConstructor([[maybe_unused]] MethodPtr method) const override;
288 
GetFileName(MethodPtr method)289     std::string GetFileName(MethodPtr method) const override
290     {
291         return MethodCast(method)->GetPandaFile()->GetFilename();
292     }
293 
GetClassNameFromMethod(MethodPtr method)294     std::string GetClassNameFromMethod(MethodPtr method) const override
295     {
296         ScopedMutatorLock lock;
297         return MethodCast(method)->GetClass()->GetName();
298     }
299 
GetClassName(ClassPtr cls)300     std::string GetClassName(ClassPtr cls) const override
301     {
302         ScopedMutatorLock lock;
303         return ClassCast(cls)->GetName();
304     }
305 
GetMethodName(MethodPtr method)306     std::string GetMethodName(MethodPtr method) const override
307     {
308         return utf::Mutf8AsCString(MethodCast(method)->GetName().data);
309     }
310 
GetBranchTakenCounter(MethodPtr method,uint32_t pc)311     int64_t GetBranchTakenCounter(MethodPtr method, uint32_t pc) const override
312     {
313         return MethodCast(method)->GetBranchTakenCounter(pc);
314     }
315 
GetBranchNotTakenCounter(MethodPtr method,uint32_t pc)316     int64_t GetBranchNotTakenCounter(MethodPtr method, uint32_t pc) const override
317     {
318         return MethodCast(method)->GetBranchNotTakenCounter(pc);
319     }
320 
GetMethodFullName(MethodPtr method,bool with_signature)321     std::string GetMethodFullName(MethodPtr method, bool with_signature) const override
322     {
323         return std::string(MethodCast(method)->GetFullName(with_signature));
324     }
325 
GetClass(MethodPtr method)326     ClassPtr GetClass(MethodPtr method) const override
327     {
328         ScopedMutatorLock lock;
329         return reinterpret_cast<ClassPtr>(MethodCast(method)->GetClass());
330     }
331 
332     std::string GetBytecodeString(MethodPtr method, uintptr_t pc) const override;
333 
334     panda::pandasm::LiteralArray GetLiteralArray(MethodPtr method, LiteralArrayId id) const override;
335 
336     bool IsInterfaceMethod(MethodPtr parent_method, MethodId id) const override;
337 
338     bool IsInterfaceMethod(MethodPtr method) const override;
339 
IsInstanceConstructor(MethodPtr method)340     bool IsInstanceConstructor(MethodPtr method) const override
341     {
342         return MethodCast(method)->IsInstanceConstructor();
343     }
344 
345     bool CanThrowException(MethodPtr method) const override;
346 
347     /**************************************************************************
348      * Thread information
349      */
350     ::panda::mem::BarrierType GetPreType() const override;
351 
352     ::panda::mem::BarrierType GetPostType() const override;
353 
354     ::panda::mem::BarrierOperand GetBarrierOperand(::panda::mem::BarrierPosition barrier_position,
355                                                    std::string_view operand_name) const override;
356 
357     /**************************************************************************
358      * Array information
359      */
360     uint32_t GetArrayElementSize(MethodPtr method, IdType id) const override;
361 
362     uintptr_t GetPointerToConstArrayData(MethodPtr method, IdType id) const override;
363 
364     size_t GetOffsetToConstArrayData(MethodPtr method, IdType id) const override;
365 
366     /**************************************************************************
367      * String information
368      */
IsCompressedStringsEnabled()369     bool IsCompressedStringsEnabled() const override
370     {
371         return panda::coretypes::String::GetCompressedStringsEnabled();
372     }
373 
374     object_pointer_type GetNonMovableString(MethodPtr method, StringId id) const override;
375 
376     ClassPtr GetStringClass(MethodPtr method) const override;
377 
378     /**************************************************************************
379      * TLAB information
380      */
381     size_t GetTLABMaxSize() const override;
382 
GetTLABAlignment()383     size_t GetTLABAlignment() const override
384     {
385         return DEFAULT_ALIGNMENT_IN_BYTES;
386     }
387 
IsTrackTlabAlloc()388     bool IsTrackTlabAlloc() const override
389     {
390         return panda::mem::PANDA_TRACK_TLAB_ALLOCATIONS;
391     }
392 
393     /**************************************************************************
394      * Object information
395      */
396     ClassPtr GetClass(MethodPtr method, IdType id) const override;
397 
398     compiler::ClassType GetClassType(MethodPtr method, IdType id) const override;
399 
400     bool IsArrayClass(MethodPtr method, IdType id) const override;
401 
IsArrayClass(ClassPtr cls)402     bool IsArrayClass(ClassPtr cls) const override
403     {
404         return ClassCast(cls)->IsArrayClass();
405     }
406 
407     ClassPtr GetArrayElementClass(ClassPtr cls) const override;
408 
409     bool CheckStoreArray(ClassPtr array_cls, ClassPtr str_cls) const override;
410 
411     bool IsAssignableFrom(ClassPtr cls1, ClassPtr cls2) const override;
412 
GetObjectHashedStatusBitNum()413     size_t GetObjectHashedStatusBitNum() const override
414     {
415         static_assert(MarkWord::MarkWordRepresentation::STATUS_SIZE == 2);
416         static_assert(MarkWord::MarkWordRepresentation::STATUS_HASHED == 2);
417         // preconditions above allow just check one bit
418         return MarkWord::MarkWordRepresentation::STATUS_SHIFT + 1;
419     }
420 
GetObjectHashShift()421     size_t GetObjectHashShift() const override
422     {
423         return MarkWord::MarkWordRepresentation::HASH_SHIFT;
424     }
425 
GetObjectHashMask()426     size_t GetObjectHashMask() const override
427     {
428         return MarkWord::MarkWordRepresentation::HASH_MASK;
429     }
430 
431     /**************************************************************************
432      * Class information
433      */
GetClassInitializedValue()434     uint8_t GetClassInitializedValue() const override
435     {
436         return static_cast<uint8_t>(panda::Class::State::INITIALIZED);
437     }
438 
439     std::optional<IdType> FindClassIdInFile(MethodPtr method, ClassPtr cls) const;
440     IdType GetClassIdWithinFile(MethodPtr method, ClassPtr cls) const override;
441     IdType GetLiteralArrayClassIdWithinFile(MethodPtr method, panda_file::LiteralTag tag) const override;
442     bool CanUseTlabForClass(ClassPtr klass) const override;
443 
GetClassSize(ClassPtr klass)444     size_t GetClassSize(ClassPtr klass) const override
445     {
446         return ClassCast(klass)->GetObjectSize();
447     }
448 
449     /**************************************************************************
450      * Field information
451      */
452 
453     FieldPtr ResolveField(MethodPtr method, size_t id, bool allow_external, uint32_t *class_id) override;
454     compiler::DataType::Type GetFieldType(FieldPtr field) const override;
455     compiler::DataType::Type GetFieldTypeById(MethodPtr parent_method, IdType id) const override;
456     size_t GetFieldOffset(FieldPtr field) const override;
457     FieldPtr GetFieldByOffset(size_t offset) const override;
458     uintptr_t GetFieldClass(FieldPtr field) const override;
459     bool IsFieldVolatile(FieldPtr field) const override;
460     bool HasFieldMetadata(FieldPtr field) const override;
461 
GetFieldName(FieldPtr field)462     std::string GetFieldName(FieldPtr field) const override
463     {
464         return utf::Mutf8AsCString(FieldCast(field)->GetName().data);
465     }
466 
FieldCast(FieldPtr field)467     panda::Field *FieldCast(FieldPtr field) const
468     {
469         ASSERT(HasFieldMetadata(field));
470         return static_cast<panda::Field *>(field);
471     }
472 
473     /**************************************************************************
474      * Type information
475      */
476 
477     PandaRuntimeInterface::ClassPtr ResolveType(MethodPtr method, size_t id) const override;
478 
479     bool IsClassInitialized(uintptr_t klass) const override;
480 
IsClassFinal(ClassPtr klass)481     bool IsClassFinal(ClassPtr klass) const override
482     {
483         return ClassCast(klass)->IsFinal();
484     }
485 
486     uintptr_t GetManagedType(uintptr_t klass) const override;
487 
TypeCast(uintptr_t klass)488     panda::Class *TypeCast(uintptr_t klass) const
489     {
490         return reinterpret_cast<panda::Class *>(klass);
491     }
492 
GetReferenceTypeMask()493     uint8_t GetReferenceTypeMask() const override
494     {
495         return static_cast<uint8_t>(panda_file::Type::TypeId::REFERENCE);
496     }
497 
498     /**************************************************************************
499      * Entrypoints
500      */
501     uintptr_t GetIntrinsicAddress(bool runtime_call, IntrinsicId id) const override;
502 
503     /**************************************************************************
504      * Dynamic object information
505      */
506 
507     uint32_t GetFunctionTargetOffset(Arch arch) const override;
508 
GetDynamicPrimitiveUndefined()509     uint64_t GetDynamicPrimitiveUndefined() const override
510     {
511         return static_cast<uint64_t>(coretypes::TaggedValue::Undefined().GetRawData());
512     }
513 
GetDynamicPrimitiveFalse()514     uint64_t GetDynamicPrimitiveFalse() const override
515     {
516         return static_cast<uint64_t>(coretypes::TaggedValue::False().GetRawData());
517     }
518 
GetDynamicPrimitiveTrue()519     uint64_t GetDynamicPrimitiveTrue() const override
520     {
521         return static_cast<uint64_t>(coretypes::TaggedValue::True().GetRawData());
522     }
523 
524     uint32_t GetNativePointerTargetOffset(Arch arch) const override;
525 
526     bool HasSafepointDuringCall() const override;
527 
528 private:
ToCompilerType(panda_file::Type type)529     static compiler::DataType::Type ToCompilerType(panda_file::Type type)
530     {
531         switch (type.GetId()) {
532             case panda_file::Type::TypeId::VOID:
533                 return compiler::DataType::VOID;
534             case panda_file::Type::TypeId::U1:
535                 return compiler::DataType::BOOL;
536             case panda_file::Type::TypeId::I8:
537                 return compiler::DataType::INT8;
538             case panda_file::Type::TypeId::U8:
539                 return compiler::DataType::UINT8;
540             case panda_file::Type::TypeId::I16:
541                 return compiler::DataType::INT16;
542             case panda_file::Type::TypeId::U16:
543                 return compiler::DataType::UINT16;
544             case panda_file::Type::TypeId::I32:
545                 return compiler::DataType::INT32;
546             case panda_file::Type::TypeId::U32:
547                 return compiler::DataType::UINT32;
548             case panda_file::Type::TypeId::I64:
549                 return compiler::DataType::INT64;
550             case panda_file::Type::TypeId::U64:
551                 return compiler::DataType::UINT64;
552             case panda_file::Type::TypeId::F32:
553                 return compiler::DataType::FLOAT32;
554             case panda_file::Type::TypeId::F64:
555                 return compiler::DataType::FLOAT64;
556             case panda_file::Type::TypeId::REFERENCE:
557                 return compiler::DataType::REFERENCE;
558             case panda_file::Type::TypeId::TAGGED:
559                 return compiler::DataType::ANY;
560             default:
561                 break;
562         }
563         UNREACHABLE();
564     }
565 
566 private:
567     ClassHierarchyAnalysisWrapper cha_;
568     InlineCachesWrapper inline_caches_;
569     UnresolvedTypesWrapper unresolved_types_;
570 };
571 
572 class Compiler : public CompilerInterface {
573 public:
Compiler(CodeAllocator * code_allocator,mem::InternalAllocatorPtr internal_allocator,const RuntimeOptions & options,mem::MemStatsType * mem_stats,compiler::RuntimeInterface * runtime_iface)574     explicit Compiler(CodeAllocator *code_allocator, mem::InternalAllocatorPtr internal_allocator,
575                       const RuntimeOptions &options, mem::MemStatsType *mem_stats,
576                       compiler::RuntimeInterface *runtime_iface)
577         : code_allocator_(code_allocator),
578           internal_allocator_(internal_allocator),
579           gdb_debug_info_allocator_(panda::SpaceType::SPACE_TYPE_COMPILER, mem_stats),
580           runtime_iface_(runtime_iface)
581     {
582         no_async_jit_ = options.IsNoAsyncJit();
583 
584         thread_pool_ = nullptr;
585         if (options.IsArkAot()) {
586             return;
587         }
588 
589         queue_ = CreateJITTaskQueue(no_async_jit_ ? "simple" : options.GetCompilerQueueType(),
590                                     options.GetCompilerQueueMaxLength(), options.GetCompilerTaskLifeSpan(),
591                                     options.GetCompilerDeathCounterValue(), options.GetCompilerEpochDuration());
592         if (queue_ == nullptr) {
593             // Because of problems (no memory) in allocator
594             LOG(ERROR, COMPILER) << "Cannot create a compiler queue";
595             no_async_jit_ = true;
596         }
597         CreateWorker();
598     }
599 
PreZygoteFork()600     void PreZygoteFork() override
601     {
602         JoinWorker();
603     }
604 
PostZygoteFork()605     void PostZygoteFork() override
606     {
607         CreateWorker();
608     }
609 
Destroy()610     void Destroy() override
611     {
612         JoinWorker();
613     }
614 
615     bool IsCompilationExpired(const CompilerTask &ctx);
616 
~Compiler()617     ~Compiler() override
618     {
619         // We need to join thread first if runtime initialization fails and Destroy is not called
620         Destroy();
621         if (queue_ != nullptr) {
622             queue_->Finalize();
623             internal_allocator_->Delete(queue_);
624         }
625     }
626 
627     bool CompileMethod(Method *method, uintptr_t bytecode_offset, bool osr) override;
628 
AddTask(CompilerTask task)629     void AddTask(CompilerTask task)
630     {
631         if (!is_thread_pool_created_) {
632             // BUG: thread pool was not created
633             LOG(ERROR, COMPILER) << "Thread pool for compilation threads was not created";
634             return;
635         }
636         thread_pool_->PutTask(task);
637     }
638 
639     /**
640      * Basic method, which starts compilation. Do not use.
641      */
642     void CompileMethodLocked(const CompilerTask &ctx);
643 
ScaleThreadPool(size_t number_of_threads)644     void ScaleThreadPool(size_t number_of_threads)
645     {
646         // Required for testing
647         thread_pool_->Scale(number_of_threads);
648     }
649 
GetOsrCode(const Method * method)650     void *GetOsrCode(const Method *method) override
651     {
652         return osr_code_map_.Get(method);
653     }
654 
SetOsrCode(const Method * method,void * ptr)655     void SetOsrCode(const Method *method, void *ptr) override
656     {
657         osr_code_map_.Set(method, ptr);
658     }
659 
RemoveOsrCode(const Method * method)660     void RemoveOsrCode(const Method *method) override
661     {
662         osr_code_map_.Remove(method);
663     }
664 
665 private:
666     /**
667      * Add a method as a compilation task into a queue.
668      * The compilation will be performed in a worker thread
669      */
670     void CompileMethodAsync(const CompilerTask &ctx);
671 
672     /**
673      * Performs compilation in the main thread
674      */
675     void CompileMethodSync(const CompilerTask &ctx);
676 
CreateJITTaskQueue(const std::string & queue_type,uint64_t max_length,uint64_t task_life,uint64_t death_counter,uint64_t epoch_duration)677     CompilerQueueInterface *CreateJITTaskQueue(const std::string &queue_type, uint64_t max_length, uint64_t task_life,
678                                                uint64_t death_counter, uint64_t epoch_duration)
679     {
680         LOG(DEBUG, COMPILER) << "Creating " << queue_type << " task queue";
681         if (queue_type == "simple") {
682             return internal_allocator_->New<CompilerQueueSimple>(internal_allocator_);
683         }
684         if (queue_type == "counter-priority") {
685             return internal_allocator_->New<CompilerPriorityCounterQueue>(internal_allocator_, max_length, task_life);
686         }
687         if (queue_type == "aged-counter-priority") {
688             return internal_allocator_->New<CompilerPriorityAgedCounterQueue>(internal_allocator_, task_life,
689                                                                               death_counter, epoch_duration);
690         }
691         LOG(FATAL, COMPILER) << "Unknown queue type";
692         return nullptr;
693     }
694 
695     void JoinWorker();
696 
CreateWorker()697     void CreateWorker()
698     {
699         if (thread_pool_ == nullptr) {
700             thread_pool_ = internal_allocator_->New<ThreadPool<CompilerTask, CompilerProcessor, Compiler *>>(
701                 internal_allocator_, queue_, this, 1, "JIT Thread");
702         }
703         is_thread_pool_created_ = true;
704     }
705 
706     CodeAllocator *code_allocator_;
707     OsrCodeMap osr_code_map_;
708     mem::InternalAllocatorPtr internal_allocator_;
709     // This allocator is used for GDB debug structures in context of JIT unwind info.
710     ArenaAllocator gdb_debug_info_allocator_;
711     compiler::RuntimeInterface *runtime_iface_;
712     // The lock is used for compiler thread synchronization
713     os::memory::Mutex compilation_lock_;
714     // This queue is used only in ThreadPool. Do not use it from this class.
715     CompilerQueueInterface *queue_ {nullptr};
716     bool no_async_jit_;
717     std::atomic_bool is_thread_pool_created_ = false;
718     ThreadPool<CompilerTask, CompilerProcessor, Compiler *> *thread_pool_;
719     NO_COPY_SEMANTIC(Compiler);
720     NO_MOVE_SEMANTIC(Compiler);
721 };
722 
723 }  // namespace panda
724 
725 #endif  // PANDA_RUNTIME_COMPILER_H_
726