blob: 4eb1f7a7ce96708a74200833d7758be0030a0484 [file] [log] [blame]
Mathieu Chartier193bad92013-08-29 18:46:00 -07001/*
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"
Dave Allisonf9487c02014-04-08 23:08:12 +000019#include "oat_writer.h"
20#include "dex/compiler_ir.h"
Mathieu Chartier193bad92013-08-29 18:46:00 -070021
22namespace art {
23
24CompiledCode::CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set,
Dave Allisonf9487c02014-04-08 23:08:12 +000025 const std::vector<uint8_t>& quick_code,
26 const FinalRelocations* relocs)
Ian Rogersef7d42f2014-01-06 12:55:46 -080027 : compiler_driver_(compiler_driver), instruction_set_(instruction_set),
Dave Allisonf9487c02014-04-08 23:08:12 +000028 portable_code_(nullptr), quick_code_(nullptr), final_relocations_(relocs) {
Ian Rogersef7d42f2014-01-06 12:55:46 -080029 SetCode(&quick_code, nullptr);
Mathieu Chartier193bad92013-08-29 18:46:00 -070030}
31
32CompiledCode::CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set,
33 const std::string& elf_object, const std::string& symbol)
Ian Rogersef7d42f2014-01-06 12:55:46 -080034 : compiler_driver_(compiler_driver), instruction_set_(instruction_set),
Dave Allisonf9487c02014-04-08 23:08:12 +000035 portable_code_(nullptr), quick_code_(nullptr), symbol_(symbol), final_relocations_(nullptr) {
Mathieu Chartier193bad92013-08-29 18:46:00 -070036 CHECK_NE(elf_object.size(), 0U);
37 CHECK_NE(symbol.size(), 0U);
38 std::vector<uint8_t> temp_code(elf_object.size());
39 for (size_t i = 0; i < elf_object.size(); ++i) {
40 temp_code[i] = elf_object[i];
41 }
42 // TODO: we shouldn't just shove ELF objects in as "code" but
43 // change to have different kinds of compiled methods. This is
44 // being deferred until we work on hybrid execution or at least
45 // until we work on batch compilation.
Ian Rogersef7d42f2014-01-06 12:55:46 -080046 SetCode(nullptr, &temp_code);
Mathieu Chartier193bad92013-08-29 18:46:00 -070047}
48
Ian Rogersef7d42f2014-01-06 12:55:46 -080049void CompiledCode::SetCode(const std::vector<uint8_t>* quick_code,
50 const std::vector<uint8_t>* portable_code) {
51 if (portable_code != nullptr) {
52 CHECK(!portable_code->empty());
53 portable_code_ = compiler_driver_->DeduplicateCode(*portable_code);
54 }
55 if (quick_code != nullptr) {
56 CHECK(!quick_code->empty());
57 quick_code_ = compiler_driver_->DeduplicateCode(*quick_code);
58 }
59}
60
61bool CompiledCode::operator==(const CompiledCode& rhs) const {
62 if (quick_code_ != nullptr) {
63 if (rhs.quick_code_ == nullptr) {
64 return false;
65 } else if (quick_code_->size() != rhs.quick_code_->size()) {
66 return false;
67 } else {
68 return std::equal(quick_code_->begin(), quick_code_->end(), rhs.quick_code_->begin());
69 }
70 } else if (portable_code_ != nullptr) {
71 if (rhs.portable_code_ == nullptr) {
72 return false;
73 } else if (portable_code_->size() != rhs.portable_code_->size()) {
74 return false;
75 } else {
76 return std::equal(portable_code_->begin(), portable_code_->end(),
77 rhs.portable_code_->begin());
78 }
79 }
80 return (rhs.quick_code_ == nullptr) && (rhs.portable_code_ == nullptr);
Mathieu Chartier193bad92013-08-29 18:46:00 -070081}
82
83uint32_t CompiledCode::AlignCode(uint32_t offset) const {
84 return AlignCode(offset, instruction_set_);
85}
86
87uint32_t CompiledCode::AlignCode(uint32_t offset, InstructionSet instruction_set) {
88 switch (instruction_set) {
89 case kArm:
90 case kThumb2:
91 return RoundUp(offset, kArmAlignment);
Stuart Monteithb95a5342014-03-12 13:32:32 +000092 case kArm64:
93 return RoundUp(offset, kArm64Alignment);
Mathieu Chartier193bad92013-08-29 18:46:00 -070094 case kMips:
95 return RoundUp(offset, kMipsAlignment);
Ian Rogersbefbd572014-03-06 01:13:39 -080096 case kX86: // Fall-through.
97 case kX86_64:
Mathieu Chartier193bad92013-08-29 18:46:00 -070098 return RoundUp(offset, kX86Alignment);
99 default:
100 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
101 return 0;
102 }
103}
104
105size_t CompiledCode::CodeDelta() const {
106 switch (instruction_set_) {
107 case kArm:
Stuart Monteithb95a5342014-03-12 13:32:32 +0000108 case kArm64:
Mathieu Chartier193bad92013-08-29 18:46:00 -0700109 case kMips:
110 case kX86:
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700111 case kX86_64:
Mathieu Chartier193bad92013-08-29 18:46:00 -0700112 return 0;
113 case kThumb2: {
114 // +1 to set the low-order bit so a BLX will switch to Thumb mode
115 return 1;
116 }
117 default:
118 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set_;
119 return 0;
120 }
121}
122
123const void* CompiledCode::CodePointer(const void* code_pointer,
124 InstructionSet instruction_set) {
125 switch (instruction_set) {
126 case kArm:
Stuart Monteithb95a5342014-03-12 13:32:32 +0000127 case kArm64:
Mathieu Chartier193bad92013-08-29 18:46:00 -0700128 case kMips:
129 case kX86:
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700130 case kX86_64:
Mathieu Chartier193bad92013-08-29 18:46:00 -0700131 return code_pointer;
132 case kThumb2: {
133 uintptr_t address = reinterpret_cast<uintptr_t>(code_pointer);
134 // Set the low-order bit so a BLX will switch to Thumb mode
135 address |= 0x1;
136 return reinterpret_cast<const void*>(address);
137 }
138 default:
139 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
140 return NULL;
141 }
142}
143
Mathieu Chartier193bad92013-08-29 18:46:00 -0700144const std::string& CompiledCode::GetSymbol() const {
145 CHECK_NE(0U, symbol_.size());
146 return symbol_;
147}
148
149const std::vector<uint32_t>& CompiledCode::GetOatdataOffsetsToCompliledCodeOffset() const {
150 CHECK_NE(0U, oatdata_offsets_to_compiled_code_offset_.size()) << symbol_;
151 return oatdata_offsets_to_compiled_code_offset_;
152}
153
154void CompiledCode::AddOatdataOffsetToCompliledCodeOffset(uint32_t offset) {
155 oatdata_offsets_to_compiled_code_offset_.push_back(offset);
156}
Mathieu Chartier193bad92013-08-29 18:46:00 -0700157
158CompiledMethod::CompiledMethod(CompilerDriver& driver,
159 InstructionSet instruction_set,
Ian Rogersef7d42f2014-01-06 12:55:46 -0800160 const std::vector<uint8_t>& quick_code,
Mathieu Chartier193bad92013-08-29 18:46:00 -0700161 const size_t frame_size_in_bytes,
162 const uint32_t core_spill_mask,
163 const uint32_t fp_spill_mask,
164 const std::vector<uint8_t>& mapping_table,
165 const std::vector<uint8_t>& vmap_table,
Mark Mendellae9fd932014-02-10 16:14:35 -0800166 const std::vector<uint8_t>& native_gc_map,
Dave Allisonf9487c02014-04-08 23:08:12 +0000167 const std::vector<uint8_t>* cfi_info,
168 const FinalRelocations* relocs)
169 : CompiledCode(&driver, instruction_set, quick_code, relocs), frame_size_in_bytes_(frame_size_in_bytes),
Mathieu Chartier193bad92013-08-29 18:46:00 -0700170 core_spill_mask_(core_spill_mask), fp_spill_mask_(fp_spill_mask),
171 mapping_table_(driver.DeduplicateMappingTable(mapping_table)),
172 vmap_table_(driver.DeduplicateVMapTable(vmap_table)),
Mark Mendellae9fd932014-02-10 16:14:35 -0800173 gc_map_(driver.DeduplicateGCMap(native_gc_map)),
174 cfi_info_(driver.DeduplicateCFIInfo(cfi_info)) {
Mathieu Chartier193bad92013-08-29 18:46:00 -0700175}
176
177CompiledMethod::CompiledMethod(CompilerDriver& driver,
178 InstructionSet instruction_set,
179 const std::vector<uint8_t>& code,
180 const size_t frame_size_in_bytes,
181 const uint32_t core_spill_mask,
182 const uint32_t fp_spill_mask)
Dave Allisonf9487c02014-04-08 23:08:12 +0000183 : CompiledCode(&driver, instruction_set, code, nullptr),
Mathieu Chartier193bad92013-08-29 18:46:00 -0700184 frame_size_in_bytes_(frame_size_in_bytes),
Mark Mendellae9fd932014-02-10 16:14:35 -0800185 core_spill_mask_(core_spill_mask), fp_spill_mask_(fp_spill_mask),
186 mapping_table_(driver.DeduplicateMappingTable(std::vector<uint8_t>())),
187 vmap_table_(driver.DeduplicateVMapTable(std::vector<uint8_t>())),
188 gc_map_(driver.DeduplicateGCMap(std::vector<uint8_t>())),
189 cfi_info_(nullptr) {
Mathieu Chartier193bad92013-08-29 18:46:00 -0700190}
191
192// Constructs a CompiledMethod for the Portable compiler.
193CompiledMethod::CompiledMethod(CompilerDriver& driver, InstructionSet instruction_set,
194 const std::string& code, const std::vector<uint8_t>& gc_map,
195 const std::string& symbol)
196 : CompiledCode(&driver, instruction_set, code, symbol),
197 frame_size_in_bytes_(kStackAlignment), core_spill_mask_(0),
198 fp_spill_mask_(0), gc_map_(driver.DeduplicateGCMap(gc_map)) {
199 mapping_table_ = driver.DeduplicateMappingTable(std::vector<uint8_t>());
200 vmap_table_ = driver.DeduplicateVMapTable(std::vector<uint8_t>());
201}
202
203CompiledMethod::CompiledMethod(CompilerDriver& driver, InstructionSet instruction_set,
204 const std::string& code, const std::string& symbol)
205 : CompiledCode(&driver, instruction_set, code, symbol),
206 frame_size_in_bytes_(kStackAlignment), core_spill_mask_(0),
207 fp_spill_mask_(0) {
208 mapping_table_ = driver.DeduplicateMappingTable(std::vector<uint8_t>());
209 vmap_table_ = driver.DeduplicateVMapTable(std::vector<uint8_t>());
210 gc_map_ = driver.DeduplicateGCMap(std::vector<uint8_t>());
211}
Mathieu Chartier193bad92013-08-29 18:46:00 -0700212} // namespace art