From 8d0d03e24325463f0060abfd05dba5598044e9b1 Mon Sep 17 00:00:00 2001 From: Razvan A Lupusoru Date: Fri, 6 Jun 2014 17:04:52 -0700 Subject: ART: Change temporaries to positive names Changes compiler temporaries to have positive names. The numbering now puts them above the code VRs (locals + ins, in that order). The patch also introduces APIs to query the number of temporaries, locals and ins. The compiler temp infrastructure suffered from several issues which are also addressed by this patch: -There is no longer a queue of compiler temps. This would be polluted with Method* when post opts were called multiple times. -Sanity checks have been added to allow requesting of temps from BE and to prevent temps after frame is committed. -None of the structures holding temps can overflow because they are allocated to allow holding maximum temps. Thus temps can be requested by BE with no problem. -Since the queue of compiler temps is no longer maintained, it is no longer possible to refer to a temp that has invalid ssa (because it was requested before ssa was run). -The BE can now request temps after all ME allocations and it is guaranteed to actually receive them. -ME temps are now treated like normal VRs in all cases with no special handling. Only the BE temps are handled specially because there are no references to them from MIRs. -Deprecated and removed several fields in CompilationUnit that saved register information and updated callsites to call the new interface from MIRGraph. Change-Id: Ia8b1fec9384a1a83017800a59e5b0498dfb2698c Signed-off-by: Razvan A Lupusoru Signed-off-by: Udayan Banerji --- compiler/dex/compiler_ir.cc | 5 - compiler/dex/compiler_ir.h | 6 - compiler/dex/frontend.cc | 2 - compiler/dex/global_value_numbering.cc | 2 +- compiler/dex/global_value_numbering_test.cc | 4 + compiler/dex/mir_dataflow.cc | 39 +++--- compiler/dex/mir_graph.cc | 33 ++++-- compiler/dex/mir_graph.h | 141 +++++++++++++++++----- compiler/dex/mir_graph_test.cc | 4 + compiler/dex/mir_optimization.cc | 176 ++++++++++++++++++++-------- compiler/dex/portable/mir_to_gbc.cc | 24 ++-- compiler/dex/portable/mir_to_gbc.h | 4 +- compiler/dex/quick/arm/call_arm.cc | 8 +- compiler/dex/quick/arm/codegen_arm.h | 2 +- compiler/dex/quick/arm64/call_arm64.cc | 8 +- compiler/dex/quick/arm64/codegen_arm64.h | 2 +- compiler/dex/quick/arm64/target_arm64.cc | 13 +- compiler/dex/quick/codegen_util.cc | 23 ++-- compiler/dex/quick/gen_common.cc | 8 +- compiler/dex/quick/gen_invoke.cc | 9 +- compiler/dex/quick/mips/call_mips.cc | 8 +- compiler/dex/quick/mips/codegen_mips.h | 2 +- compiler/dex/quick/mir_to_lir.cc | 7 +- compiler/dex/quick/mir_to_lir.h | 2 +- compiler/dex/quick/quick_compiler.cc | 4 +- compiler/dex/quick/ralloc_util.cc | 27 +---- compiler/dex/quick/x86/call_x86.cc | 8 +- compiler/dex/quick/x86/codegen_x86.h | 2 +- compiler/dex/quick/x86/target_x86.cc | 13 +- compiler/dex/quick/x86/utility_x86.cc | 3 +- compiler/dex/quick/x86/x86_lir.h | 55 +++++---- compiler/dex/ssa_transformation.cc | 15 +-- compiler/dex/vreg_analysis.cc | 30 ++--- 33 files changed, 417 insertions(+), 272 deletions(-) (limited to 'compiler') diff --git a/compiler/dex/compiler_ir.cc b/compiler/dex/compiler_ir.cc index e1d489a051..ce48eb22b0 100644 --- a/compiler/dex/compiler_ir.cc +++ b/compiler/dex/compiler_ir.cc @@ -39,11 +39,6 @@ CompilationUnit::CompilationUnit(ArenaPool* pool) compiler(nullptr), instruction_set(kNone), target64(false), - num_dalvik_registers(0), - insns(nullptr), - num_ins(0), - num_outs(0), - num_regs(0), compiler_flip_match(false), arena(pool), arena_stack(pool), diff --git a/compiler/dex/compiler_ir.h b/compiler/dex/compiler_ir.h index b20840adbc..c4e43fdf2c 100644 --- a/compiler/dex/compiler_ir.h +++ b/compiler/dex/compiler_ir.h @@ -72,12 +72,6 @@ struct CompilationUnit { InstructionSetFeatures GetInstructionSetFeatures() { return compiler_driver->GetInstructionSetFeatures(); } - // TODO: much of this info available elsewhere. Go to the original source? - uint16_t num_dalvik_registers; // method->registers_size. - const uint16_t* insns; - uint16_t num_ins; - uint16_t num_outs; - uint16_t num_regs; // Unlike num_dalvik_registers, does not include ins. // If non-empty, apply optimizer/debug flags only to matching methods. std::string compiler_method_match; diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc index 078ddf1bea..b267841fde 100644 --- a/compiler/dex/frontend.cc +++ b/compiler/dex/frontend.cc @@ -110,8 +110,6 @@ static CompiledMethod* CompileMethod(CompilerDriver& driver, (cu.instruction_set == kX86_64) || (cu.instruction_set == kMips)); - /* Adjust this value accordingly once inlining is performed */ - cu.num_dalvik_registers = code_item->registers_size_; // TODO: set this from command line cu.compiler_flip_match = false; bool use_match = !cu.compiler_method_match.empty(); diff --git a/compiler/dex/global_value_numbering.cc b/compiler/dex/global_value_numbering.cc index 3575adeac5..4d885fd5ba 100644 --- a/compiler/dex/global_value_numbering.cc +++ b/compiler/dex/global_value_numbering.cc @@ -70,7 +70,7 @@ LocalValueNumbering* GlobalValueNumbering::PrepareBasicBlock(BasicBlock* bb, if (bb->block_type == kEntryBlock) { if ((cu_->access_flags & kAccStatic) == 0) { // If non-static method, mark "this" as non-null - int this_reg = cu_->num_dalvik_registers - cu_->num_ins; + int this_reg = cu_->mir_graph->GetFirstInVR(); uint16_t value_name = work_lvn_->GetSRegValueName(this_reg); work_lvn_->SetValueNameNullChecked(value_name); } diff --git a/compiler/dex/global_value_numbering_test.cc b/compiler/dex/global_value_numbering_test.cc index e8501cd405..1c0de37ca2 100644 --- a/compiler/dex/global_value_numbering_test.cc +++ b/compiler/dex/global_value_numbering_test.cc @@ -266,6 +266,10 @@ class GlobalValueNumberingTest : public testing::Test { mir->optimization_flags = 0u; } mirs_[count - 1u].next = nullptr; + DexFile::CodeItem* code_item = static_cast( + cu_.arena.Alloc(sizeof(DexFile::CodeItem), kArenaAllocMisc)); + code_item->insns_size_in_code_units_ = 2u * count; + cu_.mir_graph->current_code_item_ = cu_.code_item = code_item; } template diff --git a/compiler/dex/mir_dataflow.cc b/compiler/dex/mir_dataflow.cc index a964cc720f..4c906b01d7 100644 --- a/compiler/dex/mir_dataflow.cc +++ b/compiler/dex/mir_dataflow.cc @@ -933,11 +933,11 @@ bool MIRGraph::FindLocalLiveIn(BasicBlock* bb) { if (bb->data_flow_info == NULL) return false; use_v = bb->data_flow_info->use_v = - new (arena_) ArenaBitVector(arena_, cu_->num_dalvik_registers, false, kBitMapUse); + new (arena_) ArenaBitVector(arena_, GetNumOfCodeAndTempVRs(), false, kBitMapUse); def_v = bb->data_flow_info->def_v = - new (arena_) ArenaBitVector(arena_, cu_->num_dalvik_registers, false, kBitMapDef); + new (arena_) ArenaBitVector(arena_, GetNumOfCodeAndTempVRs(), false, kBitMapDef); live_in_v = bb->data_flow_info->live_in_v = - new (arena_) ArenaBitVector(arena_, cu_->num_dalvik_registers, false, kBitMapLiveIn); + new (arena_) ArenaBitVector(arena_, GetNumOfCodeAndTempVRs(), false, kBitMapLiveIn); for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) { uint64_t df_attributes = GetDataFlowAttributes(mir); @@ -987,8 +987,7 @@ bool MIRGraph::FindLocalLiveIn(BasicBlock* bb) { } int MIRGraph::AddNewSReg(int v_reg) { - // Compiler temps always have a subscript of 0 - int subscript = (v_reg < 0) ? 0 : ++ssa_last_defs_[v_reg]; + int subscript = ++ssa_last_defs_[v_reg]; uint32_t ssa_reg = GetNumSSARegs(); SetNumSSARegs(ssa_reg + 1); ssa_base_vregs_->Insert(v_reg); @@ -1005,13 +1004,13 @@ int MIRGraph::AddNewSReg(int v_reg) { /* Find out the latest SSA register for a given Dalvik register */ void MIRGraph::HandleSSAUse(int* uses, int dalvik_reg, int reg_index) { - DCHECK((dalvik_reg >= 0) && (dalvik_reg < cu_->num_dalvik_registers)); + DCHECK((dalvik_reg >= 0) && (dalvik_reg < static_cast(GetNumOfCodeAndTempVRs()))); uses[reg_index] = vreg_to_ssa_map_[dalvik_reg]; } /* Setup a new SSA register for a given Dalvik register */ void MIRGraph::HandleSSADef(int* defs, int dalvik_reg, int reg_index) { - DCHECK((dalvik_reg >= 0) && (dalvik_reg < cu_->num_dalvik_registers)); + DCHECK((dalvik_reg >= 0) && (dalvik_reg < static_cast(GetNumOfCodeAndTempVRs()))); int ssa_reg = AddNewSReg(dalvik_reg); vreg_to_ssa_map_[dalvik_reg] = ssa_reg; defs[reg_index] = ssa_reg; @@ -1191,34 +1190,34 @@ bool MIRGraph::DoSSAConversion(BasicBlock* bb) { * predecessor blocks. */ bb->data_flow_info->vreg_to_ssa_map_exit = - static_cast(arena_->Alloc(sizeof(int) * cu_->num_dalvik_registers, + static_cast(arena_->Alloc(sizeof(int) * GetNumOfCodeAndTempVRs(), kArenaAllocDFInfo)); memcpy(bb->data_flow_info->vreg_to_ssa_map_exit, vreg_to_ssa_map_, - sizeof(int) * cu_->num_dalvik_registers); + sizeof(int) * GetNumOfCodeAndTempVRs()); return true; } /* Setup the basic data structures for SSA conversion */ void MIRGraph::CompilerInitializeSSAConversion() { - size_t num_dalvik_reg = cu_->num_dalvik_registers; + size_t num_reg = GetNumOfCodeAndTempVRs(); - ssa_base_vregs_ = new (arena_) GrowableArray(arena_, num_dalvik_reg + GetDefCount() + 128, + ssa_base_vregs_ = new (arena_) GrowableArray(arena_, num_reg + GetDefCount() + 128, kGrowableArraySSAtoDalvikMap); - ssa_subscripts_ = new (arena_) GrowableArray(arena_, num_dalvik_reg + GetDefCount() + 128, + ssa_subscripts_ = new (arena_) GrowableArray(arena_, num_reg + GetDefCount() + 128, kGrowableArraySSAtoDalvikMap); /* * Initial number of SSA registers is equal to the number of Dalvik * registers. */ - SetNumSSARegs(num_dalvik_reg); + SetNumSSARegs(num_reg); /* - * Initialize the SSA2Dalvik map list. For the first num_dalvik_reg elements, + * Initialize the SSA2Dalvik map list. For the first num_reg elements, * the subscript is 0 so we use the ENCODE_REG_SUB macro to encode the value * into "(0 << 16) | i" */ - for (unsigned int i = 0; i < num_dalvik_reg; i++) { + for (unsigned int i = 0; i < num_reg; i++) { ssa_base_vregs_->Insert(i); ssa_subscripts_->Insert(0); } @@ -1228,20 +1227,22 @@ void MIRGraph::CompilerInitializeSSAConversion() { * Dalvik register, and the SSA names for those are the same. */ vreg_to_ssa_map_ = - static_cast(arena_->Alloc(sizeof(int) * num_dalvik_reg, + static_cast(arena_->Alloc(sizeof(int) * num_reg, kArenaAllocDFInfo)); /* Keep track of the higest def for each dalvik reg */ ssa_last_defs_ = - static_cast(arena_->Alloc(sizeof(int) * num_dalvik_reg, + static_cast(arena_->Alloc(sizeof(int) * num_reg, kArenaAllocDFInfo)); - for (unsigned int i = 0; i < num_dalvik_reg; i++) { + for (unsigned int i = 0; i < num_reg; i++) { vreg_to_ssa_map_[i] = i; ssa_last_defs_[i] = 0; } // Create a compiler temporary for Method*. This is done after SSA initialization. - GetNewCompilerTemp(kCompilerTempSpecialMethodPtr, false); + CompilerTemp* method_temp = GetNewCompilerTemp(kCompilerTempSpecialMethodPtr, false); + // The MIR graph keeps track of the sreg for method pointer specially, so record that now. + method_sreg_ = method_temp->s_reg_low; /* * Allocate the BasicBlockDataFlow structure for the entry and code blocks diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc index 49e5c7682c..462e129c87 100644 --- a/compiler/dex/mir_graph.cc +++ b/compiler/dex/mir_graph.cc @@ -119,9 +119,10 @@ MIRGraph::MIRGraph(CompilationUnit* cu, ArenaAllocator* arena) arena_(arena), backward_branches_(0), forward_branches_(0), - compiler_temps_(arena, 6, kGrowableArrayMisc), num_non_special_compiler_temps_(0), - max_available_non_special_compiler_temps_(0), + max_available_special_compiler_temps_(1), // We only need the method ptr as a special temp for now. + requested_backend_temp_(false), + compiler_temps_committed_(false), punt_to_interpreter_(false), merged_df_flags_(0u), ifield_lowering_infos_(arena, 0u), @@ -129,8 +130,20 @@ MIRGraph::MIRGraph(CompilationUnit* cu, ArenaAllocator* arena) method_lowering_infos_(arena, 0u), gen_suspend_test_list_(arena, 0u) { try_block_addr_ = new (arena_) ArenaBitVector(arena_, 0, true /* expandable */); - max_available_special_compiler_temps_ = std::abs(static_cast(kVRegNonSpecialTempBaseReg)) - - std::abs(static_cast(kVRegTempBaseReg)); + + + if (cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64) { + // X86 requires a temp to keep track of the method address. + // TODO For x86_64, addressing can be done with RIP. When that is implemented, + // this needs to be updated to reserve 0 temps for BE. + max_available_non_special_compiler_temps_ = cu_->target64 ? 2 : 1; + reserved_temps_for_backend_ = max_available_non_special_compiler_temps_; + } else { + // Other architectures do not have a known lower bound for non-special temps. + // We allow the update of the max to happen at BE initialization stage and simply set 0 for now. + max_available_non_special_compiler_temps_ = 0; + reserved_temps_for_backend_ = 0; + } } MIRGraph::~MIRGraph() { @@ -702,11 +715,6 @@ void MIRGraph::InlineMethod(const DexFile::CodeItem* code_item, uint32_t access_ cu_->access_flags = access_flags; cu_->invoke_type = invoke_type; cu_->shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx)); - cu_->num_ins = current_code_item_->ins_size_; - cu_->num_regs = current_code_item_->registers_size_ - cu_->num_ins; - cu_->num_outs = current_code_item_->outs_size_; - cu_->num_dalvik_registers = current_code_item_->registers_size_; - cu_->insns = current_code_item_->insns_; cu_->code_item = current_code_item_; } else { UNIMPLEMENTED(FATAL) << "Nested inlining not implemented."; @@ -1429,7 +1437,7 @@ void MIRGraph::DumpMIRGraph() { }; LOG(INFO) << "Compiling " << PrettyMethod(cu_->method_idx, *cu_->dex_file); - LOG(INFO) << cu_->insns << " insns"; + LOG(INFO) << GetInsns(0) << " insns"; LOG(INFO) << GetNumBlocks() << " blocks in total"; GrowableArray::Iterator iterator(&block_list_); @@ -1516,6 +1524,9 @@ void MIRGraph::InitializeMethodUses() { int num_ssa_regs = GetNumSSARegs(); use_counts_.Resize(num_ssa_regs + 32); raw_use_counts_.Resize(num_ssa_regs + 32); + // Resize does not actually reset the number of used, so reset before initialization. + use_counts_.Reset(); + raw_use_counts_.Reset(); // Initialize list. for (int i = 0; i < num_ssa_regs; i++) { use_counts_.Insert(0); @@ -1526,7 +1537,7 @@ void MIRGraph::InitializeMethodUses() { void MIRGraph::SSATransformationStart() { DCHECK(temp_scoped_alloc_.get() == nullptr); temp_scoped_alloc_.reset(ScopedArenaAllocator::Create(&cu_->arena_stack)); - temp_bit_vector_size_ = cu_->num_dalvik_registers; + temp_bit_vector_size_ = GetNumOfCodeAndTempVRs(); temp_bit_vector_ = new (temp_scoped_alloc_.get()) ArenaBitVector( temp_scoped_alloc_.get(), temp_bit_vector_size_, false, kBitMapRegisterV); diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h index 2943b9d9b3..8d46c6d15f 100644 --- a/compiler/dex/mir_graph.h +++ b/compiler/dex/mir_graph.h @@ -217,6 +217,7 @@ struct CompilerTemp { enum CompilerTempType { kCompilerTempVR, // A virtual register temporary. kCompilerTempSpecialMethodPtr, // Temporary that keeps track of current method pointer. + kCompilerTempBackend, // Temporary that is used by backend. }; // When debug option enabled, records effectiveness of null and range check elimination. @@ -573,10 +574,26 @@ class MIRGraph { return current_code_item_->insns_; } + /** + * @brief Used to obtain the raw dex bytecode instruction pointer. + * @param m_unit_index The method index in MIRGraph (caused by having multiple methods). + * This is guaranteed to contain index 0 which is the base method being compiled. + * @return Returns the raw instruction pointer. + */ const uint16_t* GetInsns(int m_unit_index) const { return m_units_[m_unit_index]->GetCodeItem()->insns_; } + /** + * @brief Used to obtain the raw data table. + * @param mir sparse switch, packed switch, of fill-array-data + * @param table_offset The table offset from start of method. + * @return Returns the raw table pointer. + */ + const uint16_t* GetTable(MIR* mir, uint32_t table_offset) const { + return GetInsns(mir->m_unit_index) + mir->offset + table_offset; + } + unsigned int GetNumBlocks() const { return num_blocks_; } @@ -783,12 +800,12 @@ class MIRGraph { return num_reachable_blocks_; } - int GetUseCount(int vreg) const { - return use_counts_.Get(vreg); + int GetUseCount(int sreg) const { + return use_counts_.Get(sreg); } - int GetRawUseCount(int vreg) const { - return raw_use_counts_.Get(vreg); + int GetRawUseCount(int sreg) const { + return raw_use_counts_.Get(sreg); } int GetSSASubscript(int ssa_reg) const { @@ -844,9 +861,26 @@ class MIRGraph { * @return Returns the number of compiler temporaries. */ size_t GetNumUsedCompilerTemps() const { - size_t total_num_temps = compiler_temps_.Size(); - DCHECK_LE(num_non_special_compiler_temps_, total_num_temps); - return total_num_temps; + // Assume that the special temps will always be used. + return GetNumNonSpecialCompilerTemps() + max_available_special_compiler_temps_; + } + + /** + * @brief Used to obtain number of bytes needed for special temps. + * @details This space is always needed because temps have special location on stack. + * @return Returns number of bytes for the special temps. + */ + size_t GetNumBytesForSpecialTemps() const; + + /** + * @brief Used by backend as a hint for maximum number of bytes for non-special temps. + * @details Returns 4 bytes for each temp because that is the maximum amount needed + * for storing each temp. The BE could be smarter though and allocate a smaller + * spill region. + * @return Returns the maximum number of bytes needed for non-special temps. + */ + size_t GetMaximumBytesForNonSpecialTemps() const { + return GetNumNonSpecialCompilerTemps() * sizeof(uint32_t); } /** @@ -864,7 +898,9 @@ class MIRGraph { * @return Returns true if the max was set and false if failed to set. */ bool SetMaxAvailableNonSpecialCompilerTemps(size_t new_max) { - if (new_max < GetNumNonSpecialCompilerTemps()) { + // Make sure that enough temps still exist for backend and also that the + // new max can still keep around all of the already requested temps. + if (new_max < (GetNumNonSpecialCompilerTemps() + reserved_temps_for_backend_)) { return false; } else { max_available_non_special_compiler_temps_ = new_max; @@ -873,21 +909,12 @@ class MIRGraph { } /** - * @brief Provides the number of non-special compiler temps available. + * @brief Provides the number of non-special compiler temps available for use by ME. * @details Even if this returns zero, special compiler temps are guaranteed to be available. + * Additionally, this makes sure to not use any temps reserved for BE only. * @return Returns the number of available temps. */ - size_t GetNumAvailableNonSpecialCompilerTemps(); - - /** - * @brief Used to obtain an existing compiler temporary. - * @param index The index of the temporary which must be strictly less than the - * number of temporaries. - * @return Returns the temporary that was asked for. - */ - CompilerTemp* GetCompilerTemp(size_t index) const { - return compiler_temps_.Get(index); - } + size_t GetNumAvailableVRTemps(); /** * @brief Used to obtain the maximum number of compiler temporaries that can be requested. @@ -897,8 +924,23 @@ class MIRGraph { return max_available_special_compiler_temps_ + max_available_non_special_compiler_temps_; } + /** + * @brief Used to signal that the compiler temps have been committed. + * @details This should be used once the number of temps can no longer change, + * such as after frame size is committed and cannot be changed. + */ + void CommitCompilerTemps() { + compiler_temps_committed_ = true; + } + /** * @brief Used to obtain a new unique compiler temporary. + * @details Two things are done for convenience when allocating a new compiler + * temporary. The ssa register is automatically requested and the information + * about reg location is filled. This helps when the temp is requested post + * ssa initialization, such as when temps are requested by the backend. + * @warning If the temp requested will be used for ME and have multiple versions, + * the sreg provided by the temp will be invalidated on next ssa recalculation. * @param ct_type Type of compiler temporary requested. * @param wide Whether we should allocate a wide temporary. * @return Returns the newly created compiler temporary. @@ -940,8 +982,49 @@ class MIRGraph { } // Is this vreg in the in set? - bool IsInVReg(int vreg) { - return (vreg >= cu_->num_regs); + bool IsInVReg(uint32_t vreg) { + return (vreg >= GetFirstInVR()) && (vreg < GetFirstTempVR()); + } + + uint32_t GetNumOfCodeVRs() const { + return current_code_item_->registers_size_; + } + + uint32_t GetNumOfCodeAndTempVRs() const { + // Include all of the possible temps so that no structures overflow when initialized. + return GetNumOfCodeVRs() + GetMaxPossibleCompilerTemps(); + } + + uint32_t GetNumOfLocalCodeVRs() const { + // This also refers to the first "in" VR. + return GetNumOfCodeVRs() - current_code_item_->ins_size_; + } + + uint32_t GetNumOfInVRs() const { + return current_code_item_->ins_size_; + } + + uint32_t GetNumOfOutVRs() const { + return current_code_item_->outs_size_; + } + + uint32_t GetFirstInVR() const { + return GetNumOfLocalCodeVRs(); + } + + uint32_t GetFirstTempVR() const { + // Temp VRs immediately follow code VRs. + return GetNumOfCodeVRs(); + } + + uint32_t GetFirstSpecialTempVR() const { + // Special temps appear first in the ordering before non special temps. + return GetFirstTempVR(); + } + + uint32_t GetFirstNonSpecialTempVR() const { + // We always leave space for all the special temps before the non-special ones. + return GetFirstSpecialTempVR() + max_available_special_compiler_temps_; } void DumpCheckStats(); @@ -1187,7 +1270,7 @@ class MIRGraph { // Stack of the loop head indexes and recalculation flags for RepeatingTopologicalSortIterator. GrowableArray>* topological_order_loop_head_stack_; int* i_dom_list_; - ArenaBitVector** def_block_matrix_; // num_dalvik_register x num_blocks. + ArenaBitVector** def_block_matrix_; // original num registers x num_blocks. std::unique_ptr temp_scoped_alloc_; uint16_t* temp_insn_data_; uint32_t temp_bit_vector_size_; @@ -1216,11 +1299,13 @@ class MIRGraph { ArenaAllocator* arena_; int backward_branches_; int forward_branches_; - GrowableArray compiler_temps_; - size_t num_non_special_compiler_temps_; - size_t max_available_non_special_compiler_temps_; - size_t max_available_special_compiler_temps_; - bool punt_to_interpreter_; // Difficult or not worthwhile - just interpret. + size_t num_non_special_compiler_temps_; // Keeps track of allocated non-special compiler temps. These are VRs that are in compiler temp region on stack. + size_t max_available_non_special_compiler_temps_; // Keeps track of maximum available non-special temps. + size_t max_available_special_compiler_temps_; // Keeps track of maximum available special temps. + bool requested_backend_temp_; // Keeps track whether BE temps have been requested. + size_t reserved_temps_for_backend_; // Keeps track of the remaining temps that are reserved for BE. + bool compiler_temps_committed_; // Keeps track whether number of temps has been frozen (for example post frame size calculation). + bool punt_to_interpreter_; // Difficult or not worthwhile - just interpret. uint64_t merged_df_flags_; GrowableArray ifield_lowering_infos_; GrowableArray sfield_lowering_infos_; diff --git a/compiler/dex/mir_graph_test.cc b/compiler/dex/mir_graph_test.cc index 932f453b3c..bdc05a968e 100644 --- a/compiler/dex/mir_graph_test.cc +++ b/compiler/dex/mir_graph_test.cc @@ -103,6 +103,10 @@ class TopologicalSortOrderTest : public testing::Test { ASSERT_EQ(kEntryBlock, cu_.mir_graph->entry_block_->block_type); cu_.mir_graph->exit_block_ = cu_.mir_graph->block_list_.Get(2); ASSERT_EQ(kExitBlock, cu_.mir_graph->exit_block_->block_type); + + DexFile::CodeItem* code_item = static_cast(cu_.arena.Alloc(sizeof(DexFile::CodeItem), + kArenaAllocMisc)); + cu_.mir_graph->current_code_item_ = cu_.code_item = code_item; } template diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc index 8195d0efb6..5d7cbed7e6 100644 --- a/compiler/dex/mir_optimization.cc +++ b/compiler/dex/mir_optimization.cc @@ -233,27 +233,59 @@ int MIRGraph::GetSSAUseCount(int s_reg) { return raw_use_counts_.Get(s_reg); } -size_t MIRGraph::GetNumAvailableNonSpecialCompilerTemps() { - if (num_non_special_compiler_temps_ >= max_available_non_special_compiler_temps_) { +size_t MIRGraph::GetNumBytesForSpecialTemps() const { + // This logic is written with assumption that Method* is only special temp. + DCHECK_EQ(max_available_special_compiler_temps_, 1u); + return sizeof(StackReference); +} + +size_t MIRGraph::GetNumAvailableVRTemps() { + // First take into account all temps reserved for backend. + if (max_available_non_special_compiler_temps_ < reserved_temps_for_backend_) { + return 0; + } + + // Calculate remaining ME temps available. + size_t remaining_me_temps = max_available_non_special_compiler_temps_ - reserved_temps_for_backend_; + + if (num_non_special_compiler_temps_ >= remaining_me_temps) { return 0; } else { - return max_available_non_special_compiler_temps_ - num_non_special_compiler_temps_; + return remaining_me_temps - num_non_special_compiler_temps_; } } - // FIXME - will probably need to revisit all uses of this, as type not defined. static const RegLocation temp_loc = {kLocCompilerTemp, 0, 1 /*defined*/, 0, 0, 0, 0, 0, 1 /*home*/, RegStorage(), INVALID_SREG, INVALID_SREG}; CompilerTemp* MIRGraph::GetNewCompilerTemp(CompilerTempType ct_type, bool wide) { - // There is a limit to the number of non-special temps so check to make sure it wasn't exceeded. - if (ct_type == kCompilerTempVR) { - size_t available_temps = GetNumAvailableNonSpecialCompilerTemps(); - if (available_temps <= 0 || (available_temps <= 1 && wide)) { - return 0; + // Once the compiler temps have been committed, new ones cannot be requested anymore. + DCHECK_EQ(compiler_temps_committed_, false); + // Make sure that reserved for BE set is sane. + DCHECK_LE(reserved_temps_for_backend_, max_available_non_special_compiler_temps_); + + bool verbose = cu_->verbose; + const char* ct_type_str = nullptr; + + if (verbose) { + switch (ct_type) { + case kCompilerTempBackend: + ct_type_str = "backend"; + break; + case kCompilerTempSpecialMethodPtr: + ct_type_str = "method*"; + break; + case kCompilerTempVR: + ct_type_str = "VR"; + break; + default: + ct_type_str = "unknown"; + break; } + LOG(INFO) << "CompilerTemps: A compiler temp of type " << ct_type_str << " that is " + << (wide ? "wide is being requested." : "not wide is being requested."); } CompilerTemp *compiler_temp = static_cast(arena_->Alloc(sizeof(CompilerTemp), @@ -262,51 +294,100 @@ CompilerTemp* MIRGraph::GetNewCompilerTemp(CompilerTempType ct_type, bool wide) // Create the type of temp requested. Special temps need special handling because // they have a specific virtual register assignment. if (ct_type == kCompilerTempSpecialMethodPtr) { + // This has a special location on stack which is 32-bit or 64-bit depending + // on mode. However, we don't want to overlap with non-special section + // and thus even for 64-bit, we allow only a non-wide temp to be requested. DCHECK_EQ(wide, false); - compiler_temp->v_reg = static_cast(kVRegMethodPtrBaseReg); - compiler_temp->s_reg_low = AddNewSReg(compiler_temp->v_reg); - // The MIR graph keeps track of the sreg for method pointer specially, so record that now. - method_sreg_ = compiler_temp->s_reg_low; + // The vreg is always the first special temp for method ptr. + compiler_temp->v_reg = GetFirstSpecialTempVR(); + + } else if (ct_type == kCompilerTempBackend) { + requested_backend_temp_ = true; + + // Make sure that we are not exceeding temps reserved for BE. + // Since VR temps cannot be requested once the BE temps are requested, we + // allow reservation of VR temps as well for BE. We + size_t available_temps = reserved_temps_for_backend_ + GetNumAvailableVRTemps(); + if (available_temps <= 0 || (available_temps <= 1 && wide)) { + if (verbose) { + LOG(INFO) << "CompilerTemps: Not enough temp(s) of type " << ct_type_str << " are available."; + } + return nullptr; + } + + // Update the remaining reserved temps since we have now used them. + // Note that the code below is actually subtracting to remove them from reserve + // once they have been claimed. It is careful to not go below zero. + if (reserved_temps_for_backend_ >= 1) { + reserved_temps_for_backend_--; + } + if (wide && reserved_temps_for_backend_ >= 1) { + reserved_temps_for_backend_--; + } + + // The new non-special compiler temp must receive a unique v_reg. + compiler_temp->v_reg = GetFirstNonSpecialTempVR() + num_non_special_compiler_temps_; + num_non_special_compiler_temps_++; + } else if (ct_type == kCompilerTempVR) { + // Once we start giving out BE temps, we don't allow anymore ME temps to be requested. + // This is done in order to prevent problems with ssa since these structures are allocated + // and managed by the ME. + DCHECK_EQ(requested_backend_temp_, false); + + // There is a limit to the number of non-special temps so check to make sure it wasn't exceeded. + size_t available_temps = GetNumAvailableVRTemps(); + if (available_temps <= 0 || (available_temps <= 1 && wide)) { + if (verbose) { + LOG(INFO) << "CompilerTemps: Not enough temp(s) of type " << ct_type_str << " are available."; + } + return nullptr; + } + + // The new non-special compiler temp must receive a unique v_reg. + compiler_temp->v_reg = GetFirstNonSpecialTempVR() + num_non_special_compiler_temps_; + num_non_special_compiler_temps_++; } else { - DCHECK_EQ(ct_type, kCompilerTempVR); + UNIMPLEMENTED(FATAL) << "No handling for compiler temp type " << ct_type_str << "."; + } + + // We allocate an sreg as well to make developer life easier. + // However, if this is requested from an ME pass that will recalculate ssa afterwards, + // this sreg is no longer valid. The caller should be aware of this. + compiler_temp->s_reg_low = AddNewSReg(compiler_temp->v_reg); + + if (verbose) { + LOG(INFO) << "CompilerTemps: New temp of type " << ct_type_str << " with v" << compiler_temp->v_reg + << " and s" << compiler_temp->s_reg_low << " has been created."; + } - // The new non-special compiler temp must receive a unique v_reg with a negative value. - compiler_temp->v_reg = static_cast(kVRegNonSpecialTempBaseReg) - - num_non_special_compiler_temps_; - compiler_temp->s_reg_low = AddNewSReg(compiler_temp->v_reg); + if (wide) { + // Only non-special temps are handled as wide for now. + // Note that the number of non special temps is incremented below. + DCHECK(ct_type == kCompilerTempBackend || ct_type == kCompilerTempVR); + + // Ensure that the two registers are consecutive. + int ssa_reg_low = compiler_temp->s_reg_low; + int ssa_reg_high = AddNewSReg(compiler_temp->v_reg + 1); num_non_special_compiler_temps_++; - if (wide) { - // Create a new CompilerTemp for the high part. - CompilerTemp *compiler_temp_high = - static_cast(arena_->Alloc(sizeof(CompilerTemp), kArenaAllocRegAlloc)); - compiler_temp_high->v_reg = compiler_temp->v_reg; - compiler_temp_high->s_reg_low = compiler_temp->s_reg_low; - compiler_temps_.Insert(compiler_temp_high); - - // Ensure that the two registers are consecutive. Since the virtual registers used for temps - // grow in a negative fashion, we need the smaller to refer to the low part. Thus, we - // redefine the v_reg and s_reg_low. - compiler_temp->v_reg--; - int ssa_reg_high = compiler_temp->s_reg_low; - compiler_temp->s_reg_low = AddNewSReg(compiler_temp->v_reg); - int ssa_reg_low = compiler_temp->s_reg_low; - - // If needed initialize the register location for the high part. - // The low part is handled later in this method on a common path. - if (reg_location_ != nullptr) { - reg_location_[ssa_reg_high] = temp_loc; - reg_location_[ssa_reg_high].high_word = 1; - reg_location_[ssa_reg_high].s_reg_low = ssa_reg_low; - reg_location_[ssa_reg_high].wide = true; - } + if (verbose) { + LOG(INFO) << "CompilerTemps: The wide part of temp of type " << ct_type_str << " is v" + << compiler_temp->v_reg + 1 << " and s" << ssa_reg_high << "."; + } - num_non_special_compiler_temps_++; + if (reg_location_ != nullptr) { + reg_location_[ssa_reg_high] = temp_loc; + reg_location_[ssa_reg_high].high_word = true; + reg_location_[ssa_reg_high].s_reg_low = ssa_reg_low; + reg_location_[ssa_reg_high].wide = true; } } - // Have we already allocated the register locations? + // If the register locations have already been allocated, add the information + // about the temp. We will not overflow because they have been initialized + // to support the maximum number of temps. For ME temps that have multiple + // ssa versions, the structures below will be expanded on the post pass cleanup. if (reg_location_ != nullptr) { int ssa_reg_low = compiler_temp->s_reg_low; reg_location_[ssa_reg_low] = temp_loc; @@ -314,7 +395,6 @@ CompilerTemp* MIRGraph::GetNewCompilerTemp(CompilerTempType ct_type, bool wide) reg_location_[ssa_reg_low].wide = wide; } - compiler_temps_.Insert(compiler_temp); return compiler_temp; } @@ -749,13 +829,13 @@ bool MIRGraph::EliminateNullChecksAndInferTypes(BasicBlock* bb) { if (bb->block_type == kEntryBlock) { ssa_regs_to_check->ClearAllBits(); // Assume all ins are objects. - for (uint16_t in_reg = cu_->num_dalvik_registers - cu_->num_ins; - in_reg < cu_->num_dalvik_registers; in_reg++) { + for (uint16_t in_reg = GetFirstInVR(); + in_reg < GetNumOfCodeVRs(); in_reg++) { ssa_regs_to_check->SetBit(in_reg); } if ((cu_->access_flags & kAccStatic) == 0) { // If non-static method, mark "this" as non-null - int this_reg = cu_->num_dalvik_registers - cu_->num_ins; + int this_reg = GetFirstInVR(); ssa_regs_to_check->ClearBit(this_reg); } } else if (bb->predecessors->Size() == 1) { diff --git a/compiler/dex/portable/mir_to_gbc.cc b/compiler/dex/portable/mir_to_gbc.cc index fd67608e73..b0b06065b1 100644 --- a/compiler/dex/portable/mir_to_gbc.cc +++ b/compiler/dex/portable/mir_to_gbc.cc @@ -140,11 +140,11 @@ void MirConverter::InitIR() { return GetLLVMBlock(bb->id); } -void MirConverter::ConvertPackedSwitch(BasicBlock* bb, +void MirConverter::ConvertPackedSwitch(BasicBlock* bb, MIR* mir, int32_t table_offset, RegLocation rl_src) { const Instruction::PackedSwitchPayload* payload = reinterpret_cast( - cu_->insns + current_dalvik_offset_ + table_offset); + mir_graph_->GetTable(mir, table_offset)); ::llvm::Value* value = GetLLVMValue(rl_src.orig_sreg); @@ -164,11 +164,11 @@ void MirConverter::ConvertPackedSwitch(BasicBlock* bb, bb->fall_through = NullBasicBlockId; } -void MirConverter::ConvertSparseSwitch(BasicBlock* bb, +void MirConverter::ConvertSparseSwitch(BasicBlock* bb, MIR* mir, int32_t table_offset, RegLocation rl_src) { const Instruction::SparseSwitchPayload* payload = reinterpret_cast( - cu_->insns + current_dalvik_offset_ + table_offset); + mir_graph_->GetTable(mir, table_offset)); const int32_t* keys = payload->GetKeys(); const int32_t* targets = payload->GetTargets(); @@ -1536,9 +1536,9 @@ void MirConverter::SetMethodInfo() { ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id); ::llvm::Instruction* inst = irb_->CreateCall(intr); ::llvm::SmallVector< ::llvm::Value*, 2> reg_info; - reg_info.push_back(irb_->getInt32(cu_->num_ins)); - reg_info.push_back(irb_->getInt32(cu_->num_regs)); - reg_info.push_back(irb_->getInt32(cu_->num_outs)); + reg_info.push_back(irb_->getInt32(mir_graph_->GetNumOfInVRs())); + reg_info.push_back(irb_->getInt32(mir_graph_->GetNumOfLocalCodeVRs())); + reg_info.push_back(irb_->getInt32(mir_graph_->GetNumOfOutVRs())); reg_info.push_back(irb_->getInt32(mir_graph_->GetNumUsedCompilerTemps())); reg_info.push_back(irb_->getInt32(mir_graph_->GetNumSSARegs())); ::llvm::MDNode* reg_info_node = ::llvm::MDNode::get(*context_, reg_info); @@ -1669,12 +1669,12 @@ bool MirConverter::BlockBitcodeConversion(BasicBlock* bb) { art::llvm::IntrinsicHelper::IntrinsicId id = art::llvm::IntrinsicHelper::AllocaShadowFrame; ::llvm::Function* func = intrinsic_helper_->GetIntrinsicFunction(id); - ::llvm::Value* entries = irb_->getInt32(cu_->num_dalvik_registers); + ::llvm::Value* entries = irb_->getInt32(mir_graph_->GetNumOfCodeVRs()); irb_->CreateCall(func, entries); } { // Store arguments to vregs. - uint16_t arg_reg = cu_->num_regs; + uint16_t arg_reg = mir_graph_->GetFirstInVR(); ::llvm::Function::arg_iterator arg_iter(func_->arg_begin()); @@ -1843,7 +1843,7 @@ bool MirConverter::CreateFunction() { arg_iter->setName("method"); ++arg_iter; - int start_sreg = cu_->num_regs; + int start_sreg = mir_graph_->GetFirstInVR(); for (unsigned i = 0; arg_iter != arg_end; ++i, ++arg_iter) { arg_iter->setName(StringPrintf("v%i_0", start_sreg)); @@ -1909,8 +1909,8 @@ void MirConverter::MethodMIR2Bitcode() { RegLocation rl_temp = mir_graph_->reg_location_[i]; if ((mir_graph_->SRegToVReg(i) < 0) || rl_temp.high_word) { llvm_values_.Insert(0); - } else if ((i < cu_->num_regs) || - (i >= (cu_->num_regs + cu_->num_ins))) { + } else if ((i < mir_graph_->GetFirstInVR()) || + (i >= (mir_graph_->GetFirstTempVR()))) { ::llvm::Constant* imm_value = mir_graph_->reg_location_[i].wide ? irb_->getJLong(0) : irb_->getJInt(0); val = EmitConst(imm_value, mir_graph_->reg_location_[i]); diff --git a/compiler/dex/portable/mir_to_gbc.h b/compiler/dex/portable/mir_to_gbc.h index 4459eb686f..e6dee5dc0a 100644 --- a/compiler/dex/portable/mir_to_gbc.h +++ b/compiler/dex/portable/mir_to_gbc.h @@ -129,9 +129,9 @@ class MirConverter : public Backend { ::llvm::Type* LlvmTypeFromLocRec(RegLocation loc); void InitIR(); ::llvm::BasicBlock* FindCaseTarget(uint32_t vaddr); - void ConvertPackedSwitch(BasicBlock* bb, int32_t table_offset, + void ConvertPackedSwitch(BasicBlock* bb, MIR* mir, int32_t table_offset, RegLocation rl_src); - void ConvertSparseSwitch(BasicBlock* bb, int32_t table_offset, + void ConvertSparseSwitch(BasicBlock* bb, MIR* mir, int32_t table_offset, RegLocation rl_src); void ConvertSget(int32_t field_index, art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_dest); diff --git a/compiler/dex/quick/arm/call_arm.cc b/compiler/dex/quick/arm/call_arm.cc index 4ba3c4b9bb..fc98d31dd4 100644 --- a/compiler/dex/quick/arm/call_arm.cc +++ b/compiler/dex/quick/arm/call_arm.cc @@ -44,7 +44,7 @@ namespace art { * cbnz r_idx, lp */ void ArmMir2Lir::GenLargeSparseSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src) { - const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; + const uint16_t* table = mir_graph_->GetTable(mir, table_offset); if (cu_->verbose) { DumpSparseSwitchTable(table); } @@ -92,7 +92,7 @@ void ArmMir2Lir::GenLargeSparseSwitch(MIR* mir, uint32_t table_offset, RegLocati void ArmMir2Lir::GenLargePackedSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src) { - const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; + const uint16_t* table = mir_graph_->GetTable(mir, table_offset); if (cu_->verbose) { DumpPackedSwitchTable(table); } @@ -147,8 +147,8 @@ void ArmMir2Lir::GenLargePackedSwitch(MIR* mir, uint32_t table_offset, RegLocati * * Total size is 4+(width * size + 1)/2 16-bit code units. */ -void ArmMir2Lir::GenFillArrayData(uint32_t table_offset, RegLocation rl_src) { - const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; +void ArmMir2Lir::GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src) { + const uint16_t* table = mir_graph_->GetTable(mir, table_offset); // Add the table to the list - we'll process it later FillArrayData *tab_rec = static_cast(arena_->Alloc(sizeof(FillArrayData), kArenaAllocData)); diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h index 66a98ba6ef..84881e0860 100644 --- a/compiler/dex/quick/arm/codegen_arm.h +++ b/compiler/dex/quick/arm/codegen_arm.h @@ -117,7 +117,7 @@ class ArmMir2Lir FINAL : public Mir2Lir { void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method); void GenExitSequence(); void GenSpecialExitSequence(); - void GenFillArrayData(DexOffset table_offset, RegLocation rl_src); + void GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src); void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double); void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir); void GenSelect(BasicBlock* bb, MIR* mir); diff --git a/compiler/dex/quick/arm64/call_arm64.cc b/compiler/dex/quick/arm64/call_arm64.cc index eddc3a39be..b9c0990473 100644 --- a/compiler/dex/quick/arm64/call_arm64.cc +++ b/compiler/dex/quick/arm64/call_arm64.cc @@ -44,7 +44,7 @@ namespace art { * quit: */ void Arm64Mir2Lir::GenLargeSparseSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src) { - const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; + const uint16_t* table = mir_graph_->GetTable(mir, table_offset); if (cu_->verbose) { DumpSparseSwitchTable(table); } @@ -96,7 +96,7 @@ void Arm64Mir2Lir::GenLargeSparseSwitch(MIR* mir, uint32_t table_offset, RegLoca void Arm64Mir2Lir::GenLargePackedSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src) { - const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; + const uint16_t* table = mir_graph_->GetTable(mir, table_offset); if (cu_->verbose) { DumpPackedSwitchTable(table); } @@ -156,8 +156,8 @@ void Arm64Mir2Lir::GenLargePackedSwitch(MIR* mir, uint32_t table_offset, RegLoca * * Total size is 4+(width * size + 1)/2 16-bit code units. */ -void Arm64Mir2Lir::GenFillArrayData(uint32_t table_offset, RegLocation rl_src) { - const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; +void Arm64Mir2Lir::GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src) { + const uint16_t* table = mir_graph_->GetTable(mir, table_offset); // Add the table to the list - we'll process it later FillArrayData *tab_rec = static_cast(arena_->Alloc(sizeof(FillArrayData), kArenaAllocData)); diff --git a/compiler/dex/quick/arm64/codegen_arm64.h b/compiler/dex/quick/arm64/codegen_arm64.h index cc3f90a989..1c402928c3 100644 --- a/compiler/dex/quick/arm64/codegen_arm64.h +++ b/compiler/dex/quick/arm64/codegen_arm64.h @@ -183,7 +183,7 @@ class Arm64Mir2Lir FINAL : public Mir2Lir { void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) OVERRIDE; void GenExitSequence() OVERRIDE; void GenSpecialExitSequence() OVERRIDE; - void GenFillArrayData(DexOffset table_offset, RegLocation rl_src) OVERRIDE; + void GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src) OVERRIDE; void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double) OVERRIDE; void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) OVERRIDE; void GenSelect(BasicBlock* bb, MIR* mir) OVERRIDE; diff --git a/compiler/dex/quick/arm64/target_arm64.cc b/compiler/dex/quick/arm64/target_arm64.cc index bb21c7f5a9..0b58fb1d65 100644 --- a/compiler/dex/quick/arm64/target_arm64.cc +++ b/compiler/dex/quick/arm64/target_arm64.cc @@ -893,11 +893,11 @@ static RegStorage GetArgPhysicalReg(RegLocation* loc, int* num_gpr_used, int* nu RegStorage Arm64Mir2Lir::GetArgMappingToPhysicalReg(int arg_num) { if (!in_to_reg_storage_mapping_.IsInitialized()) { - int start_vreg = cu_->num_dalvik_registers - cu_->num_ins; + int start_vreg = mir_graph_->GetFirstInVR(); RegLocation* arg_locs = &mir_graph_->reg_location_[start_vreg]; InToRegStorageArm64Mapper mapper; - in_to_reg_storage_mapping_.Initialize(arg_locs, cu_->num_ins, &mapper); + in_to_reg_storage_mapping_.Initialize(arg_locs, mir_graph_->GetNumOfInVRs(), &mapper); } return in_to_reg_storage_mapping_.Get(arg_num); } @@ -931,14 +931,14 @@ void Arm64Mir2Lir::FlushIns(RegLocation* ArgLocs, RegLocation rl_method) { StoreRefDisp(TargetPtrReg(kSp), 0, rl_src.reg, kNotVolatile); } - if (cu_->num_ins == 0) { + if (mir_graph_->GetNumOfInVRs() == 0) { return; } // Handle dalvik registers. ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); - int start_vreg = cu_->num_dalvik_registers - cu_->num_ins; - for (int i = 0; i < cu_->num_ins; i++) { + int start_vreg = mir_graph_->GetFirstInVR(); + for (uint32_t i = 0; i < mir_graph_->GetNumOfInVRs(); i++) { RegLocation* t_loc = &ArgLocs[i]; OpSize op_size; RegStorage reg = GetArgPhysicalReg(t_loc, &num_gpr_used, &num_fpr_used, &op_size); @@ -1081,9 +1081,6 @@ int Arm64Mir2Lir::GenDalvikArgsRange(CallInfo* info, int call_state, } } - // Logic below assumes that Method pointer is at offset zero from SP. - DCHECK_EQ(VRegOffset(static_cast(kVRegMethodPtrBaseReg)), 0); - // The rest can be copied together int start_offset = SRegOffset(info->args[last_mapped_in + 1].s_reg_low); int outs_offset = StackVisitor::GetOutVROffset(last_mapped_in + 1, diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc index ebebe70462..08e1c1aa5a 100644 --- a/compiler/dex/quick/codegen_util.cc +++ b/compiler/dex/quick/codegen_util.cc @@ -268,8 +268,8 @@ void Mir2Lir::DumpLIRInsn(LIR* lir, unsigned char* base_addr) { } void Mir2Lir::DumpPromotionMap() { - int num_regs = cu_->num_dalvik_registers + mir_graph_->GetNumUsedCompilerTemps(); - for (int i = 0; i < num_regs; i++) { + uint32_t num_regs = mir_graph_->GetNumOfCodeAndTempVRs(); + for (uint32_t i = 0; i < num_regs; i++) { PromotionMap v_reg_map = promotion_map_[i]; std::string buf; if (v_reg_map.fp_location == kLocPhysReg) { @@ -277,12 +277,13 @@ void Mir2Lir::DumpPromotionMap() { } std::string buf3; - if (i < cu_->num_dalvik_registers) { + if (i < mir_graph_->GetNumOfCodeVRs()) { StringAppendF(&buf3, "%02d", i); - } else if (i == mir_graph_->GetMethodSReg()) { + } else if (i == mir_graph_->GetNumOfCodeVRs()) { buf3 = "Method*"; } else { - StringAppendF(&buf3, "ct%d", i - cu_->num_dalvik_registers); + uint32_t diff = i - mir_graph_->GetNumOfCodeVRs(); + StringAppendF(&buf3, "ct%d", diff); } LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(), @@ -313,9 +314,9 @@ void Mir2Lir::CodegenDump() { LIR* lir_insn; int insns_size = cu_->code_item->insns_size_in_code_units_; - LOG(INFO) << "Regs (excluding ins) : " << cu_->num_regs; - LOG(INFO) << "Ins : " << cu_->num_ins; - LOG(INFO) << "Outs : " << cu_->num_outs; + LOG(INFO) << "Regs (excluding ins) : " << mir_graph_->GetNumOfLocalCodeVRs(); + LOG(INFO) << "Ins : " << mir_graph_->GetNumOfInVRs(); + LOG(INFO) << "Outs : " << mir_graph_->GetNumOfOutVRs(); LOG(INFO) << "CoreSpills : " << num_core_spills_; LOG(INFO) << "FPSpills : " << num_fp_spills_; LOG(INFO) << "CompilerTemps : " << mir_graph_->GetNumUsedCompilerTemps(); @@ -1117,7 +1118,8 @@ size_t Mir2Lir::GetNumBytesForCompilerTempSpillRegion() { // By default assume that the Mir2Lir will need one slot for each temporary. // If the backend can better determine temps that have non-overlapping ranges and // temps that do not need spilled, it can actually provide a small region. - return (mir_graph_->GetNumUsedCompilerTemps() * sizeof(uint32_t)); + mir_graph_->CommitCompilerTemps(); + return mir_graph_->GetNumBytesForSpecialTemps() + mir_graph_->GetMaximumBytesForNonSpecialTemps(); } int Mir2Lir::ComputeFrameSize() { @@ -1125,7 +1127,8 @@ int Mir2Lir::ComputeFrameSize() { uint32_t size = num_core_spills_ * GetBytesPerGprSpillLocation(cu_->instruction_set) + num_fp_spills_ * GetBytesPerFprSpillLocation(cu_->instruction_set) + sizeof(uint32_t) // Filler. - + (cu_->num_regs + cu_->num_outs) * sizeof(uint32_t) + + mir_graph_->GetNumOfLocalCodeVRs() * sizeof(uint32_t) + + mir_graph_->GetNumOfOutVRs() * sizeof(uint32_t) + GetNumBytesForCompilerTempSpillRegion(); /* Align and set */ return RoundUp(size, kStackAlignment); diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc index b2af29833b..fbe710bebd 100644 --- a/compiler/dex/quick/gen_common.cc +++ b/compiler/dex/quick/gen_common.cc @@ -2105,7 +2105,7 @@ void Mir2Lir::GenConstWide(RegLocation rl_dest, int64_t value) { } void Mir2Lir::GenSmallPackedSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) { - const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; + const uint16_t* table = mir_graph_->GetTable(mir, table_offset); const uint16_t entries = table[1]; // Chained cmp-and-branch. const int32_t* as_int32 = reinterpret_cast(&table[2]); @@ -2148,7 +2148,7 @@ void Mir2Lir::GenSmallPackedSwitch(MIR* mir, DexOffset table_offset, RegLocation } void Mir2Lir::GenPackedSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) { - const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; + const uint16_t* table = mir_graph_->GetTable(mir, table_offset); if (cu_->verbose) { DumpSparseSwitchTable(table); } @@ -2163,7 +2163,7 @@ void Mir2Lir::GenPackedSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_s } void Mir2Lir::GenSmallSparseSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) { - const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; + const uint16_t* table = mir_graph_->GetTable(mir, table_offset); const uint16_t entries = table[1]; // Chained cmp-and-branch. const int32_t* keys = reinterpret_cast(&table[2]); @@ -2178,7 +2178,7 @@ void Mir2Lir::GenSmallSparseSwitch(MIR* mir, DexOffset table_offset, RegLocation } void Mir2Lir::GenSparseSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) { - const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; + const uint16_t* table = mir_graph_->GetTable(mir, table_offset); if (cu_->verbose) { DumpSparseSwitchTable(table); } diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc index 3fdbe2040f..e1d3241205 100755 --- a/compiler/dex/quick/gen_invoke.cc +++ b/compiler/dex/quick/gen_invoke.cc @@ -381,11 +381,11 @@ void Mir2Lir::FlushIns(RegLocation* ArgLocs, RegLocation rl_method) { StoreRefDisp(TargetPtrReg(kSp), 0, rl_src.reg, kNotVolatile); } - if (cu_->num_ins == 0) { + if (mir_graph_->GetNumOfInVRs() == 0) { return; } - int start_vreg = cu_->num_dalvik_registers - cu_->num_ins; + int start_vreg = mir_graph_->GetFirstInVR(); /* * Copy incoming arguments to their proper home locations. * NOTE: an older version of dx had an issue in which @@ -399,7 +399,7 @@ void Mir2Lir::FlushIns(RegLocation* ArgLocs, RegLocation rl_method) { * half to memory as well. */ ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); - for (int i = 0; i < cu_->num_ins; i++) { + for (uint32_t i = 0; i < mir_graph_->GetNumOfInVRs(); i++) { PromotionMap* v_map = &promotion_map_[start_vreg + i]; RegStorage reg = GetArgMappingToPhysicalReg(i); @@ -933,9 +933,6 @@ int Mir2Lir::GenDalvikArgsRange(CallInfo* info, int call_state, } } - // Logic below assumes that Method pointer is at offset zero from SP. - DCHECK_EQ(VRegOffset(static_cast(kVRegMethodPtrBaseReg)), 0); - // The first 3 arguments are passed via registers. // TODO: For 64-bit, instead of hardcoding 4 for Method* size, we should either // get size of uintptr_t or size of object reference according to model being used. diff --git a/compiler/dex/quick/mips/call_mips.cc b/compiler/dex/quick/mips/call_mips.cc index e8cb356186..f3edd7eecd 100644 --- a/compiler/dex/quick/mips/call_mips.cc +++ b/compiler/dex/quick/mips/call_mips.cc @@ -62,7 +62,7 @@ bool MipsMir2Lir::GenSpecialCase(BasicBlock* bb, MIR* mir, * */ void MipsMir2Lir::GenLargeSparseSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) { - const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; + const uint16_t* table = mir_graph_->GetTable(mir, table_offset); if (cu_->verbose) { DumpSparseSwitchTable(table); } @@ -139,7 +139,7 @@ void MipsMir2Lir::GenLargeSparseSwitch(MIR* mir, DexOffset table_offset, RegLoca * done: */ void MipsMir2Lir::GenLargePackedSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) { - const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; + const uint16_t* table = mir_graph_->GetTable(mir, table_offset); if (cu_->verbose) { DumpPackedSwitchTable(table); } @@ -220,8 +220,8 @@ void MipsMir2Lir::GenLargePackedSwitch(MIR* mir, DexOffset table_offset, RegLoca * * Total size is 4+(width * size + 1)/2 16-bit code units. */ -void MipsMir2Lir::GenFillArrayData(DexOffset table_offset, RegLocation rl_src) { - const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; +void MipsMir2Lir::GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src) { + const uint16_t* table = mir_graph_->GetTable(mir, table_offset); // Add the table to the list - we'll process it later FillArrayData* tab_rec = reinterpret_cast(arena_->Alloc(sizeof(FillArrayData), diff --git a/compiler/dex/quick/mips/codegen_mips.h b/compiler/dex/quick/mips/codegen_mips.h index 9f1af696d2..be94019ef3 100644 --- a/compiler/dex/quick/mips/codegen_mips.h +++ b/compiler/dex/quick/mips/codegen_mips.h @@ -116,7 +116,7 @@ class MipsMir2Lir FINAL : public Mir2Lir { void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method); void GenExitSequence(); void GenSpecialExitSequence(); - void GenFillArrayData(uint32_t table_offset, RegLocation rl_src); + void GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src); void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double); void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir); void GenSelect(BasicBlock* bb, MIR* mir); diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc index 3ec37f2a42..96f00e791c 100644 --- a/compiler/dex/quick/mir_to_lir.cc +++ b/compiler/dex/quick/mir_to_lir.cc @@ -599,7 +599,7 @@ void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list break; case Instruction::FILL_ARRAY_DATA: - GenFillArrayData(vB, rl_src[0]); + GenFillArrayData(mir, vB, rl_src[0]); break; case Instruction::FILLED_NEW_ARRAY: @@ -1200,9 +1200,8 @@ bool Mir2Lir::MethodBlockCodeGen(BasicBlock* bb) { if (bb->block_type == kEntryBlock) { ResetRegPool(); - int start_vreg = cu_->num_dalvik_registers - cu_->num_ins; - GenEntrySequence(&mir_graph_->reg_location_[start_vreg], - mir_graph_->reg_location_[mir_graph_->GetMethodSReg()]); + int start_vreg = mir_graph_->GetFirstInVR(); + GenEntrySequence(&mir_graph_->reg_location_[start_vreg], mir_graph_->GetMethodLoc()); } else if (bb->block_type == kExitBlock) { ResetRegPool(); GenExitSequence(); diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h index d101a13b29..d6fc2e9da5 100644 --- a/compiler/dex/quick/mir_to_lir.h +++ b/compiler/dex/quick/mir_to_lir.h @@ -1313,7 +1313,7 @@ class Mir2Lir : public Backend { virtual void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) = 0; virtual void GenExitSequence() = 0; - virtual void GenFillArrayData(DexOffset table_offset, RegLocation rl_src) = 0; + virtual void GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src) = 0; virtual void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double) = 0; virtual void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) = 0; diff --git a/compiler/dex/quick/quick_compiler.cc b/compiler/dex/quick/quick_compiler.cc index 96918645e4..49c16cb899 100644 --- a/compiler/dex/quick/quick_compiler.cc +++ b/compiler/dex/quick/quick_compiler.cc @@ -495,8 +495,8 @@ static bool CanCompileShorty(const char* shorty, InstructionSet instruction_set) bool QuickCompiler::CanCompileMethod(uint32_t method_idx, const DexFile& dex_file, CompilationUnit* cu) const { // This is a limitation in mir_graph. See MirGraph::SetNumSSARegs. - if (cu->num_dalvik_registers > kMaxAllowedDalvikRegisters) { - VLOG(compiler) << "Too many dalvik registers : " << cu->num_dalvik_registers; + if (cu->mir_graph->GetNumOfCodeAndTempVRs() > kMaxAllowedDalvikRegisters) { + VLOG(compiler) << "Too many dalvik registers : " << cu->mir_graph->GetNumOfCodeAndTempVRs(); return false; } diff --git a/compiler/dex/quick/ralloc_util.cc b/compiler/dex/quick/ralloc_util.cc index 4021c95791..0a737a9315 100644 --- a/compiler/dex/quick/ralloc_util.cc +++ b/compiler/dex/quick/ralloc_util.cc @@ -252,20 +252,7 @@ int Mir2Lir::SRegToPMap(int s_reg) { DCHECK_LT(s_reg, mir_graph_->GetNumSSARegs()); DCHECK_GE(s_reg, 0); int v_reg = mir_graph_->SRegToVReg(s_reg); - if (v_reg >= 0) { - DCHECK_LT(v_reg, cu_->num_dalvik_registers); - return v_reg; - } else { - /* - * It must be the case that the v_reg for temporary is less than or equal to the - * base reg for temps. For that reason, "position" must be zero or positive. - */ - unsigned int position = std::abs(v_reg) - std::abs(static_cast(kVRegTempBaseReg)); - - // The temporaries are placed after dalvik registers in the promotion map - DCHECK_LT(position, mir_graph_->GetNumUsedCompilerTemps()); - return cu_->num_dalvik_registers + position; - } + return v_reg; } // TODO: refactor following Alloc/Record routines - much commonality. @@ -1211,8 +1198,7 @@ void Mir2Lir::DumpCounts(const RefCounts* arr, int size, const char* msg) { * optimization is disabled. */ void Mir2Lir::DoPromotion() { - int dalvik_regs = cu_->num_dalvik_registers; - int num_regs = dalvik_regs + mir_graph_->GetNumUsedCompilerTemps(); + int num_regs = mir_graph_->GetNumOfCodeAndTempVRs(); const int promotion_threshold = 1; // Allocate the promotion map - one entry for each Dalvik vReg or compiler temp promotion_map_ = static_cast @@ -1241,17 +1227,10 @@ void Mir2Lir::DoPromotion() { static_cast(arena_->Alloc(sizeof(RefCounts) * fp_reg_count_size, kArenaAllocRegAlloc)); // Set ssa names for original Dalvik registers - for (int i = 0; i < dalvik_regs; i++) { + for (int i = 0; i < num_regs; i++) { core_regs[i].s_reg = fp_regs[i].s_reg = i; } - // Set ssa names for compiler temporaries - for (unsigned int ct_idx = 0; ct_idx < mir_graph_->GetNumUsedCompilerTemps(); ct_idx++) { - CompilerTemp* ct = mir_graph_->GetCompilerTemp(ct_idx); - core_regs[dalvik_regs + ct_idx].s_reg = ct->s_reg_low; - fp_regs[dalvik_regs + ct_idx].s_reg = ct->s_reg_low; - } - // Duplicate in upper half to represent possible wide starting sregs. for (size_t i = num_regs; i < fp_reg_count_size; i++) { fp_regs[i].s_reg = fp_regs[i - num_regs].s_reg | STARTING_WIDE_SREG; diff --git a/compiler/dex/quick/x86/call_x86.cc b/compiler/dex/quick/x86/call_x86.cc index 996689a46c..482c430e88 100644 --- a/compiler/dex/quick/x86/call_x86.cc +++ b/compiler/dex/quick/x86/call_x86.cc @@ -28,7 +28,7 @@ namespace art { * pairs. */ void X86Mir2Lir::GenLargeSparseSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) { - const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; + const uint16_t* table = mir_graph_->GetTable(mir, table_offset); if (cu_->verbose) { DumpSparseSwitchTable(table); } @@ -61,7 +61,7 @@ void X86Mir2Lir::GenLargeSparseSwitch(MIR* mir, DexOffset table_offset, RegLocat * done: */ void X86Mir2Lir::GenLargePackedSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) { - const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; + const uint16_t* table = mir_graph_->GetTable(mir, table_offset); if (cu_->verbose) { DumpPackedSwitchTable(table); } @@ -134,8 +134,8 @@ void X86Mir2Lir::GenLargePackedSwitch(MIR* mir, DexOffset table_offset, RegLocat * * Total size is 4+(width * size + 1)/2 16-bit code units. */ -void X86Mir2Lir::GenFillArrayData(DexOffset table_offset, RegLocation rl_src) { - const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; +void X86Mir2Lir::GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src) { + const uint16_t* table = mir_graph_->GetTable(mir, table_offset); // Add the table to the list - we'll process it later FillArrayData* tab_rec = static_cast(arena_->Alloc(sizeof(FillArrayData), kArenaAllocData)); diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h index aeeaea24d5..7ad917da19 100644 --- a/compiler/dex/quick/x86/codegen_x86.h +++ b/compiler/dex/quick/x86/codegen_x86.h @@ -235,7 +235,7 @@ class X86Mir2Lir : public Mir2Lir { void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) OVERRIDE; void GenExitSequence() OVERRIDE; void GenSpecialExitSequence() OVERRIDE; - void GenFillArrayData(DexOffset table_offset, RegLocation rl_src) OVERRIDE; + void GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src) OVERRIDE; void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double) OVERRIDE; void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) OVERRIDE; void GenSelect(BasicBlock* bb, MIR* mir) OVERRIDE; diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc index c43a1ff10b..68c1633c2a 100755 --- a/compiler/dex/quick/x86/target_x86.cc +++ b/compiler/dex/quick/x86/target_x86.cc @@ -2234,11 +2234,11 @@ RegStorage X86Mir2Lir::GetArgMappingToPhysicalReg(int arg_num) { } if (!in_to_reg_storage_mapping_.IsInitialized()) { - int start_vreg = cu_->num_dalvik_registers - cu_->num_ins; + int start_vreg = cu_->mir_graph->GetFirstInVR(); RegLocation* arg_locs = &mir_graph_->reg_location_[start_vreg]; InToRegStorageX86_64Mapper mapper(this); - in_to_reg_storage_mapping_.Initialize(arg_locs, cu_->num_ins, &mapper); + in_to_reg_storage_mapping_.Initialize(arg_locs, mir_graph_->GetNumOfInVRs(), &mapper); } return in_to_reg_storage_mapping_.Get(arg_num); } @@ -2287,11 +2287,11 @@ void X86Mir2Lir::FlushIns(RegLocation* ArgLocs, RegLocation rl_method) { StoreRefDisp(rs_rX86_SP, 0, As32BitReg(TargetReg(kArg0, kRef)), kNotVolatile); } - if (cu_->num_ins == 0) { + if (mir_graph_->GetNumOfInVRs() == 0) { return; } - int start_vreg = cu_->num_dalvik_registers - cu_->num_ins; + int start_vreg = cu_->mir_graph->GetFirstInVR(); /* * Copy incoming arguments to their proper home locations. * NOTE: an older version of dx had an issue in which @@ -2305,7 +2305,7 @@ void X86Mir2Lir::FlushIns(RegLocation* ArgLocs, RegLocation rl_method) { * half to memory as well. */ ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); - for (int i = 0; i < cu_->num_ins; i++) { + for (uint32_t i = 0; i < mir_graph_->GetNumOfInVRs(); i++) { // get reg corresponding to input RegStorage reg = GetArgMappingToPhysicalReg(i); @@ -2437,9 +2437,6 @@ int X86Mir2Lir::GenDalvikArgsRange(CallInfo* info, int call_state, } } - // Logic below assumes that Method pointer is at offset zero from SP. - DCHECK_EQ(VRegOffset(static_cast(kVRegMethodPtrBaseReg)), 0); - // The rest can be copied together int start_offset = SRegOffset(info->args[last_mapped_in + size_of_the_last_mapped].s_reg_low); int outs_offset = StackVisitor::GetOutVROffset(last_mapped_in + size_of_the_last_mapped, diff --git a/compiler/dex/quick/x86/utility_x86.cc b/compiler/dex/quick/x86/utility_x86.cc index 037dfedfe7..022fd80663 100644 --- a/compiler/dex/quick/x86/utility_x86.cc +++ b/compiler/dex/quick/x86/utility_x86.cc @@ -957,7 +957,8 @@ void X86Mir2Lir::AnalyzeMIR() { // Did we need a pointer to the method code? if (store_method_addr_) { - base_of_code_ = mir_graph_->GetNewCompilerTemp(kCompilerTempVR, cu_->target64 == true); + base_of_code_ = mir_graph_->GetNewCompilerTemp(kCompilerTempBackend, cu_->target64 == true); + DCHECK(base_of_code_ != nullptr); } else { base_of_code_ = nullptr; } diff --git a/compiler/dex/quick/x86/x86_lir.h b/compiler/dex/quick/x86/x86_lir.h index 15fe7e298f..e3ef8c1868 100644 --- a/compiler/dex/quick/x86/x86_lir.h +++ b/compiler/dex/quick/x86/x86_lir.h @@ -75,33 +75,36 @@ namespace art { * ST1 .. ST7: caller save * * Stack frame diagram (stack grows down, higher addresses at top): + * For a more detailed view of each region see stack.h. * - * +------------------------+ - * | IN[ins-1] | {Note: resides in caller's frame} - * | . | - * | IN[0] | - * | caller's Method* | - * +========================+ {Note: start of callee's frame} - * | return address | {pushed by call} - * | spill region | {variable sized} - * +------------------------+ - * | ...filler word... | {Note: used as 2nd word of V[locals-1] if long] - * +------------------------+ - * | V[locals-1] | - * | V[locals-2] | - * | . | - * | . | - * | V[1] | - * | V[0] | - * +------------------------+ - * | 0 to 3 words padding | - * +------------------------+ - * | OUT[outs-1] | - * | OUT[outs-2] | - * | . | - * | OUT[0] | - * | cur_method* | <<== sp w/ 16-byte alignment - * +========================+ + * +---------------------------+ + * | IN[ins-1] | {Note: resides in caller's frame} + * | . | + * | IN[0] | + * | caller's Method* | + * +===========================+ {Note: start of callee's frame} + * | return address | {pushed by call} + * | spill region | {variable sized} + * +---------------------------+ + * | ...filler 4-bytes... | {Note: used as 2nd word of V[locals-1] if long] + * +---------------------------+ + * | V[locals-1] | + * | V[locals-2] | + * | . | + * | . | + * | V[1] | + * | V[0] | + * +---------------------------+ + * | 0 to 12-bytes padding | + * +---------------------------+ + * | compiler temp region | + * +---------------------------+ + * | OUT[outs-1] | + * | OUT[outs-2] | + * | . | + * | OUT[0] | + * | StackReference | <<== sp w/ 16-byte alignment + * +===========================+ */ enum X86ResourceEncodingPos { diff --git a/compiler/dex/ssa_transformation.cc b/compiler/dex/ssa_transformation.cc index 4a55de6891..7bf7a651ab 100644 --- a/compiler/dex/ssa_transformation.cc +++ b/compiler/dex/ssa_transformation.cc @@ -147,8 +147,8 @@ bool MIRGraph::FillDefBlockMatrix(BasicBlock* bb) { } void MIRGraph::ComputeDefBlockMatrix() { - int num_registers = cu_->num_dalvik_registers; - /* Allocate num_dalvik_registers bit vector pointers */ + int num_registers = GetNumOfCodeAndTempVRs(); + /* Allocate num_registers bit vector pointers */ def_block_matrix_ = static_cast (arena_->Alloc(sizeof(ArenaBitVector *) * num_registers, kArenaAllocDFInfo)); @@ -159,6 +159,7 @@ void MIRGraph::ComputeDefBlockMatrix() { def_block_matrix_[i] = new (arena_) ArenaBitVector(arena_, GetNumBlocks(), false, kBitMapBMatrix); } + AllNodesIterator iter(this); for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) { FindLocalLiveIn(bb); @@ -172,8 +173,8 @@ void MIRGraph::ComputeDefBlockMatrix() { * Also set the incoming parameters as defs in the entry block. * Only need to handle the parameters for the outer method. */ - int num_regs = cu_->num_dalvik_registers; - int in_reg = num_regs - cu_->num_ins; + int num_regs = GetNumOfCodeVRs(); + int in_reg = GetFirstInVR(); for (; in_reg < num_regs; in_reg++) { def_block_matrix_[in_reg]->SetBit(GetEntryBlock()->id); } @@ -457,7 +458,7 @@ void MIRGraph::ComputeSuccLineIn(ArenaBitVector* dest, const ArenaBitVector* src * insert a phi node if the variable is live-in to the block. */ bool MIRGraph::ComputeBlockLiveIns(BasicBlock* bb) { - DCHECK_EQ(temp_bit_vector_size_, cu_->num_dalvik_registers); + DCHECK_EQ(temp_bit_vector_size_, cu_->mir_graph.get()->GetNumOfCodeAndTempVRs()); ArenaBitVector* temp_dalvik_register_v = temp_bit_vector_; if (bb->data_flow_info == NULL) { @@ -508,7 +509,7 @@ void MIRGraph::InsertPhiNodes() { } /* Iterate through each Dalvik register */ - for (dalvik_reg = cu_->num_dalvik_registers - 1; dalvik_reg >= 0; dalvik_reg--) { + for (dalvik_reg = GetNumOfCodeAndTempVRs() - 1; dalvik_reg >= 0; dalvik_reg--) { input_blocks->Copy(def_block_matrix_[dalvik_reg]); phi_blocks->ClearAllBits(); do { @@ -587,7 +588,7 @@ void MIRGraph::DoDFSPreOrderSSARename(BasicBlock* block) { /* Process this block */ DoSSAConversion(block); - int map_size = sizeof(int) * cu_->num_dalvik_registers; + int map_size = sizeof(int) * GetNumOfCodeAndTempVRs(); /* Save SSA map snapshot */ ScopedArenaAllocator allocator(&cu_->arena_stack); diff --git a/compiler/dex/vreg_analysis.cc b/compiler/dex/vreg_analysis.cc index 0d8a6f8793..bdfab130c0 100644 --- a/compiler/dex/vreg_analysis.cc +++ b/compiler/dex/vreg_analysis.cc @@ -401,7 +401,7 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed) { return changed; } -static const char* storage_name[] = {" Frame ", "PhysReg", " Spill "}; +static const char* storage_name[] = {" Frame ", "PhysReg", " CompilerTemp "}; void MIRGraph::DumpRegLocTable(RegLocation* table, int count) { for (int i = 0; i < count; i++) { @@ -421,7 +421,9 @@ static const RegLocation fresh_loc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0, RegStorage(), INVALID_SREG, INVALID_SREG}; void MIRGraph::InitRegLocations() { - /* Allocate the location map */ + // Allocate the location map. We also include the maximum possible temps because + // the temp allocation initializes reg location as well (in order to deal with + // case when it will be called after this pass). int max_regs = GetNumSSARegs() + GetMaxPossibleCompilerTemps(); RegLocation* loc = static_cast(arena_->Alloc(max_regs * sizeof(*loc), kArenaAllocRegAlloc)); @@ -432,22 +434,18 @@ void MIRGraph::InitRegLocations() { loc[i].wide = false; } - /* Patch up the locations for the compiler temps */ - GrowableArray::Iterator iter(&compiler_temps_); - for (CompilerTemp* ct = iter.Next(); ct != NULL; ct = iter.Next()) { - loc[ct->s_reg_low].location = kLocCompilerTemp; - loc[ct->s_reg_low].defined = true; - } - /* Treat Method* as a normal reference */ - loc[GetMethodSReg()].ref = true; + int method_sreg = GetMethodSReg(); + loc[method_sreg].ref = true; + loc[method_sreg].location = kLocCompilerTemp; + loc[method_sreg].defined = true; reg_location_ = loc; - int num_regs = cu_->num_dalvik_registers; + int num_regs = GetNumOfCodeVRs(); /* Add types of incoming arguments based on signature */ - int num_ins = cu_->num_ins; + int num_ins = GetNumOfInVRs(); if (num_ins > 0) { int s_reg = num_regs - num_ins; if ((cu_->access_flags & kAccStatic) == 0) { @@ -502,11 +500,9 @@ void MIRGraph::InitRegLocations() { */ void MIRGraph::RemapRegLocations() { for (int i = 0; i < GetNumSSARegs(); i++) { - if (reg_location_[i].location != kLocCompilerTemp) { - int orig_sreg = reg_location_[i].s_reg_low; - reg_location_[i].orig_sreg = orig_sreg; - reg_location_[i].s_reg_low = SRegToVReg(orig_sreg); - } + int orig_sreg = reg_location_[i].s_reg_low; + reg_location_[i].orig_sreg = orig_sreg; + reg_location_[i].s_reg_low = SRegToVReg(orig_sreg); } } -- cgit v1.2.3