From c1e7dd83a469be4262a2dfed754e9091b6557a69 Mon Sep 17 00:00:00 2001 From: "whesse@chromium.org" Date: Thu, 5 Nov 2009 10:15:25 +0000 Subject: [PATCH] Implement typeof in fast compiler. Review URL: http://codereview.chromium.org/354027 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3222 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/fast-codegen-arm.cc | 40 ++++++++++++++++++++++++++++++++--- src/compiler.cc | 3 +++ src/ia32/fast-codegen-ia32.cc | 37 ++++++++++++++++++++++++++++++-- src/x64/fast-codegen-x64.cc | 37 ++++++++++++++++++++++++++++++-- 4 files changed, 110 insertions(+), 7 deletions(-) diff --git a/src/arm/fast-codegen-arm.cc b/src/arm/fast-codegen-arm.cc index b3a05e4738..f7d369938e 100644 --- a/src/arm/fast-codegen-arm.cc +++ b/src/arm/fast-codegen-arm.cc @@ -732,7 +732,7 @@ void FastCodeGenerator::VisitProperty(Property* expr) { if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() && !String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) { // Do a NAMED property load. - // The IC expects the property name in ecx and the receiver on the stack. + // The IC expects the property name in r2 and the receiver on the stack. __ mov(r2, Operand(key->AsLiteral()->handle())); Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); __ Call(ic, RelocInfo::CODE_TARGET); @@ -915,9 +915,9 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { - Comment cmnt(masm_, "[ UnaryOperation"); switch (expr->op()) { - case Token::VOID: + case Token::VOID: { + Comment cmnt(masm_, "[ UnaryOperation (VOID)"); Visit(expr->expression()); ASSERT_EQ(Expression::kEffect, expr->expression()->context()); switch (expr->context()) { @@ -940,8 +940,10 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { break; } break; + } case Token::NOT: { + Comment cmnt(masm_, "[ UnaryOperation (NOT)"); ASSERT_EQ(Expression::kTest, expr->expression()->context()); Label push_true; @@ -1006,6 +1008,38 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { break; } + case Token::TYPEOF: { + Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); + ASSERT_EQ(Expression::kValue, expr->expression()->context()); + + VariableProxy* proxy = expr->expression()->AsVariableProxy(); + if (proxy != NULL && proxy->var()->is_global()) { + Comment cmnt(masm_, "Global variable"); + __ ldr(r0, CodeGenerator::GlobalObject()); + __ push(r0); + __ mov(r2, Operand(proxy->name())); + Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); + // Use a regular load, not a contextual load, to avoid a reference + // error. + __ Call(ic, RelocInfo::CODE_TARGET); + __ str(r0, MemOperand(sp)); + } else if (proxy != NULL && + proxy->var()->slot() != NULL && + proxy->var()->slot()->type() == Slot::LOOKUP) { + __ mov(r0, Operand(proxy->name())); + __ stm(db_w, sp, cp.bit() | r0.bit()); + __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); + __ push(r0); + } else { + // This expression cannot throw a reference error at the top level. + Visit(expr->expression()); + } + + __ CallRuntime(Runtime::kTypeof, 1); + Move(expr->context(), r0); + break; + } + default: UNREACHABLE(); } diff --git a/src/compiler.cc b/src/compiler.cc index 8a0acfeb3d..69be462211 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -987,6 +987,9 @@ void CodeGenSelector::VisitUnaryOperation(UnaryOperation* expr) { case Token::NOT: ProcessExpression(expr->expression(), Expression::kTest); break; + case Token::TYPEOF: + ProcessExpression(expr->expression(), Expression::kValue); + break; default: BAILOUT("UnaryOperation"); } diff --git a/src/ia32/fast-codegen-ia32.cc b/src/ia32/fast-codegen-ia32.cc index 064ed1bc30..038bfd620d 100644 --- a/src/ia32/fast-codegen-ia32.cc +++ b/src/ia32/fast-codegen-ia32.cc @@ -916,9 +916,9 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { - Comment cmnt(masm_, "[ UnaryOperation"); switch (expr->op()) { - case Token::VOID: + case Token::VOID: { + Comment cmnt(masm_, "[ UnaryOperation (VOID)"); Visit(expr->expression()); ASSERT_EQ(Expression::kEffect, expr->expression()->context()); switch (expr->context()) { @@ -940,8 +940,10 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { break; } break; + } case Token::NOT: { + Comment cmnt(masm_, "[ UnaryOperation (NOT)"); ASSERT_EQ(Expression::kTest, expr->expression()->context()); Label push_true; @@ -1002,6 +1004,37 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { break; } + case Token::TYPEOF: { + Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); + ASSERT_EQ(Expression::kValue, expr->expression()->context()); + + VariableProxy* proxy = expr->expression()->AsVariableProxy(); + if (proxy != NULL && proxy->var()->is_global()) { + Comment cmnt(masm_, "Global variable"); + __ push(CodeGenerator::GlobalObject()); + __ mov(ecx, Immediate(proxy->name())); + Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); + // Use a regular load, not a contextual load, to avoid a reference + // error. + __ call(ic, RelocInfo::CODE_TARGET); + __ mov(Operand(esp, 0), eax); + } else if (proxy != NULL && + proxy->var()->slot() != NULL && + proxy->var()->slot()->type() == Slot::LOOKUP) { + __ push(esi); + __ push(Immediate(proxy->name())); + __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); + __ push(eax); + } else { + // This expression cannot throw a reference error at the top level. + Visit(expr->expression()); + } + + __ CallRuntime(Runtime::kTypeof, 1); + Move(expr->context(), eax); + break; + } + default: UNREACHABLE(); } diff --git a/src/x64/fast-codegen-x64.cc b/src/x64/fast-codegen-x64.cc index f23343a570..e68e5e4a70 100644 --- a/src/x64/fast-codegen-x64.cc +++ b/src/x64/fast-codegen-x64.cc @@ -991,9 +991,9 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { - Comment cmnt(masm_, "[ UnaryOperation"); switch (expr->op()) { - case Token::VOID: + case Token::VOID: { + Comment cmnt(masm_, "[ UnaryOperation (VOID)"); Visit(expr->expression()); ASSERT_EQ(Expression::kEffect, expr->expression()->context()); switch (expr->context()) { @@ -1015,8 +1015,10 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { break; } break; + } case Token::NOT: { + Comment cmnt(masm_, "[ UnaryOperation (NOT)"); ASSERT_EQ(Expression::kTest, expr->expression()->context()); Label push_true; @@ -1077,6 +1079,37 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { break; } + case Token::TYPEOF: { + Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); + ASSERT_EQ(Expression::kValue, expr->expression()->context()); + + VariableProxy* proxy = expr->expression()->AsVariableProxy(); + if (proxy != NULL && proxy->var()->is_global()) { + Comment cmnt(masm_, "Global variable"); + __ push(CodeGenerator::GlobalObject()); + __ Move(rcx, proxy->name()); + Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); + // Use a regular load, not a contextual load, to avoid a reference + // error. + __ Call(ic, RelocInfo::CODE_TARGET); + __ movq(Operand(rsp, 0), rax); + } else if (proxy != NULL && + proxy->var()->slot() != NULL && + proxy->var()->slot()->type() == Slot::LOOKUP) { + __ push(rsi); + __ Push(proxy->name()); + __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); + __ push(rax); + } else { + // This expression cannot throw a reference error at the top level. + Visit(expr->expression()); + } + + __ CallRuntime(Runtime::kTypeof, 1); + Move(expr->context(), rax); + break; + } + default: UNREACHABLE(); }