Index: src/mips/macro-assembler-mips.cc |
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc |
index 76b724ceebc6e41257ea0bd8e0fac541acc430d9..dd9e7d980e87438b7ff4d8b1d01745310aedc692 100644 |
--- a/src/mips/macro-assembler-mips.cc |
+++ b/src/mips/macro-assembler-mips.cc |
@@ -4095,6 +4095,65 @@ void MacroAssembler::MovToFloatParameters(DoubleRegister src1, |
// ----------------------------------------------------------------------------- |
// JavaScript invokes. |
+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; |
+ Lsa(dst_reg, fp, caller_args_count_reg, kPointerSizeLog2); |
+ Addu(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()) { |
+ Lsa(src_reg, sp, callee_args_count.reg(), kPointerSizeLog2); |
+ Addu(src_reg, src_reg, Operand(kPointerSize)); |
+ } else { |
+ Addu(src_reg, sp, |
+ Operand((callee_args_count.immediate() + 1) * kPointerSize)); |
+ } |
+ |
+ if (FLAG_debug_code) { |
+ Check(lo, kStackAccessBelowStackPointer, src_reg, Operand(dst_reg)); |
+ } |
+ |
+ // Restore caller's frame pointer and return address now as they will be |
+ // overwritten by the copying loop. |
+ lw(ra, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); |
+ lw(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; |
+ Branch(&entry); |
+ bind(&loop); |
+ Subu(src_reg, src_reg, Operand(kPointerSize)); |
+ Subu(dst_reg, dst_reg, Operand(kPointerSize)); |
+ lw(tmp_reg, MemOperand(src_reg)); |
+ sw(tmp_reg, MemOperand(dst_reg)); |
+ bind(&entry); |
+ Branch(&loop, ne, sp, Operand(src_reg)); |
+ |
+ // Leave current frame. |
+ mov(sp, dst_reg); |
+} |
+ |
void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
const ParameterCount& actual, |
Label* done, |