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