• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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