1 /**
2 * Copyright (c) 2021-2024 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 "plugins/ets/runtime/ets_class_linker_extension.h"
17
18 #include "include/method.h"
19 #include "libpandabase/macros.h"
20 #include "libpandabase/utils/logger.h"
21 #include "plugins/ets/runtime/ets_annotation.h"
22 #include "plugins/ets/runtime/ets_coroutine.h"
23 #include "plugins/ets/runtime/ets_exceptions.h"
24 #include "plugins/ets/runtime/ets_panda_file_items.h"
25 #include "plugins/ets/runtime/ets_vm.h"
26 #include "plugins/ets/runtime/napi/ets_napi_helpers.h"
27 #include "plugins/ets/runtime/types/ets_object.h"
28 #include "plugins/ets/runtime/types/ets_method.h"
29 #include "runtime/include/class_linker_extension.h"
30 #include "runtime/include/class_linker-inl.h"
31 #include "runtime/include/language_context.h"
32 #include "runtime/include/mem/panda_string.h"
33 #include "runtime/include/panda_vm.h"
34 #include "runtime/mem/heap_manager.h"
35
36 namespace ark::ets {
37 namespace {
38 enum class EtsNapiType {
39 GENERIC, // - Switches the coroutine to native mode (GC is allowed)
40 // - Prepends the argument list with two additional arguments (NAPI environment and this / class object)
41
42 FAST, // - Leaves the coroutine in managed mode (GC is not allowed)
43 // - Prepends the argument list with two additional arguments (NAPI environment and this / class object)
44 // - !!! The native function should not make any allocations (GC may be triggered during an allocation)
45
46 CRITICAL // - Leaves the coroutine in managed mode (GC is not allowed)
47 // - Passes the arguments as is (the callee method should be static)
48 // - !!! The native function should not make any allocations (GC may be triggered during an allocation)
49 };
50 } // namespace
51
52 extern "C" void EtsAsyncEntryPoint();
53
GetEtsNapiType(Method * method)54 static EtsNapiType GetEtsNapiType([[maybe_unused]] Method *method)
55 {
56 // NOTE(#18101): support other NAPI types after annotations have been implemented.
57 return EtsNapiType::GENERIC;
58 }
59
GetClassLinkerErrorDescriptor(ClassLinker::Error error)60 static std::string_view GetClassLinkerErrorDescriptor(ClassLinker::Error error)
61 {
62 switch (error) {
63 case ClassLinker::Error::CLASS_NOT_FOUND:
64 return panda_file_items::class_descriptors::CLASS_NOT_FOUND_EXCEPTION;
65 case ClassLinker::Error::FIELD_NOT_FOUND:
66 return panda_file_items::class_descriptors::NO_SUCH_FIELD_ERROR;
67 case ClassLinker::Error::METHOD_NOT_FOUND:
68 return panda_file_items::class_descriptors::NO_SUCH_METHOD_ERROR;
69 case ClassLinker::Error::NO_CLASS_DEF:
70 return panda_file_items::class_descriptors::NO_CLASS_DEF_FOUND_ERROR;
71 case ClassLinker::Error::CLASS_CIRCULARITY:
72 return panda_file_items::class_descriptors::CLASS_CIRCULARITY_ERROR;
73 case ClassLinker::Error::OVERRIDES_FINAL:
74 case ClassLinker::Error::MULTIPLE_OVERRIDE:
75 case ClassLinker::Error::MULTIPLE_IMPLEMENT:
76 return panda_file_items::class_descriptors::LINKAGE_ERROR;
77 default:
78 LOG(FATAL, CLASS_LINKER) << "Unhandled class linker error (" << helpers::ToUnderlying(error) << "): ";
79 UNREACHABLE();
80 }
81 }
82
OnError(ClassLinker::Error error,const PandaString & message)83 void EtsClassLinkerExtension::ErrorHandler::OnError(ClassLinker::Error error, const PandaString &message)
84 {
85 ThrowEtsException(EtsCoroutine::GetCurrent(), GetClassLinkerErrorDescriptor(error), message);
86 }
87
InitializeClassRoots()88 void EtsClassLinkerExtension::InitializeClassRoots()
89 {
90 InitializeArrayClassRoot(ClassRoot::ARRAY_CLASS, ClassRoot::CLASS,
91 utf::Mutf8AsCString(langCtx_.GetClassArrayClassDescriptor()));
92
93 InitializePrimitiveClassRoot(ClassRoot::V, panda_file::Type::TypeId::VOID, "V");
94 InitializePrimitiveClassRoot(ClassRoot::U1, panda_file::Type::TypeId::U1, "Z");
95 InitializePrimitiveClassRoot(ClassRoot::I8, panda_file::Type::TypeId::I8, "B");
96 InitializePrimitiveClassRoot(ClassRoot::U8, panda_file::Type::TypeId::U8, "H");
97 InitializePrimitiveClassRoot(ClassRoot::I16, panda_file::Type::TypeId::I16, "S");
98 InitializePrimitiveClassRoot(ClassRoot::U16, panda_file::Type::TypeId::U16, "C");
99 InitializePrimitiveClassRoot(ClassRoot::I32, panda_file::Type::TypeId::I32, "I");
100 InitializePrimitiveClassRoot(ClassRoot::U32, panda_file::Type::TypeId::U32, "U");
101 InitializePrimitiveClassRoot(ClassRoot::I64, panda_file::Type::TypeId::I64, "J");
102 InitializePrimitiveClassRoot(ClassRoot::U64, panda_file::Type::TypeId::U64, "Q");
103 InitializePrimitiveClassRoot(ClassRoot::F32, panda_file::Type::TypeId::F32, "F");
104 InitializePrimitiveClassRoot(ClassRoot::F64, panda_file::Type::TypeId::F64, "D");
105 InitializePrimitiveClassRoot(ClassRoot::TAGGED, panda_file::Type::TypeId::TAGGED, "A");
106
107 InitializeArrayClassRoot(ClassRoot::ARRAY_U1, ClassRoot::U1, "[Z");
108 InitializeArrayClassRoot(ClassRoot::ARRAY_I8, ClassRoot::I8, "[B");
109 InitializeArrayClassRoot(ClassRoot::ARRAY_U8, ClassRoot::U8, "[H");
110 InitializeArrayClassRoot(ClassRoot::ARRAY_I16, ClassRoot::I16, "[S");
111 InitializeArrayClassRoot(ClassRoot::ARRAY_U16, ClassRoot::U16, "[C");
112 InitializeArrayClassRoot(ClassRoot::ARRAY_I32, ClassRoot::I32, "[I");
113 InitializeArrayClassRoot(ClassRoot::ARRAY_U32, ClassRoot::U32, "[U");
114 InitializeArrayClassRoot(ClassRoot::ARRAY_I64, ClassRoot::I64, "[J");
115 InitializeArrayClassRoot(ClassRoot::ARRAY_U64, ClassRoot::U64, "[Q");
116 InitializeArrayClassRoot(ClassRoot::ARRAY_F32, ClassRoot::F32, "[F");
117 InitializeArrayClassRoot(ClassRoot::ARRAY_F64, ClassRoot::F64, "[D");
118 InitializeArrayClassRoot(ClassRoot::ARRAY_TAGGED, ClassRoot::TAGGED, "[A");
119 InitializeArrayClassRoot(ClassRoot::ARRAY_STRING, ClassRoot::STRING,
120 utf::Mutf8AsCString(langCtx_.GetStringArrayClassDescriptor()));
121 }
122
InitializeImpl(bool compressedStringEnabled)123 bool EtsClassLinkerExtension::InitializeImpl(bool compressedStringEnabled)
124 {
125 // NOLINTNEXTLINE(google-build-using-namespace)
126 using namespace panda_file_items::class_descriptors;
127
128 auto *coroutine = ets::EtsCoroutine::GetCurrent();
129 langCtx_ = Runtime::GetCurrent()->GetLanguageContext(panda_file::SourceLang::ETS);
130 heapManager_ = coroutine->GetVM()->GetHeapManager();
131
132 auto *objectClass = GetClassLinker()->GetClass(langCtx_.GetObjectClassDescriptor(), false, GetBootContext());
133 if (objectClass == nullptr) {
134 LOG(ERROR, CLASS_LINKER) << "Cannot create class '" << langCtx_.GetObjectClassDescriptor() << "'";
135 return false;
136 }
137 SetClassRoot(ClassRoot::OBJECT, objectClass);
138
139 auto *classClass = GetClassLinker()->GetClass(langCtx_.GetClassClassDescriptor(), false, GetBootContext());
140 if (classClass == nullptr) {
141 LOG(ERROR, CLASS_LINKER) << "Cannot create class '" << langCtx_.GetClassClassDescriptor() << "'";
142 return false;
143 }
144 SetClassRoot(ClassRoot::CLASS, classClass);
145
146 EtsClass::FromRuntimeClass(classClass)->AsObject()->GetCoreType()->SetClass(classClass);
147 EtsClass::FromRuntimeClass(objectClass)->AsObject()->GetCoreType()->SetClass(classClass);
148
149 coretypes::String::SetCompressedStringsEnabled(compressedStringEnabled);
150
151 auto *stringClass = GetClassLinker()->GetClass(langCtx_.GetStringClassDescriptor(), false, GetBootContext());
152 if (stringClass == nullptr) {
153 LOG(ERROR, CLASS_LINKER) << "Cannot create class '" << langCtx_.GetStringClassDescriptor() << "'";
154 return false;
155 }
156 SetClassRoot(ClassRoot::STRING, stringClass);
157 stringClass->SetStringClass();
158
159 InitializeClassRoots();
160
161 return true;
162 }
163
InitializeArrayClass(Class * arrayClass,Class * componentClass)164 bool EtsClassLinkerExtension::InitializeArrayClass(Class *arrayClass, Class *componentClass)
165 {
166 ASSERT(IsInitialized());
167
168 ASSERT(!arrayClass->IsInitialized());
169 ASSERT(arrayClass->GetComponentType() == nullptr);
170
171 auto *objectClass = GetClassRoot(ClassRoot::OBJECT);
172 arrayClass->SetBase(objectClass);
173 arrayClass->SetComponentType(componentClass);
174
175 auto accessFlags = componentClass->GetAccessFlags() & ACC_FILE_MASK;
176 accessFlags &= ~ACC_INTERFACE;
177 accessFlags |= ACC_FINAL | ACC_ABSTRACT;
178
179 arrayClass->SetAccessFlags(accessFlags);
180
181 auto objectClassVtable = objectClass->GetVTable();
182 auto arrayClassVtable = arrayClass->GetVTable();
183 for (size_t i = 0; i < objectClassVtable.size(); i++) {
184 arrayClassVtable[i] = objectClassVtable[i];
185 }
186
187 arrayClass->SetState(Class::State::INITIALIZED);
188
189 ASSERT(arrayClass->IsArrayClass()); // After init, we give out a well-formed array class.
190 return true;
191 }
192
InitializeClass(Class * klass)193 bool EtsClassLinkerExtension::InitializeClass(Class *klass)
194 {
195 ASSERT(IsInitialized());
196 ASSERT_HAVE_ACCESS_TO_MANAGED_OBJECTS();
197
198 constexpr uint32_t ETS_ACCESS_FLAGS_MASK = 0xFFFFU;
199
200 EtsClass::FromRuntimeClass(klass)->Initialize(
201 klass->GetBase() != nullptr ? EtsClass::FromRuntimeClass(klass->GetBase()) : nullptr,
202 klass->GetAccessFlags() & ETS_ACCESS_FLAGS_MASK, klass->IsPrimitive());
203
204 return true;
205 }
206
InitializePrimitiveClass(Class * primitiveClass)207 void EtsClassLinkerExtension::InitializePrimitiveClass(Class *primitiveClass)
208 {
209 ASSERT(IsInitialized());
210
211 ASSERT(!primitiveClass->IsInitialized());
212 ASSERT(primitiveClass->IsPrimitive());
213
214 primitiveClass->SetAccessFlags(ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT);
215 primitiveClass->SetState(Class::State::INITIALIZED);
216 }
217
GetClassVTableSize(ClassRoot root)218 size_t EtsClassLinkerExtension::GetClassVTableSize(ClassRoot root)
219 {
220 ASSERT(IsInitialized());
221
222 switch (root) {
223 case ClassRoot::V:
224 case ClassRoot::U1:
225 case ClassRoot::I8:
226 case ClassRoot::U8:
227 case ClassRoot::I16:
228 case ClassRoot::U16:
229 case ClassRoot::I32:
230 case ClassRoot::U32:
231 case ClassRoot::I64:
232 case ClassRoot::U64:
233 case ClassRoot::F32:
234 case ClassRoot::F64:
235 case ClassRoot::TAGGED:
236 return 0;
237 case ClassRoot::ARRAY_U1:
238 case ClassRoot::ARRAY_I8:
239 case ClassRoot::ARRAY_U8:
240 case ClassRoot::ARRAY_I16:
241 case ClassRoot::ARRAY_U16:
242 case ClassRoot::ARRAY_I32:
243 case ClassRoot::ARRAY_U32:
244 case ClassRoot::ARRAY_I64:
245 case ClassRoot::ARRAY_U64:
246 case ClassRoot::ARRAY_F32:
247 case ClassRoot::ARRAY_F64:
248 case ClassRoot::ARRAY_TAGGED:
249 case ClassRoot::ARRAY_CLASS:
250 case ClassRoot::ARRAY_STRING:
251 return GetArrayClassVTableSize();
252 case ClassRoot::OBJECT:
253 case ClassRoot::STRING:
254 return GetClassRoot(root)->GetVTableSize();
255 case ClassRoot::CLASS:
256 return 0;
257 default: {
258 break;
259 }
260 }
261
262 UNREACHABLE();
263 return 0;
264 }
265
GetClassIMTSize(ClassRoot root)266 size_t EtsClassLinkerExtension::GetClassIMTSize(ClassRoot root)
267 {
268 ASSERT(IsInitialized());
269
270 switch (root) {
271 case ClassRoot::V:
272 case ClassRoot::U1:
273 case ClassRoot::I8:
274 case ClassRoot::U8:
275 case ClassRoot::I16:
276 case ClassRoot::U16:
277 case ClassRoot::I32:
278 case ClassRoot::U32:
279 case ClassRoot::I64:
280 case ClassRoot::U64:
281 case ClassRoot::F32:
282 case ClassRoot::F64:
283 case ClassRoot::TAGGED:
284 return 0;
285 case ClassRoot::ARRAY_U1:
286 case ClassRoot::ARRAY_I8:
287 case ClassRoot::ARRAY_U8:
288 case ClassRoot::ARRAY_I16:
289 case ClassRoot::ARRAY_U16:
290 case ClassRoot::ARRAY_I32:
291 case ClassRoot::ARRAY_U32:
292 case ClassRoot::ARRAY_I64:
293 case ClassRoot::ARRAY_U64:
294 case ClassRoot::ARRAY_F32:
295 case ClassRoot::ARRAY_F64:
296 case ClassRoot::ARRAY_TAGGED:
297 case ClassRoot::ARRAY_CLASS:
298 case ClassRoot::ARRAY_STRING:
299 return GetArrayClassIMTSize();
300 case ClassRoot::OBJECT:
301 case ClassRoot::CLASS:
302 case ClassRoot::STRING:
303 return 0;
304 default: {
305 break;
306 }
307 }
308
309 UNREACHABLE();
310 return 0;
311 }
312
GetClassSize(ClassRoot root)313 size_t EtsClassLinkerExtension::GetClassSize(ClassRoot root)
314 {
315 ASSERT(IsInitialized());
316
317 switch (root) {
318 case ClassRoot::V:
319 case ClassRoot::U1:
320 case ClassRoot::I8:
321 case ClassRoot::U8:
322 case ClassRoot::I16:
323 case ClassRoot::U16:
324 case ClassRoot::I32:
325 case ClassRoot::U32:
326 case ClassRoot::I64:
327 case ClassRoot::U64:
328 case ClassRoot::F32:
329 case ClassRoot::F64:
330 case ClassRoot::TAGGED:
331 return Class::ComputeClassSize(GetClassVTableSize(root), GetClassIMTSize(root), 0, 0, 0, 0, 0, 0);
332 case ClassRoot::ARRAY_U1:
333 case ClassRoot::ARRAY_I8:
334 case ClassRoot::ARRAY_U8:
335 case ClassRoot::ARRAY_I16:
336 case ClassRoot::ARRAY_U16:
337 case ClassRoot::ARRAY_I32:
338 case ClassRoot::ARRAY_U32:
339 case ClassRoot::ARRAY_I64:
340 case ClassRoot::ARRAY_U64:
341 case ClassRoot::ARRAY_F32:
342 case ClassRoot::ARRAY_F64:
343 case ClassRoot::ARRAY_TAGGED:
344 case ClassRoot::ARRAY_CLASS:
345 case ClassRoot::ARRAY_STRING:
346 return GetArrayClassSize();
347 case ClassRoot::OBJECT:
348 case ClassRoot::CLASS:
349 case ClassRoot::STRING:
350 return Class::ComputeClassSize(GetClassVTableSize(root), GetClassIMTSize(root), 0, 0, 0, 0, 0, 0);
351 default: {
352 break;
353 }
354 }
355
356 UNREACHABLE();
357 return 0;
358 }
359
GetArrayClassVTableSize()360 size_t EtsClassLinkerExtension::GetArrayClassVTableSize()
361 {
362 ASSERT(IsInitialized());
363
364 return GetClassVTableSize(ClassRoot::OBJECT);
365 }
366
GetArrayClassIMTSize()367 size_t EtsClassLinkerExtension::GetArrayClassIMTSize()
368 {
369 ASSERT(IsInitialized());
370
371 return GetClassIMTSize(ClassRoot::OBJECT);
372 }
373
GetArrayClassSize()374 size_t EtsClassLinkerExtension::GetArrayClassSize()
375 {
376 ASSERT(IsInitialized());
377
378 return GetClassSize(ClassRoot::OBJECT);
379 }
380
InitializeClass(ObjectHeader * objectHeader,const uint8_t * descriptor,size_t vtableSize,size_t imtSize,size_t size)381 Class *EtsClassLinkerExtension::InitializeClass(ObjectHeader *objectHeader, const uint8_t *descriptor,
382 size_t vtableSize, size_t imtSize, size_t size)
383 {
384 auto managedClass = reinterpret_cast<EtsClass *>(objectHeader);
385 managedClass->InitClass(descriptor, vtableSize, imtSize, size);
386 auto klass = managedClass->GetRuntimeClass();
387 klass->SetManagedObject(objectHeader);
388 klass->SetSourceLang(GetLanguage());
389
390 AddCreatedClass(klass);
391
392 return klass;
393 }
394
CreateClass(const uint8_t * descriptor,size_t vtableSize,size_t imtSize,size_t size)395 Class *EtsClassLinkerExtension::CreateClass(const uint8_t *descriptor, size_t vtableSize, size_t imtSize, size_t size)
396 {
397 ASSERT(IsInitialized());
398
399 Class *classClassRoot = GetClassRoot(ClassRoot::CLASS);
400 ObjectHeader *classObject;
401 if (UNLIKELY(classClassRoot == nullptr)) {
402 ASSERT(utf::IsEqual(descriptor, langCtx_.GetObjectClassDescriptor()) ||
403 utf::IsEqual(descriptor, langCtx_.GetClassClassDescriptor()));
404 classObject = heapManager_->AllocateNonMovableObject<true>(classClassRoot, EtsClass::GetSize(size));
405 } else {
406 classObject = heapManager_->AllocateNonMovableObject<false>(classClassRoot, EtsClass::GetSize(size));
407 }
408 if (UNLIKELY(classObject == nullptr)) {
409 return nullptr;
410 }
411
412 return InitializeClass(classObject, descriptor, vtableSize, imtSize, size);
413 }
414
CreateClassRoot(const uint8_t * descriptor,ClassRoot root)415 Class *EtsClassLinkerExtension::CreateClassRoot(const uint8_t *descriptor, ClassRoot root)
416 {
417 auto vtableSize = GetClassVTableSize(root);
418 auto imtSize = GetClassIMTSize(root);
419 auto size = GetClassSize(root);
420
421 Class *klass;
422 if (root == ClassRoot::CLASS) {
423 ASSERT(GetClassRoot(ClassRoot::CLASS) == nullptr);
424 auto objectHeader = heapManager_->AllocateNonMovableObject<true>(nullptr, EtsClass::GetSize(size));
425 ASSERT(objectHeader != nullptr);
426
427 klass = InitializeClass(objectHeader, descriptor, vtableSize, imtSize, size);
428 klass->SetObjectSize(EtsClass::GetSize(size));
429 EtsClass::FromRuntimeClass(klass)->AsObject()->SetClass(EtsClass::FromRuntimeClass(klass));
430 } else {
431 klass = CreateClass(descriptor, vtableSize, imtSize, size);
432 }
433
434 ASSERT(klass != nullptr);
435 klass->SetBase(GetClassRoot(ClassRoot::OBJECT));
436 klass->SetState(Class::State::LOADED);
437 klass->SetLoadContext(GetBootContext());
438 GetClassLinker()->AddClassRoot(root, klass);
439 return klass;
440 }
441
FreeClass(Class * klass)442 void EtsClassLinkerExtension::FreeClass(Class *klass)
443 {
444 ASSERT(IsInitialized());
445
446 RemoveCreatedClass(klass);
447 }
448
~EtsClassLinkerExtension()449 EtsClassLinkerExtension::~EtsClassLinkerExtension()
450 {
451 if (!IsInitialized()) {
452 return;
453 }
454
455 FreeLoadedClasses();
456 }
457
GetNativeEntryPointFor(Method * method) const458 const void *EtsClassLinkerExtension::GetNativeEntryPointFor(Method *method) const
459 {
460 panda_file::File::EntityId asyncAnnId = EtsAnnotation::FindAsyncAnnotation(method);
461 if (asyncAnnId.IsValid()) {
462 return reinterpret_cast<const void *>(EtsAsyncEntryPoint);
463 }
464 switch (GetEtsNapiType(method)) {
465 case EtsNapiType::GENERIC: {
466 return napi::GetEtsNapiEntryPoint();
467 }
468 case EtsNapiType::FAST: {
469 auto flags = method->GetAccessFlags();
470 flags |= ACC_FAST_NATIVE;
471 method->SetAccessFlags(flags);
472
473 return napi::GetEtsNapiEntryPoint();
474 }
475 case EtsNapiType::CRITICAL: {
476 auto flags = method->GetAccessFlags();
477 flags |= ACC_CRITICAL_NATIVE;
478 method->SetAccessFlags(flags);
479
480 return napi::GetEtsNapiCriticalEntryPoint();
481 }
482 }
483
484 UNREACHABLE();
485 }
486
FromClassObject(ark::ObjectHeader * obj)487 Class *EtsClassLinkerExtension::FromClassObject(ark::ObjectHeader *obj)
488 {
489 return obj != nullptr ? reinterpret_cast<EtsClass *>(obj)->GetRuntimeClass() : nullptr;
490 }
491
GetClassObjectSizeFromClassSize(uint32_t size)492 size_t EtsClassLinkerExtension::GetClassObjectSizeFromClassSize(uint32_t size)
493 {
494 return EtsClass::GetSize(size);
495 }
496
CacheClass(std::string_view descriptor,bool forceInit)497 Class *EtsClassLinkerExtension::CacheClass(std::string_view descriptor, bool forceInit)
498 {
499 Class *cls = GetClassLinker()->GetClass(utf::CStringAsMutf8(descriptor.data()), false, GetBootContext());
500 if (cls == nullptr) {
501 LOG(ERROR, CLASS_LINKER) << "Cannot create class " << descriptor;
502 return nullptr;
503 }
504 if (forceInit && !GetClassLinker()->InitializeClass(EtsCoroutine::GetCurrent(), cls)) {
505 LOG(ERROR, CLASS_LINKER) << "Cannot initialize class " << descriptor;
506 return nullptr;
507 }
508 return cls;
509 }
510
511 template <typename F>
CacheClass(std::string_view descriptor,F const & setup,bool forceInit)512 Class *EtsClassLinkerExtension::CacheClass(std::string_view descriptor, F const &setup, bool forceInit)
513 {
514 Class *cls = CacheClass(descriptor, forceInit);
515 if (cls != nullptr) {
516 setup(EtsClass::FromRuntimeClass(cls));
517 }
518 return cls;
519 }
520
InitializeBuiltinSpecialClasses()521 void EtsClassLinkerExtension::InitializeBuiltinSpecialClasses()
522 {
523 // CC-OFFNXT(WordsTool.95) false positive
524 // NOLINTNEXTLINE(google-build-using-namespace)
525 using namespace panda_file_items::class_descriptors;
526
527 CacheClass(STRING, [](auto *c) { c->SetValueTyped(); });
528 undefinedClass_ = CacheClass(INTERNAL_UNDEFINED, [](auto *c) {
529 c->SetUndefined();
530 c->SetValueTyped();
531 });
532 auto const setupBoxedFlags = [](EtsClass *c) {
533 c->SetBoxed();
534 c->SetValueTyped();
535 };
536 boxBooleanClass_ = CacheClass(BOX_BOOLEAN, setupBoxedFlags);
537 boxByteClass_ = CacheClass(BOX_BYTE, setupBoxedFlags);
538 boxCharClass_ = CacheClass(BOX_CHAR, setupBoxedFlags);
539 boxShortClass_ = CacheClass(BOX_SHORT, setupBoxedFlags);
540 boxIntClass_ = CacheClass(BOX_INT, setupBoxedFlags);
541 boxLongClass_ = CacheClass(BOX_LONG, setupBoxedFlags);
542 boxFloatClass_ = CacheClass(BOX_FLOAT, setupBoxedFlags);
543 boxDoubleClass_ = CacheClass(BOX_DOUBLE, setupBoxedFlags);
544 bigintClass_ = CacheClass(BIG_INT, [](auto *c) {
545 c->SetBigInt();
546 c->SetValueTyped();
547 });
548 functionClass_ = CacheClass(FUNCTION, [](auto *c) { c->SetFunction(); });
549 }
550
InitializeBuiltinClasses()551 void EtsClassLinkerExtension::InitializeBuiltinClasses()
552 {
553 // NOLINTNEXTLINE(google-build-using-namespace)
554 using namespace panda_file_items::class_descriptors;
555
556 InitializeBuiltinSpecialClasses();
557
558 promiseClass_ = CacheClass(PROMISE);
559 if (promiseClass_ != nullptr) {
560 subscribeOnAnotherPromiseMethod_ = EtsMethod::ToRuntimeMethod(
561 EtsClass::FromRuntimeClass(promiseClass_)->GetMethod("subscribeOnAnotherPromise"));
562 ASSERT(subscribeOnAnotherPromiseMethod_ != nullptr);
563 }
564 promiseRefClass_ = CacheClass(PROMISE_REF);
565 waiterListClass_ = CacheClass(WAITERS_LIST);
566 mutexClass_ = CacheClass(MUTEX);
567 eventClass_ = CacheClass(EVENT);
568 condVarClass_ = CacheClass(COND_VAR);
569 exceptionClass_ = CacheClass(EXCEPTION);
570 errorClass_ = CacheClass(ERROR);
571 arraybufClass_ = CacheClass(ARRAY_BUFFER);
572 stringBuilderClass_ = CacheClass(STRING_BUILDER);
573 arrayAsListIntClass_ = CacheClass(ARRAY_AS_LIST_INT);
574 arrayClass_ = CacheClass(ARRAY);
575 typeapiFieldClass_ = CacheClass(FIELD);
576 typeapiMethodClass_ = CacheClass(METHOD);
577 typeapiParameterClass_ = CacheClass(PARAMETER);
578 sharedMemoryClass_ = CacheClass(SHARED_MEMORY);
579 jsvalueClass_ = CacheClass(JS_VALUE);
580 finalizableWeakClass_ = CacheClass(FINALIZABLE_WEAK_REF, [](auto *c) {
581 c->SetFinalizeReference();
582 c->SetWeakReference();
583 });
584 CacheClass(WEAK_REF, [](auto *c) { c->SetWeakReference(); });
585
586 auto coro = EtsCoroutine::GetCurrent();
587 coro->SetPromiseClass(promiseClass_);
588 // NOTE (electronick, #15938): Refactor the managed class-related pseudo TLS fields
589 // initialization in MT ManagedThread ctor and EtsCoroutine::Initialize
590 coro->SetStringClassPtr(GetClassRoot(ClassRoot::STRING));
591 coro->SetArrayU16ClassPtr(GetClassRoot(ClassRoot::ARRAY_U16));
592 coro->SetArrayU8ClassPtr(GetClassRoot(ClassRoot::ARRAY_U8));
593 }
594
595 } // namespace ark::ets
596