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
CompiledCode(CompilerDriver * compiler_driver,InstructionSet instruction_set,const ArrayRef<const uint8_t> & quick_code)22 CompiledCode::CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set,
23 const ArrayRef<const 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
CompiledCode(CompilerDriver * compiler_driver,InstructionSet instruction_set,const std::string & elf_object,const std::string & symbol)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_(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) {
36 CHECK_NE(elf_object.size(), 0U);
37 CHECK_NE(symbol.size(), 0U);
38 // 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.
42 }
43
SetCode(const ArrayRef<const uint8_t> * quick_code,const ArrayRef<const uint8_t> * portable_code)44 void CompiledCode::SetCode(const ArrayRef<const uint8_t>* quick_code,
45 const ArrayRef<const uint8_t>* portable_code) {
46 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
operator ==(const CompiledCode & rhs) const56 bool 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);
76 }
77
AlignCode(uint32_t offset) const78 uint32_t CompiledCode::AlignCode(uint32_t offset) const {
79 return AlignCode(offset, instruction_set_);
80 }
81
AlignCode(uint32_t offset,InstructionSet instruction_set)82 uint32_t CompiledCode::AlignCode(uint32_t offset, InstructionSet instruction_set) {
83 return RoundUp(offset, GetInstructionSetAlignment(instruction_set));
84 }
85
CodeDelta() const86 size_t CompiledCode::CodeDelta() const {
87 return CodeDelta(instruction_set_);
88 }
89
CodeDelta(InstructionSet instruction_set)90 size_t CompiledCode::CodeDelta(InstructionSet instruction_set) {
91 switch (instruction_set) {
92 case kArm:
93 case kArm64:
94 case kMips:
95 case kX86:
96 case kX86_64:
97 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:
103 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
104 return 0;
105 }
106 }
107
CodePointer(const void * code_pointer,InstructionSet instruction_set)108 const void* CompiledCode::CodePointer(const void* code_pointer,
109 InstructionSet instruction_set) {
110 switch (instruction_set) {
111 case kArm:
112 case kArm64:
113 case kMips:
114 case kX86:
115 case kX86_64:
116 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
GetSymbol() const129 const std::string& CompiledCode::GetSymbol() const {
130 CHECK_NE(0U, symbol_.size());
131 return symbol_;
132 }
133
GetOatdataOffsetsToCompliledCodeOffset() const134 const 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
AddOatdataOffsetToCompliledCodeOffset(uint32_t offset)139 void CompiledCode::AddOatdataOffsetToCompliledCodeOffset(uint32_t offset) {
140 oatdata_offsets_to_compiled_code_offset_.push_back(offset);
141 }
142
CompiledMethod(CompilerDriver * driver,InstructionSet instruction_set,const ArrayRef<const uint8_t> & quick_code,const size_t frame_size_in_bytes,const uint32_t core_spill_mask,const uint32_t fp_spill_mask,const ArrayRef<const uint8_t> & mapping_table,const ArrayRef<const uint8_t> & vmap_table,const ArrayRef<const uint8_t> & native_gc_map,const ArrayRef<const uint8_t> & cfi_info)143 CompiledMethod::CompiledMethod(CompilerDriver* driver,
144 InstructionSet instruction_set,
145 const ArrayRef<const uint8_t>& quick_code,
146 const size_t frame_size_in_bytes,
147 const uint32_t core_spill_mask,
148 const uint32_t fp_spill_mask,
149 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)
153 : CompiledCode(driver, instruction_set, quick_code), frame_size_in_bytes_(frame_size_in_bytes),
154 core_spill_mask_(core_spill_mask), fp_spill_mask_(fp_spill_mask),
155 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)) {
159 }
160
CompiledMethod(CompilerDriver * driver,InstructionSet instruction_set,const ArrayRef<const uint8_t> & code,const size_t frame_size_in_bytes,const uint32_t core_spill_mask,const uint32_t fp_spill_mask)161 CompiledMethod::CompiledMethod(CompilerDriver* driver,
162 InstructionSet instruction_set,
163 const ArrayRef<const uint8_t>& code,
164 const size_t frame_size_in_bytes,
165 const uint32_t core_spill_mask,
166 const uint32_t fp_spill_mask)
167 : CompiledCode(driver, instruction_set, code),
168 frame_size_in_bytes_(frame_size_in_bytes),
169 core_spill_mask_(core_spill_mask), fp_spill_mask_(fp_spill_mask),
170 cfi_info_(nullptr) {
171 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>());
174 }
175
176 // Constructs a CompiledMethod for the Portable compiler.
CompiledMethod(CompilerDriver * driver,InstructionSet instruction_set,const std::string & code,const ArrayRef<const uint8_t> & gc_map,const std::string & symbol)177 CompiledMethod::CompiledMethod(CompilerDriver* driver, InstructionSet instruction_set,
178 const std::string& code, const ArrayRef<const uint8_t>& gc_map,
179 const std::string& symbol)
180 : CompiledCode(driver, instruction_set, code, symbol),
181 frame_size_in_bytes_(kStackAlignment), core_spill_mask_(0),
182 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>());
186 }
187
CompiledMethod(CompilerDriver * driver,InstructionSet instruction_set,const std::string & code,const std::string & symbol)188 CompiledMethod::CompiledMethod(CompilerDriver* driver, InstructionSet instruction_set,
189 const std::string& code, 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), 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
SwapAllocCompiledMethod(CompilerDriver * driver,InstructionSet instruction_set,const ArrayRef<const uint8_t> & quick_code,const size_t frame_size_in_bytes,const uint32_t core_spill_mask,const uint32_t fp_spill_mask,const ArrayRef<const uint8_t> & mapping_table,const ArrayRef<const uint8_t> & vmap_table,const ArrayRef<const uint8_t> & native_gc_map,const ArrayRef<const uint8_t> & cfi_info)198 CompiledMethod* 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
SwapAllocCompiledMethod(CompilerDriver * driver,InstructionSet instruction_set,const ArrayRef<const uint8_t> & quick_code,const size_t frame_size_in_bytes,const uint32_t core_spill_mask,const uint32_t fp_spill_mask)215 CompiledMethod* 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
ReleaseSwapAllocatedCompiledMethod(CompilerDriver * driver,CompiledMethod * m)228 void CompiledMethod::ReleaseSwapAllocatedCompiledMethod(CompilerDriver* driver, CompiledMethod* m) {
229 SwapAllocator<CompiledMethod> alloc(driver->GetSwapSpaceAllocator());
230 alloc.destroy(m);
231 alloc.deallocate(m, 1);
232 }
233
234 } // namespace art
235