1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_COMPILER_COMPILED_METHOD_H_ 18 #define ART_COMPILER_COMPILED_METHOD_H_ 19 20 #include <memory> 21 #include <iosfwd> 22 #include <string> 23 #include <vector> 24 25 #include "arch/instruction_set.h" 26 #include "base/array_ref.h" 27 #include "base/bit_utils.h" 28 #include "base/length_prefixed_array.h" 29 #include "dex_file_types.h" 30 #include "method_reference.h" 31 32 namespace art { 33 34 class CompilerDriver; 35 class CompiledMethodStorage; 36 37 class CompiledCode { 38 public: 39 // For Quick to supply an code blob 40 CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set, 41 const ArrayRef<const uint8_t>& quick_code); 42 43 virtual ~CompiledCode(); 44 GetInstructionSet()45 InstructionSet GetInstructionSet() const { 46 return instruction_set_; 47 } 48 GetQuickCode()49 ArrayRef<const uint8_t> GetQuickCode() const { 50 return GetArray(quick_code_); 51 } 52 53 bool operator==(const CompiledCode& rhs) const; 54 55 // To align an offset from a page-aligned value to make it suitable 56 // for code storage. For example on ARM, to ensure that PC relative 57 // valu computations work out as expected. 58 size_t AlignCode(size_t offset) const; 59 static size_t AlignCode(size_t offset, InstructionSet instruction_set); 60 61 // returns the difference between the code address and a usable PC. 62 // mainly to cope with kThumb2 where the lower bit must be set. 63 size_t CodeDelta() const; 64 static size_t CodeDelta(InstructionSet instruction_set); 65 66 // Returns a pointer suitable for invoking the code at the argument 67 // code_pointer address. Mainly to cope with kThumb2 where the 68 // lower bit must be set to indicate Thumb mode. 69 static const void* CodePointer(const void* code_pointer, 70 InstructionSet instruction_set); 71 72 protected: 73 template <typename T> GetArray(const LengthPrefixedArray<T> * array)74 static ArrayRef<const T> GetArray(const LengthPrefixedArray<T>* array) { 75 if (array == nullptr) { 76 return ArrayRef<const T>(); 77 } 78 DCHECK_NE(array->size(), 0u); 79 return ArrayRef<const T>(&array->At(0), array->size()); 80 } 81 GetCompilerDriver()82 CompilerDriver* GetCompilerDriver() { 83 return compiler_driver_; 84 } 85 86 private: 87 CompilerDriver* const compiler_driver_; 88 89 const InstructionSet instruction_set_; 90 91 // Used to store the PIC code for Quick. 92 const LengthPrefixedArray<uint8_t>* const quick_code_; 93 }; 94 95 class SrcMapElem { 96 public: 97 uint32_t from_; 98 int32_t to_; 99 }; 100 101 inline bool operator<(const SrcMapElem& lhs, const SrcMapElem& rhs) { 102 if (lhs.from_ != rhs.from_) { 103 return lhs.from_ < rhs.from_; 104 } 105 return lhs.to_ < rhs.to_; 106 } 107 108 inline bool operator==(const SrcMapElem& lhs, const SrcMapElem& rhs) { 109 return lhs.from_ == rhs.from_ && lhs.to_ == rhs.to_; 110 } 111 112 class LinkerPatch { 113 public: 114 // Note: We explicitly specify the underlying type of the enum because GCC 115 // would otherwise select a bigger underlying type and then complain that 116 // 'art::LinkerPatch::patch_type_' is too small to hold all 117 // values of 'enum class art::LinkerPatch::Type' 118 // which is ridiculous given we have only a handful of values here. If we 119 // choose to squeeze the Type into fewer than 8 bits, we'll have to declare 120 // patch_type_ as an uintN_t and do explicit static_cast<>s. 121 enum class Type : uint8_t { 122 kMethod, 123 kCall, 124 kCallRelative, // NOTE: Actual patching is instruction_set-dependent. 125 kType, 126 kTypeRelative, // NOTE: Actual patching is instruction_set-dependent. 127 kTypeBssEntry, // NOTE: Actual patching is instruction_set-dependent. 128 kString, 129 kStringRelative, // NOTE: Actual patching is instruction_set-dependent. 130 kStringBssEntry, // NOTE: Actual patching is instruction_set-dependent. 131 kDexCacheArray, // NOTE: Actual patching is instruction_set-dependent. 132 kBakerReadBarrierBranch, // NOTE: Actual patching is instruction_set-dependent. 133 }; 134 MethodPatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t target_method_idx)135 static LinkerPatch MethodPatch(size_t literal_offset, 136 const DexFile* target_dex_file, 137 uint32_t target_method_idx) { 138 LinkerPatch patch(literal_offset, Type::kMethod, target_dex_file); 139 patch.method_idx_ = target_method_idx; 140 return patch; 141 } 142 CodePatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t target_method_idx)143 static LinkerPatch CodePatch(size_t literal_offset, 144 const DexFile* target_dex_file, 145 uint32_t target_method_idx) { 146 LinkerPatch patch(literal_offset, Type::kCall, target_dex_file); 147 patch.method_idx_ = target_method_idx; 148 return patch; 149 } 150 RelativeCodePatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t target_method_idx)151 static LinkerPatch RelativeCodePatch(size_t literal_offset, 152 const DexFile* target_dex_file, 153 uint32_t target_method_idx) { 154 LinkerPatch patch(literal_offset, Type::kCallRelative, target_dex_file); 155 patch.method_idx_ = target_method_idx; 156 return patch; 157 } 158 TypePatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t target_type_idx)159 static LinkerPatch TypePatch(size_t literal_offset, 160 const DexFile* target_dex_file, 161 uint32_t target_type_idx) { 162 LinkerPatch patch(literal_offset, Type::kType, target_dex_file); 163 patch.type_idx_ = target_type_idx; 164 return patch; 165 } 166 RelativeTypePatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t pc_insn_offset,uint32_t target_type_idx)167 static LinkerPatch RelativeTypePatch(size_t literal_offset, 168 const DexFile* target_dex_file, 169 uint32_t pc_insn_offset, 170 uint32_t target_type_idx) { 171 LinkerPatch patch(literal_offset, Type::kTypeRelative, target_dex_file); 172 patch.type_idx_ = target_type_idx; 173 patch.pc_insn_offset_ = pc_insn_offset; 174 return patch; 175 } 176 TypeBssEntryPatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t pc_insn_offset,uint32_t target_type_idx)177 static LinkerPatch TypeBssEntryPatch(size_t literal_offset, 178 const DexFile* target_dex_file, 179 uint32_t pc_insn_offset, 180 uint32_t target_type_idx) { 181 LinkerPatch patch(literal_offset, Type::kTypeBssEntry, target_dex_file); 182 patch.type_idx_ = target_type_idx; 183 patch.pc_insn_offset_ = pc_insn_offset; 184 return patch; 185 } 186 StringPatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t target_string_idx)187 static LinkerPatch StringPatch(size_t literal_offset, 188 const DexFile* target_dex_file, 189 uint32_t target_string_idx) { 190 LinkerPatch patch(literal_offset, Type::kString, target_dex_file); 191 patch.string_idx_ = target_string_idx; 192 return patch; 193 } 194 RelativeStringPatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t pc_insn_offset,uint32_t target_string_idx)195 static LinkerPatch RelativeStringPatch(size_t literal_offset, 196 const DexFile* target_dex_file, 197 uint32_t pc_insn_offset, 198 uint32_t target_string_idx) { 199 LinkerPatch patch(literal_offset, Type::kStringRelative, target_dex_file); 200 patch.string_idx_ = target_string_idx; 201 patch.pc_insn_offset_ = pc_insn_offset; 202 return patch; 203 } 204 StringBssEntryPatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t pc_insn_offset,uint32_t target_string_idx)205 static LinkerPatch StringBssEntryPatch(size_t literal_offset, 206 const DexFile* target_dex_file, 207 uint32_t pc_insn_offset, 208 uint32_t target_string_idx) { 209 LinkerPatch patch(literal_offset, Type::kStringBssEntry, target_dex_file); 210 patch.string_idx_ = target_string_idx; 211 patch.pc_insn_offset_ = pc_insn_offset; 212 return patch; 213 } 214 DexCacheArrayPatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t pc_insn_offset,uint32_t element_offset)215 static LinkerPatch DexCacheArrayPatch(size_t literal_offset, 216 const DexFile* target_dex_file, 217 uint32_t pc_insn_offset, 218 uint32_t element_offset) { 219 LinkerPatch patch(literal_offset, Type::kDexCacheArray, target_dex_file); 220 patch.pc_insn_offset_ = pc_insn_offset; 221 patch.element_offset_ = element_offset; 222 return patch; 223 } 224 225 static LinkerPatch BakerReadBarrierBranchPatch(size_t literal_offset, 226 uint32_t custom_value1 = 0u, 227 uint32_t custom_value2 = 0u) { 228 LinkerPatch patch(literal_offset, Type::kBakerReadBarrierBranch, nullptr); 229 patch.baker_custom_value1_ = custom_value1; 230 patch.baker_custom_value2_ = custom_value2; 231 return patch; 232 } 233 234 LinkerPatch(const LinkerPatch& other) = default; 235 LinkerPatch& operator=(const LinkerPatch& other) = default; 236 LiteralOffset()237 size_t LiteralOffset() const { 238 return literal_offset_; 239 } 240 GetType()241 Type GetType() const { 242 return patch_type_; 243 } 244 IsPcRelative()245 bool IsPcRelative() const { 246 switch (GetType()) { 247 case Type::kCallRelative: 248 case Type::kTypeRelative: 249 case Type::kTypeBssEntry: 250 case Type::kStringRelative: 251 case Type::kStringBssEntry: 252 case Type::kDexCacheArray: 253 case Type::kBakerReadBarrierBranch: 254 return true; 255 default: 256 return false; 257 } 258 } 259 TargetMethod()260 MethodReference TargetMethod() const { 261 DCHECK(patch_type_ == Type::kMethod || 262 patch_type_ == Type::kCall || 263 patch_type_ == Type::kCallRelative); 264 return MethodReference(target_dex_file_, method_idx_); 265 } 266 TargetTypeDexFile()267 const DexFile* TargetTypeDexFile() const { 268 DCHECK(patch_type_ == Type::kType || 269 patch_type_ == Type::kTypeRelative || 270 patch_type_ == Type::kTypeBssEntry); 271 return target_dex_file_; 272 } 273 TargetTypeIndex()274 dex::TypeIndex TargetTypeIndex() const { 275 DCHECK(patch_type_ == Type::kType || 276 patch_type_ == Type::kTypeRelative || 277 patch_type_ == Type::kTypeBssEntry); 278 return dex::TypeIndex(type_idx_); 279 } 280 TargetStringDexFile()281 const DexFile* TargetStringDexFile() const { 282 DCHECK(patch_type_ == Type::kString || 283 patch_type_ == Type::kStringRelative || 284 patch_type_ == Type::kStringBssEntry); 285 return target_dex_file_; 286 } 287 TargetStringIndex()288 dex::StringIndex TargetStringIndex() const { 289 DCHECK(patch_type_ == Type::kString || 290 patch_type_ == Type::kStringRelative || 291 patch_type_ == Type::kStringBssEntry); 292 return dex::StringIndex(string_idx_); 293 } 294 TargetDexCacheDexFile()295 const DexFile* TargetDexCacheDexFile() const { 296 DCHECK(patch_type_ == Type::kDexCacheArray); 297 return target_dex_file_; 298 } 299 TargetDexCacheElementOffset()300 size_t TargetDexCacheElementOffset() const { 301 DCHECK(patch_type_ == Type::kDexCacheArray); 302 return element_offset_; 303 } 304 PcInsnOffset()305 uint32_t PcInsnOffset() const { 306 DCHECK(patch_type_ == Type::kTypeRelative || 307 patch_type_ == Type::kTypeBssEntry || 308 patch_type_ == Type::kStringRelative || 309 patch_type_ == Type::kStringBssEntry || 310 patch_type_ == Type::kDexCacheArray); 311 return pc_insn_offset_; 312 } 313 GetBakerCustomValue1()314 uint32_t GetBakerCustomValue1() const { 315 DCHECK(patch_type_ == Type::kBakerReadBarrierBranch); 316 return baker_custom_value1_; 317 } 318 GetBakerCustomValue2()319 uint32_t GetBakerCustomValue2() const { 320 DCHECK(patch_type_ == Type::kBakerReadBarrierBranch); 321 return baker_custom_value2_; 322 } 323 324 private: LinkerPatch(size_t literal_offset,Type patch_type,const DexFile * target_dex_file)325 LinkerPatch(size_t literal_offset, Type patch_type, const DexFile* target_dex_file) 326 : target_dex_file_(target_dex_file), 327 literal_offset_(literal_offset), 328 patch_type_(patch_type) { 329 cmp1_ = 0u; 330 cmp2_ = 0u; 331 // The compiler rejects methods that are too big, so the compiled code 332 // of a single method really shouln't be anywhere close to 16MiB. 333 DCHECK(IsUint<24>(literal_offset)); 334 } 335 336 const DexFile* target_dex_file_; 337 // TODO: Clean up naming. Some patched locations are literals but others are not. 338 uint32_t literal_offset_ : 24; // Method code size up to 16MiB. 339 Type patch_type_ : 8; 340 union { 341 uint32_t cmp1_; // Used for relational operators. 342 uint32_t method_idx_; // Method index for Call/Method patches. 343 uint32_t type_idx_; // Type index for Type patches. 344 uint32_t string_idx_; // String index for String patches. 345 uint32_t element_offset_; // Element offset in the dex cache arrays. 346 uint32_t baker_custom_value1_; 347 static_assert(sizeof(method_idx_) == sizeof(cmp1_), "needed by relational operators"); 348 static_assert(sizeof(type_idx_) == sizeof(cmp1_), "needed by relational operators"); 349 static_assert(sizeof(string_idx_) == sizeof(cmp1_), "needed by relational operators"); 350 static_assert(sizeof(element_offset_) == sizeof(cmp1_), "needed by relational operators"); 351 static_assert(sizeof(baker_custom_value1_) == sizeof(cmp1_), "needed by relational operators"); 352 }; 353 union { 354 // Note: To avoid uninitialized padding on 64-bit systems, we use `size_t` for `cmp2_`. 355 // This allows a hashing function to treat an array of linker patches as raw memory. 356 size_t cmp2_; // Used for relational operators. 357 // Literal offset of the insn loading PC (same as literal_offset if it's the same insn, 358 // may be different if the PC-relative addressing needs multiple insns). 359 uint32_t pc_insn_offset_; 360 uint32_t baker_custom_value2_; 361 static_assert(sizeof(pc_insn_offset_) <= sizeof(cmp2_), "needed by relational operators"); 362 static_assert(sizeof(baker_custom_value2_) <= sizeof(cmp2_), "needed by relational operators"); 363 }; 364 365 friend bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs); 366 friend bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs); 367 }; 368 std::ostream& operator<<(std::ostream& os, const LinkerPatch::Type& type); 369 370 inline bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs) { 371 return lhs.literal_offset_ == rhs.literal_offset_ && 372 lhs.patch_type_ == rhs.patch_type_ && 373 lhs.target_dex_file_ == rhs.target_dex_file_ && 374 lhs.cmp1_ == rhs.cmp1_ && 375 lhs.cmp2_ == rhs.cmp2_; 376 } 377 378 inline bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs) { 379 return (lhs.literal_offset_ != rhs.literal_offset_) ? lhs.literal_offset_ < rhs.literal_offset_ 380 : (lhs.patch_type_ != rhs.patch_type_) ? lhs.patch_type_ < rhs.patch_type_ 381 : (lhs.target_dex_file_ != rhs.target_dex_file_) ? lhs.target_dex_file_ < rhs.target_dex_file_ 382 : (lhs.cmp1_ != rhs.cmp1_) ? lhs.cmp1_ < rhs.cmp1_ 383 : lhs.cmp2_ < rhs.cmp2_; 384 } 385 386 class CompiledMethod FINAL : public CompiledCode { 387 public: 388 // Constructs a CompiledMethod. 389 // Note: Consider using the static allocation methods below that will allocate the CompiledMethod 390 // in the swap space. 391 CompiledMethod(CompilerDriver* driver, 392 InstructionSet instruction_set, 393 const ArrayRef<const uint8_t>& quick_code, 394 const size_t frame_size_in_bytes, 395 const uint32_t core_spill_mask, 396 const uint32_t fp_spill_mask, 397 const ArrayRef<const uint8_t>& method_info, 398 const ArrayRef<const uint8_t>& vmap_table, 399 const ArrayRef<const uint8_t>& cfi_info, 400 const ArrayRef<const LinkerPatch>& patches); 401 402 virtual ~CompiledMethod(); 403 404 static CompiledMethod* SwapAllocCompiledMethod( 405 CompilerDriver* driver, 406 InstructionSet instruction_set, 407 const ArrayRef<const uint8_t>& quick_code, 408 const size_t frame_size_in_bytes, 409 const uint32_t core_spill_mask, 410 const uint32_t fp_spill_mask, 411 const ArrayRef<const uint8_t>& method_info, 412 const ArrayRef<const uint8_t>& vmap_table, 413 const ArrayRef<const uint8_t>& cfi_info, 414 const ArrayRef<const LinkerPatch>& patches); 415 416 static void ReleaseSwapAllocatedCompiledMethod(CompilerDriver* driver, CompiledMethod* m); 417 GetFrameSizeInBytes()418 size_t GetFrameSizeInBytes() const { 419 return frame_size_in_bytes_; 420 } 421 GetCoreSpillMask()422 uint32_t GetCoreSpillMask() const { 423 return core_spill_mask_; 424 } 425 GetFpSpillMask()426 uint32_t GetFpSpillMask() const { 427 return fp_spill_mask_; 428 } 429 GetMethodInfo()430 ArrayRef<const uint8_t> GetMethodInfo() const { 431 return GetArray(method_info_); 432 } 433 GetVmapTable()434 ArrayRef<const uint8_t> GetVmapTable() const { 435 return GetArray(vmap_table_); 436 } 437 GetCFIInfo()438 ArrayRef<const uint8_t> GetCFIInfo() const { 439 return GetArray(cfi_info_); 440 } 441 GetPatches()442 ArrayRef<const LinkerPatch> GetPatches() const { 443 return GetArray(patches_); 444 } 445 446 private: 447 // For quick code, the size of the activation used by the code. 448 const size_t frame_size_in_bytes_; 449 // For quick code, a bit mask describing spilled GPR callee-save registers. 450 const uint32_t core_spill_mask_; 451 // For quick code, a bit mask describing spilled FPR callee-save registers. 452 const uint32_t fp_spill_mask_; 453 // For quick code, method specific information that is not very dedupe friendly (method indices). 454 const LengthPrefixedArray<uint8_t>* const method_info_; 455 // For quick code, holds code infos which contain stack maps, inline information, and etc. 456 const LengthPrefixedArray<uint8_t>* const vmap_table_; 457 // For quick code, a FDE entry for the debug_frame section. 458 const LengthPrefixedArray<uint8_t>* const cfi_info_; 459 // For quick code, linker patches needed by the method. 460 const LengthPrefixedArray<LinkerPatch>* const patches_; 461 }; 462 463 } // namespace art 464 465 #endif // ART_COMPILER_COMPILED_METHOD_H_ 466