1 /**
2 * Copyright (c) 2021-2022 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
21 namespace panda::ets {
GetClass(MethodPtr method,IdType id) const22 compiler::RuntimeInterface::ClassPtr EtsRuntimeInterface::GetClass(MethodPtr method, IdType id) const
23 {
24 if (id == RuntimeInterface::MEM_PROMISE_CLASS_ID) {
25 ScopedMutatorLock lock;
26 auto *caller = MethodCast(method);
27 LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(*caller);
28 return static_cast<EtsClassLinkerExtension *>(Runtime::GetCurrent()->GetClassLinker()->GetExtension(ctx))
29 ->GetPromiseClass();
30 }
31 return PandaRuntimeInterface::GetClass(method, id);
32 }
33
ResolveLookUpField(FieldPtr rawField,ClassPtr klass)34 compiler::RuntimeInterface::FieldPtr EtsRuntimeInterface::ResolveLookUpField(FieldPtr rawField, ClassPtr klass)
35 {
36 ScopedMutatorLock lock;
37 ASSERT(rawField != nullptr);
38 ASSERT(klass != nullptr);
39 return ClassCast(klass)->LookupFieldByName(FieldCast(rawField)->GetName());
40 }
41
42 template <panda_file::Type::TypeId FIELD_TYPE>
GetLookUpCall(FieldPtr rawField,ClassPtr klass,bool isSetter)43 compiler::RuntimeInterface::MethodPtr EtsRuntimeInterface::GetLookUpCall(FieldPtr rawField, ClassPtr klass,
44 bool isSetter)
45 {
46 if (isSetter) {
47 return ClassCast(klass)->LookupSetterByName<FIELD_TYPE>(FieldCast(rawField)->GetName());
48 }
49 return ClassCast(klass)->LookupGetterByName<FIELD_TYPE>(FieldCast(rawField)->GetName());
50 }
51
ResolveLookUpCall(FieldPtr rawField,ClassPtr klass,bool isSetter)52 compiler::RuntimeInterface::MethodPtr EtsRuntimeInterface::ResolveLookUpCall(FieldPtr rawField, ClassPtr klass,
53 bool isSetter)
54 {
55 ScopedMutatorLock lock;
56 ASSERT(rawField != nullptr);
57 ASSERT(klass != nullptr);
58 switch (FieldCast(rawField)->GetTypeId()) {
59 case panda_file::Type::TypeId::U1:
60 return GetLookUpCall<panda_file::Type::TypeId::U1>(rawField, klass, isSetter);
61 case panda_file::Type::TypeId::U8:
62 return GetLookUpCall<panda_file::Type::TypeId::U8>(rawField, klass, isSetter);
63 case panda_file::Type::TypeId::I8:
64 return GetLookUpCall<panda_file::Type::TypeId::I8>(rawField, klass, isSetter);
65 case panda_file::Type::TypeId::I16:
66 return GetLookUpCall<panda_file::Type::TypeId::I16>(rawField, klass, isSetter);
67 case panda_file::Type::TypeId::U16:
68 return GetLookUpCall<panda_file::Type::TypeId::U16>(rawField, klass, isSetter);
69 case panda_file::Type::TypeId::I32:
70 return GetLookUpCall<panda_file::Type::TypeId::I32>(rawField, klass, isSetter);
71 case panda_file::Type::TypeId::U32:
72 return GetLookUpCall<panda_file::Type::TypeId::U32>(rawField, klass, isSetter);
73 case panda_file::Type::TypeId::I64:
74 return GetLookUpCall<panda_file::Type::TypeId::I64>(rawField, klass, isSetter);
75 case panda_file::Type::TypeId::U64:
76 return GetLookUpCall<panda_file::Type::TypeId::U64>(rawField, klass, isSetter);
77 case panda_file::Type::TypeId::F32:
78 return GetLookUpCall<panda_file::Type::TypeId::F32>(rawField, klass, isSetter);
79 case panda_file::Type::TypeId::F64:
80 return GetLookUpCall<panda_file::Type::TypeId::F64>(rawField, klass, isSetter);
81 case panda_file::Type::TypeId::REFERENCE:
82 return GetLookUpCall<panda_file::Type::TypeId::REFERENCE>(rawField, klass, isSetter);
83 default: {
84 UNREACHABLE();
85 break;
86 }
87 }
88 return nullptr;
89 }
90
GetUndefinedObject() const91 uint64_t EtsRuntimeInterface::GetUndefinedObject() const
92 {
93 return ToUintPtr(PandaEtsVM::GetCurrent()->GetUndefinedObject());
94 }
95
GetInteropCallKind(MethodPtr methodPtr) const96 compiler::RuntimeInterface::InteropCallKind EtsRuntimeInterface::GetInteropCallKind(MethodPtr methodPtr) const
97 {
98 auto className = GetClassNameFromMethod(methodPtr);
99 auto classNameSuffix = className.substr(className.find_last_of('.') + 1);
100 if (classNameSuffix == "$jsnew") {
101 return InteropCallKind::NEW_INSTANCE;
102 }
103 if (classNameSuffix != "$jscall") {
104 return InteropCallKind::UNKNOWN;
105 }
106
107 auto method = MethodCast(methodPtr);
108 auto pf = method->GetPandaFile();
109 panda_file::ProtoDataAccessor pda(*pf, panda_file::MethodDataAccessor::GetProtoId(*pf, method->GetFileId()));
110
111 ClassLinker *classLinker = Runtime::GetCurrent()->GetClassLinker();
112 LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(*method);
113 auto linkerCtx = static_cast<EtsClassLinkerExtension *>(classLinker->GetExtension(ctx))->GetBootContext();
114
115 ScopedMutatorLock lock;
116
117 ASSERT(method->GetArgType(0).IsReference()); // arg0 is always a reference
118 ASSERT(method->GetArgType(1).IsReference()); // arg1 is always a reference
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;
123 }
124 return InteropCallKind::CALL_BY_VALUE;
125 }
126
GetFuncPropName(MethodPtr methodPtr,uint32_t strId) const127 char *EtsRuntimeInterface::GetFuncPropName(MethodPtr methodPtr, uint32_t strId) const
128 {
129 auto method = MethodCast(methodPtr);
130 auto pf = method->GetPandaFile();
131 auto str = reinterpret_cast<const char *>(pf->GetStringData(panda::panda_file::File::EntityId(strId)).data);
132 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
133 return const_cast<char *>(std::strrchr(str, '.') + 1);
134 }
135
GetFuncPropNameOffset(MethodPtr methodPtr,uint32_t strId) const136 uint64_t EtsRuntimeInterface::GetFuncPropNameOffset(MethodPtr methodPtr, uint32_t strId) const
137 {
138 auto pf = MethodCast(methodPtr)->GetPandaFile();
139 auto str = GetFuncPropName(methodPtr, strId);
140 return reinterpret_cast<uint64_t>(str) - reinterpret_cast<uint64_t>(pf->GetBase());
141 }
142
IsMethodStringBuilderConstructorWithStringArg(MethodPtr method) const143 bool EtsRuntimeInterface::IsMethodStringBuilderConstructorWithStringArg(MethodPtr method) const
144 {
145 return MethodCast(method)->IsConstructor() && GetClassNameFromMethod(method) == "std.core.StringBuilder" &&
146 MethodCast(method)->GetProto().GetSignature() == "(Lstd/core/String;)V";
147 }
148
IsMethodStringBuilderToString(MethodPtr method) const149 bool EtsRuntimeInterface::IsMethodStringBuilderToString(MethodPtr method) const
150 {
151 return GetMethodFullName(method, false) == "std.core.StringBuilder::toString" &&
152 MethodCast(method)->GetProto().GetSignature() == "()Lstd/core/String;";
153 }
154
IsIntrinsicStringBuilderToString(IntrinsicId id) const155 bool EtsRuntimeInterface::IsIntrinsicStringBuilderToString(IntrinsicId id) const
156 {
157 return id == RuntimeInterface::IntrinsicId::INTRINSIC_STD_CORE_SB_TO_STRING;
158 }
159
160 } // namespace panda::ets
161