builder.h revision e53798a7e3267305f696bf658e418c92e63e0834
1/*
2 * Copyright (C) 2014 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#ifndef ART_COMPILER_OPTIMIZING_BUILDER_H_
18#define ART_COMPILER_OPTIMIZING_BUILDER_H_
19
20#include "dex_file.h"
21#include "dex_file-inl.h"
22#include "driver/compiler_driver.h"
23#include "driver/dex_compilation_unit.h"
24#include "optimizing_compiler_stats.h"
25#include "primitive.h"
26#include "utils/arena_object.h"
27#include "utils/growable_array.h"
28#include "nodes.h"
29
30namespace art {
31
32class Instruction;
33class SwitchTable;
34
35class HGraphBuilder : public ValueObject {
36 public:
37  HGraphBuilder(ArenaAllocator* arena,
38                DexCompilationUnit* dex_compilation_unit,
39                const DexCompilationUnit* const outer_compilation_unit,
40                const DexFile* dex_file,
41                CompilerDriver* driver,
42                OptimizingCompilerStats* compiler_stats)
43      : arena_(arena),
44        branch_targets_(arena, 0),
45        locals_(arena, 0),
46        entry_block_(nullptr),
47        exit_block_(nullptr),
48        current_block_(nullptr),
49        graph_(nullptr),
50        constant0_(nullptr),
51        constant1_(nullptr),
52        dex_file_(dex_file),
53        dex_compilation_unit_(dex_compilation_unit),
54        compiler_driver_(driver),
55        outer_compilation_unit_(outer_compilation_unit),
56        return_type_(Primitive::GetType(dex_compilation_unit_->GetShorty()[0])),
57        code_start_(nullptr),
58        latest_result_(nullptr),
59        compilation_stats_(compiler_stats) {}
60
61  // Only for unit testing.
62  HGraphBuilder(ArenaAllocator* arena, Primitive::Type return_type = Primitive::kPrimInt)
63      : arena_(arena),
64        branch_targets_(arena, 0),
65        locals_(arena, 0),
66        entry_block_(nullptr),
67        exit_block_(nullptr),
68        current_block_(nullptr),
69        graph_(nullptr),
70        constant0_(nullptr),
71        constant1_(nullptr),
72        dex_file_(nullptr),
73        dex_compilation_unit_(nullptr),
74        compiler_driver_(nullptr),
75        outer_compilation_unit_(nullptr),
76        return_type_(return_type),
77        code_start_(nullptr),
78        latest_result_(nullptr),
79        compilation_stats_(nullptr) {}
80
81  HGraph* BuildGraph(const DexFile::CodeItem& code, int start_instruction_id = 0);
82
83 private:
84  // Analyzes the dex instruction and adds HInstruction to the graph
85  // to execute that instruction. Returns whether the instruction can
86  // be handled.
87  bool AnalyzeDexInstruction(const Instruction& instruction, uint32_t dex_pc);
88
89  // Finds all instructions that start a new block, and populates branch_targets_ with
90  // the newly created blocks.
91  // As a side effect, also compute the number of dex instructions, blocks, and
92  // branches.
93  void ComputeBranchTargets(const uint16_t* start,
94                            const uint16_t* end,
95                            size_t* number_of_dex_instructions,
96                            size_t* number_of_block,
97                            size_t* number_of_branches);
98  void MaybeUpdateCurrentBlock(size_t index);
99  HBasicBlock* FindBlockStartingAt(int32_t index) const;
100
101  HIntConstant* GetIntConstant0();
102  HIntConstant* GetIntConstant1();
103  HIntConstant* GetIntConstant(int32_t constant);
104  HLongConstant* GetLongConstant(int64_t constant);
105  void InitializeLocals(uint16_t count);
106  HLocal* GetLocalAt(int register_index) const;
107  void UpdateLocal(int register_index, HInstruction* instruction) const;
108  HInstruction* LoadLocal(int register_index, Primitive::Type type) const;
109  void PotentiallyAddSuspendCheck(int32_t target_offset, uint32_t dex_pc);
110  void InitializeParameters(uint16_t number_of_parameters);
111
112  template<typename T>
113  void Unop_12x(const Instruction& instruction, Primitive::Type type);
114
115  template<typename T>
116  void Binop_23x(const Instruction& instruction, Primitive::Type type);
117
118  template<typename T>
119  void Binop_23x(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
120
121  template<typename T>
122  void Binop_23x_shift(const Instruction& instruction, Primitive::Type type);
123
124  void Binop_23x_cmp(const Instruction& instruction, Primitive::Type type, HCompare::Bias bias);
125
126  template<typename T>
127  void Binop_12x(const Instruction& instruction, Primitive::Type type);
128
129  template<typename T>
130  void Binop_12x(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
131
132  template<typename T>
133  void Binop_12x_shift(const Instruction& instruction, Primitive::Type type);
134
135  template<typename T>
136  void Binop_22b(const Instruction& instruction, bool reverse);
137
138  template<typename T>
139  void Binop_22s(const Instruction& instruction, bool reverse);
140
141  template<typename T> void If_21t(const Instruction& instruction, uint32_t dex_pc);
142  template<typename T> void If_22t(const Instruction& instruction, uint32_t dex_pc);
143
144  void Conversion_12x(const Instruction& instruction,
145                      Primitive::Type input_type,
146                      Primitive::Type result_type,
147                      uint32_t dex_pc);
148
149  void BuildCheckedDivRem(uint16_t out_reg,
150                          uint16_t first_reg,
151                          int64_t second_reg_or_constant,
152                          uint32_t dex_pc,
153                          Primitive::Type type,
154                          bool second_is_lit,
155                          bool is_div);
156
157  void BuildReturn(const Instruction& instruction, Primitive::Type type);
158
159  // Builds an instance field access node and returns whether the instruction is supported.
160  bool BuildInstanceFieldAccess(const Instruction& instruction, uint32_t dex_pc, bool is_put);
161
162  // Builds a static field access node and returns whether the instruction is supported.
163  bool BuildStaticFieldAccess(const Instruction& instruction, uint32_t dex_pc, bool is_put);
164
165  void BuildArrayAccess(const Instruction& instruction,
166                        uint32_t dex_pc,
167                        bool is_get,
168                        Primitive::Type anticipated_type);
169
170  // Builds an invocation node and returns whether the instruction is supported.
171  bool BuildInvoke(const Instruction& instruction,
172                   uint32_t dex_pc,
173                   uint32_t method_idx,
174                   uint32_t number_of_vreg_arguments,
175                   bool is_range,
176                   uint32_t* args,
177                   uint32_t register_index);
178
179  // Builds a new array node and the instructions that fill it.
180  void BuildFilledNewArray(uint32_t dex_pc,
181                           uint32_t type_index,
182                           uint32_t number_of_vreg_arguments,
183                           bool is_range,
184                           uint32_t* args,
185                           uint32_t register_index);
186
187  void BuildFillArrayData(const Instruction& instruction, uint32_t dex_pc);
188
189  // Fills the given object with data as specified in the fill-array-data
190  // instruction. Currently only used for non-reference and non-floating point
191  // arrays.
192  template <typename T>
193  void BuildFillArrayData(HInstruction* object,
194                          const T* data,
195                          uint32_t element_count,
196                          Primitive::Type anticipated_type,
197                          uint32_t dex_pc);
198
199  // Fills the given object with data as specified in the fill-array-data
200  // instruction. The data must be for long and double arrays.
201  void BuildFillWideArrayData(HInstruction* object,
202                              const int64_t* data,
203                              uint32_t element_count,
204                              uint32_t dex_pc);
205
206  // Builds a `HInstanceOf`, or a `HCheckCast` instruction.
207  // Returns whether we succeeded in building the instruction.
208  bool BuildTypeCheck(const Instruction& instruction,
209                      uint8_t destination,
210                      uint8_t reference,
211                      uint16_t type_index,
212                      uint32_t dex_pc);
213
214  // Builds an instruction sequence for a packed switch statement.
215  void BuildPackedSwitch(const Instruction& instruction, uint32_t dex_pc);
216
217  // Builds an instruction sequence for a sparse switch statement.
218  void BuildSparseSwitch(const Instruction& instruction, uint32_t dex_pc);
219
220  void BuildSwitchCaseHelper(const Instruction& instruction, size_t index,
221                             bool is_last_case, const SwitchTable& table,
222                             HInstruction* value, int32_t case_value_int,
223                             int32_t target_offset, uint32_t dex_pc);
224
225  bool SkipCompilation(size_t number_of_dex_instructions,
226                       size_t number_of_blocks,
227                       size_t number_of_branches);
228
229  void MaybeRecordStat(MethodCompilationStat compilation_stat);
230
231  // Returns whether `type_index` points to the outer-most compiling method's class.
232  bool IsCompilingClass(uint16_t type_index) const {
233    uint32_t referrer_index = outer_compilation_unit_->GetDexMethodIndex();
234    const DexFile::MethodId& method_id =
235        outer_compilation_unit_->GetDexFile()->GetMethodId(referrer_index);
236    return method_id.class_idx_ == type_index;
237  }
238
239  ArenaAllocator* const arena_;
240
241  // A list of the size of the dex code holding block information for
242  // the method. If an entry contains a block, then the dex instruction
243  // starting at that entry is the first instruction of a new block.
244  GrowableArray<HBasicBlock*> branch_targets_;
245
246  GrowableArray<HLocal*> locals_;
247
248  HBasicBlock* entry_block_;
249  HBasicBlock* exit_block_;
250  HBasicBlock* current_block_;
251  HGraph* graph_;
252
253  HIntConstant* constant0_;
254  HIntConstant* constant1_;
255
256  // The dex file where the method being compiled is.
257  const DexFile* const dex_file_;
258
259  // The compilation unit of the current method being compiled. Note that
260  // it can be an inlined method.
261  DexCompilationUnit* const dex_compilation_unit_;
262
263  CompilerDriver* const compiler_driver_;
264
265  // The compilation unit of the outermost method being compiled. That is the
266  // method being compiled (and not inlined), and potentially inlining other
267  // methods.
268  const DexCompilationUnit* const outer_compilation_unit_;
269
270  // The return type of the method being compiled.
271  const Primitive::Type return_type_;
272
273  // The pointer in the dex file where the instructions of the code item
274  // being currently compiled start.
275  const uint16_t* code_start_;
276
277  // The last invoke or fill-new-array being built. Only to be
278  // used by move-result instructions.
279  HInstruction* latest_result_;
280
281  OptimizingCompilerStats* compilation_stats_;
282
283  DISALLOW_COPY_AND_ASSIGN(HGraphBuilder);
284};
285
286}  // namespace art
287
288#endif  // ART_COMPILER_OPTIMIZING_BUILDER_H_
289