Index: src/arm/virtual-frame-arm.cc |
=================================================================== |
--- src/arm/virtual-frame-arm.cc (revision 4341) |
+++ src/arm/virtual-frame-arm.cc (working copy) |
@@ -37,37 +37,123 @@ |
#define __ ACCESS_MASM(masm()) |
-void VirtualFrame::SyncElementBelowStackPointer(int index) { |
- UNREACHABLE(); |
+void VirtualFrame::PopToR1R0() { |
+ VirtualFrame where_to_go = *this; |
+ where_to_go.top_of_stack_state_ = R1_R0_TOS; |
+ MergeTo(&where_to_go); |
Søren Thygesen Gjesse
2010/04/07 10:46:51
Maybe add a comment here saying the r0/r1 TOS stat
Erik Corry
2010/04/07 12:49:17
Done.
|
+ element_count_ -= 2; |
+ top_of_stack_state_ = NO_TOS_REGISTERS; |
} |
-void VirtualFrame::SyncElementByPushing(int index) { |
- UNREACHABLE(); |
+void VirtualFrame::PopToR1() { |
+ VirtualFrame where_to_go = *this; |
+ where_to_go.top_of_stack_state_ = R1_TOS; |
+ MergeTo(&where_to_go); |
+ element_count_ -= 1; |
+ top_of_stack_state_ = NO_TOS_REGISTERS; |
} |
-void VirtualFrame::MergeTo(VirtualFrame* expected) { |
- // ARM frames are currently always in memory. |
- ASSERT(Equals(expected)); |
+void VirtualFrame::PopToR0() { |
+ VirtualFrame where_to_go = *this; |
+ where_to_go.top_of_stack_state_ = R0_TOS; |
+ MergeTo(&where_to_go); |
+ element_count_ -= 1; |
+ top_of_stack_state_ = NO_TOS_REGISTERS; |
} |
-void VirtualFrame::MergeMoveRegistersToMemory(VirtualFrame* expected) { |
- UNREACHABLE(); |
+void VirtualFrame::MergeTo(VirtualFrame* expected) { |
Kasper Lund
2010/04/07 08:09:50
Do you have good tests of this function? Full cove
Erik Corry
2010/04/07 12:49:17
No. The coverage tool for covering code generated
|
+ if (Equals(expected)) return; |
+ switch (top_of_stack_state_ * 5 + expected->top_of_stack_state_) { |
Søren Thygesen Gjesse
2010/04/07 10:46:51
Maybe add a macro for (one_state * 5 + another_sta
Erik Corry
2010/04/07 12:49:17
On ARM multiplying by 5 should be the same speed a
|
+ case NO_TOS_REGISTERS * 5 + NO_TOS_REGISTERS: |
+ break; |
+ case NO_TOS_REGISTERS * 5 + R0_TOS: |
+ __ pop(r0); |
+ break; |
+ case NO_TOS_REGISTERS * 5 + R1_TOS: |
+ __ pop(r1); |
+ break; |
+ case NO_TOS_REGISTERS * 5 + R1_R0_TOS: |
+ __ pop(r0); |
+ __ pop(r1); |
+ break; |
+ case NO_TOS_REGISTERS * 5 + R0_R1_TOS: |
+ __ pop(r0); |
+ __ pop(r1); |
+ break; |
+ case R0_TOS * 5 + NO_TOS_REGISTERS: |
+ __ push(r0); |
+ break; |
+ case R0_TOS * 5 + R0_TOS: |
+ break; |
+ case R0_TOS * 5 + R1_TOS: |
+ __ mov(r1, r0); |
+ break; |
+ case R0_TOS * 5 + R1_R0_TOS: |
+ __ pop(r1); |
+ break; |
+ case R0_TOS * 5 + R0_R1_TOS: |
+ __ mov(r1, r0); |
+ __ pop(r0); |
+ break; |
+ case R1_TOS * 5 + NO_TOS_REGISTERS: |
+ __ push(r1); |
+ break; |
+ case R1_TOS * 5 + R0_TOS: |
+ __ mov(r0, r1); |
+ break; |
+ case R1_TOS * 5 + R1_TOS: |
+ break; |
+ case R1_TOS * 5 + R1_R0_TOS: |
+ __ mov(r0, r1); |
+ __ pop(r1); |
+ break; |
+ case R1_TOS * 5 + R0_R1_TOS: |
+ __ pop(r0); |
+ break; |
+ case R1_R0_TOS * 5 + NO_TOS_REGISTERS: |
+ __ push(r1); |
+ __ push(r0); |
+ break; |
+ case R1_R0_TOS * 5 + R0_TOS: |
+ __ push(r1); |
+ break; |
+ case R1_R0_TOS * 5 + R1_TOS: |
+ __ push(r1); |
+ __ mov(r1, r0); |
+ break; |
+ case R1_R0_TOS * 5 + R1_R0_TOS: |
+ break; |
+ case R1_R0_TOS * 5 + R0_R1_TOS: |
Søren Thygesen Gjesse
2010/04/07 07:53:37
MacroAssembler::Swap?
Erik Corry
2010/04/07 12:49:17
Done.
|
+ __ eor(r0, r0, Operand(r1)); |
+ __ eor(r1, r1, Operand(r0)); |
+ __ eor(r0, r0, Operand(r1)); |
+ break; |
+ case R0_R1_TOS * 5 + NO_TOS_REGISTERS: |
+ __ push(r0); |
+ __ push(r1); |
+ break; |
+ case R0_R1_TOS * 5 + R0_TOS: |
+ __ push(r0); |
+ __ mov(r0, r1); |
+ break; |
+ case R0_R1_TOS * 5 + R1_TOS: |
+ __ push(r0); |
+ break; |
+ case R0_R1_TOS * 5 + R1_R0_TOS: |
+ __ eor(r0, r0, Operand(r1)); |
Kasper Lund
2010/04/07 08:09:50
Swap again.
Erik Corry
2010/04/07 12:49:17
Done.
|
+ __ eor(r1, r1, Operand(r0)); |
+ __ eor(r0, r0, Operand(r1)); |
+ break; |
+ case R0_R1_TOS * 5 + R0_R1_TOS: |
+ break; |
Søren Thygesen Gjesse
2010/04/07 10:46:51
default with UNREACHABLE()?
Erik Corry
2010/04/07 12:49:17
Done.
|
+ } |
+ ASSERT(register_allocation_map_ == expected->register_allocation_map_); |
} |
-void VirtualFrame::MergeMoveRegistersToRegisters(VirtualFrame* expected) { |
- UNREACHABLE(); |
-} |
- |
- |
-void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame* expected) { |
- UNREACHABLE(); |
-} |
- |
- |
void VirtualFrame::Enter() { |
Comment cmnt(masm(), "[ Enter JS frame"); |
@@ -92,8 +178,6 @@ |
__ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); |
// Adjust FP to point to saved FP. |
__ add(fp, sp, Operand(2 * kPointerSize)); |
- cgen()->allocator()->Unuse(r1); |
- cgen()->allocator()->Unuse(lr); |
} |
@@ -152,37 +236,11 @@ |
-void VirtualFrame::SaveContextRegister() { |
- UNIMPLEMENTED(); |
-} |
- |
- |
-void VirtualFrame::RestoreContextRegister() { |
- UNIMPLEMENTED(); |
-} |
- |
- |
void VirtualFrame::PushReceiverSlotAddress() { |
UNIMPLEMENTED(); |
} |
-int VirtualFrame::InvalidateFrameSlotAt(int index) { |
- UNIMPLEMENTED(); |
- return kIllegalIndex; |
-} |
- |
- |
-void VirtualFrame::TakeFrameSlotAt(int index) { |
- UNIMPLEMENTED(); |
-} |
- |
- |
-void VirtualFrame::StoreToFrameSlotAt(int index) { |
- UNIMPLEMENTED(); |
-} |
- |
- |
void VirtualFrame::PushTryHandler(HandlerType type) { |
// Grow the expression stack by handler size less one (the return |
// address in lr is already counted by a call instruction). |
@@ -247,47 +305,155 @@ |
} |
Søren Thygesen Gjesse
2010/04/07 10:46:51
Lining up the states in a comment here could be he
Erik Corry
2010/04/07 12:49:17
Done.
|
+const bool VirtualFrame::kR0InUse[TOS_STATES] = |
+ { false, true, false, true, true }; |
+const bool VirtualFrame::kR1InUse[TOS_STATES] = |
+ { false, false, true, true, true }; |
+const int VirtualFrame::kVirtualElements[TOS_STATES] = { 0, 1, 1, 2, 2 }; |
+const VirtualFrame::TopOfStack VirtualFrame::kPopState[TOS_STATES] = |
+ { NO_TOS_REGISTERS, NO_TOS_REGISTERS, NO_TOS_REGISTERS, R0_TOS, R1_TOS }; |
+const VirtualFrame::TopOfStack VirtualFrame::kPushState[TOS_STATES] = |
+ { R0_TOS, R0_R1_TOS, R1_R0_TOS, R1_R0_TOS, R0_R1_TOS }; |
+const Register VirtualFrame::kTopRegister[TOS_STATES] = { r0, r0, r1, r1, r0 }; |
+const Register VirtualFrame::kBottomRegister[TOS_STATES] = |
+ { r0, r0, r1, r0, r1 }; |
+const Register VirtualFrame::kAllocatedRegisters[ |
+ VirtualFrame::kNumberOfAllocatedRegisters] = { r2, r3, r4, r5, r6 }; |
+ |
+ |
+bool VirtualFrame::SpilledScope::is_spilled_ = false; |
+ |
+ |
void VirtualFrame::Drop(int count) { |
ASSERT(count >= 0); |
ASSERT(height() >= count); |
- int num_virtual_elements = (element_count() - 1) - stack_pointer_; |
- |
- // Emit code to lower the stack pointer if necessary. |
- if (num_virtual_elements < count) { |
- int num_dropped = count - num_virtual_elements; |
- stack_pointer_ -= num_dropped; |
- __ add(sp, sp, Operand(num_dropped * kPointerSize)); |
+ // Discard elements from the virtual frame and free any registers. |
+ int num_virtual_elements = kVirtualElements[top_of_stack_state_]; |
+ while (num_virtual_elements > 0) { |
+ Pop(); |
+ num_virtual_elements--; |
+ count--; |
+ if (count == 0) return; |
} |
- |
- // Discard elements from the virtual frame and free any registers. |
+ if (count == 0) return; |
+ __ add(sp, sp, Operand(count * kPointerSize)); |
element_count_ -= count; |
} |
-Result VirtualFrame::Pop() { |
- UNIMPLEMENTED(); |
- return Result(); |
+void VirtualFrame::Pop() { |
+ if (top_of_stack_state_ == NO_TOS_REGISTERS) { |
+ __ add(sp, sp, Operand(kPointerSize)); |
+ } else { |
+ top_of_stack_state_ = kPopState[top_of_stack_state_]; |
+ } |
+ element_count_--; |
} |
void VirtualFrame::EmitPop(Register reg) { |
- ASSERT(stack_pointer_ == element_count() - 1); |
- stack_pointer_--; |
+ ASSERT(!is_used(reg)); |
+ if (top_of_stack_state_ == NO_TOS_REGISTERS) { |
+ __ pop(reg); |
+ } else { |
+ __ mov(reg, kTopRegister[top_of_stack_state_]); |
+ top_of_stack_state_ = kPopState[top_of_stack_state_]; |
+ } |
element_count_--; |
- __ pop(reg); |
} |
+Register VirtualFrame::Peek() { |
+ AssertIsNotSpilled(); |
+ if (top_of_stack_state_ == NO_TOS_REGISTERS) { |
+ top_of_stack_state_ = kPushState[top_of_stack_state_]; |
+ Register answer = kTopRegister[top_of_stack_state_]; |
+ __ pop(answer); |
+ return answer; |
+ } else { |
+ return kTopRegister[top_of_stack_state_]; |
+ } |
+} |
+ |
+ |
+Register VirtualFrame::PopToRegister(Register but_not_to_this_one) { |
Søren Thygesen Gjesse
2010/04/07 10:46:51
Maybe assert that but_not_to_this_one is one of th
Erik Corry
2010/04/07 12:49:17
Done.
|
+ AssertIsNotSpilled(); |
+ element_count_--; |
+ if (top_of_stack_state_ == NO_TOS_REGISTERS) { |
+ if (but_not_to_this_one.is(r0)) { |
+ __ pop(r1); |
+ return r1; |
+ } else { |
+ __ pop(r0); |
+ return r0; |
+ } |
+ } else { |
Søren Thygesen Gjesse
2010/04/07 10:46:51
Isn't but_not_to_this_one ignored in the else part
Erik Corry
2010/04/07 12:49:17
Yes, because it never happens.
|
+ Register answer = kTopRegister[top_of_stack_state_]; |
+ top_of_stack_state_ = kPopState[top_of_stack_state_]; |
Søren Thygesen Gjesse
2010/04/07 10:46:51
ASSERT(!answer.is(but_not_to_this_one));
Erik Corry
2010/04/07 12:49:17
Done.
|
+ return answer; |
+ } |
+} |
+ |
+ |
void VirtualFrame::EmitPush(Register reg) { |
- ASSERT(stack_pointer_ == element_count() - 1); |
element_count_++; |
- stack_pointer_++; |
- __ push(reg); |
+ if (SpilledScope::is_spilled()) { |
+ __ push(reg); |
+ return; |
+ } |
+ if (top_of_stack_state_ == NO_TOS_REGISTERS) { |
+ if (reg.is(r0)) { |
+ top_of_stack_state_ = R0_TOS; |
+ return; |
+ } |
+ if (reg.is(r1)) { |
+ top_of_stack_state_ = R1_TOS; |
+ return; |
+ } |
+ } |
Søren Thygesen Gjesse
2010/04/07 10:46:51
Maybe add some kind of helper function "EnsureOneF
Erik Corry
2010/04/07 12:49:17
Done.
|
+ if (kVirtualElements[top_of_stack_state_] == kMaxTOSRegisters) { |
+ __ push(kBottomRegister[top_of_stack_state_]); |
+ } |
+ top_of_stack_state_ = kPushState[top_of_stack_state_]; |
+ Register dest = kTopRegister[top_of_stack_state_]; |
+ if (!dest.is(reg)) { |
+ __ mov(dest, reg); |
+ } |
} |
+Register VirtualFrame::GetTOSRegister() { |
+ if (SpilledScope::is_spilled()) return r0; |
+ |
+ if (kVirtualElements[top_of_stack_state_] == kMaxTOSRegisters) { |
+ Register answer = kBottomRegister[top_of_stack_state_]; |
+ __ push(answer); |
+ top_of_stack_state_ = kPushState[top_of_stack_state_]; |
+ top_of_stack_state_ = kPopState[top_of_stack_state_]; |
+ return answer; |
+ } |
+ |
+ return kTopRegister[kPushState[top_of_stack_state_]]; |
+} |
+ |
+ |
+void VirtualFrame::EmitPush(MemOperand operand) { |
+ element_count_++; |
+ if (SpilledScope::is_spilled()) { |
+ __ ldr(r0, operand); |
+ __ push(r0); |
+ return; |
+ } |
+ if (kVirtualElements[top_of_stack_state_] == kMaxTOSRegisters) { |
+ __ push(kBottomRegister[top_of_stack_state_]); |
+ } |
+ top_of_stack_state_ = kPushState[top_of_stack_state_]; |
+ __ ldr(kTopRegister[top_of_stack_state_], operand); |
+} |
+ |
+ |
void VirtualFrame::EmitPushMultiple(int count, int src_regs) { |
- ASSERT(stack_pointer_ == element_count() - 1); |
+ ASSERT(SpilledScope::is_spilled()); |
Adjust(count); |
__ stm(db_w, sp, src_regs); |
} |