summaryrefslogtreecommitdiffstats
path: root/compiler
diff options
context:
space:
mode:
authorBill Buzbee <buzbee@android.com>2014-08-27 21:33:14 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2014-08-27 21:33:14 +0000
commit70644461909a68eb5cd032027ae0eb528143d99c (patch)
treead5087e2610d9c9d29c9d9ca2fd568190bcb6889 /compiler
parent90364c5f94069cf96e507b40076ea8eb2a6f303b (diff)
parent8d0d03e24325463f0060abfd05dba5598044e9b1 (diff)
downloadart-70644461909a68eb5cd032027ae0eb528143d99c.tar.gz
art-70644461909a68eb5cd032027ae0eb528143d99c.tar.bz2
art-70644461909a68eb5cd032027ae0eb528143d99c.zip
Merge "ART: Change temporaries to positive names"
Diffstat (limited to 'compiler')
-rw-r--r--compiler/dex/compiler_ir.cc5
-rw-r--r--compiler/dex/compiler_ir.h6
-rw-r--r--compiler/dex/frontend.cc2
-rw-r--r--compiler/dex/global_value_numbering.cc2
-rw-r--r--compiler/dex/global_value_numbering_test.cc4
-rw-r--r--compiler/dex/mir_dataflow.cc39
-rw-r--r--compiler/dex/mir_graph.cc33
-rw-r--r--compiler/dex/mir_graph.h141
-rw-r--r--compiler/dex/mir_graph_test.cc4
-rw-r--r--compiler/dex/mir_optimization.cc176
-rw-r--r--compiler/dex/portable/mir_to_gbc.cc24
-rw-r--r--compiler/dex/portable/mir_to_gbc.h4
-rw-r--r--compiler/dex/quick/arm/call_arm.cc8
-rw-r--r--compiler/dex/quick/arm/codegen_arm.h2
-rw-r--r--compiler/dex/quick/arm64/call_arm64.cc8
-rw-r--r--compiler/dex/quick/arm64/codegen_arm64.h2
-rw-r--r--compiler/dex/quick/arm64/target_arm64.cc13
-rw-r--r--compiler/dex/quick/codegen_util.cc23
-rw-r--r--compiler/dex/quick/gen_common.cc8
-rwxr-xr-xcompiler/dex/quick/gen_invoke.cc9
-rw-r--r--compiler/dex/quick/mips/call_mips.cc8
-rw-r--r--compiler/dex/quick/mips/codegen_mips.h2
-rw-r--r--compiler/dex/quick/mir_to_lir.cc7
-rw-r--r--compiler/dex/quick/mir_to_lir.h2
-rw-r--r--compiler/dex/quick/quick_compiler.cc4
-rw-r--r--compiler/dex/quick/ralloc_util.cc27
-rw-r--r--compiler/dex/quick/x86/call_x86.cc8
-rw-r--r--compiler/dex/quick/x86/codegen_x86.h2
-rwxr-xr-xcompiler/dex/quick/x86/target_x86.cc13
-rw-r--r--compiler/dex/quick/x86/utility_x86.cc3
-rw-r--r--compiler/dex/quick/x86/x86_lir.h55
-rw-r--r--compiler/dex/ssa_transformation.cc15
-rw-r--r--compiler/dex/vreg_analysis.cc30
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);
}
}