Revision: 3645
Author: [email protected]
Date: Tue Jan 19 04:41:02 2010
Log: First step of refactoring expression contexts in the toplevel code
generator.

Contexts are no longer stored in the AST but in the code generator's
state.  This means that the running the code generator selector is not
required to use the toplevel code generator (for instance, if we
already know that we can and should use it).

Review URL: http://codereview.chromium.org/546075
http://code.google.com/p/v8/source/detail?r=3645

Modified:
 /branches/bleeding_edge/src/arm/fast-codegen-arm.cc
 /branches/bleeding_edge/src/ast.h
 /branches/bleeding_edge/src/compiler.cc
 /branches/bleeding_edge/src/fast-codegen.cc
 /branches/bleeding_edge/src/fast-codegen.h
 /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc
 /branches/bleeding_edge/src/x64/fast-codegen-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Mon Jan 18 06:04:55 2010 +++ /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Tue Jan 19 04:41:02 2010
@@ -662,13 +662,13 @@
   __ mov(r0, Operand(boilerplate));
   __ stm(db_w, sp, cp.bit() | r0.bit());
   __ CallRuntime(Runtime::kNewClosure, 2);
-  Apply(expr->context(), r0);
+  Apply(context_, r0);
 }


 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
   Comment cmnt(masm_, "[ VariableProxy");
-  EmitVariableLoad(expr->var(), expr->context());
+  EmitVariableLoad(expr->var(), context_);
 }


@@ -768,7 +768,7 @@
   __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit());
   __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
   __ bind(&done);
-  Apply(expr->context(), r0);
+  Apply(context_, r0);
 }


@@ -840,9 +840,9 @@
   }

   if (result_saved) {
-    ApplyTOS(expr->context());
+    ApplyTOS(context_);
   } else {
-    Apply(expr->context(), r0);
+    Apply(context_, r0);
   }
 }

@@ -893,9 +893,9 @@
   }

   if (result_saved) {
-    ApplyTOS(expr->context());
+    ApplyTOS(context_);
   } else {
-    Apply(expr->context(), r0);
+    Apply(context_, r0);
   }
 }

@@ -1007,7 +1007,7 @@
     __ pop(r0);
   }

-  DropAndApply(1, expr->context(), r0);
+  DropAndApply(1, context_, r0);
 }


@@ -1042,7 +1042,7 @@
   }

   // Receiver and key are still on stack.
-  DropAndApply(2, expr->context(), r0);
+  DropAndApply(2, context_, r0);
 }


@@ -1056,12 +1056,12 @@
   if (key->IsPropertyName()) {
     EmitNamedPropertyLoad(expr);
     // Drop receiver left on the stack by IC.
-    DropAndApply(1, expr->context(), r0);
+    DropAndApply(1, context_, r0);
   } else {
     VisitForValue(expr->key(), kStack);
     EmitKeyedPropertyLoad(expr);
     // Drop key and receiver left on the stack by IC.
-    DropAndApply(2, expr->context(), r0);
+    DropAndApply(2, context_, r0);
   }
 }

@@ -1083,7 +1083,7 @@
   // Restore context register.
   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   // Discard the function left on TOS.
-  DropAndApply(1, expr->context(), r0);
+  DropAndApply(1, context_, r0);
 }


@@ -1101,7 +1101,7 @@
   // Restore context register.
   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   // Discard the function left on TOS.
-  DropAndApply(1, expr->context(), r0);
+  DropAndApply(1, context_, r0);
 }


@@ -1207,7 +1207,7 @@
   __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);

   // Replace function on TOS with result in r0, or pop it.
-  DropAndApply(1, expr->context(), r0);
+  DropAndApply(1, context_, r0);
 }


@@ -1237,11 +1237,11 @@
     // Restore context register.
     __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
     // Discard the function left on TOS.
-    DropAndApply(1, expr->context(), r0);
+    DropAndApply(1, context_, r0);
   } else {
     // Call the C runtime function.
     __ CallRuntime(expr->function(), arg_count);
-    Apply(expr->context(), r0);
+    Apply(context_, r0);
   }
 }

@@ -1250,9 +1250,8 @@
   switch (expr->op()) {
     case Token::VOID: {
       Comment cmnt(masm_, "[ UnaryOperation (VOID)");
-      ASSERT_EQ(Expression::kEffect, expr->expression()->context());
-      Visit(expr->expression());
-      switch (expr->context()) {
+      VisitForEffect(expr->expression());
+      switch (context_) {
         case Expression::kUninitialized:
           UNREACHABLE();
           break;
@@ -1289,14 +1288,12 @@

     case Token::NOT: {
       Comment cmnt(masm_, "[ UnaryOperation (NOT)");
-      ASSERT_EQ(Expression::kTest, expr->expression()->context());
-
       Label materialize_true, materialize_false, done;
       // Initially assume a pure test context.  Notice that the labels are
       // swapped.
       Label* if_true = false_label_;
       Label* if_false = true_label_;
-      switch (expr->context()) {
+      switch (context_) {
         case Expression::kUninitialized:
           UNREACHABLE();
           break;
@@ -1318,14 +1315,12 @@
           break;
       }
       VisitForControl(expr->expression(), if_true, if_false);
-      Apply(expr->context(), if_false, if_true);  // Labels swapped.
+      Apply(context_, if_false, if_true);  // Labels swapped.
       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_this() &&
@@ -1352,7 +1347,7 @@
       }

       __ CallRuntime(Runtime::kTypeof, 1);
-      Apply(expr->context(), r0);
+      Apply(context_, r0);
       break;
     }

@@ -1373,9 +1368,8 @@
   // In case of a property we use the uninitialized expression context
   // of the key to detect a named property.
   if (prop != NULL) {
-    assign_type = (prop->key()->context() == Expression::kUninitialized)
-        ? NAMED_PROPERTY
-        : KEYED_PROPERTY;
+    assign_type =
+        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
   }

   // Evaluate expression and get value.
@@ -1388,8 +1382,7 @@
     location_ = saved_location;
   } else {
     // Reserve space for result of postfix operation.
-    if (expr->is_postfix() && expr->context() != Expression::kEffect) {
-      ASSERT(expr->context() != Expression::kUninitialized);
+    if (expr->is_postfix() && context_ != Expression::kEffect) {
       __ mov(ip, Operand(Smi::FromInt(0)));
       __ push(ip);
     }
@@ -1408,7 +1401,7 @@

   // Save result for postfix expressions.
   if (expr->is_postfix()) {
-    switch (expr->context()) {
+    switch (context_) {
       case Expression::kUninitialized:
         UNREACHABLE();
       case Expression::kEffect:
@@ -1451,12 +1444,12 @@
                                Expression::kEffect);
         // For all contexts except kEffect: We have the result on
         // top of the stack.
-        if (expr->context() != Expression::kEffect) {
-          ApplyTOS(expr->context());
+        if (context_ != Expression::kEffect) {
+          ApplyTOS(context_);
         }
       } else {
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
-                               expr->context());
+                               context_);
       }
       break;
     case NAMED_PROPERTY: {
@@ -1465,11 +1458,11 @@
       __ Call(ic, RelocInfo::CODE_TARGET);
       if (expr->is_postfix()) {
         __ Drop(1);  // Result is on the stack under the receiver.
-        if (expr->context() != Expression::kEffect) {
-          ApplyTOS(expr->context());
+        if (context_ != Expression::kEffect) {
+          ApplyTOS(context_);
         }
       } else {
-        DropAndApply(1, expr->context(), r0);
+        DropAndApply(1, context_, r0);
       }
       break;
     }
@@ -1478,11 +1471,11 @@
       __ Call(ic, RelocInfo::CODE_TARGET);
       if (expr->is_postfix()) {
__ Drop(2); // Result is on the stack under the key and the receiver.
-        if (expr->context() != Expression::kEffect) {
-          ApplyTOS(expr->context());
+        if (context_ != Expression::kEffect) {
+          ApplyTOS(context_);
         }
       } else {
-        DropAndApply(2, expr->context(), r0);
+        DropAndApply(2, context_, r0);
       }
       break;
     }
@@ -1494,9 +1487,7 @@
   Comment cmnt(masm_, "[ BinaryOperation");
   switch (expr->op()) {
     case Token::COMMA:
-      ASSERT_EQ(Expression::kEffect, expr->left()->context());
-      ASSERT_EQ(expr->context(), expr->right()->context());
-      Visit(expr->left());
+      VisitForEffect(expr->left());
       Visit(expr->right());
       break;

@@ -1518,7 +1509,7 @@
     case Token::SAR:
       VisitForValue(expr->left(), kStack);
       VisitForValue(expr->right(), kAccumulator);
-      EmitBinaryOp(expr->op(), expr->context());
+      EmitBinaryOp(expr->op(), context_);
       break;

     default:
@@ -1536,7 +1527,7 @@
   // Initially assume we are in a test context.
   Label* if_true = true_label_;
   Label* if_false = false_label_;
-  switch (expr->context()) {
+  switch (context_) {
     case Expression::kUninitialized:
       UNREACHABLE();
       break;
@@ -1638,13 +1629,13 @@

   // Convert the result of the comparison into one expected for this
   // expression's context.
-  Apply(expr->context(), if_true, if_false);
+  Apply(context_, if_true, if_false);
 }


 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
   __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  Apply(expr->context(), r0);
+  Apply(context_, r0);
 }


=======================================
--- /branches/bleeding_edge/src/ast.h   Thu Jan 14 09:22:59 2010
+++ /branches/bleeding_edge/src/ast.h   Tue Jan 19 04:41:02 2010
@@ -179,8 +179,6 @@
     // needed if false.
     kTestValue
   };
-
-  Expression() : context_(kUninitialized) {}

   virtual Expression* AsExpression()  { return this; }

@@ -199,13 +197,9 @@

   // Static type information for this expression.
   StaticType* type() { return &type_; }
-
-  Context context() { return context_; }
-  void set_context(Context context) { context_ = context; }

  private:
   StaticType type_;
-  Context context_;
 };


=======================================
--- /branches/bleeding_edge/src/compiler.cc     Tue Jan 12 09:22:57 2010
+++ /branches/bleeding_edge/src/compiler.cc     Tue Jan 19 04:41:02 2010
@@ -46,25 +46,11 @@
  public:
   enum CodeGenTag { NORMAL, FAST };

-  CodeGenSelector()
-      : has_supported_syntax_(true),
-        context_(Expression::kUninitialized) {
-  }
+  CodeGenSelector() : has_supported_syntax_(true) {}

   CodeGenTag Select(FunctionLiteral* fun);

  private:
-  // Visit an expression in a given expression context.
-  void ProcessExpression(Expression* expr, Expression::Context context) {
-    ASSERT(expr->context() == Expression::kUninitialized ||
-           expr->context() == context);
-    Expression::Context saved = context_;
-    context_ = context;
-    Visit(expr);
-    expr->set_context(context);
-    context_ = saved;
-  }
-
   void VisitDeclarations(ZoneList<Declaration*>* decls);
   void VisitStatements(ZoneList<Statement*>* stmts);

@@ -75,9 +61,6 @@

   bool has_supported_syntax_;

-  // The desired expression context of the currently visited expression.
-  Expression::Context context_;
-
   DISALLOW_COPY_AND_ASSIGN(CodeGenSelector);
 };

@@ -649,12 +632,12 @@
 void CodeGenSelector::VisitDeclaration(Declaration* decl) {
   Property* prop = decl->proxy()->AsProperty();
   if (prop != NULL) {
-    ProcessExpression(prop->obj(), Expression::kValue);
-    ProcessExpression(prop->key(), Expression::kValue);
+    Visit(prop->obj());
+    Visit(prop->key());
   }

   if (decl->fun() != NULL) {
-    ProcessExpression(decl->fun(), Expression::kValue);
+    Visit(decl->fun());
   }
 }

@@ -665,17 +648,15 @@


 void CodeGenSelector::VisitExpressionStatement(ExpressionStatement* stmt) {
-  ProcessExpression(stmt->expression(), Expression::kEffect);
+  Visit(stmt->expression());
 }


-void CodeGenSelector::VisitEmptyStatement(EmptyStatement* stmt) {
-  // EmptyStatement is supported.
-}
+void CodeGenSelector::VisitEmptyStatement(EmptyStatement* stmt) {}


 void CodeGenSelector::VisitIfStatement(IfStatement* stmt) {
-  ProcessExpression(stmt->condition(), Expression::kTest);
+  Visit(stmt->condition());
   CHECK_BAILOUT;
   Visit(stmt->then_statement());
   CHECK_BAILOUT;
@@ -683,27 +664,23 @@
 }


-void CodeGenSelector::VisitContinueStatement(ContinueStatement* stmt) {
-}
+void CodeGenSelector::VisitContinueStatement(ContinueStatement* stmt) {}


-void CodeGenSelector::VisitBreakStatement(BreakStatement* stmt) {
-}
+void CodeGenSelector::VisitBreakStatement(BreakStatement* stmt) {}


 void CodeGenSelector::VisitReturnStatement(ReturnStatement* stmt) {
-  ProcessExpression(stmt->expression(), Expression::kValue);
+  Visit(stmt->expression());
 }


 void CodeGenSelector::VisitWithEnterStatement(WithEnterStatement* stmt) {
-  ProcessExpression(stmt->expression(), Expression::kValue);
+  Visit(stmt->expression());
 }


-void CodeGenSelector::VisitWithExitStatement(WithExitStatement* stmt) {
-  // Supported.
-}
+void CodeGenSelector::VisitWithExitStatement(WithExitStatement* stmt) {}


 void CodeGenSelector::VisitSwitchStatement(SwitchStatement* stmt) {
@@ -712,18 +689,14 @@


 void CodeGenSelector::VisitDoWhileStatement(DoWhileStatement* stmt) {
-  // We do not handle loops with breaks or continue statements in their
-  // body.  We will bailout when we hit those statements in the body.
-  ProcessExpression(stmt->cond(), Expression::kTest);
+  Visit(stmt->cond());
   CHECK_BAILOUT;
   Visit(stmt->body());
 }


 void CodeGenSelector::VisitWhileStatement(WhileStatement* stmt) {
-  // We do not handle loops with breaks or continue statements in their
-  // body.  We will bailout when we hit those statements in the body.
-  ProcessExpression(stmt->cond(), Expression::kTest);
+  Visit(stmt->cond());
   CHECK_BAILOUT;
   Visit(stmt->body());
 }
@@ -753,14 +726,10 @@
 }


-void CodeGenSelector::VisitDebuggerStatement(DebuggerStatement* stmt) {
-  // Debugger statement is supported.
-}
+void CodeGenSelector::VisitDebuggerStatement(DebuggerStatement* stmt) {}


-void CodeGenSelector::VisitFunctionLiteral(FunctionLiteral* expr) {
-  // Function literal is supported.
-}
+void CodeGenSelector::VisitFunctionLiteral(FunctionLiteral* expr) {}


 void CodeGenSelector::VisitFunctionBoilerplateLiteral(
@@ -770,11 +739,11 @@


 void CodeGenSelector::VisitConditional(Conditional* expr) {
-  ProcessExpression(expr->condition(), Expression::kTest);
+  Visit(expr->condition());
   CHECK_BAILOUT;
-  ProcessExpression(expr->then_expression(), context_);
+  Visit(expr->then_expression());
   CHECK_BAILOUT;
-  ProcessExpression(expr->else_expression(), context_);
+  Visit(expr->else_expression());
 }


@@ -784,11 +753,9 @@


 void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) {
-  Expression* rewrite = expr->var()->rewrite();
-  // A rewrite of NULL indicates a global variable.
-  if (rewrite != NULL) {
-    // Non-global.
-    Slot* slot = rewrite->AsSlot();
+  Variable* var = expr->var();
+  if (!var->is_global()) {
+    Slot* slot = var->slot();
     if (slot != NULL) {
       Slot::Type type = slot->type();
       // When LOOKUP slots are enabled, some currently dead code
@@ -797,10 +764,10 @@
         BAILOUT("Lookup slot");
       }
     } else {
+ // If not global or a slot, it is a parameter rewritten to an explicit
+      // property reference on the (shadow) arguments object.
 #ifdef DEBUG
-      // Only remaining possibility is a property where the object is
-      // a slotted variable and the key is a smi.
-      Property* property = rewrite->AsProperty();
+      Property* property = var->AsProperty();
       ASSERT_NOT_NULL(property);
       Variable* object = property->obj()->AsVariableProxy()->AsVariable();
       ASSERT_NOT_NULL(object);
@@ -813,14 +780,10 @@
 }


-void CodeGenSelector::VisitLiteral(Literal* expr) {
-  /* Nothing to do. */
-}
+void CodeGenSelector::VisitLiteral(Literal* expr) {}


-void CodeGenSelector::VisitRegExpLiteral(RegExpLiteral* expr) {
-  /* Nothing to do. */
-}
+void CodeGenSelector::VisitRegExpLiteral(RegExpLiteral* expr) {}


 void CodeGenSelector::VisitObjectLiteral(ObjectLiteral* expr) {
@@ -829,32 +792,10 @@
   for (int i = 0, len = properties->length(); i < len; i++) {
     ObjectLiteral::Property* property = properties->at(i);
     if (property->IsCompileTimeValue()) continue;
-
-    switch (property->kind()) {
-      case ObjectLiteral::Property::CONSTANT:
-        UNREACHABLE();
-
-      // For (non-compile-time) materialized literals and computed
-      // properties with symbolic keys we will use an IC and therefore not
-      // generate code for the key.
-      case ObjectLiteral::Property::COMPUTED:  // Fall through.
-      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
-        if (property->key()->handle()->IsSymbol()) {
-          break;
-        }
-        // Fall through.
-
-      // In all other cases we need the key's value on the stack
-      // for a runtime call.  (Relies on TEMP meaning STACK.)
-      case ObjectLiteral::Property::GETTER:  // Fall through.
-      case ObjectLiteral::Property::SETTER:  // Fall through.
-      case ObjectLiteral::Property::PROTOTYPE:
-        ProcessExpression(property->key(), Expression::kValue);
-        CHECK_BAILOUT;
-        break;
-    }
-    ProcessExpression(property->value(), Expression::kValue);
+    Visit(property->key());
     CHECK_BAILOUT;
+    Visit(property->value());
+    CHECK_BAILOUT;
   }
 }

@@ -865,16 +806,16 @@
     Expression* subexpr = subexprs->at(i);
     if (subexpr->AsLiteral() != NULL) continue;
     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
-    ProcessExpression(subexpr, Expression::kValue);
+    Visit(subexpr);
     CHECK_BAILOUT;
   }
 }


void CodeGenSelector::VisitCatchExtensionObject(CatchExtensionObject* expr) {
-  ProcessExpression(expr->key(), Expression::kValue);
+  Visit(expr->key());
   CHECK_BAILOUT;
-  ProcessExpression(expr->value(), Expression::kValue);
+  Visit(expr->value());
 }


@@ -900,33 +841,28 @@
       }
     }
   } else if (prop != NULL) {
-    ProcessExpression(prop->obj(), Expression::kValue);
+    Visit(prop->obj());
     CHECK_BAILOUT;
-    // We will only visit the key during code generation for keyed property
-    // stores.  Leave its expression context uninitialized for named
-    // property stores.
-    if (!prop->key()->IsPropertyName()) {
-      ProcessExpression(prop->key(), Expression::kValue);
-      CHECK_BAILOUT;
-    }
+    Visit(prop->key());
+    CHECK_BAILOUT;
   } else {
     // This is a throw reference error.
     BAILOUT("non-variable/non-property assignment");
   }

-  ProcessExpression(expr->value(), Expression::kValue);
+  Visit(expr->value());
 }


 void CodeGenSelector::VisitThrow(Throw* expr) {
-  ProcessExpression(expr->exception(), Expression::kValue);
+  Visit(expr->exception());
 }


 void CodeGenSelector::VisitProperty(Property* expr) {
-  ProcessExpression(expr->obj(), Expression::kValue);
+  Visit(expr->obj());
   CHECK_BAILOUT;
-  ProcessExpression(expr->key(), Expression::kValue);
+  Visit(expr->key());
 }


@@ -946,34 +882,29 @@
   } else if (fun->AsProperty() != NULL) {
     Property* prop = fun->AsProperty();
     Literal* literal_key = prop->key()->AsLiteral();
-    if (literal_key != NULL && literal_key->handle()->IsSymbol()) {
-      ProcessExpression(prop->obj(), Expression::kValue);
-      CHECK_BAILOUT;
-    } else {
-      ProcessExpression(prop->obj(), Expression::kValue);
-      CHECK_BAILOUT;
-      ProcessExpression(prop->key(), Expression::kValue);
-      CHECK_BAILOUT;
-    }
+    Visit(prop->obj());
+    CHECK_BAILOUT;
+    Visit(prop->key());
+    CHECK_BAILOUT;
   } else {
     // Otherwise the call is supported if the function expression is.
-    ProcessExpression(fun, Expression::kValue);
+    Visit(fun);
   }
   // Check all arguments to the call.
   for (int i = 0; i < args->length(); i++) {
-    ProcessExpression(args->at(i), Expression::kValue);
+    Visit(args->at(i));
     CHECK_BAILOUT;
   }
 }


 void CodeGenSelector::VisitCallNew(CallNew* expr) {
-  ProcessExpression(expr->expression(), Expression::kValue);
+  Visit(expr->expression());
   CHECK_BAILOUT;
   ZoneList<Expression*>* args = expr->arguments();
   // Check all arguments to the call
   for (int i = 0; i < args->length(); i++) {
-    ProcessExpression(args->at(i), Expression::kValue);
+    Visit(args->at(i));
     CHECK_BAILOUT;
   }
 }
@@ -987,7 +918,7 @@
   }
   // Check all arguments to the call.  (Relies on TEMP meaning STACK.)
   for (int i = 0; i < expr->arguments()->length(); i++) {
-    ProcessExpression(expr->arguments()->at(i), Expression::kValue);
+    Visit(expr->arguments()->at(i));
     CHECK_BAILOUT;
   }
 }
@@ -996,16 +927,16 @@
 void CodeGenSelector::VisitUnaryOperation(UnaryOperation* expr) {
   switch (expr->op()) {
     case Token::VOID:
-      ProcessExpression(expr->expression(), Expression::kEffect);
-      break;
     case Token::NOT:
-      ProcessExpression(expr->expression(), Expression::kTest);
-      break;
     case Token::TYPEOF:
-      ProcessExpression(expr->expression(), Expression::kValue);
+      Visit(expr->expression());
       break;
+    case BIT_NOT:
+      BAILOUT("UnaryOperataion: BIT_NOT");
+    case DELETE:
+      BAILOUT("UnaryOperataion: DELETE");
     default:
-      BAILOUT("UnaryOperation");
+      UNREACHABLE();
   }
 }

@@ -1024,15 +955,10 @@
       }
     }
   } else if (prop != NULL) {
-    ProcessExpression(prop->obj(), Expression::kValue);
+    Visit(prop->obj());
     CHECK_BAILOUT;
-    // We will only visit the key during code generation for keyed property
-    // stores.  Leave its expression context uninitialized for named
-    // property stores.
-    if (!prop->key()->IsPropertyName()) {
-      ProcessExpression(prop->key(), Expression::kValue);
-      CHECK_BAILOUT;
-    }
+    Visit(prop->key());
+    CHECK_BAILOUT;
   } else {
     // This is a throw reference error.
     BAILOUT("CountOperation non-variable/non-property expression");
@@ -1041,89 +967,20 @@


 void CodeGenSelector::VisitBinaryOperation(BinaryOperation* expr) {
-  switch (expr->op()) {
-    case Token::COMMA:
-      ProcessExpression(expr->left(), Expression::kEffect);
-      CHECK_BAILOUT;
-      ProcessExpression(expr->right(), context_);
-      break;
-
-    case Token::OR:
-      switch (context_) {
-        case Expression::kUninitialized:
-          UNREACHABLE();
-        case Expression::kEffect:  // Fall through.
-        case Expression::kTest:  // Fall through.
-        case Expression::kTestValue:
-          // The left subexpression's value is not needed, it is in a pure
-          // test context.
-          ProcessExpression(expr->left(), Expression::kTest);
-          break;
-        case Expression::kValue:  // Fall through.
-        case Expression::kValueTest:
-          // The left subexpression's value is needed, it is in a hybrid
-          // value/test context.
-          ProcessExpression(expr->left(), Expression::kValueTest);
-          break;
-      }
-      CHECK_BAILOUT;
-      ProcessExpression(expr->right(), context_);
-      break;
-
-    case Token::AND:
-      switch (context_) {
-        case Expression::kUninitialized:
-          UNREACHABLE();
-        case Expression::kEffect:  // Fall through.
-        case Expression::kTest:  // Fall through.
-        case Expression::kValueTest:
-          // The left subexpression's value is not needed, it is in a pure
-          // test context.
-          ProcessExpression(expr->left(), Expression::kTest);
-          break;
-        case Expression::kValue:  // Fall through.
-        case Expression::kTestValue:
-          // The left subexpression's value is needed, it is in a hybrid
-          // test/value context.
-          ProcessExpression(expr->left(), Expression::kTestValue);
-          break;
-      }
-      CHECK_BAILOUT;
-      ProcessExpression(expr->right(), context_);
-      break;
-
-    case Token::ADD:
-    case Token::SUB:
-    case Token::DIV:
-    case Token::MOD:
-    case Token::MUL:
-    case Token::BIT_OR:
-    case Token::BIT_AND:
-    case Token::BIT_XOR:
-    case Token::SHL:
-    case Token::SHR:
-    case Token::SAR:
-      ProcessExpression(expr->left(), Expression::kValue);
-      CHECK_BAILOUT;
-      ProcessExpression(expr->right(), Expression::kValue);
-      break;
-
-    default:
-      BAILOUT("Unsupported binary operation");
-  }
+  Visit(expr->left());
+  CHECK_BAILOUT;
+  Visit(expr->right());
 }


 void CodeGenSelector::VisitCompareOperation(CompareOperation* expr) {
-  ProcessExpression(expr->left(), Expression::kValue);
+  Visit(expr->left());
   CHECK_BAILOUT;
-  ProcessExpression(expr->right(), Expression::kValue);
+  Visit(expr->right());
 }


-void CodeGenSelector::VisitThisFunction(ThisFunction* expr) {
-  // ThisFunction is supported.
-}
+void CodeGenSelector::VisitThisFunction(ThisFunction* expr) {}

 #undef BAILOUT
 #undef CHECK_BAILOUT
=======================================
--- /branches/bleeding_edge/src/fast-codegen.cc Mon Jan 18 06:04:55 2010
+++ /branches/bleeding_edge/src/fast-codegen.cc Tue Jan 19 04:41:02 2010
@@ -165,68 +165,65 @@


 void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
-#ifdef DEBUG
-  Expression::Context expected = Expression::kUninitialized;
-  switch (expr->context()) {
-    case Expression::kUninitialized:
-      UNREACHABLE();
-    case Expression::kEffect:
-    case Expression::kTest:
-      // The value of the left subexpression is not needed.
-      expected = Expression::kTest;
-      break;
-    case Expression::kValue:
-      // The value of the left subexpression is needed and its specific
-      // context depends on the operator.
-      expected = (expr->op() == Token::OR)
-          ? Expression::kValueTest
-          : Expression::kTestValue;
-      break;
-    case Expression::kValueTest:
-      // The value of the left subexpression is needed for OR.
-      expected = (expr->op() == Token::OR)
-          ? Expression::kValueTest
-          : Expression::kTest;
-      break;
-    case Expression::kTestValue:
-      // The value of the left subexpression is needed for AND.
-      expected = (expr->op() == Token::OR)
-          ? Expression::kTest
-          : Expression::kTestValue;
-      break;
-  }
-  ASSERT_EQ(expected, expr->left()->context());
-  ASSERT_EQ(expr->context(), expr->right()->context());
-#endif
-
   Label eval_right, done;

   // Set up the appropriate context for the left subexpression based
   // on the operation and our own context.  Initially assume we can
   // inherit both true and false labels from our context.
-  Label* if_true = true_label_;
-  Label* if_false = false_label_;
   if (expr->op() == Token::OR) {
-    // If we are not in some kind of a test context, we did not inherit a
-    // true label from our context.  Use the end of the expression.
-    if (expr->context() == Expression::kEffect ||
-        expr->context() == Expression::kValue) {
-      if_true = &done;
-    }
-    // The false label is the label of the right subexpression.
-    if_false = &eval_right;
+    switch (context_) {
+      case Expression::kUninitialized:
+        UNREACHABLE();
+      case Expression::kEffect:
+        VisitForControl(expr->left(), &done, &eval_right);
+        break;
+      case Expression::kValue:
+        VisitForValueControl(expr->left(),
+                             location_,
+                             &done,
+                             &eval_right);
+        break;
+      case Expression::kTest:
+        VisitForControl(expr->left(), true_label_, &eval_right);
+        break;
+      case Expression::kValueTest:
+        VisitForValueControl(expr->left(),
+                             location_,
+                             true_label_,
+                             &eval_right);
+        break;
+      case Expression::kTestValue:
+        VisitForControl(expr->left(), true_label_, &eval_right);
+        break;
+    }
   } else {
     ASSERT_EQ(Token::AND, expr->op());
-    // The true label is the label of the right subexpression.
-    if_true = &eval_right;
-    // If we are not in some kind of a test context, we did not inherit a
-    // false label from our context.  Use the end of the expression.
-    if (expr->context() == Expression::kEffect ||
-        expr->context() == Expression::kValue) {
-      if_false = &done;
+    switch (context_) {
+      case Expression::kUninitialized:
+        UNREACHABLE();
+      case Expression::kEffect:
+        VisitForControl(expr->left(), &eval_right, &done);
+        break;
+      case Expression::kValue:
+        VisitForControlValue(expr->left(),
+                             location_,
+                             &eval_right,
+                             &done);
+        break;
+      case Expression::kTest:
+        VisitForControl(expr->left(), &eval_right, false_label_);
+        break;
+      case Expression::kValueTest:
+        VisitForControl(expr->left(), &eval_right, false_label_);
+        break;
+      case Expression::kTestValue:
+        VisitForControlValue(expr->left(),
+                             location_,
+                             &eval_right,
+                             false_label_);
+        break;
     }
   }
-  VisitForControl(expr->left(), if_true, if_false);

   __ bind(&eval_right);
   Visit(expr->right());
@@ -247,7 +244,7 @@
void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
   Comment cmnt(masm_, "[ ExpressionStatement");
   SetStatementPosition(stmt);
-  Visit(stmt->expression());
+  VisitForEffect(stmt->expression());
 }


@@ -446,7 +443,6 @@
   // that scope again afterwards.

   Label try_handler_setup, catch_entry, done;
-
   __ Call(&try_handler_setup);
   // Try handler code, exception in result register.

@@ -558,27 +554,20 @@

 void FastCodeGenerator::VisitConditional(Conditional* expr) {
   Comment cmnt(masm_, "[ Conditional");
-  ASSERT_EQ(Expression::kTest, expr->condition()->context());
-  ASSERT_EQ(expr->context(), expr->then_expression()->context());
-  ASSERT_EQ(expr->context(), expr->else_expression()->context());
-
-
   Label true_case, false_case, done;
   VisitForControl(expr->condition(), &true_case, &false_case);

   __ bind(&true_case);
   Visit(expr->then_expression());
   // If control flow falls through Visit, jump to done.
-  if (expr->context() == Expression::kEffect ||
-      expr->context() == Expression::kValue) {
+  if (context_ == Expression::kEffect || context_ == Expression::kValue) {
     __ jmp(&done);
   }

   __ bind(&false_case);
   Visit(expr->else_expression());
   // If control flow falls through Visit, merge it with true case here.
-  if (expr->context() == Expression::kEffect ||
-      expr->context() == Expression::kValue) {
+  if (context_ == Expression::kEffect || context_ == Expression::kValue) {
     __ bind(&done);
   }
 }
@@ -592,24 +581,20 @@

 void FastCodeGenerator::VisitLiteral(Literal* expr) {
   Comment cmnt(masm_, "[ Literal");
-  Apply(expr->context(), expr);
+  Apply(context_, expr);
 }


 void FastCodeGenerator::VisitAssignment(Assignment* expr) {
   Comment cmnt(masm_, "[ Assignment");
-
// Left-hand side can only be a property, a global or a (parameter or local) // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
   enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
   LhsKind assign_type = VARIABLE;
   Property* prop = expr->target()->AsProperty();
-  // In case of a property we use the uninitialized expression context
-  // of the key to detect a named property.
   if (prop != NULL) {
-    assign_type = (prop->key()->context() == Expression::kUninitialized)
-        ? NAMED_PROPERTY
-        : KEYED_PROPERTY;
+    assign_type =
+        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
   }

   // Evaluate LHS expression.
@@ -667,7 +652,7 @@
   switch (assign_type) {
     case VARIABLE:
       EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
-                             expr->context());
+                             context_);
       break;
     case NAMED_PROPERTY:
       EmitNamedPropertyAssignment(expr);
@@ -683,14 +668,11 @@
   // Call runtime routine to allocate the catch extension object and
   // assign the exception value to the catch variable.
   Comment cmnt(masm_, "[ CatchExtensionObject");
-
   VisitForValue(expr->key(), kStack);
   VisitForValue(expr->value(), kStack);
-
   // Create catch extension object.
   __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2);
-
-  __ push(result_register());
+  Apply(context_, result_register());
 }


=======================================
--- /branches/bleeding_edge/src/fast-codegen.h  Mon Jan 18 06:04:55 2010
+++ /branches/bleeding_edge/src/fast-codegen.h  Tue Jan 19 04:41:02 2010
@@ -250,26 +250,73 @@
   // register.
   MemOperand EmitSlotSearch(Slot* slot, Register scratch);

+  void VisitForEffect(Expression* expr) {
+    Expression::Context saved_context = context_;
+    context_ = Expression::kEffect;
+    Visit(expr);
+    context_ = saved_context;
+  }
+
   void VisitForValue(Expression* expr, Location where) {
-    ASSERT(expr->context() == Expression::kValue);
+    Expression::Context saved_context = context_;
     Location saved_location = location_;
+    context_ = Expression::kValue;
     location_ = where;
     Visit(expr);
+    context_ = saved_context;
     location_ = saved_location;
   }

   void VisitForControl(Expression* expr, Label* if_true, Label* if_false) {
-    ASSERT(expr->context() == Expression::kTest ||
-           expr->context() == Expression::kValueTest ||
-           expr->context() == Expression::kTestValue);
+    Expression::Context saved_context = context_;
     Label* saved_true = true_label_;
     Label* saved_false = false_label_;
+    context_ = Expression::kTest;
     true_label_ = if_true;
     false_label_ = if_false;
     Visit(expr);
+    context_ = saved_context;
     true_label_ = saved_true;
     false_label_ = saved_false;
   }
+
+  void VisitForValueControl(Expression* expr,
+                            Location where,
+                            Label* if_true,
+                            Label* if_false) {
+    Expression::Context saved_context = context_;
+    Location saved_location = location_;
+    Label* saved_true = true_label_;
+    Label* saved_false = false_label_;
+    context_ = Expression::kValueTest;
+    location_ = where;
+    true_label_ = if_true;
+    false_label_ = if_false;
+    Visit(expr);
+    context_ = saved_context;
+    location_ = saved_location;
+    true_label_ = saved_true;
+    false_label_ = saved_false;
+  }
+
+  void VisitForControlValue(Expression* expr,
+                            Location where,
+                            Label* if_true,
+                            Label* if_false) {
+    Expression::Context saved_context = context_;
+    Location saved_location = location_;
+    Label* saved_true = true_label_;
+    Label* saved_false = false_label_;
+    context_ = Expression::kTestValue;
+    location_ = where;
+    true_label_ = if_true;
+    false_label_ = if_false;
+    Visit(expr);
+    context_ = saved_context;
+    location_ = saved_location;
+    true_label_ = saved_true;
+    false_label_ = saved_false;
+  }

   void VisitDeclarations(ZoneList<Declaration*>* declarations);
   void DeclareGlobals(Handle<FixedArray> pairs);
@@ -356,6 +403,7 @@
   NestedStatement* nesting_stack_;
   int loop_depth_;

+  Expression::Context context_;
   Location location_;
   Label* true_label_;
   Label* false_label_;
=======================================
--- /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc Mon Jan 18 15:18:09 2010 +++ /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc Tue Jan 19 04:41:02 2010
@@ -775,13 +775,13 @@
   __ push(esi);
   __ push(Immediate(boilerplate));
   __ CallRuntime(Runtime::kNewClosure, 2);
-  Apply(expr->context(), eax);
+  Apply(context_, eax);
 }


 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
   Comment cmnt(masm_, "[ VariableProxy");
-  EmitVariableLoad(expr->var(), expr->context());
+  EmitVariableLoad(expr->var(), context_);
 }


@@ -885,7 +885,7 @@
   __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
   // Label done:
   __ bind(&done);
-  Apply(expr->context(), eax);
+  Apply(context_, eax);
 }


@@ -951,9 +951,9 @@
   }

   if (result_saved) {
-    ApplyTOS(expr->context());
+    ApplyTOS(context_);
   } else {
-    Apply(expr->context(), eax);
+    Apply(context_, eax);
   }
 }

@@ -1001,9 +1001,9 @@
   }

   if (result_saved) {
-    ApplyTOS(expr->context());
+    ApplyTOS(context_);
   } else {
-    Apply(expr->context(), eax);
+    Apply(context_, eax);
   }
 }

@@ -1117,7 +1117,7 @@
     __ pop(eax);
   }

-  DropAndApply(1, expr->context(), eax);
+  DropAndApply(1, context_, eax);
 }


@@ -1153,7 +1153,7 @@
   }

   // Receiver and key are still on stack.
-  DropAndApply(2, expr->context(), eax);
+  DropAndApply(2, context_, eax);
 }


@@ -1167,12 +1167,12 @@
   if (key->IsPropertyName()) {
     EmitNamedPropertyLoad(expr);
     // Drop receiver left on the stack by IC.
-    DropAndApply(1, expr->context(), eax);
+    DropAndApply(1, context_, eax);
   } else {
     VisitForValue(expr->key(), kStack);
     EmitKeyedPropertyLoad(expr);
     // Drop key and receiver left on the stack by IC.
-    DropAndApply(2, expr->context(), eax);
+    DropAndApply(2, context_, eax);
   }
 }

@@ -1194,7 +1194,7 @@
   __ call(ic, mode);
   // Restore context register.
   __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-  Apply(expr->context(), eax);
+  Apply(context_, eax);
 }


@@ -1211,7 +1211,7 @@
   __ CallStub(&stub);
   // Restore context register.
   __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-  DropAndApply(1, expr->context(), eax);
+  DropAndApply(1, context_, eax);
 }


@@ -1317,7 +1317,7 @@
   __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL);

   // Replace function on TOS with result in eax, or pop it.
-  DropAndApply(1, expr->context(), eax);
+  DropAndApply(1, context_, eax);
 }


@@ -1349,7 +1349,7 @@
     // Call the C runtime function.
     __ CallRuntime(expr->function(), arg_count);
   }
-  Apply(expr->context(), eax);
+  Apply(context_, eax);
 }


@@ -1357,9 +1357,8 @@
   switch (expr->op()) {
     case Token::VOID: {
       Comment cmnt(masm_, "[ UnaryOperation (VOID)");
-      ASSERT_EQ(Expression::kEffect, expr->expression()->context());
-      Visit(expr->expression());
-      switch (expr->context()) {
+      VisitForEffect(expr->expression());
+      switch (context_) {
         case Expression::kUninitialized:
           UNREACHABLE();
           break;
@@ -1396,14 +1395,12 @@

     case Token::NOT: {
       Comment cmnt(masm_, "[ UnaryOperation (NOT)");
-      ASSERT_EQ(Expression::kTest, expr->expression()->context());
-
       Label materialize_true, materialize_false, done;
       // Initially assume a pure test context.  Notice that the labels are
       // swapped.
       Label* if_true = false_label_;
       Label* if_false = true_label_;
-      switch (expr->context()) {
+      switch (context_) {
         case Expression::kUninitialized:
           UNREACHABLE();
           break;
@@ -1425,14 +1422,12 @@
           break;
       }
       VisitForControl(expr->expression(), if_true, if_false);
-      Apply(expr->context(), if_false, if_true);  // Labels swapped.
+      Apply(context_, if_false, if_true);  // Labels swapped.
       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_this() &&
@@ -1458,7 +1453,7 @@
       }

       __ CallRuntime(Runtime::kTypeof, 1);
-      Apply(expr->context(), eax);
+      Apply(context_, eax);
       break;
     }

@@ -1479,9 +1474,8 @@
   // In case of a property we use the uninitialized expression context
   // of the key to detect a named property.
   if (prop != NULL) {
-    assign_type = (prop->key()->context() == Expression::kUninitialized)
-        ? NAMED_PROPERTY
-        : KEYED_PROPERTY;
+    assign_type =
+        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
   }

   // Evaluate expression and get value.
@@ -1494,8 +1488,7 @@
     location_ = saved_location;
   } else  {
     // Reserve space for result of postfix operation.
-    if (expr->is_postfix() && expr->context() != Expression::kEffect) {
-      ASSERT(expr->context() != Expression::kUninitialized);
+    if (expr->is_postfix() && context_ != Expression::kEffect) {
       __ push(Immediate(Smi::FromInt(0)));
     }
     VisitForValue(prop->obj(), kStack);
@@ -1513,7 +1506,7 @@

   // Save result for postfix expressions.
   if (expr->is_postfix()) {
-    switch (expr->context()) {
+    switch (context_) {
       case Expression::kUninitialized:
         UNREACHABLE();
       case Expression::kEffect:
@@ -1557,12 +1550,12 @@
                                Expression::kEffect);
         // For all contexts except kEffect: We have the result on
         // top of the stack.
-        if (expr->context() != Expression::kEffect) {
-          ApplyTOS(expr->context());
+        if (context_ != Expression::kEffect) {
+          ApplyTOS(context_);
         }
       } else {
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
-                               expr->context());
+                               context_);
       }
       break;
     case NAMED_PROPERTY: {
@@ -1574,11 +1567,11 @@
       __ nop();
       if (expr->is_postfix()) {
         __ Drop(1);  // Result is on the stack under the receiver.
-        if (expr->context() != Expression::kEffect) {
-          ApplyTOS(expr->context());
+        if (context_ != Expression::kEffect) {
+          ApplyTOS(context_);
         }
       } else {
-        DropAndApply(1, expr->context(), eax);
+        DropAndApply(1, context_, eax);
       }
       break;
     }
@@ -1590,11 +1583,11 @@
       __ nop();
       if (expr->is_postfix()) {
__ Drop(2); // Result is on the stack under the key and the receiver.
-        if (expr->context() != Expression::kEffect) {
-          ApplyTOS(expr->context());
+        if (context_ != Expression::kEffect) {
+          ApplyTOS(context_);
         }
       } else {
-        DropAndApply(2, expr->context(), eax);
+        DropAndApply(2, context_, eax);
       }
       break;
     }
@@ -1606,9 +1599,7 @@
   Comment cmnt(masm_, "[ BinaryOperation");
   switch (expr->op()) {
     case Token::COMMA:
-      ASSERT_EQ(Expression::kEffect, expr->left()->context());
-      ASSERT_EQ(expr->context(), expr->right()->context());
-      Visit(expr->left());
+      VisitForEffect(expr->left());
       Visit(expr->right());
       break;

@@ -1630,7 +1621,7 @@
     case Token::SAR:
       VisitForValue(expr->left(), kStack);
       VisitForValue(expr->right(), kAccumulator);
-      EmitBinaryOp(expr->op(), expr->context());
+      EmitBinaryOp(expr->op(), context_);
       break;

     default:
@@ -1648,7 +1639,7 @@
   // Initially assume we are in a test context.
   Label* if_true = true_label_;
   Label* if_false = false_label_;
-  switch (expr->context()) {
+  switch (context_) {
     case Expression::kUninitialized:
       UNREACHABLE();
       break;
@@ -1750,13 +1741,13 @@

   // Convert the result of the comparison into one expected for this
   // expression's context.
-  Apply(expr->context(), if_true, if_false);
+  Apply(context_, if_true, if_false);
 }


 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
   __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
-  Apply(expr->context(), eax);
+  Apply(context_, eax);
 }


=======================================
--- /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Mon Jan 18 15:18:09 2010 +++ /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Tue Jan 19 04:41:02 2010
@@ -778,13 +778,13 @@
   __ push(rsi);
   __ Push(boilerplate);
   __ CallRuntime(Runtime::kNewClosure, 2);
-  Apply(expr->context(), rax);
+  Apply(context_, rax);
 }


 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
   Comment cmnt(masm_, "[ VariableProxy");
-  EmitVariableLoad(expr->var(), expr->context());
+  EmitVariableLoad(expr->var(), context_);
 }


@@ -886,7 +886,7 @@
   __ Push(expr->flags());
   __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
   __ bind(&done);
-  Apply(expr->context(), rax);
+  Apply(context_, rax);
 }


@@ -953,9 +953,9 @@
   }

   if (result_saved) {
-    ApplyTOS(expr->context());
+    ApplyTOS(context_);
   } else {
-    Apply(expr->context(), rax);
+    Apply(context_, rax);
   }
 }

@@ -1003,9 +1003,9 @@
   }

   if (result_saved) {
-    ApplyTOS(expr->context());
+    ApplyTOS(context_);
   } else {
-    Apply(expr->context(), rax);
+    Apply(context_, rax);
   }
 }

@@ -1117,7 +1117,7 @@
     __ pop(rax);
   }

-  DropAndApply(1, expr->context(), rax);
+  DropAndApply(1, context_, rax);
 }


@@ -1153,7 +1153,7 @@
   }

   // Receiver and key are still on stack.
-  DropAndApply(2, expr->context(), rax);
+  DropAndApply(2, context_, rax);
 }


@@ -1167,12 +1167,12 @@
   if (key->IsPropertyName()) {
     EmitNamedPropertyLoad(expr);
     // Drop receiver left on the stack by IC.
-    DropAndApply(1, expr->context(), rax);
+    DropAndApply(1, context_, rax);
   } else {
     VisitForValue(expr->key(), kStack);
     EmitKeyedPropertyLoad(expr);
     // Drop key and receiver left on the stack by IC.
-    DropAndApply(2, expr->context(), rax);
+    DropAndApply(2, context_, rax);
   }
 }

@@ -1196,7 +1196,7 @@
   // Restore context register.
   __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
   // Discard the function left on TOS.
-  DropAndApply(1, expr->context(), rax);
+  DropAndApply(1, context_, rax);
 }


@@ -1214,7 +1214,7 @@
   // Restore context register.
   __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
   // Discard the function left on TOS.
-  DropAndApply(1, expr->context(), rax);
+  DropAndApply(1, context_, rax);
 }


@@ -1323,7 +1323,7 @@
   __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);

   // Replace function on TOS with result in rax, or pop it.
-  DropAndApply(1, expr->context(), rax);
+  DropAndApply(1, context_, rax);
 }


@@ -1352,10 +1352,10 @@
     // Restore context register.
     __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
     // Discard the function left on TOS.
-    DropAndApply(1, expr->context(), rax);
+    DropAndApply(1, context_, rax);
   } else {
     __ CallRuntime(expr->function(), arg_count);
-    Apply(expr->context(), rax);
+    Apply(context_, rax);
   }
 }

@@ -1364,9 +1364,8 @@
   switch (expr->op()) {
     case Token::VOID: {
       Comment cmnt(masm_, "[ UnaryOperation (VOID)");
-      ASSERT_EQ(Expression::kEffect, expr->expression()->context());
-      Visit(expr->expression());
-      switch (expr->context()) {
+      VisitForEffect(expr->expression());
+      switch (context_) {
         case Expression::kUninitialized:
           UNREACHABLE();
           break;
@@ -1403,14 +1402,12 @@

     case Token::NOT: {
       Comment cmnt(masm_, "[ UnaryOperation (NOT)");
-      ASSERT_EQ(Expression::kTest, expr->expression()->context());
-
       Label materialize_true, materialize_false, done;
       // Initially assume a pure test context.  Notice that the labels are
       // swapped.
       Label* if_true = false_label_;
       Label* if_false = true_label_;
-      switch (expr->context()) {
+      switch (context_) {
         case Expression::kUninitialized:
           UNREACHABLE();
           break;
@@ -1432,14 +1429,12 @@
           break;
       }
       VisitForControl(expr->expression(), if_true, if_false);
-      Apply(expr->context(), if_false, if_true);  // Labels swapped.
+      Apply(context_, if_false, if_true);  // Labels swapped.
       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_this() &&
@@ -1465,7 +1460,7 @@
       }

       __ CallRuntime(Runtime::kTypeof, 1);
-      Apply(expr->context(), rax);
+      Apply(context_, rax);
       break;
     }

@@ -1486,9 +1481,8 @@
   // In case of a property we use the uninitialized expression context
   // of the key to detect a named property.
   if (prop != NULL) {
-    assign_type = (prop->key()->context() == Expression::kUninitialized)
-        ? NAMED_PROPERTY
-        : KEYED_PROPERTY;
+    assign_type =
+        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
   }

   // Evaluate expression and get value.
@@ -1501,8 +1495,7 @@
     location_ = saved_location;
   } else  {
     // Reserve space for result of postfix operation.
-    if (expr->is_postfix() && expr->context() != Expression::kEffect) {
-      ASSERT(expr->context() != Expression::kUninitialized);
+    if (expr->is_postfix() && context_ != Expression::kEffect) {
       __ Push(Smi::FromInt(0));
     }
     VisitForValue(prop->obj(), kStack);
@@ -1520,7 +1513,7 @@

   // Save result for postfix expressions.
   if (expr->is_postfix()) {
-    switch (expr->context()) {
+    switch (context_) {
       case Expression::kUninitialized:
         UNREACHABLE();
       case Expression::kEffect:
@@ -1564,12 +1557,12 @@
                                Expression::kEffect);
         // For all contexts except kEffect: We have the result on
         // top of the stack.
-        if (expr->context() != Expression::kEffect) {
-          ApplyTOS(expr->context());
+        if (context_ != Expression::kEffect) {
+          ApplyTOS(context_);
         }
       } else {
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
-                               expr->context());
+                               context_);
       }
       break;
     case NAMED_PROPERTY: {
@@ -1581,11 +1574,11 @@
       __ nop();
       if (expr->is_postfix()) {
         __ Drop(1);  // Result is on the stack under the receiver.
-        if (expr->context() != Expression::kEffect) {
-          ApplyTOS(expr->context());
+        if (context_ != Expression::kEffect) {
+          ApplyTOS(context_);
         }
       } else {
-        DropAndApply(1, expr->context(), rax);
+        DropAndApply(1, context_, rax);
       }
       break;
     }
@@ -1597,11 +1590,11 @@
       __ nop();
       if (expr->is_postfix()) {
__ Drop(2); // Result is on the stack under the key and the receiver.
-        if (expr->context() != Expression::kEffect) {
-          ApplyTOS(expr->context());
+        if (context_ != Expression::kEffect) {
+          ApplyTOS(context_);
         }
       } else {
-        DropAndApply(2, expr->context(), rax);
+        DropAndApply(2, context_, rax);
       }
       break;
     }
@@ -1612,9 +1605,7 @@
   Comment cmnt(masm_, "[ BinaryOperation");
   switch (expr->op()) {
     case Token::COMMA:
-      ASSERT_EQ(Expression::kEffect, expr->left()->context());
-      ASSERT_EQ(expr->context(), expr->right()->context());
-      Visit(expr->left());
+      VisitForEffect(expr->left());
       Visit(expr->right());
       break;

@@ -1636,7 +1627,7 @@
     case Token::SAR:
       VisitForValue(expr->left(), kStack);
       VisitForValue(expr->right(), kAccumulator);
-      EmitBinaryOp(expr->op(), expr->context());
+      EmitBinaryOp(expr->op(), context_);
       break;

     default:
@@ -1654,7 +1645,7 @@
   // Initially assume we are in a test context.
   Label* if_true = true_label_;
   Label* if_false = false_label_;
-  switch (expr->context()) {
+  switch (context_) {
     case Expression::kUninitialized:
       UNREACHABLE();
       break;
@@ -1753,13 +1744,13 @@

   // Convert the result of the comparison into one expected for this
   // expression's context.
-  Apply(expr->context(), if_true, if_false);
+  Apply(context_, if_true, if_false);
 }


 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
   __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
-  Apply(expr->context(), rax);
+  Apply(context_, rax);
 }


-- 
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to