From 299a491d7a4e0c297d4f7b7430e8ea1135345130 Mon Sep 17 00:00:00 2001 From: "whesse@chromium.org" Date: Tue, 27 Oct 2009 14:52:55 +0000 Subject: [PATCH] Add VisitCallNew to fast compiler. Review URL: http://codereview.chromium.org/334041 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3148 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/fast-codegen-arm.cc | 46 ++++++++++++++++++++++++++++++++++++++++++ src/compiler.cc | 9 ++++++++- src/fast-codegen.cc | 5 ----- src/ia32/fast-codegen-ia32.cc | 46 ++++++++++++++++++++++++++++++++++++++++++ src/x64/fast-codegen-x64.cc | 47 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 147 insertions(+), 6 deletions(-) diff --git a/src/arm/fast-codegen-arm.cc b/src/arm/fast-codegen-arm.cc index 02557d3..757a03f 100644 --- a/src/arm/fast-codegen-arm.cc +++ b/src/arm/fast-codegen-arm.cc @@ -536,6 +536,52 @@ void FastCodeGenerator::VisitCall(Call* expr) { } +void FastCodeGenerator::VisitCallNew(CallNew* node) { + Comment cmnt(masm_, "[ CallNew"); + // 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. + Visit(node->expression()); + ASSERT(node->expression()->location().is_temporary()); + + // Push global object (receiver). + __ ldr(r0, CodeGenerator::GlobalObject()); + __ push(r0); + // Push the arguments ("left-to-right") on the stack. + ZoneList* args = node->arguments(); + int arg_count = args->length(); + for (int i = 0; i < arg_count; i++) { + Visit(args->at(i)); + ASSERT(args->at(i)->location().is_temporary()); + // If location is temporary, it is already on the stack, + // so nothing to do here. + } + + // Call the construct call builtin that handles allocation and + // constructor invocation. + SetSourcePosition(node->position()); + + // Load function, arg_count into r1 and r0. + __ mov(r0, Operand(arg_count)); + // Function is in esp[arg_count + 1]. + __ ldr(r1, MemOperand(sp, (arg_count + 1) * 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. + switch (node->location().type()) { + case Location::TEMP: + __ str(r0, MemOperand(sp, 0)); + break; + case Location::NOWHERE: + __ pop(); + break; + } +} + + void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { Comment cmnt(masm_, "[ CallRuntime"); ZoneList* args = expr->arguments(); diff --git a/src/compiler.cc b/src/compiler.cc index 436e429..23fb46e 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -725,7 +725,14 @@ void CodeGenSelector::VisitCall(Call* expr) { void CodeGenSelector::VisitCallNew(CallNew* expr) { - BAILOUT("CallNew"); + Visit(expr->expression()); + CHECK_BAILOUT; + ZoneList* args = expr->arguments(); + // Check all arguments to the call + for (int i = 0; i < args->length(); i++) { + Visit(args->at(i)); + CHECK_BAILOUT; + } } diff --git a/src/fast-codegen.cc b/src/fast-codegen.cc index a93e911..bb53f41 100644 --- a/src/fast-codegen.cc +++ b/src/fast-codegen.cc @@ -356,11 +356,6 @@ void FastCodeGenerator::VisitProperty(Property* expr) { } -void FastCodeGenerator::VisitCallNew(CallNew* expr) { - UNREACHABLE(); -} - - void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { UNREACHABLE(); } diff --git a/src/ia32/fast-codegen-ia32.cc b/src/ia32/fast-codegen-ia32.cc index 9b53223..c24f41a 100644 --- a/src/ia32/fast-codegen-ia32.cc +++ b/src/ia32/fast-codegen-ia32.cc @@ -527,6 +527,52 @@ void FastCodeGenerator::VisitCall(Call* expr) { } +void FastCodeGenerator::VisitCallNew(CallNew* node) { + Comment cmnt(masm_, "[ CallNew"); + // 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. + Visit(node->expression()); + ASSERT(node->expression()->location().is_temporary()); + + // Push global object (receiver). + __ push(CodeGenerator::GlobalObject()); + + // Push the arguments ("left-to-right") on the stack. + ZoneList* args = node->arguments(); + int arg_count = args->length(); + for (int i = 0; i < arg_count; i++) { + Visit(args->at(i)); + ASSERT(args->at(i)->location().is_temporary()); + // If location is temporary, it is already on the stack, + // so nothing to do here. + } + + // Call the construct call builtin that handles allocation and + // constructor invocation. + SetSourcePosition(node->position()); + + // Load function, arg_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)); + + Handle construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); + __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); + + // Replace function on TOS with result in eax, or pop it. + switch (node->location().type()) { + case Location::TEMP: + __ mov(Operand(esp, 0), eax); + break; + case Location::NOWHERE: + __ add(Operand(esp), Immediate(kPointerSize)); + break; + } +} + + void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { Comment cmnt(masm_, "[ CallRuntime"); ZoneList* args = expr->arguments(); diff --git a/src/x64/fast-codegen-x64.cc b/src/x64/fast-codegen-x64.cc index 802635f..315d7f1 100644 --- a/src/x64/fast-codegen-x64.cc +++ b/src/x64/fast-codegen-x64.cc @@ -541,6 +541,53 @@ void FastCodeGenerator::VisitCall(Call* expr) { } +void FastCodeGenerator::VisitCallNew(CallNew* node) { + Comment cmnt(masm_, "[ CallNew"); + // 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. + Visit(node->expression()); + ASSERT(node->expression()->location().is_temporary()); + // If location is temporary, already on the stack, + + // Push global object (receiver). + __ push(CodeGenerator::GlobalObject()); + + // Push the arguments ("left-to-right") on the stack. + ZoneList* args = node->arguments(); + int arg_count = args->length(); + for (int i = 0; i < arg_count; i++) { + Visit(args->at(i)); + ASSERT(args->at(i)->location().is_temporary()); + // If location is temporary, it is already on the stack, + // so nothing to do here. + } + + // Call the construct call builtin that handles allocation and + // constructor invocation. + SetSourcePosition(node->position()); + + // Load function, arg_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)); + + Handle construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); + __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); + + // Replace function on TOS with result in rax, or pop it. + switch (node->location().type()) { + case Location::TEMP: + __ movq(Operand(rsp, 0), rax); + break; + case Location::NOWHERE: + __ addq(rsp, Immediate(kPointerSize)); + break; + } +} + + void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { Comment cmnt(masm_, "[ CallRuntime"); ZoneList* args = expr->arguments(); -- 2.7.4