1 /**
2 * Copyright (c) 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 *tsClass *$1;
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_platform_types.h"
17 #include "ets_class_linker_extension.h"
18 #include "plugins/ets/runtime/ets_class_linker.h"
19 #include "plugins/ets/runtime/ets_panda_file_items.h"
20 #include "plugins/ets/runtime/types/ets_class.h"
21 #include "plugins/ets/runtime/types/ets_method.h"
22 #include "plugins/ets/runtime/ets_vm.h"
23
24 #include "runtime/include/class_linker-inl.h"
25
26 namespace ark::ets {
27
CreateAndInitializeCaches()28 void EtsPlatformTypes::CreateAndInitializeCaches()
29 {
30 auto *charClass = this->coreString;
31 asciiCharCache_ = EtsTypedObjectArray<EtsString>::Create(charClass, EtsPlatformTypes::ASCII_CHAR_TABLE_SIZE,
32 ark::SpaceType::SPACE_TYPE_OBJECT);
33 if (UNLIKELY(asciiCharCache_ == nullptr)) {
34 LOG(FATAL, RUNTIME) << "Failed to create asciiCharCache";
35 }
36
37 for (uint32_t i = 0; i < EtsPlatformTypes::ASCII_CHAR_TABLE_SIZE; ++i) {
38 auto *str = EtsString::CreateNewStringFromCharCode(i);
39 asciiCharCache_->Set(i, str);
40 }
41 }
42
VisitRoots(const GCRootVisitor & visitor) const43 void EtsPlatformTypes::VisitRoots(const GCRootVisitor &visitor) const
44 {
45 if (asciiCharCache_ != nullptr) {
46 visitor(mem::GCRoot(mem::RootType::ROOT_VM, asciiCharCache_->GetCoreType()));
47 }
48 }
49
UpdateCachesVmRefs(const GCRootUpdater & updater) const50 void EtsPlatformTypes::UpdateCachesVmRefs(const GCRootUpdater &updater) const
51 {
52 if (asciiCharCache_ != nullptr) {
53 auto *obj = static_cast<ark::ObjectHeader *>(asciiCharCache_->GetCoreType());
54 if (updater(&obj)) {
55 asciiCharCache_ = reinterpret_cast<EtsTypedObjectArray<EtsString> *>(obj);
56 }
57 }
58 }
59
PlatformTypes(PandaEtsVM * vm)60 EtsPlatformTypes const *PlatformTypes(PandaEtsVM *vm)
61 {
62 return vm->GetClassLinker()->GetEtsClassLinkerExtension()->GetPlatformTypes();
63 }
64
PlatformTypes()65 EtsPlatformTypes const *PlatformTypes()
66 {
67 return PlatformTypes(PandaEtsVM::GetCurrent());
68 }
69
70 class SuppressErrorHandler : public ClassLinkerErrorHandler {
OnError(ClassLinker::Error error,const PandaString & message)71 void OnError([[maybe_unused]] ClassLinker::Error error, [[maybe_unused]] const PandaString &message) override {}
72 };
73
FindType(EtsClassLinker * classLinker,std::string_view descriptor)74 static EtsClass *FindType(EtsClassLinker *classLinker, std::string_view descriptor)
75 {
76 SuppressErrorHandler handler;
77 auto bootCtx = classLinker->GetEtsClassLinkerExtension()->GetBootContext();
78 auto klass = classLinker->GetClass(descriptor.data(), false, bootCtx, &handler);
79 if (klass == nullptr) {
80 LOG(ERROR, RUNTIME) << "Cannot find a platform class " << descriptor;
81 return nullptr;
82 }
83 return klass;
84 }
85
86 template <bool IS_STATIC>
FindMethod(EtsClass * klass,char const * name,char const * signature)87 static EtsMethod *FindMethod(EtsClass *klass, char const *name, char const *signature)
88 {
89 if (klass == nullptr) {
90 return nullptr;
91 }
92
93 EtsMethod *method = [&]() {
94 if constexpr (IS_STATIC) {
95 return klass->GetStaticMethod(name, signature);
96 } else {
97 return klass->GetInstanceMethod(name, signature);
98 }
99 }();
100
101 if (method == nullptr) {
102 LOG(ERROR, RUNTIME) << "Method " << name << " is not found in class " << klass->GetDescriptor();
103 return nullptr;
104 }
105 return method;
106 }
107
108 // CC-OFFNXT(huge_method[C++], G.FUN.01-CPP, G.FUD.05) solid logic
EtsPlatformTypes(EtsCoroutine * coro)109 EtsPlatformTypes::EtsPlatformTypes([[maybe_unused]] EtsCoroutine *coro)
110 {
111 // NOLINTNEXTLINE(google-build-using-namespace)
112 using namespace panda_file_items::class_descriptors;
113
114 auto classLinker = PandaEtsVM::GetCurrent()->GetClassLinker();
115 auto const findType = [classLinker](std::string_view descriptor) { return FindType(classLinker, descriptor); };
116 coreString = findType(STRING);
117 coreBoolean = findType(BOX_BOOLEAN);
118 coreByte = findType(BOX_BYTE);
119 coreChar = findType(BOX_CHAR);
120 coreShort = findType(BOX_SHORT);
121 coreInt = findType(BOX_INT);
122 coreLong = findType(BOX_LONG);
123 coreFloat = findType(BOX_FLOAT);
124 coreObject = findType(OBJECT);
125 coreDouble = findType(BOX_DOUBLE);
126 escompatBigint = findType(BIG_INT);
127 coreFunction = findType(FUNCTION);
128
129 coreRuntimeLinker = findType(RUNTIME_LINKER);
130 coreBootRuntimeLinker = findType(BOOT_RUNTIME_LINKER);
131 coreAbcFile = findType(ABC_FILE);
132 coreAbcRuntimeLinker = findType(ABC_RUNTIME_LINKER);
133 memoryRuntimeLinker = findType(MEMORY_RUNTIME_LINKER);
134 corePromise = findType(PROMISE);
135 corePromiseSubscribeOnAnotherPromise =
136 FindMethod<false>(corePromise, "subscribeOnAnotherPromise", "Lstd/core/PromiseLike;:V");
137 corePromiseRef = findType(PROMISE_REF);
138 coreJob = findType(JOB);
139 coreWaitersList = findType(WAITERS_LIST);
140 coreMutex = findType(MUTEX);
141 coreEvent = findType(EVENT);
142 coreCondVar = findType(COND_VAR);
143 coreQueueSpinlock = findType(QUEUE_SPINLOCK);
144
145 coreException = findType(EXCEPTION);
146 escompatError = findType(ERROR);
147 coreOutOfMemoryError = findType(OUT_OF_MEMORY_ERROR);
148 escompatArrayBuffer = findType(ARRAY_BUFFER);
149 coreStringBuilder = findType(STRING_BUILDER);
150 containersArrayAsListInt = findType(ARRAY_AS_LIST_INT);
151 escompatArray = findType(ARRAY);
152
153 coreField = findType(FIELD);
154 coreMethod = findType(METHOD);
155 coreParameter = findType(PARAMETER);
156
157 interopJSValue = findType(JS_VALUE);
158
159 coreTupleN = findType(TUPLEN);
160
161 coreStackTraceElement = findType(STACK_TRACE_ELEMENT);
162
163 coreFinalizableWeakRef = findType(FINALIZABLE_WEAK_REF);
164 coreFinalizationRegistry = findType(FINALIZATION_REGISTRY);
165 coreFinalizationRegistryExecCleanup =
166 FindMethod<true>(coreFinalizationRegistry, "execCleanup", "[Lstd/core/WeakRef;I:V");
167
168 escompatRecord = findType(RECORD);
169 escompatRecordGetter = FindMethod<false>(escompatRecord, GET_INDEX_METHOD, nullptr);
170 escompatRecordSetter = FindMethod<false>(escompatRecord, SET_INDEX_METHOD, nullptr);
171
172 escompatProcess = findType(PROCESS);
173 escompatProcessListUnhandledJobs = FindMethod<true>(escompatProcess, "listUnhandledJobs", "Lescompat/Array;:V");
174 escompatProcessListUnhandledPromises =
175 FindMethod<true>(escompatProcess, "listUnhandledPromises", "Lescompat/Array;:V");
176
177 coreTuple = findType(TUPLE);
178 escompatRegExpExecArray = findType(REG_EXP_EXEC_ARRAY);
179 escompatJsonReplacer = findType(JSON_REPLACER);
180 if (LIKELY(Runtime::GetOptions().IsUseStringCaches())) {
181 CreateAndInitializeCaches();
182 }
183 }
184
185 } // namespace ark::ets
186