1 /*
2 * Copyright (c) 2022-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 #ifndef PANDA_PLUGINS_ETS_RUNTIME_INTEROP_JS_ETS_INTEROP_RUNTIME_INTERFACE_INL_H
16 #define PANDA_PLUGINS_ETS_RUNTIME_INTEROP_JS_ETS_INTEROP_RUNTIME_INTERFACE_INL_H
17
GetInfoForInteropConvert(panda_file::Type::TypeId typeId)18 static std::pair<IntrinsicId, compiler::DataType::Type> GetInfoForInteropConvert(panda_file::Type::TypeId typeId)
19 {
20 switch (typeId) {
21 case panda_file::Type::TypeId::VOID:
22 return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_VOID_TO_LOCAL, compiler::DataType::NO_TYPE};
23 case panda_file::Type::TypeId::U1:
24 return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_U1_TO_LOCAL, compiler::DataType::BOOL};
25 case panda_file::Type::TypeId::I8:
26 return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_I8_TO_LOCAL, compiler::DataType::INT8};
27 case panda_file::Type::TypeId::U8:
28 return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_U8_TO_LOCAL, compiler::DataType::UINT8};
29 case panda_file::Type::TypeId::I16:
30 return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_I16_TO_LOCAL, compiler::DataType::INT16};
31 case panda_file::Type::TypeId::U16:
32 return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_U16_TO_LOCAL, compiler::DataType::UINT16};
33 case panda_file::Type::TypeId::I32:
34 return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_I32_TO_LOCAL, compiler::DataType::INT32};
35 case panda_file::Type::TypeId::U32:
36 return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_U32_TO_LOCAL, compiler::DataType::UINT32};
37 case panda_file::Type::TypeId::I64:
38 return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_I64_TO_LOCAL, compiler::DataType::INT64};
39 case panda_file::Type::TypeId::U64:
40 return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_U64_TO_LOCAL, compiler::DataType::UINT64};
41 case panda_file::Type::TypeId::F32:
42 return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_F32_TO_LOCAL, compiler::DataType::FLOAT32};
43 case panda_file::Type::TypeId::F64:
44 return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_F64_TO_LOCAL, compiler::DataType::FLOAT64};
45 case panda_file::Type::TypeId::REFERENCE:
46 return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_REF_TYPE_TO_LOCAL, compiler::DataType::REFERENCE};
47 default: {
48 UNREACHABLE();
49 }
50 }
51 }
52
GetInfoForInteropCallArgsConversion(MethodPtr methodPtr,uint32_t skipArgs,ArenaVector<std::pair<IntrinsicId,compiler::DataType::Type>> * intrinsics)53 void GetInfoForInteropCallArgsConversion(
54 MethodPtr methodPtr, uint32_t skipArgs,
55 ArenaVector<std::pair<IntrinsicId, compiler::DataType::Type>> *intrinsics) const override
56 {
57 auto method = MethodCast(methodPtr);
58 uint32_t numArgs = method->GetNumArgs() - skipArgs;
59 panda_file::ShortyIterator it(method->GetShorty());
60 for (uint32_t i = 0; i < 1U + skipArgs; i++) { // 1 for return value
61 it.IncrementWithoutCheck();
62 }
63 for (uint32_t argIdx = 0; argIdx < numArgs; ++argIdx, it.IncrementWithoutCheck()) {
64 auto type = *it;
65 intrinsics->push_back(GetInfoForInteropConvert(type.GetId()));
66 }
67 }
68
GetInteropRefReturnValueConvertIntrinsic(Method * method)69 compiler::RuntimeInterface::IntrinsicId GetInteropRefReturnValueConvertIntrinsic(Method *method) const
70 {
71 auto vm = reinterpret_cast<PandaEtsVM *>(Thread::GetCurrent()->GetVM());
72 auto classLinker = vm->GetClassLinker();
73 auto klass = GetClass(method, GetMethodReturnTypeId(method));
74 // start fastpath
75 if (klass == classLinker->GetClass(panda_file_items::class_descriptors::JS_VALUE.data())->GetRuntimeClass()) {
76 return IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_JS_VALUE;
77 }
78 if (klass == classLinker->GetClass(panda_file_items::class_descriptors::STRING.data())->GetRuntimeClass()) {
79 return IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_STRING;
80 }
81 return IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_REF_TYPE;
82 }
83
84 std::optional<std::pair<compiler::RuntimeInterface::IntrinsicId, compiler::DataType::Type>>
GetInfoForInteropCallRetValueConversion(MethodPtr methodPtr)85 GetInfoForInteropCallRetValueConversion(MethodPtr methodPtr) const override
86 {
87 auto method = MethodCast(methodPtr);
88 auto type = method->GetReturnType();
89 switch (type.GetId()) {
90 case panda_file::Type::TypeId::VOID:
91 return {};
92 case panda_file::Type::TypeId::U1:
93 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_U1, compiler::DataType::BOOL}};
94 case panda_file::Type::TypeId::I8:
95 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_I8, compiler::DataType::INT8}};
96 case panda_file::Type::TypeId::U8:
97 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_U8, compiler::DataType::UINT8}};
98 case panda_file::Type::TypeId::I16:
99 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_I16, compiler::DataType::INT16}};
100 case panda_file::Type::TypeId::U16:
101 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_U16, compiler::DataType::UINT16}};
102 case panda_file::Type::TypeId::I32:
103 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_I32, compiler::DataType::INT32}};
104 case panda_file::Type::TypeId::U32:
105 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_U32, compiler::DataType::UINT32}};
106 case panda_file::Type::TypeId::I64:
107 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_I64, compiler::DataType::INT64}};
108 case panda_file::Type::TypeId::U64:
109 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_U64, compiler::DataType::UINT64}};
110 case panda_file::Type::TypeId::F32:
111 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_F32, compiler::DataType::FLOAT32}};
112 case panda_file::Type::TypeId::F64:
113 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_F64, compiler::DataType::FLOAT64}};
114 case panda_file::Type::TypeId::REFERENCE: {
115 return {{GetInteropRefReturnValueConvertIntrinsic(method), compiler::DataType::REFERENCE}};
116 }
117 default: {
118 UNREACHABLE();
119 }
120 }
121 return {};
122 }
123
GetInteropConstantPoolOffsetField(ClassPtr klass)124 FieldPtr GetInteropConstantPoolOffsetField(ClassPtr klass) const override
125 {
126 auto fields = ClassCast(klass)->GetStaticFields();
127 ASSERT(fields.Size() == 1);
128 return &fields[0];
129 }
130
131 // returns index of the first element in annotation array having the same value as element `index`
GetAnnotationElementUniqueIndex(ClassPtr klass,const char * annotation,uint32_t index)132 uint32_t GetAnnotationElementUniqueIndex(ClassPtr klass, const char *annotation, uint32_t index) override
133 {
134 auto [it, inserted] = annotationOffsets_.try_emplace(klass);
135 if (!inserted) {
136 return it->second[index];
137 }
138 auto pf = ClassCast(klass)->GetPandaFile();
139 panda_file::ClassDataAccessor cda(*pf, ClassCast(klass)->GetFileId());
140
141 [[maybe_unused]] auto annotationFound =
142 cda.EnumerateAnnotation(annotation, [pf, &indices = it->second](panda_file::AnnotationDataAccessor &ada) {
143 for (uint32_t i = 0; i < ada.GetCount(); i++) {
144 auto adae = ada.GetElement(i);
145 auto *elemName = pf->GetStringData(adae.GetNameId()).data;
146 if (!utf::IsEqual(utf::CStringAsMutf8("value"), elemName)) {
147 continue;
148 }
149 auto arr = adae.GetArrayValue();
150 indices.resize(arr.GetCount());
151 std::unordered_map<uint32_t, uint32_t> firstIndexByOffset;
152 for (uint32_t strIdx = 0; strIdx < indices.size(); strIdx++) {
153 auto strOffset = arr.Get<uint32_t>(strIdx);
154 indices[strIdx] = firstIndexByOffset.try_emplace(strOffset, strIdx).first->second;
155 }
156 return true;
157 }
158 UNREACHABLE();
159 });
160 ASSERT(annotationFound.has_value());
161 return it->second[index];
162 }
163
164 private:
165 std::unordered_map<ClassPtr, std::vector<uint32_t>> annotationOffsets_;
166
167 #endif // PANDA_PLUGINS_ETS_RUNTIME_INTEROP_JS_ETS_INTEROP_RUNTIME_INTERFACE_INL_H
168