Revision: 10854
Author:   [email protected]
Date:     Tue Feb 28 02:12:39 2012
Log:      Further refactoring of declarations in the AST:

Define modules as module declarations.
Separate function declarations from var declarations.

[email protected]
BUG=
TEST=

Review URL: https://chromiumcodereview.appspot.com/9460064
http://code.google.com/p/v8/source/detail?r=10854

Modified:
 /branches/bleeding_edge/src/ast.cc
 /branches/bleeding_edge/src/ast.h
 /branches/bleeding_edge/src/full-codegen.cc
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/hydrogen.h
 /branches/bleeding_edge/src/parser.cc
 /branches/bleeding_edge/src/parser.h
 /branches/bleeding_edge/src/prettyprinter.cc
 /branches/bleeding_edge/src/rewriter.cc

=======================================
--- /branches/bleeding_edge/src/ast.cc  Tue Feb 28 01:05:55 2012
+++ /branches/bleeding_edge/src/ast.cc  Tue Feb 28 02:12:39 2012
@@ -417,8 +417,8 @@
   return proxy()->var()->IsStackAllocated();
 }

-bool VariableDeclaration::IsInlineable() const {
-  return Declaration::IsInlineable() && fun() == NULL;
+bool FunctionDeclaration::IsInlineable() const {
+  return false;
 }


@@ -1003,6 +1003,7 @@
   }

 INCREASE_NODE_COUNT(VariableDeclaration)
+INCREASE_NODE_COUNT(FunctionDeclaration)
 INCREASE_NODE_COUNT(ModuleDeclaration)
 INCREASE_NODE_COUNT(ModuleLiteral)
 INCREASE_NODE_COUNT(ModuleVariable)
=======================================
--- /branches/bleeding_edge/src/ast.h   Tue Feb 28 01:05:55 2012
+++ /branches/bleeding_edge/src/ast.h   Tue Feb 28 02:12:39 2012
@@ -61,6 +61,7 @@

 #define DECLARATION_NODE_LIST(V)                \
   V(VariableDeclaration)                        \
+  V(FunctionDeclaration)                        \
   V(ModuleDeclaration)                          \

 #define MODULE_NODE_LIST(V)                     \
@@ -444,10 +445,10 @@
   VariableProxy* proxy() const { return proxy_; }
   VariableMode mode() const { return mode_; }
   Scope* scope() const { return scope_; }
+  virtual InitializationFlag initialization() const = 0;
   virtual bool IsInlineable() const;

   virtual Declaration* AsDeclaration() { return this; }
-  virtual VariableDeclaration* AsVariableDeclaration() { return NULL; }

  protected:
   Declaration(VariableProxy* proxy,
@@ -475,22 +476,43 @@
  public:
   DECLARE_NODE_TYPE(VariableDeclaration)

-  virtual VariableDeclaration* AsVariableDeclaration() { return this; }
-
-  FunctionLiteral* fun() const { return fun_; }  // may be NULL
+  virtual InitializationFlag initialization() const {
+    return mode() == VAR ? kCreatedInitialized : kNeedsInitialization;
+  }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  VariableDeclaration(VariableProxy* proxy,
+                      VariableMode mode,
+                      Scope* scope)
+      : Declaration(proxy, mode, scope) {
+  }
+};
+
+
+class FunctionDeclaration: public Declaration {
+ public:
+  DECLARE_NODE_TYPE(FunctionDeclaration)
+
+  FunctionLiteral* fun() const { return fun_; }
+  virtual InitializationFlag initialization() const {
+    return kCreatedInitialized;
+  }
   virtual bool IsInlineable() const;

  protected:
   template<class> friend class AstNodeFactory;

-  VariableDeclaration(VariableProxy* proxy,
+  FunctionDeclaration(VariableProxy* proxy,
                       VariableMode mode,
                       FunctionLiteral* fun,
                       Scope* scope)
       : Declaration(proxy, mode, scope),
         fun_(fun) {
-    // At the moment there are no "const functions"'s in JavaScript...
-    ASSERT(fun == NULL || mode == VAR || mode == LET);
+    // At the moment there are no "const functions" in JavaScript...
+    ASSERT(mode == VAR || mode == LET);
+    ASSERT(fun != NULL);
   }

  private:
@@ -503,6 +525,9 @@
   DECLARE_NODE_TYPE(ModuleDeclaration)

   Module* module() const { return module_; }
+  virtual InitializationFlag initialization() const {
+    return kCreatedInitialized;
+  }

  protected:
   template<class> friend class AstNodeFactory;
@@ -2532,12 +2557,20 @@

   VariableDeclaration* NewVariableDeclaration(VariableProxy* proxy,
                                               VariableMode mode,
-                                              FunctionLiteral* fun,
                                               Scope* scope) {
     VariableDeclaration* decl =
-        new(zone_) VariableDeclaration(proxy, mode, fun, scope);
+        new(zone_) VariableDeclaration(proxy, mode, scope);
     VISIT_AND_RETURN(VariableDeclaration, decl)
   }
+
+  FunctionDeclaration* NewFunctionDeclaration(VariableProxy* proxy,
+                                              VariableMode mode,
+                                              FunctionLiteral* fun,
+                                              Scope* scope) {
+    FunctionDeclaration* decl =
+        new(zone_) FunctionDeclaration(proxy, mode, fun, scope);
+    VISIT_AND_RETURN(FunctionDeclaration, decl)
+  }

   ModuleDeclaration* NewModuleDeclaration(VariableProxy* proxy,
                                           Module* module,
=======================================
--- /branches/bleeding_edge/src/full-codegen.cc Sun Feb 26 23:49:14 2012
+++ /branches/bleeding_edge/src/full-codegen.cc Tue Feb 28 02:12:39 2012
@@ -54,6 +54,10 @@
 void BreakableStatementChecker::VisitVariableDeclaration(
     VariableDeclaration* decl) {
 }
+
+void BreakableStatementChecker::VisitFunctionDeclaration(
+    FunctionDeclaration* decl) {
+}

 void BreakableStatementChecker::VisitModuleDeclaration(
     ModuleDeclaration* decl) {
@@ -569,29 +573,28 @@
        isolate()->factory()->NewFixedArray(2 * global_count_, TENURED);
     int length = declarations->length();
     for (int j = 0, i = 0; i < length; i++) {
- VariableDeclaration* decl = declarations->at(i)->AsVariableDeclaration();
-      if (decl != NULL) {
-        Variable* var = decl->proxy()->var();
-
-        if (var->IsUnallocated()) {
-          array->set(j++, *(var->name()));
-          if (decl->fun() == NULL) {
-            if (var->binding_needs_init()) {
-              // In case this binding needs initialization use the hole.
-              array->set_the_hole(j++);
-            } else {
-              array->set_undefined(j++);
-            }
+      Declaration* decl = declarations->at(i);
+      Variable* var = decl->proxy()->var();
+
+      if (var->IsUnallocated()) {
+        array->set(j++, *(var->name()));
+        FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration();
+        if (fun_decl == NULL) {
+          if (var->binding_needs_init()) {
+            // In case this binding needs initialization use the hole.
+            array->set_the_hole(j++);
           } else {
-            Handle<SharedFunctionInfo> function =
-                Compiler::BuildFunctionInfo(decl->fun(), script());
-            // Check for stack-overflow exception.
-            if (function.is_null()) {
-              SetStackOverflow();
-              return;
-            }
-            array->set(j++, *function);
-          }
+            array->set_undefined(j++);
+          }
+        } else {
+          Handle<SharedFunctionInfo> function =
+              Compiler::BuildFunctionInfo(fun_decl->fun(), script());
+          // Check for stack-overflow exception.
+          if (function.is_null()) {
+            SetStackOverflow();
+            return;
+          }
+          array->set(j++, *function);
         }
       }
     }
@@ -605,12 +608,17 @@


void FullCodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
+  EmitDeclaration(decl->proxy(), decl->mode(), NULL);
+}
+
+
+void FullCodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
   EmitDeclaration(decl->proxy(), decl->mode(), decl->fun());
 }


 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* decl) {
-  // TODO(rossberg)
+  EmitDeclaration(decl->proxy(), decl->mode(), NULL);
 }


=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Tue Feb 28 01:05:55 2012
+++ /branches/bleeding_edge/src/hydrogen.cc     Tue Feb 28 02:12:39 2012
@@ -2466,7 +2466,7 @@
     // Handle implicit declaration of the function name in named function
     // expressions before other declarations.
     if (scope->is_function_scope() && scope->function() != NULL) {
-      HandleVariableDeclaration(scope->function(), CONST, NULL, NULL);
+      HandleDeclaration(scope->function(), CONST, NULL, NULL);
     }
     VisitDeclarations(scope->declarations());
     AddSimulate(AstNode::kDeclarationsId);
@@ -6826,20 +6826,16 @@
 }


-void HGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
-  UNREACHABLE();
-}
-
void HGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) {
   int length = declarations->length();
   int global_count = 0;
   for (int i = 0; i < declarations->length(); i++) {
- VariableDeclaration* decl = declarations->at(i)->AsVariableDeclaration();
-    if (decl == NULL) continue;
-    HandleVariableDeclaration(decl->proxy(),
-                              decl->mode(),
-                              decl->fun(),
-                              &global_count);
+    Declaration* decl = declarations->at(i);
+    FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration();
+    HandleDeclaration(decl->proxy(),
+                      decl->mode(),
+                      fun_decl != NULL ? fun_decl->fun() : NULL,
+                      &global_count);
   }

   // Batch declare global functions and variables.
@@ -6847,13 +6843,13 @@
     Handle<FixedArray> array =
         isolate()->factory()->NewFixedArray(2 * global_count, TENURED);
     for (int j = 0, i = 0; i < length; i++) {
- VariableDeclaration* decl = declarations->at(i)->AsVariableDeclaration();
-      if (decl == NULL) continue;
+      Declaration* decl = declarations->at(i);
       Variable* var = decl->proxy()->var();

       if (var->IsUnallocated()) {
         array->set(j++, *(var->name()));
-        if (decl->fun() == NULL) {
+        FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration();
+        if (fun_decl == NULL) {
           if (var->binding_needs_init()) {
             // In case this binding needs initialization use the hole.
             array->set_the_hole(j++);
@@ -6862,7 +6858,7 @@
           }
         } else {
           Handle<SharedFunctionInfo> function =
-              Compiler::BuildFunctionInfo(decl->fun(), info()->script());
+ Compiler::BuildFunctionInfo(fun_decl->fun(), info()->script());
           // Check for stack-overflow exception.
           if (function.is_null()) {
             SetStackOverflow();
@@ -6884,10 +6880,10 @@
 }


-void HGraphBuilder::HandleVariableDeclaration(VariableProxy* proxy,
-                                              VariableMode mode,
-                                              FunctionLiteral* function,
-                                              int* global_count) {
+void HGraphBuilder::HandleDeclaration(VariableProxy* proxy,
+                                      VariableMode mode,
+                                      FunctionLiteral* function,
+                                      int* global_count) {
   Variable* var = proxy->var();
   bool binding_needs_init =
       (mode == CONST || mode == CONST_HARMONY || mode == LET);
@@ -6921,6 +6917,16 @@
       return Bailout("unsupported lookup slot in declaration");
   }
 }
+
+
+void HGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
+  UNREACHABLE();
+}
+
+
+void HGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
+  UNREACHABLE();
+}


 void HGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* decl) {
=======================================
--- /branches/bleeding_edge/src/hydrogen.h      Tue Feb 28 01:38:16 2012
+++ /branches/bleeding_edge/src/hydrogen.h      Tue Feb 28 02:12:39 2012
@@ -870,10 +870,10 @@
   INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
 #undef INLINE_FUNCTION_GENERATOR_DECLARATION

-  void HandleVariableDeclaration(VariableProxy* proxy,
-                                 VariableMode mode,
-                                 FunctionLiteral* function,
-                                 int* global_count);
+  void HandleDeclaration(VariableProxy* proxy,
+                         VariableMode mode,
+                         FunctionLiteral* function,
+                         int* global_count);

   void VisitDelete(UnaryOperation* expr);
   void VisitVoid(UnaryOperation* expr);
=======================================
--- /branches/bleeding_edge/src/parser.cc       Fri Feb 24 07:53:09 2012
+++ /branches/bleeding_edge/src/parser.cc       Tue Feb 28 02:12:39 2012
@@ -1221,13 +1221,14 @@
   // Create new block with one expected declaration.
   Block* block = factory()->NewBlock(NULL, 1, true);
   Handle<String> name = ParseIdentifier(CHECK_OK);
-  // top_scope_->AddDeclaration(
-  //     factory()->NewModuleDeclaration(proxy, module, top_scope_));
-  VariableProxy* proxy = Declare(name, LET, NULL, true, CHECK_OK);
-  Module* module = ParseModule(ok);
+  Module* module = ParseModule(CHECK_OK);
+  VariableProxy* proxy = NewUnresolved(name, LET);
+  Declaration* declaration =
+      factory()->NewModuleDeclaration(proxy, module, top_scope_);
+  Declare(declaration, true, CHECK_OK);
+
   // TODO(rossberg): Add initialization statement to block.
-  USE(proxy);
-  USE(module);
+
   return block;
 }

@@ -1497,21 +1498,22 @@
 }


-VariableProxy* Parser::Declare(Handle<String> name,
-                               VariableMode mode,
-                               FunctionLiteral* fun,
-                               bool resolve,
-                               bool* ok) {
-  Variable* var = NULL;
+VariableProxy* Parser::NewUnresolved(Handle<String> name, VariableMode mode) { // If we are inside a function, a declaration of a var/const variable is a // truly local variable, and the scope of the variable is always the function
   // scope.
// Let/const variables in harmony mode are always added to the immediately
   // enclosing scope.
-  Scope* declaration_scope = (mode == LET || mode == CONST_HARMONY)
-      ? top_scope_ : top_scope_->DeclarationScope();
-  InitializationFlag init_flag = (fun != NULL || mode == VAR)
-      ? kCreatedInitialized : kNeedsInitialization;
+  return DeclarationScope(mode)->NewUnresolved(
+      factory(), name, scanner().location().beg_pos);
+}
+
+
+void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
+  Handle<String> name = declaration->proxy()->name();
+  VariableMode mode = declaration->mode();
+  Scope* declaration_scope = DeclarationScope(mode);
+  Variable* var = NULL;

   // If a function scope exists, then we can statically declare this
   // variable and also set its mode. In any case, a Declaration node
@@ -1531,7 +1533,8 @@
     var = declaration_scope->LocalLookup(name);
     if (var == NULL) {
       // Declare the name.
-      var = declaration_scope->DeclareLocal(name, mode, init_flag);
+      var = declaration_scope->DeclareLocal(
+          name, mode, declaration->initialization());
     } else {
       // The name was declared in this scope before; check for conflicting
// re-declarations. We have a conflict if either of the declarations is
@@ -1558,7 +1561,7 @@
           Vector<const char*> args(elms, 2);
           ReportMessage("redeclaration", args);
           *ok = false;
-          return NULL;
+          return;
         }
         const char* type = (var->mode() == VAR)
             ? "var" : var->is_const_mode() ? "const" : "let";
@@ -1588,10 +1591,7 @@
   // semantic issue as long as we keep the source order, but it may be
   // a performance issue since it may lead to repeated
   // Runtime::DeclareContextSlot() calls.
-  VariableProxy* proxy = declaration_scope->NewUnresolved(
-      factory(), name, scanner().location().beg_pos);
-  declaration_scope->AddDeclaration(
-      factory()->NewVariableDeclaration(proxy, mode, fun, top_scope_));
+  declaration_scope->AddDeclaration(declaration);

   if ((mode == CONST || mode == CONST_HARMONY) &&
       declaration_scope->is_global_scope()) {
@@ -1615,7 +1615,7 @@
                                mode,
                                true,
                                kind,
-                               init_flag);
+                               declaration->initialization());
     var->AllocateTo(Variable::LOOKUP, -1);
     resolve = true;
   }
@@ -1644,9 +1644,7 @@
   // initialization code. Thus, inside the 'with' statement, we need
   // both access to the static and the dynamic context chain; the
   // runtime needs to provide both.
-  if (resolve && var != NULL) proxy->BindTo(var);
-
-  return proxy;
+  if (resolve && var != NULL) declaration->proxy()->BindTo(var);
 }


@@ -1673,7 +1671,7 @@
   // isn't lazily compiled. The extension structures are only
   // accessible while parsing the first time not when reparsing
   // because of lazy compilation.
-  top_scope_->DeclarationScope()->ForceEagerCompilation();
+  DeclarationScope(VAR)->ForceEagerCompilation();

   // Compute the function template for the native function.
   v8::Handle<v8::FunctionTemplate> fun_template =
@@ -1698,12 +1696,15 @@
   // TODO(1240846): It's weird that native function declarations are
   // introduced dynamically when we meet their declarations, whereas
   // other functions are set up when entering the surrounding scope.
+  VariableProxy* proxy = NewUnresolved(name, VAR);
+  Declaration* declaration =
+      factory()->NewVariableDeclaration(proxy, VAR, top_scope_);
+  Declare(declaration, true, CHECK_OK);
   SharedFunctionInfoLiteral* lit =
       factory()->NewSharedFunctionInfoLiteral(shared);
-  VariableProxy* var = Declare(name, VAR, NULL, true, CHECK_OK);
   return factory()->NewExpressionStatement(
       factory()->NewAssignment(
-          Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
+          Token::INIT_VAR, proxy, lit, RelocInfo::kNoPosition));
 }


@@ -1724,7 +1725,10 @@
   // scope, we treat is as such and introduce the function with it's
   // initial value upon entering the corresponding scope.
   VariableMode mode = is_extended_mode() ? LET : VAR;
-  Declare(name, mode, fun, true, CHECK_OK);
+  VariableProxy* proxy = NewUnresolved(name, mode);
+  Declaration* declaration =
+      factory()->NewFunctionDeclaration(proxy, mode, fun, top_scope_);
+  Declare(declaration, true, CHECK_OK);
   return factory()->NewEmptyStatement();
 }

@@ -1902,8 +1906,8 @@
     UNREACHABLE();  // by current callers
   }

-  Scope* declaration_scope = (mode == LET || mode == CONST_HARMONY)
-      ? top_scope_ : top_scope_->DeclarationScope();
+  Scope* declaration_scope = DeclarationScope(mode);
+
   // The scope of a var/const declared variable anywhere inside a function
   // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
   // transform a source-level var/const declaration into a (Function)
@@ -1950,7 +1954,10 @@
     // For let/const declarations in harmony mode, we can also immediately
     // pre-resolve the proxy because it resides in the same scope as the
     // declaration.
- VariableProxy* proxy = Declare(name, mode, NULL, mode != VAR, CHECK_OK);
+    VariableProxy* proxy = NewUnresolved(name, mode);
+    Declaration* declaration =
+        factory()->NewVariableDeclaration(proxy, mode, top_scope_);
+    Declare(declaration, mode != VAR, CHECK_OK);
     nvars++;
     if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
       ReportMessageAt(scanner().location(), "too_many_variables",
=======================================
--- /branches/bleeding_edge/src/parser.h        Mon Feb 20 06:02:59 2012
+++ /branches/bleeding_edge/src/parser.h        Tue Feb 28 02:12:39 2012
@@ -566,6 +566,10 @@
     ASSERT(top_scope_ != NULL);
     return top_scope_->is_extended_mode();
   }
+  Scope* DeclarationScope(VariableMode mode) {
+    return (mode == LET || mode == CONST_HARMONY)
+        ? top_scope_ : top_scope_->DeclarationScope();
+  }

   // Check if the given string is 'eval' or 'arguments'.
   bool IsEvalOrArguments(Handle<String> string);
@@ -756,10 +760,8 @@
   void CheckConflictingVarDeclarations(Scope* scope, bool* ok);

   // Parser support
-  VariableProxy* Declare(Handle<String> name, VariableMode mode,
-                         FunctionLiteral* fun,
-                         bool resolve,
-                         bool* ok);
+  VariableProxy* NewUnresolved(Handle<String> name, VariableMode mode);
+  void Declare(Declaration* declaration, bool resolve, bool* ok);

   bool TargetStackContainsLabel(Handle<String> label);
   BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok);
=======================================
--- /branches/bleeding_edge/src/prettyprinter.cc        Mon Feb 20 06:02:59 2012
+++ /branches/bleeding_edge/src/prettyprinter.cc        Tue Feb 28 02:12:39 2012
@@ -61,12 +61,17 @@
 void PrettyPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
   Print("var ");
   PrintLiteral(node->proxy()->name(), false);
-  if (node->fun() != NULL) {
-    Print(" = ");
-    PrintFunctionLiteral(node->fun());
-  }
   Print(";");
 }
+
+
+void PrettyPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
+  Print("function ");
+  PrintLiteral(node->proxy()->name(), false);
+  Print(" = ");
+  PrintFunctionLiteral(node->fun());
+  Print(";");
+}


 void PrettyPrinter::VisitModuleDeclaration(ModuleDeclaration* node) {
@@ -744,19 +749,18 @@


 void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
-  if (node->fun() == NULL) {
-    // var or const declarations
-    PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
-                                 node->proxy()->var(),
-                                 node->proxy()->name());
-  } else {
-    // function declarations
-    PrintIndented("FUNCTION ");
-    PrintLiteral(node->proxy()->name(), true);
-    Print(" = function ");
-    PrintLiteral(node->fun()->name(), false);
-    Print("\n");
-  }
+  PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
+                               node->proxy()->var(),
+                               node->proxy()->name());
+}
+
+
+void AstPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
+  PrintIndented("FUNCTION ");
+  PrintLiteral(node->proxy()->name(), true);
+  Print(" = function ");
+  PrintLiteral(node->fun()->name(), false);
+  Print("\n");
 }


=======================================
--- /branches/bleeding_edge/src/rewriter.cc     Thu Feb  9 05:40:41 2012
+++ /branches/bleeding_edge/src/rewriter.cc     Tue Feb 28 02:12:39 2012
@@ -210,6 +210,7 @@

 // Do nothing:
 void Processor::VisitVariableDeclaration(VariableDeclaration* node) {}
+void Processor::VisitFunctionDeclaration(FunctionDeclaration* node) {}
 void Processor::VisitModuleDeclaration(ModuleDeclaration* node) {}
 void Processor::VisitModuleLiteral(ModuleLiteral* node) {}
 void Processor::VisitModuleVariable(ModuleVariable* node) {}

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

Reply via email to