blob: 1849e7ef64cb6e22f131330ef0a01972a7e7e40e [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,
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080023 const ArrayRef<const uint8_t>& quick_code, bool owns_code_array)
Ian Rogersef7d42f2014-01-06 12:55:46 -080024 : compiler_driver_(compiler_driver), instruction_set_(instruction_set),
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080025 owns_code_array_(owns_code_array), quick_code_(nullptr) {
Elliott Hughes956af0f2014-12-11 14:34:28 -080026 SetCode(&quick_code);
Mathieu Chartier193bad92013-08-29 18:46:00 -070027}
28
Andreas Gampee21dc3d2014-12-08 16:59:43 -080029void CompiledCode::SetCode(const ArrayRef<const uint8_t>* quick_code) {
Ian Rogersef7d42f2014-01-06 12:55:46 -080030 if (quick_code != nullptr) {
31 CHECK(!quick_code->empty());
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080032 if (owns_code_array_) {
33 // If we are supposed to own the code, don't deduplicate it.
34 CHECK(quick_code_ == nullptr);
35 quick_code_ = new SwapVector<uint8_t>(quick_code->begin(), quick_code->end(),
36 compiler_driver_->GetSwapSpaceAllocator());
37 } else {
38 quick_code_ = compiler_driver_->DeduplicateCode(*quick_code);
39 }
40 }
41}
42
43CompiledCode::~CompiledCode() {
44 if (owns_code_array_) {
45 delete quick_code_;
Ian Rogersef7d42f2014-01-06 12:55:46 -080046 }
47}
48
49bool CompiledCode::operator==(const CompiledCode& rhs) const {
50 if (quick_code_ != nullptr) {
51 if (rhs.quick_code_ == nullptr) {
52 return false;
53 } else if (quick_code_->size() != rhs.quick_code_->size()) {
54 return false;
55 } else {
56 return std::equal(quick_code_->begin(), quick_code_->end(), rhs.quick_code_->begin());
57 }
Ian Rogersef7d42f2014-01-06 12:55:46 -080058 }
Elliott Hughes956af0f2014-12-11 14:34:28 -080059 return (rhs.quick_code_ == nullptr);
Mathieu Chartier193bad92013-08-29 18:46:00 -070060}
61
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080062size_t CompiledCode::AlignCode(size_t offset) const {
Mathieu Chartier193bad92013-08-29 18:46:00 -070063 return AlignCode(offset, instruction_set_);
64}
65
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080066size_t CompiledCode::AlignCode(size_t offset, InstructionSet instruction_set) {
Andreas Gampeaf13ad92014-04-11 12:07:48 -070067 return RoundUp(offset, GetInstructionSetAlignment(instruction_set));
Mathieu Chartier193bad92013-08-29 18:46:00 -070068}
69
70size_t CompiledCode::CodeDelta() const {
Dave Allison50abf0a2014-06-23 13:19:59 -070071 return CodeDelta(instruction_set_);
72}
73
74size_t CompiledCode::CodeDelta(InstructionSet instruction_set) {
75 switch (instruction_set) {
Mathieu Chartier193bad92013-08-29 18:46:00 -070076 case kArm:
Stuart Monteithb95a5342014-03-12 13:32:32 +000077 case kArm64:
Mathieu Chartier193bad92013-08-29 18:46:00 -070078 case kMips:
Andreas Gampe57b34292015-01-14 15:45:59 -080079 case kMips64:
Mathieu Chartier193bad92013-08-29 18:46:00 -070080 case kX86:
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070081 case kX86_64:
Mathieu Chartier193bad92013-08-29 18:46:00 -070082 return 0;
83 case kThumb2: {
84 // +1 to set the low-order bit so a BLX will switch to Thumb mode
85 return 1;
86 }
87 default:
Dave Allison50abf0a2014-06-23 13:19:59 -070088 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
Mathieu Chartier193bad92013-08-29 18:46:00 -070089 return 0;
90 }
91}
92
93const void* CompiledCode::CodePointer(const void* code_pointer,
94 InstructionSet instruction_set) {
95 switch (instruction_set) {
96 case kArm:
Stuart Monteithb95a5342014-03-12 13:32:32 +000097 case kArm64:
Mathieu Chartier193bad92013-08-29 18:46:00 -070098 case kMips:
Andreas Gampe57b34292015-01-14 15:45:59 -080099 case kMips64:
Mathieu Chartier193bad92013-08-29 18:46:00 -0700100 case kX86:
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700101 case kX86_64:
Mathieu Chartier193bad92013-08-29 18:46:00 -0700102 return code_pointer;
103 case kThumb2: {
104 uintptr_t address = reinterpret_cast<uintptr_t>(code_pointer);
105 // Set the low-order bit so a BLX will switch to Thumb mode
106 address |= 0x1;
107 return reinterpret_cast<const void*>(address);
108 }
109 default:
110 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
111 return NULL;
112 }
113}
114
Mathieu Chartier193bad92013-08-29 18:46:00 -0700115const std::vector<uint32_t>& CompiledCode::GetOatdataOffsetsToCompliledCodeOffset() const {
Elliott Hughes956af0f2014-12-11 14:34:28 -0800116 CHECK_NE(0U, oatdata_offsets_to_compiled_code_offset_.size());
Mathieu Chartier193bad92013-08-29 18:46:00 -0700117 return oatdata_offsets_to_compiled_code_offset_;
118}
119
120void CompiledCode::AddOatdataOffsetToCompliledCodeOffset(uint32_t offset) {
121 oatdata_offsets_to_compiled_code_offset_.push_back(offset);
122}
Mathieu Chartier193bad92013-08-29 18:46:00 -0700123
Ian Rogers72d32622014-05-06 16:20:11 -0700124CompiledMethod::CompiledMethod(CompilerDriver* driver,
Mathieu Chartier193bad92013-08-29 18:46:00 -0700125 InstructionSet instruction_set,
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800126 const ArrayRef<const uint8_t>& quick_code,
Mathieu Chartier193bad92013-08-29 18:46:00 -0700127 const size_t frame_size_in_bytes,
128 const uint32_t core_spill_mask,
129 const uint32_t fp_spill_mask,
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800130 DefaultSrcMap* src_mapping_table,
131 const ArrayRef<const uint8_t>& mapping_table,
132 const ArrayRef<const uint8_t>& vmap_table,
133 const ArrayRef<const uint8_t>& native_gc_map,
134 const ArrayRef<const uint8_t>& cfi_info,
Vladimir Markof4da6752014-08-01 19:04:18 +0100135 const ArrayRef<LinkerPatch>& patches)
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800136 : CompiledCode(driver, instruction_set, quick_code, !driver->DedupeEnabled()),
137 owns_arrays_(!driver->DedupeEnabled()),
138 frame_size_in_bytes_(frame_size_in_bytes), core_spill_mask_(core_spill_mask),
139 fp_spill_mask_(fp_spill_mask),
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800140 patches_(patches.begin(), patches.end(), driver->GetSwapSpaceAllocator()) {
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800141 if (owns_arrays_) {
142 if (src_mapping_table == nullptr) {
143 src_mapping_table_ = new SwapSrcMap(driver->GetSwapSpaceAllocator());
144 } else {
145 src_mapping_table->Arrange();
146 src_mapping_table_ = new SwapSrcMap(src_mapping_table->begin(), src_mapping_table->end(),
147 driver->GetSwapSpaceAllocator());
148 }
149 mapping_table_ = mapping_table.empty() ?
150 nullptr : new SwapVector<uint8_t>(mapping_table.begin(), mapping_table.end(),
151 driver->GetSwapSpaceAllocator());
152 vmap_table_ = new SwapVector<uint8_t>(vmap_table.begin(), vmap_table.end(),
153 driver->GetSwapSpaceAllocator());
154 gc_map_ = native_gc_map.empty() ? nullptr :
155 new SwapVector<uint8_t>(native_gc_map.begin(), native_gc_map.end(),
156 driver->GetSwapSpaceAllocator());
157 cfi_info_ = cfi_info.empty() ? nullptr :
158 new SwapVector<uint8_t>(cfi_info.begin(), cfi_info.end(), driver->GetSwapSpaceAllocator());
159 } else {
160 src_mapping_table_ = src_mapping_table == nullptr ?
161 driver->DeduplicateSrcMappingTable(ArrayRef<SrcMapElem>()) :
162 driver->DeduplicateSrcMappingTable(ArrayRef<SrcMapElem>(src_mapping_table->Arrange()));
163 mapping_table_ = mapping_table.empty() ?
164 nullptr : driver->DeduplicateMappingTable(mapping_table);
165 vmap_table_ = driver->DeduplicateVMapTable(vmap_table);
166 gc_map_ = native_gc_map.empty() ? nullptr : driver->DeduplicateGCMap(native_gc_map);
167 cfi_info_ = cfi_info.empty() ? nullptr : driver->DeduplicateCFIInfo(cfi_info);
168 }
Mathieu Chartier193bad92013-08-29 18:46:00 -0700169}
170
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800171CompiledMethod* CompiledMethod::SwapAllocCompiledMethod(
172 CompilerDriver* driver,
173 InstructionSet instruction_set,
174 const ArrayRef<const uint8_t>& quick_code,
175 const size_t frame_size_in_bytes,
176 const uint32_t core_spill_mask,
177 const uint32_t fp_spill_mask,
178 DefaultSrcMap* src_mapping_table,
179 const ArrayRef<const uint8_t>& mapping_table,
180 const ArrayRef<const uint8_t>& vmap_table,
181 const ArrayRef<const uint8_t>& native_gc_map,
182 const ArrayRef<const uint8_t>& cfi_info,
183 const ArrayRef<LinkerPatch>& patches) {
184 SwapAllocator<CompiledMethod> alloc(driver->GetSwapSpaceAllocator());
185 CompiledMethod* ret = alloc.allocate(1);
186 alloc.construct(ret, driver, instruction_set, quick_code, frame_size_in_bytes, core_spill_mask,
187 fp_spill_mask, src_mapping_table, mapping_table, vmap_table, native_gc_map,
188 cfi_info, patches);
189 return ret;
Nicolas Geoffray39468442014-09-02 15:17:15 +0100190}
191
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800192CompiledMethod* CompiledMethod::SwapAllocCompiledMethodStackMap(
193 CompilerDriver* driver,
194 InstructionSet instruction_set,
195 const ArrayRef<const uint8_t>& quick_code,
196 const size_t frame_size_in_bytes,
197 const uint32_t core_spill_mask,
198 const uint32_t fp_spill_mask,
199 const ArrayRef<const uint8_t>& stack_map) {
200 SwapAllocator<CompiledMethod> alloc(driver->GetSwapSpaceAllocator());
201 CompiledMethod* ret = alloc.allocate(1);
202 alloc.construct(ret, driver, instruction_set, quick_code, frame_size_in_bytes, core_spill_mask,
203 fp_spill_mask, nullptr, ArrayRef<const uint8_t>(), stack_map,
204 ArrayRef<const uint8_t>(), ArrayRef<const uint8_t>(), ArrayRef<LinkerPatch>());
205 return ret;
206}
207
208CompiledMethod* CompiledMethod::SwapAllocCompiledMethodCFI(
209 CompilerDriver* driver,
210 InstructionSet instruction_set,
211 const ArrayRef<const uint8_t>& quick_code,
212 const size_t frame_size_in_bytes,
213 const uint32_t core_spill_mask,
214 const uint32_t fp_spill_mask,
215 const ArrayRef<const uint8_t>& cfi_info) {
216 SwapAllocator<CompiledMethod> alloc(driver->GetSwapSpaceAllocator());
217 CompiledMethod* ret = alloc.allocate(1);
218 alloc.construct(ret, driver, instruction_set, quick_code, frame_size_in_bytes, core_spill_mask,
219 fp_spill_mask, nullptr, ArrayRef<const uint8_t>(),
220 ArrayRef<const uint8_t>(), ArrayRef<const uint8_t>(),
221 cfi_info, ArrayRef<LinkerPatch>());
222 return ret;
223}
224
225
226void CompiledMethod::ReleaseSwapAllocatedCompiledMethod(CompilerDriver* driver, CompiledMethod* m) {
227 SwapAllocator<CompiledMethod> alloc(driver->GetSwapSpaceAllocator());
228 alloc.destroy(m);
229 alloc.deallocate(m, 1);
Mathieu Chartier193bad92013-08-29 18:46:00 -0700230}
231
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800232CompiledMethod::~CompiledMethod() {
233 if (owns_arrays_) {
234 delete src_mapping_table_;
235 delete mapping_table_;
236 delete vmap_table_;
237 delete gc_map_;
238 delete cfi_info_;
239 }
240}
241
Mathieu Chartier193bad92013-08-29 18:46:00 -0700242} // namespace art