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 #include "compiled_method.h" 18 #include "driver/compiler_driver.h" 19 20 namespace art { 21 22 CompiledCode::CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set, 23 const ArrayRef<const uint8_t>& quick_code) 24 : compiler_driver_(compiler_driver), instruction_set_(instruction_set), 25 portable_code_(nullptr), quick_code_(nullptr) { 26 SetCode(&quick_code, nullptr); 27 } 28 29 CompiledCode::CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set, 30 const std::string& elf_object, const std::string& symbol) 31 : compiler_driver_(compiler_driver), instruction_set_(instruction_set), 32 portable_code_(compiler_driver_->DeduplicateCode( 33 ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t*>(elf_object.data()), 34 elf_object.size()))), 35 quick_code_(nullptr), symbol_(symbol) { 36 CHECK_NE(elf_object.size(), 0U); 37 CHECK_NE(symbol.size(), 0U); 38 // TODO: we shouldn't just shove ELF objects in as "code" but 39 // change to have different kinds of compiled methods. This is 40 // being deferred until we work on hybrid execution or at least 41 // until we work on batch compilation. 42 } 43 44 void CompiledCode::SetCode(const ArrayRef<const uint8_t>* quick_code, 45 const ArrayRef<const uint8_t>* portable_code) { 46 if (portable_code != nullptr) { 47 CHECK(!portable_code->empty()); 48 portable_code_ = compiler_driver_->DeduplicateCode(*portable_code); 49 } 50 if (quick_code != nullptr) { 51 CHECK(!quick_code->empty()); 52 quick_code_ = compiler_driver_->DeduplicateCode(*quick_code); 53 } 54 } 55 56 bool CompiledCode::operator==(const CompiledCode& rhs) const { 57 if (quick_code_ != nullptr) { 58 if (rhs.quick_code_ == nullptr) { 59 return false; 60 } else if (quick_code_->size() != rhs.quick_code_->size()) { 61 return false; 62 } else { 63 return std::equal(quick_code_->begin(), quick_code_->end(), rhs.quick_code_->begin()); 64 } 65 } else if (portable_code_ != nullptr) { 66 if (rhs.portable_code_ == nullptr) { 67 return false; 68 } else if (portable_code_->size() != rhs.portable_code_->size()) { 69 return false; 70 } else { 71 return std::equal(portable_code_->begin(), portable_code_->end(), 72 rhs.portable_code_->begin()); 73 } 74 } 75 return (rhs.quick_code_ == nullptr) && (rhs.portable_code_ == nullptr); 76 } 77 78 uint32_t CompiledCode::AlignCode(uint32_t offset) const { 79 return AlignCode(offset, instruction_set_); 80 } 81 82 uint32_t CompiledCode::AlignCode(uint32_t offset, InstructionSet instruction_set) { 83 return RoundUp(offset, GetInstructionSetAlignment(instruction_set)); 84 } 85 86 size_t CompiledCode::CodeDelta() const { 87 return CodeDelta(instruction_set_); 88 } 89 90 size_t CompiledCode::CodeDelta(InstructionSet instruction_set) { 91 switch (instruction_set) { 92 case kArm: 93 case kArm64: 94 case kMips: 95 case kX86: 96 case kX86_64: 97 return 0; 98 case kThumb2: { 99 // +1 to set the low-order bit so a BLX will switch to Thumb mode 100 return 1; 101 } 102 default: 103 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set; 104 return 0; 105 } 106 } 107 108 const void* CompiledCode::CodePointer(const void* code_pointer, 109 InstructionSet instruction_set) { 110 switch (instruction_set) { 111 case kArm: 112 case kArm64: 113 case kMips: 114 case kX86: 115 case kX86_64: 116 return code_pointer; 117 case kThumb2: { 118 uintptr_t address = reinterpret_cast<uintptr_t>(code_pointer); 119 // Set the low-order bit so a BLX will switch to Thumb mode 120 address |= 0x1; 121 return reinterpret_cast<const void*>(address); 122 } 123 default: 124 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set; 125 return NULL; 126 } 127 } 128 129 const std::string& CompiledCode::GetSymbol() const { 130 CHECK_NE(0U, symbol_.size()); 131 return symbol_; 132 } 133 134 const std::vector<uint32_t>& CompiledCode::GetOatdataOffsetsToCompliledCodeOffset() const { 135 CHECK_NE(0U, oatdata_offsets_to_compiled_code_offset_.size()) << symbol_; 136 return oatdata_offsets_to_compiled_code_offset_; 137 } 138 139 void CompiledCode::AddOatdataOffsetToCompliledCodeOffset(uint32_t offset) { 140 oatdata_offsets_to_compiled_code_offset_.push_back(offset); 141 } 142 143 CompiledMethod::CompiledMethod(CompilerDriver* driver, 144 InstructionSet instruction_set, 145 const ArrayRef<const uint8_t>& quick_code, 146 const size_t frame_size_in_bytes, 147 const uint32_t core_spill_mask, 148 const uint32_t fp_spill_mask, 149 const ArrayRef<const uint8_t>& mapping_table, 150 const ArrayRef<const uint8_t>& vmap_table, 151 const ArrayRef<const uint8_t>& native_gc_map, 152 const ArrayRef<const uint8_t>& cfi_info) 153 : CompiledCode(driver, instruction_set, quick_code), frame_size_in_bytes_(frame_size_in_bytes), 154 core_spill_mask_(core_spill_mask), fp_spill_mask_(fp_spill_mask), 155 mapping_table_(driver->DeduplicateMappingTable(mapping_table)), 156 vmap_table_(driver->DeduplicateVMapTable(vmap_table)), 157 gc_map_(driver->DeduplicateGCMap(native_gc_map)), 158 cfi_info_(cfi_info.data() == nullptr ? nullptr : driver->DeduplicateCFIInfo(cfi_info)) { 159 } 160 161 CompiledMethod::CompiledMethod(CompilerDriver* driver, 162 InstructionSet instruction_set, 163 const ArrayRef<const uint8_t>& code, 164 const size_t frame_size_in_bytes, 165 const uint32_t core_spill_mask, 166 const uint32_t fp_spill_mask) 167 : CompiledCode(driver, instruction_set, code), 168 frame_size_in_bytes_(frame_size_in_bytes), 169 core_spill_mask_(core_spill_mask), fp_spill_mask_(fp_spill_mask), 170 cfi_info_(nullptr) { 171 mapping_table_ = driver->DeduplicateMappingTable(ArrayRef<const uint8_t>()); 172 vmap_table_ = driver->DeduplicateVMapTable(ArrayRef<const uint8_t>()); 173 gc_map_ = driver->DeduplicateGCMap(ArrayRef<const uint8_t>()); 174 } 175 176 // Constructs a CompiledMethod for the Portable compiler. 177 CompiledMethod::CompiledMethod(CompilerDriver* driver, InstructionSet instruction_set, 178 const std::string& code, const ArrayRef<const uint8_t>& gc_map, 179 const std::string& symbol) 180 : CompiledCode(driver, instruction_set, code, symbol), 181 frame_size_in_bytes_(kStackAlignment), core_spill_mask_(0), 182 fp_spill_mask_(0), gc_map_(driver->DeduplicateGCMap(gc_map)), 183 cfi_info_(nullptr) { 184 mapping_table_ = driver->DeduplicateMappingTable(ArrayRef<const uint8_t>()); 185 vmap_table_ = driver->DeduplicateVMapTable(ArrayRef<const uint8_t>()); 186 } 187 188 CompiledMethod::CompiledMethod(CompilerDriver* driver, InstructionSet instruction_set, 189 const std::string& code, const std::string& symbol) 190 : CompiledCode(driver, instruction_set, code, symbol), 191 frame_size_in_bytes_(kStackAlignment), core_spill_mask_(0), 192 fp_spill_mask_(0), cfi_info_(nullptr) { 193 mapping_table_ = driver->DeduplicateMappingTable(ArrayRef<const uint8_t>()); 194 vmap_table_ = driver->DeduplicateVMapTable(ArrayRef<const uint8_t>()); 195 gc_map_ = driver->DeduplicateGCMap(ArrayRef<const uint8_t>()); 196 } 197 198 CompiledMethod* CompiledMethod::SwapAllocCompiledMethod(CompilerDriver* driver, 199 InstructionSet instruction_set, 200 const ArrayRef<const uint8_t>& quick_code, 201 const size_t frame_size_in_bytes, 202 const uint32_t core_spill_mask, 203 const uint32_t fp_spill_mask, 204 const ArrayRef<const uint8_t>& mapping_table, 205 const ArrayRef<const uint8_t>& vmap_table, 206 const ArrayRef<const uint8_t>& native_gc_map, 207 const ArrayRef<const uint8_t>& cfi_info) { 208 SwapAllocator<CompiledMethod> alloc(driver->GetSwapSpaceAllocator()); 209 CompiledMethod* ret = alloc.allocate(1); 210 alloc.construct(ret, driver, instruction_set, quick_code, frame_size_in_bytes, core_spill_mask, 211 fp_spill_mask, mapping_table, vmap_table, native_gc_map, cfi_info); 212 return ret; 213 } 214 215 CompiledMethod* CompiledMethod::SwapAllocCompiledMethod(CompilerDriver* driver, 216 InstructionSet instruction_set, 217 const ArrayRef<const uint8_t>& quick_code, 218 const size_t frame_size_in_bytes, 219 const uint32_t core_spill_mask, 220 const uint32_t fp_spill_mask) { 221 SwapAllocator<CompiledMethod> alloc(driver->GetSwapSpaceAllocator()); 222 CompiledMethod* ret = alloc.allocate(1); 223 alloc.construct(ret, driver, instruction_set, quick_code, frame_size_in_bytes, core_spill_mask, 224 fp_spill_mask); 225 return ret; 226 } 227 228 void CompiledMethod::ReleaseSwapAllocatedCompiledMethod(CompilerDriver* driver, CompiledMethod* m) { 229 SwapAllocator<CompiledMethod> alloc(driver->GetSwapSpaceAllocator()); 230 alloc.destroy(m); 231 alloc.deallocate(m, 1); 232 } 233 234 } // namespace art 235