blob: 40ef51344c282e4216eeac68749749b1c1aa1b85 [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"
19
20namespace art {
21
22CompiledCode::CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set,
Andreas Gampe62746d82014-12-08 16:59:43 -080023 const ArrayRef<const uint8_t>& quick_code)
Ian Rogersef7d42f2014-01-06 12:55:46 -080024 : compiler_driver_(compiler_driver), instruction_set_(instruction_set),
Dave Allisond6ed6422014-04-09 23:36:15 +000025 portable_code_(nullptr), quick_code_(nullptr) {
Ian Rogersef7d42f2014-01-06 12:55:46 -080026 SetCode(&quick_code, nullptr);
Mathieu Chartier193bad92013-08-29 18:46:00 -070027}
28
29CompiledCode::CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set,
30 const std::string& elf_object, const std::string& symbol)
Ian Rogersef7d42f2014-01-06 12:55:46 -080031 : compiler_driver_(compiler_driver), instruction_set_(instruction_set),
Andreas Gampe62746d82014-12-08 16:59:43 -080032 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) {
Mathieu Chartier193bad92013-08-29 18:46:00 -070036 CHECK_NE(elf_object.size(), 0U);
37 CHECK_NE(symbol.size(), 0U);
Mathieu Chartier193bad92013-08-29 18:46:00 -070038 // 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.
Mathieu Chartier193bad92013-08-29 18:46:00 -070042}
43
Andreas Gampe62746d82014-12-08 16:59:43 -080044void CompiledCode::SetCode(const ArrayRef<const uint8_t>* quick_code,
45 const ArrayRef<const uint8_t>* portable_code) {
Ian Rogersef7d42f2014-01-06 12:55:46 -080046 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
56bool 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);
Mathieu Chartier193bad92013-08-29 18:46:00 -070076}
77
78uint32_t CompiledCode::AlignCode(uint32_t offset) const {
79 return AlignCode(offset, instruction_set_);
80}
81
82uint32_t CompiledCode::AlignCode(uint32_t offset, InstructionSet instruction_set) {
Andreas Gampeaf13ad92014-04-11 12:07:48 -070083 return RoundUp(offset, GetInstructionSetAlignment(instruction_set));
Mathieu Chartier193bad92013-08-29 18:46:00 -070084}
85
86size_t CompiledCode::CodeDelta() const {
Dave Allison50abf0a2014-06-23 13:19:59 -070087 return CodeDelta(instruction_set_);
88}
89
90size_t CompiledCode::CodeDelta(InstructionSet instruction_set) {
91 switch (instruction_set) {
Mathieu Chartier193bad92013-08-29 18:46:00 -070092 case kArm:
Stuart Monteithb95a5342014-03-12 13:32:32 +000093 case kArm64:
Mathieu Chartier193bad92013-08-29 18:46:00 -070094 case kMips:
95 case kX86:
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070096 case kX86_64:
Mathieu Chartier193bad92013-08-29 18:46:00 -070097 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:
Dave Allison50abf0a2014-06-23 13:19:59 -0700103 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
Mathieu Chartier193bad92013-08-29 18:46:00 -0700104 return 0;
105 }
106}
107
108const void* CompiledCode::CodePointer(const void* code_pointer,
109 InstructionSet instruction_set) {
110 switch (instruction_set) {
111 case kArm:
Stuart Monteithb95a5342014-03-12 13:32:32 +0000112 case kArm64:
Mathieu Chartier193bad92013-08-29 18:46:00 -0700113 case kMips:
114 case kX86:
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700115 case kX86_64:
Mathieu Chartier193bad92013-08-29 18:46:00 -0700116 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
Mathieu Chartier193bad92013-08-29 18:46:00 -0700129const std::string& CompiledCode::GetSymbol() const {
130 CHECK_NE(0U, symbol_.size());
131 return symbol_;
132}
133
134const 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
139void CompiledCode::AddOatdataOffsetToCompliledCodeOffset(uint32_t offset) {
140 oatdata_offsets_to_compiled_code_offset_.push_back(offset);
141}
Mathieu Chartier193bad92013-08-29 18:46:00 -0700142
Ian Rogers72d32622014-05-06 16:20:11 -0700143CompiledMethod::CompiledMethod(CompilerDriver* driver,
Mathieu Chartier193bad92013-08-29 18:46:00 -0700144 InstructionSet instruction_set,
Andreas Gampe62746d82014-12-08 16:59:43 -0800145 const ArrayRef<const uint8_t>& quick_code,
Mathieu Chartier193bad92013-08-29 18:46:00 -0700146 const size_t frame_size_in_bytes,
147 const uint32_t core_spill_mask,
148 const uint32_t fp_spill_mask,
Andreas Gampe62746d82014-12-08 16:59:43 -0800149 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)
Ian Rogers72d32622014-05-06 16:20:11 -0700153 : CompiledCode(driver, instruction_set, quick_code), frame_size_in_bytes_(frame_size_in_bytes),
Mathieu Chartier193bad92013-08-29 18:46:00 -0700154 core_spill_mask_(core_spill_mask), fp_spill_mask_(fp_spill_mask),
Andreas Gampe62746d82014-12-08 16:59:43 -0800155 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)) {
Mathieu Chartier193bad92013-08-29 18:46:00 -0700159}
160
Ian Rogers72d32622014-05-06 16:20:11 -0700161CompiledMethod::CompiledMethod(CompilerDriver* driver,
Mathieu Chartier193bad92013-08-29 18:46:00 -0700162 InstructionSet instruction_set,
Andreas Gampe62746d82014-12-08 16:59:43 -0800163 const ArrayRef<const uint8_t>& code,
Mathieu Chartier193bad92013-08-29 18:46:00 -0700164 const size_t frame_size_in_bytes,
165 const uint32_t core_spill_mask,
166 const uint32_t fp_spill_mask)
Ian Rogers72d32622014-05-06 16:20:11 -0700167 : CompiledCode(driver, instruction_set, code),
Mathieu Chartier193bad92013-08-29 18:46:00 -0700168 frame_size_in_bytes_(frame_size_in_bytes),
Mark Mendellae9fd932014-02-10 16:14:35 -0800169 core_spill_mask_(core_spill_mask), fp_spill_mask_(fp_spill_mask),
Mark Mendellae9fd932014-02-10 16:14:35 -0800170 cfi_info_(nullptr) {
Andreas Gampe62746d82014-12-08 16:59:43 -0800171 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>());
Mathieu Chartier193bad92013-08-29 18:46:00 -0700174}
175
176// Constructs a CompiledMethod for the Portable compiler.
Ian Rogers72d32622014-05-06 16:20:11 -0700177CompiledMethod::CompiledMethod(CompilerDriver* driver, InstructionSet instruction_set,
Andreas Gampe62746d82014-12-08 16:59:43 -0800178 const std::string& code, const ArrayRef<const uint8_t>& gc_map,
Mathieu Chartier193bad92013-08-29 18:46:00 -0700179 const std::string& symbol)
Ian Rogers72d32622014-05-06 16:20:11 -0700180 : CompiledCode(driver, instruction_set, code, symbol),
Mathieu Chartier193bad92013-08-29 18:46:00 -0700181 frame_size_in_bytes_(kStackAlignment), core_spill_mask_(0),
Andreas Gampe62746d82014-12-08 16:59:43 -0800182 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>());
Mathieu Chartier193bad92013-08-29 18:46:00 -0700186}
187
Ian Rogers72d32622014-05-06 16:20:11 -0700188CompiledMethod::CompiledMethod(CompilerDriver* driver, InstructionSet instruction_set,
Mathieu Chartier193bad92013-08-29 18:46:00 -0700189 const std::string& code, const std::string& symbol)
Ian Rogers72d32622014-05-06 16:20:11 -0700190 : CompiledCode(driver, instruction_set, code, symbol),
Mathieu Chartier193bad92013-08-29 18:46:00 -0700191 frame_size_in_bytes_(kStackAlignment), core_spill_mask_(0),
Andreas Gampe62746d82014-12-08 16:59:43 -0800192 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
198CompiledMethod* 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
215CompiledMethod* 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
228void CompiledMethod::ReleaseSwapAllocatedCompiledMethod(CompilerDriver* driver, CompiledMethod* m) {
229 SwapAllocator<CompiledMethod> alloc(driver->GetSwapSpaceAllocator());
230 alloc.destroy(m);
231 alloc.deallocate(m, 1);
Mathieu Chartier193bad92013-08-29 18:46:00 -0700232}
Dave Allisond6ed6422014-04-09 23:36:15 +0000233
Mathieu Chartier193bad92013-08-29 18:46:00 -0700234} // namespace art