Implement typeof in fast compiler.
authorwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 5 Nov 2009 10:15:25 +0000 (10:15 +0000)
committerwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 5 Nov 2009 10:15:25 +0000 (10:15 +0000)
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
src/compiler.cc
src/ia32/fast-codegen-ia32.cc
src/x64/fast-codegen-x64.cc

index b3a05e4..f7d3699 100644 (file)
@@ -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<Code> 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<Code> 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();
   }
index 8a0acfe..69be462 100644 (file)
@@ -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");
   }
index 064ed1b..038bfd6 100644 (file)
@@ -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<Code> 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();
   }
index f23343a..e68e5e4 100644 (file)
@@ -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<Code> 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();
   }