diff options
Diffstat (limited to 'compiler/optimizing/builder.h')
| -rw-r--r-- | compiler/optimizing/builder.h | 348 |
1 files changed, 51 insertions, 297 deletions
diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h index 48f5316222..4f46d5edda 100644 --- a/compiler/optimizing/builder.h +++ b/compiler/optimizing/builder.h @@ -19,320 +19,90 @@ #include "base/arena_containers.h" #include "base/arena_object.h" +#include "block_builder.h" #include "dex_file.h" #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, DexCompilationUnit* dex_compilation_unit, const DexCompilationUnit* const outer_compilation_unit, const DexFile* dex_file, + const DexFile::CodeItem& code_item, CompilerDriver* driver, OptimizingCompilerStats* compiler_stats, const uint8_t* interpreter_metadata, - Handle<mirror::DexCache> dex_cache) - : arena_(graph->GetArena()), - branch_targets_(graph->GetArena()->Adapter(kArenaAllocGraphBuilder)), - locals_(graph->GetArena()->Adapter(kArenaAllocGraphBuilder)), - entry_block_(nullptr), - exit_block_(nullptr), - current_block_(nullptr), - graph_(graph), + Handle<mirror::DexCache> dex_cache, + StackHandleScopeCollection* handles) + : graph_(graph), dex_file_(dex_file), + code_item_(code_item), dex_compilation_unit_(dex_compilation_unit), 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), - interpreter_metadata_(interpreter_metadata), - dex_cache_(dex_cache) {} + 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) {} // Only for unit testing. - HGraphBuilder(HGraph* graph, Primitive::Type return_type = Primitive::kPrimInt) - : arena_(graph->GetArena()), - branch_targets_(graph->GetArena()->Adapter(kArenaAllocGraphBuilder)), - locals_(graph->GetArena()->Adapter(kArenaAllocGraphBuilder)), - entry_block_(nullptr), - exit_block_(nullptr), - current_block_(nullptr), - graph_(graph), + HGraphBuilder(HGraph* graph, + const DexFile::CodeItem& code_item, + StackHandleScopeCollection* handles, + Primitive::Type return_type = Primitive::kPrimInt) + : graph_(graph), dex_file_(nullptr), + code_item_(code_item), dex_compilation_unit_(nullptr), compiler_driver_(nullptr), - outer_compilation_unit_(nullptr), - return_type_(return_type), - code_start_(nullptr), - latest_result_(nullptr), - compilation_stats_(nullptr), - interpreter_metadata_(nullptr), null_dex_cache_(), - dex_cache_(null_dex_cache_) {} - - GraphAnalysisResult BuildGraph(const DexFile::CodeItem& code, - StackHandleScopeCollection* handles); + compilation_stats_(nullptr), + 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(); static constexpr const char* kBuilderPassName = "builder"; - // The number of entries in a packed switch before we use a jump table or specified - // compare/jump series. - static constexpr uint16_t kSmallSwitchThreshold = 3; - 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, uint32_t dex_pc); - - // Finds all instructions that start a new block, and populates branch_targets_ with - // the newly created blocks. - // 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 dex_pc); - void FindNativeDebugInfoLocations(const DexFile::CodeItem& code_item, ArenaBitVector* locations); - HBasicBlock* FindBlockStartingAt(int32_t dex_pc) const; - HBasicBlock* FindOrCreateBlockStartingAt(int32_t dex_pc); - - // Adds new blocks to `branch_targets_` starting at the limits of TryItems and - // their exception handlers. - void CreateBlocksForTryCatch(const DexFile::CodeItem& code_item); - - // Splits edges which cross the boundaries of TryItems, inserts TryBoundary - // instructions and links them to the corresponding catch blocks. - void InsertTryBoundaryBlocks(const DexFile::CodeItem& code_item); - - // Iterates over the exception handlers of `try_item`, finds the corresponding - // catch blocks and makes them successors of `try_boundary`. The order of - // successors matches the order in which runtime exception delivery searches - // for a handler. - void LinkToCatchBlocks(HTryBoundary* try_boundary, - const DexFile::CodeItem& code_item, - const DexFile::TryItem* try_item); - - bool CanDecodeQuickenedInfo() const; - uint16_t LookupQuickenedInfo(uint32_t 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 packed switch statement. - void BuildPackedSwitch(const Instruction& instruction, uint32_t dex_pc); - - // Build a switch instruction from a packed switch statement. - void BuildSwitchJumpTable(const SwitchTable& table, - const Instruction& instruction, - HInstruction* value, - 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); + bool SkipCompilation(size_t number_of_branches); - // 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_; - - // A list of the size of the dex code holding block information for - // the method. If an entry contains a block, then the dex instruction - // starting at that entry is the first instruction of a new block. - ArenaVector<HBasicBlock*> branch_targets_; - - ArenaVector<HLocal*> locals_; - - HBasicBlock* entry_block_; - HBasicBlock* exit_block_; - HBasicBlock* current_block_; HGraph* const graph_; - - // The dex file where the method being compiled is. const DexFile* const dex_file_; + const DexFile::CodeItem& code_item_; // The compilation unit of the current method being compiled. Note that // it can be an inlined method. @@ -340,29 +110,13 @@ class HGraphBuilder : public ValueObject { 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_; + ScopedNullHandle<mirror::DexCache> null_dex_cache_; OptimizingCompilerStats* compilation_stats_; - const uint8_t* interpreter_metadata_; - - // Dex cache for dex_file_. - ScopedNullHandle<mirror::DexCache> null_dex_cache_; - Handle<mirror::DexCache> dex_cache_; + HBasicBlockBuilder block_builder_; + SsaBuilder ssa_builder_; + HInstructionBuilder instruction_builder_; DISALLOW_COPY_AND_ASSIGN(HGraphBuilder); }; |