Revision: 5335
Author: kasp...@chromium.org
Date: Wed Aug 25 00:18:32 2010
Log: Simplify the way constructors are called and avoid pushing
a dummy receiver that we end up ignoring anyway.
Review URL: http://codereview.chromium.org/3136032
http://code.google.com/p/v8/source/detail?r=5335

Modified:
 /branches/bleeding_edge/src/arm/builtins-arm.cc
 /branches/bleeding_edge/src/arm/codegen-arm.cc
 /branches/bleeding_edge/src/arm/full-codegen-arm.cc
 /branches/bleeding_edge/src/ia32/builtins-ia32.cc
 /branches/bleeding_edge/src/ia32/codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc
 /branches/bleeding_edge/src/x64/builtins-x64.cc
 /branches/bleeding_edge/src/x64/codegen-x64.cc
 /branches/bleeding_edge/src/x64/full-codegen-x64.cc
 /branches/bleeding_edge/src/x64/virtual-frame-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/builtins-arm.cc     Fri Aug 20 00:10:18 2010
+++ /branches/bleeding_edge/src/arm/builtins-arm.cc     Wed Aug 25 00:18:32 2010
@@ -505,10 +505,6 @@
   // 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);
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc      Tue Aug 24 00:26:49 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc      Wed Aug 25 00:18:32 2010
@@ -4179,11 +4179,10 @@
   // 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<Expression*>* args = node->arguments();
@@ -4192,21 +4191,21 @@
     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<Code> ic(Builtins::builtin(Builtins::JSConstructCall));
   frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, arg_count + 1);
-
- // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)).
-  __ str(r0, frame_->Top());
+  frame_->EmitPush(r0);
+
   ASSERT_EQ(original_height + 1, frame_->height());
 }

=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Tue Aug 24 06:51:23 2010 +++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Wed Aug 25 00:18:32 2010
@@ -1700,12 +1700,12 @@
   // 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<Expression*>* args = expr->arguments();
   int arg_count = args->length();
@@ -1717,16 +1717,13 @@
   // 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<Code> 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);
 }


=======================================
--- /branches/bleeding_edge/src/ia32/builtins-ia32.cc Fri Aug 20 00:10:18 2010 +++ /branches/bleeding_edge/src/ia32/builtins-ia32.cc Wed Aug 25 00:18:32 2010
@@ -95,10 +95,6 @@
   // 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);
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Tue Aug 24 06:51:23 2010 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Wed Aug 25 00:18:32 2010
@@ -6390,11 +6390,10 @@
   // 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<Expression*>* args = node->arguments();
@@ -6407,8 +6406,7 @@
   // 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);
 }


=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Tue Aug 24 06:51:23 2010 +++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Wed Aug 25 00:18:32 2010
@@ -1700,12 +1700,12 @@
   // 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).
-  __ push(CodeGenerator::GlobalObject());
-
   // Push the arguments ("left-to-right") on the stack.
   ZoneList<Expression*>* args = expr->arguments();
   int arg_count = args->length();
@@ -1717,16 +1717,13 @@
   // 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<Code> 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);
 }


=======================================
--- /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc Tue Jul 20 23:59:34 2010 +++ /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc Wed Aug 25 00:18:32 2010
@@ -1143,9 +1143,9 @@
   // and receiver on the stack.
   Handle<Code> 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
=======================================
--- /branches/bleeding_edge/src/x64/builtins-x64.cc     Fri Aug 20 00:10:18 2010
+++ /branches/bleeding_edge/src/x64/builtins-x64.cc     Wed Aug 25 00:18:32 2010
@@ -897,10 +897,6 @@
   // 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);
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc      Tue Aug 24 06:51:23 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc      Wed Aug 25 00:18:32 2010
@@ -5656,11 +5656,10 @@
   // 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<Expression*>* args = node->arguments();
@@ -5673,8 +5672,7 @@
   // 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);
 }


=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Tue Aug 24 06:51:23 2010 +++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Wed Aug 25 00:18:32 2010
@@ -1709,12 +1709,12 @@
   // 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).
-  __ push(CodeGenerator::GlobalObject());
-
   // Push the arguments ("left-to-right") on the stack.
   ZoneList<Expression*>* args = expr->arguments();
   int arg_count = args->length();
@@ -1726,16 +1726,13 @@
   // 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<Code> 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);
 }


=======================================
--- /branches/bleeding_edge/src/x64/virtual-frame-x64.cc Wed Jul 21 08:16:01 2010 +++ /branches/bleeding_edge/src/x64/virtual-frame-x64.cc Wed Aug 25 00:18:32 2010
@@ -1230,9 +1230,9 @@
   // and receiver on the stack.
   Handle<Code> 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

--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev

Reply via email to