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