Commit d71374b1 authored by Junliang Yan's avatar Junliang Yan Committed by Commit Bot

PPC/s390: [arm] Port the skipping of arguments adaptor frames.

Port 4f62b4bb

Original Commit Message:

    This is a port of the improvements to the ArgumentsAdaptorTrampoline
    that previously landed for x64. It skips the arguments adaptor frame
    creation if the callee cannot observe the actual arguments (as indicated
    by the "is_safe_to_skip_arguments_adaptor" bit on the SharedFunctionInfo),
    and instead just massages the current stack frame appropriately (either
    by pushing more undefineds in case of under application, or by removing
    the superfluous arguments in case of over application).

R=bmeurer@chromium.org, joransiu@ca.ibm.com, michael_dawson@ca.ibm.com, miladfar@ca.ibm.com
BUG=
LOG=N

Change-Id: I94824c4b3d94f7c93c7526c865b82649426cd3a4
Reviewed-on: https://chromium-review.googlesource.com/c/1495014Reviewed-by: 's avatarMilad Farazmand <miladfar@ca.ibm.com>
Commit-Queue: Junliang Yan <jyan@ca.ibm.com>
Cr-Commit-Position: refs/heads/master@{#59974}
parent c8d0dae8
......@@ -2374,112 +2374,160 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
// -- r6 : new target (passed through to callee)
// -----------------------------------
Label invoke, dont_adapt_arguments, stack_overflow;
Label enough, too_few;
Label dont_adapt_arguments, stack_overflow, skip_adapt_arguments;
__ cmpli(r5, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
__ beq(&dont_adapt_arguments);
__ cmp(r3, r5);
__ blt(&too_few);
{ // Enough parameters: actual >= expected
__ bind(&enough);
EnterArgumentsAdaptorFrame(masm);
Generate_StackOverflowCheck(masm, r5, r8, &stack_overflow);
// Calculate copy start address into r3 and copy end address into r7.
// r3: actual number of arguments as a smi
// r4: function
// r5: expected number of arguments
// r6: new target (passed through to callee)
__ SmiToPtrArrayOffset(r3, r3);
__ add(r3, r3, fp);
// adjust for return address and receiver
__ addi(r3, r3, Operand(2 * kPointerSize));
__ ShiftLeftImm(r7, r5, Operand(kPointerSizeLog2));
__ sub(r7, r3, r7);
// Copy the arguments (including the receiver) to the new stack frame.
// r3: copy start address
// r4: function
// r5: expected number of arguments
// r6: new target (passed through to callee)
// r7: copy end address
__ LoadP(r7, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
__ LoadP(r7, FieldMemOperand(r7, SharedFunctionInfo::kFlagsOffset));
__ TestBitMask(r7, SharedFunctionInfo::IsSafeToSkipArgumentsAdaptorBit::kMask,
r0);
__ bne(&skip_adapt_arguments, cr0);
Label copy;
__ bind(&copy);
__ LoadP(r0, MemOperand(r3, 0));
__ push(r0);
__ cmp(r3, r7); // Compare before moving to next argument.
__ subi(r3, r3, Operand(kPointerSize));
__ bne(&copy);
// -------------------------------------------
// Adapt arguments.
// -------------------------------------------
{
Label under_application, over_application, invoke;
__ cmp(r3, r5);
__ blt(&under_application);
__ b(&invoke);
}
// Enough parameters: actual >= expected
__ bind(&over_application);
{
EnterArgumentsAdaptorFrame(masm);
Generate_StackOverflowCheck(masm, r5, r8, &stack_overflow);
// Calculate copy start address into r3 and copy end address into r7.
// r3: actual number of arguments as a smi
// r4: function
// r5: expected number of arguments
// r6: new target (passed through to callee)
__ SmiToPtrArrayOffset(r3, r3);
__ add(r3, r3, fp);
// adjust for return address and receiver
__ addi(r3, r3, Operand(2 * kPointerSize));
__ ShiftLeftImm(r7, r5, Operand(kPointerSizeLog2));
__ sub(r7, r3, r7);
// Copy the arguments (including the receiver) to the new stack frame.
// r3: copy start address
// r4: function
// r5: expected number of arguments
// r6: new target (passed through to callee)
// r7: copy end address
Label copy;
__ bind(&copy);
__ LoadP(r0, MemOperand(r3, 0));
__ push(r0);
__ cmp(r3, r7); // Compare before moving to next argument.
__ subi(r3, r3, Operand(kPointerSize));
__ bne(&copy);
__ b(&invoke);
}
{ // Too few parameters: Actual < expected
__ bind(&too_few);
// Too few parameters: Actual < expected
__ bind(&under_application);
{
EnterArgumentsAdaptorFrame(masm);
Generate_StackOverflowCheck(masm, r5, r8, &stack_overflow);
// Calculate copy start address into r0 and copy end address is fp.
// r3: actual number of arguments as a smi
// r4: function
// r5: expected number of arguments
// r6: new target (passed through to callee)
__ SmiToPtrArrayOffset(r3, r3);
__ add(r3, r3, fp);
// Copy the arguments (including the receiver) to the new stack frame.
// r3: copy start address
// r4: function
// r5: expected number of arguments
// r6: new target (passed through to callee)
Label copy;
__ bind(&copy);
// Adjust load for return address and receiver.
__ LoadP(r0, MemOperand(r3, 2 * kPointerSize));
__ push(r0);
__ cmp(r3, fp); // Compare before moving to next argument.
__ subi(r3, r3, Operand(kPointerSize));
__ bne(&copy);
// Fill the remaining expected arguments with undefined.
// r4: function
// r5: expected number of arguments
// r6: new target (passed through to callee)
__ LoadRoot(r0, RootIndex::kUndefinedValue);
__ ShiftLeftImm(r7, r5, Operand(kPointerSizeLog2));
__ sub(r7, fp, r7);
// Adjust for frame.
__ subi(r7, r7,
Operand(ArgumentsAdaptorFrameConstants::kFixedFrameSizeFromFp +
kPointerSize));
Label fill;
__ bind(&fill);
__ push(r0);
__ cmp(sp, r7);
__ bne(&fill);
}
EnterArgumentsAdaptorFrame(masm);
Generate_StackOverflowCheck(masm, r5, r8, &stack_overflow);
// Call the entry point.
__ bind(&invoke);
__ mr(r3, r5);
// r3 : expected number of arguments
// r4 : function (passed through to callee)
// r6 : new target (passed through to callee)
static_assert(kJavaScriptCallCodeStartRegister == r5, "ABI mismatch");
__ LoadP(r5, FieldMemOperand(r4, JSFunction::kCodeOffset));
__ CallCodeObject(r5);
// Calculate copy start address into r0 and copy end address is fp.
// r3: actual number of arguments as a smi
// r4: function
// r5: expected number of arguments
// r6: new target (passed through to callee)
__ SmiToPtrArrayOffset(r3, r3);
__ add(r3, r3, fp);
// Store offset of return address for deoptimizer.
masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(
masm->pc_offset());
// Copy the arguments (including the receiver) to the new stack frame.
// r3: copy start address
// r4: function
// r5: expected number of arguments
// r6: new target (passed through to callee)
Label copy;
__ bind(&copy);
// Adjust load for return address and receiver.
__ LoadP(r0, MemOperand(r3, 2 * kPointerSize));
__ push(r0);
__ cmp(r3, fp); // Compare before moving to next argument.
__ subi(r3, r3, Operand(kPointerSize));
__ bne(&copy);
// Fill the remaining expected arguments with undefined.
// r4: function
// r5: expected number of arguments
// r6: new target (passed through to callee)
__ LoadRoot(r0, RootIndex::kUndefinedValue);
__ ShiftLeftImm(r7, r5, Operand(kPointerSizeLog2));
__ sub(r7, fp, r7);
// Adjust for frame.
__ subi(r7, r7,
Operand(ArgumentsAdaptorFrameConstants::kFixedFrameSizeFromFp +
kPointerSize));
Label fill;
__ bind(&fill);
__ push(r0);
__ cmp(sp, r7);
__ bne(&fill);
}
// Call the entry point.
__ bind(&invoke);
__ mr(r3, r5);
// r3 : expected number of arguments
// r4 : function (passed through to callee)
// r6 : new target (passed through to callee)
static_assert(kJavaScriptCallCodeStartRegister == r5, "ABI mismatch");
__ LoadP(r5, FieldMemOperand(r4, JSFunction::kCodeOffset));
__ CallCodeObject(r5);
// Exit frame and return.
LeaveArgumentsAdaptorFrame(masm);
__ blr();
}
// Store offset of return address for deoptimizer.
masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
// -------------------------------------------
// Skip adapt arguments.
// -------------------------------------------
__ bind(&skip_adapt_arguments);
{
// The callee cannot observe the actual arguments, so it's safe to just
// pass the expected arguments by massaging the stack appropriately. See
// http://bit.ly/v8-faster-calls-with-arguments-mismatch for details.
Label under_application, over_application;
__ cmp(r3, r5);
__ blt(&under_application);
__ bind(&over_application);
{
// Remove superfluous parameters from the stack.
__ sub(r7, r3, r5);
__ mr(r3, r5);
__ ShiftLeftImm(r7, r7, Operand(kPointerSizeLog2));
__ add(sp, sp, r7);
__ b(&dont_adapt_arguments);
}
// Exit frame and return.
LeaveArgumentsAdaptorFrame(masm);
__ blr();
__ bind(&under_application);
{
// Fill remaining expected arguments with undefined values.
Label fill;
__ LoadRoot(r7, RootIndex::kUndefinedValue);
__ bind(&fill);
__ addi(r3, r3, Operand(1));
__ push(r7);
__ cmp(r3, r5);
__ blt(&fill);
__ b(&dont_adapt_arguments);
}
}
// -------------------------------------------
// Dont adapt arguments.
......
......@@ -2428,111 +2428,159 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
// -- r5 : new target (passed through to callee)
// -----------------------------------
Label invoke, dont_adapt_arguments, stack_overflow;
Label enough, too_few;
Label dont_adapt_arguments, stack_overflow, skip_adapt_arguments;
__ tmll(r4, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
__ b(Condition(1), &dont_adapt_arguments);
__ CmpLogicalP(r2, r4);
__ blt(&too_few);
__ LoadP(r6, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset));
__ LoadP(r6, FieldMemOperand(r6, SharedFunctionInfo::kFlagsOffset));
__ tmll(r6,
Operand(SharedFunctionInfo::IsSafeToSkipArgumentsAdaptorBit::kMask));
__ bne(&skip_adapt_arguments);
{ // Enough parameters: actual >= expected
__ bind(&enough);
EnterArgumentsAdaptorFrame(masm);
Generate_StackOverflowCheck(masm, r4, r7, &stack_overflow);
// -------------------------------------------
// Adapt arguments.
// -------------------------------------------
{
Label under_application, over_application, invoke;
__ CmpP(r2, r4);
__ blt(&under_application);
// Calculate copy start address into r2 and copy end address into r6.
// r2: actual number of arguments as a smi
// r3: function
// r4: expected number of arguments
// r5: new target (passed through to callee)
__ SmiToPtrArrayOffset(r2, r2);
__ AddP(r2, fp);
// adjust for return address and receiver
__ AddP(r2, r2, Operand(2 * kPointerSize));
__ ShiftLeftP(r6, r4, Operand(kPointerSizeLog2));
__ SubP(r6, r2, r6);
// Copy the arguments (including the receiver) to the new stack frame.
// r2: copy start address
// r3: function
// r4: expected number of arguments
// r5: new target (passed through to callee)
// r6: copy end address
Label copy;
__ bind(&copy);
__ LoadP(r0, MemOperand(r2, 0));
__ push(r0);
__ CmpP(r2, r6); // Compare before moving to next argument.
__ lay(r2, MemOperand(r2, -kPointerSize));
__ bne(&copy);
__ b(&invoke);
}
// Enough parameters: actual >= expected
__ bind(&over_application);
{
EnterArgumentsAdaptorFrame(masm);
Generate_StackOverflowCheck(masm, r4, r7, &stack_overflow);
// Calculate copy start address into r2 and copy end address into r6.
// r2: actual number of arguments as a smi
// r3: function
// r4: expected number of arguments
// r5: new target (passed through to callee)
__ SmiToPtrArrayOffset(r2, r2);
__ AddP(r2, fp);
// adjust for return address and receiver
__ AddP(r2, r2, Operand(2 * kPointerSize));
__ ShiftLeftP(r6, r4, Operand(kPointerSizeLog2));
__ SubP(r6, r2, r6);
// Copy the arguments (including the receiver) to the new stack frame.
// r2: copy start address
// r3: function
// r4: expected number of arguments
// r5: new target (passed through to callee)
// r6: copy end address
Label copy;
__ bind(&copy);
__ LoadP(r0, MemOperand(r2, 0));
__ push(r0);
__ CmpP(r2, r6); // Compare before moving to next argument.
__ lay(r2, MemOperand(r2, -kPointerSize));
__ bne(&copy);
__ b(&invoke);
}
{ // Too few parameters: Actual < expected
__ bind(&too_few);
// Too few parameters: Actual < expected
__ bind(&under_application);
{
EnterArgumentsAdaptorFrame(masm);
Generate_StackOverflowCheck(masm, r4, r7, &stack_overflow);
// Calculate copy start address into r0 and copy end address is fp.
// r2: actual number of arguments as a smi
// r3: function
// r4: expected number of arguments
// r5: new target (passed through to callee)
__ SmiToPtrArrayOffset(r2, r2);
__ lay(r2, MemOperand(r2, fp));
// Copy the arguments (including the receiver) to the new stack frame.
// r2: copy start address
// r3: function
// r4: expected number of arguments
// r5: new target (passed through to callee)
Label copy;
__ bind(&copy);
// Adjust load for return address and receiver.
__ LoadP(r0, MemOperand(r2, 2 * kPointerSize));
__ push(r0);
__ CmpP(r2, fp); // Compare before moving to next argument.
__ lay(r2, MemOperand(r2, -kPointerSize));
__ bne(&copy);
// Fill the remaining expected arguments with undefined.
// r3: function
// r4: expected number of argumentus
__ LoadRoot(r0, RootIndex::kUndefinedValue);
__ ShiftLeftP(r6, r4, Operand(kPointerSizeLog2));
__ SubP(r6, fp, r6);
// Adjust for frame.
__ SubP(r6, r6,
Operand(ArgumentsAdaptorFrameConstants::kFixedFrameSizeFromFp +
kPointerSize));
Label fill;
__ bind(&fill);
__ push(r0);
__ CmpP(sp, r6);
__ bne(&fill);
}
EnterArgumentsAdaptorFrame(masm);
Generate_StackOverflowCheck(masm, r4, r7, &stack_overflow);
// Call the entry point.
__ bind(&invoke);
__ LoadRR(r2, r4);
// r2 : expected number of arguments
// r3 : function (passed through to callee)
// r5 : new target (passed through to callee)
static_assert(kJavaScriptCallCodeStartRegister == r4, "ABI mismatch");
__ LoadP(r4, FieldMemOperand(r3, JSFunction::kCodeOffset));
__ CallCodeObject(r4);
// Calculate copy start address into r0 and copy end address is fp.
// r2: actual number of arguments as a smi
// r3: function
// r4: expected number of arguments
// r5: new target (passed through to callee)
__ SmiToPtrArrayOffset(r2, r2);
__ lay(r2, MemOperand(r2, fp));
// Store offset of return address for deoptimizer.
masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(
masm->pc_offset());
// Copy the arguments (including the receiver) to the new stack frame.
// r2: copy start address
// r3: function
// r4: expected number of arguments
// r5: new target (passed through to callee)
Label copy;
__ bind(&copy);
// Adjust load for return address and receiver.
__ LoadP(r0, MemOperand(r2, 2 * kPointerSize));
__ push(r0);
__ CmpP(r2, fp); // Compare before moving to next argument.
__ lay(r2, MemOperand(r2, -kPointerSize));
__ bne(&copy);
// Fill the remaining expected arguments with undefined.
// r3: function
// r4: expected number of argumentus
__ LoadRoot(r0, RootIndex::kUndefinedValue);
__ ShiftLeftP(r6, r4, Operand(kPointerSizeLog2));
__ SubP(r6, fp, r6);
// Adjust for frame.
__ SubP(r6, r6,
Operand(ArgumentsAdaptorFrameConstants::kFixedFrameSizeFromFp +
kPointerSize));
Label fill;
__ bind(&fill);
__ push(r0);
__ CmpP(sp, r6);
__ bne(&fill);
// Exit frame and return.
LeaveArgumentsAdaptorFrame(masm);
__ Ret();
}
// Call the entry point.
__ bind(&invoke);
__ LoadRR(r2, r4);
// r2 : expected number of arguments
// r3 : function (passed through to callee)
// r5 : new target (passed through to callee)
static_assert(kJavaScriptCallCodeStartRegister == r4, "ABI mismatch");
__ LoadP(r4, FieldMemOperand(r3, JSFunction::kCodeOffset));
__ CallCodeObject(r4);
// Store offset of return address for deoptimizer.
masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
// -------------------------------------------
// Skip adapt arguments.
// -------------------------------------------
__ bind(&skip_adapt_arguments);
{
// The callee cannot observe the actual arguments, so it's safe to just
// pass the expected arguments by massaging the stack appropriately. See
// http://bit.ly/v8-faster-calls-with-arguments-mismatch for details.
Label under_application, over_application;
__ CmpP(r2, r4);
__ blt(&under_application);
__ bind(&over_application);
{
// Remove superfluous parameters from the stack.
__ SubP(r6, r2, r4);
__ lgr(r2, r4);
__ ShiftLeftP(r6, r6, Operand(kPointerSizeLog2));
__ lay(sp, MemOperand(sp, r6));
__ b(&dont_adapt_arguments);
}
// Exit frame and return.
LeaveArgumentsAdaptorFrame(masm);
__ Ret();
__ bind(&under_application);
{
// Fill remaining expected arguments with undefined values.
Label fill;
__ LoadRoot(r6, RootIndex::kUndefinedValue);
__ bind(&fill);
__ AddP(r2, r2, Operand(1));
__ push(r6);
__ CmpP(r2, r4);
__ blt(&fill);
__ b(&dont_adapt_arguments);
}
}
// -------------------------------------------
// Dont adapt arguments.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment