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