X87: [turbofan] Introduce JSCallForwardVarargs operator.

port 69747e2658f1de973ba75c60fe31b402bd6031a5(r42680)

  original commit message:
  We turn a JSCallFunction node for

    f.apply(receiver, arguments)

  into a JSCallForwardVarargs node, when the arguments refers to the
  arguments of the outermost optimized code object, i.e. not an inlined
  arguments, and the apply method refers to Function.prototype.apply,
  and there's no other user of arguments except in frame states.

  We also replace the arguments node in the graph with a marker for
  the Deoptimizer similar to Crankshaft to make sure we don't materialize
  unused arguments just for the sake of deoptimization. We plan to replace
  this with a saner EscapeAnalysis based solution soon.

BUG=

Review-Url: https://codereview.chromium.org/2681783002
Cr-Commit-Position: refs/heads/master@{#43516}
This commit is contained in:
zhengxing.li 2017-03-01 05:26:55 -08:00 committed by Commit bot
parent 8e681b24f6
commit 6cff2ddf7d
2 changed files with 87 additions and 0 deletions

View File

@ -2312,6 +2312,86 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
}
}
// static
void Builtins::Generate_CallForwardVarargs(MacroAssembler* masm,
Handle<Code> code) {
// ----------- S t a t e -------------
// -- edi : the target to call (can be any Object)
// -- ecx : start index (to support rest parameters)
// -- esp[0] : return address.
// -- esp[4] : thisArgument
// -----------------------------------
// Check if we have an arguments adaptor frame below the function frame.
Label arguments_adaptor, arguments_done;
__ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
__ cmp(Operand(ebx, CommonFrameConstants::kContextOrFrameTypeOffset),
Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
__ j(equal, &arguments_adaptor, Label::kNear);
{
__ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
__ mov(eax, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset));
__ mov(eax,
FieldOperand(eax, SharedFunctionInfo::kFormalParameterCountOffset));
__ mov(ebx, ebp);
}
__ jmp(&arguments_done, Label::kNear);
__ bind(&arguments_adaptor);
{
// Just load the length from the ArgumentsAdaptorFrame.
__ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
}
__ bind(&arguments_done);
Label stack_empty, stack_done;
__ SmiUntag(eax);
__ sub(eax, ecx);
__ j(less_equal, &stack_empty);
{
// Check for stack overflow.
{
// Check the stack for overflow. We are not trying to catch interruptions
// (i.e. debug break and preemption) here, so check the "real stack
// limit".
Label done;
__ LoadRoot(ecx, Heap::kRealStackLimitRootIndex);
// Make ecx the space we have left. The stack might already be
// overflowed here which will cause ecx to become negative.
__ neg(ecx);
__ add(ecx, esp);
__ sar(ecx, kPointerSizeLog2);
// Check if the arguments will overflow the stack.
__ cmp(ecx, eax);
__ j(greater, &done, Label::kNear); // Signed comparison.
__ TailCallRuntime(Runtime::kThrowStackOverflow);
__ bind(&done);
}
// Forward the arguments from the caller frame.
{
Label loop;
__ mov(ecx, eax);
__ pop(edx);
__ bind(&loop);
{
__ Push(Operand(ebx, ecx, times_pointer_size, 1 * kPointerSize));
__ dec(ecx);
__ j(not_zero, &loop);
}
__ push(edx);
}
}
__ jmp(&stack_done, Label::kNear);
__ bind(&stack_empty);
{
// We just pass the receiver, which is already on the stack.
__ Move(eax, Immediate(0));
}
__ bind(&stack_done);
__ Jump(code, RelocInfo::CODE_TARGET);
}
namespace {
// Drops top JavaScript frame and an arguments adaptor frame below it (if

View File

@ -174,6 +174,13 @@ void CallTrampolineDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// ecx : start index (to support rest parameters)
// edi : the target to call
Register registers[] = {edi, ecx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructStubDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {