• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef BYTECODE_OPTIMIZER_RUNTIME_ADAPTER_H
17 #define BYTECODE_OPTIMIZER_RUNTIME_ADAPTER_H
18 
19 #include "compiler/optimizer/ir/runtime_interface.h"
20 #include "libpandafile/bytecode_instruction.h"
21 #include "libpandafile/class_data_accessor.h"
22 #include "libpandafile/code_data_accessor.h"
23 #include "libpandafile/field_data_accessor.h"
24 #include "libpandafile/file.h"
25 #include "libpandafile/file_items.h"
26 #include "libpandafile/method_data_accessor.h"
27 #include "libpandafile/proto_data_accessor.h"
28 #include "libpandafile/proto_data_accessor-inl.h"
29 #include "libpandafile/type_helper.h"
30 
31 namespace panda {
32 using compiler::RuntimeInterface;
33 
34 class BytecodeOptimizerRuntimeAdapter : public RuntimeInterface {
35 public:
BytecodeOptimizerRuntimeAdapter(const panda_file::File & panda_file)36     explicit BytecodeOptimizerRuntimeAdapter(const panda_file::File &panda_file) : panda_file_(panda_file) {}
37 
38     ~BytecodeOptimizerRuntimeAdapter() override = default;
39 
GetBinaryFileForMethod(MethodPtr method)40     BinaryFilePtr GetBinaryFileForMethod([[maybe_unused]] MethodPtr method) const override
41     {
42         return const_cast<panda_file::File *>(&panda_file_);
43     }
44 
ResolveOffsetByIndex(MethodPtr parent_method,uint16_t index)45     uint32_t ResolveOffsetByIndex(MethodPtr parent_method, uint16_t index) const override
46     {
47         return panda_file_.ResolveOffsetByIndex(MethodCast(parent_method), index).GetOffset();
48     }
49 
GetMethodId(MethodPtr method)50     MethodId GetMethodId(MethodPtr method) const override
51     {
52         return static_cast<MethodId>(reinterpret_cast<uintptr_t>(method));
53     }
54 
GetMethodTotalArgumentsCount(MethodPtr method)55     size_t GetMethodTotalArgumentsCount(MethodPtr method) const override
56     {
57         panda_file::MethodDataAccessor mda(panda_file_, MethodCast(method));
58 
59         ASSERT(!mda.IsExternal());
60         panda_file::CodeDataAccessor cda(panda_file_, mda.GetCodeId().value());
61 
62         return cda.GetNumArgs();
63     }
64 
GetMethodArgumentsCount(MethodPtr caller,MethodId id)65     size_t GetMethodArgumentsCount([[maybe_unused]] MethodPtr caller, MethodId id) const override
66     {
67         panda_file::MethodDataAccessor mda(panda_file_, panda_file::File::EntityId(id));
68         panda_file::ProtoDataAccessor pda(panda_file_, mda.GetProtoId());
69 
70         return pda.GetNumArgs();
71     }
72 
GetMethodRegistersCount(MethodPtr method)73     size_t GetMethodRegistersCount(MethodPtr method) const override
74     {
75         panda_file::MethodDataAccessor mda(panda_file_, MethodCast(method));
76 
77         ASSERT(!mda.IsExternal());
78         panda_file::CodeDataAccessor cda(panda_file_, mda.GetCodeId().value());
79 
80         return cda.GetNumVregs();
81     }
82 
GetMethodCode(MethodPtr method)83     const uint8_t *GetMethodCode(MethodPtr method) const override
84     {
85         panda_file::MethodDataAccessor mda(panda_file_, MethodCast(method));
86 
87         ASSERT(!mda.IsExternal());
88         panda_file::CodeDataAccessor cda(panda_file_, mda.GetCodeId().value());
89 
90         return cda.GetInstructions();
91     }
92 
GetMethodCodeSize(MethodPtr method)93     size_t GetMethodCodeSize(MethodPtr method) const override
94     {
95         panda_file::MethodDataAccessor mda(panda_file_, MethodCast(method));
96 
97         ASSERT(!mda.IsExternal());
98         panda_file::CodeDataAccessor cda(panda_file_, mda.GetCodeId().value());
99 
100         return cda.GetCodeSize();
101     }
102 
GetMethodSourceLanguage(MethodPtr method)103     compiler::SourceLanguage GetMethodSourceLanguage(MethodPtr method) const override
104     {
105         panda_file::MethodDataAccessor mda(panda_file_, MethodCast(method));
106 
107         ASSERT(!mda.IsExternal());
108 
109         auto source_lang = mda.GetSourceLang();
110         ASSERT(source_lang.has_value());
111 
112         return static_cast<compiler::SourceLanguage>(source_lang.value());
113     }
114 
GetClassIdForMethod(MethodPtr method)115     size_t GetClassIdForMethod(MethodPtr method) const override
116     {
117         panda_file::MethodDataAccessor mda(panda_file_, MethodCast(method));
118 
119         return static_cast<size_t>(mda.GetClassId().GetOffset());
120     }
121 
GetClassNameFromMethod(MethodPtr method)122     std::string GetClassNameFromMethod(MethodPtr method) const override
123     {
124         panda_file::MethodDataAccessor mda(panda_file_, MethodCast(method));
125 
126         auto string_data = panda_file_.GetStringData(mda.GetClassId());
127 
128         return std::string(reinterpret_cast<const char *>(string_data.data));
129     }
130 
GetMethodName(MethodPtr method)131     std::string GetMethodName(MethodPtr method) const override
132     {
133         panda_file::MethodDataAccessor mda(panda_file_, MethodCast(method));
134 
135         auto string_data = panda_file_.GetStringData(mda.GetNameId());
136 
137         return std::string(reinterpret_cast<const char *>(string_data.data));
138     }
139 
GetMethodFullName(MethodPtr method,bool)140     std::string GetMethodFullName(MethodPtr method, bool /* with_signature */) const override
141     {
142         auto class_name = GetClassNameFromMethod(method);
143         auto method_name = GetMethodName(method);
144 
145         return class_name + "::" + method_name;
146     }
147 
GetTypeInfoIndexByInstId(size_t id)148     TypeInfoIndex GetTypeInfoIndexByInstId(size_t id) const override
149     {
150         const auto it = instid_type_map_.find(id);
151         if (it == instid_type_map_.end()) {
152             return NO_EXPLICIT_TYPE;
153         }
154         return it->second;
155     }
156 
IsPcBindType(int32_t pc)157     bool IsPcBindType(int32_t pc) const override
158     {
159         return pc_type_map_.find(pc) != pc_type_map_.end();
160     }
161 
FillInstIdTypePairByPc(size_t id,int32_t pc)162     bool FillInstIdTypePairByPc(size_t id, int32_t pc) override
163     {
164         const auto it = pc_type_map_.find(pc);
165         if (it != pc_type_map_.end()) {
166             instid_type_map_.emplace(id, it->second);
167             return true;
168         }
169         return false;
170     }
171 
HasInsTypeinfo()172     bool HasInsTypeinfo() const override
173     {
174         return !instid_type_map_.empty();
175     }
176 
AddPcTypePair(int32_t pc,TypeInfoIndex type)177     bool AddPcTypePair(int32_t pc, TypeInfoIndex type) override
178     {
179         if (pc_type_map_.find(pc) != pc_type_map_.end()) {
180             return false;
181         }
182         pc_type_map_.emplace(pc, type);
183         return true;
184     }
185 
FillArgTypePairs(std::unordered_map<int32_t,TypeInfoIndex> * map)186     bool FillArgTypePairs(std::unordered_map<int32_t, TypeInfoIndex> *map) const override
187     {
188         ASSERT(map != nullptr);
189         ASSERT(map->empty());
190         for (const auto &[pc, type] : pc_type_map_) {
191             if (pc < 0) {
192                 map->emplace(pc, type);
193             }
194         }
195         return !map->empty();
196     }
197 
SetTypeLiteralArrayKey(std::string key)198     bool SetTypeLiteralArrayKey(std::string key) override
199     {
200         literalarray_key = key;
201         return !literalarray_key.empty();
202     }
203 
GetTypeLiteralArrayKey()204     const std::string *GetTypeLiteralArrayKey() const override
205     {
206         return &literalarray_key;
207     }
208 
209 private:
ToCompilerType(panda_file::Type type)210     static compiler::DataType::Type ToCompilerType(panda_file::Type type)
211     {
212         switch (type.GetId()) {
213             case panda_file::Type::TypeId::VOID:
214                 return compiler::DataType::VOID;
215             case panda_file::Type::TypeId::I32:
216                 return compiler::DataType::INT32;
217             case panda_file::Type::TypeId::U32:
218                 return compiler::DataType::UINT32;
219             case panda_file::Type::TypeId::I64:
220                 return compiler::DataType::INT64;
221             case panda_file::Type::TypeId::U64:
222                 return compiler::DataType::UINT64;
223             case panda_file::Type::TypeId::F64:
224                 return compiler::DataType::FLOAT64;
225             case panda_file::Type::TypeId::REFERENCE:
226                 return compiler::DataType::REFERENCE;
227             case panda_file::Type::TypeId::TAGGED:
228             case panda_file::Type::TypeId::INVALID:
229                 return compiler::DataType::ANY;
230             default:
231                 break;
232         }
233         UNREACHABLE();
234     }
235 
MethodCast(RuntimeInterface::MethodPtr method)236     static panda_file::File::EntityId MethodCast(RuntimeInterface::MethodPtr method)
237     {
238         return panda_file::File::EntityId(reinterpret_cast<uintptr_t>(method));
239     }
240 
241     const panda_file::File &panda_file_;
242     std::unordered_map<size_t, TypeInfoIndex> instid_type_map_;
243     std::unordered_map<int32_t, TypeInfoIndex> pc_type_map_;
244     std::string literalarray_key;
245     std::pair<size_t, size_t> anno_elem_idx_ = std::make_pair(INVALID_TYPE_INDEX, INVALID_TYPE_INDEX);
246 };
247 }  // namespace panda
248 
249 #endif  // BYTECODE_OPTIMIZER_RUNTIME_ADAPTER_H
250