Commit 3658a431 authored by Milad Fa's avatar Milad Fa Committed by Commit Bot

PPC/s390: [builtins] Streamline the construct stubs

Port 366d30c9

Original Commit Message:

    - don't restore the context register after InvokeFunction unless we need
      to for throwing exceptions.
    - manually manage the frame to improve code layout for the fast path

R=verwaest@chromium.org, joransiu@ca.ibm.com, junyan@redhat.com, midawson@redhat.com
BUG=
LOG=N

Change-Id: I2db3ccd8948c21bc7c5be34237f016be305d7e72
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2530873Reviewed-by: 's avatarJunliang Yan <junyan@redhat.com>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71109}
parent 11195df8
......@@ -177,10 +177,10 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// -- sp[...]: constructor arguments
// -----------------------------------
FrameScope scope(masm, StackFrame::MANUAL);
// Enter a construct frame.
{
FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT);
Label post_instantiation_deopt_entry, not_create_implicit_receiver;
__ EnterFrame(StackFrame::CONSTRUCT);
// Preserve the incoming parameters on the stack.
__ SmiTag(r3);
......@@ -204,10 +204,9 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
&not_create_implicit_receiver);
// If not derived class constructor: Allocate the new receiver object.
__ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1,
r7, r8);
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1, r7,
r8);
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject), RelocInfo::CODE_TARGET);
__ b(&post_instantiation_deopt_entry);
// Else: use TheHoleValue as receiver for constructor call
......@@ -259,18 +258,8 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ LoadP(r3, MemOperand(fp, ConstructFrameConstants::kLengthOffset));
__ SmiUntag(r3);
Label enough_stack_space, stack_overflow;
Label stack_overflow;
Generate_StackOverflowCheck(masm, r3, r8, &stack_overflow);
__ b(&enough_stack_space);
__ bind(&stack_overflow);
// Restore the context from the frame.
__ LoadP(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowStackOverflow);
// Unreachable code.
__ bkpt(0);
__ bind(&enough_stack_space);
// Copy arguments and receiver to the expression stack.
__ PushArray(r7, r3, r8, r0);
......@@ -297,44 +286,28 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset(
masm->pc_offset());
// Restore the context from the frame.
__ LoadP(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
// If the result is an object (in the ECMA sense), we should get rid
// of the receiver and use the result; see ECMA-262 section 13.2.2-7
// on page 74.
Label use_receiver, do_throw, leave_frame;
Label use_receiver, do_throw, leave_and_return, check_receiver;
// If the result is undefined, we jump out to using the implicit receiver.
__ JumpIfRoot(r3, RootIndex::kUndefinedValue, &use_receiver);
__ JumpIfNotRoot(r3, RootIndex::kUndefinedValue, &check_receiver);
// Otherwise we do a smi check and fall through to check if the return value
// is a valid receiver.
// If the result is a smi, it is *not* an object in the ECMA sense.
__ JumpIfSmi(r3, &use_receiver);
// If the type of the result (stored in its map) is less than
// FIRST_JS_RECEIVER_TYPE, it is not an object in the ECMA sense.
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ CompareObjectType(r3, r7, r7, FIRST_JS_RECEIVER_TYPE);
__ bge(&leave_frame);
__ b(&use_receiver);
__ bind(&do_throw);
__ CallRuntime(Runtime::kThrowConstructorReturnedNonObject);
// Throw away the result of the constructor invocation and use the
// on-stack receiver as the result.
__ bind(&use_receiver);
__ LoadP(r3, MemOperand(sp));
__ JumpIfRoot(r3, RootIndex::kTheHoleValue, &do_throw);
__ bind(&leave_frame);
__ bind(&leave_and_return);
// Restore smi-tagged arguments count from the frame.
__ LoadP(r4, MemOperand(fp, ConstructFrameConstants::kLengthOffset));
// Leave construct frame.
}
__ LeaveFrame(StackFrame::CONSTRUCT);
// Remove caller arguments from the stack and return.
STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
......@@ -343,6 +316,30 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ add(sp, sp, r4);
__ addi(sp, sp, Operand(kSystemPointerSize));
__ blr();
__ bind(&check_receiver);
// If the result is a smi, it is *not* an object in the ECMA sense.
__ JumpIfSmi(r3, &use_receiver);
// If the type of the result (stored in its map) is less than
// FIRST_JS_RECEIVER_TYPE, it is not an object in the ECMA sense.
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ CompareObjectType(r3, r7, r7, FIRST_JS_RECEIVER_TYPE);
__ bge(&leave_and_return);
__ b(&use_receiver);
__ bind(&do_throw);
// Restore the context from the frame.
__ LoadP(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowConstructorReturnedNonObject);
__ bkpt(0);
__ bind(&stack_overflow);
// Restore the context from the frame.
__ LoadP(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowStackOverflow);
// Unreachable code.
__ bkpt(0);
}
void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
......
......@@ -173,10 +173,10 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// -- sp[...]: constructor arguments
// -----------------------------------
FrameScope scope(masm, StackFrame::MANUAL);
// Enter a construct frame.
{
FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT);
Label post_instantiation_deopt_entry, not_create_implicit_receiver;
__ EnterFrame(StackFrame::CONSTRUCT);
// Preserve the incoming parameters on the stack.
__ SmiTag(r2);
......@@ -200,10 +200,9 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
&not_create_implicit_receiver);
// If not derived class constructor: Allocate the new receiver object.
__ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1,
r6, r7);
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1, r6,
r7);
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject), RelocInfo::CODE_TARGET);
__ b(&post_instantiation_deopt_entry);
// Else: use TheHoleValue as receiver for constructor call
......@@ -254,18 +253,8 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ LoadP(r2, MemOperand(fp, ConstructFrameConstants::kLengthOffset));
__ SmiUntag(r2);
Label enough_stack_space, stack_overflow;
Label stack_overflow;
Generate_StackOverflowCheck(masm, r2, r7, &stack_overflow);
__ b(&enough_stack_space);
__ bind(&stack_overflow);
// Restore the context from the frame.
__ LoadP(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowStackOverflow);
// Unreachable code.
__ bkpt(0);
__ bind(&enough_stack_space);
// Copy arguments and receiver to the expression stack.
__ PushArray(r6, r2, r1, r0);
......@@ -289,44 +278,28 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset(
masm->pc_offset());
// Restore the context from the frame.
__ LoadP(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
// If the result is an object (in the ECMA sense), we should get rid
// of the receiver and use the result; see ECMA-262 section 13.2.2-7
// on page 74.
Label use_receiver, do_throw, leave_frame;
Label use_receiver, do_throw, leave_and_return, check_receiver;
// If the result is undefined, we jump out to using the implicit receiver.
__ JumpIfRoot(r2, RootIndex::kUndefinedValue, &use_receiver);
__ JumpIfNotRoot(r2, RootIndex::kUndefinedValue, &check_receiver);
// Otherwise we do a smi check and fall through to check if the return value
// is a valid receiver.
// If the result is a smi, it is *not* an object in the ECMA sense.
__ JumpIfSmi(r2, &use_receiver);
// If the type of the result (stored in its map) is less than
// FIRST_JS_RECEIVER_TYPE, it is not an object in the ECMA sense.
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ CompareObjectType(r2, r6, r6, FIRST_JS_RECEIVER_TYPE);
__ bge(&leave_frame);
__ b(&use_receiver);
__ bind(&do_throw);
__ CallRuntime(Runtime::kThrowConstructorReturnedNonObject);
// Throw away the result of the constructor invocation and use the
// on-stack receiver as the result.
__ bind(&use_receiver);
__ LoadP(r2, MemOperand(sp));
__ JumpIfRoot(r2, RootIndex::kTheHoleValue, &do_throw);
__ bind(&leave_frame);
__ bind(&leave_and_return);
// Restore smi-tagged arguments count from the frame.
__ LoadP(r3, MemOperand(fp, ConstructFrameConstants::kLengthOffset));
// Leave construct frame.
}
__ LeaveFrame(StackFrame::CONSTRUCT);
// Remove caller arguments from the stack and return.
STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
......@@ -335,6 +308,30 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ AddP(sp, sp, r3);
__ AddP(sp, sp, Operand(kSystemPointerSize));
__ Ret();
__ bind(&check_receiver);
// If the result is a smi, it is *not* an object in the ECMA sense.
__ JumpIfSmi(r2, &use_receiver);
// If the type of the result (stored in its map) is less than
// FIRST_JS_RECEIVER_TYPE, it is not an object in the ECMA sense.
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ CompareObjectType(r2, r6, r6, FIRST_JS_RECEIVER_TYPE);
__ bge(&leave_and_return);
__ b(&use_receiver);
__ bind(&do_throw);
// Restore the context from the frame.
__ LoadP(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowConstructorReturnedNonObject);
__ bkpt(0);
__ bind(&stack_overflow);
// Restore the context from the frame.
__ LoadP(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowStackOverflow);
// Unreachable code.
__ bkpt(0);
}
void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
......
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