• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-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  *
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 "ani.h"
19 #include "ets_runtime_interface.h"
20 #include "plugins/ets/runtime/ets_stubs-inl.h"
21 #include "plugins/ets/runtime/ets_class_linker_extension.h"
22 #include "types/ets_method.h"
23 
24 namespace ark::ets {
GetClass(MethodPtr method,IdType id) const25 compiler::RuntimeInterface::ClassPtr EtsRuntimeInterface::GetClass(MethodPtr method, IdType id) const
26 {
27     if (id == RuntimeInterface::MEM_PROMISE_CLASS_ID) {
28         return PlatformTypes(PandaEtsVM::GetCurrent())->corePromise->GetRuntimeClass();
29     }
30     return PandaRuntimeInterface::GetClass(method, id);
31 }
32 
ResolveLookUpField(FieldPtr rawField,ClassPtr klass)33 compiler::RuntimeInterface::FieldPtr EtsRuntimeInterface::ResolveLookUpField(FieldPtr rawField, ClassPtr klass)
34 {
35     ASSERT(rawField != nullptr);
36     ASSERT(klass != nullptr);
37     Class *current = ClassCast(klass);
38     Field *raw = FieldCast(rawField);
39     while (current != nullptr) {
40         Field *field = LookupFieldByName(raw->GetName(), current);
41         if (LIKELY(field != nullptr)) {
42             return field;
43         }
44         current = current->GetBase();
45     }
46     return nullptr;
47 }
48 
49 template <panda_file::Type::TypeId FIELD_TYPE>
GetLookUpCall(FieldPtr rawField,ClassPtr klass,bool isSetter)50 compiler::RuntimeInterface::MethodPtr EtsRuntimeInterface::GetLookUpCall(FieldPtr rawField, ClassPtr klass,
51                                                                          bool isSetter)
52 {
53     Field *raw = FieldCast(rawField);
54     Method *method = nullptr;
55     Class *current = ClassCast(klass);
56     while (current != nullptr) {
57         if (isSetter) {
58             method = LookupSetterByName<FIELD_TYPE>(raw->GetName(), current);
59         } else {
60             method = LookupGetterByName<FIELD_TYPE>(raw->GetName(), current);
61         }
62         if (LIKELY(method != nullptr)) {
63             return method;
64         }
65         current = current->GetBase();
66     }
67     return method;
68 }
69 
ResolveLookUpCall(FieldPtr rawField,ClassPtr klass,bool isSetter)70 compiler::RuntimeInterface::MethodPtr EtsRuntimeInterface::ResolveLookUpCall(FieldPtr rawField, ClassPtr klass,
71                                                                              bool isSetter)
72 {
73     ASSERT(rawField != nullptr);
74     ASSERT(klass != nullptr);
75     switch (FieldCast(rawField)->GetTypeId()) {
76         case panda_file::Type::TypeId::U1:
77             return GetLookUpCall<panda_file::Type::TypeId::U1>(rawField, klass, isSetter);
78         case panda_file::Type::TypeId::U8:
79             return GetLookUpCall<panda_file::Type::TypeId::U8>(rawField, klass, isSetter);
80         case panda_file::Type::TypeId::I8:
81             return GetLookUpCall<panda_file::Type::TypeId::I8>(rawField, klass, isSetter);
82         case panda_file::Type::TypeId::I16:
83             return GetLookUpCall<panda_file::Type::TypeId::I16>(rawField, klass, isSetter);
84         case panda_file::Type::TypeId::U16:
85             return GetLookUpCall<panda_file::Type::TypeId::U16>(rawField, klass, isSetter);
86         case panda_file::Type::TypeId::I32:
87             return GetLookUpCall<panda_file::Type::TypeId::I32>(rawField, klass, isSetter);
88         case panda_file::Type::TypeId::U32:
89             return GetLookUpCall<panda_file::Type::TypeId::U32>(rawField, klass, isSetter);
90         case panda_file::Type::TypeId::I64:
91             return GetLookUpCall<panda_file::Type::TypeId::I64>(rawField, klass, isSetter);
92         case panda_file::Type::TypeId::U64:
93             return GetLookUpCall<panda_file::Type::TypeId::U64>(rawField, klass, isSetter);
94         case panda_file::Type::TypeId::F32:
95             return GetLookUpCall<panda_file::Type::TypeId::F32>(rawField, klass, isSetter);
96         case panda_file::Type::TypeId::F64:
97             return GetLookUpCall<panda_file::Type::TypeId::F64>(rawField, klass, isSetter);
98         case panda_file::Type::TypeId::REFERENCE:
99             return GetLookUpCall<panda_file::Type::TypeId::REFERENCE>(rawField, klass, isSetter);
100         default: {
101             UNREACHABLE();
102             break;
103         }
104     }
105     return nullptr;
106 }
107 
GetUniqueObject() const108 uint64_t EtsRuntimeInterface::GetUniqueObject() const
109 {
110     return ToUintPtr(PandaEtsVM::GetCurrent()->GetNullValue());
111 }
112 
GetInteropCallKind(MethodPtr methodPtr) const113 compiler::RuntimeInterface::InteropCallKind EtsRuntimeInterface::GetInteropCallKind(MethodPtr methodPtr) const
114 {
115     auto className = GetClassNameFromMethod(methodPtr);
116     auto classNameSuffix = className.substr(className.find_last_of('.') + 1);
117     if (classNameSuffix == "$jsnew") {
118         return InteropCallKind::NEW_INSTANCE;
119     }
120     if (classNameSuffix != "$jscall") {
121         return InteropCallKind::UNKNOWN;
122     }
123 
124     auto method = MethodCast(methodPtr);
125 
126     ASSERT(method->GetArgType(0).IsReference());  // arg0 is always a reference
127     if (method->GetArgType(1).IsReference()) {
128         auto pf = method->GetPandaFile();
129         panda_file::ProtoDataAccessor pda(*pf, panda_file::MethodDataAccessor::GetProtoId(*pf, method->GetFileId()));
130         ClassLinker *classLinker = Runtime::GetCurrent()->GetClassLinker();
131         auto linkerCtx = method->GetClass()->GetLoadContext();
132         uint32_t const argReftypeShift = method->GetReturnType().IsReference() ? 1 : 0;
133         ScopedMutatorLock lock;
134         auto cls = classLinker->GetClass(*pf, pda.GetReferenceType(1 + argReftypeShift), linkerCtx);
135         ASSERT(cls != nullptr);
136         if (!cls->IsStringClass()) {
137             return InteropCallKind::CALL_BY_VALUE;
138         }
139     } else {
140         // arg1 and arg2 are start position and length of qualified name
141         ASSERT(method->GetArgType(1).GetId() == panda_file::Type::TypeId::I32);
142         ASSERT(method->GetArgType(2U).GetId() == panda_file::Type::TypeId::I32);
143     }
144     return InteropCallKind::CALL;
145 }
146 
GetFuncPropName(MethodPtr methodPtr,uint32_t strId) const147 char *EtsRuntimeInterface::GetFuncPropName(MethodPtr methodPtr, uint32_t strId) const
148 {
149     auto method = MethodCast(methodPtr);
150     auto pf = method->GetPandaFile();
151     auto str = reinterpret_cast<const char *>(pf->GetStringData(ark::panda_file::File::EntityId(strId)).data);
152     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
153     return const_cast<char *>(std::strrchr(str, '.') + 1);
154 }
155 
GetFuncPropNameOffset(MethodPtr methodPtr,uint32_t strId) const156 uint64_t EtsRuntimeInterface::GetFuncPropNameOffset(MethodPtr methodPtr, uint32_t strId) const
157 {
158     auto pf = MethodCast(methodPtr)->GetPandaFile();
159     auto str = GetFuncPropName(methodPtr, strId);
160     return reinterpret_cast<uint64_t>(str) - reinterpret_cast<uint64_t>(pf->GetBase());
161 }
162 
IsMethodStringConcat(MethodPtr method) const163 bool EtsRuntimeInterface::IsMethodStringConcat(MethodPtr method) const
164 {
165     return GetMethodFullName(method, false) == "std.core.String::concat" &&
166            MethodCast(method)->GetProto().GetSignature() == "([Lstd/core/String;)Lstd/core/String;";
167 }
168 
IsMethodStringBuilderConstructorWithStringArg(MethodPtr method) const169 bool EtsRuntimeInterface::IsMethodStringBuilderConstructorWithStringArg(MethodPtr method) const
170 {
171     return MethodCast(method)->IsConstructor() && GetClassNameFromMethod(method) == "std.core.StringBuilder" &&
172            MethodCast(method)->GetProto().GetSignature() == "(Lstd/core/String;)V";
173 }
174 
IsMethodStringBuilderConstructorWithCharArrayArg(MethodPtr method) const175 bool EtsRuntimeInterface::IsMethodStringBuilderConstructorWithCharArrayArg(MethodPtr method) const
176 {
177     return MethodCast(method)->IsConstructor() && GetClassNameFromMethod(method) == "std.core.StringBuilder" &&
178            MethodCast(method)->GetProto().GetSignature() == "([C)V";
179 }
180 
IsMethodStringBuilderDefaultConstructor(MethodPtr method) const181 bool EtsRuntimeInterface::IsMethodStringBuilderDefaultConstructor(MethodPtr method) const
182 {
183     return MethodCast(method)->IsConstructor() && GetClassNameFromMethod(method) == "std.core.StringBuilder" &&
184            MethodCast(method)->GetProto().GetSignature() == "()V";
185 }
186 
IsMethodStringBuilderToString(MethodPtr method) const187 bool EtsRuntimeInterface::IsMethodStringBuilderToString(MethodPtr method) const
188 {
189     return GetMethodFullName(method, false) == "std.core.StringBuilder::toString" &&
190            MethodCast(method)->GetProto().GetSignature() == "()Lstd/core/String;";
191 }
192 
IsMethodStringBuilderAppend(MethodPtr method) const193 bool EtsRuntimeInterface::IsMethodStringBuilderAppend(MethodPtr method) const
194 {
195     return GetMethodFullName(method, false) == "std.core.StringBuilder::append";
196 }
197 
IsMethodInModuleScope(MethodPtr method) const198 bool EtsRuntimeInterface::IsMethodInModuleScope(MethodPtr method) const
199 {
200     return static_cast<EtsMethod *>(method)->GetClass()->IsModule();
201 }
202 
IsClassStringBuilder(ClassPtr klass) const203 bool EtsRuntimeInterface::IsClassStringBuilder(ClassPtr klass) const
204 {
205     return ClassCast(klass)->GetName() == "std.core.StringBuilder";
206 }
207 
IsClassEscompatArray(ClassPtr klass) const208 bool EtsRuntimeInterface::IsClassEscompatArray(ClassPtr klass) const
209 {
210     return ClassCast(klass)->GetName() == "escompat.Array";
211 }
212 
GetClassOffsetObjectsArray(MethodPtr method) const213 uint32_t EtsRuntimeInterface::GetClassOffsetObjectsArray(MethodPtr method) const
214 {
215     auto pf = MethodCast(method)->GetPandaFile();
216     return pf->GetClassId(utf::CStringAsMutf8("[Lstd/core/Object;")).GetOffset();
217 }
218 
GetClassOffsetObject(MethodPtr method) const219 uint32_t EtsRuntimeInterface::GetClassOffsetObject(MethodPtr method) const
220 {
221     auto pf = MethodCast(method)->GetPandaFile();
222     return pf->GetClassId(utf::CStringAsMutf8("std.core.Object")).GetOffset();
223 }
224 
GetStringBuilderClass() const225 EtsRuntimeInterface::ClassPtr EtsRuntimeInterface::GetStringBuilderClass() const
226 {
227     return PlatformTypes(PandaEtsVM::GetCurrent())->coreStringBuilder->GetRuntimeClass();
228 }
229 
GetEscompatArrayClass() const230 EtsRuntimeInterface::ClassPtr EtsRuntimeInterface::GetEscompatArrayClass() const
231 {
232     return PlatformTypes(PandaEtsVM::GetCurrent())->escompatArray->GetRuntimeClass();
233 }
234 
GetStringBuilderDefaultConstructor() const235 EtsRuntimeInterface::MethodPtr EtsRuntimeInterface::GetStringBuilderDefaultConstructor() const
236 {
237     for (auto ctor : PlatformTypes()->coreStringBuilder->GetConstructors()) {
238         if (IsMethodStringBuilderDefaultConstructor(ctor)) {
239             return ctor;
240         }
241     }
242 
243     UNREACHABLE();
244 }
245 
GetMethodId(MethodPtr method) const246 uint32_t EtsRuntimeInterface::GetMethodId(MethodPtr method) const
247 {
248     ASSERT(method != nullptr);
249     return static_cast<EtsMethod *>(method)->GetMethodId();
250 }
251 
IsFieldBooleanFalse(FieldPtr field) const252 bool EtsRuntimeInterface::IsFieldBooleanFalse([[maybe_unused]] FieldPtr field) const
253 {
254     return IsClassBoxedBoolean((FieldCast(field)->GetClass())) && GetFieldName(field) == "FALSE";
255 }
256 
IsFieldBooleanTrue(FieldPtr field) const257 bool EtsRuntimeInterface::IsFieldBooleanTrue([[maybe_unused]] FieldPtr field) const
258 {
259     return IsClassBoxedBoolean((FieldCast(field)->GetClass())) && GetFieldName(field) == "TRUE";
260 }
261 
IsFieldBooleanValue(FieldPtr field) const262 bool EtsRuntimeInterface::IsFieldBooleanValue([[maybe_unused]] FieldPtr field) const
263 {
264     return IsClassBoxedBoolean((FieldCast(field)->GetClass())) && GetFieldName(field) == "value";
265 }
266 
GetFieldStringBuilderBuffer(ClassPtr klass) const267 EtsRuntimeInterface::FieldPtr EtsRuntimeInterface::GetFieldStringBuilderBuffer(ClassPtr klass) const
268 {
269     ASSERT(IsClassStringBuilder(klass));
270     return ClassCast(klass)->GetInstanceFieldByName(utf::CStringAsMutf8("buf"));
271 }
272 
GetFieldStringBuilderIndex(ClassPtr klass) const273 EtsRuntimeInterface::FieldPtr EtsRuntimeInterface::GetFieldStringBuilderIndex(ClassPtr klass) const
274 {
275     ASSERT(IsClassStringBuilder(klass));
276     return ClassCast(klass)->GetInstanceFieldByName(utf::CStringAsMutf8("index"));
277 }
278 
GetFieldStringBuilderLength(ClassPtr klass) const279 EtsRuntimeInterface::FieldPtr EtsRuntimeInterface::GetFieldStringBuilderLength(ClassPtr klass) const
280 {
281     ASSERT(IsClassStringBuilder(klass));
282     return ClassCast(klass)->GetInstanceFieldByName(utf::CStringAsMutf8("length"));
283 }
284 
GetFieldStringBuilderCompress(ClassPtr klass) const285 EtsRuntimeInterface::FieldPtr EtsRuntimeInterface::GetFieldStringBuilderCompress(ClassPtr klass) const
286 {
287     ASSERT(IsClassStringBuilder(klass));
288     return ClassCast(klass)->GetInstanceFieldByName(utf::CStringAsMutf8("compress"));
289 }
290 
GetEscompatArrayActualLength(ClassPtr klass) const291 EtsRuntimeInterface::FieldPtr EtsRuntimeInterface::GetEscompatArrayActualLength(ClassPtr klass) const
292 {
293     ASSERT(IsClassEscompatArray(klass));
294     return ClassCast(klass)->GetInstanceFieldByName(utf::CStringAsMutf8("actualLength"));
295 }
296 
GetEscompatArrayBuffer(ClassPtr klass) const297 EtsRuntimeInterface::FieldPtr EtsRuntimeInterface::GetEscompatArrayBuffer(ClassPtr klass) const
298 {
299     ASSERT(IsClassEscompatArray(klass));
300     return ClassCast(klass)->GetInstanceFieldByName(utf::CStringAsMutf8("buffer"));
301 }
302 
IsFieldStringBuilderBuffer(FieldPtr field) const303 bool EtsRuntimeInterface::IsFieldStringBuilderBuffer(FieldPtr field) const
304 {
305     return IsClassStringBuilder(FieldCast(field)->GetClass()) && GetFieldName(field) == "buf";
306 }
307 
IsFieldStringBuilderIndex(FieldPtr field) const308 bool EtsRuntimeInterface::IsFieldStringBuilderIndex(FieldPtr field) const
309 {
310     return IsClassStringBuilder(FieldCast(field)->GetClass()) && GetFieldName(field) == "index";
311 }
312 
IsFieldArrayActualLength(FieldPtr field) const313 bool EtsRuntimeInterface::IsFieldArrayActualLength(FieldPtr field) const
314 {
315     return IsClassEscompatArray(FieldCast(field)->GetClass()) && GetFieldName(field) == "actualLength";
316 }
317 
IsFieldArrayBuffer(FieldPtr field) const318 bool EtsRuntimeInterface::IsFieldArrayBuffer(FieldPtr field) const
319 {
320     return IsClassEscompatArray(FieldCast(field)->GetClass()) && GetFieldName(field) == "buffer";
321 }
322 
IsFieldArray(ArrayField kind,FieldPtr field) const323 bool EtsRuntimeInterface::IsFieldArray(ArrayField kind, FieldPtr field) const
324 {
325     if (!HasFieldMetadata(field)) {
326         return false;
327     }
328     switch (kind) {
329         case ArrayField::ACTUAL_LENGTH:
330             return IsFieldArrayActualLength(field);
331         case ArrayField::BUFFER:
332             return IsFieldArrayBuffer(field);
333         default:
334             return false;
335     }
336 }
337 
IsIntrinsicStringBuilderToString(IntrinsicId id) const338 bool EtsRuntimeInterface::IsIntrinsicStringBuilderToString(IntrinsicId id) const
339 {
340     return id == RuntimeInterface::IntrinsicId::INTRINSIC_STD_CORE_SB_TO_STRING;
341 }
342 
IsIntrinsicStringBuilderAppendString(IntrinsicId id) const343 bool EtsRuntimeInterface::IsIntrinsicStringBuilderAppendString(IntrinsicId id) const
344 {
345     switch (id) {
346         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING:
347             return true;
348         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING2:
349             return true;
350         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING3:
351             return true;
352         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING4:
353             return true;
354         default:
355             return false;
356     }
357 }
358 
IsIntrinsicStringBuilderAppend(IntrinsicId id) const359 bool EtsRuntimeInterface::IsIntrinsicStringBuilderAppend(IntrinsicId id) const
360 {
361     switch (id) {
362         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_FLOAT:
363             return true;
364         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_DOUBLE:
365             return true;
366         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_LONG:
367             return true;
368         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_INT:
369             return true;
370         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_BYTE:
371             return true;
372         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_SHORT:
373             return true;
374         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_CHAR:
375             return true;
376         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_BOOL:
377             return true;
378         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING:
379             return true;
380         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING2:
381             return true;
382         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING3:
383             return true;
384         case IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING4:
385             return true;
386         default:
387             return false;
388     }
389 }
390 
IsIntrinsicStringConcat(IntrinsicId id) const391 bool EtsRuntimeInterface::IsIntrinsicStringConcat(IntrinsicId id) const
392 {
393     switch (id) {
394         case IntrinsicId::INTRINSIC_STD_CORE_STRING_CONCAT2:
395             return true;
396         case IntrinsicId::INTRINSIC_STD_CORE_STRING_CONCAT3:
397             return true;
398         case IntrinsicId::INTRINSIC_STD_CORE_STRING_CONCAT4:
399             return true;
400         default:
401             return false;
402     }
403 }
404 
ConvertTypeToStringBuilderAppendIntrinsicId(compiler::DataType::Type type) const405 EtsRuntimeInterface::IntrinsicId EtsRuntimeInterface::ConvertTypeToStringBuilderAppendIntrinsicId(
406     compiler::DataType::Type type) const
407 {
408     switch (type) {
409         case compiler::DataType::BOOL:
410             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_BOOL;
411         case compiler::DataType::INT8:
412             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_CHAR;
413         case compiler::DataType::UINT8:
414             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_BYTE;
415         case compiler::DataType::INT16:
416             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_SHORT;
417         case compiler::DataType::INT32:
418             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_INT;
419         case compiler::DataType::INT64:
420             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_LONG;
421         case compiler::DataType::FLOAT64:
422             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_DOUBLE;
423         case compiler::DataType::FLOAT32:
424             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_FLOAT;
425         case compiler::DataType::REFERENCE:
426             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING;
427         default:
428             UNREACHABLE();
429     }
430     return IntrinsicId::INVALID;
431 }
432 
GetStringConcatStringsIntrinsicId(size_t numArgs) const433 EtsRuntimeInterface::IntrinsicId EtsRuntimeInterface::GetStringConcatStringsIntrinsicId(size_t numArgs) const
434 {
435     // NOLINTBEGIN(readability-magic-numbers)
436     switch (numArgs) {
437         case 2U:
438             return IntrinsicId::INTRINSIC_STD_CORE_STRING_CONCAT2;
439         case 3U:
440             return IntrinsicId::INTRINSIC_STD_CORE_STRING_CONCAT3;
441         case 4U:
442             return IntrinsicId::INTRINSIC_STD_CORE_STRING_CONCAT4;
443         default:
444             UNREACHABLE();
445     }
446     // NOLINTEND(readability-magic-numbers)
447 }
448 
GetStringIsCompressedIntrinsicId() const449 EtsRuntimeInterface::IntrinsicId EtsRuntimeInterface::GetStringIsCompressedIntrinsicId() const
450 {
451     return IntrinsicId::INTRINSIC_STD_CORE_STRING_IS_COMPRESSED;
452 }
453 
GetStringBuilderAppendStringsIntrinsicId(size_t numArgs) const454 EtsRuntimeInterface::IntrinsicId EtsRuntimeInterface::GetStringBuilderAppendStringsIntrinsicId(size_t numArgs) const
455 {
456     // NOLINTBEGIN(readability-magic-numbers)
457     switch (numArgs) {
458         case 1U:
459             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING;
460         case 2U:
461             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING2;
462         case 3U:
463             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING3;
464         case 4U:
465             return IntrinsicId::INTRINSIC_STD_CORE_SB_APPEND_STRING4;
466         default:
467             UNREACHABLE();
468     }
469     // NOLINTEND(readability-magic-numbers)
470 }
471 
GetStringBuilderToStringIntrinsicId() const472 EtsRuntimeInterface::IntrinsicId EtsRuntimeInterface::GetStringBuilderToStringIntrinsicId() const
473 {
474     return IntrinsicId::INTRINSIC_STD_CORE_SB_TO_STRING;
475 }
476 
IsClassValueTyped(ClassPtr klass) const477 bool EtsRuntimeInterface::IsClassValueTyped(ClassPtr klass) const
478 {
479     return EtsClass::FromRuntimeClass(ClassCast(klass))->IsValueTyped();
480 }
481 
GetDoubleToStringCache() const482 void *EtsRuntimeInterface::GetDoubleToStringCache() const
483 {
484     return ark::ets::PandaEtsVM::GetCurrent()->GetDoubleToStringCache();
485 }
486 
IsStringCachesUsed() const487 bool EtsRuntimeInterface::IsStringCachesUsed() const
488 {
489     return Runtime::GetCurrent()->GetOptions().IsUseStringCaches();
490 }
491 
IsNativeMethodOptimizationEnabled() const492 bool EtsRuntimeInterface::IsNativeMethodOptimizationEnabled() const
493 {
494     return true;
495 }
496 
GetDeprecatedNativeApiMask() const497 uint64_t EtsRuntimeInterface::GetDeprecatedNativeApiMask() const
498 {
499     return ACC_DEPRECATED_NATIVE_API;
500 }
501 
GetRuntimeClassOffset(Arch arch) const502 uint32_t EtsRuntimeInterface::GetRuntimeClassOffset(Arch arch) const
503 {
504     return ark::cross_values::GetEtsClassRuntimeClassOffset(arch);
505 }
506 
IsBoxedClass(ClassPtr klass) const507 bool EtsRuntimeInterface::IsBoxedClass(ClassPtr klass) const
508 {
509     return EtsClass::FromRuntimeClass(ClassCast(klass))->IsBoxed();
510 }
511 
IsClassBoxedBoolean(ClassPtr klass) const512 bool EtsRuntimeInterface::IsClassBoxedBoolean(ClassPtr klass) const
513 {
514     return PlatformTypes(PandaEtsVM::GetCurrent())->coreBoolean->GetRuntimeClass() == klass;
515 }
516 
GetTlsNativeApiOffset(Arch arch) const517 size_t EtsRuntimeInterface::GetTlsNativeApiOffset(Arch arch) const
518 {
519     return ark::cross_values::GetEtsCoroutineAniEnvOffset(arch);
520 }
521 
522 }  // namespace ark::ets
523