| Index: src/x64/macro-assembler-x64.cc
|
| diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
|
| index 59a836062b86fe57cd120f4a50a9418144e2fd1d..24dbdd6dae3ed568922bdee98bb43f4754c5b428 100644
|
| --- a/src/x64/macro-assembler-x64.cc
|
| +++ b/src/x64/macro-assembler-x64.cc
|
| @@ -4027,6 +4027,103 @@ void MacroAssembler::DebugBreak() {
|
| }
|
|
|
|
|
| +//
|
| +// Stack structure for the function g() tail calling f():
|
| +//
|
| +// ------- Caller frame: -------
|
| +// | ...
|
| +// | g()'s arg M
|
| +// | ...
|
| +// | g()'s arg 1
|
| +// | g()'s receiver arg
|
| +// | g()'s caller pc
|
| +// ------- g()'s frame: -------
|
| +// | g()'s caller fp <- fp
|
| +// | g()'s context
|
| +// | function pointer: g
|
| +// | -------------------------
|
| +// | ...
|
| +// | ...
|
| +// | f()'s arg N
|
| +// | ...
|
| +// | f()'s arg 1
|
| +// | f()'s receiver arg
|
| +// | f()'s caller pc <- sp
|
| +// ----------------------
|
| +//
|
| +void MacroAssembler::DropCurrentJSFrame(Register args_reg, Register scratch1,
|
| + Register scratch2, Register scratch3) {
|
| + DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
|
| +
|
| + Label no_arguments_adaptor, formal_parameter_count_loaded;
|
| + // TODO(ishell): check for arguments adaptor frame presence
|
| + movp(scratch2, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
|
| + Cmp(Operand(scratch2, StandardFrameConstants::kContextOffset),
|
| + Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
|
| + j(not_equal, &no_arguments_adaptor, Label::kNear);
|
| +
|
| + // Drop arguments adaptor frame and load arguments count.
|
| + movp(rbp, scratch2);
|
| + SmiToInteger32(scratch1,
|
| + Operand(rbp, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
| + jmp(&formal_parameter_count_loaded, Label::kNear);
|
| +
|
| + bind(&no_arguments_adaptor);
|
| + // Load caller's formal parameter count
|
| + movp(scratch1, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
|
| + movp(scratch1, FieldOperand(scratch1, JSFunction::kSharedFunctionInfoOffset));
|
| + LoadSharedFunctionInfoSpecialField(
|
| + scratch1, scratch1, SharedFunctionInfo::kFormalParameterCountOffset);
|
| +
|
| + bind(&formal_parameter_count_loaded);
|
| +
|
| + // Calculate the destination address where we will put the return address
|
| + // after we drop current frame.
|
| + Register new_sp_reg = scratch2;
|
| + subp(scratch1, args_reg);
|
| + leap(new_sp_reg, Operand(rbp, scratch1, times_pointer_size,
|
| + StandardFrameConstants::kCallerPCOffset));
|
| +
|
| + if (emit_debug_code()) {
|
| + cmpp(rsp, new_sp_reg);
|
| + Check(below, kStackAccessBelowStackPointer);
|
| + }
|
| +
|
| + // Copy receiver and return address as well.
|
| + Register count_reg = scratch1;
|
| + leap(count_reg, Operand(args_reg, 2));
|
| +
|
| + // Copy return address from caller's frame to current frame's return address
|
| + // to avoid its trashing and let the following loop copy it to the right
|
| + // place.
|
| + Register tmp_reg = scratch3;
|
| + movp(tmp_reg, Operand(rbp, StandardFrameConstants::kCallerPCOffset));
|
| + movp(Operand(rsp, 0), tmp_reg);
|
| +
|
| + // Restore caller's frame pointer now as it could be overwritten by
|
| + // the copying loop.
|
| + movp(rbp, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
|
| +
|
| + Operand src(rsp, count_reg, times_pointer_size, 0);
|
| + Operand dst(new_sp_reg, count_reg, times_pointer_size, 0);
|
| +
|
| + // Now copy callee arguments to the caller frame going backwards to avoid
|
| + // callee arguments corruption (source and destination areas could overlap).
|
| + Label loop, entry;
|
| + jmp(&entry, Label::kNear);
|
| + bind(&loop);
|
| + decp(count_reg);
|
| + movp(tmp_reg, src);
|
| + movp(dst, tmp_reg);
|
| + bind(&entry);
|
| + cmpp(count_reg, Immediate(0));
|
| + j(not_equal, &loop, Label::kNear);
|
| +
|
| + // Leave current frame.
|
| + movp(rsp, new_sp_reg);
|
| +}
|
| +
|
| +
|
| void MacroAssembler::InvokeFunction(Register function,
|
| Register new_target,
|
| const ParameterCount& actual,
|
| @@ -5083,13 +5180,13 @@ void MacroAssembler::InitializeFieldsWithFiller(Register current_address,
|
| Register end_address,
|
| Register filler) {
|
| Label loop, entry;
|
| - jmp(&entry);
|
| + jmp(&entry, Label::kNear);
|
| bind(&loop);
|
| movp(Operand(current_address, 0), filler);
|
| addp(current_address, Immediate(kPointerSize));
|
| bind(&entry);
|
| cmpp(current_address, end_address);
|
| - j(below, &loop);
|
| + j(below, &loop, Label::kNear);
|
| }
|
|
|
|
|
|
|