blob: d6a07f6226e515c56a3c277036abcc5b3ae45f46 [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
30namespace art {
31
Mathieu Chartier193bad92013-08-29 18:46:00 -070032class CompilerDriver;
33
Logan Chien598c5132012-04-28 22:00:44 +080034class CompiledCode {
35 public:
Brian Carlstrom265091e2013-01-30 14:08:26 -080036 // For Quick to supply an code blob
Mathieu Chartier193bad92013-08-29 18:46:00 -070037 CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set,
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080038 const ArrayRef<const uint8_t>& quick_code, bool owns_code_array);
39
40 virtual ~CompiledCode();
Logan Chien598c5132012-04-28 22:00:44 +080041
Logan Chien598c5132012-04-28 22:00:44 +080042 InstructionSet GetInstructionSet() const {
43 return instruction_set_;
44 }
45
Andreas Gampee21dc3d2014-12-08 16:59:43 -080046 const SwapVector<uint8_t>* GetQuickCode() const {
Ian Rogersef7d42f2014-01-06 12:55:46 -080047 return quick_code_;
Logan Chien598c5132012-04-28 22:00:44 +080048 }
49
Andreas Gampee21dc3d2014-12-08 16:59:43 -080050 void SetCode(const ArrayRef<const uint8_t>* quick_code);
Ian Rogersef7d42f2014-01-06 12:55:46 -080051
52 bool operator==(const CompiledCode& rhs) const;
53
Logan Chien598c5132012-04-28 22:00:44 +080054 // To align an offset from a page-aligned value to make it suitable
55 // for code storage. For example on ARM, to ensure that PC relative
56 // valu computations work out as expected.
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080057 size_t AlignCode(size_t offset) const;
58 static size_t AlignCode(size_t offset, InstructionSet instruction_set);
Logan Chien598c5132012-04-28 22:00:44 +080059
60 // returns the difference between the code address and a usable PC.
61 // mainly to cope with kThumb2 where the lower bit must be set.
62 size_t CodeDelta() const;
Dave Allison50abf0a2014-06-23 13:19:59 -070063 static size_t CodeDelta(InstructionSet instruction_set);
Logan Chien598c5132012-04-28 22:00:44 +080064
65 // Returns a pointer suitable for invoking the code at the argument
66 // code_pointer address. Mainly to cope with kThumb2 where the
67 // lower bit must be set to indicate Thumb mode.
68 static const void* CodePointer(const void* code_pointer,
69 InstructionSet instruction_set);
70
Brian Carlstrom265091e2013-01-30 14:08:26 -080071 const std::vector<uint32_t>& GetOatdataOffsetsToCompliledCodeOffset() const;
72 void AddOatdataOffsetToCompliledCodeOffset(uint32_t offset);
Brian Carlstrom265091e2013-01-30 14:08:26 -080073
Logan Chien598c5132012-04-28 22:00:44 +080074 private:
Ian Rogersef7d42f2014-01-06 12:55:46 -080075 CompilerDriver* const compiler_driver_;
Mathieu Chartier193bad92013-08-29 18:46:00 -070076
Logan Chien598c5132012-04-28 22:00:44 +080077 const InstructionSet instruction_set_;
Brian Carlstrom8227cc12013-03-06 14:26:48 -080078
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080079 // If we own the code array (means that we free in destructor).
80 const bool owns_code_array_;
81
Ian Rogersef7d42f2014-01-06 12:55:46 -080082 // Used to store the PIC code for Quick.
Andreas Gampee21dc3d2014-12-08 16:59:43 -080083 SwapVector<uint8_t>* quick_code_;
Brian Carlstrom265091e2013-01-30 14:08:26 -080084
Brian Carlstrom265091e2013-01-30 14:08:26 -080085 // There are offsets from the oatdata symbol to where the offset to
86 // the compiled method will be found. These are computed by the
87 // OatWriter and then used by the ElfWriter to add relocations so
88 // that MCLinker can update the values to the location in the linked .so.
89 std::vector<uint32_t> oatdata_offsets_to_compiled_code_offset_;
Logan Chien598c5132012-04-28 22:00:44 +080090};
91
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070092class SrcMapElem {
93 public:
94 uint32_t from_;
95 int32_t to_;
96
Yevgeny Rouban33ac8192014-08-19 18:39:57 +070097 explicit operator int64_t() const {
98 return (static_cast<int64_t>(to_) << 32) | from_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070099 }
100
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700101 bool operator<(const SrcMapElem& sme) const {
102 return int64_t(*this) < int64_t(sme);
103 }
104
105 bool operator==(const SrcMapElem& sme) const {
106 return int64_t(*this) == int64_t(sme);
107 }
108
109 explicit operator uint8_t() const {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700110 return static_cast<uint8_t>(from_ + to_);
111 }
112};
113
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800114template <class Allocator>
115class SrcMap FINAL : public std::vector<SrcMapElem, Allocator> {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700116 public:
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800117 using std::vector<SrcMapElem, Allocator>::begin;
118 using typename std::vector<SrcMapElem, Allocator>::const_iterator;
119 using std::vector<SrcMapElem, Allocator>::empty;
120 using std::vector<SrcMapElem, Allocator>::end;
121 using std::vector<SrcMapElem, Allocator>::resize;
122 using std::vector<SrcMapElem, Allocator>::shrink_to_fit;
123 using std::vector<SrcMapElem, Allocator>::size;
124
125 explicit SrcMap() {}
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800126 explicit SrcMap(const Allocator& alloc) : std::vector<SrcMapElem, Allocator>(alloc) {}
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800127
128 template <class InputIt>
129 SrcMap(InputIt first, InputIt last, const Allocator& alloc)
130 : std::vector<SrcMapElem, Allocator>(first, last, alloc) {}
131
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700132 void SortByFrom() {
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700133 std::sort(begin(), end(), [] (const SrcMapElem& lhs, const SrcMapElem& rhs) -> bool {
134 return lhs.from_ < rhs.from_;
135 });
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700136 }
137
138 const_iterator FindByTo(int32_t to) const {
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700139 return std::lower_bound(begin(), end(), SrcMapElem({0, to}));
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700140 }
141
142 SrcMap& Arrange() {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700143 if (!empty()) {
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700144 std::sort(begin(), end());
145 resize(std::unique(begin(), end()) - begin());
146 shrink_to_fit();
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700147 }
148 return *this;
149 }
150
151 void DeltaFormat(const SrcMapElem& start, uint32_t highest_pc) {
152 // Convert from abs values to deltas.
153 if (!empty()) {
154 SortByFrom();
155
156 // TODO: one PC can be mapped to several Java src lines.
157 // do we want such a one-to-many correspondence?
158
159 // get rid of the highest values
160 size_t i = size() - 1;
161 for (; i > 0 ; i--) {
Yevgeny Rouban1127b122014-09-16 11:29:26 +0700162 if ((*this)[i].from_ < highest_pc) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700163 break;
164 }
165 }
166 this->resize(i + 1);
167
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800168 for (i = size(); --i >= 1; ) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700169 (*this)[i].from_ -= (*this)[i-1].from_;
170 (*this)[i].to_ -= (*this)[i-1].to_;
171 }
172 DCHECK((*this)[0].from_ >= start.from_);
173 (*this)[0].from_ -= start.from_;
174 (*this)[0].to_ -= start.to_;
175 }
176 }
177};
178
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800179using DefaultSrcMap = SrcMap<std::allocator<SrcMapElem>>;
180using SwapSrcMap = SrcMap<SwapAllocator<SrcMapElem>>;
181
182
Vladimir Markof4da6752014-08-01 19:04:18 +0100183enum LinkerPatchType {
184 kLinkerPatchMethod,
185 kLinkerPatchCall,
186 kLinkerPatchCallRelative, // NOTE: Actual patching is instruction_set-dependent.
187 kLinkerPatchType,
188};
189
190class LinkerPatch {
191 public:
192 static LinkerPatch MethodPatch(size_t literal_offset,
193 const DexFile* target_dex_file,
194 uint32_t target_method_idx) {
195 return LinkerPatch(literal_offset, kLinkerPatchMethod,
196 target_method_idx, target_dex_file);
197 }
198
199 static LinkerPatch CodePatch(size_t literal_offset,
200 const DexFile* target_dex_file,
201 uint32_t target_method_idx) {
202 return LinkerPatch(literal_offset, kLinkerPatchCall,
203 target_method_idx, target_dex_file);
204 }
205
206 static LinkerPatch RelativeCodePatch(size_t literal_offset,
207 const DexFile* target_dex_file,
208 uint32_t target_method_idx) {
209 return LinkerPatch(literal_offset, kLinkerPatchCallRelative,
210 target_method_idx, target_dex_file);
211 }
212
213 static LinkerPatch TypePatch(size_t literal_offset,
214 const DexFile* target_dex_file,
215 uint32_t target_type_idx) {
216 return LinkerPatch(literal_offset, kLinkerPatchType, target_type_idx, target_dex_file);
217 }
218
219 LinkerPatch(const LinkerPatch& other) = default;
220 LinkerPatch& operator=(const LinkerPatch& other) = default;
221
222 size_t LiteralOffset() const {
223 return literal_offset_;
224 }
225
226 LinkerPatchType Type() const {
227 return patch_type_;
228 }
229
230 MethodReference TargetMethod() const {
231 DCHECK(patch_type_ == kLinkerPatchMethod ||
232 patch_type_ == kLinkerPatchCall || patch_type_ == kLinkerPatchCallRelative);
233 return MethodReference(target_dex_file_, target_idx_);
234 }
235
236 const DexFile* TargetTypeDexFile() const {
237 DCHECK(patch_type_ == kLinkerPatchType);
238 return target_dex_file_;
239 }
240
241 uint32_t TargetTypeIndex() const {
242 DCHECK(patch_type_ == kLinkerPatchType);
243 return target_idx_;
244 }
245
246 private:
247 LinkerPatch(size_t literal_offset, LinkerPatchType patch_type,
248 uint32_t target_idx, const DexFile* target_dex_file)
249 : literal_offset_(literal_offset),
250 patch_type_(patch_type),
251 target_idx_(target_idx),
252 target_dex_file_(target_dex_file) {
253 }
254
255 size_t literal_offset_;
256 LinkerPatchType patch_type_;
257 uint32_t target_idx_; // Method index (Call/Method patches) or type index (Type patches).
258 const DexFile* target_dex_file_;
259
260 friend bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs);
261 friend bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs);
262};
263
264inline bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs) {
265 return lhs.literal_offset_ == rhs.literal_offset_ &&
266 lhs.patch_type_ == rhs.patch_type_ &&
267 lhs.target_idx_ == rhs.target_idx_ &&
268 lhs.target_dex_file_ == rhs.target_dex_file_;
269}
270
271inline bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs) {
272 return (lhs.literal_offset_ != rhs.literal_offset_) ? lhs.literal_offset_ < rhs.literal_offset_
273 : (lhs.patch_type_ != rhs.patch_type_) ? lhs.patch_type_ < rhs.patch_type_
274 : (lhs.target_idx_ != rhs.target_idx_) ? lhs.target_idx_ < rhs.target_idx_
275 : lhs.target_dex_file_ < rhs.target_dex_file_;
276}
277
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700278class CompiledMethod FINAL : public CompiledCode {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700279 public:
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800280 // Constructs a CompiledMethod.
281 // Note: Consider using the static allocation methods below that will allocate the CompiledMethod
282 // in the swap space.
Ian Rogers72d32622014-05-06 16:20:11 -0700283 CompiledMethod(CompilerDriver* driver,
Mathieu Chartier193bad92013-08-29 18:46:00 -0700284 InstructionSet instruction_set,
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800285 const ArrayRef<const uint8_t>& quick_code,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700286 const size_t frame_size_in_bytes,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700287 const uint32_t core_spill_mask,
288 const uint32_t fp_spill_mask,
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800289 DefaultSrcMap* src_mapping_table,
290 const ArrayRef<const uint8_t>& mapping_table,
291 const ArrayRef<const uint8_t>& vmap_table,
292 const ArrayRef<const uint8_t>& native_gc_map,
293 const ArrayRef<const uint8_t>& cfi_info,
Vladimir Markof4da6752014-08-01 19:04:18 +0100294 const ArrayRef<LinkerPatch>& patches = ArrayRef<LinkerPatch>());
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700295
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800296 virtual ~CompiledMethod();
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700297
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800298 static CompiledMethod* SwapAllocCompiledMethod(
299 CompilerDriver* driver,
300 InstructionSet instruction_set,
301 const ArrayRef<const uint8_t>& quick_code,
302 const size_t frame_size_in_bytes,
303 const uint32_t core_spill_mask,
304 const uint32_t fp_spill_mask,
305 DefaultSrcMap* src_mapping_table,
306 const ArrayRef<const uint8_t>& mapping_table,
307 const ArrayRef<const uint8_t>& vmap_table,
308 const ArrayRef<const uint8_t>& native_gc_map,
309 const ArrayRef<const uint8_t>& cfi_info,
310 const ArrayRef<LinkerPatch>& patches = ArrayRef<LinkerPatch>());
311
312 static CompiledMethod* SwapAllocCompiledMethodStackMap(
313 CompilerDriver* driver,
314 InstructionSet instruction_set,
315 const ArrayRef<const uint8_t>& quick_code,
316 const size_t frame_size_in_bytes,
317 const uint32_t core_spill_mask,
318 const uint32_t fp_spill_mask,
319 const ArrayRef<const uint8_t>& stack_map);
320
321 static CompiledMethod* SwapAllocCompiledMethodCFI(CompilerDriver* driver,
322 InstructionSet instruction_set,
323 const ArrayRef<const uint8_t>& quick_code,
324 const size_t frame_size_in_bytes,
325 const uint32_t core_spill_mask,
326 const uint32_t fp_spill_mask,
327 const ArrayRef<const uint8_t>& cfi_info);
328
329 static void ReleaseSwapAllocatedCompiledMethod(CompilerDriver* driver, CompiledMethod* m);
330
Ian Rogers0c7abda2012-09-19 13:33:42 -0700331 size_t GetFrameSizeInBytes() const {
332 return frame_size_in_bytes_;
Logan Chien110bcba2012-04-16 19:11:28 +0800333 }
Ian Rogers0c7abda2012-09-19 13:33:42 -0700334
335 uint32_t GetCoreSpillMask() const {
336 return core_spill_mask_;
337 }
338
339 uint32_t GetFpSpillMask() const {
340 return fp_spill_mask_;
341 }
342
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800343 const SwapSrcMap& GetSrcMappingTable() const {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700344 DCHECK(src_mapping_table_ != nullptr);
345 return *src_mapping_table_;
346 }
347
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800348 SwapVector<uint8_t> const* GetMappingTable() const {
Nicolas Geoffray376b2bb2014-12-09 14:26:32 +0000349 return mapping_table_;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700350 }
351
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800352 const SwapVector<uint8_t>* GetVmapTable() const {
Mathieu Chartier193bad92013-08-29 18:46:00 -0700353 DCHECK(vmap_table_ != nullptr);
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800354 return vmap_table_;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700355 }
356
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800357 SwapVector<uint8_t> const* GetGcMap() const {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100358 return gc_map_;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700359 }
Logan Chien110bcba2012-04-16 19:11:28 +0800360
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800361 const SwapVector<uint8_t>* GetCFIInfo() const {
Mark Mendellae9fd932014-02-10 16:14:35 -0800362 return cfi_info_;
363 }
364
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800365 const SwapVector<LinkerPatch>& GetPatches() const {
Vladimir Markof4da6752014-08-01 19:04:18 +0100366 return patches_;
367 }
368
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700369 private:
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800370 // Whether or not the arrays are owned by the compiled method or dedupe sets.
371 const bool owns_arrays_;
Ian Rogersa1827042013-04-18 16:36:43 -0700372 // For quick code, the size of the activation used by the code.
Ian Rogers0c7abda2012-09-19 13:33:42 -0700373 const size_t frame_size_in_bytes_;
Ian Rogersa1827042013-04-18 16:36:43 -0700374 // For quick code, a bit mask describing spilled GPR callee-save registers.
Ian Rogers169c9a72011-11-13 20:13:17 -0800375 const uint32_t core_spill_mask_;
Ian Rogersa1827042013-04-18 16:36:43 -0700376 // For quick code, a bit mask describing spilled FPR callee-save registers.
Ian Rogers169c9a72011-11-13 20:13:17 -0800377 const uint32_t fp_spill_mask_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700378 // For quick code, a set of pairs (PC, Line) mapping from native PC offset to Java line
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800379 SwapSrcMap* src_mapping_table_;
Ian Rogers96faf5b2013-08-09 22:05:32 -0700380 // For quick code, a uleb128 encoded map from native PC offset to dex PC aswell as dex PC to
381 // native PC offset. Size prefixed.
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800382 SwapVector<uint8_t>* mapping_table_;
Ian Rogers96faf5b2013-08-09 22:05:32 -0700383 // For quick code, a uleb128 encoded map from GPR/FPR register to dex register. Size prefixed.
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800384 SwapVector<uint8_t>* vmap_table_;
Ian Rogersa1827042013-04-18 16:36:43 -0700385 // For quick code, a map keyed by native PC indices to bitmaps describing what dalvik registers
Elliott Hughes956af0f2014-12-11 14:34:28 -0800386 // are live.
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800387 SwapVector<uint8_t>* gc_map_;
Mark Mendellae9fd932014-02-10 16:14:35 -0800388 // For quick code, a FDE entry for the debug_frame section.
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800389 SwapVector<uint8_t>* cfi_info_;
Vladimir Markof4da6752014-08-01 19:04:18 +0100390 // For quick code, linker patches needed by the method.
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800391 SwapVector<LinkerPatch> patches_;
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700392};
393
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700394} // namespace art
395
Mathieu Chartier193bad92013-08-29 18:46:00 -0700396#endif // ART_COMPILER_COMPILED_METHOD_H_