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