diff options
Diffstat (limited to 'compiler/optimizing/builder.h')
-rw-r--r-- | compiler/optimizing/builder.h | 284 |
1 files changed, 241 insertions, 43 deletions
diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h index 4f46d5edda..50a13344df 100644 --- a/compiler/optimizing/builder.h +++ b/compiler/optimizing/builder.h @@ -24,14 +24,14 @@ #include "dex_file-inl.h" #include "driver/compiler_driver.h" #include "driver/dex_compilation_unit.h" -#include "instruction_builder.h" #include "optimizing_compiler_stats.h" #include "primitive.h" #include "nodes.h" -#include "ssa_builder.h" namespace art { +class Instruction; + class HGraphBuilder : public ValueObject { public: HGraphBuilder(HGraph* graph, @@ -42,65 +42,245 @@ class HGraphBuilder : public ValueObject { CompilerDriver* driver, OptimizingCompilerStats* compiler_stats, const uint8_t* interpreter_metadata, - Handle<mirror::DexCache> dex_cache, - StackHandleScopeCollection* handles) - : graph_(graph), + Handle<mirror::DexCache> dex_cache) + : arena_(graph->GetArena()), + locals_(graph->GetArena()->Adapter(kArenaAllocGraphBuilder)), + current_block_(nullptr), + graph_(graph), dex_file_(dex_file), code_item_(code_item), dex_compilation_unit_(dex_compilation_unit), compiler_driver_(driver), - compilation_stats_(compiler_stats), + outer_compilation_unit_(outer_compilation_unit), + return_type_(Primitive::GetType(dex_compilation_unit_->GetShorty()[0])), + code_start_(code_item.insns_), block_builder_(graph, dex_file, code_item), - ssa_builder_(graph, handles), - instruction_builder_(graph, - &block_builder_, - &ssa_builder_, - dex_file, - code_item_, - Primitive::GetType(dex_compilation_unit_->GetShorty()[0]), - dex_compilation_unit, - outer_compilation_unit, - driver, - interpreter_metadata, - compiler_stats, - dex_cache) {} + latest_result_(nullptr), + compilation_stats_(compiler_stats), + interpreter_metadata_(interpreter_metadata), + dex_cache_(dex_cache) {} // Only for unit testing. HGraphBuilder(HGraph* graph, const DexFile::CodeItem& code_item, - StackHandleScopeCollection* handles, Primitive::Type return_type = Primitive::kPrimInt) - : graph_(graph), + : arena_(graph->GetArena()), + locals_(graph->GetArena()->Adapter(kArenaAllocGraphBuilder)), + current_block_(nullptr), + graph_(graph), dex_file_(nullptr), code_item_(code_item), dex_compilation_unit_(nullptr), compiler_driver_(nullptr), - null_dex_cache_(), - compilation_stats_(nullptr), + outer_compilation_unit_(nullptr), + return_type_(return_type), + code_start_(code_item.insns_), block_builder_(graph, nullptr, code_item), - ssa_builder_(graph, handles), - instruction_builder_(graph, - &block_builder_, - &ssa_builder_, - /* dex_file */ nullptr, - code_item_, - return_type, - /* dex_compilation_unit */ nullptr, - /* outer_compilation_unit */ nullptr, - /* compiler_driver */ nullptr, - /* interpreter_metadata */ nullptr, - /* compiler_stats */ nullptr, - null_dex_cache_) {} - - GraphAnalysisResult BuildGraph(); + latest_result_(nullptr), + compilation_stats_(nullptr), + interpreter_metadata_(nullptr), + null_dex_cache_(), + dex_cache_(null_dex_cache_) {} + + GraphAnalysisResult BuildGraph(StackHandleScopeCollection* handles); static constexpr const char* kBuilderPassName = "builder"; private: - void MaybeRecordStat(MethodCompilationStat compilation_stat); + bool GenerateInstructions(); + bool AnalyzeDexInstruction(const Instruction& instruction, uint32_t dex_pc); + + void FindNativeDebugInfoLocations(ArenaBitVector* locations); + + bool CanDecodeQuickenedInfo() const; + uint16_t LookupQuickenedInfo(uint32_t dex_pc); + + HBasicBlock* FindBlockStartingAt(uint32_t dex_pc) const { + return block_builder_.GetBlockAt(dex_pc); + } + + void InitializeLocals(uint16_t count); + HLocal* GetLocalAt(uint32_t register_index) const; + void UpdateLocal(uint32_t register_index, HInstruction* instruction, uint32_t dex_pc) const; + HInstruction* LoadLocal(uint32_t register_index, Primitive::Type type, uint32_t dex_pc) const; + void InitializeParameters(uint16_t number_of_parameters); + + // Returns whether the current method needs access check for the type. + // Output parameter finalizable is set to whether the type is finalizable. + bool NeedsAccessCheck(uint32_t type_index, /*out*/bool* finalizable) const; + + template<typename T> + void Unop_12x(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc); + + 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, uint32_t dex_pc); + + void Binop_23x_cmp(const Instruction& instruction, + Primitive::Type type, + ComparisonBias bias, + uint32_t dex_pc); + + 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, uint32_t dex_pc); + + template<typename T> + void Binop_22b(const Instruction& instruction, bool reverse, uint32_t dex_pc); + + template<typename T> + void Binop_22s(const Instruction& instruction, bool reverse, uint32_t dex_pc); + + 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, uint32_t dex_pc); + + // 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); + + void BuildUnresolvedStaticFieldAccess(const Instruction& instruction, + uint32_t dex_pc, + bool is_put, + Primitive::Type field_type); + // 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_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_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. + void BuildTypeCheck(const Instruction& instruction, + uint8_t destination, + uint8_t reference, + uint16_t type_index, + uint32_t dex_pc); + + // Builds an instruction sequence for a switch statement. + void BuildSwitch(const Instruction& instruction, uint32_t dex_pc); + bool SkipCompilation(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; + + void PotentiallySimplifyFakeString(uint16_t original_dex_register, + uint32_t dex_pc, + HInvoke* invoke); + + bool SetupInvokeArguments(HInvoke* invoke, + uint32_t number_of_vreg_arguments, + uint32_t* args, + uint32_t register_index, + bool is_range, + const char* descriptor, + size_t start_index, + size_t* argument_index); + + bool HandleInvoke(HInvoke* invoke, + uint32_t number_of_vreg_arguments, + uint32_t* args, + uint32_t register_index, + bool is_range, + const char* descriptor, + HClinitCheck* clinit_check); + + bool HandleStringInit(HInvoke* invoke, + uint32_t number_of_vreg_arguments, + uint32_t* args, + uint32_t register_index, + bool is_range, + const char* descriptor); + + HClinitCheck* ProcessClinitCheckForInvoke( + uint32_t dex_pc, + ArtMethod* method, + uint32_t method_idx, + HInvokeStaticOrDirect::ClinitCheckRequirement* clinit_check_requirement) + SHARED_REQUIRES(Locks::mutator_lock_); + + // Build a HNewInstance instruction. + bool BuildNewInstance(uint16_t type_index, uint32_t dex_pc); + + // Return whether the compiler can assume `cls` is initialized. + bool IsInitialized(Handle<mirror::Class> cls) const + SHARED_REQUIRES(Locks::mutator_lock_); + + // Try to resolve a method using the class linker. Return null if a method could + // not be resolved. + ArtMethod* ResolveMethod(uint16_t method_idx, InvokeType invoke_type); + + ArenaAllocator* const arena_; + + ArenaVector<HLocal*> locals_; + + HBasicBlock* current_block_; HGraph* const graph_; + + // The dex file where the method being compiled is, and the bytecode data. const DexFile* const dex_file_; const DexFile::CodeItem& code_item_; @@ -110,13 +290,31 @@ class HGraphBuilder : public ValueObject { CompilerDriver* const compiler_driver_; - ScopedNullHandle<mirror::DexCache> null_dex_cache_; + // 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_; - OptimizingCompilerStats* compilation_stats_; + // 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_; HBasicBlockBuilder block_builder_; - SsaBuilder ssa_builder_; - HInstructionBuilder instruction_builder_; + + // The last invoke or fill-new-array being built. Only to be + // used by move-result instructions. + HInstruction* latest_result_; + + OptimizingCompilerStats* compilation_stats_; + + const uint8_t* interpreter_metadata_; + + // Dex cache for dex_file_. + ScopedNullHandle<mirror::DexCache> null_dex_cache_; + Handle<mirror::DexCache> dex_cache_; DISALLOW_COPY_AND_ASSIGN(HGraphBuilder); }; |