diff options
Diffstat (limited to 'compiler/optimizing/builder.h')
| -rw-r--r-- | compiler/optimizing/builder.h | 209 |
1 files changed, 178 insertions, 31 deletions
diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h index 170c42761a..052aaf8b42 100644 --- a/compiler/optimizing/builder.h +++ b/compiler/optimizing/builder.h @@ -17,96 +17,223 @@ #ifndef ART_COMPILER_OPTIMIZING_BUILDER_H_ #define ART_COMPILER_OPTIMIZING_BUILDER_H_ +#include "base/arena_object.h" #include "dex_file.h" +#include "dex_file-inl.h" #include "driver/compiler_driver.h" #include "driver/dex_compilation_unit.h" +#include "optimizing_compiler_stats.h" #include "primitive.h" -#include "utils/allocation.h" #include "utils/growable_array.h" #include "nodes.h" namespace art { class Instruction; +class SwitchTable; class HGraphBuilder : public ValueObject { public: - HGraphBuilder(ArenaAllocator* arena, - DexCompilationUnit* dex_compilation_unit = nullptr, - const DexFile* dex_file = nullptr, - CompilerDriver* driver = nullptr) - : arena_(arena), - branch_targets_(arena, 0), - locals_(arena, 0), + HGraphBuilder(HGraph* graph, + DexCompilationUnit* dex_compilation_unit, + const DexCompilationUnit* const outer_compilation_unit, + const DexFile* dex_file, + CompilerDriver* driver, + OptimizingCompilerStats* compiler_stats) + : arena_(graph->GetArena()), + branch_targets_(graph->GetArena(), 0), + locals_(graph->GetArena(), 0), entry_block_(nullptr), exit_block_(nullptr), current_block_(nullptr), - graph_(nullptr), - constant0_(nullptr), - constant1_(nullptr), + graph_(graph), dex_file_(dex_file), dex_compilation_unit_(dex_compilation_unit), - compiler_driver_(driver) {} + compiler_driver_(driver), + outer_compilation_unit_(outer_compilation_unit), + return_type_(Primitive::GetType(dex_compilation_unit_->GetShorty()[0])), + code_start_(nullptr), + latest_result_(nullptr), + compilation_stats_(compiler_stats) {} - HGraph* BuildGraph(const DexFile::CodeItem& code); + // Only for unit testing. + HGraphBuilder(HGraph* graph, Primitive::Type return_type = Primitive::kPrimInt) + : arena_(graph->GetArena()), + branch_targets_(graph->GetArena(), 0), + locals_(graph->GetArena(), 0), + entry_block_(nullptr), + exit_block_(nullptr), + current_block_(nullptr), + graph_(graph), + dex_file_(nullptr), + dex_compilation_unit_(nullptr), + compiler_driver_(nullptr), + outer_compilation_unit_(nullptr), + return_type_(return_type), + code_start_(nullptr), + latest_result_(nullptr), + compilation_stats_(nullptr) {} + + bool BuildGraph(const DexFile::CodeItem& code); + + static constexpr const char* kBuilderPassName = "builder"; private: // Analyzes the dex instruction and adds HInstruction to the graph // to execute that instruction. Returns whether the instruction can // be handled. - bool AnalyzeDexInstruction(const Instruction& instruction, int32_t dex_offset); + bool AnalyzeDexInstruction(const Instruction& instruction, uint32_t dex_pc); // Finds all instructions that start a new block, and populates branch_targets_ with // the newly created blocks. - void ComputeBranchTargets(const uint16_t* start, const uint16_t* end); + // As a side effect, also compute the number of dex instructions, blocks, and + // branches. + // Returns true if all the branches fall inside the method code, false otherwise. + // (In normal cases this should always return true but someone can artificially + // create a code unit in which branches fall-through out of it). + bool ComputeBranchTargets(const uint16_t* start, + const uint16_t* end, + size_t* number_of_branches); void MaybeUpdateCurrentBlock(size_t index); HBasicBlock* FindBlockStartingAt(int32_t index) const; - HIntConstant* GetIntConstant0(); - HIntConstant* GetIntConstant1(); - HIntConstant* GetIntConstant(int32_t constant); - HLongConstant* GetLongConstant(int64_t constant); void InitializeLocals(uint16_t count); HLocal* GetLocalAt(int register_index) const; void UpdateLocal(int register_index, HInstruction* instruction) const; HInstruction* LoadLocal(int register_index, Primitive::Type type) const; + void PotentiallyAddSuspendCheck(HBasicBlock* target, uint32_t dex_pc); + void InitializeParameters(uint16_t number_of_parameters); + bool NeedsAccessCheck(uint32_t type_index) const; - // Temporarily returns whether the compiler supports the parameters - // of the method. - bool InitializeParameters(uint16_t number_of_parameters); + template<typename T> + void Unop_12x(const Instruction& instruction, Primitive::Type type); template<typename T> void Binop_23x(const Instruction& instruction, Primitive::Type type); template<typename T> + void Binop_23x(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc); + + template<typename T> + void Binop_23x_shift(const Instruction& instruction, Primitive::Type type); + + void Binop_23x_cmp(const Instruction& instruction, + Primitive::Type type, + HCompare::Bias bias, + uint32_t dex_pc); + + template<typename T> void Binop_12x(const Instruction& instruction, Primitive::Type type); template<typename T> + void Binop_12x(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc); + + template<typename T> + void Binop_12x_shift(const Instruction& instruction, Primitive::Type type); + + template<typename T> void Binop_22b(const Instruction& instruction, bool reverse); template<typename T> void Binop_22s(const Instruction& instruction, bool reverse); - template<typename T> void If_21t(const Instruction& instruction, uint32_t dex_offset); - template<typename T> void If_22t(const Instruction& instruction, uint32_t dex_offset); + template<typename T> void If_21t(const Instruction& instruction, uint32_t dex_pc); + template<typename T> void If_22t(const Instruction& instruction, uint32_t dex_pc); + + void Conversion_12x(const Instruction& instruction, + Primitive::Type input_type, + Primitive::Type result_type, + uint32_t dex_pc); + + void BuildCheckedDivRem(uint16_t out_reg, + uint16_t first_reg, + int64_t second_reg_or_constant, + uint32_t dex_pc, + Primitive::Type type, + bool second_is_lit, + bool is_div); void BuildReturn(const Instruction& instruction, Primitive::Type type); - bool BuildFieldAccess(const Instruction& instruction, uint32_t dex_offset, bool is_get); + // Builds an instance field access node and returns whether the instruction is supported. + bool BuildInstanceFieldAccess(const Instruction& instruction, uint32_t dex_pc, bool is_put); + + // Builds a static field access node and returns whether the instruction is supported. + bool BuildStaticFieldAccess(const Instruction& instruction, uint32_t dex_pc, bool is_put); + void BuildArrayAccess(const Instruction& instruction, - uint32_t dex_offset, + uint32_t dex_pc, bool is_get, Primitive::Type anticipated_type); // Builds an invocation node and returns whether the instruction is supported. bool BuildInvoke(const Instruction& instruction, - uint32_t dex_offset, + uint32_t dex_pc, uint32_t method_idx, uint32_t number_of_vreg_arguments, bool is_range, uint32_t* args, uint32_t register_index); + // Builds a new array node and the instructions that fill it. + void BuildFilledNewArray(uint32_t dex_pc, + uint32_t type_index, + uint32_t number_of_vreg_arguments, + bool is_range, + uint32_t* args, + uint32_t register_index); + + void BuildFillArrayData(const Instruction& instruction, uint32_t dex_pc); + + // Fills the given object with data as specified in the fill-array-data + // instruction. Currently only used for non-reference and non-floating point + // arrays. + template <typename T> + void BuildFillArrayData(HInstruction* object, + const T* data, + uint32_t element_count, + Primitive::Type anticipated_type, + uint32_t dex_pc); + + // Fills the given object with data as specified in the fill-array-data + // instruction. The data must be for long and double arrays. + void BuildFillWideArrayData(HInstruction* object, + const int64_t* data, + uint32_t element_count, + uint32_t dex_pc); + + // Builds a `HInstanceOf`, or a `HCheckCast` instruction. + // Returns whether we succeeded in building the instruction. + bool BuildTypeCheck(const Instruction& instruction, + uint8_t destination, + uint8_t reference, + uint16_t type_index, + uint32_t dex_pc); + + // Builds an instruction sequence for a packed switch statement. + void BuildPackedSwitch(const Instruction& instruction, uint32_t dex_pc); + + // Builds an instruction sequence for a sparse switch statement. + void BuildSparseSwitch(const Instruction& instruction, uint32_t dex_pc); + + void BuildSwitchCaseHelper(const Instruction& instruction, size_t index, + bool is_last_case, const SwitchTable& table, + HInstruction* value, int32_t case_value_int, + int32_t target_offset, uint32_t dex_pc); + + bool SkipCompilation(const DexFile::CodeItem& code_item, size_t number_of_branches); + + void MaybeRecordStat(MethodCompilationStat compilation_stat); + + // Returns the outer-most compiling method's class. + mirror::Class* GetOutermostCompilingClass() const; + + // Returns the class whose method is being compiled. + mirror::Class* GetCompilingClass() const; + + // Returns whether `type_index` points to the outer-most compiling method's class. + bool IsOutermostCompilingClass(uint16_t type_index) const; + ArenaAllocator* const arena_; // A list of the size of the dex code holding block information for @@ -119,15 +246,35 @@ class HGraphBuilder : public ValueObject { HBasicBlock* entry_block_; HBasicBlock* exit_block_; HBasicBlock* current_block_; - HGraph* graph_; - - HIntConstant* constant0_; - HIntConstant* constant1_; + HGraph* const graph_; + // The dex file where the method being compiled is. const DexFile* const dex_file_; + + // The compilation unit of the current method being compiled. Note that + // it can be an inlined method. DexCompilationUnit* const dex_compilation_unit_; + CompilerDriver* const compiler_driver_; + // The compilation unit of the outermost method being compiled. That is the + // method being compiled (and not inlined), and potentially inlining other + // methods. + const DexCompilationUnit* const outer_compilation_unit_; + + // The return type of the method being compiled. + const Primitive::Type return_type_; + + // The pointer in the dex file where the instructions of the code item + // being currently compiled start. + const uint16_t* code_start_; + + // The last invoke or fill-new-array being built. Only to be + // used by move-result instructions. + HInstruction* latest_result_; + + OptimizingCompilerStats* compilation_stats_; + DISALLOW_COPY_AND_ASSIGN(HGraphBuilder); }; |