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_DEX2OAT_DRIVER_COMPILED_METHOD_H_ 18 #define ART_DEX2OAT_DRIVER_COMPILED_METHOD_H_ 19 20 #include <memory> 21 #include <string> 22 #include <vector> 23 24 #include "arch/instruction_set.h" 25 #include "base/bit_field.h" 26 #include "base/bit_utils.h" 27 28 namespace art { 29 30 template <typename T> class ArrayRef; 31 class CompiledMethodStorage; 32 template<typename T> class LengthPrefixedArray; 33 34 namespace linker { 35 class LinkerPatch; 36 } // namespace linker 37 38 class CompiledCode { 39 public: 40 // For Quick to supply an code blob 41 CompiledCode(CompiledMethodStorage* storage, 42 InstructionSet instruction_set, 43 const ArrayRef<const uint8_t>& quick_code); 44 45 virtual ~CompiledCode(); 46 GetInstructionSet()47 InstructionSet GetInstructionSet() const { 48 return GetPackedField<InstructionSetField>(); 49 } 50 51 ArrayRef<const uint8_t> GetQuickCode() const; 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 GetEntryPointAdjustment() const; 64 65 protected: 66 static constexpr size_t kInstructionSetFieldSize = 67 MinimumBitsToStore(static_cast<size_t>(InstructionSet::kLast)); 68 static constexpr size_t kNumberOfCompiledCodePackedBits = kInstructionSetFieldSize; 69 static constexpr size_t kMaxNumberOfPackedBits = sizeof(uint32_t) * kBitsPerByte; 70 71 template <typename T> 72 static ArrayRef<const T> GetArray(const LengthPrefixedArray<T>* array); 73 GetStorage()74 CompiledMethodStorage* GetStorage() { 75 return storage_; 76 } 77 78 template <typename BitFieldType> GetPackedField()79 typename BitFieldType::value_type GetPackedField() const { 80 return BitFieldType::Decode(packed_fields_); 81 } 82 83 template <typename BitFieldType> SetPackedField(typename BitFieldType::value_type value)84 void SetPackedField(typename BitFieldType::value_type value) { 85 DCHECK(IsUint<BitFieldType::size>(static_cast<uintptr_t>(value))); 86 packed_fields_ = BitFieldType::Update(value, packed_fields_); 87 } 88 89 private: 90 using InstructionSetField = BitField<InstructionSet, 0u, kInstructionSetFieldSize>; 91 92 CompiledMethodStorage* const storage_; 93 94 // Used to store the compiled code. 95 const LengthPrefixedArray<uint8_t>* const quick_code_; 96 97 uint32_t packed_fields_; 98 }; 99 100 class CompiledMethod final : public CompiledCode { 101 public: 102 // Constructs a CompiledMethod. 103 // Note: Consider using the static allocation methods below that will allocate the CompiledMethod 104 // in the swap space. 105 CompiledMethod(CompiledMethodStorage* storage, 106 InstructionSet instruction_set, 107 const ArrayRef<const uint8_t>& quick_code, 108 const ArrayRef<const uint8_t>& vmap_table, 109 const ArrayRef<const uint8_t>& cfi_info, 110 const ArrayRef<const linker::LinkerPatch>& patches); 111 112 virtual ~CompiledMethod(); 113 114 static CompiledMethod* SwapAllocCompiledMethod( 115 CompiledMethodStorage* storage, 116 InstructionSet instruction_set, 117 const ArrayRef<const uint8_t>& quick_code, 118 const ArrayRef<const uint8_t>& vmap_table, 119 const ArrayRef<const uint8_t>& cfi_info, 120 const ArrayRef<const linker::LinkerPatch>& patches); 121 122 static void ReleaseSwapAllocatedCompiledMethod(CompiledMethodStorage* storage, CompiledMethod* m); 123 IsIntrinsic()124 bool IsIntrinsic() const { 125 return GetPackedField<IsIntrinsicField>(); 126 } 127 128 // Marks the compiled method as being generated using an intrinsic codegen. 129 // Such methods have no relationships to their code items. 130 // This affects debug information generated at link time. MarkAsIntrinsic()131 void MarkAsIntrinsic() { 132 DCHECK(!IsIntrinsic()); 133 SetPackedField<IsIntrinsicField>(/* value= */ true); 134 } 135 136 ArrayRef<const uint8_t> GetVmapTable() const; 137 138 ArrayRef<const uint8_t> GetCFIInfo() const; 139 140 ArrayRef<const linker::LinkerPatch> GetPatches() const; 141 142 private: 143 static constexpr size_t kIsIntrinsicLsb = kNumberOfCompiledCodePackedBits; 144 static constexpr size_t kIsIntrinsicSize = 1u; 145 static constexpr size_t kNumberOfCompiledMethodPackedBits = kIsIntrinsicLsb + kIsIntrinsicSize; 146 static_assert(kNumberOfCompiledMethodPackedBits <= CompiledCode::kMaxNumberOfPackedBits, 147 "Too many packed fields."); 148 149 using IsIntrinsicField = BitField<bool, kIsIntrinsicLsb, kIsIntrinsicSize>; 150 151 // For quick code, holds code infos which contain stack maps, inline information, and etc. 152 const LengthPrefixedArray<uint8_t>* const vmap_table_; 153 // For quick code, a FDE entry for the debug_frame section. 154 const LengthPrefixedArray<uint8_t>* const cfi_info_; 155 // For quick code, linker patches needed by the method. 156 const LengthPrefixedArray<linker::LinkerPatch>* const patches_; 157 }; 158 159 } // namespace art 160 161 #endif // ART_DEX2OAT_DRIVER_COMPILED_METHOD_H_ 162