Merge V8 at 3.9.24.13

Bug: 5688872
Change-Id: Id0aa8d23375030494d3189c31774059c0f5398fc
diff --git a/src/ast.h b/src/ast.h
index b56205f..b827302 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -28,14 +28,21 @@
 #ifndef V8_AST_H_
 #define V8_AST_H_
 
-#include "allocation.h"
-#include "execution.h"
+#include "v8.h"
+
+#include "assembler.h"
 #include "factory.h"
+#include "isolate.h"
 #include "jsregexp.h"
+#include "list-inl.h"
 #include "runtime.h"
 #include "small-pointer-list.h"
+#include "smart-array-pointer.h"
 #include "token.h"
+#include "utils.h"
 #include "variables.h"
+#include "interface.h"
+#include "zone-inl.h"
 
 namespace v8 {
 namespace internal {
@@ -53,6 +60,19 @@
 // Nodes of the abstract syntax tree. Only concrete classes are
 // enumerated here.
 
+#define DECLARATION_NODE_LIST(V)                \
+  V(VariableDeclaration)                        \
+  V(FunctionDeclaration)                        \
+  V(ModuleDeclaration)                          \
+  V(ImportDeclaration)                          \
+  V(ExportDeclaration)                          \
+
+#define MODULE_NODE_LIST(V)                     \
+  V(ModuleLiteral)                              \
+  V(ModuleVariable)                             \
+  V(ModulePath)                                 \
+  V(ModuleUrl)
+
 #define STATEMENT_NODE_LIST(V)                  \
   V(Block)                                      \
   V(ExpressionStatement)                        \
@@ -90,21 +110,41 @@
   V(CountOperation)                             \
   V(BinaryOperation)                            \
   V(CompareOperation)                           \
-  V(CompareToNull)                              \
   V(ThisFunction)
 
 #define AST_NODE_LIST(V)                        \
-  V(Declaration)                                \
+  DECLARATION_NODE_LIST(V)                      \
+  MODULE_NODE_LIST(V)                           \
   STATEMENT_NODE_LIST(V)                        \
   EXPRESSION_NODE_LIST(V)
 
 // Forward declarations
-class BitVector;
-class DefinitionInfo;
+class AstConstructionVisitor;
+template<class> class AstNodeFactory;
+class AstVisitor;
+class Declaration;
+class Module;
+class BreakableStatement;
+class Expression;
+class IterationStatement;
 class MaterializedLiteral;
+class Statement;
 class TargetCollector;
 class TypeFeedbackOracle;
 
+class RegExpAlternative;
+class RegExpAssertion;
+class RegExpAtom;
+class RegExpBackReference;
+class RegExpCapture;
+class RegExpCharacterClass;
+class RegExpCompiler;
+class RegExpDisjunction;
+class RegExpEmpty;
+class RegExpLookahead;
+class RegExpQuantifier;
+class RegExpText;
+
 #define DEF_FORWARD_DECLARATION(type) class type;
 AST_NODE_LIST(DEF_FORWARD_DECLARATION)
 #undef DEF_FORWARD_DECLARATION
@@ -118,8 +158,31 @@
 
 #define DECLARE_NODE_TYPE(type)                                         \
   virtual void Accept(AstVisitor* v);                                   \
-  virtual AstNode::Type node_type() const { return AstNode::k##type; }  \
-  virtual type* As##type() { return this; }
+  virtual AstNode::Type node_type() const { return AstNode::k##type; }
+
+
+enum AstPropertiesFlag {
+  kDontInline,
+  kDontOptimize,
+  kDontSelfOptimize,
+  kDontSoftInline
+};
+
+
+class AstProperties BASE_EMBEDDED {
+ public:
+  class Flags : public EnumSet<AstPropertiesFlag, int> {};
+
+  AstProperties() : node_count_(0) { }
+
+  Flags* flags() { return &flags_; }
+  int node_count() { return node_count_; }
+  void add_node_count(int count) { node_count_ += count; }
+
+ private:
+  Flags flags_;
+  int node_count_;
+};
 
 
 class AstNode: public ZoneObject {
@@ -138,14 +201,11 @@
   // that emit code (function declarations).
   static const int kDeclarationsId = 3;
 
-  // Override ZoneObject's new to count allocated AST nodes.
   void* operator new(size_t size, Zone* zone) {
-    Isolate* isolate = zone->isolate();
-    isolate->set_ast_node_count(isolate->ast_node_count() + 1);
     return zone->New(static_cast<int>(size));
   }
 
-  AstNode() {}
+  AstNode() { }
 
   virtual ~AstNode() { }
 
@@ -154,10 +214,12 @@
 
   // Type testing & conversion functions overridden by concrete subclasses.
 #define DECLARE_NODE_FUNCTIONS(type)                  \
-  virtual type* As##type() { return NULL; }
+  bool Is##type() { return node_type() == AstNode::k##type; }          \
+  type* As##type() { return Is##type() ? reinterpret_cast<type*>(this) : NULL; }
   AST_NODE_LIST(DECLARE_NODE_FUNCTIONS)
 #undef DECLARE_NODE_FUNCTIONS
 
+  virtual Declaration* AsDeclaration() { return NULL; }
   virtual Statement* AsStatement() { return NULL; }
   virtual Expression* AsExpression() { return NULL; }
   virtual TargetCollector* AsTargetCollector() { return NULL; }
@@ -165,19 +227,13 @@
   virtual IterationStatement* AsIterationStatement() { return NULL; }
   virtual MaterializedLiteral* AsMaterializedLiteral() { return NULL; }
 
-  // True if the node is simple enough for us to inline calls containing it.
-  virtual bool IsInlineable() const = 0;
-
-  static int Count() { return Isolate::Current()->ast_node_count(); }
-  static void ResetIds() { Isolate::Current()->set_ast_node_id(0); }
-
  protected:
-  static unsigned GetNextId(Isolate* isolate) {
+  static int GetNextId(Isolate* isolate) {
     return ReserveIdRange(isolate, 1);
   }
 
-  static unsigned ReserveIdRange(Isolate* isolate, int n) {
-    unsigned tmp = isolate->ast_node_id();
+  static int ReserveIdRange(Isolate* isolate, int n) {
+    int tmp = isolate->ast_node_id();
     isolate->set_ast_node_id(tmp + n);
     return tmp;
   }
@@ -197,9 +253,6 @@
 
   virtual Statement* AsStatement()  { return this; }
 
-  virtual Assignment* StatementAsSimpleAssignment() { return NULL; }
-  virtual CountOperation* StatementAsCountOperation() { return NULL; }
-
   bool IsEmpty() { return AsEmptyStatement() != NULL; }
 
   void set_statement_pos(int statement_pos) { statement_pos_ = statement_pos; }
@@ -254,10 +307,6 @@
     kTest
   };
 
-  explicit Expression(Isolate* isolate)
-      : id_(GetNextId(isolate)),
-        test_id_(GetNextId(isolate)) {}
-
   virtual int position() const {
     UNREACHABLE();
     return 0;
@@ -265,7 +314,6 @@
 
   virtual Expression* AsExpression()  { return this; }
 
-  virtual bool IsTrivial() { return false; }
   virtual bool IsValidLeftHandSide() { return false; }
 
   // Helpers for ToBoolean conversion.
@@ -277,27 +325,24 @@
   // names because [] for string objects is handled only by keyed ICs.
   virtual bool IsPropertyName() { return false; }
 
-  // Mark the expression as being compiled as an expression
-  // statement. This is used to transform postfix increments to
-  // (faster) prefix increments.
-  virtual void MarkAsStatement() { /* do nothing */ }
-
   // True iff the result can be safely overwritten (to avoid allocation).
   // False for operations that can return one of their operands.
   virtual bool ResultOverwriteAllowed() { return false; }
 
   // True iff the expression is a literal represented as a smi.
-  virtual bool IsSmiLiteral() { return false; }
+  bool IsSmiLiteral();
+
+  // True iff the expression is a string literal.
+  bool IsStringLiteral();
+
+  // True iff the expression is the null literal.
+  bool IsNullLiteral();
 
   // Type feedback information for assignments and properties.
   virtual bool IsMonomorphic() {
     UNREACHABLE();
     return false;
   }
-  virtual bool IsArrayLength() {
-    UNREACHABLE();
-    return false;
-  }
   virtual SmallMapList* GetReceiverTypes() {
     UNREACHABLE();
     return NULL;
@@ -312,9 +357,14 @@
   unsigned id() const { return id_; }
   unsigned test_id() const { return test_id_; }
 
+ protected:
+  explicit Expression(Isolate* isolate)
+      : id_(GetNextId(isolate)),
+        test_id_(GetNextId(isolate)) {}
+
  private:
-  unsigned id_;
-  unsigned test_id_;
+  int id_;
+  int test_id_;
 };
 
 
@@ -343,7 +393,14 @@
   int ExitId() const { return exit_id_; }
 
  protected:
-  BreakableStatement(Isolate* isolate, ZoneStringList* labels, Type type);
+  BreakableStatement(Isolate* isolate, ZoneStringList* labels, Type type)
+      : labels_(labels),
+        type_(type),
+        entry_id_(GetNextId(isolate)),
+        exit_id_(GetNextId(isolate)) {
+    ASSERT(labels == NULL || labels->length() > 0);
+  }
+
 
  private:
   ZoneStringList* labels_;
@@ -356,25 +413,8 @@
 
 class Block: public BreakableStatement {
  public:
-  inline Block(Isolate* isolate,
-               ZoneStringList* labels,
-               int capacity,
-               bool is_initializer_block);
-
   DECLARE_NODE_TYPE(Block)
 
-  virtual Assignment* StatementAsSimpleAssignment() {
-    if (statements_.length() != 1) return NULL;
-    return statements_[0]->StatementAsSimpleAssignment();
-  }
-
-  virtual CountOperation* StatementAsCountOperation() {
-    if (statements_.length() != 1) return NULL;
-    return statements_[0]->StatementAsCountOperation();
-  }
-
-  virtual bool IsInlineable() const;
-
   void AddStatement(Statement* statement) { statements_.Add(statement); }
 
   ZoneList<Statement*>* statements() { return &statements_; }
@@ -383,6 +423,19 @@
   Scope* block_scope() const { return block_scope_; }
   void set_block_scope(Scope* block_scope) { block_scope_ = block_scope; }
 
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  Block(Isolate* isolate,
+        ZoneStringList* labels,
+        int capacity,
+        bool is_initializer_block)
+      : BreakableStatement(isolate, labels, TARGET_FOR_NAMED_ONLY),
+        statements_(capacity),
+        is_initializer_block_(is_initializer_block),
+        block_scope_(NULL) {
+  }
+
  private:
   ZoneList<Statement*> statements_;
   bool is_initializer_block_;
@@ -392,39 +445,236 @@
 
 class Declaration: public AstNode {
  public:
+  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; }
+
+ protected:
   Declaration(VariableProxy* proxy,
-              Variable::Mode mode,
-              FunctionLiteral* fun,
+              VariableMode mode,
               Scope* scope)
       : proxy_(proxy),
         mode_(mode),
-        fun_(fun),
         scope_(scope) {
-    ASSERT(mode == Variable::VAR ||
-           mode == Variable::CONST ||
-           mode == Variable::LET);
-    // At the moment there are no "const functions"'s in JavaScript...
-    ASSERT(fun == NULL || mode == Variable::VAR || mode == Variable::LET);
+    ASSERT(mode == VAR ||
+           mode == CONST ||
+           mode == CONST_HARMONY ||
+           mode == LET);
   }
 
-  DECLARE_NODE_TYPE(Declaration)
-
-  VariableProxy* proxy() const { return proxy_; }
-  Variable::Mode mode() const { return mode_; }
-  FunctionLiteral* fun() const { return fun_; }  // may be NULL
-  virtual bool IsInlineable() const;
-  Scope* scope() const { return scope_; }
-
  private:
   VariableProxy* proxy_;
-  Variable::Mode mode_;
-  FunctionLiteral* fun_;
+  VariableMode mode_;
 
   // Nested scope from which the declaration originated.
   Scope* scope_;
 };
 
 
+class VariableDeclaration: public Declaration {
+ public:
+  DECLARE_NODE_TYPE(VariableDeclaration)
+
+  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;
+
+  FunctionDeclaration(VariableProxy* proxy,
+                      VariableMode mode,
+                      FunctionLiteral* fun,
+                      Scope* scope)
+      : Declaration(proxy, mode, scope),
+        fun_(fun) {
+    // At the moment there are no "const functions" in JavaScript...
+    ASSERT(mode == VAR || mode == LET);
+    ASSERT(fun != NULL);
+  }
+
+ private:
+  FunctionLiteral* fun_;
+};
+
+
+class ModuleDeclaration: public Declaration {
+ public:
+  DECLARE_NODE_TYPE(ModuleDeclaration)
+
+  Module* module() const { return module_; }
+  virtual InitializationFlag initialization() const {
+    return kCreatedInitialized;
+  }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  ModuleDeclaration(VariableProxy* proxy,
+                    Module* module,
+                    Scope* scope)
+      : Declaration(proxy, LET, scope),
+        module_(module) {
+  }
+
+ private:
+  Module* module_;
+};
+
+
+class ImportDeclaration: public Declaration {
+ public:
+  DECLARE_NODE_TYPE(ImportDeclaration)
+
+  Module* module() const { return module_; }
+  virtual InitializationFlag initialization() const {
+    return kCreatedInitialized;
+  }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  ImportDeclaration(VariableProxy* proxy,
+                    Module* module,
+                    Scope* scope)
+      : Declaration(proxy, LET, scope),
+        module_(module) {
+  }
+
+ private:
+  Module* module_;
+};
+
+
+class ExportDeclaration: public Declaration {
+ public:
+  DECLARE_NODE_TYPE(ExportDeclaration)
+
+  virtual InitializationFlag initialization() const {
+    return kCreatedInitialized;
+  }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  ExportDeclaration(VariableProxy* proxy,
+                    Scope* scope)
+      : Declaration(proxy, LET, scope) {
+  }
+};
+
+
+class Module: public AstNode {
+ public:
+  Interface* interface() const { return interface_; }
+
+ protected:
+  Module() : interface_(Interface::NewModule()) {}
+  explicit Module(Interface* interface) : interface_(interface) {}
+
+ private:
+  Interface* interface_;
+};
+
+
+class ModuleLiteral: public Module {
+ public:
+  DECLARE_NODE_TYPE(ModuleLiteral)
+
+  Block* body() const { return body_; }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  ModuleLiteral(Block* body, Interface* interface)
+      : Module(interface),
+        body_(body) {
+  }
+
+ private:
+  Block* body_;
+};
+
+
+class ModuleVariable: public Module {
+ public:
+  DECLARE_NODE_TYPE(ModuleVariable)
+
+  VariableProxy* proxy() const { return proxy_; }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  inline explicit ModuleVariable(VariableProxy* proxy);
+
+ private:
+  VariableProxy* proxy_;
+};
+
+
+class ModulePath: public Module {
+ public:
+  DECLARE_NODE_TYPE(ModulePath)
+
+  Module* module() const { return module_; }
+  Handle<String> name() const { return name_; }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  ModulePath(Module* module, Handle<String> name)
+      : module_(module),
+        name_(name) {
+  }
+
+ private:
+  Module* module_;
+  Handle<String> name_;
+};
+
+
+class ModuleUrl: public Module {
+ public:
+  DECLARE_NODE_TYPE(ModuleUrl)
+
+  Handle<String> url() const { return url_; }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  explicit ModuleUrl(Handle<String> url) : url_(url) {
+  }
+
+ private:
+  Handle<String> url_;
+};
+
+
 class IterationStatement: public BreakableStatement {
  public:
   // Type testing & conversion.
@@ -441,7 +691,11 @@
   Label* continue_target()  { return &continue_target_; }
 
  protected:
-  inline IterationStatement(Isolate* isolate, ZoneStringList* labels);
+  IterationStatement(Isolate* isolate, ZoneStringList* labels)
+      : BreakableStatement(isolate, labels, TARGET_FOR_ANONYMOUS),
+        body_(NULL),
+        osr_entry_id_(GetNextId(isolate)) {
+  }
 
   void Initialize(Statement* body) {
     body_ = body;
@@ -456,8 +710,6 @@
 
 class DoWhileStatement: public IterationStatement {
  public:
-  inline DoWhileStatement(Isolate* isolate, ZoneStringList* labels);
-
   DECLARE_NODE_TYPE(DoWhileStatement)
 
   void Initialize(Expression* cond, Statement* body) {
@@ -477,7 +729,16 @@
   virtual int StackCheckId() const { return back_edge_id_; }
   int BackEdgeId() const { return back_edge_id_; }
 
-  virtual bool IsInlineable() const;
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  DoWhileStatement(Isolate* isolate, ZoneStringList* labels)
+      : IterationStatement(isolate, labels),
+        cond_(NULL),
+        condition_position_(-1),
+        continue_id_(GetNextId(isolate)),
+        back_edge_id_(GetNextId(isolate)) {
+  }
 
  private:
   Expression* cond_;
@@ -489,8 +750,6 @@
 
 class WhileStatement: public IterationStatement {
  public:
-  inline WhileStatement(Isolate* isolate, ZoneStringList* labels);
-
   DECLARE_NODE_TYPE(WhileStatement)
 
   void Initialize(Expression* cond, Statement* body) {
@@ -505,13 +764,22 @@
   void set_may_have_function_literal(bool value) {
     may_have_function_literal_ = value;
   }
-  virtual bool IsInlineable() const;
 
   // Bailout support.
   virtual int ContinueId() const { return EntryId(); }
   virtual int StackCheckId() const { return body_id_; }
   int BodyId() const { return body_id_; }
 
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  WhileStatement(Isolate* isolate, ZoneStringList* labels)
+      : IterationStatement(isolate, labels),
+        cond_(NULL),
+        may_have_function_literal_(true),
+        body_id_(GetNextId(isolate)) {
+  }
+
  private:
   Expression* cond_;
   // True if there is a function literal subexpression in the condition.
@@ -522,8 +790,6 @@
 
 class ForStatement: public IterationStatement {
  public:
-  inline ForStatement(Isolate* isolate, ZoneStringList* labels);
-
   DECLARE_NODE_TYPE(ForStatement)
 
   void Initialize(Statement* init,
@@ -555,7 +821,20 @@
   bool is_fast_smi_loop() { return loop_variable_ != NULL; }
   Variable* loop_variable() { return loop_variable_; }
   void set_loop_variable(Variable* var) { loop_variable_ = var; }
-  virtual bool IsInlineable() const;
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  ForStatement(Isolate* isolate, ZoneStringList* labels)
+      : IterationStatement(isolate, labels),
+        init_(NULL),
+        cond_(NULL),
+        next_(NULL),
+        may_have_function_literal_(true),
+        loop_variable_(NULL),
+        continue_id_(GetNextId(isolate)),
+        body_id_(GetNextId(isolate)) {
+  }
 
  private:
   Statement* init_;
@@ -571,8 +850,6 @@
 
 class ForInStatement: public IterationStatement {
  public:
-  inline ForInStatement(Isolate* isolate, ZoneStringList* labels);
-
   DECLARE_NODE_TYPE(ForInStatement)
 
   void Initialize(Expression* each, Expression* enumerable, Statement* body) {
@@ -583,35 +860,44 @@
 
   Expression* each() const { return each_; }
   Expression* enumerable() const { return enumerable_; }
-  virtual bool IsInlineable() const;
 
-  // Bailout support.
-  int AssignmentId() const { return assignment_id_; }
   virtual int ContinueId() const { return EntryId(); }
-  virtual int StackCheckId() const { return EntryId(); }
+  virtual int StackCheckId() const { return body_id_; }
+  int BodyId() const { return body_id_; }
+  int PrepareId() const { return prepare_id_; }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  ForInStatement(Isolate* isolate, ZoneStringList* labels)
+      : IterationStatement(isolate, labels),
+        each_(NULL),
+        enumerable_(NULL),
+        body_id_(GetNextId(isolate)),
+        prepare_id_(GetNextId(isolate)) {
+  }
 
  private:
   Expression* each_;
   Expression* enumerable_;
-  int assignment_id_;
+  int body_id_;
+  int prepare_id_;
 };
 
 
 class ExpressionStatement: public Statement {
  public:
-  explicit ExpressionStatement(Expression* expression)
-      : expression_(expression) { }
-
   DECLARE_NODE_TYPE(ExpressionStatement)
 
-  virtual bool IsInlineable() const;
-
-  virtual Assignment* StatementAsSimpleAssignment();
-  virtual CountOperation* StatementAsCountOperation();
-
   void set_expression(Expression* e) { expression_ = e; }
   Expression* expression() const { return expression_; }
 
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  explicit ExpressionStatement(Expression* expression)
+      : expression_(expression) { }
+
  private:
   Expression* expression_;
 };
@@ -619,13 +905,15 @@
 
 class ContinueStatement: public Statement {
  public:
-  explicit ContinueStatement(IterationStatement* target)
-      : target_(target) { }
-
   DECLARE_NODE_TYPE(ContinueStatement)
 
   IterationStatement* target() const { return target_; }
-  virtual bool IsInlineable() const;
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  explicit ContinueStatement(IterationStatement* target)
+      : target_(target) { }
 
  private:
   IterationStatement* target_;
@@ -634,13 +922,15 @@
 
 class BreakStatement: public Statement {
  public:
-  explicit BreakStatement(BreakableStatement* target)
-      : target_(target) { }
-
   DECLARE_NODE_TYPE(BreakStatement)
 
   BreakableStatement* target() const { return target_; }
-  virtual bool IsInlineable() const;
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  explicit BreakStatement(BreakableStatement* target)
+      : target_(target) { }
 
  private:
   BreakableStatement* target_;
@@ -649,13 +939,15 @@
 
 class ReturnStatement: public Statement {
  public:
-  explicit ReturnStatement(Expression* expression)
-      : expression_(expression) { }
-
   DECLARE_NODE_TYPE(ReturnStatement)
 
   Expression* expression() const { return expression_; }
-  virtual bool IsInlineable() const;
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  explicit ReturnStatement(Expression* expression)
+      : expression_(expression) { }
 
  private:
   Expression* expression_;
@@ -664,15 +956,17 @@
 
 class WithStatement: public Statement {
  public:
-  WithStatement(Expression* expression, Statement* statement)
-      : expression_(expression), statement_(statement) { }
-
   DECLARE_NODE_TYPE(WithStatement)
 
   Expression* expression() const { return expression_; }
   Statement* statement() const { return statement_; }
 
-  virtual bool IsInlineable() const;
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  WithStatement(Expression* expression, Statement* statement)
+      : expression_(expression),
+        statement_(statement) { }
 
  private:
   Expression* expression_;
@@ -704,6 +998,8 @@
   // Type feedback information.
   void RecordTypeFeedback(TypeFeedbackOracle* oracle);
   bool IsSmiCompare() { return compare_type_ == SMI_ONLY; }
+  bool IsSymbolCompare() { return compare_type_ == SYMBOL_ONLY; }
+  bool IsStringCompare() { return compare_type_ == STRING_ONLY; }
   bool IsObjectCompare() { return compare_type_ == OBJECT_ONLY; }
 
  private:
@@ -711,7 +1007,13 @@
   Label body_target_;
   ZoneList<Statement*>* statements_;
   int position_;
-  enum CompareTypeFeedback { NONE, SMI_ONLY, OBJECT_ONLY };
+  enum CompareTypeFeedback {
+    NONE,
+    SMI_ONLY,
+    SYMBOL_ONLY,
+    STRING_ONLY,
+    OBJECT_ONLY
+  };
   CompareTypeFeedback compare_type_;
   int compare_id_;
   int entry_id_;
@@ -720,8 +1022,6 @@
 
 class SwitchStatement: public BreakableStatement {
  public:
-  inline SwitchStatement(Isolate* isolate, ZoneStringList* labels);
-
   DECLARE_NODE_TYPE(SwitchStatement)
 
   void Initialize(Expression* tag, ZoneList<CaseClause*>* cases) {
@@ -731,7 +1031,14 @@
 
   Expression* tag() const { return tag_; }
   ZoneList<CaseClause*>* cases() const { return cases_; }
-  virtual bool IsInlineable() const;
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  SwitchStatement(Isolate* isolate, ZoneStringList* labels)
+      : BreakableStatement(isolate, labels, TARGET_FOR_ANONYMOUS),
+        tag_(NULL),
+        cases_(NULL) { }
 
  private:
   Expression* tag_;
@@ -746,22 +1053,8 @@
 // given if-statement has a then- or an else-part containing code.
 class IfStatement: public Statement {
  public:
-  IfStatement(Isolate* isolate,
-              Expression* condition,
-              Statement* then_statement,
-              Statement* else_statement)
-      : condition_(condition),
-        then_statement_(then_statement),
-        else_statement_(else_statement),
-        if_id_(GetNextId(isolate)),
-        then_id_(GetNextId(isolate)),
-        else_id_(GetNextId(isolate)) {
-  }
-
   DECLARE_NODE_TYPE(IfStatement)
 
-  virtual bool IsInlineable() const;
-
   bool HasThenStatement() const { return !then_statement()->IsEmpty(); }
   bool HasElseStatement() const { return !else_statement()->IsEmpty(); }
 
@@ -773,6 +1066,21 @@
   int ThenId() const { return then_id_; }
   int ElseId() const { return else_id_; }
 
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  IfStatement(Isolate* isolate,
+              Expression* condition,
+              Statement* then_statement,
+              Statement* else_statement)
+      : condition_(condition),
+        then_statement_(then_statement),
+        else_statement_(else_statement),
+        if_id_(GetNextId(isolate)),
+        then_id_(GetNextId(isolate)),
+        else_id_(GetNextId(isolate)) {
+  }
+
  private:
   Expression* condition_;
   Statement* then_statement_;
@@ -787,7 +1095,7 @@
 // stack in the compiler; this should probably be reworked.
 class TargetCollector: public AstNode {
  public:
-  TargetCollector(): targets_(0) { }
+  TargetCollector() : targets_(0) { }
 
   // Adds a jump target to the collector. The collector stores a pointer not
   // a copy of the target to make binding work, so make sure not to pass in
@@ -799,7 +1107,6 @@
   virtual TargetCollector* AsTargetCollector() { return this; }
 
   ZoneList<Label*>* targets() { return &targets_; }
-  virtual bool IsInlineable() const;
 
  private:
   ZoneList<Label*> targets_;
@@ -808,18 +1115,24 @@
 
 class TryStatement: public Statement {
  public:
-  explicit TryStatement(Block* try_block)
-      : try_block_(try_block), escaping_targets_(NULL) { }
-
   void set_escaping_targets(ZoneList<Label*>* targets) {
     escaping_targets_ = targets;
   }
 
+  int index() const { return index_; }
   Block* try_block() const { return try_block_; }
   ZoneList<Label*>* escaping_targets() const { return escaping_targets_; }
-  virtual bool IsInlineable() const;
+
+ protected:
+  TryStatement(int index, Block* try_block)
+      : index_(index),
+        try_block_(try_block),
+        escaping_targets_(NULL) { }
 
  private:
+  // Unique (per-function) index of this handler.  This is not an AST ID.
+  int index_;
+
   Block* try_block_;
   ZoneList<Label*>* escaping_targets_;
 };
@@ -827,22 +1140,25 @@
 
 class TryCatchStatement: public TryStatement {
  public:
-  TryCatchStatement(Block* try_block,
-                    Scope* scope,
-                    Variable* variable,
-                    Block* catch_block)
-      : TryStatement(try_block),
-        scope_(scope),
-        variable_(variable),
-        catch_block_(catch_block) {
-  }
-
   DECLARE_NODE_TYPE(TryCatchStatement)
 
   Scope* scope() { return scope_; }
   Variable* variable() { return variable_; }
   Block* catch_block() const { return catch_block_; }
-  virtual bool IsInlineable() const;
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  TryCatchStatement(int index,
+                    Block* try_block,
+                    Scope* scope,
+                    Variable* variable,
+                    Block* catch_block)
+      : TryStatement(index, try_block),
+        scope_(scope),
+        variable_(variable),
+        catch_block_(catch_block) {
+  }
 
  private:
   Scope* scope_;
@@ -853,14 +1169,16 @@
 
 class TryFinallyStatement: public TryStatement {
  public:
-  TryFinallyStatement(Block* try_block, Block* finally_block)
-      : TryStatement(try_block),
-        finally_block_(finally_block) { }
-
   DECLARE_NODE_TYPE(TryFinallyStatement)
 
   Block* finally_block() const { return finally_block_; }
-  virtual bool IsInlineable() const;
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  TryFinallyStatement(int index, Block* try_block, Block* finally_block)
+      : TryStatement(index, try_block),
+        finally_block_(finally_block) { }
 
  private:
   Block* finally_block_;
@@ -870,7 +1188,11 @@
 class DebuggerStatement: public Statement {
  public:
   DECLARE_NODE_TYPE(DebuggerStatement)
-  virtual bool IsInlineable() const;
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  DebuggerStatement() {}
 };
 
 
@@ -878,25 +1200,17 @@
  public:
   DECLARE_NODE_TYPE(EmptyStatement)
 
-  virtual bool IsInlineable() const;
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  EmptyStatement() {}
 };
 
 
 class Literal: public Expression {
  public:
-  Literal(Isolate* isolate, Handle<Object> handle)
-      : Expression(isolate), handle_(handle) { }
-
   DECLARE_NODE_TYPE(Literal)
 
-  virtual bool IsTrivial() { return true; }
-  virtual bool IsSmiLiteral() { return handle_->IsSmi(); }
-
-  // Check if this literal is identical to the other literal.
-  bool IsIdenticalTo(const Literal* other) const {
-    return handle_.is_identical_to(other->handle_);
-  }
-
   virtual bool IsPropertyName() {
     if (handle_->IsSymbol()) {
       uint32_t ignored;
@@ -928,9 +1242,27 @@
   }
 
   Handle<Object> handle() const { return handle_; }
-  virtual bool IsInlineable() const;
+
+  // Support for using Literal as a HashMap key. NOTE: Currently, this works
+  // only for string and number literals!
+  uint32_t Hash() { return ToString()->Hash(); }
+
+  static bool Match(void* literal1, void* literal2) {
+    Handle<String> s1 = static_cast<Literal*>(literal1)->ToString();
+    Handle<String> s2 = static_cast<Literal*>(literal2)->ToString();
+    return s1->Equals(*s2);
+  }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  Literal(Isolate* isolate, Handle<Object> handle)
+      : Expression(isolate),
+        handle_(handle) { }
 
  private:
+  Handle<String> ToString();
+
   Handle<Object> handle_;
 };
 
@@ -938,15 +1270,6 @@
 // Base class for literals that needs space in the corresponding JSFunction.
 class MaterializedLiteral: public Expression {
  public:
-  MaterializedLiteral(Isolate* isolate,
-                      int literal_index,
-                      bool is_simple,
-                      int depth)
-      : Expression(isolate),
-        literal_index_(literal_index),
-        is_simple_(is_simple),
-        depth_(depth) {}
-
   virtual MaterializedLiteral* AsMaterializedLiteral() { return this; }
 
   int literal_index() { return literal_index_; }
@@ -956,7 +1279,16 @@
   bool is_simple() const { return is_simple_; }
 
   int depth() const { return depth_; }
-  virtual bool IsInlineable() const;
+
+ protected:
+  MaterializedLiteral(Isolate* isolate,
+                      int literal_index,
+                      bool is_simple,
+                      int depth)
+      : Expression(isolate),
+        literal_index_(literal_index),
+        is_simple_(is_simple),
+        depth_(depth) {}
 
  private:
   int literal_index_;
@@ -982,39 +1314,36 @@
       PROTOTYPE              // Property is __proto__.
     };
 
-    Property(Literal* key, Expression* value);
-    Property(bool is_getter, FunctionLiteral* value);
+    Property(Literal* key, Expression* value, Isolate* isolate);
 
     Literal* key() { return key_; }
     Expression* value() { return value_; }
     Kind kind() { return kind_; }
 
+    // Type feedback information.
+    void RecordTypeFeedback(TypeFeedbackOracle* oracle);
+    bool IsMonomorphic() { return !receiver_type_.is_null(); }
+    Handle<Map> GetReceiverType() { return receiver_type_; }
+
     bool IsCompileTimeValue();
 
     void set_emit_store(bool emit_store);
     bool emit_store();
 
+   protected:
+    template<class> friend class AstNodeFactory;
+
+    Property(bool is_getter, FunctionLiteral* value);
+    void set_key(Literal* key) { key_ = key; }
+
    private:
     Literal* key_;
     Expression* value_;
     Kind kind_;
     bool emit_store_;
+    Handle<Map> receiver_type_;
   };
 
-  ObjectLiteral(Isolate* isolate,
-                Handle<FixedArray> constant_properties,
-                ZoneList<Property*>* properties,
-                int literal_index,
-                bool is_simple,
-                bool fast_elements,
-                int depth,
-                bool has_function)
-      : MaterializedLiteral(isolate, literal_index, is_simple, depth),
-        constant_properties_(constant_properties),
-        properties_(properties),
-        fast_elements_(fast_elements),
-        has_function_(has_function) {}
-
   DECLARE_NODE_TYPE(ObjectLiteral)
 
   Handle<FixedArray> constant_properties() const {
@@ -1037,6 +1366,29 @@
     kHasFunction = 1 << 1
   };
 
+  struct Accessors: public ZoneObject {
+    Accessors() : getter(NULL), setter(NULL) { }
+    Expression* getter;
+    Expression* setter;
+  };
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  ObjectLiteral(Isolate* isolate,
+                Handle<FixedArray> constant_properties,
+                ZoneList<Property*>* properties,
+                int literal_index,
+                bool is_simple,
+                bool fast_elements,
+                int depth,
+                bool has_function)
+      : MaterializedLiteral(isolate, literal_index, is_simple, depth),
+        constant_properties_(constant_properties),
+        properties_(properties),
+        fast_elements_(fast_elements),
+        has_function_(has_function) {}
+
  private:
   Handle<FixedArray> constant_properties_;
   ZoneList<Property*>* properties_;
@@ -1048,6 +1400,14 @@
 // Node for capturing a regexp literal.
 class RegExpLiteral: public MaterializedLiteral {
  public:
+  DECLARE_NODE_TYPE(RegExpLiteral)
+
+  Handle<String> pattern() const { return pattern_; }
+  Handle<String> flags() const { return flags_; }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
   RegExpLiteral(Isolate* isolate,
                 Handle<String> pattern,
                 Handle<String> flags,
@@ -1056,11 +1416,6 @@
         pattern_(pattern),
         flags_(flags) {}
 
-  DECLARE_NODE_TYPE(RegExpLiteral)
-
-  Handle<String> pattern() const { return pattern_; }
-  Handle<String> flags() const { return flags_; }
-
  private:
   Handle<String> pattern_;
   Handle<String> flags_;
@@ -1070,6 +1425,17 @@
 // for minimizing the work when constructing it at runtime.
 class ArrayLiteral: public MaterializedLiteral {
  public:
+  DECLARE_NODE_TYPE(ArrayLiteral)
+
+  Handle<FixedArray> constant_elements() const { return constant_elements_; }
+  ZoneList<Expression*>* values() const { return values_; }
+
+  // Return an AST id for an element that is used in simulate instructions.
+  int GetIdForElement(int i) { return first_element_id_ + i; }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
   ArrayLiteral(Isolate* isolate,
                Handle<FixedArray> constant_elements,
                ZoneList<Expression*>* values,
@@ -1081,14 +1447,6 @@
         values_(values),
         first_element_id_(ReserveIdRange(isolate, values->length())) {}
 
-  DECLARE_NODE_TYPE(ArrayLiteral)
-
-  Handle<FixedArray> constant_elements() const { return constant_elements_; }
-  ZoneList<Expression*>* values() const { return values_; }
-
-  // Return an AST id for an element that is used in simulate instructions.
-  int GetIdForElement(int i) { return first_element_id_ + i; }
-
  private:
   Handle<FixedArray> constant_elements_;
   ZoneList<Expression*>* values_;
@@ -1098,77 +1456,63 @@
 
 class VariableProxy: public Expression {
  public:
-  VariableProxy(Isolate* isolate, Variable* var);
-
   DECLARE_NODE_TYPE(VariableProxy)
 
   virtual bool IsValidLeftHandSide() {
     return var_ == NULL ? true : var_->IsValidLeftHandSide();
   }
 
-  virtual bool IsTrivial() {
-    // Reading from a mutable variable is a side effect, but the
-    // variable for 'this' is immutable.
-    return is_this_ || is_trivial_;
-  }
-
-  virtual bool IsInlineable() const;
-
   bool IsVariable(Handle<String> n) {
     return !is_this() && name().is_identical_to(n);
   }
 
   bool IsArguments() { return var_ != NULL && var_->is_arguments(); }
 
+  bool IsLValue() {
+    return is_lvalue_;
+  }
+
   Handle<String> name() const { return name_; }
   Variable* var() const { return var_; }
   bool is_this() const { return is_this_; }
-  bool inside_with() const { return inside_with_; }
   int position() const { return position_; }
+  Interface* interface() const { return interface_; }
+
 
   void MarkAsTrivial() { is_trivial_ = true; }
+  void MarkAsLValue() { is_lvalue_ = true; }
 
   // Bind this proxy to the variable var.
   void BindTo(Variable* var);
 
  protected:
-  Handle<String> name_;
-  Variable* var_;  // resolved variable, or NULL
-  bool is_this_;
-  bool inside_with_;
-  bool is_trivial_;
-  int position_;
+  template<class> friend class AstNodeFactory;
+
+  VariableProxy(Isolate* isolate, Variable* var);
 
   VariableProxy(Isolate* isolate,
                 Handle<String> name,
                 bool is_this,
-                bool inside_with,
-                int position = RelocInfo::kNoPosition);
+                int position,
+                Interface* interface);
 
-  friend class Scope;
+  Handle<String> name_;
+  Variable* var_;  // resolved variable, or NULL
+  bool is_this_;
+  bool is_trivial_;
+  // True if this variable proxy is being used in an assignment
+  // or with a increment/decrement operator.
+  bool is_lvalue_;
+  int position_;
+  Interface* interface_;
 };
 
 
 class Property: public Expression {
  public:
-  Property(Isolate* isolate,
-           Expression* obj,
-           Expression* key,
-           int pos)
-      : Expression(isolate),
-        obj_(obj),
-        key_(key),
-        pos_(pos),
-        is_monomorphic_(false),
-        is_array_length_(false),
-        is_string_length_(false),
-        is_string_access_(false),
-        is_function_prototype_(false) { }
-
   DECLARE_NODE_TYPE(Property)
 
   virtual bool IsValidLeftHandSide() { return true; }
-  virtual bool IsInlineable() const;
 
   Expression* obj() const { return obj_; }
   Expression* key() const { return key_; }
@@ -1182,7 +1526,26 @@
   void RecordTypeFeedback(TypeFeedbackOracle* oracle);
   virtual bool IsMonomorphic() { return is_monomorphic_; }
   virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
-  virtual bool IsArrayLength() { return is_array_length_; }
+  bool IsArrayLength() { return is_array_length_; }
+  bool IsUninitialized() { return is_uninitialized_; }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  Property(Isolate* isolate,
+           Expression* obj,
+           Expression* key,
+           int pos)
+      : Expression(isolate),
+        obj_(obj),
+        key_(key),
+        pos_(pos),
+        is_monomorphic_(false),
+        is_uninitialized_(false),
+        is_array_length_(false),
+        is_string_length_(false),
+        is_string_access_(false),
+        is_function_prototype_(false) { }
 
  private:
   Expression* obj_;
@@ -1191,6 +1554,7 @@
 
   SmallMapList receiver_types_;
   bool is_monomorphic_ : 1;
+  bool is_uninitialized_ : 1;
   bool is_array_length_ : 1;
   bool is_string_length_ : 1;
   bool is_string_access_ : 1;
@@ -1200,23 +1564,8 @@
 
 class Call: public Expression {
  public:
-  Call(Isolate* isolate,
-       Expression* expression,
-       ZoneList<Expression*>* arguments,
-       int pos)
-      : Expression(isolate),
-        expression_(expression),
-        arguments_(arguments),
-        pos_(pos),
-        is_monomorphic_(false),
-        check_type_(RECEIVER_MAP_CHECK),
-        return_id_(GetNextId(isolate)) {
-  }
-
   DECLARE_NODE_TYPE(Call)
 
-  virtual bool IsInlineable() const;
-
   Expression* expression() const { return expression_; }
   ZoneList<Expression*>* arguments() const { return arguments_; }
   virtual int position() const { return pos_; }
@@ -1241,6 +1590,21 @@
   bool return_is_recorded_;
 #endif
 
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  Call(Isolate* isolate,
+       Expression* expression,
+       ZoneList<Expression*>* arguments,
+       int pos)
+      : Expression(isolate),
+        expression_(expression),
+        arguments_(arguments),
+        pos_(pos),
+        is_monomorphic_(false),
+        check_type_(RECEIVER_MAP_CHECK),
+        return_id_(GetNextId(isolate)) { }
+
  private:
   Expression* expression_;
   ZoneList<Expression*>* arguments_;
@@ -1259,6 +1623,22 @@
 
 class CallNew: public Expression {
  public:
+  DECLARE_NODE_TYPE(CallNew)
+
+  Expression* expression() const { return expression_; }
+  ZoneList<Expression*>* arguments() const { return arguments_; }
+  virtual int position() const { return pos_; }
+
+  void RecordTypeFeedback(TypeFeedbackOracle* oracle);
+  virtual bool IsMonomorphic() { return is_monomorphic_; }
+  Handle<JSFunction> target() { return target_; }
+
+  // Bailout support.
+  int ReturnId() const { return return_id_; }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
   CallNew(Isolate* isolate,
           Expression* expression,
           ZoneList<Expression*>* arguments,
@@ -1266,20 +1646,19 @@
       : Expression(isolate),
         expression_(expression),
         arguments_(arguments),
-        pos_(pos) { }
-
-  DECLARE_NODE_TYPE(CallNew)
-
-  virtual bool IsInlineable() const;
-
-  Expression* expression() const { return expression_; }
-  ZoneList<Expression*>* arguments() const { return arguments_; }
-  virtual int position() const { return pos_; }
+        pos_(pos),
+        is_monomorphic_(false),
+        return_id_(GetNextId(isolate)) { }
 
  private:
   Expression* expression_;
   ZoneList<Expression*>* arguments_;
   int pos_;
+
+  bool is_monomorphic_;
+  Handle<JSFunction> target_;
+
+  int return_id_;
 };
 
 
@@ -1289,6 +1668,16 @@
 // implemented in JavaScript (see "v8natives.js").
 class CallRuntime: public Expression {
  public:
+  DECLARE_NODE_TYPE(CallRuntime)
+
+  Handle<String> name() const { return name_; }
+  const Runtime::Function* function() const { return function_; }
+  ZoneList<Expression*>* arguments() const { return arguments_; }
+  bool is_jsruntime() const { return function_ == NULL; }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
   CallRuntime(Isolate* isolate,
               Handle<String> name,
               const Runtime::Function* function,
@@ -1298,15 +1687,6 @@
         function_(function),
         arguments_(arguments) { }
 
-  DECLARE_NODE_TYPE(CallRuntime)
-
-  virtual bool IsInlineable() const;
-
-  Handle<String> name() const { return name_; }
-  const Runtime::Function* function() const { return function_; }
-  ZoneList<Expression*>* arguments() const { return arguments_; }
-  bool is_jsruntime() const { return function_ == NULL; }
-
  private:
   Handle<String> name_;
   const Runtime::Function* function_;
@@ -1316,49 +1696,53 @@
 
 class UnaryOperation: public Expression {
  public:
-  UnaryOperation(Isolate* isolate,
-                 Token::Value op,
-                 Expression* expression,
-                 int pos)
-      : Expression(isolate), op_(op), expression_(expression), pos_(pos) {
-    ASSERT(Token::IsUnaryOp(op));
-  }
-
   DECLARE_NODE_TYPE(UnaryOperation)
 
-  virtual bool IsInlineable() const;
-
   virtual bool ResultOverwriteAllowed();
 
   Token::Value op() const { return op_; }
   Expression* expression() const { return expression_; }
   virtual int position() const { return pos_; }
 
+  int MaterializeTrueId() { return materialize_true_id_; }
+  int MaterializeFalseId() { return materialize_false_id_; }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  UnaryOperation(Isolate* isolate,
+                 Token::Value op,
+                 Expression* expression,
+                 int pos)
+      : Expression(isolate),
+        op_(op),
+        expression_(expression),
+        pos_(pos),
+        materialize_true_id_(AstNode::kNoNumber),
+        materialize_false_id_(AstNode::kNoNumber) {
+    ASSERT(Token::IsUnaryOp(op));
+    if (op == Token::NOT) {
+      materialize_true_id_ = GetNextId(isolate);
+      materialize_false_id_ = GetNextId(isolate);
+    }
+  }
+
  private:
   Token::Value op_;
   Expression* expression_;
   int pos_;
+
+  // For unary not (Token::NOT), the AST ids where true and false will
+  // actually be materialized, respectively.
+  int materialize_true_id_;
+  int materialize_false_id_;
 };
 
 
 class BinaryOperation: public Expression {
  public:
-  BinaryOperation(Isolate* isolate,
-                  Token::Value op,
-                  Expression* left,
-                  Expression* right,
-                  int pos)
-      : Expression(isolate), op_(op), left_(left), right_(right), pos_(pos) {
-    ASSERT(Token::IsBinaryOp(op));
-    right_id_ = (op == Token::AND || op == Token::OR)
-        ? static_cast<int>(GetNextId(isolate))
-        : AstNode::kNoNumber;
-  }
-
   DECLARE_NODE_TYPE(BinaryOperation)
 
-  virtual bool IsInlineable() const;
-
   virtual bool ResultOverwriteAllowed();
 
   Token::Value op() const { return op_; }
@@ -1369,6 +1753,21 @@
   // Bailout support.
   int RightId() const { return right_id_; }
 
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  BinaryOperation(Isolate* isolate,
+                  Token::Value op,
+                  Expression* left,
+                  Expression* right,
+                  int pos)
+      : Expression(isolate), op_(op), left_(left), right_(right), pos_(pos) {
+    ASSERT(Token::IsBinaryOp(op));
+    right_id_ = (op == Token::AND || op == Token::OR)
+        ? GetNextId(isolate)
+        : AstNode::kNoNumber;
+  }
+
  private:
   Token::Value op_;
   Expression* left_;
@@ -1382,19 +1781,6 @@
 
 class CountOperation: public Expression {
  public:
-  CountOperation(Isolate* isolate,
-                 Token::Value op,
-                 bool is_prefix,
-                 Expression* expr,
-                 int pos)
-      : Expression(isolate),
-        op_(op),
-        is_prefix_(is_prefix),
-        expression_(expr),
-        pos_(pos),
-        assignment_id_(GetNextId(isolate)),
-        count_id_(GetNextId(isolate)) {}
-
   DECLARE_NODE_TYPE(CountOperation)
 
   bool is_prefix() const { return is_prefix_; }
@@ -1410,8 +1796,6 @@
 
   virtual void MarkAsStatement() { is_prefix_ = true; }
 
-  virtual bool IsInlineable() const;
-
   void RecordTypeFeedback(TypeFeedbackOracle* oracle);
   virtual bool IsMonomorphic() { return is_monomorphic_; }
   virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
@@ -1420,6 +1804,22 @@
   int AssignmentId() const { return assignment_id_; }
   int CountId() const { return count_id_; }
 
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  CountOperation(Isolate* isolate,
+                 Token::Value op,
+                 bool is_prefix,
+                 Expression* expr,
+                 int pos)
+      : Expression(isolate),
+        op_(op),
+        is_prefix_(is_prefix),
+        expression_(expr),
+        pos_(pos),
+        assignment_id_(GetNextId(isolate)),
+        count_id_(GetNextId(isolate)) {}
+
  private:
   Token::Value op_;
   bool is_prefix_;
@@ -1434,6 +1834,26 @@
 
 class CompareOperation: public Expression {
  public:
+  DECLARE_NODE_TYPE(CompareOperation)
+
+  Token::Value op() const { return op_; }
+  Expression* left() const { return left_; }
+  Expression* right() const { return right_; }
+  virtual int position() const { return pos_; }
+
+  // Type feedback information.
+  void RecordTypeFeedback(TypeFeedbackOracle* oracle);
+  bool IsSmiCompare() { return compare_type_ == SMI_ONLY; }
+  bool IsObjectCompare() { return compare_type_ == OBJECT_ONLY; }
+
+  // Match special cases.
+  bool IsLiteralCompareTypeof(Expression** expr, Handle<String>* check);
+  bool IsLiteralCompareUndefined(Expression** expr);
+  bool IsLiteralCompareNull(Expression** expr);
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
   CompareOperation(Isolate* isolate,
                    Token::Value op,
                    Expression* left,
@@ -1448,24 +1868,6 @@
     ASSERT(Token::IsCompareOp(op));
   }
 
-  DECLARE_NODE_TYPE(CompareOperation)
-
-  Token::Value op() const { return op_; }
-  Expression* left() const { return left_; }
-  Expression* right() const { return right_; }
-  virtual int position() const { return pos_; }
-
-  virtual bool IsInlineable() const;
-
-  // Type feedback information.
-  void RecordTypeFeedback(TypeFeedbackOracle* oracle);
-  bool IsSmiCompare() { return compare_type_ == SMI_ONLY; }
-  bool IsObjectCompare() { return compare_type_ == OBJECT_ONLY; }
-
-  // Match special cases.
-  bool IsLiteralCompareTypeof(Expression** expr, Handle<String>* check);
-  bool IsLiteralCompareUndefined(Expression** expr);
-
  private:
   Token::Value op_;
   Expression* left_;
@@ -1477,27 +1879,23 @@
 };
 
 
-class CompareToNull: public Expression {
- public:
-  CompareToNull(Isolate* isolate, bool is_strict, Expression* expression)
-      : Expression(isolate), is_strict_(is_strict), expression_(expression) { }
-
-  DECLARE_NODE_TYPE(CompareToNull)
-
-  virtual bool IsInlineable() const;
-
-  bool is_strict() const { return is_strict_; }
-  Token::Value op() const { return is_strict_ ? Token::EQ_STRICT : Token::EQ; }
-  Expression* expression() const { return expression_; }
-
- private:
-  bool is_strict_;
-  Expression* expression_;
-};
-
-
 class Conditional: public Expression {
  public:
+  DECLARE_NODE_TYPE(Conditional)
+
+  Expression* condition() const { return condition_; }
+  Expression* then_expression() const { return then_expression_; }
+  Expression* else_expression() const { return else_expression_; }
+
+  int then_expression_position() const { return then_expression_position_; }
+  int else_expression_position() const { return else_expression_position_; }
+
+  int ThenId() const { return then_id_; }
+  int ElseId() const { return else_id_; }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
   Conditional(Isolate* isolate,
               Expression* condition,
               Expression* then_expression,
@@ -1511,22 +1909,7 @@
         then_expression_position_(then_expression_position),
         else_expression_position_(else_expression_position),
         then_id_(GetNextId(isolate)),
-        else_id_(GetNextId(isolate)) {
-  }
-
-  DECLARE_NODE_TYPE(Conditional)
-
-  virtual bool IsInlineable() const;
-
-  Expression* condition() const { return condition_; }
-  Expression* then_expression() const { return then_expression_; }
-  Expression* else_expression() const { return else_expression_; }
-
-  int then_expression_position() const { return then_expression_position_; }
-  int else_expression_position() const { return else_expression_position_; }
-
-  int ThenId() const { return then_id_; }
-  int ElseId() const { return else_id_; }
+        else_id_(GetNextId(isolate)) { }
 
  private:
   Expression* condition_;
@@ -1541,16 +1924,8 @@
 
 class Assignment: public Expression {
  public:
-  Assignment(Isolate* isolate,
-             Token::Value op,
-             Expression* target,
-             Expression* value,
-             int pos);
-
   DECLARE_NODE_TYPE(Assignment)
 
-  virtual bool IsInlineable() const;
-
   Assignment* AsSimpleAssignment() { return !is_compound() ? this : NULL; }
 
   Token::Value binary_op() const;
@@ -1582,6 +1957,25 @@
   int CompoundLoadId() const { return compound_load_id_; }
   int AssignmentId() const { return assignment_id_; }
 
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  Assignment(Isolate* isolate,
+             Token::Value op,
+             Expression* target,
+             Expression* value,
+             int pos);
+
+  template<class Visitor>
+  void Init(Isolate* isolate, AstNodeFactory<Visitor>* factory) {
+    ASSERT(Token::IsAssignmentOp(op_));
+    if (is_compound()) {
+      binary_operation_ =
+          factory->NewBinaryOperation(binary_op(), target_, value_, pos_ + 1);
+      compound_load_id_ = GetNextId(isolate);
+    }
+  }
+
  private:
   Token::Value op_;
   Expression* target_;
@@ -1601,14 +1995,16 @@
 
 class Throw: public Expression {
  public:
-  Throw(Isolate* isolate, Expression* exception, int pos)
-      : Expression(isolate), exception_(exception), pos_(pos) {}
-
   DECLARE_NODE_TYPE(Throw)
 
   Expression* exception() const { return exception_; }
   virtual int position() const { return pos_; }
-  virtual bool IsInlineable() const;
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  Throw(Isolate* isolate, Expression* exception, int pos)
+      : Expression(isolate), exception_(exception), pos_(pos) {}
 
  private:
   Expression* exception_;
@@ -1624,38 +2020,15 @@
     DECLARATION
   };
 
-  FunctionLiteral(Isolate* isolate,
-                  Handle<String> name,
-                  Scope* scope,
-                  ZoneList<Statement*>* body,
-                  int materialized_literal_count,
-                  int expected_property_count,
-                  bool has_only_simple_this_property_assignments,
-                  Handle<FixedArray> this_property_assignments,
-                  int num_parameters,
-                  int start_position,
-                  int end_position,
-                  Type type,
-                  bool has_duplicate_parameters)
-      : Expression(isolate),
-        name_(name),
-        scope_(scope),
-        body_(body),
-        materialized_literal_count_(materialized_literal_count),
-        expected_property_count_(expected_property_count),
-        has_only_simple_this_property_assignments_(
-            has_only_simple_this_property_assignments),
-        this_property_assignments_(this_property_assignments),
-        num_parameters_(num_parameters),
-        start_position_(start_position),
-        end_position_(end_position),
-        function_token_position_(RelocInfo::kNoPosition),
-        inferred_name_(HEAP->empty_string()),
-        is_expression_(type != DECLARATION),
-        is_anonymous_(type == ANONYMOUS_EXPRESSION),
-        pretenure_(false),
-        has_duplicate_parameters_(has_duplicate_parameters) {
-  }
+  enum ParameterFlag {
+    kNoDuplicateParameters = 0,
+    kHasDuplicateParameters = 1
+  };
+
+  enum IsFunctionFlag {
+    kGlobalOrEval,
+    kIsFunction
+  };
 
   DECLARE_NODE_TYPE(FunctionLiteral)
 
@@ -1664,21 +2037,24 @@
   ZoneList<Statement*>* body() const { return body_; }
   void set_function_token_position(int pos) { function_token_position_ = pos; }
   int function_token_position() const { return function_token_position_; }
-  int start_position() const { return start_position_; }
-  int end_position() const { return end_position_; }
-  bool is_expression() const { return is_expression_; }
-  bool is_anonymous() const { return is_anonymous_; }
-  bool strict_mode() const;
+  int start_position() const;
+  int end_position() const;
+  int SourceSize() const { return end_position() - start_position(); }
+  bool is_expression() const { return IsExpression::decode(bitfield_); }
+  bool is_anonymous() const { return IsAnonymous::decode(bitfield_); }
+  bool is_classic_mode() const { return language_mode() == CLASSIC_MODE; }
+  LanguageMode language_mode() const;
 
   int materialized_literal_count() { return materialized_literal_count_; }
   int expected_property_count() { return expected_property_count_; }
+  int handler_count() { return handler_count_; }
   bool has_only_simple_this_property_assignments() {
-      return has_only_simple_this_property_assignments_;
+    return HasOnlySimpleThisPropertyAssignments::decode(bitfield_);
   }
   Handle<FixedArray> this_property_assignments() {
       return this_property_assignments_;
   }
-  int num_parameters() { return num_parameters_; }
+  int parameter_count() { return parameter_count_; }
 
   bool AllowsLazyCompilation();
 
@@ -1692,45 +2068,98 @@
     inferred_name_ = inferred_name;
   }
 
-  bool pretenure() { return pretenure_; }
-  void set_pretenure(bool value) { pretenure_ = value; }
-  virtual bool IsInlineable() const;
+  bool pretenure() { return Pretenure::decode(bitfield_); }
+  void set_pretenure() { bitfield_ |= Pretenure::encode(true); }
 
-  bool has_duplicate_parameters() { return has_duplicate_parameters_; }
+  bool has_duplicate_parameters() {
+    return HasDuplicateParameters::decode(bitfield_);
+  }
+
+  bool is_function() { return IsFunction::decode(bitfield_) == kIsFunction; }
+
+  int ast_node_count() { return ast_properties_.node_count(); }
+  AstProperties::Flags* flags() { return ast_properties_.flags(); }
+  void set_ast_properties(AstProperties* ast_properties) {
+    ast_properties_ = *ast_properties;
+  }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  FunctionLiteral(Isolate* isolate,
+                  Handle<String> name,
+                  Scope* scope,
+                  ZoneList<Statement*>* body,
+                  int materialized_literal_count,
+                  int expected_property_count,
+                  int handler_count,
+                  bool has_only_simple_this_property_assignments,
+                  Handle<FixedArray> this_property_assignments,
+                  int parameter_count,
+                  Type type,
+                  ParameterFlag has_duplicate_parameters,
+                  IsFunctionFlag is_function)
+      : Expression(isolate),
+        name_(name),
+        scope_(scope),
+        body_(body),
+        this_property_assignments_(this_property_assignments),
+        inferred_name_(isolate->factory()->empty_string()),
+        materialized_literal_count_(materialized_literal_count),
+        expected_property_count_(expected_property_count),
+        handler_count_(handler_count),
+        parameter_count_(parameter_count),
+        function_token_position_(RelocInfo::kNoPosition) {
+    bitfield_ =
+        HasOnlySimpleThisPropertyAssignments::encode(
+            has_only_simple_this_property_assignments) |
+        IsExpression::encode(type != DECLARATION) |
+        IsAnonymous::encode(type == ANONYMOUS_EXPRESSION) |
+        Pretenure::encode(false) |
+        HasDuplicateParameters::encode(has_duplicate_parameters) |
+        IsFunction::encode(is_function);
+  }
 
  private:
   Handle<String> name_;
   Scope* scope_;
   ZoneList<Statement*>* body_;
+  Handle<FixedArray> this_property_assignments_;
+  Handle<String> inferred_name_;
+  AstProperties ast_properties_;
+
   int materialized_literal_count_;
   int expected_property_count_;
-  bool has_only_simple_this_property_assignments_;
-  Handle<FixedArray> this_property_assignments_;
-  int num_parameters_;
-  int start_position_;
-  int end_position_;
+  int handler_count_;
+  int parameter_count_;
   int function_token_position_;
-  Handle<String> inferred_name_;
-  bool is_expression_;
-  bool is_anonymous_;
-  bool pretenure_;
-  bool has_duplicate_parameters_;
+
+  unsigned bitfield_;
+  class HasOnlySimpleThisPropertyAssignments: public BitField<bool, 0, 1> {};
+  class IsExpression: public BitField<bool, 1, 1> {};
+  class IsAnonymous: public BitField<bool, 2, 1> {};
+  class Pretenure: public BitField<bool, 3, 1> {};
+  class HasDuplicateParameters: public BitField<ParameterFlag, 4, 1> {};
+  class IsFunction: public BitField<IsFunctionFlag, 5, 1> {};
 };
 
 
 class SharedFunctionInfoLiteral: public Expression {
  public:
-  SharedFunctionInfoLiteral(
-      Isolate* isolate,
-      Handle<SharedFunctionInfo> shared_function_info)
-      : Expression(isolate), shared_function_info_(shared_function_info) { }
-
   DECLARE_NODE_TYPE(SharedFunctionInfoLiteral)
 
   Handle<SharedFunctionInfo> shared_function_info() const {
     return shared_function_info_;
   }
-  virtual bool IsInlineable() const;
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  SharedFunctionInfoLiteral(
+      Isolate* isolate,
+      Handle<SharedFunctionInfo> shared_function_info)
+      : Expression(isolate),
+        shared_function_info_(shared_function_info) { }
 
  private:
   Handle<SharedFunctionInfo> shared_function_info_;
@@ -1739,11 +2168,16 @@
 
 class ThisFunction: public Expression {
  public:
-  explicit ThisFunction(Isolate* isolate) : Expression(isolate) {}
   DECLARE_NODE_TYPE(ThisFunction)
-  virtual bool IsInlineable() const;
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  explicit ThisFunction(Isolate* isolate): Expression(isolate) {}
 };
 
+#undef DECLARE_NODE_TYPE
+
 
 // ----------------------------------------------------------------------------
 // Regular expressions
@@ -2096,13 +2530,23 @@
   virtual bool IsEmpty();
   virtual int min_match() { return 0; }
   virtual int max_match() { return 0; }
-  static RegExpEmpty* GetInstance() { return &kInstance; }
- private:
-  static RegExpEmpty kInstance;
+  static RegExpEmpty* GetInstance() {
+    static RegExpEmpty* instance = ::new RegExpEmpty();
+    return instance;
+  }
 };
 
 
 // ----------------------------------------------------------------------------
+// Out-of-line inline constructors (to side-step cyclic dependencies).
+
+inline ModuleVariable::ModuleVariable(VariableProxy* proxy)
+    : Module(proxy->interface()),
+      proxy_(proxy) {
+}
+
+
+// ----------------------------------------------------------------------------
 // Basic visitor
 // - leaf node visitors are abstract.
 
@@ -2144,6 +2588,397 @@
 };
 
 
+// ----------------------------------------------------------------------------
+// Construction time visitor.
+
+class AstConstructionVisitor BASE_EMBEDDED {
+ public:
+  AstConstructionVisitor() { }
+
+  AstProperties* ast_properties() { return &properties_; }
+
+ private:
+  template<class> friend class AstNodeFactory;
+
+  // Node visitors.
+#define DEF_VISIT(type) \
+  void Visit##type(type* node);
+  AST_NODE_LIST(DEF_VISIT)
+#undef DEF_VISIT
+
+  void increase_node_count() { properties_.add_node_count(1); }
+  void add_flag(AstPropertiesFlag flag) { properties_.flags()->Add(flag); }
+
+  AstProperties properties_;
+};
+
+
+class AstNullVisitor BASE_EMBEDDED {
+ public:
+  // Node visitors.
+#define DEF_VISIT(type) \
+  void Visit##type(type* node) {}
+  AST_NODE_LIST(DEF_VISIT)
+#undef DEF_VISIT
+};
+
+
+
+// ----------------------------------------------------------------------------
+// AstNode factory
+
+template<class Visitor>
+class AstNodeFactory BASE_EMBEDDED {
+ public:
+  explicit AstNodeFactory(Isolate* isolate)
+      : isolate_(isolate),
+        zone_(isolate_->zone()) { }
+
+  Visitor* visitor() { return &visitor_; }
+
+#define VISIT_AND_RETURN(NodeType, node) \
+  visitor_.Visit##NodeType((node)); \
+  return node;
+
+  VariableDeclaration* NewVariableDeclaration(VariableProxy* proxy,
+                                              VariableMode mode,
+                                              Scope* scope) {
+    VariableDeclaration* decl =
+        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,
+                                          Scope* scope) {
+    ModuleDeclaration* decl =
+        new(zone_) ModuleDeclaration(proxy, module, scope);
+    VISIT_AND_RETURN(ModuleDeclaration, decl)
+  }
+
+  ImportDeclaration* NewImportDeclaration(VariableProxy* proxy,
+                                          Module* module,
+                                          Scope* scope) {
+    ImportDeclaration* decl =
+        new(zone_) ImportDeclaration(proxy, module, scope);
+    VISIT_AND_RETURN(ImportDeclaration, decl)
+  }
+
+  ExportDeclaration* NewExportDeclaration(VariableProxy* proxy,
+                                          Scope* scope) {
+    ExportDeclaration* decl =
+        new(zone_) ExportDeclaration(proxy, scope);
+    VISIT_AND_RETURN(ExportDeclaration, decl)
+  }
+
+  ModuleLiteral* NewModuleLiteral(Block* body, Interface* interface) {
+    ModuleLiteral* module = new(zone_) ModuleLiteral(body, interface);
+    VISIT_AND_RETURN(ModuleLiteral, module)
+  }
+
+  ModuleVariable* NewModuleVariable(VariableProxy* proxy) {
+    ModuleVariable* module = new(zone_) ModuleVariable(proxy);
+    VISIT_AND_RETURN(ModuleVariable, module)
+  }
+
+  ModulePath* NewModulePath(Module* origin, Handle<String> name) {
+    ModulePath* module = new(zone_) ModulePath(origin, name);
+    VISIT_AND_RETURN(ModulePath, module)
+  }
+
+  ModuleUrl* NewModuleUrl(Handle<String> url) {
+    ModuleUrl* module = new(zone_) ModuleUrl(url);
+    VISIT_AND_RETURN(ModuleUrl, module)
+  }
+
+  Block* NewBlock(ZoneStringList* labels,
+                  int capacity,
+                  bool is_initializer_block) {
+    Block* block = new(zone_) Block(
+        isolate_, labels, capacity, is_initializer_block);
+    VISIT_AND_RETURN(Block, block)
+  }
+
+#define STATEMENT_WITH_LABELS(NodeType) \
+  NodeType* New##NodeType(ZoneStringList* labels) { \
+    NodeType* stmt = new(zone_) NodeType(isolate_, labels); \
+    VISIT_AND_RETURN(NodeType, stmt); \
+  }
+  STATEMENT_WITH_LABELS(DoWhileStatement)
+  STATEMENT_WITH_LABELS(WhileStatement)
+  STATEMENT_WITH_LABELS(ForStatement)
+  STATEMENT_WITH_LABELS(ForInStatement)
+  STATEMENT_WITH_LABELS(SwitchStatement)
+#undef STATEMENT_WITH_LABELS
+
+  ExpressionStatement* NewExpressionStatement(Expression* expression) {
+    ExpressionStatement* stmt = new(zone_) ExpressionStatement(expression);
+    VISIT_AND_RETURN(ExpressionStatement, stmt)
+  }
+
+  ContinueStatement* NewContinueStatement(IterationStatement* target) {
+    ContinueStatement* stmt = new(zone_) ContinueStatement(target);
+    VISIT_AND_RETURN(ContinueStatement, stmt)
+  }
+
+  BreakStatement* NewBreakStatement(BreakableStatement* target) {
+    BreakStatement* stmt = new(zone_) BreakStatement(target);
+    VISIT_AND_RETURN(BreakStatement, stmt)
+  }
+
+  ReturnStatement* NewReturnStatement(Expression* expression) {
+    ReturnStatement* stmt = new(zone_) ReturnStatement(expression);
+    VISIT_AND_RETURN(ReturnStatement, stmt)
+  }
+
+  WithStatement* NewWithStatement(Expression* expression,
+                                  Statement* statement) {
+    WithStatement* stmt = new(zone_) WithStatement(expression, statement);
+    VISIT_AND_RETURN(WithStatement, stmt)
+  }
+
+  IfStatement* NewIfStatement(Expression* condition,
+                              Statement* then_statement,
+                              Statement* else_statement) {
+    IfStatement* stmt = new(zone_) IfStatement(
+        isolate_, condition, then_statement, else_statement);
+    VISIT_AND_RETURN(IfStatement, stmt)
+  }
+
+  TryCatchStatement* NewTryCatchStatement(int index,
+                                          Block* try_block,
+                                          Scope* scope,
+                                          Variable* variable,
+                                          Block* catch_block) {
+    TryCatchStatement* stmt = new(zone_) TryCatchStatement(
+        index, try_block, scope, variable, catch_block);
+    VISIT_AND_RETURN(TryCatchStatement, stmt)
+  }
+
+  TryFinallyStatement* NewTryFinallyStatement(int index,
+                                              Block* try_block,
+                                              Block* finally_block) {
+    TryFinallyStatement* stmt =
+        new(zone_) TryFinallyStatement(index, try_block, finally_block);
+    VISIT_AND_RETURN(TryFinallyStatement, stmt)
+  }
+
+  DebuggerStatement* NewDebuggerStatement() {
+    DebuggerStatement* stmt = new(zone_) DebuggerStatement();
+    VISIT_AND_RETURN(DebuggerStatement, stmt)
+  }
+
+  EmptyStatement* NewEmptyStatement() {
+    return new(zone_) EmptyStatement();
+  }
+
+  Literal* NewLiteral(Handle<Object> handle) {
+    Literal* lit = new(zone_) Literal(isolate_, handle);
+    VISIT_AND_RETURN(Literal, lit)
+  }
+
+  Literal* NewNumberLiteral(double number) {
+    return NewLiteral(isolate_->factory()->NewNumber(number, TENURED));
+  }
+
+  ObjectLiteral* NewObjectLiteral(
+      Handle<FixedArray> constant_properties,
+      ZoneList<ObjectLiteral::Property*>* properties,
+      int literal_index,
+      bool is_simple,
+      bool fast_elements,
+      int depth,
+      bool has_function) {
+    ObjectLiteral* lit = new(zone_) ObjectLiteral(
+        isolate_, constant_properties, properties, literal_index,
+        is_simple, fast_elements, depth, has_function);
+    VISIT_AND_RETURN(ObjectLiteral, lit)
+  }
+
+  ObjectLiteral::Property* NewObjectLiteralProperty(bool is_getter,
+                                                    FunctionLiteral* value) {
+    ObjectLiteral::Property* prop =
+        new(zone_) ObjectLiteral::Property(is_getter, value);
+    prop->set_key(NewLiteral(value->name()));
+    return prop;  // Not an AST node, will not be visited.
+  }
+
+  RegExpLiteral* NewRegExpLiteral(Handle<String> pattern,
+                                  Handle<String> flags,
+                                  int literal_index) {
+    RegExpLiteral* lit =
+        new(zone_) RegExpLiteral(isolate_, pattern, flags, literal_index);
+    VISIT_AND_RETURN(RegExpLiteral, lit);
+  }
+
+  ArrayLiteral* NewArrayLiteral(Handle<FixedArray> constant_elements,
+                                ZoneList<Expression*>* values,
+                                int literal_index,
+                                bool is_simple,
+                                int depth) {
+    ArrayLiteral* lit = new(zone_) ArrayLiteral(
+        isolate_, constant_elements, values, literal_index, is_simple, depth);
+    VISIT_AND_RETURN(ArrayLiteral, lit)
+  }
+
+  VariableProxy* NewVariableProxy(Variable* var) {
+    VariableProxy* proxy = new(zone_) VariableProxy(isolate_, var);
+    VISIT_AND_RETURN(VariableProxy, proxy)
+  }
+
+  VariableProxy* NewVariableProxy(Handle<String> name,
+                                  bool is_this,
+                                  int position = RelocInfo::kNoPosition,
+                                  Interface* interface =
+                                      Interface::NewValue()) {
+    VariableProxy* proxy =
+        new(zone_) VariableProxy(isolate_, name, is_this, position, interface);
+    VISIT_AND_RETURN(VariableProxy, proxy)
+  }
+
+  Property* NewProperty(Expression* obj, Expression* key, int pos) {
+    Property* prop = new(zone_) Property(isolate_, obj, key, pos);
+    VISIT_AND_RETURN(Property, prop)
+  }
+
+  Call* NewCall(Expression* expression,
+                ZoneList<Expression*>* arguments,
+                int pos) {
+    Call* call = new(zone_) Call(isolate_, expression, arguments, pos);
+    VISIT_AND_RETURN(Call, call)
+  }
+
+  CallNew* NewCallNew(Expression* expression,
+                      ZoneList<Expression*>* arguments,
+                      int pos) {
+    CallNew* call = new(zone_) CallNew(isolate_, expression, arguments, pos);
+    VISIT_AND_RETURN(CallNew, call)
+  }
+
+  CallRuntime* NewCallRuntime(Handle<String> name,
+                              const Runtime::Function* function,
+                              ZoneList<Expression*>* arguments) {
+    CallRuntime* call =
+        new(zone_) CallRuntime(isolate_, name, function, arguments);
+    VISIT_AND_RETURN(CallRuntime, call)
+  }
+
+  UnaryOperation* NewUnaryOperation(Token::Value op,
+                                    Expression* expression,
+                                    int pos) {
+    UnaryOperation* node =
+        new(zone_) UnaryOperation(isolate_, op, expression, pos);
+    VISIT_AND_RETURN(UnaryOperation, node)
+  }
+
+  BinaryOperation* NewBinaryOperation(Token::Value op,
+                                      Expression* left,
+                                      Expression* right,
+                                      int pos) {
+    BinaryOperation* node =
+        new(zone_) BinaryOperation(isolate_, op, left, right, pos);
+    VISIT_AND_RETURN(BinaryOperation, node)
+  }
+
+  CountOperation* NewCountOperation(Token::Value op,
+                                    bool is_prefix,
+                                    Expression* expr,
+                                    int pos) {
+    CountOperation* node =
+        new(zone_) CountOperation(isolate_, op, is_prefix, expr, pos);
+    VISIT_AND_RETURN(CountOperation, node)
+  }
+
+  CompareOperation* NewCompareOperation(Token::Value op,
+                                        Expression* left,
+                                        Expression* right,
+                                        int pos) {
+    CompareOperation* node =
+        new(zone_) CompareOperation(isolate_, op, left, right, pos);
+    VISIT_AND_RETURN(CompareOperation, node)
+  }
+
+  Conditional* NewConditional(Expression* condition,
+                              Expression* then_expression,
+                              Expression* else_expression,
+                              int then_expression_position,
+                              int else_expression_position) {
+    Conditional* cond = new(zone_) Conditional(
+        isolate_, condition, then_expression, else_expression,
+        then_expression_position, else_expression_position);
+    VISIT_AND_RETURN(Conditional, cond)
+  }
+
+  Assignment* NewAssignment(Token::Value op,
+                            Expression* target,
+                            Expression* value,
+                            int pos) {
+    Assignment* assign =
+        new(zone_) Assignment(isolate_, op, target, value, pos);
+    assign->Init(isolate_, this);
+    VISIT_AND_RETURN(Assignment, assign)
+  }
+
+  Throw* NewThrow(Expression* exception, int pos) {
+    Throw* t = new(zone_) Throw(isolate_, exception, pos);
+    VISIT_AND_RETURN(Throw, t)
+  }
+
+  FunctionLiteral* NewFunctionLiteral(
+      Handle<String> name,
+      Scope* scope,
+      ZoneList<Statement*>* body,
+      int materialized_literal_count,
+      int expected_property_count,
+      int handler_count,
+      bool has_only_simple_this_property_assignments,
+      Handle<FixedArray> this_property_assignments,
+      int parameter_count,
+      FunctionLiteral::ParameterFlag has_duplicate_parameters,
+      FunctionLiteral::Type type,
+      FunctionLiteral::IsFunctionFlag is_function) {
+    FunctionLiteral* lit = new(zone_) FunctionLiteral(
+        isolate_, name, scope, body,
+        materialized_literal_count, expected_property_count, handler_count,
+        has_only_simple_this_property_assignments, this_property_assignments,
+        parameter_count, type, has_duplicate_parameters, is_function);
+    // Top-level literal doesn't count for the AST's properties.
+    if (is_function == FunctionLiteral::kIsFunction) {
+      visitor_.VisitFunctionLiteral(lit);
+    }
+    return lit;
+  }
+
+  SharedFunctionInfoLiteral* NewSharedFunctionInfoLiteral(
+      Handle<SharedFunctionInfo> shared_function_info) {
+    SharedFunctionInfoLiteral* lit =
+        new(zone_) SharedFunctionInfoLiteral(isolate_, shared_function_info);
+    VISIT_AND_RETURN(SharedFunctionInfoLiteral, lit)
+  }
+
+  ThisFunction* NewThisFunction() {
+    ThisFunction* fun = new(zone_) ThisFunction(isolate_);
+    VISIT_AND_RETURN(ThisFunction, fun)
+  }
+
+#undef VISIT_AND_RETURN
+
+ private:
+  Isolate* isolate_;
+  Zone* zone_;
+  Visitor visitor_;
+};
+
+
 } }  // namespace v8::internal
 
 #endif  // V8_AST_H_