Enable references and assignments to lookup slots in the toplevel code
authorkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 27 Jan 2010 12:14:26 +0000 (12:14 +0000)
committerkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 27 Jan 2010 12:14:26 +0000 (12:14 +0000)
generator.

Review URL: http://codereview.chromium.org/553116

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3716 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/arm/full-codegen-arm.cc
src/full-codegen.cc
src/full-codegen.h
src/ia32/full-codegen-ia32.cc
src/x64/full-codegen-x64.cc

index 9c178ae..1844c28 100644 (file)
@@ -674,9 +674,13 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
 
 void FullCodeGenerator::EmitVariableLoad(Variable* var,
                                          Expression::Context context) {
-  Expression* rewrite = var->rewrite();
-  if (rewrite == NULL) {
-    ASSERT(var->is_global());
+  // Four cases: non-this global variables, lookup slots, all other
+  // types of slots, and parameters that rewrite to explicit property
+  // accesses on the arguments object.
+  Slot* slot = var->slot();
+  Property* property = var->AsProperty();
+
+  if (var->is_global() && !var->is_this()) {
     Comment cmnt(masm_, "Global variable");
     // Use inline caching. Variable name is passed in r2 and the global
     // object on the stack.
@@ -686,34 +690,24 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
     Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
     __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
     DropAndApply(1, context, r0);
-  } else if (rewrite->AsSlot() != NULL) {
-    Slot* slot = rewrite->AsSlot();
-    if (FLAG_debug_code) {
-      switch (slot->type()) {
-        case Slot::PARAMETER:
-        case Slot::LOCAL: {
-          Comment cmnt(masm_, "Stack slot");
-          break;
-        }
-        case Slot::CONTEXT: {
-          Comment cmnt(masm_, "Context slot");
-          break;
-        }
-        case Slot::LOOKUP:
-          UNIMPLEMENTED();
-          break;
-      }
-    }
+
+  } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
+    Comment cmnt(masm_, "Lookup slot");
+    __ mov(r1, Operand(var->name()));
+    __ stm(db_w, sp, cp.bit() | r1.bit());  // Context and name.
+    __ CallRuntime(Runtime::kLoadContextSlot, 2);
+    Apply(context, r0);
+
+  } else if (slot != NULL) {
+    Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
+                            ? "Context slot"
+                            : "Stack slot");
     Apply(context, slot);
+
   } else {
-    Comment cmnt(masm_, "Variable rewritten to property");
-    // A variable has been rewritten into an explicit access to an object
-    // property.
-    Property* property = rewrite->AsProperty();
+    Comment cmnt(masm_, "Rewritten parameter");
     ASSERT_NOT_NULL(property);
-
-    // The only property expressions that can occur are of the form
-    // "slot[literal]".
+    // Rewritten parameter accesses are of the form "slot[literal]".
 
     // Assert that the object is in a slot.
     Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
@@ -927,9 +921,15 @@ void FullCodeGenerator::EmitBinaryOp(Token::Value op,
 
 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
                                                Expression::Context context) {
+  // Three main cases: global variables, lookup slots, and all other
+  // types of slots.  Left-hand-side parameters that rewrite to
+  // explicit property accesses do not reach here.
   ASSERT(var != NULL);
   ASSERT(var->is_global() || var->slot() != NULL);
+
+  Slot* slot = var->slot();
   if (var->is_global()) {
+    ASSERT(!var->is_this());
     // Assignment to a global variable.  Use inline caching for the
     // assignment.  Right-hand-side value is passed in r0, variable name in
     // r2, and the global object on the stack.
@@ -941,6 +941,13 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
     // Overwrite the global object on the stack with the result if needed.
     DropAndApply(1, context, r0);
 
+  } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
+    __ push(result_register());  // Value.
+    __ mov(r1, Operand(var->name()));
+    __ stm(db_w, sp, cp.bit() | r1.bit());  // Context and name.
+    __ CallRuntime(Runtime::kStoreContextSlot, 3);
+    Apply(context, r0);
+
   } else if (var->slot() != NULL) {
     Slot* slot = var->slot();
     switch (slot->type()) {
@@ -967,6 +974,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
         break;
     }
     Apply(context, result_register());
+
   } else {
     // Variables rewritten as properties are not treated as variables in
     // assignments.
index 4bda364..0477ab9 100644 (file)
@@ -133,7 +133,9 @@ void FullCodeGenSyntaxChecker::VisitContinueStatement(ContinueStatement* stmt) {
 }
 
 
-void FullCodeGenSyntaxChecker::VisitBreakStatement(BreakStatement* stmt) {}
+void FullCodeGenSyntaxChecker::VisitBreakStatement(BreakStatement* stmt) {
+  // Supported.
+}
 
 
 void FullCodeGenSyntaxChecker::VisitReturnStatement(ReturnStatement* stmt) {
@@ -241,30 +243,7 @@ void FullCodeGenSyntaxChecker::VisitSlot(Slot* expr) {
 
 
 void FullCodeGenSyntaxChecker::VisitVariableProxy(VariableProxy* expr) {
-  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
-      // implementing unary typeof will become live.
-      if (type == Slot::LOOKUP) {
-        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
-      Property* property = var->AsProperty();
-      ASSERT_NOT_NULL(property);
-      Variable* object = property->obj()->AsVariableProxy()->AsVariable();
-      ASSERT_NOT_NULL(object);
-      ASSERT_NOT_NULL(object->slot());
-      ASSERT_NOT_NULL(property->key()->AsLiteral());
-      ASSERT(property->key()->AsLiteral()->handle()->IsSmi());
-#endif
-    }
-  }
+  // Supported.
 }
 
 
@@ -313,8 +292,6 @@ void FullCodeGenSyntaxChecker::VisitCatchExtensionObject(
 
 
 void FullCodeGenSyntaxChecker::VisitAssignment(Assignment* expr) {
-  // We support plain non-compound assignments to properties, parameters and
-  // non-context (stack-allocated) locals, and global variables.
   Token::Value op = expr->op();
   if (op == Token::INIT_CONST) BAILOUT("initialize constant");
 
@@ -322,17 +299,8 @@ void FullCodeGenSyntaxChecker::VisitAssignment(Assignment* expr) {
   Property* prop = expr->target()->AsProperty();
   ASSERT(var == NULL || prop == NULL);
   if (var != NULL) {
-    if (var->mode() == Variable::CONST) {
-      BAILOUT("Assignment to const");
-    }
-    // All global variables are supported.
-    if (!var->is_global()) {
-      ASSERT(var->slot() != NULL);
-      Slot::Type type = var->slot()->type();
-      if (type == Slot::LOOKUP) {
-        BAILOUT("Lookup slot");
-      }
-    }
+    if (var->mode() == Variable::CONST) BAILOUT("Assignment to const");
+    // All other variables are supported.
   } else if (prop != NULL) {
     Visit(prop->obj());
     CHECK_BAILOUT;
@@ -1079,6 +1047,7 @@ void FullCodeGenerator::VisitLiteral(Literal* expr) {
 
 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
   Comment cmnt(masm_, "[ Assignment");
+  ASSERT(expr->op() != Token::INIT_CONST);
   // 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 };
@@ -1129,7 +1098,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
   Expression* rhs = expr->value();
   VisitForValue(rhs, kAccumulator);
 
-  // If we have a compount assignment: Apply operator.
+  // If we have a compound assignment: Apply operator.
   if (expr->is_compound()) {
     Location saved_location = location_;
     location_ = kAccumulator;
index acb9d52..35ed25f 100644 (file)
@@ -245,7 +245,10 @@ class FullCodeGenerator: public AstVisitor {
   // or on top of the stack) into the result expected according to an
   // expression context.
   void Apply(Expression::Context context, Register reg);
+
+  // Slot cannot have type Slot::LOOKUP.
   void Apply(Expression::Context context, Slot* slot);
+
   void Apply(Expression::Context context, Literal* lit);
   void ApplyTOS(Expression::Context context);
 
index 74de4b9..fbeec3f 100644 (file)
@@ -787,9 +787,13 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
 
 void FullCodeGenerator::EmitVariableLoad(Variable* var,
                                          Expression::Context context) {
-  Expression* rewrite = var->rewrite();
-  if (rewrite == NULL) {
-    ASSERT(var->is_global());
+  // Four cases: non-this global variables, lookup slots, all other
+  // types of slots, and parameters that rewrite to explicit property
+  // accesses on the arguments object.
+  Slot* slot = var->slot();
+  Property* property = var->AsProperty();
+
+  if (var->is_global() && !var->is_this()) {
     Comment cmnt(masm_, "Global variable");
     // Use inline caching. Variable name is passed in ecx and the global
     // object on the stack.
@@ -803,34 +807,24 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
     // (eg, push/pop elimination).
     __ nop();
     DropAndApply(1, context, eax);
-  } else if (rewrite->AsSlot() != NULL) {
-    Slot* slot = rewrite->AsSlot();
-    if (FLAG_debug_code) {
-      switch (slot->type()) {
-        case Slot::PARAMETER:
-        case Slot::LOCAL: {
-          Comment cmnt(masm_, "Stack slot");
-          break;
-        }
-        case Slot::CONTEXT: {
-          Comment cmnt(masm_, "Context slot");
-          break;
-        }
-        case Slot::LOOKUP:
-          UNIMPLEMENTED();
-          break;
-      }
-    }
+
+  } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
+    Comment cmnt(masm_, "Lookup slot");
+    __ push(esi);  // Context.
+    __ push(Immediate(var->name()));
+    __ CallRuntime(Runtime::kLoadContextSlot, 2);
+    Apply(context, eax);
+
+  } else if (slot != NULL) {
+    Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
+                            ? "Context slot"
+                            : "Stack slot");
     Apply(context, slot);
+
   } else {
-    Comment cmnt(masm_, "Variable rewritten to property");
-    // A variable has been rewritten into an explicit access to an object
-    // property.
-    Property* property = rewrite->AsProperty();
+    Comment cmnt(masm_, "Rewritten parameter");
     ASSERT_NOT_NULL(property);
-
-    // The only property expressions that can occur are of the form
-    // "slot[literal]".
+    // Rewritten parameter accesses are of the form "slot[literal]".
 
     // Assert that the object is in a slot.
     Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
@@ -1039,9 +1033,15 @@ void FullCodeGenerator::EmitBinaryOp(Token::Value op,
 
 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
                                                Expression::Context context) {
+  // Three main cases: global variables, lookup slots, and all other
+  // types of slots.  Left-hand-side parameters that rewrite to
+  // explicit property accesses do not reach here.
   ASSERT(var != NULL);
   ASSERT(var->is_global() || var->slot() != NULL);
+
+  Slot* slot = var->slot();
   if (var->is_global()) {
+    ASSERT(!var->is_this());
     // Assignment to a global variable.  Use inline caching for the
     // assignment.  Right-hand-side value is passed in eax, variable name in
     // ecx, and the global object on the stack.
@@ -1053,8 +1053,14 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
     // Overwrite the receiver on the stack with the result if needed.
     DropAndApply(1, context, eax);
 
-  } else if (var->slot() != NULL) {
-    Slot* slot = var->slot();
+  } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
+    __ push(result_register());  // Value.
+    __ push(esi);  // Context.
+    __ push(Immediate(var->name()));
+    __ CallRuntime(Runtime::kStoreContextSlot, 3);
+    Apply(context, eax);
+
+  } else if (slot != NULL) {
     switch (slot->type()) {
       case Slot::LOCAL:
       case Slot::PARAMETER:
index 002840a..a5085ca 100644 (file)
@@ -790,9 +790,13 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
 
 void FullCodeGenerator::EmitVariableLoad(Variable* var,
                                          Expression::Context context) {
-  Expression* rewrite = var->rewrite();
-  if (rewrite == NULL) {
-    ASSERT(var->is_global());
+  // Four cases: non-this global variables, lookup slots, all other
+  // types of slots, and parameters that rewrite to explicit property
+  // accesses on the arguments object.
+  Slot* slot = var->slot();
+  Property* property = var->AsProperty();
+
+  if (var->is_global() && !var->is_this()) {
     Comment cmnt(masm_, "Global variable");
     // Use inline caching. Variable name is passed in rcx and the global
     // object on the stack.
@@ -805,34 +809,24 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
     // is no test rax instruction here.
     __ nop();
     DropAndApply(1, context, rax);
-  } else if (rewrite->AsSlot() != NULL) {
-    Slot* slot = rewrite->AsSlot();
-    if (FLAG_debug_code) {
-      switch (slot->type()) {
-        case Slot::PARAMETER:
-        case Slot::LOCAL: {
-          Comment cmnt(masm_, "Stack slot");
-          break;
-        }
-        case Slot::CONTEXT: {
-          Comment cmnt(masm_, "Context slot");
-          break;
-        }
-        case Slot::LOOKUP:
-          UNIMPLEMENTED();
-          break;
-      }
-    }
+
+  } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
+    Comment cmnt(masm_, "Lookup slot");
+    __ push(rsi);  // Context.
+    __ Push(var->name());
+    __ CallRuntime(Runtime::kLoadContextSlot, 2);
+    Apply(context, rax);
+
+  } else if (slot != NULL) {
+    Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
+                            ? "Context slot"
+                            : "Stack slot");
     Apply(context, slot);
+
   } else {
-    Comment cmnt(masm_, "Variable rewritten to property");
-    // A variable has been rewritten into an explicit access to an object
-    // property.
-    Property* property = rewrite->AsProperty();
+    Comment cmnt(masm_, "Rewritten parameter");
     ASSERT_NOT_NULL(property);
-
-    // The only property expressions that can occur are of the form
-    // "slot[literal]".
+    // Rewritten parameter accesses are of the form "slot[literal]".
 
     // Assert that the object is in a slot.
     Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
@@ -1041,9 +1035,14 @@ void FullCodeGenerator::EmitBinaryOp(Token::Value op,
 
 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
                                                Expression::Context context) {
+  // Three main cases: non-this global variables, lookup slots, and
+  // all other types of slots.  Left-hand-side parameters that rewrite
+  // to explicit property accesses do not reach here.
   ASSERT(var != NULL);
   ASSERT(var->is_global() || var->slot() != NULL);
+  Slot* slot = var->slot();
   if (var->is_global()) {
+    ASSERT(!var->is_this());
     // Assignment to a global variable.  Use inline caching for the
     // assignment.  Right-hand-side value is passed in rax, variable name in
     // rcx, and the global object on the stack.
@@ -1054,8 +1053,14 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
     // Overwrite the global object on the stack with the result if needed.
     DropAndApply(1, context, rax);
 
+  } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
+    __ push(result_register());  // Value.
+    __ push(rsi);  // Context.
+    __ Push(var->name());
+    __ CallRuntime(Runtime::kStoreContextSlot, 3);
+    Apply(context, rax);
+
   } else if (var->slot() != NULL) {
-    Slot* slot = var->slot();
     switch (slot->type()) {
       case Slot::LOCAL:
       case Slot::PARAMETER:
@@ -1078,6 +1083,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
         break;
     }
     Apply(context, result_register());
+
   } else {
     // Variables rewritten as properties are not treated as variables in
     // assignments.