diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc index 224b75f1e0..a279687a76 100644 --- a/src/arm/builtins-arm.cc +++ b/src/arm/builtins-arm.cc @@ -505,10 +505,6 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { // r0: number of arguments // r1: called object __ bind(&non_function_call); - // CALL_NON_FUNCTION expects the non-function constructor as receiver - // (instead of the original receiver from the call site). The receiver is - // stack element argc. - __ str(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); // Set expected number of arguments to zero (not changing r0). __ mov(r2, Operand(0)); __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc index cf71105098..47f5cbb43c 100644 --- a/src/arm/codegen-arm.cc +++ b/src/arm/codegen-arm.cc @@ -4179,11 +4179,10 @@ void CodeGenerator::VisitCallNew(CallNew* node) { // actual function to call is resolved after the arguments have been // evaluated. - // Compute function to call and use the global object as the - // receiver. There is no need to use the global proxy here because - // it will always be replaced with a newly allocated object. + // Push constructor on the stack. If it's not a function it's used as + // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is + // ignored. Load(node->expression()); - LoadGlobal(); // Push the arguments ("left-to-right") on the stack. ZoneList* args = node->arguments(); @@ -4192,21 +4191,21 @@ void CodeGenerator::VisitCallNew(CallNew* node) { Load(args->at(i)); } + // Spill everything from here to simplify the implementation. VirtualFrame::SpilledScope spilled_scope(frame_); - // r0: the number of arguments. + // Load the argument count into r0 and the function into r1 as per + // calling convention. __ mov(r0, Operand(arg_count)); - // Load the function into r1 as per calling convention. - __ ldr(r1, frame_->ElementAt(arg_count + 1)); + __ ldr(r1, frame_->ElementAt(arg_count)); // Call the construct call builtin that handles allocation and // constructor invocation. CodeForSourcePosition(node->position()); Handle ic(Builtins::builtin(Builtins::JSConstructCall)); frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, arg_count + 1); + frame_->EmitPush(r0); - // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). - __ str(r0, frame_->Top()); ASSERT_EQ(original_height + 1, frame_->height()); } diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 67bfc2eecd..9922be4409 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -1700,12 +1700,12 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { // According to ECMA-262, section 11.2.2, page 44, the function // expression in new calls must be evaluated before the // arguments. - // Push function on the stack. + + // Push constructor on the stack. If it's not a function it's used as + // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is + // ignored. VisitForValue(expr->expression(), kStack); - // Push global object (receiver). - __ ldr(r0, CodeGenerator::GlobalObject()); - __ push(r0); // Push the arguments ("left-to-right") on the stack. ZoneList* args = expr->arguments(); int arg_count = args->length(); @@ -1717,16 +1717,13 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { // constructor invocation. SetSourcePosition(expr->position()); - // Load function, arg_count into r1 and r0. + // Load function and argument count into r1 and r0. __ mov(r0, Operand(arg_count)); - // Function is in sp[arg_count + 1]. - __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); + __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); Handle construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); - - // Replace function on TOS with result in r0, or pop it. - DropAndApply(1, context_, r0); + Apply(context_, r0); } diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc index 15c3198f82..1c2eb94cf5 100644 --- a/src/ia32/builtins-ia32.cc +++ b/src/ia32/builtins-ia32.cc @@ -95,10 +95,6 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { // edi: called object // eax: number of arguments __ bind(&non_function_call); - // CALL_NON_FUNCTION expects the non-function constructor as receiver - // (instead of the original receiver from the call site). The receiver is - // stack element argc+1. - __ mov(Operand(esp, eax, times_4, kPointerSize), edi); // Set expected number of arguments to zero (not changing eax). __ Set(ebx, Immediate(0)); __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index ba1e020eb1..922998dddc 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -6390,11 +6390,10 @@ void CodeGenerator::VisitCallNew(CallNew* node) { // actual function to call is resolved after the arguments have been // evaluated. - // Compute function to call and use the global object as the - // receiver. There is no need to use the global proxy here because - // it will always be replaced with a newly allocated object. + // Push constructor on the stack. If it's not a function it's used as + // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is + // ignored. Load(node->expression()); - LoadGlobal(); // Push the arguments ("left-to-right") on the stack. ZoneList* args = node->arguments(); @@ -6407,8 +6406,7 @@ void CodeGenerator::VisitCallNew(CallNew* node) { // constructor invocation. CodeForSourcePosition(node->position()); Result result = frame_->CallConstructor(arg_count); - // Replace the function on the stack with the result. - frame_->SetElementAt(0, &result); + frame_->Push(&result); } diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index cea498a273..a98904d7f5 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -1700,11 +1700,11 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { // According to ECMA-262, section 11.2.2, page 44, the function // expression in new calls must be evaluated before the // arguments. - // Push function on the stack. - VisitForValue(expr->expression(), kStack); - // Push global object (receiver). - __ push(CodeGenerator::GlobalObject()); + // Push constructor on the stack. If it's not a function it's used as + // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is + // ignored. + VisitForValue(expr->expression(), kStack); // Push the arguments ("left-to-right") on the stack. ZoneList* args = expr->arguments(); @@ -1717,16 +1717,13 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { // constructor invocation. SetSourcePosition(expr->position()); - // Load function, arg_count into edi and eax. + // Load function and argument count into edi and eax. __ Set(eax, Immediate(arg_count)); - // Function is in esp[arg_count + 1]. - __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); + __ mov(edi, Operand(esp, arg_count * kPointerSize)); Handle construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); - - // Replace function on TOS with result in eax, or pop it. - DropAndApply(1, context_, eax); + Apply(context_, eax); } diff --git a/src/ia32/virtual-frame-ia32.cc b/src/ia32/virtual-frame-ia32.cc index ff9132cf71..5f1e1e4e5e 100644 --- a/src/ia32/virtual-frame-ia32.cc +++ b/src/ia32/virtual-frame-ia32.cc @@ -1143,9 +1143,9 @@ Result VirtualFrame::CallConstructor(int arg_count) { // and receiver on the stack. Handle ic(Builtins::builtin(Builtins::JSConstructCall)); // Duplicate the function before preparing the frame. - PushElementAt(arg_count + 1); + PushElementAt(arg_count); Result function = Pop(); - PrepareForCall(arg_count + 1, arg_count + 1); // Spill args and receiver. + PrepareForCall(arg_count + 1, arg_count + 1); // Spill function and args. function.ToRegister(edi); // Constructors are called with the number of arguments in register diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc index 7cc493e545..e5d9d04b4b 100644 --- a/src/x64/builtins-x64.cc +++ b/src/x64/builtins-x64.cc @@ -897,10 +897,6 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { // rdi: called object // rax: number of arguments __ bind(&non_function_call); - // CALL_NON_FUNCTION expects the non-function constructor as receiver - // (instead of the original receiver from the call site). The receiver is - // stack element argc+1. - __ movq(Operand(rsp, rax, times_pointer_size, kPointerSize), rdi); // Set expected number of arguments to zero (not changing rax). __ movq(rbx, Immediate(0)); __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index fcf499bea6..b5a0d4b2f2 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -5656,11 +5656,10 @@ void CodeGenerator::VisitCallNew(CallNew* node) { // actual function to call is resolved after the arguments have been // evaluated. - // Compute function to call and use the global object as the - // receiver. There is no need to use the global proxy here because - // it will always be replaced with a newly allocated object. + // Push constructor on the stack. If it's not a function it's used as + // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is + // ignored. Load(node->expression()); - LoadGlobal(); // Push the arguments ("left-to-right") on the stack. ZoneList* args = node->arguments(); @@ -5673,8 +5672,7 @@ void CodeGenerator::VisitCallNew(CallNew* node) { // constructor invocation. CodeForSourcePosition(node->position()); Result result = frame_->CallConstructor(arg_count); - // Replace the function on the stack with the result. - frame_->SetElementAt(0, &result); + frame_->Push(&result); } diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index cd028297fb..559647adc1 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -1709,11 +1709,11 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { // According to ECMA-262, section 11.2.2, page 44, the function // expression in new calls must be evaluated before the // arguments. - // Push function on the stack. - VisitForValue(expr->expression(), kStack); - // Push global object (receiver). - __ push(CodeGenerator::GlobalObject()); + // Push constructor on the stack. If it's not a function it's used as + // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is + // ignored. + VisitForValue(expr->expression(), kStack); // Push the arguments ("left-to-right") on the stack. ZoneList* args = expr->arguments(); @@ -1726,16 +1726,13 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { // constructor invocation. SetSourcePosition(expr->position()); - // Load function, arg_count into rdi and rax. + // Load function and argument count into rdi and rax. __ Set(rax, arg_count); - // Function is in rsp[arg_count + 1]. - __ movq(rdi, Operand(rsp, rax, times_pointer_size, kPointerSize)); + __ movq(rdi, Operand(rsp, arg_count * kPointerSize)); Handle construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); - - // Replace function on TOS with result in rax, or pop it. - DropAndApply(1, context_, rax); + Apply(context_, rax); } diff --git a/src/x64/virtual-frame-x64.cc b/src/x64/virtual-frame-x64.cc index b8b008c7a6..88e7cc8811 100644 --- a/src/x64/virtual-frame-x64.cc +++ b/src/x64/virtual-frame-x64.cc @@ -1230,9 +1230,9 @@ Result VirtualFrame::CallConstructor(int arg_count) { // and receiver on the stack. Handle ic(Builtins::builtin(Builtins::JSConstructCall)); // Duplicate the function before preparing the frame. - PushElementAt(arg_count + 1); + PushElementAt(arg_count); Result function = Pop(); - PrepareForCall(arg_count + 1, arg_count + 1); // Spill args and receiver. + PrepareForCall(arg_count + 1, arg_count + 1); // Spill function and args. function.ToRegister(rdi); // Constructors are called with the number of arguments in register