Index: src/arm/macro-assembler-arm.cc |
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc |
index 80aef0c4ffefa253069de6ac66473a4ac116b2a4..54063bbb1b7343ecd7695ff3649bae983844dd54 100644 |
--- a/src/arm/macro-assembler-arm.cc |
+++ b/src/arm/macro-assembler-arm.cc |
@@ -1300,6 +1300,64 @@ void MacroAssembler::MovFromFloatParameter(DwVfpRegister dst) { |
MovFromFloatResult(dst); |
} |
+void MacroAssembler::PrepareForTailCall(const ParameterCount& callee_args_count, |
+ Register caller_args_count_reg, |
+ Register scratch0, Register scratch1) { |
+#if DEBUG |
+ if (callee_args_count.is_reg()) { |
+ DCHECK(!AreAliased(callee_args_count.reg(), caller_args_count_reg, scratch0, |
+ scratch1)); |
+ } else { |
+ DCHECK(!AreAliased(caller_args_count_reg, scratch0, scratch1)); |
+ } |
+#endif |
+ |
+ // Calculate the end of destination area where we will put the arguments |
+ // after we drop current frame. We add kPointerSize to count the receiver |
+ // argument which is not included into formal parameters count. |
+ Register dst_reg = scratch0; |
+ add(dst_reg, fp, Operand(caller_args_count_reg, LSL, kPointerSizeLog2)); |
+ add(dst_reg, dst_reg, |
+ Operand(StandardFrameConstants::kCallerSPOffset + kPointerSize)); |
+ |
+ Register src_reg = caller_args_count_reg; |
+ // Calculate the end of source area. +kPointerSize is for the receiver. |
+ if (callee_args_count.is_reg()) { |
+ add(src_reg, sp, Operand(callee_args_count.reg(), LSL, kPointerSizeLog2)); |
+ add(src_reg, src_reg, Operand(kPointerSize)); |
+ } else { |
+ add(src_reg, sp, |
+ Operand((callee_args_count.immediate() + 1) * kPointerSize)); |
+ } |
+ |
+ if (FLAG_debug_code) { |
+ cmp(src_reg, dst_reg); |
+ Check(lo, kStackAccessBelowStackPointer); |
+ } |
+ |
+ // Restore caller's frame pointer and return address now as they will be |
+ // overwritten by the copying loop. |
+ ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); |
+ ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
+ |
+ // Now copy callee arguments to the caller frame going backwards to avoid |
+ // callee arguments corruption (source and destination areas could overlap). |
+ |
+ // Both src_reg and dst_reg are pointing to the word after the one to copy, |
+ // so they must be pre-decremented in the loop. |
+ Register tmp_reg = scratch1; |
+ Label loop, entry; |
+ b(&entry); |
+ bind(&loop); |
+ ldr(tmp_reg, MemOperand(src_reg, -kPointerSize, PreIndex)); |
+ str(tmp_reg, MemOperand(dst_reg, -kPointerSize, PreIndex)); |
+ bind(&entry); |
+ cmp(sp, src_reg); |
+ b(ne, &loop); |
+ |
+ // Leave current frame. |
+ mov(sp, dst_reg); |
+} |
void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
const ParameterCount& actual, |