blob: 6013507ac49e81130e2e4ad462fa4e9b75ad37de [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
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 */
Brian Carlstrom3320cf42011-10-04 14:58:28 -070016
Mathieu Chartier193bad92013-08-29 18:46:00 -070017#ifndef ART_COMPILER_COMPILED_METHOD_H_
18#define ART_COMPILER_COMPILED_METHOD_H_
Brian Carlstrom3320cf42011-10-04 14:58:28 -070019
Ian Rogers700a4022014-05-19 16:49:03 -070020#include <memory>
Brian Carlstrom265091e2013-01-30 14:08:26 -080021#include <string>
Brian Carlstrom3320cf42011-10-04 14:58:28 -070022#include <vector>
23
Ian Rogersd582fa42014-11-05 23:46:43 -080024#include "arch/instruction_set.h"
Vladimir Markof4da6752014-08-01 19:04:18 +010025#include "method_reference.h"
Brian Carlstrom3320cf42011-10-04 14:58:28 -070026#include "utils.h"
Vladimir Markof4da6752014-08-01 19:04:18 +010027#include "utils/array_ref.h"
Andreas Gampee21dc3d2014-12-08 16:59:43 -080028#include "utils/swap_space.h"
Brian Carlstrom3320cf42011-10-04 14:58:28 -070029
Shih-wei Liaod1fec812012-02-13 09:51:10 -080030namespace llvm {
31 class Function;
Ian Rogersa1827042013-04-18 16:36:43 -070032} // namespace llvm
Shih-wei Liaod1fec812012-02-13 09:51:10 -080033
Brian Carlstrom3320cf42011-10-04 14:58:28 -070034namespace art {
35
Mathieu Chartier193bad92013-08-29 18:46:00 -070036class CompilerDriver;
37
Logan Chien598c5132012-04-28 22:00:44 +080038class CompiledCode {
39 public:
Brian Carlstrom265091e2013-01-30 14:08:26 -080040 // For Quick to supply an code blob
Mathieu Chartier193bad92013-08-29 18:46:00 -070041 CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set,
Andreas Gampee21dc3d2014-12-08 16:59:43 -080042 const ArrayRef<const uint8_t>& quick_code);
Logan Chien598c5132012-04-28 22:00:44 +080043
Logan Chien598c5132012-04-28 22:00:44 +080044 InstructionSet GetInstructionSet() const {
45 return instruction_set_;
46 }
47
Andreas Gampee21dc3d2014-12-08 16:59:43 -080048 const SwapVector<uint8_t>* GetQuickCode() const {
Ian Rogersef7d42f2014-01-06 12:55:46 -080049 return quick_code_;
Logan Chien598c5132012-04-28 22:00:44 +080050 }
51
Andreas Gampee21dc3d2014-12-08 16:59:43 -080052 void SetCode(const ArrayRef<const uint8_t>* quick_code);
Ian Rogersef7d42f2014-01-06 12:55:46 -080053
54 bool operator==(const CompiledCode& rhs) const;
55
Logan Chien598c5132012-04-28 22:00:44 +080056 // To align an offset from a page-aligned value to make it suitable
57 // for code storage. For example on ARM, to ensure that PC relative
58 // valu computations work out as expected.
59 uint32_t AlignCode(uint32_t offset) const;
60 static uint32_t AlignCode(uint32_t offset, InstructionSet instruction_set);
61
62 // returns the difference between the code address and a usable PC.
63 // mainly to cope with kThumb2 where the lower bit must be set.
64 size_t CodeDelta() const;
Dave Allison50abf0a2014-06-23 13:19:59 -070065 static size_t CodeDelta(InstructionSet instruction_set);
Logan Chien598c5132012-04-28 22:00:44 +080066
67 // Returns a pointer suitable for invoking the code at the argument
68 // code_pointer address. Mainly to cope with kThumb2 where the
69 // lower bit must be set to indicate Thumb mode.
70 static const void* CodePointer(const void* code_pointer,
71 InstructionSet instruction_set);
72
Brian Carlstrom265091e2013-01-30 14:08:26 -080073 const std::vector<uint32_t>& GetOatdataOffsetsToCompliledCodeOffset() const;
74 void AddOatdataOffsetToCompliledCodeOffset(uint32_t offset);
Brian Carlstrom265091e2013-01-30 14:08:26 -080075
Logan Chien598c5132012-04-28 22:00:44 +080076 private:
Ian Rogersef7d42f2014-01-06 12:55:46 -080077 CompilerDriver* const compiler_driver_;
Mathieu Chartier193bad92013-08-29 18:46:00 -070078
Logan Chien598c5132012-04-28 22:00:44 +080079 const InstructionSet instruction_set_;
Brian Carlstrom8227cc12013-03-06 14:26:48 -080080
Ian Rogersef7d42f2014-01-06 12:55:46 -080081 // Used to store the PIC code for Quick.
Andreas Gampee21dc3d2014-12-08 16:59:43 -080082 SwapVector<uint8_t>* quick_code_;
Brian Carlstrom265091e2013-01-30 14:08:26 -080083
Brian Carlstrom265091e2013-01-30 14:08:26 -080084 // There are offsets from the oatdata symbol to where the offset to
85 // the compiled method will be found. These are computed by the
86 // OatWriter and then used by the ElfWriter to add relocations so
87 // that MCLinker can update the values to the location in the linked .so.
88 std::vector<uint32_t> oatdata_offsets_to_compiled_code_offset_;
Logan Chien598c5132012-04-28 22:00:44 +080089};
90
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070091class SrcMapElem {
92 public:
93 uint32_t from_;
94 int32_t to_;
95
Yevgeny Rouban33ac8192014-08-19 18:39:57 +070096 explicit operator int64_t() const {
97 return (static_cast<int64_t>(to_) << 32) | from_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070098 }
99
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700100 bool operator<(const SrcMapElem& sme) const {
101 return int64_t(*this) < int64_t(sme);
102 }
103
104 bool operator==(const SrcMapElem& sme) const {
105 return int64_t(*this) == int64_t(sme);
106 }
107
108 explicit operator uint8_t() const {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700109 return static_cast<uint8_t>(from_ + to_);
110 }
111};
112
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800113template <class Allocator>
114class SrcMap FINAL : public std::vector<SrcMapElem, Allocator> {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700115 public:
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800116 using std::vector<SrcMapElem, Allocator>::begin;
117 using typename std::vector<SrcMapElem, Allocator>::const_iterator;
118 using std::vector<SrcMapElem, Allocator>::empty;
119 using std::vector<SrcMapElem, Allocator>::end;
120 using std::vector<SrcMapElem, Allocator>::resize;
121 using std::vector<SrcMapElem, Allocator>::shrink_to_fit;
122 using std::vector<SrcMapElem, Allocator>::size;
123
124 explicit SrcMap() {}
125
126 template <class InputIt>
127 SrcMap(InputIt first, InputIt last, const Allocator& alloc)
128 : std::vector<SrcMapElem, Allocator>(first, last, alloc) {}
129
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700130 void SortByFrom() {
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700131 std::sort(begin(), end(), [] (const SrcMapElem& lhs, const SrcMapElem& rhs) -> bool {
132 return lhs.from_ < rhs.from_;
133 });
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700134 }
135
136 const_iterator FindByTo(int32_t to) const {
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700137 return std::lower_bound(begin(), end(), SrcMapElem({0, to}));
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700138 }
139
140 SrcMap& Arrange() {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700141 if (!empty()) {
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700142 std::sort(begin(), end());
143 resize(std::unique(begin(), end()) - begin());
144 shrink_to_fit();
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700145 }
146 return *this;
147 }
148
149 void DeltaFormat(const SrcMapElem& start, uint32_t highest_pc) {
150 // Convert from abs values to deltas.
151 if (!empty()) {
152 SortByFrom();
153
154 // TODO: one PC can be mapped to several Java src lines.
155 // do we want such a one-to-many correspondence?
156
157 // get rid of the highest values
158 size_t i = size() - 1;
159 for (; i > 0 ; i--) {
Yevgeny Rouban1127b122014-09-16 11:29:26 +0700160 if ((*this)[i].from_ < highest_pc) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700161 break;
162 }
163 }
164 this->resize(i + 1);
165
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800166 for (i = size(); --i >= 1; ) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700167 (*this)[i].from_ -= (*this)[i-1].from_;
168 (*this)[i].to_ -= (*this)[i-1].to_;
169 }
170 DCHECK((*this)[0].from_ >= start.from_);
171 (*this)[0].from_ -= start.from_;
172 (*this)[0].to_ -= start.to_;
173 }
174 }
175};
176
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800177using DefaultSrcMap = SrcMap<std::allocator<SrcMapElem>>;
178using SwapSrcMap = SrcMap<SwapAllocator<SrcMapElem>>;
179
180
Vladimir Markof4da6752014-08-01 19:04:18 +0100181enum LinkerPatchType {
182 kLinkerPatchMethod,
183 kLinkerPatchCall,
184 kLinkerPatchCallRelative, // NOTE: Actual patching is instruction_set-dependent.
185 kLinkerPatchType,
186};
187
188class LinkerPatch {
189 public:
190 static LinkerPatch MethodPatch(size_t literal_offset,
191 const DexFile* target_dex_file,
192 uint32_t target_method_idx) {
193 return LinkerPatch(literal_offset, kLinkerPatchMethod,
194 target_method_idx, target_dex_file);
195 }
196
197 static LinkerPatch CodePatch(size_t literal_offset,
198 const DexFile* target_dex_file,
199 uint32_t target_method_idx) {
200 return LinkerPatch(literal_offset, kLinkerPatchCall,
201 target_method_idx, target_dex_file);
202 }
203
204 static LinkerPatch RelativeCodePatch(size_t literal_offset,
205 const DexFile* target_dex_file,
206 uint32_t target_method_idx) {
207 return LinkerPatch(literal_offset, kLinkerPatchCallRelative,
208 target_method_idx, target_dex_file);
209 }
210
211 static LinkerPatch TypePatch(size_t literal_offset,
212 const DexFile* target_dex_file,
213 uint32_t target_type_idx) {
214 return LinkerPatch(literal_offset, kLinkerPatchType, target_type_idx, target_dex_file);
215 }
216
217 LinkerPatch(const LinkerPatch& other) = default;
218 LinkerPatch& operator=(const LinkerPatch& other) = default;
219
220 size_t LiteralOffset() const {
221 return literal_offset_;
222 }
223
224 LinkerPatchType Type() const {
225 return patch_type_;
226 }
227
228 MethodReference TargetMethod() const {
229 DCHECK(patch_type_ == kLinkerPatchMethod ||
230 patch_type_ == kLinkerPatchCall || patch_type_ == kLinkerPatchCallRelative);
231 return MethodReference(target_dex_file_, target_idx_);
232 }
233
234 const DexFile* TargetTypeDexFile() const {
235 DCHECK(patch_type_ == kLinkerPatchType);
236 return target_dex_file_;
237 }
238
239 uint32_t TargetTypeIndex() const {
240 DCHECK(patch_type_ == kLinkerPatchType);
241 return target_idx_;
242 }
243
244 private:
245 LinkerPatch(size_t literal_offset, LinkerPatchType patch_type,
246 uint32_t target_idx, const DexFile* target_dex_file)
247 : literal_offset_(literal_offset),
248 patch_type_(patch_type),
249 target_idx_(target_idx),
250 target_dex_file_(target_dex_file) {
251 }
252
253 size_t literal_offset_;
254 LinkerPatchType patch_type_;
255 uint32_t target_idx_; // Method index (Call/Method patches) or type index (Type patches).
256 const DexFile* target_dex_file_;
257
258 friend bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs);
259 friend bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs);
260};
261
262inline bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs) {
263 return lhs.literal_offset_ == rhs.literal_offset_ &&
264 lhs.patch_type_ == rhs.patch_type_ &&
265 lhs.target_idx_ == rhs.target_idx_ &&
266 lhs.target_dex_file_ == rhs.target_dex_file_;
267}
268
269inline bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs) {
270 return (lhs.literal_offset_ != rhs.literal_offset_) ? lhs.literal_offset_ < rhs.literal_offset_
271 : (lhs.patch_type_ != rhs.patch_type_) ? lhs.patch_type_ < rhs.patch_type_
272 : (lhs.target_idx_ != rhs.target_idx_) ? lhs.target_idx_ < rhs.target_idx_
273 : lhs.target_dex_file_ < rhs.target_dex_file_;
274}
275
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700276class CompiledMethod FINAL : public CompiledCode {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700277 public:
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800278 // Constructs a CompiledMethod.
279 // Note: Consider using the static allocation methods below that will allocate the CompiledMethod
280 // in the swap space.
Ian Rogers72d32622014-05-06 16:20:11 -0700281 CompiledMethod(CompilerDriver* driver,
Mathieu Chartier193bad92013-08-29 18:46:00 -0700282 InstructionSet instruction_set,
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800283 const ArrayRef<const uint8_t>& quick_code,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700284 const size_t frame_size_in_bytes,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700285 const uint32_t core_spill_mask,
286 const uint32_t fp_spill_mask,
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800287 DefaultSrcMap* src_mapping_table,
288 const ArrayRef<const uint8_t>& mapping_table,
289 const ArrayRef<const uint8_t>& vmap_table,
290 const ArrayRef<const uint8_t>& native_gc_map,
291 const ArrayRef<const uint8_t>& cfi_info,
Vladimir Markof4da6752014-08-01 19:04:18 +0100292 const ArrayRef<LinkerPatch>& patches = ArrayRef<LinkerPatch>());
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700293
Ian Rogers0c7abda2012-09-19 13:33:42 -0700294 ~CompiledMethod() {}
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700295
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800296 static CompiledMethod* SwapAllocCompiledMethod(
297 CompilerDriver* driver,
298 InstructionSet instruction_set,
299 const ArrayRef<const uint8_t>& quick_code,
300 const size_t frame_size_in_bytes,
301 const uint32_t core_spill_mask,
302 const uint32_t fp_spill_mask,
303 DefaultSrcMap* src_mapping_table,
304 const ArrayRef<const uint8_t>& mapping_table,
305 const ArrayRef<const uint8_t>& vmap_table,
306 const ArrayRef<const uint8_t>& native_gc_map,
307 const ArrayRef<const uint8_t>& cfi_info,
308 const ArrayRef<LinkerPatch>& patches = ArrayRef<LinkerPatch>());
309
310 static CompiledMethod* SwapAllocCompiledMethodStackMap(
311 CompilerDriver* driver,
312 InstructionSet instruction_set,
313 const ArrayRef<const uint8_t>& quick_code,
314 const size_t frame_size_in_bytes,
315 const uint32_t core_spill_mask,
316 const uint32_t fp_spill_mask,
317 const ArrayRef<const uint8_t>& stack_map);
318
319 static CompiledMethod* SwapAllocCompiledMethodCFI(CompilerDriver* driver,
320 InstructionSet instruction_set,
321 const ArrayRef<const uint8_t>& quick_code,
322 const size_t frame_size_in_bytes,
323 const uint32_t core_spill_mask,
324 const uint32_t fp_spill_mask,
325 const ArrayRef<const uint8_t>& cfi_info);
326
327 static void ReleaseSwapAllocatedCompiledMethod(CompilerDriver* driver, CompiledMethod* m);
328
Ian Rogers0c7abda2012-09-19 13:33:42 -0700329 size_t GetFrameSizeInBytes() const {
330 return frame_size_in_bytes_;
Logan Chien110bcba2012-04-16 19:11:28 +0800331 }
Ian Rogers0c7abda2012-09-19 13:33:42 -0700332
333 uint32_t GetCoreSpillMask() const {
334 return core_spill_mask_;
335 }
336
337 uint32_t GetFpSpillMask() const {
338 return fp_spill_mask_;
339 }
340
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800341 const SwapSrcMap& GetSrcMappingTable() const {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700342 DCHECK(src_mapping_table_ != nullptr);
343 return *src_mapping_table_;
344 }
345
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800346 SwapVector<uint8_t> const* GetMappingTable() const {
Nicolas Geoffray376b2bb2014-12-09 14:26:32 +0000347 return mapping_table_;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700348 }
349
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800350 const SwapVector<uint8_t>& GetVmapTable() const {
Mathieu Chartier193bad92013-08-29 18:46:00 -0700351 DCHECK(vmap_table_ != nullptr);
352 return *vmap_table_;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700353 }
354
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800355 SwapVector<uint8_t> const* GetGcMap() const {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100356 return gc_map_;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700357 }
Logan Chien110bcba2012-04-16 19:11:28 +0800358
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800359 const SwapVector<uint8_t>* GetCFIInfo() const {
Mark Mendellae9fd932014-02-10 16:14:35 -0800360 return cfi_info_;
361 }
362
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800363 const SwapVector<LinkerPatch>& GetPatches() const {
Vladimir Markof4da6752014-08-01 19:04:18 +0100364 return patches_;
365 }
366
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700367 private:
Ian Rogersa1827042013-04-18 16:36:43 -0700368 // For quick code, the size of the activation used by the code.
Ian Rogers0c7abda2012-09-19 13:33:42 -0700369 const size_t frame_size_in_bytes_;
Ian Rogersa1827042013-04-18 16:36:43 -0700370 // For quick code, a bit mask describing spilled GPR callee-save registers.
Ian Rogers169c9a72011-11-13 20:13:17 -0800371 const uint32_t core_spill_mask_;
Ian Rogersa1827042013-04-18 16:36:43 -0700372 // For quick code, a bit mask describing spilled FPR callee-save registers.
Ian Rogers169c9a72011-11-13 20:13:17 -0800373 const uint32_t fp_spill_mask_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700374 // For quick code, a set of pairs (PC, Line) mapping from native PC offset to Java line
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800375 SwapSrcMap* src_mapping_table_;
Ian Rogers96faf5b2013-08-09 22:05:32 -0700376 // For quick code, a uleb128 encoded map from native PC offset to dex PC aswell as dex PC to
377 // native PC offset. Size prefixed.
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800378 SwapVector<uint8_t>* mapping_table_;
Ian Rogers96faf5b2013-08-09 22:05:32 -0700379 // For quick code, a uleb128 encoded map from GPR/FPR register to dex register. Size prefixed.
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800380 SwapVector<uint8_t>* vmap_table_;
Ian Rogersa1827042013-04-18 16:36:43 -0700381 // For quick code, a map keyed by native PC indices to bitmaps describing what dalvik registers
Elliott Hughes956af0f2014-12-11 14:34:28 -0800382 // are live.
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800383 SwapVector<uint8_t>* gc_map_;
Mark Mendellae9fd932014-02-10 16:14:35 -0800384 // For quick code, a FDE entry for the debug_frame section.
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800385 SwapVector<uint8_t>* cfi_info_;
Vladimir Markof4da6752014-08-01 19:04:18 +0100386 // For quick code, linker patches needed by the method.
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800387 SwapVector<LinkerPatch> patches_;
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700388};
389
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700390} // namespace art
391
Mathieu Chartier193bad92013-08-29 18:46:00 -0700392#endif // ART_COMPILER_COMPILED_METHOD_H_