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 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 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_(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 46 void 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 58 bool 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 80 uint32_t CompiledCode::AlignCode(uint32_t offset) const { 81 return AlignCode(offset, instruction_set_); 82 } 83 84 uint32_t CompiledCode::AlignCode(uint32_t offset, InstructionSet instruction_set) { 85 return RoundUp(offset, GetInstructionSetAlignment(instruction_set)); 86 } 87 88 size_t CompiledCode::CodeDelta() const { 89 return CodeDelta(instruction_set_); 90 } 91 92 size_t CompiledCode::CodeDelta(InstructionSet instruction_set) { 93 switch (instruction_set) { 94 case kArm: 95 case kArm64: 96 case kMips: 97 case kX86: 98 case kX86_64: 99 return 0; 100 case kThumb2: { 101 // +1 to set the low-order bit so a BLX will switch to Thumb mode 102 return 1; 103 } 104 default: 105 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set; 106 return 0; 107 } 108 } 109 110 const void* CompiledCode::CodePointer(const void* code_pointer, 111 InstructionSet instruction_set) { 112 switch (instruction_set) { 113 case kArm: 114 case kArm64: 115 case kMips: 116 case kX86: 117 case kX86_64: 118 return code_pointer; 119 case kThumb2: { 120 uintptr_t address = reinterpret_cast<uintptr_t>(code_pointer); 121 // Set the low-order bit so a BLX will switch to Thumb mode 122 address |= 0x1; 123 return reinterpret_cast<const void*>(address); 124 } 125 default: 126 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set; 127 return NULL; 128 } 129 } 130 131 const std::string& CompiledCode::GetSymbol() const { 132 CHECK_NE(0U, symbol_.size()); 133 return symbol_; 134 } 135 136 const std::vector<uint32_t>& CompiledCode::GetOatdataOffsetsToCompliledCodeOffset() const { 137 CHECK_NE(0U, oatdata_offsets_to_compiled_code_offset_.size()) << symbol_; 138 return oatdata_offsets_to_compiled_code_offset_; 139 } 140 141 void CompiledCode::AddOatdataOffsetToCompliledCodeOffset(uint32_t offset) { 142 oatdata_offsets_to_compiled_code_offset_.push_back(offset); 143 } 144 145 CompiledMethod::CompiledMethod(CompilerDriver* driver, 146 InstructionSet instruction_set, 147 const std::vector<uint8_t>& quick_code, 148 const size_t frame_size_in_bytes, 149 const uint32_t core_spill_mask, 150 const uint32_t fp_spill_mask, 151 const std::vector<uint8_t>& mapping_table, 152 const std::vector<uint8_t>& vmap_table, 153 const std::vector<uint8_t>& native_gc_map, 154 const std::vector<uint8_t>* cfi_info) 155 : CompiledCode(driver, instruction_set, quick_code), frame_size_in_bytes_(frame_size_in_bytes), 156 core_spill_mask_(core_spill_mask), fp_spill_mask_(fp_spill_mask), 157 mapping_table_(driver->DeduplicateMappingTable(mapping_table)), 158 vmap_table_(driver->DeduplicateVMapTable(vmap_table)), 159 gc_map_(driver->DeduplicateGCMap(native_gc_map)), 160 cfi_info_(driver->DeduplicateCFIInfo(cfi_info)) { 161 } 162 163 CompiledMethod::CompiledMethod(CompilerDriver* driver, 164 InstructionSet instruction_set, 165 const std::vector<uint8_t>& code, 166 const size_t frame_size_in_bytes, 167 const uint32_t core_spill_mask, 168 const uint32_t fp_spill_mask) 169 : CompiledCode(driver, instruction_set, code), 170 frame_size_in_bytes_(frame_size_in_bytes), 171 core_spill_mask_(core_spill_mask), fp_spill_mask_(fp_spill_mask), 172 mapping_table_(driver->DeduplicateMappingTable(std::vector<uint8_t>())), 173 vmap_table_(driver->DeduplicateVMapTable(std::vector<uint8_t>())), 174 gc_map_(driver->DeduplicateGCMap(std::vector<uint8_t>())), 175 cfi_info_(nullptr) { 176 } 177 178 // Constructs a CompiledMethod for the Portable compiler. 179 CompiledMethod::CompiledMethod(CompilerDriver* driver, InstructionSet instruction_set, 180 const std::string& code, const std::vector<uint8_t>& gc_map, 181 const std::string& symbol) 182 : CompiledCode(driver, instruction_set, code, symbol), 183 frame_size_in_bytes_(kStackAlignment), core_spill_mask_(0), 184 fp_spill_mask_(0), gc_map_(driver->DeduplicateGCMap(gc_map)) { 185 mapping_table_ = driver->DeduplicateMappingTable(std::vector<uint8_t>()); 186 vmap_table_ = driver->DeduplicateVMapTable(std::vector<uint8_t>()); 187 } 188 189 CompiledMethod::CompiledMethod(CompilerDriver* driver, InstructionSet instruction_set, 190 const std::string& code, const std::string& symbol) 191 : CompiledCode(driver, instruction_set, code, symbol), 192 frame_size_in_bytes_(kStackAlignment), core_spill_mask_(0), 193 fp_spill_mask_(0) { 194 mapping_table_ = driver->DeduplicateMappingTable(std::vector<uint8_t>()); 195 vmap_table_ = driver->DeduplicateVMapTable(std::vector<uint8_t>()); 196 gc_map_ = driver->DeduplicateGCMap(std::vector<uint8_t>()); 197 } 198 199 } // namespace art 200