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