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 <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 CompilerDriver; 32 class CompiledMethodStorage; 33 template<typename T> class LengthPrefixedArray; 34 35 namespace linker { 36 class LinkerPatch; 37 } // namespace linker 38 39 class CompiledCode { 40 public: 41 // For Quick to supply an code blob 42 CompiledCode(CompilerDriver* compiler_driver, 43 InstructionSet instruction_set, 44 const ArrayRef<const uint8_t>& quick_code); 45 46 virtual ~CompiledCode(); 47 GetInstructionSet()48 InstructionSet GetInstructionSet() const { 49 return GetPackedField<InstructionSetField>(); 50 } 51 52 ArrayRef<const uint8_t> GetQuickCode() const; 53 54 bool operator==(const CompiledCode& rhs) const; 55 56 // To align an offset from a page-aligned value to make it suitable 57 // for code storage. For example on ARM, to ensure that PC relative 58 // valu computations work out as expected. 59 size_t AlignCode(size_t offset) const; 60 static size_t AlignCode(size_t offset, InstructionSet instruction_set); 61 62 // returns the difference between the code address and a usable PC. 63 // mainly to cope with kThumb2 where the lower bit must be set. 64 size_t CodeDelta() const; 65 static size_t CodeDelta(InstructionSet instruction_set); 66 67 // Returns a pointer suitable for invoking the code at the argument 68 // code_pointer address. Mainly to cope with kThumb2 where the 69 // lower bit must be set to indicate Thumb mode. 70 static const void* CodePointer(const void* code_pointer, InstructionSet instruction_set); 71 72 protected: 73 static constexpr size_t kInstructionSetFieldSize = 74 MinimumBitsToStore(static_cast<size_t>(InstructionSet::kLast)); 75 static constexpr size_t kNumberOfCompiledCodePackedBits = kInstructionSetFieldSize; 76 static constexpr size_t kMaxNumberOfPackedBits = sizeof(uint32_t) * kBitsPerByte; 77 78 template <typename T> 79 static ArrayRef<const T> GetArray(const LengthPrefixedArray<T>* array); 80 GetCompilerDriver()81 CompilerDriver* GetCompilerDriver() { 82 return compiler_driver_; 83 } 84 85 template <typename BitFieldType> GetPackedField()86 typename BitFieldType::value_type GetPackedField() const { 87 return BitFieldType::Decode(packed_fields_); 88 } 89 90 template <typename BitFieldType> SetPackedField(typename BitFieldType::value_type value)91 void SetPackedField(typename BitFieldType::value_type value) { 92 DCHECK(IsUint<BitFieldType::size>(static_cast<uintptr_t>(value))); 93 packed_fields_ = BitFieldType::Update(value, packed_fields_); 94 } 95 96 private: 97 using InstructionSetField = BitField<InstructionSet, 0u, kInstructionSetFieldSize>; 98 99 CompilerDriver* const compiler_driver_; 100 101 // Used to store the compiled code. 102 const LengthPrefixedArray<uint8_t>* const quick_code_; 103 104 uint32_t packed_fields_; 105 }; 106 107 class CompiledMethod FINAL : public CompiledCode { 108 public: 109 // Constructs a CompiledMethod. 110 // Note: Consider using the static allocation methods below that will allocate the CompiledMethod 111 // in the swap space. 112 CompiledMethod(CompilerDriver* driver, 113 InstructionSet instruction_set, 114 const ArrayRef<const uint8_t>& quick_code, 115 const size_t frame_size_in_bytes, 116 const uint32_t core_spill_mask, 117 const uint32_t fp_spill_mask, 118 const ArrayRef<const uint8_t>& method_info, 119 const ArrayRef<const uint8_t>& vmap_table, 120 const ArrayRef<const uint8_t>& cfi_info, 121 const ArrayRef<const linker::LinkerPatch>& patches); 122 123 virtual ~CompiledMethod(); 124 125 static CompiledMethod* SwapAllocCompiledMethod( 126 CompilerDriver* driver, 127 InstructionSet instruction_set, 128 const ArrayRef<const uint8_t>& quick_code, 129 const size_t frame_size_in_bytes, 130 const uint32_t core_spill_mask, 131 const uint32_t fp_spill_mask, 132 const ArrayRef<const uint8_t>& method_info, 133 const ArrayRef<const uint8_t>& vmap_table, 134 const ArrayRef<const uint8_t>& cfi_info, 135 const ArrayRef<const linker::LinkerPatch>& patches); 136 137 static void ReleaseSwapAllocatedCompiledMethod(CompilerDriver* driver, CompiledMethod* m); 138 IsIntrinsic()139 bool IsIntrinsic() const { 140 return GetPackedField<IsIntrinsicField>(); 141 } 142 143 // Marks the compiled method as being generated using an intrinsic codegen. 144 // Such methods have no relationships to their code items. 145 // This affects debug information generated at link time. MarkAsIntrinsic()146 void MarkAsIntrinsic() { 147 DCHECK(!IsIntrinsic()); 148 SetPackedField<IsIntrinsicField>(/* value */ true); 149 } 150 GetFrameSizeInBytes()151 size_t GetFrameSizeInBytes() const { 152 return frame_size_in_bytes_; 153 } 154 GetCoreSpillMask()155 uint32_t GetCoreSpillMask() const { 156 return core_spill_mask_; 157 } 158 GetFpSpillMask()159 uint32_t GetFpSpillMask() const { 160 return fp_spill_mask_; 161 } 162 163 ArrayRef<const uint8_t> GetMethodInfo() const; 164 165 ArrayRef<const uint8_t> GetVmapTable() const; 166 167 ArrayRef<const uint8_t> GetCFIInfo() const; 168 169 ArrayRef<const linker::LinkerPatch> GetPatches() const; 170 171 private: 172 static constexpr size_t kIsIntrinsicLsb = kNumberOfCompiledCodePackedBits; 173 static constexpr size_t kIsIntrinsicSize = 1u; 174 static constexpr size_t kNumberOfCompiledMethodPackedBits = kIsIntrinsicLsb + kIsIntrinsicSize; 175 static_assert(kNumberOfCompiledMethodPackedBits <= CompiledCode::kMaxNumberOfPackedBits, 176 "Too many packed fields."); 177 178 using IsIntrinsicField = BitField<bool, kIsIntrinsicLsb, kIsIntrinsicSize>; 179 180 // For quick code, the size of the activation used by the code. 181 const size_t frame_size_in_bytes_; 182 // For quick code, a bit mask describing spilled GPR callee-save registers. 183 const uint32_t core_spill_mask_; 184 // For quick code, a bit mask describing spilled FPR callee-save registers. 185 const uint32_t fp_spill_mask_; 186 // For quick code, method specific information that is not very dedupe friendly (method indices). 187 const LengthPrefixedArray<uint8_t>* const method_info_; 188 // For quick code, holds code infos which contain stack maps, inline information, and etc. 189 const LengthPrefixedArray<uint8_t>* const vmap_table_; 190 // For quick code, a FDE entry for the debug_frame section. 191 const LengthPrefixedArray<uint8_t>* const cfi_info_; 192 // For quick code, linker patches needed by the method. 193 const LengthPrefixedArray<linker::LinkerPatch>* const patches_; 194 }; 195 196 } // namespace art 197 198 #endif // ART_COMPILER_COMPILED_METHOD_H_ 199