Index: src/arm/lithium-codegen-arm.cc |
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc |
index 0d4d805acbed5ab227d64cf2a6fd7c85635ace07..7c162f7f6009e04dde6b57b57fe55ab3d40b8694 100644 |
--- a/src/arm/lithium-codegen-arm.cc |
+++ b/src/arm/lithium-codegen-arm.cc |
@@ -98,6 +98,38 @@ void LCodeGen::Abort(BailoutReason reason) { |
} |
+void LCodeGen::SaveCallerDoubles() { |
+ ASSERT(info()->saves_caller_doubles()); |
+ ASSERT(NeedsEagerFrame()); |
+ Comment(";;; Save clobbered callee double registers"); |
+ int count = 0; |
+ BitVector* doubles = chunk()->allocated_double_registers(); |
+ BitVector::Iterator save_iterator(doubles); |
+ while (!save_iterator.Done()) { |
+ __ vstr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), |
+ MemOperand(sp, count * kDoubleSize)); |
+ save_iterator.Advance(); |
+ count++; |
+ } |
+} |
+ |
+ |
+void LCodeGen::RestoreCallerDoubles() { |
+ ASSERT(info()->saves_caller_doubles()); |
+ ASSERT(NeedsEagerFrame()); |
+ Comment(";;; Restore clobbered callee double registers"); |
+ BitVector* doubles = chunk()->allocated_double_registers(); |
+ BitVector::Iterator save_iterator(doubles); |
+ int count = 0; |
+ while (!save_iterator.Done()) { |
+ __ vldr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), |
+ MemOperand(sp, count * kDoubleSize)); |
+ save_iterator.Advance(); |
+ count++; |
+ } |
+} |
+ |
+ |
bool LCodeGen::GeneratePrologue() { |
ASSERT(is_generating()); |
@@ -158,16 +190,7 @@ bool LCodeGen::GeneratePrologue() { |
} |
if (info()->saves_caller_doubles()) { |
- Comment(";;; Save clobbered callee double registers"); |
- int count = 0; |
- BitVector* doubles = chunk()->allocated_double_registers(); |
- BitVector::Iterator save_iterator(doubles); |
- while (!save_iterator.Done()) { |
- __ vstr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), |
- MemOperand(sp, count * kDoubleSize)); |
- save_iterator.Advance(); |
- count++; |
- } |
+ SaveCallerDoubles(); |
} |
// Possibly allocate a local context. |
@@ -313,6 +336,7 @@ bool LCodeGen::GenerateDeoptJumpTable() { |
Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); |
} |
if (deopt_jump_table_[i].needs_frame) { |
+ ASSERT(!info()->saves_caller_doubles()); |
__ mov(ip, Operand(ExternalReference::ForDeoptEntry(entry))); |
if (needs_frame.is_bound()) { |
__ b(&needs_frame); |
@@ -330,6 +354,10 @@ bool LCodeGen::GenerateDeoptJumpTable() { |
__ mov(pc, ip); |
} |
} else { |
+ if (info()->saves_caller_doubles()) { |
+ ASSERT(info()->IsStub()); |
+ RestoreCallerDoubles(); |
+ } |
__ mov(lr, Operand(pc), LeaveCC, al); |
__ mov(pc, Operand(ExternalReference::ForDeoptEntry(entry))); |
} |
@@ -828,7 +856,10 @@ void LCodeGen::DeoptimizeIf(Condition condition, |
} |
ASSERT(info()->IsStub() || frame_is_built_); |
- if (condition == al && frame_is_built_) { |
+ // Go through jump table if we need to handle condition, build frame, or |
+ // restore caller doubles. |
+ if (condition == al && frame_is_built_ && |
+ !info()->saves_caller_doubles()) { |
__ Call(entry, RelocInfo::RUNTIME_ENTRY); |
} else { |
// We often have several deopts to the same entry, reuse the last |
@@ -2959,16 +2990,7 @@ void LCodeGen::DoReturn(LReturn* instr) { |
__ CallRuntime(Runtime::kTraceExit, 1); |
} |
if (info()->saves_caller_doubles()) { |
- ASSERT(NeedsEagerFrame()); |
- BitVector* doubles = chunk()->allocated_double_registers(); |
- BitVector::Iterator save_iterator(doubles); |
- int count = 0; |
- while (!save_iterator.Done()) { |
- __ vldr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), |
- MemOperand(sp, count * kDoubleSize)); |
- save_iterator.Advance(); |
- count++; |
- } |
+ RestoreCallerDoubles(); |
} |
int no_frame_start = -1; |
if (NeedsEagerFrame()) { |