Commit 838ce2be authored by Liu Yu's avatar Liu Yu Committed by Commit Bot

[mips][builtins] Streamline the construct stubs

Port: 366d30c9

Change-Id: I8cb720b7de38344627818c578efc36f42c33bbcb
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2531367Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Auto-Submit: Liu yu <liuyu@loongson.cn>
Cr-Commit-Position: refs/heads/master@{#71105}
parent c1d85f53
......@@ -128,9 +128,9 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// -----------------------------------
// Enter a construct frame.
{
FrameScope scope(masm, StackFrame::CONSTRUCT);
FrameScope scope(masm, StackFrame::MANUAL);
Label post_instantiation_deopt_entry, not_create_implicit_receiver;
__ EnterFrame(StackFrame::CONSTRUCT);
// Preserve the incoming parameters on the stack.
__ SmiTag(a0);
......@@ -155,8 +155,7 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// If not derived class constructor: Allocate the new receiver object.
__ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1,
t2, t3);
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject), RelocInfo::CODE_TARGET);
__ Branch(&post_instantiation_deopt_entry);
// Else: use TheHoleValue as receiver for constructor call
......@@ -181,6 +180,7 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// Push the allocated receiver to the stack.
__ Push(v0);
// We need two copies because we may have to return the original one
// and the calling conventions dictate that the called function pops the
// receiver. The second copy is pushed after the arguments, we saved in s0
......@@ -188,9 +188,8 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ mov(s0, v0);
// Set up pointer to last argument.
__ Addu(
t2, fp,
Operand(StandardFrameConstants::kCallerSPOffset + kSystemPointerSize));
__ Addu(t2, fp, Operand(StandardFrameConstants::kCallerSPOffset +
kSystemPointerSize));
// ----------- S t a t e -------------
// -- r3: new target
......@@ -207,18 +206,8 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ lw(a0, MemOperand(fp, ConstructFrameConstants::kLengthOffset));
__ SmiUntag(a0);
Label enough_stack_space, stack_overflow;
Label stack_overflow;
__ StackOverflowCheck(a0, t0, t1, &stack_overflow);
__ Branch(&enough_stack_space);
__ bind(&stack_overflow);
// Restore the context from the frame.
__ lw(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowStackOverflow);
// Unreachable code.
__ break_(0xCC);
__ bind(&enough_stack_space);
// TODO(victorgomes): When the arguments adaptor is completely removed, we
// should get the formal parameter count and copy the arguments in its
......@@ -227,6 +216,7 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// Copy arguments and receiver to the expression stack.
__ PushArray(t2, a0, t0, t1);
// We need two copies because we may have to return the original one
// and the calling conventions dictate that the called function pops the
// receiver. The second copy is pushed after the arguments.
......@@ -248,48 +238,58 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset(
masm->pc_offset());
// Restore the context from the frame.
__ lw(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(v0, RootIndex::kUndefinedValue, &use_receiver);
__ JumpIfNotRoot(v0, 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(v0, &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.
__ GetObjectType(v0, t2, t2);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ Branch(&leave_frame, greater_equal, t2, Operand(FIRST_JS_RECEIVER_TYPE));
__ Branch(&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);
__ lw(v0, MemOperand(sp, 0 * kPointerSize));
__ JumpIfRoot(v0, RootIndex::kTheHoleValue, &do_throw);
__ bind(&leave_frame);
__ bind(&leave_and_return);
// Restore smi-tagged arguments count from the frame.
__ lw(a1, MemOperand(fp, ConstructFrameConstants::kLengthOffset));
// Leave construct frame.
}
__ LeaveFrame(StackFrame::CONSTRUCT);
// Remove caller arguments from the stack and return.
__ Lsa(sp, sp, a1, kPointerSizeLog2 - kSmiTagSize);
__ Addu(sp, sp, kPointerSize);
__ Ret();
__ bind(&check_receiver);
// If the result is a smi, it is *not* an object in the ECMA sense.
__ JumpIfSmi(v0, &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.
__ GetObjectType(v0, t2, t2);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ Branch(&leave_and_return, greater_equal, t2,
Operand(FIRST_JS_RECEIVER_TYPE));
__ Branch(&use_receiver);
__ bind(&do_throw);
// Restore the context from the frame.
__ lw(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowConstructorReturnedNonObject);
__ break_(0xCC);
__ bind(&stack_overflow);
// Restore the context from the frame.
__ lw(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowStackOverflow);
// Unreachable code.
__ break_(0xCC);
}
void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
......
......@@ -129,9 +129,9 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// -----------------------------------
// Enter a construct frame.
{
FrameScope scope(masm, StackFrame::CONSTRUCT);
FrameScope scope(masm, StackFrame::MANUAL);
Label post_instantiation_deopt_entry, not_create_implicit_receiver;
__ EnterFrame(StackFrame::CONSTRUCT);
// Preserve the incoming parameters on the stack.
__ SmiTag(a0);
......@@ -208,18 +208,8 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ Ld(a0, MemOperand(fp, ConstructFrameConstants::kLengthOffset));
__ SmiUntag(a0);
Label enough_stack_space, stack_overflow;
Label stack_overflow;
__ StackOverflowCheck(a0, t0, t1, &stack_overflow);
__ Branch(&enough_stack_space);
__ bind(&stack_overflow);
// Restore the context from the frame.
__ Ld(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowStackOverflow);
// Unreachable code.
__ break_(0xCC);
__ bind(&enough_stack_space);
// TODO(victorgomes): When the arguments adaptor is completely removed, we
// should get the formal parameter count and copy the arguments in its
......@@ -249,49 +239,57 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset(
masm->pc_offset());
// Restore the context from the frame.
__ Ld(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(v0, RootIndex::kUndefinedValue, &use_receiver);
__ JumpIfNotRoot(v0, 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(v0, &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.
__ GetObjectType(v0, t2, t2);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ Branch(&leave_frame, greater_equal, t2, Operand(FIRST_JS_RECEIVER_TYPE));
__ Branch(&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);
__ Ld(v0, MemOperand(sp, 0 * kPointerSize));
__ JumpIfRoot(v0, RootIndex::kTheHoleValue, &do_throw);
__ bind(&leave_frame);
__ bind(&leave_and_return);
// Restore smi-tagged arguments count from the frame.
__ Ld(a1, MemOperand(fp, ConstructFrameConstants::kLengthOffset));
// Leave construct frame.
}
__ LeaveFrame(StackFrame::CONSTRUCT);
// Remove caller arguments from the stack and return.
__ SmiScale(a4, a1, kPointerSizeLog2);
__ Daddu(sp, sp, a4);
__ Daddu(sp, sp, kPointerSize);
__ Ret();
__ bind(&check_receiver);
__ JumpIfSmi(v0, &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.
__ GetObjectType(v0, t2, t2);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
__ Branch(&leave_and_return, greater_equal, t2,
Operand(FIRST_JS_RECEIVER_TYPE));
__ Branch(&use_receiver);
__ bind(&do_throw);
// Restore the context from the frame.
__ Ld(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowConstructorReturnedNonObject);
__ break_(0xCC);
__ bind(&stack_overflow);
// Restore the context from the frame.
__ Ld(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowStackOverflow);
__ break_(0xCC);
}
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