Index: runtime/vm/flow_graph_compiler_x64.cc |
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc |
index 0b846fa3547541f68c7f9dd7fc36c05142214b34..95e50a83a454e13223017607d17749e7744b1c29 100644 |
--- a/runtime/vm/flow_graph_compiler_x64.cc |
+++ b/runtime/vm/flow_graph_compiler_x64.cc |
@@ -32,6 +32,11 @@ DECLARE_FLAG(bool, report_usage_count); |
DECLARE_FLAG(bool, code_comments); |
+static Register ToRegister(Location loc) { |
+ return RegisterLocation::Cast(loc).reg(); |
+} |
+ |
+ |
FlowGraphCompiler::FlowGraphCompiler( |
Assembler* assembler, |
const ParsedFunction& parsed_function, |
@@ -546,22 +551,37 @@ void FlowGraphCompiler::VisitInstanceCall(InstanceCallComp* comp) { |
} |
+LocationSummary* StrictCompareComp::MakeLocationSummary() { |
srdjan
2012/05/18 18:00:14
In unoptimizing compiler this is the same for all
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
Preallocating and reusing proves to be hard becaus
srdjan
2012/05/21 16:05:22
Valid points, good suggestion. Let's not do anythi
|
+ LocationSummary* summary = new LocationSummary(2); |
+ summary->SetInputLocationAt( |
+ 0, UnallocatedLocation(UnallocatedLocation::REGISTER)); |
+ summary->SetInputLocationAt( |
+ 1, UnallocatedLocation(UnallocatedLocation::REGISTER)); |
srdjan
2012/05/18 18:00:14
Too verbose.
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
introduced a helper function and shortened method
|
+ summary->set_result_location( |
+ UnallocatedLocation(UnallocatedLocation::SAME_AS_FIRST_INPUT)); |
+ return summary; |
srdjan
2012/05/18 18:00:14
As you said, this does not belong here. Maybe in a
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
moved to intermediate_language_x64.cc
|
+} |
+ |
+ |
void FlowGraphCompiler::VisitStrictCompare(StrictCompareComp* comp) { |
const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
- LoadValue(RDX, comp->right()); |
- LoadValue(RAX, comp->left()); |
- __ cmpq(RAX, RDX); |
+ |
+ Register left = ToRegister(comp->GetLocationSummary()->InputLocationAt(0)); |
+ Register right = ToRegister(comp->GetLocationSummary()->InputLocationAt(1)); |
+ Register result = ToRegister(comp->GetLocationSummary()->result_location()); |
srdjan
2012/05/18 18:00:14
Too verbose, maybe:
comp->locs()->in(0)->AsRegiste
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
Done.
|
+ |
+ __ cmpq(left, right); |
Label load_true, done; |
if (comp->kind() == Token::kEQ_STRICT) { |
__ j(EQUAL, &load_true, Assembler::kNearJump); |
} else { |
__ j(NOT_EQUAL, &load_true, Assembler::kNearJump); |
} |
- __ LoadObject(RAX, bool_false); |
+ __ LoadObject(result, bool_false); |
__ jmp(&done, Assembler::kNearJump); |
__ Bind(&load_true); |
- __ LoadObject(RAX, bool_true); |
+ __ LoadObject(result, bool_true); |
__ Bind(&done); |
} |
@@ -1122,6 +1142,73 @@ void FlowGraphCompiler::VisitCatchEntry(CatchEntryComp* comp) { |
} |
+static Register AllocateFreeRegister(bool* blocked_registers) { |
srdjan
2012/05/18 18:00:14
I would rather use BitVector or GrowableArray sinc
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
both are zone allocated which seems unnecessary ex
|
+ for (int regno = 0; regno < kNumberOfCpuRegisters; regno++) { |
+ if (!blocked_registers[regno]) { |
+ blocked_registers[regno] = true; |
+ return static_cast<Register>(regno); |
srdjan
2012/05/18 18:00:14
The register allocation needs also to move out of
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
Moved simple register allocator into LocationSumma
|
+ } |
+ } |
+ UNREACHABLE(); |
+ return kNoRegister; |
+} |
+ |
+ |
+static void AllocateRegisters(LocationSummary* summary) { |
+ bool blocked_registers[kNumberOfCpuRegisters] = { false }; |
+ |
+ for (intptr_t i = 0; i < summary->InputLocationsCount(); i++) { |
+ Location loc = summary->InputLocationAt(i); |
+ if (loc.kind() == Location::REGISTER) { |
+ ASSERT(!blocked_registers[ToRegister(loc)]); |
+ blocked_registers[loc.value()] = true; |
+ } |
+ } |
+ |
+ for (intptr_t i = 0; i < summary->InputLocationsCount(); i++) { |
+ Location loc = summary->InputLocationAt(i); |
+ if (loc.kind() == Location::UNALLOCATED) { |
+ ASSERT(UnallocatedLocation::Cast(loc).policy() == |
+ UnallocatedLocation::REGISTER); |
+ summary->SetInputLocationAt(i, RegisterLocation( |
+ AllocateFreeRegister(blocked_registers))); |
+ } |
+ } |
+ |
+ Location result_location = summary->result_location(); |
+ if (result_location.kind() == Location::UNALLOCATED) { |
+ switch (UnallocatedLocation::Cast(result_location).policy()) { |
+ case UnallocatedLocation::REGISTER: |
+ result_location = RegisterLocation( |
+ AllocateFreeRegister(blocked_registers)); |
+ break; |
+ case UnallocatedLocation::SAME_AS_FIRST_INPUT: |
+ result_location = summary->InputLocationAt(0); |
+ break; |
+ } |
+ summary->set_result_location(result_location); |
+ } |
+} |
+ |
+ |
+void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) { |
+ LocationSummary* summary = instr->GetLocationSummary(); |
+ |
+ // Check if current instruction has any special location requirements. |
+ if (summary == NULL) return; |
+ |
+ AllocateRegisters(summary); |
+ |
+ // Load instruction inputs into allocated registers. |
+ for (intptr_t i = summary->InputLocationsCount() - 1; i >= 0; i--) { |
+ Location loc = summary->InputLocationAt(i); |
+ if (loc.kind() == Location::REGISTER) { |
+ __ popq(ToRegister(loc)); |
+ } |
+ } |
+} |
+ |
+ |
void FlowGraphCompiler::VisitBlocks() { |
for (intptr_t i = 0; i < block_order_.length(); ++i) { |
__ Comment("B%d", i); |
@@ -1131,6 +1218,7 @@ void FlowGraphCompiler::VisitBlocks() { |
// Compile all successors until an exit, branch, or a block entry. |
while ((instr != NULL) && !instr->IsBlockEntry()) { |
if (FLAG_code_comments) EmitComment(instr); |
+ EmitInstructionPrologue(instr); |
instr = instr->Accept(this); |
} |
@@ -1182,7 +1270,14 @@ void FlowGraphCompiler::VisitDo(DoInstr* instr) { |
void FlowGraphCompiler::VisitBind(BindInstr* instr) { |
instr->computation()->Accept(this); |
- __ pushq(RAX); |
+ |
+ if (instr->GetLocationSummary() == NULL) { |
+ // If instruction does not have special location requirements |
+ // then it returns result in register RAX. |
+ __ pushq(RAX); |
+ } else { |
+ __ pushq(ToRegister(instr->GetLocationSummary()->result_location())); |
+ } |
} |