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