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
InitializeClassRoot()88 void EtsClassLinkerExtension::InitializeClassRoot()
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 // NB! By convention, class_class should be allocated first, so that all
133 // other class objects receive a pointer to it in their klass words.
134 // At the same time, std.core.Class is derived from std.core.Object, so we
135 // allocate object_class immediately after std.core.Class and manually adjust
136 // inheritance chain. After this, initialization order is not fixed.
137 auto classClass = CreateClassRoot(langCtx_.GetClassClassDescriptor(), ClassRoot::CLASS);
138
139 // EtsClass has reference fields, if they are not traversed in gc, then
140 // they can be either deallocated or moved
141 classClass->SetRefFieldsOffset(EtsClass::GCRefFieldsOffset(), false);
142 classClass->SetRefFieldsNum(EtsClass::GCRefFieldsNum(), false);
143 classClass->SetVolatileRefFieldsNum(0, false);
144
145 auto *objectClass = GetClassLinker()->GetClass(langCtx_.GetObjectClassDescriptor(), false, GetBootContext());
146 if (objectClass == nullptr) {
147 LOG(ERROR, CLASS_LINKER) << "Cannot create class '" << langCtx_.GetObjectClassDescriptor() << "'";
148 return false;
149 }
150
151 SetClassRoot(ClassRoot::OBJECT, objectClass);
152
153 ASSERT(classClass->GetBase() == nullptr);
154 classClass->SetBase(objectClass);
155
156 coretypes::String::SetCompressedStringsEnabled(compressedStringEnabled);
157
158 auto *stringClass = GetClassLinker()->GetClass(langCtx_.GetStringClassDescriptor(), false, GetBootContext());
159 if (stringClass == nullptr) {
160 LOG(ERROR, CLASS_LINKER) << "Cannot create class '" << langCtx_.GetStringClassDescriptor() << "'";
161 return false;
162 }
163
164 SetClassRoot(ClassRoot::STRING, stringClass);
165 stringClass->SetStringClass();
166
167 InitializeClassRoot();
168
169 return true;
170 }
171
InitializeArrayClass(Class * arrayClass,Class * componentClass)172 bool EtsClassLinkerExtension::InitializeArrayClass(Class *arrayClass, Class *componentClass)
173 {
174 ASSERT(IsInitialized());
175
176 ASSERT(!arrayClass->IsInitialized());
177 ASSERT(arrayClass->GetComponentType() == nullptr);
178
179 auto *objectClass = GetClassRoot(ClassRoot::OBJECT);
180 arrayClass->SetBase(objectClass);
181 arrayClass->SetComponentType(componentClass);
182
183 auto accessFlags = componentClass->GetAccessFlags() & ACC_FILE_MASK;
184 accessFlags &= ~ACC_INTERFACE;
185 accessFlags |= ACC_FINAL | ACC_ABSTRACT;
186
187 arrayClass->SetAccessFlags(accessFlags);
188
189 auto objectClassVtable = objectClass->GetVTable();
190 auto arrayClassVtable = arrayClass->GetVTable();
191 for (size_t i = 0; i < objectClassVtable.size(); i++) {
192 arrayClassVtable[i] = objectClassVtable[i];
193 }
194
195 arrayClass->SetState(Class::State::INITIALIZED);
196
197 ASSERT(arrayClass->IsArrayClass()); // After init, we give out a well-formed array class.
198 return true;
199 }
200
InitializeClass(Class * klass)201 bool EtsClassLinkerExtension::InitializeClass(Class *klass)
202 {
203 ASSERT(IsInitialized());
204 ASSERT_HAVE_ACCESS_TO_MANAGED_OBJECTS();
205
206 constexpr uint32_t ETS_ACCESS_FLAGS_MASK = 0xFFFFU;
207
208 EtsClass::FromRuntimeClass(klass)->Initialize(
209 klass->GetBase() != nullptr ? EtsClass::FromRuntimeClass(klass->GetBase()) : nullptr,
210 klass->GetAccessFlags() & ETS_ACCESS_FLAGS_MASK, klass->IsPrimitive());
211
212 return true;
213 }
214
InitializePrimitiveClass(Class * primitiveClass)215 void EtsClassLinkerExtension::InitializePrimitiveClass(Class *primitiveClass)
216 {
217 ASSERT(IsInitialized());
218
219 ASSERT(!primitiveClass->IsInitialized());
220 ASSERT(primitiveClass->IsPrimitive());
221
222 primitiveClass->SetAccessFlags(ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT);
223 primitiveClass->SetState(Class::State::INITIALIZED);
224 }
225
GetClassVTableSize(ClassRoot root)226 size_t EtsClassLinkerExtension::GetClassVTableSize(ClassRoot root)
227 {
228 ASSERT(IsInitialized());
229
230 switch (root) {
231 case ClassRoot::V:
232 case ClassRoot::U1:
233 case ClassRoot::I8:
234 case ClassRoot::U8:
235 case ClassRoot::I16:
236 case ClassRoot::U16:
237 case ClassRoot::I32:
238 case ClassRoot::U32:
239 case ClassRoot::I64:
240 case ClassRoot::U64:
241 case ClassRoot::F32:
242 case ClassRoot::F64:
243 case ClassRoot::TAGGED:
244 return 0;
245 case ClassRoot::ARRAY_U1:
246 case ClassRoot::ARRAY_I8:
247 case ClassRoot::ARRAY_U8:
248 case ClassRoot::ARRAY_I16:
249 case ClassRoot::ARRAY_U16:
250 case ClassRoot::ARRAY_I32:
251 case ClassRoot::ARRAY_U32:
252 case ClassRoot::ARRAY_I64:
253 case ClassRoot::ARRAY_U64:
254 case ClassRoot::ARRAY_F32:
255 case ClassRoot::ARRAY_F64:
256 case ClassRoot::ARRAY_TAGGED:
257 case ClassRoot::ARRAY_CLASS:
258 case ClassRoot::ARRAY_STRING:
259 return GetArrayClassVTableSize();
260 case ClassRoot::OBJECT:
261 case ClassRoot::STRING:
262 return GetClassRoot(root)->GetVTableSize();
263 case ClassRoot::CLASS:
264 return 0;
265 default: {
266 break;
267 }
268 }
269
270 UNREACHABLE();
271 return 0;
272 }
273
GetClassIMTSize(ClassRoot root)274 size_t EtsClassLinkerExtension::GetClassIMTSize(ClassRoot root)
275 {
276 ASSERT(IsInitialized());
277
278 switch (root) {
279 case ClassRoot::V:
280 case ClassRoot::U1:
281 case ClassRoot::I8:
282 case ClassRoot::U8:
283 case ClassRoot::I16:
284 case ClassRoot::U16:
285 case ClassRoot::I32:
286 case ClassRoot::U32:
287 case ClassRoot::I64:
288 case ClassRoot::U64:
289 case ClassRoot::F32:
290 case ClassRoot::F64:
291 case ClassRoot::TAGGED:
292 return 0;
293 case ClassRoot::ARRAY_U1:
294 case ClassRoot::ARRAY_I8:
295 case ClassRoot::ARRAY_U8:
296 case ClassRoot::ARRAY_I16:
297 case ClassRoot::ARRAY_U16:
298 case ClassRoot::ARRAY_I32:
299 case ClassRoot::ARRAY_U32:
300 case ClassRoot::ARRAY_I64:
301 case ClassRoot::ARRAY_U64:
302 case ClassRoot::ARRAY_F32:
303 case ClassRoot::ARRAY_F64:
304 case ClassRoot::ARRAY_TAGGED:
305 case ClassRoot::ARRAY_CLASS:
306 case ClassRoot::ARRAY_STRING:
307 return GetArrayClassIMTSize();
308 case ClassRoot::OBJECT:
309 case ClassRoot::CLASS:
310 case ClassRoot::STRING:
311 return 0;
312 default: {
313 break;
314 }
315 }
316
317 UNREACHABLE();
318 return 0;
319 }
320
GetClassSize(ClassRoot root)321 size_t EtsClassLinkerExtension::GetClassSize(ClassRoot root)
322 {
323 ASSERT(IsInitialized());
324
325 switch (root) {
326 case ClassRoot::V:
327 case ClassRoot::U1:
328 case ClassRoot::I8:
329 case ClassRoot::U8:
330 case ClassRoot::I16:
331 case ClassRoot::U16:
332 case ClassRoot::I32:
333 case ClassRoot::U32:
334 case ClassRoot::I64:
335 case ClassRoot::U64:
336 case ClassRoot::F32:
337 case ClassRoot::F64:
338 case ClassRoot::TAGGED:
339 return Class::ComputeClassSize(GetClassVTableSize(root), GetClassIMTSize(root), 0, 0, 0, 0, 0, 0);
340 case ClassRoot::ARRAY_U1:
341 case ClassRoot::ARRAY_I8:
342 case ClassRoot::ARRAY_U8:
343 case ClassRoot::ARRAY_I16:
344 case ClassRoot::ARRAY_U16:
345 case ClassRoot::ARRAY_I32:
346 case ClassRoot::ARRAY_U32:
347 case ClassRoot::ARRAY_I64:
348 case ClassRoot::ARRAY_U64:
349 case ClassRoot::ARRAY_F32:
350 case ClassRoot::ARRAY_F64:
351 case ClassRoot::ARRAY_TAGGED:
352 case ClassRoot::ARRAY_CLASS:
353 case ClassRoot::ARRAY_STRING:
354 return GetArrayClassSize();
355 case ClassRoot::OBJECT:
356 case ClassRoot::CLASS:
357 case ClassRoot::STRING:
358 return Class::ComputeClassSize(GetClassVTableSize(root), GetClassIMTSize(root), 0, 0, 0, 0, 0, 0);
359 default: {
360 break;
361 }
362 }
363
364 UNREACHABLE();
365 return 0;
366 }
367
GetArrayClassVTableSize()368 size_t EtsClassLinkerExtension::GetArrayClassVTableSize()
369 {
370 ASSERT(IsInitialized());
371
372 return GetClassVTableSize(ClassRoot::OBJECT);
373 }
374
GetArrayClassIMTSize()375 size_t EtsClassLinkerExtension::GetArrayClassIMTSize()
376 {
377 ASSERT(IsInitialized());
378
379 return GetClassIMTSize(ClassRoot::OBJECT);
380 }
381
GetArrayClassSize()382 size_t EtsClassLinkerExtension::GetArrayClassSize()
383 {
384 ASSERT(IsInitialized());
385
386 return GetClassSize(ClassRoot::OBJECT);
387 }
388
InitializeClass(ObjectHeader * objectHeader,const uint8_t * descriptor,size_t vtableSize,size_t imtSize,size_t size)389 Class *EtsClassLinkerExtension::InitializeClass(ObjectHeader *objectHeader, const uint8_t *descriptor,
390 size_t vtableSize, size_t imtSize, size_t size)
391 {
392 auto managedClass = reinterpret_cast<EtsClass *>(objectHeader);
393 managedClass->InitClass(descriptor, vtableSize, imtSize, size);
394 auto klass = managedClass->GetRuntimeClass();
395 klass->SetManagedObject(objectHeader);
396 klass->SetSourceLang(GetLanguage());
397
398 AddCreatedClass(klass);
399
400 return klass;
401 }
402
CreateClass(const uint8_t * descriptor,size_t vtableSize,size_t imtSize,size_t size)403 Class *EtsClassLinkerExtension::CreateClass(const uint8_t *descriptor, size_t vtableSize, size_t imtSize, size_t size)
404 {
405 ASSERT(IsInitialized());
406
407 auto classRoot = GetClassRoot(ClassRoot::CLASS);
408 ASSERT(classRoot != nullptr);
409
410 auto objectHeader = heapManager_->AllocateNonMovableObject<false>(classRoot, EtsClass::GetSize(size));
411 if (UNLIKELY(objectHeader == nullptr)) {
412 return nullptr;
413 }
414
415 return InitializeClass(objectHeader, descriptor, vtableSize, imtSize, size);
416 }
417
CreateClassRoot(const uint8_t * descriptor,ClassRoot root)418 Class *EtsClassLinkerExtension::CreateClassRoot(const uint8_t *descriptor, ClassRoot root)
419 {
420 auto vtableSize = GetClassVTableSize(root);
421 auto imtSize = GetClassIMTSize(root);
422 auto size = GetClassSize(root);
423
424 Class *klass;
425 if (root == ClassRoot::CLASS) {
426 ASSERT(GetClassRoot(ClassRoot::CLASS) == nullptr);
427 auto objectHeader = heapManager_->AllocateNonMovableObject<true>(nullptr, EtsClass::GetSize(size));
428 ASSERT(objectHeader != nullptr);
429
430 klass = InitializeClass(objectHeader, descriptor, vtableSize, imtSize, size);
431 klass->SetObjectSize(EtsClass::GetSize(size));
432 EtsClass::FromRuntimeClass(klass)->AsObject()->SetClass(EtsClass::FromRuntimeClass(klass));
433 } else {
434 klass = CreateClass(descriptor, vtableSize, imtSize, size);
435 }
436
437 ASSERT(klass != nullptr);
438 klass->SetBase(GetClassRoot(ClassRoot::OBJECT));
439 klass->SetState(Class::State::LOADED);
440 klass->SetLoadContext(GetBootContext());
441 GetClassLinker()->AddClassRoot(root, klass);
442 return klass;
443 }
444
FreeClass(Class * klass)445 void EtsClassLinkerExtension::FreeClass(Class *klass)
446 {
447 ASSERT(IsInitialized());
448
449 RemoveCreatedClass(klass);
450 }
451
~EtsClassLinkerExtension()452 EtsClassLinkerExtension::~EtsClassLinkerExtension()
453 {
454 if (!IsInitialized()) {
455 return;
456 }
457
458 FreeLoadedClasses();
459 }
460
GetNativeEntryPointFor(Method * method) const461 const void *EtsClassLinkerExtension::GetNativeEntryPointFor(Method *method) const
462 {
463 panda_file::File::EntityId asyncAnnId = EtsAnnotation::FindAsyncAnnotation(method);
464 if (asyncAnnId.IsValid()) {
465 return reinterpret_cast<const void *>(EtsAsyncEntryPoint);
466 }
467 switch (GetEtsNapiType(method)) {
468 case EtsNapiType::GENERIC: {
469 return napi::GetEtsNapiEntryPoint();
470 }
471 case EtsNapiType::FAST: {
472 auto flags = method->GetAccessFlags();
473 flags |= ACC_FAST_NATIVE;
474 method->SetAccessFlags(flags);
475
476 return napi::GetEtsNapiEntryPoint();
477 }
478 case EtsNapiType::CRITICAL: {
479 auto flags = method->GetAccessFlags();
480 flags |= ACC_CRITICAL_NATIVE;
481 method->SetAccessFlags(flags);
482
483 return napi::GetEtsNapiCriticalEntryPoint();
484 }
485 }
486
487 UNREACHABLE();
488 }
489
FromClassObject(ark::ObjectHeader * obj)490 Class *EtsClassLinkerExtension::FromClassObject(ark::ObjectHeader *obj)
491 {
492 return obj != nullptr ? reinterpret_cast<EtsClass *>(obj)->GetRuntimeClass() : nullptr;
493 }
494
GetClassObjectSizeFromClassSize(uint32_t size)495 size_t EtsClassLinkerExtension::GetClassObjectSizeFromClassSize(uint32_t size)
496 {
497 return EtsClass::GetSize(size);
498 }
499
CacheClass(std::string_view descriptor,bool forceInit)500 Class *EtsClassLinkerExtension::CacheClass(std::string_view descriptor, bool forceInit)
501 {
502 Class *cls = GetClassLinker()->GetClass(utf::CStringAsMutf8(descriptor.data()), false, GetBootContext());
503 if (cls == nullptr) {
504 LOG(ERROR, CLASS_LINKER) << "Cannot create class " << descriptor;
505 return nullptr;
506 }
507 if (forceInit && !GetClassLinker()->InitializeClass(EtsCoroutine::GetCurrent(), cls)) {
508 LOG(ERROR, CLASS_LINKER) << "Cannot initialize class " << descriptor;
509 return nullptr;
510 }
511 return cls;
512 }
513
514 template <typename F>
CacheClass(std::string_view descriptor,F const & setup,bool forceInit)515 Class *EtsClassLinkerExtension::CacheClass(std::string_view descriptor, F const &setup, bool forceInit)
516 {
517 Class *cls = CacheClass(descriptor, forceInit);
518 if (cls != nullptr) {
519 setup(EtsClass::FromRuntimeClass(cls));
520 }
521 return cls;
522 }
523
InitializeBuiltinClasses()524 void EtsClassLinkerExtension::InitializeBuiltinClasses()
525 {
526 // NOLINTNEXTLINE(google-build-using-namespace)
527 using namespace panda_file_items::class_descriptors;
528
529 CacheClass(STRING, [](auto *c) { c->SetValueTyped(); });
530 undefinedClass_ = CacheClass(INTERNAL_UNDEFINED, [](auto *c) { c->SetValueTyped(); });
531 boxBooleanClass_ = CacheClass(BOX_BOOLEAN, [](auto *c) { c->SetValueTyped(); });
532 boxByteClass_ = CacheClass(BOX_BYTE, [](auto *c) { c->SetValueTyped(); });
533 boxCharClass_ = CacheClass(BOX_CHAR, [](auto *c) { c->SetValueTyped(); });
534 boxShortClass_ = CacheClass(BOX_SHORT, [](auto *c) { c->SetValueTyped(); });
535 boxIntClass_ = CacheClass(BOX_INT, [](auto *c) { c->SetValueTyped(); });
536 boxLongClass_ = CacheClass(BOX_LONG, [](auto *c) { c->SetValueTyped(); });
537 boxFloatClass_ = CacheClass(BOX_FLOAT, [](auto *c) { c->SetValueTyped(); });
538 boxDoubleClass_ = CacheClass(BOX_DOUBLE, [](auto *c) { c->SetValueTyped(); });
539 bigintClass_ = CacheClass(BIG_INT, [](auto *c) { c->SetValueTyped(); });
540 promiseClass_ = CacheClass(PROMISE);
541 if (promiseClass_ != nullptr) {
542 subscribeOnAnotherPromiseMethod_ = EtsMethod::ToRuntimeMethod(
543 EtsClass::FromRuntimeClass(promiseClass_)->GetMethod("subscribeOnAnotherPromise"));
544 ASSERT(subscribeOnAnotherPromiseMethod_ != nullptr);
545 }
546 promiseRefClass_ = CacheClass(PROMISE_REF);
547 exceptionClass_ = CacheClass(EXCEPTION);
548 errorClass_ = CacheClass(ERROR);
549 arraybufClass_ = CacheClass(ARRAY_BUFFER);
550 stringBuilderClass_ = CacheClass(STRING_BUILDER);
551 arrayAsListIntClass_ = CacheClass(ARRAY_AS_LIST_INT);
552 arrayClass_ = CacheClass(ARRAY);
553 typeapiFieldClass_ = CacheClass(FIELD);
554 typeapiMethodClass_ = CacheClass(METHOD);
555 typeapiParameterClass_ = CacheClass(PARAMETER);
556 ifuncClass_ = CacheClass(IFUNCTION);
557 sharedMemoryClass_ = CacheClass(SHARED_MEMORY);
558 jsvalueClass_ = CacheClass(JS_VALUE);
559 finalizableWeakClass_ = CacheClass(FINALIZABLE_WEAK_REF, [](auto *c) {
560 c->SetFinalizeReference();
561 c->SetWeakReference();
562 });
563 CacheClass(WEAK_REF, [](auto *c) { c->SetWeakReference(); });
564
565 auto coro = EtsCoroutine::GetCurrent();
566 coro->SetPromiseClass(promiseClass_);
567 // NOTE (electronick, #15938): Refactor the managed class-related pseudo TLS fields
568 // initialization in MT ManagedThread ctor and EtsCoroutine::Initialize
569 coro->SetStringClassPtr(GetClassRoot(ClassRoot::STRING));
570 coro->SetArrayU16ClassPtr(GetClassRoot(ClassRoot::ARRAY_U16));
571 }
572
573 } // namespace ark::ets
574