Support declarations of context allocated locals in Crankshaft.
authorfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 1 Sep 2011 16:33:57 +0000 (16:33 +0000)
committerfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 1 Sep 2011 16:33:57 +0000 (16:33 +0000)
The changes to scopes and parser introduce a VariableProxy
wrapping the function-name variable for function literals.
It seems the easiest way to get an AST id for the HSimulate
after context-slot stores in declarations.
Review URL: http://codereview.chromium.org/7826009

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

src/arm/full-codegen-arm.cc
src/full-codegen.h
src/hydrogen.cc
src/hydrogen.h
src/ia32/full-codegen-ia32.cc
src/scopeinfo.cc
src/scopes.cc
src/scopes.h
src/x64/full-codegen-x64.cc

index 13421880f6918b0c3c8fa5af0df00d28dd9e195b..fc12bd03fce88c9f7248a649f2f6a38d88f23a31 100644 (file)
@@ -688,10 +688,11 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
 }
 
 
-void FullCodeGenerator::EmitDeclaration(Variable* variable,
+void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
                                         Variable::Mode mode,
                                         FunctionLiteral* function) {
   Comment cmnt(masm_, "[ Declaration");
+  Variable* variable = proxy->var();
   ASSERT(variable != NULL);  // Must have been resolved.
   Slot* slot = variable->AsSlot();
   ASSERT(slot != NULL);
@@ -729,10 +730,12 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
         // We know that we have written a function, which is not a smi.
         __ mov(r1, Operand(cp));
         __ RecordWrite(r1, Operand(offset), r2, result_register());
+        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
       } else if (mode == Variable::CONST || mode == Variable::LET) {
         __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
         __ str(ip, ContextOperand(cp, slot->index()));
         // No write barrier since the_hole_value is in old space.
+        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
       }
       break;
 
@@ -767,7 +770,7 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
 
 
 void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
-  EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
+  EmitDeclaration(decl->proxy(), decl->mode(), decl->fun());
 }
 
 
index 56bfe85cac4965b85ad7add517c35ded0fbd3a35..28be00855ec28a8053c2356d512abd4f7f26478b 100644 (file)
@@ -403,7 +403,7 @@ class FullCodeGenerator: public AstVisitor {
 
   // Platform-specific code for a variable, constant, or function
   // declaration.  Functions have an initial value.
-  void EmitDeclaration(Variable* variable,
+  void EmitDeclaration(VariableProxy* proxy,
                        Variable::Mode mode,
                        FunctionLiteral* function);
 
index f848e7fd912a4a3e36104056152be06b579ebbd5..57f5ff57acb0ff87fbc2f75913b6c752c4d3b1a6 100644 (file)
@@ -2298,11 +2298,7 @@ HGraph* HGraphBuilder::CreateGraph() {
     // Handle implicit declaration of the function name in named function
     // expressions before other declarations.
     if (scope->is_function_scope() && scope->function() != NULL) {
-      if (!scope->function()->IsStackAllocated()) {
-        Bailout("unsupported declaration");
-        return NULL;
-      }
-      environment()->Bind(scope->function(), graph()->GetConstantHole());
+      HandleDeclaration(scope->function(), Variable::CONST, NULL);
     }
     VisitDeclarations(scope->declarations());
     AddSimulate(AstNode::kDeclarationsId);
@@ -5822,20 +5818,51 @@ void HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
 
 
 void HGraphBuilder::VisitDeclaration(Declaration* decl) {
-  // We support only declarations that do not require code generation.
-  Variable* var = decl->proxy()->var();
-  if (!var->IsStackAllocated() ||
-      decl->mode() == Variable::LET) {
-    return Bailout("unsupported declaration");
-  }
-
-  if (decl->mode() == Variable::CONST) {
-    ASSERT(var->IsStackAllocated());
-    environment()->Bind(var, graph()->GetConstantHole());
-  } else if (decl->fun() != NULL) {
-    VisitForValue(decl->fun());
-    HValue* function = Pop();
-    environment()->Bind(var, function);
+  HandleDeclaration(decl->proxy(), decl->mode(), decl->fun());
+}
+
+
+void HGraphBuilder::HandleDeclaration(VariableProxy* proxy,
+                                    Variable::Mode mode,
+                                    FunctionLiteral* function) {
+  if (mode == Variable::LET) return Bailout("unsupported let declaration");
+  Variable* var = proxy->var();
+  Slot* slot = var->AsSlot();
+  ASSERT(slot != NULL);
+  switch (slot->type()) {
+    case Slot::PARAMETER:
+    case Slot::LOCAL:
+      if (mode == Variable::CONST) {
+        environment()->Bind(var, graph()->GetConstantHole());
+      } else if (function != NULL) {
+        VisitForValue(function);
+        HValue* function_value = Pop();
+        environment()->Bind(var, function_value);
+      }
+      break;
+    case Slot::CONTEXT: {
+      HValue* context = environment()->LookupContext();
+      if (mode == Variable::CONST) {
+        HStoreContextSlot* store =
+            new HStoreContextSlot(context,
+                                  slot->index(),
+                                  graph()->GetConstantHole());
+        AddInstruction(store);
+        if (store->HasSideEffects()) AddSimulate(proxy->id());
+      } else if (function != NULL) {
+        VisitForValue(function);
+        HValue* function_value = Pop();
+        HStoreContextSlot* store =
+            new HStoreContextSlot(context,
+                                  slot->index(),
+                                  function_value);
+        AddInstruction(store);
+        if (store->HasSideEffects()) AddSimulate(proxy->id());
+      }
+      break;
+    }
+    case Slot::LOOKUP:
+      return Bailout("unsupported lookup slot in declaration");
   }
 }
 
index c18ba5815345821dddc7507ba7d080314c6c00ef..b5fdf4902639d1a5db8ca9643d18478ea543caba 100644 (file)
@@ -779,6 +779,10 @@ class HGraphBuilder: public AstVisitor {
   INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
 #undef INLINE_FUNCTION_GENERATOR_DECLARATION
 
+  void HandleDeclaration(VariableProxy* proxy,
+                         Variable::Mode mode,
+                         FunctionLiteral* function);
+
   void VisitDelete(UnaryOperation* expr);
   void VisitVoid(UnaryOperation* expr);
   void VisitTypeof(UnaryOperation* expr);
index edeb028b252b18a689284bc4b303ed546f4a103d..a0e4faa38240a288dc7f145f3b2d03e8fc7444f5 100644 (file)
@@ -684,10 +684,11 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
 }
 
 
-void FullCodeGenerator::EmitDeclaration(Variable* variable,
+void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
                                         Variable::Mode mode,
                                         FunctionLiteral* function) {
   Comment cmnt(masm_, "[ Declaration");
+  Variable* variable = proxy->var();
   ASSERT(variable != NULL);  // Must have been resolved.
   Slot* slot = variable->AsSlot();
   ASSERT(slot != NULL);
@@ -724,10 +725,12 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
         int offset = Context::SlotOffset(slot->index());
         __ mov(ebx, esi);
         __ RecordWrite(ebx, offset, result_register(), ecx);
+        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
       } else if (mode == Variable::CONST || mode == Variable::LET) {
         __ mov(ContextOperand(esi, slot->index()),
                Immediate(isolate()->factory()->the_hole_value()));
         // No write barrier since the hole value is in old space.
+        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
       }
       break;
 
@@ -763,7 +766,7 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
 
 
 void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
-  EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
+  EmitDeclaration(decl->proxy(), decl->mode(), decl->fun());
 }
 
 
index 0eacc83c79a3b5d5c11d8bc50e2836317b8a78b2..6d1ffb99b8448687dbe133baf647fc1798efd170 100644 (file)
@@ -131,18 +131,18 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope)
   // For now, this must happen at the very end because of the
   // ordering of the scope info slots and the respective slot indices.
   if (scope->is_function_scope()) {
-    Variable* var = scope->function();
-    if (var != NULL &&
-        var->is_used() &&
-        var->AsSlot()->type() == Slot::CONTEXT) {
-      function_name_ = var->name();
+    VariableProxy* proxy = scope->function();
+    if (proxy != NULL &&
+        proxy->var()->is_used() &&
+        proxy->var()->IsContextSlot()) {
+      function_name_ = proxy->name();
       // Note that we must not find the function name in the context slot
       // list - instead it must be handled separately in the
       // Contexts::Lookup() function. Thus record an empty symbol here so we
       // get the correct number of context slots.
-      ASSERT(var->AsSlot()->index() - Context::MIN_CONTEXT_SLOTS ==
+      ASSERT(proxy->var()->AsSlot()->index() - Context::MIN_CONTEXT_SLOTS ==
              context_slots_.length());
-      ASSERT(var->AsSlot()->index() - Context::MIN_CONTEXT_SLOTS ==
+      ASSERT(proxy->var()->AsSlot()->index() - Context::MIN_CONTEXT_SLOTS ==
              context_modes_.length());
       context_slots_.Add(FACTORY->empty_symbol());
       context_modes_.Add(Variable::INTERNAL);
index 8d5a4a84e9ec93d8eeaeb54a63c082946f4c1fe3..b2958db60fbc20d5d7689bfcb4aca8adf50ca2c6 100644 (file)
@@ -378,8 +378,10 @@ Variable* Scope::Lookup(Handle<String> name) {
 
 Variable* Scope::DeclareFunctionVar(Handle<String> name) {
   ASSERT(is_function_scope() && function_ == NULL);
-  function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL);
-  return function_;
+  Variable* function_var =
+      new Variable(this, name, Variable::CONST, true, Variable::NORMAL);
+  function_ = new(isolate_->zone()) VariableProxy(isolate_, function_var);
+  return function_->var();
 }
 
 
@@ -715,7 +717,7 @@ void Scope::Print(int n) {
   PrettyPrinter printer;
   Indent(n1, "// function var\n");
   if (function_ != NULL) {
-    PrintVar(&printer, n1, function_);
+    PrintVar(&printer, n1, function_->var());
   }
 
   Indent(n1, "// temporary vars\n");
@@ -796,7 +798,7 @@ Variable* Scope::LookupRecursive(Handle<String> name,
     // the name of named function literal is kept in an intermediate scope
     // in between this scope and the next outer scope.)
     if (function_ != NULL && function_->name().is_identical_to(name)) {
-      var = function_;
+      var = function_->var();
 
     } else if (outer_scope_ != NULL) {
       var = outer_scope_->LookupRecursive(
@@ -1114,7 +1116,7 @@ void Scope::AllocateNonParameterLocals() {
   // because of the current ScopeInfo implementation (see
   // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
   if (function_ != NULL) {
-    AllocateNonParameterLocal(function_);
+    AllocateNonParameterLocal(function_->var());
   }
 }
 
index 4af19d3938194fd492d0e2f73ff021816e52df52..a01d9c7d472b5c2b1005d158c5efed6088c6af0e 100644 (file)
@@ -239,7 +239,7 @@ class Scope: public ZoneObject {
   // The variable holding the function literal for named function
   // literals, or NULL.
   // Only valid for function scopes.
-  Variable* function() const {
+  VariableProxy* function() const {
     ASSERT(is_function_scope());
     return function_;
   }
@@ -358,7 +358,7 @@ class Scope: public ZoneObject {
   // Convenience variable.
   Variable* receiver_;
   // Function variable, if any; function scopes only.
-  Variable* function_;
+  VariableProxy* function_;
   // Convenience variable; function scopes only.
   Variable* arguments_;
 
index 55a3905b92cd4c2003ae242732d31b6a604bb86f..6b3f45f9b371453ec4753a46151b4015343015da 100644 (file)
@@ -659,10 +659,11 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
 }
 
 
-void FullCodeGenerator::EmitDeclaration(Variable* variable,
+void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
                                         Variable::Mode mode,
                                         FunctionLiteral* function) {
   Comment cmnt(masm_, "[ Declaration");
+  Variable* variable = proxy->var();
   ASSERT(variable != NULL);  // Must have been resolved.
   Slot* slot = variable->AsSlot();
   ASSERT(slot != NULL);
@@ -699,10 +700,12 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
         int offset = Context::SlotOffset(slot->index());
         __ movq(rbx, rsi);
         __ RecordWrite(rbx, offset, result_register(), rcx);
+        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
       } else if (mode == Variable::CONST || mode == Variable::LET) {
         __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
         __ movq(ContextOperand(rsi, slot->index()), kScratchRegister);
         // No write barrier since the hole value is in old space.
+        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
       }
       break;
 
@@ -734,7 +737,7 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
 
 
 void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
-  EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
+  EmitDeclaration(decl->proxy(), decl->mode(), decl->fun());
 }