PPC/s390: [turbofan] Introduce JSCallForwardVarargs operator.
Port 69747e2658
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.
R=bmeurer@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com
BUG=v8:5267,v8:5726
LOG=N
Review-Url: https://codereview.chromium.org/2656363002
Cr-Commit-Position: refs/heads/master@{#42745}
This commit is contained in:
parent
53667c89b0
commit
e668872857
@ -2305,6 +2305,76 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_CallForwardVarargs(MacroAssembler* masm,
|
||||
Handle<Code> code) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r4 : the target to call (can be any Object)
|
||||
// -- r5 : start index (to support rest parameters)
|
||||
// -- lr : return address.
|
||||
// -- sp[0] : thisArgument
|
||||
// -----------------------------------
|
||||
|
||||
// Check if we have an arguments adaptor frame below the function frame.
|
||||
Label arguments_adaptor, arguments_done;
|
||||
__ LoadP(r6, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
|
||||
__ LoadP(ip, MemOperand(r6, CommonFrameConstants::kContextOrFrameTypeOffset));
|
||||
__ CmpSmiLiteral(ip, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
|
||||
__ beq(&arguments_adaptor);
|
||||
{
|
||||
__ LoadP(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
|
||||
__ LoadP(r3, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ LoadWordArith(
|
||||
r3,
|
||||
FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
|
||||
__ mr(r6, fp);
|
||||
}
|
||||
__ b(&arguments_done);
|
||||
__ bind(&arguments_adaptor);
|
||||
{
|
||||
// Load the length from the ArgumentsAdaptorFrame.
|
||||
__ LoadP(r3, MemOperand(r6, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
||||
}
|
||||
__ bind(&arguments_done);
|
||||
|
||||
Label stack_empty, stack_done, stack_overflow;
|
||||
__ SmiUntag(r3);
|
||||
__ sub(r3, r3, r5);
|
||||
__ cmpi(r3, Operand::Zero());
|
||||
__ ble(&stack_empty);
|
||||
{
|
||||
// Check for stack overflow.
|
||||
Generate_StackOverflowCheck(masm, r3, r5, &stack_overflow);
|
||||
|
||||
// Forward the arguments from the caller frame.
|
||||
{
|
||||
Label loop;
|
||||
__ addi(r6, r6, Operand(kPointerSize));
|
||||
__ mr(r5, r3);
|
||||
__ bind(&loop);
|
||||
{
|
||||
__ ShiftLeftImm(ip, r5, Operand(kPointerSizeLog2));
|
||||
__ LoadPX(ip, MemOperand(r6, ip));
|
||||
__ push(ip);
|
||||
__ subi(r5, r5, Operand(1));
|
||||
__ cmpi(r5, Operand::Zero());
|
||||
__ bne(&loop);
|
||||
}
|
||||
}
|
||||
}
|
||||
__ b(&stack_done);
|
||||
__ bind(&stack_overflow);
|
||||
__ TailCallRuntime(Runtime::kThrowStackOverflow);
|
||||
__ bind(&stack_empty);
|
||||
{
|
||||
// We just pass the receiver, which is already on the stack.
|
||||
__ mov(r3, Operand::Zero());
|
||||
}
|
||||
__ bind(&stack_done);
|
||||
|
||||
__ Jump(code, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Drops top JavaScript frame and an arguments adaptor frame below it (if
|
||||
|
@ -2317,6 +2317,75 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_CallForwardVarargs(MacroAssembler* masm,
|
||||
Handle<Code> code) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r3 : the target to call (can be any Object)
|
||||
// -- r4 : start index (to support rest parameters)
|
||||
// -- lr : return address.
|
||||
// -- sp[0] : thisArgument
|
||||
// -----------------------------------
|
||||
|
||||
// Check if we have an arguments adaptor frame below the function frame.
|
||||
Label arguments_adaptor, arguments_done;
|
||||
__ LoadP(r5, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
|
||||
__ LoadP(ip, MemOperand(r5, CommonFrameConstants::kContextOrFrameTypeOffset));
|
||||
__ CmpSmiLiteral(ip, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
|
||||
__ beq(&arguments_adaptor);
|
||||
{
|
||||
__ LoadP(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
|
||||
__ LoadP(r2, FieldMemOperand(r2, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ LoadW(r2, FieldMemOperand(
|
||||
r2, SharedFunctionInfo::kFormalParameterCountOffset));
|
||||
__ LoadRR(r5, fp);
|
||||
}
|
||||
__ b(&arguments_done);
|
||||
__ bind(&arguments_adaptor);
|
||||
{
|
||||
// Load the length from the ArgumentsAdaptorFrame.
|
||||
__ LoadP(r2, MemOperand(r5, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
||||
}
|
||||
__ bind(&arguments_done);
|
||||
|
||||
Label stack_empty, stack_done, stack_overflow;
|
||||
__ SmiUntag(r2);
|
||||
__ SubP(r2, r2, r4);
|
||||
__ CmpP(r2, Operand::Zero());
|
||||
__ ble(&stack_empty);
|
||||
{
|
||||
// Check for stack overflow.
|
||||
Generate_StackOverflowCheck(masm, r2, r4, &stack_overflow);
|
||||
|
||||
// Forward the arguments from the caller frame.
|
||||
{
|
||||
Label loop;
|
||||
__ AddP(r5, r5, Operand(kPointerSize));
|
||||
__ LoadRR(r4, r2);
|
||||
__ bind(&loop);
|
||||
{
|
||||
__ ShiftLeftP(ip, r4, Operand(kPointerSizeLog2));
|
||||
__ LoadP(ip, MemOperand(r5, ip));
|
||||
__ push(ip);
|
||||
__ SubP(r4, r4, Operand(1));
|
||||
__ CmpP(r4, Operand::Zero());
|
||||
__ bne(&loop);
|
||||
}
|
||||
}
|
||||
}
|
||||
__ b(&stack_done);
|
||||
__ bind(&stack_overflow);
|
||||
__ TailCallRuntime(Runtime::kThrowStackOverflow);
|
||||
__ bind(&stack_empty);
|
||||
{
|
||||
// We just pass the receiver, which is already on the stack.
|
||||
__ mov(r2, Operand::Zero());
|
||||
}
|
||||
__ bind(&stack_done);
|
||||
|
||||
__ Jump(code, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Drops top JavaScript frame and an arguments adaptor frame below it (if
|
||||
|
@ -174,6 +174,13 @@ void CallTrampolineDescriptor::InitializePlatformSpecific(
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void CallForwardVarargsDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
// r5 : start index (to support rest parameters)
|
||||
// r4 : the target to call
|
||||
Register registers[] = {r4, r5};
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void ConstructStubDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
|
@ -161,6 +161,14 @@ void CallTrampolineDescriptor::InitializePlatformSpecific(
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void CallForwardVarargsDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
// r4 : start index (to support rest parameters)
|
||||
// r3 : the target to call
|
||||
Register registers[] = {r3, r4};
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void ConstructStubDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
// r2 : number of arguments
|
||||
|
Loading…
Reference in New Issue
Block a user