• 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         return PandaEtsVM::GetCurrent()->GetClassLinker()->GetEtsClassLinkerExtension()->GetPromiseClass();
27     }
28     return PandaRuntimeInterface::GetClass(method, id);
29 }
30 
ResolveLookUpField(FieldPtr rawField,ClassPtr klass)31 compiler::RuntimeInterface::FieldPtr EtsRuntimeInterface::ResolveLookUpField(FieldPtr rawField, ClassPtr klass)
32 {
33     ASSERT(rawField != nullptr);
34     ASSERT(klass != nullptr);
35     return ClassCast(klass)->LookupFieldByName(FieldCast(rawField)->GetName());
36 }
37 
38 template <panda_file::Type::TypeId FIELD_TYPE>
GetLookUpCall(FieldPtr rawField,ClassPtr klass,bool isSetter)39 compiler::RuntimeInterface::MethodPtr EtsRuntimeInterface::GetLookUpCall(FieldPtr rawField, ClassPtr klass,
40                                                                          bool isSetter)
41 {
42     if (isSetter) {
43         return ClassCast(klass)->LookupSetterByName<FIELD_TYPE>(FieldCast(rawField)->GetName());
44     }
45     return ClassCast(klass)->LookupGetterByName<FIELD_TYPE>(FieldCast(rawField)->GetName());
46 }
47 
ResolveLookUpCall(FieldPtr rawField,ClassPtr klass,bool isSetter)48 compiler::RuntimeInterface::MethodPtr EtsRuntimeInterface::ResolveLookUpCall(FieldPtr rawField, ClassPtr klass,
49                                                                              bool isSetter)
50 {
51     ASSERT(rawField != nullptr);
52     ASSERT(klass != nullptr);
53     switch (FieldCast(rawField)->GetTypeId()) {
54         case panda_file::Type::TypeId::U1:
55             return GetLookUpCall<panda_file::Type::TypeId::U1>(rawField, klass, isSetter);
56         case panda_file::Type::TypeId::U8:
57             return GetLookUpCall<panda_file::Type::TypeId::U8>(rawField, klass, isSetter);
58         case panda_file::Type::TypeId::I8:
59             return GetLookUpCall<panda_file::Type::TypeId::I8>(rawField, klass, isSetter);
60         case panda_file::Type::TypeId::I16:
61             return GetLookUpCall<panda_file::Type::TypeId::I16>(rawField, klass, isSetter);
62         case panda_file::Type::TypeId::U16:
63             return GetLookUpCall<panda_file::Type::TypeId::U16>(rawField, klass, isSetter);
64         case panda_file::Type::TypeId::I32:
65             return GetLookUpCall<panda_file::Type::TypeId::I32>(rawField, klass, isSetter);
66         case panda_file::Type::TypeId::U32:
67             return GetLookUpCall<panda_file::Type::TypeId::U32>(rawField, klass, isSetter);
68         case panda_file::Type::TypeId::I64:
69             return GetLookUpCall<panda_file::Type::TypeId::I64>(rawField, klass, isSetter);
70         case panda_file::Type::TypeId::U64:
71             return GetLookUpCall<panda_file::Type::TypeId::U64>(rawField, klass, isSetter);
72         case panda_file::Type::TypeId::F32:
73             return GetLookUpCall<panda_file::Type::TypeId::F32>(rawField, klass, isSetter);
74         case panda_file::Type::TypeId::F64:
75             return GetLookUpCall<panda_file::Type::TypeId::F64>(rawField, klass, isSetter);
76         case panda_file::Type::TypeId::REFERENCE:
77             return GetLookUpCall<panda_file::Type::TypeId::REFERENCE>(rawField, klass, isSetter);
78         default: {
79             UNREACHABLE();
80             break;
81         }
82     }
83     return nullptr;
84 }
85 
GetUndefinedObject() const86 uint64_t EtsRuntimeInterface::GetUndefinedObject() const
87 {
88     return ToUintPtr(PandaEtsVM::GetCurrent()->GetUndefinedObject());
89 }
90 
GetInteropCallKind(MethodPtr methodPtr) const91 compiler::RuntimeInterface::InteropCallKind EtsRuntimeInterface::GetInteropCallKind(MethodPtr methodPtr) const
92 {
93     auto className = GetClassNameFromMethod(methodPtr);
94     auto classNameSuffix = className.substr(className.find_last_of('.') + 1);
95     if (classNameSuffix == "$jsnew") {
96         return InteropCallKind::NEW_INSTANCE;
97     }
98     if (classNameSuffix != "$jscall") {
99         return InteropCallKind::UNKNOWN;
100     }
101 
102     auto method = MethodCast(methodPtr);
103 
104     ASSERT(method->GetArgType(0).IsReference());  // arg0 is always a reference
105     if (method->GetArgType(1).IsReference()) {
106         auto pf = method->GetPandaFile();
107         panda_file::ProtoDataAccessor pda(*pf, panda_file::MethodDataAccessor::GetProtoId(*pf, method->GetFileId()));
108         ClassLinker *classLinker = Runtime::GetCurrent()->GetClassLinker();
109         auto linkerCtx = method->GetClass()->GetLoadContext();
110         uint32_t const argReftypeShift = method->GetReturnType().IsReference() ? 1 : 0;
111         ScopedMutatorLock lock;
112         auto cls = classLinker->GetClass(*pf, pda.GetReferenceType(1 + argReftypeShift), linkerCtx);
113         if (!cls->IsStringClass()) {
114             return InteropCallKind::CALL_BY_VALUE;
115         }
116     } else {
117         // arg1 and arg2 are start position and length of qualified name
118         ASSERT(method->GetArgType(1).GetId() == panda_file::Type::TypeId::I32);
119         ASSERT(method->GetArgType(2U).GetId() == panda_file::Type::TypeId::I32);
120     }
121     return InteropCallKind::CALL;
122 }
123 
GetFuncPropName(MethodPtr methodPtr,uint32_t strId) const124 char *EtsRuntimeInterface::GetFuncPropName(MethodPtr methodPtr, uint32_t strId) const
125 {
126     auto method = MethodCast(methodPtr);
127     auto pf = method->GetPandaFile();
128     auto str = reinterpret_cast<const char *>(pf->GetStringData(ark::panda_file::File::EntityId(strId)).data);
129     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
130     return const_cast<char *>(std::strrchr(str, '.') + 1);
131 }
132 
GetFuncPropNameOffset(MethodPtr methodPtr,uint32_t strId) const133 uint64_t EtsRuntimeInterface::GetFuncPropNameOffset(MethodPtr methodPtr, uint32_t strId) const
134 {
135     auto pf = MethodCast(methodPtr)->GetPandaFile();
136     auto str = GetFuncPropName(methodPtr, strId);
137     return reinterpret_cast<uint64_t>(str) - reinterpret_cast<uint64_t>(pf->GetBase());
138 }
139 
IsMethodStringConcat(MethodPtr method) const140 bool EtsRuntimeInterface::IsMethodStringConcat(MethodPtr method) const
141 {
142     return GetMethodFullName(method, false) == "std.core.String::concat" &&
143            MethodCast(method)->GetProto().GetSignature() == "([Lstd/core/String;)Lstd/core/String;";
144 }
145 
IsMethodStringBuilderConstructorWithStringArg(MethodPtr method) const146 bool EtsRuntimeInterface::IsMethodStringBuilderConstructorWithStringArg(MethodPtr method) const
147 {
148     return MethodCast(method)->IsConstructor() && GetClassNameFromMethod(method) == "std.core.StringBuilder" &&
149            MethodCast(method)->GetProto().GetSignature() == "(Lstd/core/String;)V";
150 }
151 
IsMethodStringBuilderConstructorWithCharArrayArg(MethodPtr method) const152 bool EtsRuntimeInterface::IsMethodStringBuilderConstructorWithCharArrayArg(MethodPtr method) const
153 {
154     return MethodCast(method)->IsConstructor() && GetClassNameFromMethod(method) == "std.core.StringBuilder" &&
155            MethodCast(method)->GetProto().GetSignature() == "([C)V";
156 }
157 
IsMethodStringBuilderDefaultConstructor(MethodPtr method) const158 bool EtsRuntimeInterface::IsMethodStringBuilderDefaultConstructor(MethodPtr method) const
159 {
160     return MethodCast(method)->IsConstructor() && GetClassNameFromMethod(method) == "std.core.StringBuilder" &&
161            MethodCast(method)->GetProto().GetSignature() == "()V";
162 }
163 
IsMethodStringBuilderToString(MethodPtr method) const164 bool EtsRuntimeInterface::IsMethodStringBuilderToString(MethodPtr method) const
165 {
166     return GetMethodFullName(method, false) == "std.core.StringBuilder::toString" &&
167            MethodCast(method)->GetProto().GetSignature() == "()Lstd/core/String;";
168 }
169 
IsMethodStringBuilderAppend(MethodPtr method) const170 bool EtsRuntimeInterface::IsMethodStringBuilderAppend(MethodPtr method) const
171 {
172     return GetMethodFullName(method, false) == "std.core.StringBuilder::append";
173 }
174 
IsClassStringBuilder(ClassPtr klass) const175 bool EtsRuntimeInterface::IsClassStringBuilder(ClassPtr klass) const
176 {
177     return ClassCast(klass)->GetName() == "std.core.StringBuilder";
178 }
179 
GetClassOffsetObjectsArray(MethodPtr method) const180 uint32_t EtsRuntimeInterface::GetClassOffsetObjectsArray(MethodPtr method) const
181 {
182     auto pf = MethodCast(method)->GetPandaFile();
183     return pf->GetClassId(utf::CStringAsMutf8("[Lstd/core/Object;")).GetOffset();
184 }
185 
GetClassOffsetObject(MethodPtr method) const186 uint32_t EtsRuntimeInterface::GetClassOffsetObject(MethodPtr method) const
187 {
188     auto pf = MethodCast(method)->GetPandaFile();
189     return pf->GetClassId(utf::CStringAsMutf8("std.core.Object")).GetOffset();
190 }
191 
GetStringBuilderClass() const192 EtsRuntimeInterface::ClassPtr EtsRuntimeInterface::GetStringBuilderClass() const
193 {
194     return PandaEtsVM::GetCurrent()->GetClassLinker()->GetEtsClassLinkerExtension()->GetStringBuilderClass();
195 }
196 
GetStringBuilderDefaultConstructor() const197 EtsRuntimeInterface::MethodPtr EtsRuntimeInterface::GetStringBuilderDefaultConstructor() const
198 {
199     auto classLinker = PandaEtsVM::GetCurrent()->GetClassLinker();
200     for (auto ctor : classLinker->GetStringBuilderClass()->GetConstructors()) {
201         if (IsMethodStringBuilderDefaultConstructor(ctor)) {
202             return ctor;
203         }
204     }
205 
206     UNREACHABLE();
207 }
208 
GetMethodId(MethodPtr method) const209 uint32_t EtsRuntimeInterface::GetMethodId(MethodPtr method) const
210 {
211     ASSERT(method != nullptr);
212     return static_cast<EtsMethod *>(method)->GetMethodId();
213 }
214 
GetFieldStringBuilderBuffer(ClassPtr klass) const215 EtsRuntimeInterface::FieldPtr EtsRuntimeInterface::GetFieldStringBuilderBuffer(ClassPtr klass) const
216 {
217     ASSERT(IsClassStringBuilder(klass));
218     return ClassCast(klass)->GetInstanceFieldByName(utf::CStringAsMutf8("buf"));
219 }
220 
GetFieldStringBuilderIndex(ClassPtr klass) const221 EtsRuntimeInterface::FieldPtr EtsRuntimeInterface::GetFieldStringBuilderIndex(ClassPtr klass) const
222 {
223     ASSERT(IsClassStringBuilder(klass));
224     return ClassCast(klass)->GetInstanceFieldByName(utf::CStringAsMutf8("index"));
225 }
226 
GetFieldStringBuilderLength(ClassPtr klass) const227 EtsRuntimeInterface::FieldPtr EtsRuntimeInterface::GetFieldStringBuilderLength(ClassPtr klass) const
228 {
229     ASSERT(IsClassStringBuilder(klass));
230     return ClassCast(klass)->GetInstanceFieldByName(utf::CStringAsMutf8("length"));
231 }
232 
GetFieldStringBuilderCompress(ClassPtr klass) const233 EtsRuntimeInterface::FieldPtr EtsRuntimeInterface::GetFieldStringBuilderCompress(ClassPtr klass) const
234 {
235     ASSERT(IsClassStringBuilder(klass));
236     return ClassCast(klass)->GetInstanceFieldByName(utf::CStringAsMutf8("compress"));
237 }
238 
IsFieldStringBuilderBuffer(FieldPtr field) const239 bool EtsRuntimeInterface::IsFieldStringBuilderBuffer(FieldPtr field) const
240 {
241     return IsClassStringBuilder(FieldCast(field)->GetClass()) && GetFieldName(field) == "buf";
242 }
243 
IsFieldStringBuilderIndex(FieldPtr field) const244 bool EtsRuntimeInterface::IsFieldStringBuilderIndex(FieldPtr field) const
245 {
246     return IsClassStringBuilder(FieldCast(field)->GetClass()) && GetFieldName(field) == "index";
247 }
248 
IsIntrinsicStringBuilderToString(IntrinsicId id) const249 bool EtsRuntimeInterface::IsIntrinsicStringBuilderToString(IntrinsicId id) const
250 {
251     return id == RuntimeInterface::IntrinsicId::INTRINSIC_STD_CORE_SB_TO_STRING;
252 }
253 
IsIntrinsicStringBuilderAppendString(IntrinsicId id) const254 bool EtsRuntimeInterface::IsIntrinsicStringBuilderAppendString(IntrinsicId id) const
255 {
256     switch (id) {
257         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING:
258             return true;
259         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING2:
260             return true;
261         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING3:
262             return true;
263         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING4:
264             return true;
265         default:
266             return false;
267     }
268 }
269 
IsIntrinsicStringBuilderAppend(IntrinsicId id) const270 bool EtsRuntimeInterface::IsIntrinsicStringBuilderAppend(IntrinsicId id) const
271 {
272     switch (id) {
273         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_FLOAT:
274             return true;
275         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_DOUBLE:
276             return true;
277         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_LONG:
278             return true;
279         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_INT:
280             return true;
281         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_BYTE:
282             return true;
283         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_SHORT:
284             return true;
285         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_CHAR:
286             return true;
287         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_BOOL:
288             return true;
289         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING:
290             return true;
291         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING2:
292             return true;
293         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING3:
294             return true;
295         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING4:
296             return true;
297         default:
298             return false;
299     }
300 }
301 
ConvertTypeToStringBuilderAppendIntrinsicId(compiler::DataType::Type type) const302 EtsRuntimeInterface::IntrinsicId EtsRuntimeInterface::ConvertTypeToStringBuilderAppendIntrinsicId(
303     compiler::DataType::Type type) const
304 {
305     switch (type) {
306         case compiler::DataType::BOOL:
307             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_BOOL;
308         case compiler::DataType::INT8:
309             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_CHAR;
310         case compiler::DataType::UINT8:
311             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_BYTE;
312         case compiler::DataType::INT16:
313             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_SHORT;
314         case compiler::DataType::INT32:
315             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_INT;
316         case compiler::DataType::INT64:
317             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_LONG;
318         case compiler::DataType::FLOAT64:
319             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_DOUBLE;
320         case compiler::DataType::FLOAT32:
321             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_FLOAT;
322         case compiler::DataType::REFERENCE:
323             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING;
324         default:
325             UNREACHABLE();
326     }
327     return IntrinsicId::INVALID;
328 }
329 
GetStringConcatStringsIntrinsicId(size_t numArgs) const330 EtsRuntimeInterface::IntrinsicId EtsRuntimeInterface::GetStringConcatStringsIntrinsicId(size_t numArgs) const
331 {
332     // NOLINTBEGIN(readability-magic-numbers)
333     switch (numArgs) {
334         case 2U:
335             return IntrinsicId::INTRINSIC_STD_CORE_STRING_CONCAT2;
336         case 3U:
337             return IntrinsicId::INTRINSIC_STD_CORE_STRING_CONCAT3;
338         case 4U:
339             return IntrinsicId::INTRINSIC_STD_CORE_STRING_CONCAT4;
340         default:
341             UNREACHABLE();
342     }
343     // NOLINTEND(readability-magic-numbers)
344 }
345 
GetStringIsCompressedIntrinsicId() const346 EtsRuntimeInterface::IntrinsicId EtsRuntimeInterface::GetStringIsCompressedIntrinsicId() const
347 {
348     return IntrinsicId::INTRINSIC_STD_CORE_STRING_IS_COMPRESSED;
349 }
350 
GetStringBuilderAppendStringsIntrinsicId(size_t numArgs) const351 EtsRuntimeInterface::IntrinsicId EtsRuntimeInterface::GetStringBuilderAppendStringsIntrinsicId(size_t numArgs) const
352 {
353     // NOLINTBEGIN(readability-magic-numbers)
354     switch (numArgs) {
355         case 1U:
356             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING;
357         case 2U:
358             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING2;
359         case 3U:
360             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING3;
361         case 4U:
362             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING4;
363         default:
364             UNREACHABLE();
365     }
366     // NOLINTEND(readability-magic-numbers)
367 }
368 
GetStringBuilderToStringIntrinsicId() const369 EtsRuntimeInterface::IntrinsicId EtsRuntimeInterface::GetStringBuilderToStringIntrinsicId() const
370 {
371     return IntrinsicId::INTRINSIC_STD_CORE_SB_TO_STRING;
372 }
373 
IsClassValueTyped(ClassPtr klass) const374 bool EtsRuntimeInterface::IsClassValueTyped(ClassPtr klass) const
375 {
376     return EtsClass::FromRuntimeClass(ClassCast(klass))->IsValueTyped();
377 }
378 
GetDoubleToStringCache() const379 void *EtsRuntimeInterface::GetDoubleToStringCache() const
380 {
381     return ark::ets::PandaEtsVM::GetCurrent()->GetDoubleToStringCache();
382 }
383 
384 }  // namespace ark::ets
385