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