diff options
author | Bill Buzbee <buzbee@android.com> | 2014-08-27 21:33:14 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2014-08-27 21:33:14 +0000 |
commit | 70644461909a68eb5cd032027ae0eb528143d99c (patch) | |
tree | ad5087e2610d9c9d29c9d9ca2fd568190bcb6889 /compiler | |
parent | 90364c5f94069cf96e507b40076ea8eb2a6f303b (diff) | |
parent | 8d0d03e24325463f0060abfd05dba5598044e9b1 (diff) | |
download | art-70644461909a68eb5cd032027ae0eb528143d99c.tar.gz art-70644461909a68eb5cd032027ae0eb528143d99c.tar.bz2 art-70644461909a68eb5cd032027ae0eb528143d99c.zip |
Merge "ART: Change temporaries to positive names"
Diffstat (limited to 'compiler')
33 files changed, 417 insertions, 272 deletions
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<DexFile::CodeItem*>( + 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 <size_t count> 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<int>(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<int>(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<int*>(arena_->Alloc(sizeof(int) * cu_->num_dalvik_registers, + static_cast<int*>(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<int>(arena_, num_dalvik_reg + GetDefCount() + 128, + ssa_base_vregs_ = new (arena_) GrowableArray<int>(arena_, num_reg + GetDefCount() + 128, kGrowableArraySSAtoDalvikMap); - ssa_subscripts_ = new (arena_) GrowableArray<int>(arena_, num_dalvik_reg + GetDefCount() + 128, + ssa_subscripts_ = new (arena_) GrowableArray<int>(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<int*>(arena_->Alloc(sizeof(int) * num_dalvik_reg, + static_cast<int*>(arena_->Alloc(sizeof(int) * num_reg, kArenaAllocDFInfo)); /* Keep track of the higest def for each dalvik reg */ ssa_last_defs_ = - static_cast<int*>(arena_->Alloc(sizeof(int) * num_dalvik_reg, + static_cast<int*>(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<int>(kVRegNonSpecialTempBaseReg)) - - std::abs(static_cast<int>(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<BasicBlock*>::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. @@ -898,7 +925,22 @@ class MIRGraph { } /** + * @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<std::pair<uint16_t, bool>>* 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<ScopedArenaAllocator> 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<CompilerTemp*> 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<MirIFieldLoweringInfo> ifield_lowering_infos_; GrowableArray<MirSFieldLoweringInfo> 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<DexFile::CodeItem*>(cu_.arena.Alloc(sizeof(DexFile::CodeItem), + kArenaAllocMisc)); + cu_.mir_graph->current_code_item_ = cu_.code_item = code_item; } template <size_t count> 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<mirror::ArtMethod>); +} + +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<CompilerTemp *>(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<int>(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<int>(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<CompilerTemp *>(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<const Instruction::PackedSwitchPayload*>( - 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<const Instruction::SparseSwitchPayload*>( - 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<FillArrayData*>(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<FillArrayData*>(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<int>(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<const int32_t*>(&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<const int32_t*>(&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<int>(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<FillArrayData*>(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<int>(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<PromotionMap*> @@ -1241,17 +1227,10 @@ void Mir2Lir::DoPromotion() { static_cast<RefCounts *>(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<FillArrayData*>(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<int>(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<ArtMethod> | <<== 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<ArenaBitVector**> (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<RegLocation*>(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<CompilerTemp*>::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); } } |