blob: d93db0380692653ac35aeb3f823617982921c432 [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"
Brian Carlstrom3320cf42011-10-04 14:58:28 -070028
Shih-wei Liaod1fec812012-02-13 09:51:10 -080029namespace llvm {
30 class Function;
Ian Rogersa1827042013-04-18 16:36:43 -070031} // namespace llvm
Shih-wei Liaod1fec812012-02-13 09:51:10 -080032
Brian Carlstrom3320cf42011-10-04 14:58:28 -070033namespace art {
34
Mathieu Chartier193bad92013-08-29 18:46:00 -070035class CompilerDriver;
36
Logan Chien598c5132012-04-28 22:00:44 +080037class CompiledCode {
38 public:
Brian Carlstrom265091e2013-01-30 14:08:26 -080039 // For Quick to supply an code blob
Mathieu Chartier193bad92013-08-29 18:46:00 -070040 CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set,
Dave Allisond6ed6422014-04-09 23:36:15 +000041 const std::vector<uint8_t>& quick_code);
Logan Chien598c5132012-04-28 22:00:44 +080042
Logan Chien598c5132012-04-28 22:00:44 +080043 InstructionSet GetInstructionSet() const {
44 return instruction_set_;
45 }
46
Ian Rogersef7d42f2014-01-06 12:55:46 -080047 const std::vector<uint8_t>* GetQuickCode() const {
48 return quick_code_;
Logan Chien598c5132012-04-28 22:00:44 +080049 }
50
Elliott Hughes956af0f2014-12-11 14:34:28 -080051 void SetCode(const std::vector<uint8_t>* quick_code);
Ian Rogersef7d42f2014-01-06 12:55:46 -080052
53 bool operator==(const CompiledCode& rhs) const;
54
Logan Chien598c5132012-04-28 22:00:44 +080055 // To align an offset from a page-aligned value to make it suitable
56 // for code storage. For example on ARM, to ensure that PC relative
57 // valu computations work out as expected.
58 uint32_t AlignCode(uint32_t offset) const;
59 static uint32_t AlignCode(uint32_t offset, InstructionSet instruction_set);
60
61 // returns the difference between the code address and a usable PC.
62 // mainly to cope with kThumb2 where the lower bit must be set.
63 size_t CodeDelta() const;
Dave Allison50abf0a2014-06-23 13:19:59 -070064 static size_t CodeDelta(InstructionSet instruction_set);
Logan Chien598c5132012-04-28 22:00:44 +080065
66 // Returns a pointer suitable for invoking the code at the argument
67 // code_pointer address. Mainly to cope with kThumb2 where the
68 // lower bit must be set to indicate Thumb mode.
69 static const void* CodePointer(const void* code_pointer,
70 InstructionSet instruction_set);
71
Brian Carlstrom265091e2013-01-30 14:08:26 -080072 const std::vector<uint32_t>& GetOatdataOffsetsToCompliledCodeOffset() const;
73 void AddOatdataOffsetToCompliledCodeOffset(uint32_t offset);
Brian Carlstrom265091e2013-01-30 14:08:26 -080074
Logan Chien598c5132012-04-28 22:00:44 +080075 private:
Ian Rogersef7d42f2014-01-06 12:55:46 -080076 CompilerDriver* const compiler_driver_;
Mathieu Chartier193bad92013-08-29 18:46:00 -070077
Logan Chien598c5132012-04-28 22:00:44 +080078 const InstructionSet instruction_set_;
Brian Carlstrom8227cc12013-03-06 14:26:48 -080079
Ian Rogersef7d42f2014-01-06 12:55:46 -080080 // Used to store the PIC code for Quick.
81 std::vector<uint8_t>* quick_code_;
Brian Carlstrom265091e2013-01-30 14:08:26 -080082
Brian Carlstrom265091e2013-01-30 14:08:26 -080083 // There are offsets from the oatdata symbol to where the offset to
84 // the compiled method will be found. These are computed by the
85 // OatWriter and then used by the ElfWriter to add relocations so
86 // that MCLinker can update the values to the location in the linked .so.
87 std::vector<uint32_t> oatdata_offsets_to_compiled_code_offset_;
Logan Chien598c5132012-04-28 22:00:44 +080088};
89
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070090class SrcMapElem {
91 public:
92 uint32_t from_;
93 int32_t to_;
94
Yevgeny Rouban33ac8192014-08-19 18:39:57 +070095 explicit operator int64_t() const {
96 return (static_cast<int64_t>(to_) << 32) | from_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070097 }
98
Yevgeny Rouban33ac8192014-08-19 18:39:57 +070099 bool operator<(const SrcMapElem& sme) const {
100 return int64_t(*this) < int64_t(sme);
101 }
102
103 bool operator==(const SrcMapElem& sme) const {
104 return int64_t(*this) == int64_t(sme);
105 }
106
107 explicit operator uint8_t() const {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700108 return static_cast<uint8_t>(from_ + to_);
109 }
110};
111
112class SrcMap FINAL : public std::vector<SrcMapElem> {
113 public:
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700114 void SortByFrom() {
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700115 std::sort(begin(), end(), [] (const SrcMapElem& lhs, const SrcMapElem& rhs) -> bool {
116 return lhs.from_ < rhs.from_;
117 });
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700118 }
119
120 const_iterator FindByTo(int32_t to) const {
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700121 return std::lower_bound(begin(), end(), SrcMapElem({0, to}));
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700122 }
123
124 SrcMap& Arrange() {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700125 if (!empty()) {
Yevgeny Rouban33ac8192014-08-19 18:39:57 +0700126 std::sort(begin(), end());
127 resize(std::unique(begin(), end()) - begin());
128 shrink_to_fit();
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700129 }
130 return *this;
131 }
132
133 void DeltaFormat(const SrcMapElem& start, uint32_t highest_pc) {
134 // Convert from abs values to deltas.
135 if (!empty()) {
136 SortByFrom();
137
138 // TODO: one PC can be mapped to several Java src lines.
139 // do we want such a one-to-many correspondence?
140
141 // get rid of the highest values
142 size_t i = size() - 1;
143 for (; i > 0 ; i--) {
Yevgeny Rouban1127b122014-09-16 11:29:26 +0700144 if ((*this)[i].from_ < highest_pc) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700145 break;
146 }
147 }
148 this->resize(i + 1);
149
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800150 for (i = size(); --i >= 1; ) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700151 (*this)[i].from_ -= (*this)[i-1].from_;
152 (*this)[i].to_ -= (*this)[i-1].to_;
153 }
154 DCHECK((*this)[0].from_ >= start.from_);
155 (*this)[0].from_ -= start.from_;
156 (*this)[0].to_ -= start.to_;
157 }
158 }
159};
160
Vladimir Markof4da6752014-08-01 19:04:18 +0100161enum LinkerPatchType {
162 kLinkerPatchMethod,
163 kLinkerPatchCall,
164 kLinkerPatchCallRelative, // NOTE: Actual patching is instruction_set-dependent.
165 kLinkerPatchType,
166};
167
168class LinkerPatch {
169 public:
170 static LinkerPatch MethodPatch(size_t literal_offset,
171 const DexFile* target_dex_file,
172 uint32_t target_method_idx) {
173 return LinkerPatch(literal_offset, kLinkerPatchMethod,
174 target_method_idx, target_dex_file);
175 }
176
177 static LinkerPatch CodePatch(size_t literal_offset,
178 const DexFile* target_dex_file,
179 uint32_t target_method_idx) {
180 return LinkerPatch(literal_offset, kLinkerPatchCall,
181 target_method_idx, target_dex_file);
182 }
183
184 static LinkerPatch RelativeCodePatch(size_t literal_offset,
185 const DexFile* target_dex_file,
186 uint32_t target_method_idx) {
187 return LinkerPatch(literal_offset, kLinkerPatchCallRelative,
188 target_method_idx, target_dex_file);
189 }
190
191 static LinkerPatch TypePatch(size_t literal_offset,
192 const DexFile* target_dex_file,
193 uint32_t target_type_idx) {
194 return LinkerPatch(literal_offset, kLinkerPatchType, target_type_idx, target_dex_file);
195 }
196
197 LinkerPatch(const LinkerPatch& other) = default;
198 LinkerPatch& operator=(const LinkerPatch& other) = default;
199
200 size_t LiteralOffset() const {
201 return literal_offset_;
202 }
203
204 LinkerPatchType Type() const {
205 return patch_type_;
206 }
207
208 MethodReference TargetMethod() const {
209 DCHECK(patch_type_ == kLinkerPatchMethod ||
210 patch_type_ == kLinkerPatchCall || patch_type_ == kLinkerPatchCallRelative);
211 return MethodReference(target_dex_file_, target_idx_);
212 }
213
214 const DexFile* TargetTypeDexFile() const {
215 DCHECK(patch_type_ == kLinkerPatchType);
216 return target_dex_file_;
217 }
218
219 uint32_t TargetTypeIndex() const {
220 DCHECK(patch_type_ == kLinkerPatchType);
221 return target_idx_;
222 }
223
224 private:
225 LinkerPatch(size_t literal_offset, LinkerPatchType patch_type,
226 uint32_t target_idx, const DexFile* target_dex_file)
227 : literal_offset_(literal_offset),
228 patch_type_(patch_type),
229 target_idx_(target_idx),
230 target_dex_file_(target_dex_file) {
231 }
232
233 size_t literal_offset_;
234 LinkerPatchType patch_type_;
235 uint32_t target_idx_; // Method index (Call/Method patches) or type index (Type patches).
236 const DexFile* target_dex_file_;
237
238 friend bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs);
239 friend bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs);
240};
241
242inline bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs) {
243 return lhs.literal_offset_ == rhs.literal_offset_ &&
244 lhs.patch_type_ == rhs.patch_type_ &&
245 lhs.target_idx_ == rhs.target_idx_ &&
246 lhs.target_dex_file_ == rhs.target_dex_file_;
247}
248
249inline bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs) {
250 return (lhs.literal_offset_ != rhs.literal_offset_) ? lhs.literal_offset_ < rhs.literal_offset_
251 : (lhs.patch_type_ != rhs.patch_type_) ? lhs.patch_type_ < rhs.patch_type_
252 : (lhs.target_idx_ != rhs.target_idx_) ? lhs.target_idx_ < rhs.target_idx_
253 : lhs.target_dex_file_ < rhs.target_dex_file_;
254}
255
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700256class CompiledMethod FINAL : public CompiledCode {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700257 public:
Nicolas Geoffray39468442014-09-02 15:17:15 +0100258 // Constructs a CompiledMethod for Quick.
Ian Rogers72d32622014-05-06 16:20:11 -0700259 CompiledMethod(CompilerDriver* driver,
Mathieu Chartier193bad92013-08-29 18:46:00 -0700260 InstructionSet instruction_set,
Ian Rogersef7d42f2014-01-06 12:55:46 -0800261 const std::vector<uint8_t>& quick_code,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700262 const size_t frame_size_in_bytes,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700263 const uint32_t core_spill_mask,
264 const uint32_t fp_spill_mask,
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700265 SrcMap* src_mapping_table,
Ian Rogers96faf5b2013-08-09 22:05:32 -0700266 const std::vector<uint8_t>& mapping_table,
267 const std::vector<uint8_t>& vmap_table,
Mark Mendellae9fd932014-02-10 16:14:35 -0800268 const std::vector<uint8_t>& native_gc_map,
Vladimir Markof4da6752014-08-01 19:04:18 +0100269 const std::vector<uint8_t>* cfi_info,
270 const ArrayRef<LinkerPatch>& patches = ArrayRef<LinkerPatch>());
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700271
Nicolas Geoffray39468442014-09-02 15:17:15 +0100272 // Constructs a CompiledMethod for Optimizing.
273 CompiledMethod(CompilerDriver* driver,
274 InstructionSet instruction_set,
275 const std::vector<uint8_t>& quick_code,
276 const size_t frame_size_in_bytes,
277 const uint32_t core_spill_mask,
278 const uint32_t fp_spill_mask,
Nicolas Geoffray39468442014-09-02 15:17:15 +0100279 const std::vector<uint8_t>& vmap_table);
280
Ian Rogersef7d42f2014-01-06 12:55:46 -0800281 // Constructs a CompiledMethod for the QuickJniCompiler.
Ian Rogers72d32622014-05-06 16:20:11 -0700282 CompiledMethod(CompilerDriver* driver,
Mathieu Chartier193bad92013-08-29 18:46:00 -0700283 InstructionSet instruction_set,
Ian Rogersef7d42f2014-01-06 12:55:46 -0800284 const std::vector<uint8_t>& quick_code,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700285 const size_t frame_size_in_bytes,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700286 const uint32_t core_spill_mask,
Tong Shen547cdfd2014-08-05 01:54:19 -0700287 const uint32_t fp_spill_mask,
288 const std::vector<uint8_t>* cfi_info);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700289
Ian Rogers0c7abda2012-09-19 13:33:42 -0700290 ~CompiledMethod() {}
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700291
Ian Rogers0c7abda2012-09-19 13:33:42 -0700292 size_t GetFrameSizeInBytes() const {
293 return frame_size_in_bytes_;
Logan Chien110bcba2012-04-16 19:11:28 +0800294 }
Ian Rogers0c7abda2012-09-19 13:33:42 -0700295
296 uint32_t GetCoreSpillMask() const {
297 return core_spill_mask_;
298 }
299
300 uint32_t GetFpSpillMask() const {
301 return fp_spill_mask_;
302 }
303
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700304 const SrcMap& GetSrcMappingTable() const {
305 DCHECK(src_mapping_table_ != nullptr);
306 return *src_mapping_table_;
307 }
308
Nicolas Geoffray376b2bb2014-12-09 14:26:32 +0000309 std::vector<uint8_t> const* GetMappingTable() const {
310 return mapping_table_;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700311 }
312
Ian Rogers96faf5b2013-08-09 22:05:32 -0700313 const std::vector<uint8_t>& GetVmapTable() const {
Mathieu Chartier193bad92013-08-29 18:46:00 -0700314 DCHECK(vmap_table_ != nullptr);
315 return *vmap_table_;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700316 }
317
Nicolas Geoffray39468442014-09-02 15:17:15 +0100318 std::vector<uint8_t> const* GetGcMap() const {
319 return gc_map_;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700320 }
Logan Chien110bcba2012-04-16 19:11:28 +0800321
Mark Mendellae9fd932014-02-10 16:14:35 -0800322 const std::vector<uint8_t>* GetCFIInfo() const {
323 return cfi_info_;
324 }
325
Vladimir Markof4da6752014-08-01 19:04:18 +0100326 const std::vector<LinkerPatch>& GetPatches() const {
327 return patches_;
328 }
329
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700330 private:
Ian Rogersa1827042013-04-18 16:36:43 -0700331 // For quick code, the size of the activation used by the code.
Ian Rogers0c7abda2012-09-19 13:33:42 -0700332 const size_t frame_size_in_bytes_;
Ian Rogersa1827042013-04-18 16:36:43 -0700333 // For quick code, a bit mask describing spilled GPR callee-save registers.
Ian Rogers169c9a72011-11-13 20:13:17 -0800334 const uint32_t core_spill_mask_;
Ian Rogersa1827042013-04-18 16:36:43 -0700335 // For quick code, a bit mask describing spilled FPR callee-save registers.
Ian Rogers169c9a72011-11-13 20:13:17 -0800336 const uint32_t fp_spill_mask_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700337 // For quick code, a set of pairs (PC, Line) mapping from native PC offset to Java line
338 SrcMap* src_mapping_table_;
Ian Rogers96faf5b2013-08-09 22:05:32 -0700339 // For quick code, a uleb128 encoded map from native PC offset to dex PC aswell as dex PC to
340 // native PC offset. Size prefixed.
Mathieu Chartier193bad92013-08-29 18:46:00 -0700341 std::vector<uint8_t>* mapping_table_;
Ian Rogers96faf5b2013-08-09 22:05:32 -0700342 // For quick code, a uleb128 encoded map from GPR/FPR register to dex register. Size prefixed.
Mathieu Chartier193bad92013-08-29 18:46:00 -0700343 std::vector<uint8_t>* vmap_table_;
Ian Rogersa1827042013-04-18 16:36:43 -0700344 // For quick code, a map keyed by native PC indices to bitmaps describing what dalvik registers
Elliott Hughes956af0f2014-12-11 14:34:28 -0800345 // are live.
Mathieu Chartier193bad92013-08-29 18:46:00 -0700346 std::vector<uint8_t>* gc_map_;
Mark Mendellae9fd932014-02-10 16:14:35 -0800347 // For quick code, a FDE entry for the debug_frame section.
348 std::vector<uint8_t>* cfi_info_;
Vladimir Markof4da6752014-08-01 19:04:18 +0100349 // For quick code, linker patches needed by the method.
350 std::vector<LinkerPatch> patches_;
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700351};
352
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700353} // namespace art
354
Mathieu Chartier193bad92013-08-29 18:46:00 -0700355#endif // ART_COMPILER_COMPILED_METHOD_H_