• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <string>
17 
18 #include "ets_runtime_interface.h"
19 #include "plugins/ets/runtime/ets_class_linker_extension.h"
20 #include "types/ets_method.h"
21 
22 namespace ark::ets {
GetClass(MethodPtr method,IdType id) const23 compiler::RuntimeInterface::ClassPtr EtsRuntimeInterface::GetClass(MethodPtr method, IdType id) const
24 {
25     if (id == RuntimeInterface::MEM_PROMISE_CLASS_ID) {
26         ScopedMutatorLock lock;
27         auto *caller = MethodCast(method);
28         LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(*caller);
29         return static_cast<EtsClassLinkerExtension *>(Runtime::GetCurrent()->GetClassLinker()->GetExtension(ctx))
30             ->GetPromiseClass();
31     }
32     return PandaRuntimeInterface::GetClass(method, id);
33 }
34 
ResolveLookUpField(FieldPtr rawField,ClassPtr klass)35 compiler::RuntimeInterface::FieldPtr EtsRuntimeInterface::ResolveLookUpField(FieldPtr rawField, ClassPtr klass)
36 {
37     ScopedMutatorLock lock;
38     ASSERT(rawField != nullptr);
39     ASSERT(klass != nullptr);
40     return ClassCast(klass)->LookupFieldByName(FieldCast(rawField)->GetName());
41 }
42 
43 template <panda_file::Type::TypeId FIELD_TYPE>
GetLookUpCall(FieldPtr rawField,ClassPtr klass,bool isSetter)44 compiler::RuntimeInterface::MethodPtr EtsRuntimeInterface::GetLookUpCall(FieldPtr rawField, ClassPtr klass,
45                                                                          bool isSetter)
46 {
47     if (isSetter) {
48         return ClassCast(klass)->LookupSetterByName<FIELD_TYPE>(FieldCast(rawField)->GetName());
49     }
50     return ClassCast(klass)->LookupGetterByName<FIELD_TYPE>(FieldCast(rawField)->GetName());
51 }
52 
ResolveLookUpCall(FieldPtr rawField,ClassPtr klass,bool isSetter)53 compiler::RuntimeInterface::MethodPtr EtsRuntimeInterface::ResolveLookUpCall(FieldPtr rawField, ClassPtr klass,
54                                                                              bool isSetter)
55 {
56     ScopedMutatorLock lock;
57     ASSERT(rawField != nullptr);
58     ASSERT(klass != nullptr);
59     switch (FieldCast(rawField)->GetTypeId()) {
60         case panda_file::Type::TypeId::U1:
61             return GetLookUpCall<panda_file::Type::TypeId::U1>(rawField, klass, isSetter);
62         case panda_file::Type::TypeId::U8:
63             return GetLookUpCall<panda_file::Type::TypeId::U8>(rawField, klass, isSetter);
64         case panda_file::Type::TypeId::I8:
65             return GetLookUpCall<panda_file::Type::TypeId::I8>(rawField, klass, isSetter);
66         case panda_file::Type::TypeId::I16:
67             return GetLookUpCall<panda_file::Type::TypeId::I16>(rawField, klass, isSetter);
68         case panda_file::Type::TypeId::U16:
69             return GetLookUpCall<panda_file::Type::TypeId::U16>(rawField, klass, isSetter);
70         case panda_file::Type::TypeId::I32:
71             return GetLookUpCall<panda_file::Type::TypeId::I32>(rawField, klass, isSetter);
72         case panda_file::Type::TypeId::U32:
73             return GetLookUpCall<panda_file::Type::TypeId::U32>(rawField, klass, isSetter);
74         case panda_file::Type::TypeId::I64:
75             return GetLookUpCall<panda_file::Type::TypeId::I64>(rawField, klass, isSetter);
76         case panda_file::Type::TypeId::U64:
77             return GetLookUpCall<panda_file::Type::TypeId::U64>(rawField, klass, isSetter);
78         case panda_file::Type::TypeId::F32:
79             return GetLookUpCall<panda_file::Type::TypeId::F32>(rawField, klass, isSetter);
80         case panda_file::Type::TypeId::F64:
81             return GetLookUpCall<panda_file::Type::TypeId::F64>(rawField, klass, isSetter);
82         case panda_file::Type::TypeId::REFERENCE:
83             return GetLookUpCall<panda_file::Type::TypeId::REFERENCE>(rawField, klass, isSetter);
84         default: {
85             UNREACHABLE();
86             break;
87         }
88     }
89     return nullptr;
90 }
91 
GetUndefinedObject() const92 uint64_t EtsRuntimeInterface::GetUndefinedObject() const
93 {
94     return ToUintPtr(PandaEtsVM::GetCurrent()->GetUndefinedObject());
95 }
96 
GetInteropCallKind(MethodPtr methodPtr) const97 compiler::RuntimeInterface::InteropCallKind EtsRuntimeInterface::GetInteropCallKind(MethodPtr methodPtr) const
98 {
99     auto className = GetClassNameFromMethod(methodPtr);
100     auto classNameSuffix = className.substr(className.find_last_of('.') + 1);
101     if (classNameSuffix == "$jsnew") {
102         return InteropCallKind::NEW_INSTANCE;
103     }
104     if (classNameSuffix != "$jscall") {
105         return InteropCallKind::UNKNOWN;
106     }
107 
108     auto method = MethodCast(methodPtr);
109 
110     ScopedMutatorLock lock;
111 
112     ASSERT(method->GetArgType(0).IsReference());  // arg0 is always a reference
113     if (method->GetArgType(1).IsReference()) {
114         auto pf = method->GetPandaFile();
115         panda_file::ProtoDataAccessor pda(*pf, panda_file::MethodDataAccessor::GetProtoId(*pf, method->GetFileId()));
116         ClassLinker *classLinker = Runtime::GetCurrent()->GetClassLinker();
117         LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(*method);
118         auto linkerCtx = static_cast<EtsClassLinkerExtension *>(classLinker->GetExtension(ctx))->GetBootContext();
119         uint32_t const argReftypeShift = method->GetReturnType().IsReference() ? 1 : 0;
120         auto cls = classLinker->GetClass(*pf, pda.GetReferenceType(1 + argReftypeShift), linkerCtx);
121         if (!cls->IsStringClass()) {
122             return InteropCallKind::CALL_BY_VALUE;
123         }
124     } else {
125         // arg1 and arg2 are start position and length of qualified name
126         ASSERT(method->GetArgType(1).GetId() == panda_file::Type::TypeId::I32);
127         ASSERT(method->GetArgType(2U).GetId() == panda_file::Type::TypeId::I32);
128     }
129     return InteropCallKind::CALL;
130 }
131 
GetFuncPropName(MethodPtr methodPtr,uint32_t strId) const132 char *EtsRuntimeInterface::GetFuncPropName(MethodPtr methodPtr, uint32_t strId) const
133 {
134     auto method = MethodCast(methodPtr);
135     auto pf = method->GetPandaFile();
136     auto str = reinterpret_cast<const char *>(pf->GetStringData(ark::panda_file::File::EntityId(strId)).data);
137     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
138     return const_cast<char *>(std::strrchr(str, '.') + 1);
139 }
140 
GetFuncPropNameOffset(MethodPtr methodPtr,uint32_t strId) const141 uint64_t EtsRuntimeInterface::GetFuncPropNameOffset(MethodPtr methodPtr, uint32_t strId) const
142 {
143     auto pf = MethodCast(methodPtr)->GetPandaFile();
144     auto str = GetFuncPropName(methodPtr, strId);
145     return reinterpret_cast<uint64_t>(str) - reinterpret_cast<uint64_t>(pf->GetBase());
146 }
147 
IsMethodStringConcat(MethodPtr method) const148 bool EtsRuntimeInterface::IsMethodStringConcat(MethodPtr method) const
149 {
150     return GetClassNameFromMethod(method) == "std.core.String" &&
151            MethodCast(method)->GetProto().GetSignature() == "([Lstd/core/String;)Lstd/core/String;";
152 }
153 
IsMethodStringBuilderConstructorWithStringArg(MethodPtr method) const154 bool EtsRuntimeInterface::IsMethodStringBuilderConstructorWithStringArg(MethodPtr method) const
155 {
156     return MethodCast(method)->IsConstructor() && GetClassNameFromMethod(method) == "std.core.StringBuilder" &&
157            MethodCast(method)->GetProto().GetSignature() == "(Lstd/core/String;)V";
158 }
159 
IsMethodStringBuilderConstructorWithCharArrayArg(MethodPtr method) const160 bool EtsRuntimeInterface::IsMethodStringBuilderConstructorWithCharArrayArg(MethodPtr method) const
161 {
162     return MethodCast(method)->IsConstructor() && GetClassNameFromMethod(method) == "std.core.StringBuilder" &&
163            MethodCast(method)->GetProto().GetSignature() == "([C)V";
164 }
165 
IsMethodStringBuilderDefaultConstructor(MethodPtr method) const166 bool EtsRuntimeInterface::IsMethodStringBuilderDefaultConstructor(MethodPtr method) const
167 {
168     return MethodCast(method)->IsConstructor() && GetClassNameFromMethod(method) == "std.core.StringBuilder" &&
169            MethodCast(method)->GetProto().GetSignature() == "()V";
170 }
171 
IsMethodStringBuilderToString(MethodPtr method) const172 bool EtsRuntimeInterface::IsMethodStringBuilderToString(MethodPtr method) const
173 {
174     return GetMethodFullName(method, false) == "std.core.StringBuilder::toString" &&
175            MethodCast(method)->GetProto().GetSignature() == "()Lstd/core/String;";
176 }
177 
IsMethodStringBuilderAppend(MethodPtr method) const178 bool EtsRuntimeInterface::IsMethodStringBuilderAppend(MethodPtr method) const
179 {
180     return GetMethodFullName(method, false) == "std.core.StringBuilder::append";
181 }
182 
IsClassStringBuilder(ClassPtr klass) const183 bool EtsRuntimeInterface::IsClassStringBuilder(ClassPtr klass) const
184 {
185     return ClassCast(klass)->GetName() == "std.core.StringBuilder";
186 }
187 
GetClassOffsetObjectsArray(MethodPtr method) const188 uint32_t EtsRuntimeInterface::GetClassOffsetObjectsArray(MethodPtr method) const
189 {
190     auto pf = MethodCast(method)->GetPandaFile();
191     return pf->GetClassId(utf::CStringAsMutf8("[Lstd/core/Object;")).GetOffset();
192 }
193 
GetClassOffsetObject(MethodPtr method) const194 uint32_t EtsRuntimeInterface::GetClassOffsetObject(MethodPtr method) const
195 {
196     auto pf = MethodCast(method)->GetPandaFile();
197     return pf->GetClassId(utf::CStringAsMutf8("std.core.Object")).GetOffset();
198 }
199 
GetStringBuilderClass() const200 EtsRuntimeInterface::ClassPtr EtsRuntimeInterface::GetStringBuilderClass() const
201 {
202     LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(SourceLanguage::ETS);
203     return static_cast<EtsClassLinkerExtension *>(Runtime::GetCurrent()->GetClassLinker()->GetExtension(ctx))
204         ->GetStringBuilderClass();
205 }
206 
GetStringBuilderDefaultConstructor() const207 EtsRuntimeInterface::MethodPtr EtsRuntimeInterface::GetStringBuilderDefaultConstructor() const
208 {
209     auto classLinker = PandaEtsVM::GetCurrent()->GetClassLinker();
210     for (auto ctor : classLinker->GetStringBuilderClass()->GetConstructors()) {
211         if (IsMethodStringBuilderDefaultConstructor(ctor)) {
212             return ctor;
213         }
214     }
215 
216     UNREACHABLE();
217 }
218 
GetMethodId(MethodPtr method) const219 uint32_t EtsRuntimeInterface::GetMethodId(MethodPtr method) const
220 {
221     ASSERT(method != nullptr);
222     return static_cast<EtsMethod *>(method)->GetMethodId();
223 }
224 
GetFieldStringBuilderBuffer(ClassPtr klass) const225 EtsRuntimeInterface::FieldPtr EtsRuntimeInterface::GetFieldStringBuilderBuffer(ClassPtr klass) const
226 {
227     ASSERT(IsClassStringBuilder(klass));
228     return ClassCast(klass)->GetInstanceFieldByName(utf::CStringAsMutf8("buf"));
229 }
230 
GetFieldStringBuilderIndex(ClassPtr klass) const231 EtsRuntimeInterface::FieldPtr EtsRuntimeInterface::GetFieldStringBuilderIndex(ClassPtr klass) const
232 {
233     ASSERT(IsClassStringBuilder(klass));
234     return ClassCast(klass)->GetInstanceFieldByName(utf::CStringAsMutf8("index"));
235 }
236 
GetFieldStringBuilderLength(ClassPtr klass) const237 EtsRuntimeInterface::FieldPtr EtsRuntimeInterface::GetFieldStringBuilderLength(ClassPtr klass) const
238 {
239     ASSERT(IsClassStringBuilder(klass));
240     return ClassCast(klass)->GetInstanceFieldByName(utf::CStringAsMutf8("length"));
241 }
242 
GetFieldStringBuilderCompress(ClassPtr klass) const243 EtsRuntimeInterface::FieldPtr EtsRuntimeInterface::GetFieldStringBuilderCompress(ClassPtr klass) const
244 {
245     ASSERT(IsClassStringBuilder(klass));
246     return ClassCast(klass)->GetInstanceFieldByName(utf::CStringAsMutf8("compress"));
247 }
248 
IsFieldStringBuilderBuffer(FieldPtr field) const249 bool EtsRuntimeInterface::IsFieldStringBuilderBuffer(FieldPtr field) const
250 {
251     return IsClassStringBuilder(FieldCast(field)->GetClass()) && GetFieldName(field) == "buf";
252 }
253 
IsFieldStringBuilderIndex(FieldPtr field) const254 bool EtsRuntimeInterface::IsFieldStringBuilderIndex(FieldPtr field) const
255 {
256     return IsClassStringBuilder(FieldCast(field)->GetClass()) && GetFieldName(field) == "index";
257 }
258 
IsIntrinsicStringBuilderToString(IntrinsicId id) const259 bool EtsRuntimeInterface::IsIntrinsicStringBuilderToString(IntrinsicId id) const
260 {
261     return id == RuntimeInterface::IntrinsicId::INTRINSIC_STD_CORE_SB_TO_STRING;
262 }
263 
IsIntrinsicStringBuilderAppendString(IntrinsicId id) const264 bool EtsRuntimeInterface::IsIntrinsicStringBuilderAppendString(IntrinsicId id) const
265 {
266     return id == IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING;
267 }
268 
IsIntrinsicStringBuilderAppend(IntrinsicId id) const269 bool EtsRuntimeInterface::IsIntrinsicStringBuilderAppend(IntrinsicId id) const
270 {
271     switch (id) {
272         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_FLOAT:
273             return true;
274         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_DOUBLE:
275             return true;
276         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_LONG:
277             return true;
278         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_INT:
279             return true;
280         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_BYTE:
281             return true;
282         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_SHORT:
283             return true;
284         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_CHAR:
285             return true;
286         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_BOOL:
287             return true;
288         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING:
289             return true;
290         default:
291             return false;
292     }
293 }
294 
ConvertTypeToStringBuilderAppendIntrinsicId(compiler::DataType::Type type) const295 EtsRuntimeInterface::IntrinsicId EtsRuntimeInterface::ConvertTypeToStringBuilderAppendIntrinsicId(
296     compiler::DataType::Type type) const
297 {
298     switch (type) {
299         case compiler::DataType::BOOL:
300             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_BOOL;
301         case compiler::DataType::INT8:
302             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_CHAR;
303         case compiler::DataType::UINT8:
304             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_BYTE;
305         case compiler::DataType::INT16:
306             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_SHORT;
307         case compiler::DataType::INT32:
308             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_INT;
309         case compiler::DataType::INT64:
310             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_LONG;
311         case compiler::DataType::FLOAT64:
312             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_DOUBLE;
313         case compiler::DataType::FLOAT32:
314             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_FLOAT;
315         case compiler::DataType::REFERENCE:
316             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING;
317         default:
318             UNREACHABLE();
319     }
320     return IntrinsicId::INVALID;
321 }
322 
GetStringConcatStringsIntrinsicId(size_t numArgs) const323 EtsRuntimeInterface::IntrinsicId EtsRuntimeInterface::GetStringConcatStringsIntrinsicId(size_t numArgs) const
324 {
325     // NOLINTBEGIN(readability-magic-numbers)
326     switch (numArgs) {
327         case 2U:
328             return IntrinsicId::INTRINSIC_STD_CORE_STRING_CONCAT2;
329         case 3U:
330             return IntrinsicId::INTRINSIC_STD_CORE_STRING_CONCAT3;
331         case 4U:
332             return IntrinsicId::INTRINSIC_STD_CORE_STRING_CONCAT4;
333         default:
334             UNREACHABLE();
335     }
336     // NOLINTEND(readability-magic-numbers)
337 }
338 
GetStringIsCompressedIntrinsicId() const339 EtsRuntimeInterface::IntrinsicId EtsRuntimeInterface::GetStringIsCompressedIntrinsicId() const
340 {
341     return IntrinsicId::INTRINSIC_STD_CORE_STRING_IS_COMPRESSED;
342 }
343 
GetStringBuilderAppendStringIntrinsicId() const344 EtsRuntimeInterface::IntrinsicId EtsRuntimeInterface::GetStringBuilderAppendStringIntrinsicId() const
345 {
346     return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING;
347 }
348 
GetStringBuilderToStringIntrinsicId() const349 EtsRuntimeInterface::IntrinsicId EtsRuntimeInterface::GetStringBuilderToStringIntrinsicId() const
350 {
351     return IntrinsicId::INTRINSIC_STD_CORE_SB_TO_STRING;
352 }
353 
IsClassValueTyped(ClassPtr klass) const354 bool EtsRuntimeInterface::IsClassValueTyped(ClassPtr klass) const
355 {
356     return EtsClass::FromRuntimeClass(ClassCast(klass))->IsValueTyped();
357 }
358 
GetDoubleToStringCache() const359 void *EtsRuntimeInterface::GetDoubleToStringCache() const
360 {
361     return ark::ets::PandaEtsVM::GetCurrent()->GetDoubleToStringCache();
362 }
363 
364 }  // namespace ark::ets
365