Commit 366d30c9 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[builtins] Streamline the construct stubs

- 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

Change-Id: Ibccb3bf604085bd470c4279d0348edcf6f18d796
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2523196
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71094}
parent 6c693794
......@@ -151,10 +151,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.
__ LoadRoot(r4, RootIndex::kTheHoleValue);
......@@ -176,10 +176,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,
r4, r5);
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1, r4,
r5);
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject), RelocInfo::CODE_TARGET);
__ b(&post_instantiation_deopt_entry);
// Else: use TheHoleValue as receiver for constructor call
......@@ -211,8 +210,7 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ mov(r6, r0);
// Set up pointer to first argument (skip receiver).
__ add(
r4, fp,
__ add(r4, fp,
Operand(StandardFrameConstants::kCallerSPOffset + kSystemPointerSize));
// Restore constructor function and argument count.
......@@ -220,18 +218,8 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ ldr(r0, MemOperand(fp, ConstructFrameConstants::kLengthOffset));
__ SmiUntag(r0);
Label enough_stack_space, stack_overflow;
Label stack_overflow;
__ StackOverflowCheck(r0, r5, &stack_overflow);
__ b(&enough_stack_space);
__ bind(&stack_overflow);
// Restore the context from the frame.
__ ldr(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowStackOverflow);
// Unreachable code.
__ bkpt(0);
__ 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
......@@ -260,49 +248,58 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset(
masm->pc_offset());
// Restore the context from the frame.
__ ldr(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(r0, RootIndex::kUndefinedValue, &use_receiver);
__ JumpIfNotRoot(r0, 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(r0, &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(r0, r4, r5, FIRST_JS_RECEIVER_TYPE);
__ b(ge, &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);
__ ldr(r0, MemOperand(sp, 0 * kPointerSize));
__ JumpIfRoot(r0, RootIndex::kTheHoleValue, &do_throw);
__ bind(&leave_frame);
__ bind(&leave_and_return);
// Restore smi-tagged arguments count from the frame.
__ ldr(r1, MemOperand(fp, ConstructFrameConstants::kLengthOffset));
// Leave construct frame.
}
__ LeaveFrame(StackFrame::CONSTRUCT);
// Remove caller arguments from the stack and return.
STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
__ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
__ add(sp, sp, Operand(kPointerSize));
__ Jump(lr);
__ bind(&check_receiver);
// If the result is a smi, it is *not* an object in the ECMA sense.
__ JumpIfSmi(r0, &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(r0, r4, r5, FIRST_JS_RECEIVER_TYPE);
__ b(ge, &leave_and_return);
__ b(&use_receiver);
__ bind(&do_throw);
// Restore the context from the frame.
__ ldr(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowConstructorReturnedNonObject);
__ bkpt(0);
__ bind(&stack_overflow);
// Restore the context from the frame.
__ ldr(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowStackOverflow);
// Unreachable code.
__ bkpt(0);
}
void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
......
......@@ -210,9 +210,9 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
ASM_LOCATION("Builtins::Generate_JSConstructStubGeneric");
FrameScope scope(masm, StackFrame::MANUAL);
// Enter a construct frame.
{
FrameScope scope(masm, StackFrame::CONSTRUCT);
__ EnterFrame(StackFrame::CONSTRUCT);
Label post_instantiation_deopt_entry, not_create_implicit_receiver;
if (__ emit_debug_code()) {
......@@ -242,11 +242,10 @@ 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,
x4, x5);
__ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1, x4,
x5);
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject), RelocInfo::CODE_TARGET);
__ B(&post_instantiation_deopt_entry);
......@@ -309,17 +308,8 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ Bic(x10, x12, 1);
// Check if we have enough stack space to push all arguments.
Label enough_stack_space, stack_overflow;
Label stack_overflow;
__ StackOverflowCheck(x10, &stack_overflow);
__ B(&enough_stack_space);
__ Bind(&stack_overflow);
// Restore the context from the frame.
__ Ldr(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowStackOverflow);
__ Unreachable();
__ Bind(&enough_stack_space);
__ Claim(x10);
// TODO(victorgomes): When the arguments adaptor is completely removed, we
......@@ -356,20 +346,34 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset(
masm->pc_offset());
// Restore the context from the frame.
__ Ldr(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.
__ CompareRoot(x0, RootIndex::kUndefinedValue);
__ B(eq, &use_receiver);
__ B(ne, &check_receiver);
// Throw away the result of the constructor invocation and use the
// on-stack receiver as the result.
__ Bind(&use_receiver);
__ Peek(x0, 0 * kSystemPointerSize);
__ CompareRoot(x0, RootIndex::kTheHoleValue);
__ B(eq, &do_throw);
__ Bind(&leave_and_return);
// Restore smi-tagged arguments count from the frame.
__ SmiUntag(x1, MemOperand(fp, ConstructFrameConstants::kLengthOffset));
// Leave construct frame.
__ LeaveFrame(StackFrame::CONSTRUCT);
// Remove caller arguments from the stack and return.
__ DropArguments(x1, TurboAssembler::kCountExcludesReceiver);
__ Ret();
// Otherwise we do a smi check and fall through to check if the return value
// is a valid receiver.
__ bind(&check_receiver);
// If the result is a smi, it is *not* an object in the ECMA sense.
__ JumpIfSmi(x0, &use_receiver);
......@@ -377,27 +381,21 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// 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);
__ JumpIfObjectType(x0, x4, x5, FIRST_JS_RECEIVER_TYPE, &leave_frame, ge);
__ JumpIfObjectType(x0, x4, x5, FIRST_JS_RECEIVER_TYPE, &leave_and_return,
ge);
__ B(&use_receiver);
__ Bind(&do_throw);
// Restore the context from the frame.
__ Ldr(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowConstructorReturnedNonObject);
__ Unreachable();
// Throw away the result of the constructor invocation and use the
// on-stack receiver as the result.
__ Bind(&use_receiver);
__ Peek(x0, 0 * kSystemPointerSize);
__ CompareRoot(x0, RootIndex::kTheHoleValue);
__ B(eq, &do_throw);
__ Bind(&leave_frame);
// Restore smi-tagged arguments count from the frame.
__ SmiUntag(x1, MemOperand(fp, ConstructFrameConstants::kLengthOffset));
// Leave construct frame.
}
// Remove caller arguments from the stack and return.
__ DropArguments(x1, TurboAssembler::kCountExcludesReceiver);
__ Ret();
__ Bind(&stack_overflow);
// Restore the context from the frame.
__ Ldr(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowStackOverflow);
__ Unreachable();
}
void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
Generate_JSBuiltinsConstructStubHelper(masm);
......
......@@ -150,9 +150,10 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// -- sp[...]: constructor arguments
// -----------------------------------
FrameScope scope(masm, StackFrame::MANUAL);
// Enter a construct frame.
{
FrameScope scope(masm, StackFrame::CONSTRUCT);
__ EnterFrame(StackFrame::CONSTRUCT);
Label post_instantiation_deopt_entry, not_create_implicit_receiver;
// Preserve the incoming parameters on the stack.
......@@ -175,14 +176,13 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
__ mov(eax, FieldOperand(eax, SharedFunctionInfo::kFlagsOffset));
__ DecodeField<SharedFunctionInfo::FunctionKindBits>(eax);
__ JumpIfIsInRange(eax, kDefaultDerivedConstructor, kDerivedConstructor,
ecx, &not_create_implicit_receiver, Label::kNear);
__ JumpIfIsInRange(eax, kDefaultDerivedConstructor, kDerivedConstructor, ecx,
&not_create_implicit_receiver, Label::kNear);
// If not derived class constructor: Allocate the new receiver object.
__ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1,
eax);
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject), RelocInfo::CODE_TARGET);
__ jmp(&post_instantiation_deopt_entry, Label::kNear);
// Else: use TheHoleValue as receiver for constructor call
......@@ -225,18 +225,8 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// Check if we have enough stack space to push all arguments.
// Argument count in eax. Clobbers ecx.
Label enough_stack_space, stack_overflow;
Label stack_overflow;
__ StackOverflowCheck(eax, ecx, &stack_overflow);
__ jmp(&enough_stack_space);
__ bind(&stack_overflow);
// Restore context from the frame.
__ mov(esi, Operand(ebp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowStackOverflow);
// This should be unreachable.
__ int3();
__ 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
......@@ -267,32 +257,14 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset(
masm->pc_offset());
// Restore context from the frame.
__ mov(esi, Operand(ebp, 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 check_result, use_receiver, do_throw, leave_and_return;
// If the result is undefined, we jump out to using the implicit receiver.
__ JumpIfRoot(eax, RootIndex::kUndefinedValue, &use_receiver, Label::kNear);
// 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(eax, &use_receiver, Label::kNear);
// 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);
__ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, ecx);
__ j(above_equal, &leave_frame, Label::kNear);
__ jmp(&use_receiver, Label::kNear);
__ bind(&do_throw);
__ CallRuntime(Runtime::kThrowConstructorReturnedNonObject);
__ JumpIfNotRoot(eax, RootIndex::kUndefinedValue, &check_result,
Label::kNear);
// Throw away the result of the constructor invocation and use the
// on-stack receiver as the result.
......@@ -300,11 +272,11 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ mov(eax, Operand(esp, 0 * kSystemPointerSize));
__ JumpIfRoot(eax, RootIndex::kTheHoleValue, &do_throw);
__ bind(&leave_frame);
__ bind(&leave_and_return);
// Restore smi-tagged arguments count from the frame.
__ mov(edx, Operand(ebp, ConstructFrameConstants::kLengthOffset));
// Leave construct frame.
}
__ LeaveFrame(StackFrame::CONSTRUCT);
// Remove caller arguments from the stack and return.
STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
__ pop(ecx);
......@@ -312,6 +284,34 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
1 * kSystemPointerSize)); // 1 ~ receiver
__ push(ecx);
__ ret(0);
// Otherwise we do a smi check and fall through to check if the return value
// is a valid receiver.
__ bind(&check_result);
// If the result is a smi, it is *not* an object in the ECMA sense.
__ JumpIfSmi(eax, &use_receiver, Label::kNear);
// 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);
__ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, ecx);
__ j(above_equal, &leave_and_return, Label::kNear);
__ jmp(&use_receiver, Label::kNear);
__ bind(&do_throw);
// Restore context from the frame.
__ mov(esi, Operand(ebp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowConstructorReturnedNonObject);
// This should be unreachable.
__ int3();
__ bind(&stack_overflow);
// Restore context from the frame.
__ mov(esi, Operand(ebp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowStackOverflow);
// This should be unreachable.
__ int3();
}
void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
......
......@@ -114,8 +114,6 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
// rdx: new target
__ InvokeFunction(rdi, rdx, rax, CALL_FUNCTION);
// Restore context from the frame.
__ movq(rsi, Operand(rbp, ConstructFrameConstants::kContextOffset));
// Restore smi-tagged arguments count from the frame.
__ movq(rbx, Operand(rbp, ConstructFrameConstants::kLengthOffset));
......@@ -150,9 +148,9 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// -- sp[...]: constructor arguments
// -----------------------------------
FrameScope scope(masm, StackFrame::MANUAL);
// Enter a construct frame.
{
FrameScope scope(masm, StackFrame::CONSTRUCT);
__ EnterFrame(StackFrame::CONSTRUCT);
Label post_instantiation_deopt_entry, not_create_implicit_receiver;
// Preserve the incoming parameters on the stack.
......@@ -180,8 +178,7 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// If not derived class constructor: Allocate the new receiver object.
__ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1);
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject), RelocInfo::CODE_TARGET);
__ jmp(&post_instantiation_deopt_entry, Label::kNear);
// Else: use TheHoleValue as receiver for constructor call
......@@ -224,18 +221,8 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// Check if we have enough stack space to push all arguments.
// Argument count in rax. Clobbers rcx.
Label enough_stack_space, stack_overflow;
__ StackOverflowCheck(rax, rcx, &stack_overflow, Label::kNear);
__ jmp(&enough_stack_space, Label::kNear);
__ bind(&stack_overflow);
// Restore context from the frame.
__ movq(rsi, Operand(rbp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowStackOverflow);
// This should be unreachable.
__ int3();
__ bind(&enough_stack_space);
Label stack_overflow;
__ StackOverflowCheck(rax, rcx, &stack_overflow);
// TODO(victorgomes): When the arguments adaptor is completely removed, we
// should get the formal parameter count and copy the arguments in its
......@@ -264,32 +251,16 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset(
masm->pc_offset());
// Restore context from the frame.
__ movq(rsi, Operand(rbp, 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_result;
// If the result is undefined, we jump out to using the implicit receiver.
__ JumpIfRoot(rax, RootIndex::kUndefinedValue, &use_receiver, Label::kNear);
// 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(rax, &use_receiver, Label::kNear);
// 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);
__ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rcx);
__ j(above_equal, &leave_frame, Label::kNear);
__ jmp(&use_receiver, Label::kNear);
__ bind(&do_throw);
__ CallRuntime(Runtime::kThrowConstructorReturnedNonObject);
// If the result is undefined, we'll use the implicit receiver. Otherwise we
// do a smi check and fall through to check if the return value is a valid
// receiver.
__ JumpIfNotRoot(rax, RootIndex::kUndefinedValue, &check_result,
Label::kNear);
// Throw away the result of the constructor invocation and use the
// on-stack receiver as the result.
......@@ -297,17 +268,41 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ movq(rax, Operand(rsp, 0 * kSystemPointerSize));
__ JumpIfRoot(rax, RootIndex::kTheHoleValue, &do_throw, Label::kNear);
__ bind(&leave_frame);
__ bind(&leave_and_return);
// Restore the arguments count.
__ movq(rbx, Operand(rbp, ConstructFrameConstants::kLengthOffset));
// Leave construct frame.
}
__ LeaveFrame(StackFrame::CONSTRUCT);
// Remove caller arguments from the stack and return.
__ PopReturnAddressTo(rcx);
SmiIndex index = masm->SmiToIndex(rbx, rbx, kSystemPointerSizeLog2);
__ leaq(rsp, Operand(rsp, index.reg, index.scale, 1 * kSystemPointerSize));
__ PushReturnAddressFrom(rcx);
__ ret(0);
// If the result is a smi, it is *not* an object in the ECMA sense.
__ bind(&check_result);
__ JumpIfSmi(rax, &use_receiver, Label::kNear);
// 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);
__ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rcx);
__ j(above_equal, &leave_and_return, Label::kNear);
__ jmp(&use_receiver);
__ bind(&do_throw);
// Restore context from the frame.
__ movq(rsi, Operand(rbp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowConstructorReturnedNonObject);
// We don't return here.
__ int3();
__ bind(&stack_overflow);
// Restore the context from the frame.
__ movq(rsi, Operand(rbp, ConstructFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kThrowStackOverflow);
// This should be unreachable.
__ int3();
}
void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
......
......@@ -2265,7 +2265,7 @@ void MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
Register actual_parameter_count,
InvokeFlag flag) {
// You can't call a function without a valid frame.
DCHECK(flag == JUMP_FUNCTION || has_frame());
DCHECK_IMPLIES(flag == CALL_FUNCTION, has_frame());
DCHECK_EQ(function, x1);
DCHECK_IMPLIES(new_target.is_valid(), new_target == x3);
......
......@@ -1283,7 +1283,7 @@ void MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
Register actual_parameter_count,
InvokeFlag flag) {
// You can't call a function without a valid frame.
DCHECK(flag == JUMP_FUNCTION || has_frame());
DCHECK_IMPLIES(flag == CALL_FUNCTION, has_frame());
DCHECK_EQ(function, edi);
DCHECK_IMPLIES(new_target.is_valid(), new_target == edx);
DCHECK(expected_parameter_count == ecx || expected_parameter_count == eax);
......
......@@ -2394,8 +2394,8 @@ void MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
Register actual_parameter_count,
InvokeFlag flag) {
// You can't call a function without a valid frame.
DCHECK(flag == JUMP_FUNCTION || has_frame());
DCHECK(function == rdi);
DCHECK_IMPLIES(flag == CALL_FUNCTION, has_frame());
DCHECK_EQ(function, rdi);
DCHECK_IMPLIES(new_target.is_valid(), new_target == rdx);
// On function call, call into the debugger if necessary.
......
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