Index: src/arm64/macro-assembler-arm64.cc |
diff --git a/src/arm64/macro-assembler-arm64.cc b/src/arm64/macro-assembler-arm64.cc |
index 953c3fd7f2bf245e24fbe1ed9e0850d726bf9d07..c4a3a998506ccfebb46a1dc8ce08fb4dcbb0c088 100644 |
--- a/src/arm64/macro-assembler-arm64.cc |
+++ b/src/arm64/macro-assembler-arm64.cc |
@@ -2330,6 +2330,66 @@ void MacroAssembler::JumpIfNotUniqueNameInstanceType(Register type, |
B(ne, not_unique_name); |
} |
+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, jssp, Operand(callee_args_count.reg(), LSL, kPointerSizeLog2)); |
+ add(src_reg, src_reg, Operand(kPointerSize)); |
+ } else { |
+ add(src_reg, jssp, |
+ 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(jssp, src_reg); |
+ __ B(ne, &loop); |
+ |
+ // Leave current frame. |
+ __ Mov(jssp, dst_reg); |
+ __ SetStackPointer(jssp); |
+ __ AssertStackConsistency(); |
+} |
void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
const ParameterCount& actual, |