• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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