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 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5335 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
99ce72bd8a
commit
02a842daae
@ -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);
|
||||
|
@ -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<Expression*>* 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<Code> 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());
|
||||
}
|
||||
|
||||
|
@ -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<Expression*>* 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<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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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<Expression*>* 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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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<Expression*>* 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<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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1143,9 +1143,9 @@ Result VirtualFrame::CallConstructor(int arg_count) {
|
||||
// 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
|
||||
|
@ -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);
|
||||
|
@ -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<Expression*>* 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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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<Expression*>* 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<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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1230,9 +1230,9 @@ Result VirtualFrame::CallConstructor(int arg_count) {
|
||||
// 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
|
||||
|
Loading…
Reference in New Issue
Block a user