Index: src/ppc/macro-assembler-ppc.cc |
diff --git a/src/ppc/macro-assembler-ppc.cc b/src/ppc/macro-assembler-ppc.cc |
index 14759de0da334b700d2f96e720489672948b493b..3f8640a408fdf9b9393c78c164d387705424c0a9 100644 |
--- a/src/ppc/macro-assembler-ppc.cc |
+++ b/src/ppc/macro-assembler-ppc.cc |
@@ -1093,6 +1093,67 @@ void MacroAssembler::MovFromFloatParameter(const DoubleRegister dst) { |
Move(dst, d1); |
} |
+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; |
+ ShiftLeftImm(dst_reg, caller_args_count_reg, Operand(kPointerSizeLog2)); |
+ add(dst_reg, fp, dst_reg); |
+ addi(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()) { |
+ ShiftLeftImm(src_reg, callee_args_count.reg(), Operand(kPointerSizeLog2)); |
+ add(src_reg, sp, src_reg); |
+ addi(src_reg, src_reg, Operand(kPointerSize)); |
+ } else { |
+ Add(src_reg, sp, (callee_args_count.immediate() + 1) * kPointerSize, r0); |
+ } |
+ |
+ if (FLAG_debug_code) { |
+ cmpl(src_reg, dst_reg); |
+ Check(lt, kStackAccessBelowStackPointer); |
+ } |
+ |
+ // Restore caller's frame pointer and return address now as they will be |
+ // overwritten by the copying loop. |
+ RestoreFrameStateForTailCall(); |
+ |
+ // 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; |
+ if (callee_args_count.is_reg()) { |
+ addi(tmp_reg, callee_args_count.reg(), Operand(1)); // +1 for receiver |
+ } else { |
+ mov(tmp_reg, Operand(callee_args_count.immediate() + 1)); |
+ } |
+ mtctr(tmp_reg); |
+ bind(&loop); |
+ LoadPU(tmp_reg, MemOperand(src_reg, -kPointerSize)); |
+ StorePU(tmp_reg, MemOperand(dst_reg, -kPointerSize)); |
+ bdnz(&loop); |
+ |
+ // Leave current frame. |
+ mr(sp, dst_reg); |
+} |
void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
const ParameterCount& actual, Label* done, |