Collect AstNode type information
authorjkummerow@chromium.org <jkummerow@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 8 Feb 2012 09:56:33 +0000 (09:56 +0000)
committerjkummerow@chromium.org <jkummerow@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 8 Feb 2012 09:56:33 +0000 (09:56 +0000)
Review URL: https://chromiumcodereview.appspot.com/9221011

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

14 files changed:
src/ast.cc
src/ast.h
src/compiler.cc
src/heap.cc
src/hydrogen.cc
src/isolate.h
src/objects-inl.h
src/objects.h
src/parser.cc
src/parser.h
src/rewriter.cc
src/scopes.cc
src/scopes.h
test/cctest/test-ast.cc

index 18eb90c..397da5a 100644 (file)
@@ -126,18 +126,7 @@ Assignment::Assignment(Isolate* isolate,
       assignment_id_(GetNextId(isolate)),
       block_start_(false),
       block_end_(false),
-      is_monomorphic_(false) {
-  ASSERT(Token::IsAssignmentOp(op));
-  if (is_compound()) {
-    binary_operation_ =
-        new(isolate->zone()) BinaryOperation(isolate,
-                                             binary_op(),
-                                             target,
-                                             value,
-                                             pos + 1);
-    compound_load_id_ = GetNextId(isolate);
-  }
-}
+      is_monomorphic_(false) { }
 
 
 Token::Value Assignment::binary_op() const {
@@ -179,6 +168,11 @@ LanguageMode FunctionLiteral::language_mode() const {
 }
 
 
+bool FunctionLiteral::ShouldSelfOptimize() {
+  return !flags()->Contains(kDontSelfOptimize);
+}
+
+
 ObjectLiteral::Property::Property(Literal* key, Expression* value) {
   emit_store_ = true;
   key_ = key;
@@ -197,9 +191,7 @@ ObjectLiteral::Property::Property(Literal* key, Expression* value) {
 
 
 ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) {
-  Isolate* isolate = Isolate::Current();
   emit_store_ = true;
-  key_ = new(isolate->zone()) Literal(isolate, value->name());
   value_ = value;
   kind_ = is_getter ? GETTER : SETTER;
 }
@@ -431,223 +423,6 @@ bool Declaration::IsInlineable() const {
 }
 
 
-bool TargetCollector::IsInlineable() const {
-  UNREACHABLE();
-  return false;
-}
-
-
-bool ForInStatement::IsInlineable() const {
-  return false;
-}
-
-
-bool WithStatement::IsInlineable() const {
-  return false;
-}
-
-
-bool SwitchStatement::IsInlineable() const {
-  return false;
-}
-
-
-bool TryStatement::IsInlineable() const {
-  return false;
-}
-
-
-bool TryCatchStatement::IsInlineable() const {
-  return false;
-}
-
-
-bool TryFinallyStatement::IsInlineable() const {
-  return false;
-}
-
-
-bool DebuggerStatement::IsInlineable() const {
-  return false;
-}
-
-
-bool Throw::IsInlineable() const {
-  return exception()->IsInlineable();
-}
-
-
-bool MaterializedLiteral::IsInlineable() const {
-  // TODO(1322): Allow materialized literals.
-  return false;
-}
-
-
-bool FunctionLiteral::IsInlineable() const {
-  // TODO(1322): Allow materialized literals.
-  return false;
-}
-
-
-bool ThisFunction::IsInlineable() const {
-  return true;
-}
-
-
-bool SharedFunctionInfoLiteral::IsInlineable() const {
-  return false;
-}
-
-
-bool ForStatement::IsInlineable() const {
-  return (init() == NULL || init()->IsInlineable())
-      && (cond() == NULL || cond()->IsInlineable())
-      && (next() == NULL || next()->IsInlineable())
-      && body()->IsInlineable();
-}
-
-
-bool WhileStatement::IsInlineable() const {
-  return cond()->IsInlineable()
-      && body()->IsInlineable();
-}
-
-
-bool DoWhileStatement::IsInlineable() const {
-  return cond()->IsInlineable()
-      && body()->IsInlineable();
-}
-
-
-bool ContinueStatement::IsInlineable() const {
-  return true;
-}
-
-
-bool BreakStatement::IsInlineable() const {
-  return true;
-}
-
-
-bool EmptyStatement::IsInlineable() const {
-  return true;
-}
-
-
-bool Literal::IsInlineable() const {
-  return true;
-}
-
-
-bool Block::IsInlineable() const {
-  const int count = statements_.length();
-  for (int i = 0; i < count; ++i) {
-    if (!statements_[i]->IsInlineable()) return false;
-  }
-  return true;
-}
-
-
-bool ExpressionStatement::IsInlineable() const {
-  return expression()->IsInlineable();
-}
-
-
-bool IfStatement::IsInlineable() const {
-  return condition()->IsInlineable()
-      && then_statement()->IsInlineable()
-      && else_statement()->IsInlineable();
-}
-
-
-bool ReturnStatement::IsInlineable() const {
-  return expression()->IsInlineable();
-}
-
-
-bool Conditional::IsInlineable() const {
-  return condition()->IsInlineable() && then_expression()->IsInlineable() &&
-      else_expression()->IsInlineable();
-}
-
-
-bool VariableProxy::IsInlineable() const {
-  return var()->IsUnallocated()
-      || var()->IsStackAllocated()
-      || var()->IsContextSlot();
-}
-
-
-bool Assignment::IsInlineable() const {
-  return target()->IsInlineable() && value()->IsInlineable();
-}
-
-
-bool Property::IsInlineable() const {
-  return obj()->IsInlineable() && key()->IsInlineable();
-}
-
-
-bool Call::IsInlineable() const {
-  if (!expression()->IsInlineable()) return false;
-  const int count = arguments()->length();
-  for (int i = 0; i < count; ++i) {
-    if (!arguments()->at(i)->IsInlineable()) return false;
-  }
-  return true;
-}
-
-
-bool CallNew::IsInlineable() const {
-  if (!expression()->IsInlineable()) return false;
-  const int count = arguments()->length();
-  for (int i = 0; i < count; ++i) {
-    if (!arguments()->at(i)->IsInlineable()) return false;
-  }
-  return true;
-}
-
-
-bool CallRuntime::IsInlineable() const {
-  // Don't try to inline JS runtime calls because we don't (currently) even
-  // optimize them.
-  if (is_jsruntime()) return false;
-  // Don't inline the %_ArgumentsLength or %_Arguments because their
-  // implementation will not work.  There is no stack frame to get them
-  // from.
-  if (function()->intrinsic_type == Runtime::INLINE &&
-      (name()->IsEqualTo(CStrVector("_ArgumentsLength")) ||
-       name()->IsEqualTo(CStrVector("_Arguments")))) {
-    return false;
-  }
-  const int count = arguments()->length();
-  for (int i = 0; i < count; ++i) {
-    if (!arguments()->at(i)->IsInlineable()) return false;
-  }
-  return true;
-}
-
-
-bool UnaryOperation::IsInlineable() const {
-  return expression()->IsInlineable();
-}
-
-
-bool BinaryOperation::IsInlineable() const {
-  return left()->IsInlineable() && right()->IsInlineable();
-}
-
-
-bool CompareOperation::IsInlineable() const {
-  return left()->IsInlineable() && right()->IsInlineable();
-}
-
-
-bool CountOperation::IsInlineable() const {
-  return expression()->IsInlineable();
-}
-
-
 // ----------------------------------------------------------------------------
 // Recording of type feedback
 
@@ -1214,4 +989,164 @@ CaseClause::CaseClause(Isolate* isolate,
       entry_id_(AstNode::GetNextId(isolate)) {
 }
 
+
+#define INCREASE_NODE_COUNT(NodeType) \
+  void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
+    increase_node_count(); \
+  }
+
+INCREASE_NODE_COUNT(Declaration)
+INCREASE_NODE_COUNT(Block)
+INCREASE_NODE_COUNT(ExpressionStatement)
+INCREASE_NODE_COUNT(EmptyStatement)
+INCREASE_NODE_COUNT(IfStatement)
+INCREASE_NODE_COUNT(ContinueStatement)
+INCREASE_NODE_COUNT(BreakStatement)
+INCREASE_NODE_COUNT(ReturnStatement)
+INCREASE_NODE_COUNT(Conditional)
+INCREASE_NODE_COUNT(Literal)
+INCREASE_NODE_COUNT(Assignment)
+INCREASE_NODE_COUNT(Throw)
+INCREASE_NODE_COUNT(Property)
+INCREASE_NODE_COUNT(UnaryOperation)
+INCREASE_NODE_COUNT(CountOperation)
+INCREASE_NODE_COUNT(BinaryOperation)
+INCREASE_NODE_COUNT(CompareOperation)
+INCREASE_NODE_COUNT(ThisFunction)
+
+#undef INCREASE_NODE_COUNT
+
+
+void AstConstructionVisitor::VisitWithStatement(WithStatement* node) {
+  increase_node_count();
+  add_flag(kDontOptimize);
+  add_flag(kDontInline);
+}
+
+
+void AstConstructionVisitor::VisitSwitchStatement(SwitchStatement* node) {
+  increase_node_count();
+  add_flag(kDontInline);
+}
+
+
+void AstConstructionVisitor::VisitDoWhileStatement(DoWhileStatement* node) {
+  increase_node_count();
+  add_flag(kDontSelfOptimize);
+}
+
+
+void AstConstructionVisitor::VisitWhileStatement(WhileStatement* node) {
+  increase_node_count();
+  add_flag(kDontSelfOptimize);
+}
+
+
+void AstConstructionVisitor::VisitForStatement(ForStatement* node) {
+  increase_node_count();
+  add_flag(kDontSelfOptimize);
+}
+
+
+void AstConstructionVisitor::VisitForInStatement(ForInStatement* node) {
+  increase_node_count();
+  add_flag(kDontOptimize);
+  add_flag(kDontInline);
+  add_flag(kDontSelfOptimize);
+}
+
+
+void AstConstructionVisitor::VisitTryCatchStatement(TryCatchStatement* node) {
+  increase_node_count();
+  add_flag(kDontOptimize);
+  add_flag(kDontInline);
+}
+
+
+void AstConstructionVisitor::VisitTryFinallyStatement(
+    TryFinallyStatement* node) {
+  increase_node_count();
+  add_flag(kDontOptimize);
+  add_flag(kDontInline);
+}
+
+
+void AstConstructionVisitor::VisitDebuggerStatement(DebuggerStatement* node) {
+  increase_node_count();
+  add_flag(kDontOptimize);
+  add_flag(kDontInline);
+}
+
+
+void AstConstructionVisitor::VisitFunctionLiteral(FunctionLiteral* node) {
+  increase_node_count();
+  add_flag(kDontInline);
+}
+
+
+void AstConstructionVisitor::VisitSharedFunctionInfoLiteral(
+    SharedFunctionInfoLiteral* node) {
+  increase_node_count();
+  add_flag(kDontOptimize);
+  add_flag(kDontInline);
+}
+
+
+void AstConstructionVisitor::VisitVariableProxy(VariableProxy* node) {
+  increase_node_count();
+  // In theory, we'd have to add:
+  // if(node->var()->IsLookupSlot()) { add_flag(kDontInline); }
+  // However, node->var() is usually not bound yet at VariableProxy creation
+  // time, and LOOKUP variables only result from constructs that cannot
+  // be inlined anyway.
+}
+
+
+void AstConstructionVisitor::VisitRegExpLiteral(RegExpLiteral* node) {
+  increase_node_count();
+  add_flag(kDontInline);  // TODO(1322): Allow materialized literals.
+}
+
+
+void AstConstructionVisitor::VisitObjectLiteral(ObjectLiteral* node) {
+  increase_node_count();
+  add_flag(kDontInline);  // TODO(1322): Allow materialized literals.
+}
+
+
+void AstConstructionVisitor::VisitArrayLiteral(ArrayLiteral* node) {
+  increase_node_count();
+  add_flag(kDontInline);  // TODO(1322): Allow materialized literals.
+}
+
+
+void AstConstructionVisitor::VisitCall(Call* node) {
+  increase_node_count();
+  add_flag(kDontSelfOptimize);
+}
+
+
+void AstConstructionVisitor::VisitCallNew(CallNew* node) {
+  increase_node_count();
+  add_flag(kDontSelfOptimize);
+}
+
+
+void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) {
+  increase_node_count();
+  add_flag(kDontSelfOptimize);
+  if (node->is_jsruntime()) {
+    // Don't try to inline JS runtime calls because we don't (currently) even
+    // optimize them.
+    add_flag(kDontInline);
+  } else if (node->function()->intrinsic_type == Runtime::INLINE &&
+      (node->name()->IsEqualTo(CStrVector("_ArgumentsLength")) ||
+       node->name()->IsEqualTo(CStrVector("_Arguments")))) {
+    // Don't inline the %_ArgumentsLength or %_Arguments because their
+    // implementation will not work.  There is no stack frame to get them
+    // from.
+    add_flag(kDontInline);
+  }
+}
+
 } }  // namespace v8::internal
index 34fadab..bc2c67e 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -39,6 +39,7 @@
 #include "small-pointer-list.h"
 #include "smart-array-pointer.h"
 #include "token.h"
+#include "utils.h"
 #include "variables.h"
 #include "zone-inl.h"
 
@@ -103,6 +104,8 @@ namespace internal {
   EXPRESSION_NODE_LIST(V)
 
 // Forward declarations
+class AstConstructionVisitor;
+template<class> class AstNodeFactory;
 class AstVisitor;
 class BreakableStatement;
 class Expression;
@@ -136,6 +139,35 @@ typedef ZoneList<Handle<String> > ZoneStringList;
 typedef ZoneList<Handle<Object> > ZoneObjectList;
 
 
+#define DECLARE_NODE_TYPE(type)                                         \
+  virtual void Accept(AstVisitor* v);                                   \
+  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 {
  public:
 #define DECLARE_TYPE_ENUM(type) k##type,
@@ -152,14 +184,11 @@ class AstNode: public ZoneObject {
   // 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() { }
 
@@ -180,19 +209,15 @@ class AstNode: public ZoneObject {
   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;
   }
@@ -326,8 +351,8 @@ class Expression: public AstNode {
   unsigned test_id() const { return test_id_; }
 
  private:
-  unsigned id_;
-  unsigned test_id_;
+  int id_;
+  int test_id_;
 };
 
 
@@ -376,21 +401,8 @@ class BreakableStatement: public Statement {
 
 class Block: public BreakableStatement {
  public:
-  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) {
-  }
-
-
   DECLARE_NODE_TYPE(Block)
 
-  virtual bool IsInlineable() const;
-
   void AddStatement(Statement* statement) { statements_.Add(statement); }
 
   ZoneList<Statement*>* statements() { return &statements_; }
@@ -399,6 +411,19 @@ class Block: public BreakableStatement {
   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_;
@@ -408,6 +433,17 @@ class Block: public BreakableStatement {
 
 class Declaration: public AstNode {
  public:
+  DECLARE_NODE_TYPE(Declaration)
+
+  VariableProxy* proxy() const { return proxy_; }
+  VariableMode mode() const { return mode_; }
+  FunctionLiteral* fun() const { return fun_; }  // may be NULL
+  bool IsInlineable() const;
+  Scope* scope() const { return scope_; }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
   Declaration(VariableProxy* proxy,
               VariableMode mode,
               FunctionLiteral* fun,
@@ -424,14 +460,6 @@ class Declaration: public AstNode {
     ASSERT(fun == NULL || mode == VAR || mode == LET);
   }
 
-  DECLARE_NODE_TYPE(Declaration)
-
-  VariableProxy* proxy() const { return proxy_; }
-  VariableMode mode() const { return mode_; }
-  FunctionLiteral* fun() const { return fun_; }  // may be NULL
-  virtual bool IsInlineable() const;
-  Scope* scope() const { return scope_; }
-
  private:
   VariableProxy* proxy_;
   VariableMode mode_;
@@ -477,14 +505,6 @@ class IterationStatement: public BreakableStatement {
 
 class DoWhileStatement: public IterationStatement {
  public:
-  DoWhileStatement(Isolate* isolate, ZoneStringList* labels)
-      : IterationStatement(isolate, labels),
-        cond_(NULL),
-        condition_position_(-1),
-        continue_id_(GetNextId(isolate)),
-        back_edge_id_(GetNextId(isolate)) {
-  }
-
   DECLARE_NODE_TYPE(DoWhileStatement)
 
   void Initialize(Expression* cond, Statement* body) {
@@ -504,7 +524,16 @@ class DoWhileStatement: public IterationStatement {
   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_;
@@ -516,13 +545,6 @@ class DoWhileStatement: public IterationStatement {
 
 class WhileStatement: public IterationStatement {
  public:
-  WhileStatement(Isolate* isolate, ZoneStringList* labels)
-      : IterationStatement(isolate, labels),
-        cond_(NULL),
-        may_have_function_literal_(true),
-        body_id_(GetNextId(isolate)) {
-  }
-
   DECLARE_NODE_TYPE(WhileStatement)
 
   void Initialize(Expression* cond, Statement* body) {
@@ -537,13 +559,22 @@ class WhileStatement: public IterationStatement {
   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.
@@ -554,17 +585,6 @@ class WhileStatement: public IterationStatement {
 
 class ForStatement: public IterationStatement {
  public:
-  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)) {
-  }
-
   DECLARE_NODE_TYPE(ForStatement)
 
   void Initialize(Statement* init,
@@ -596,7 +616,20 @@ class ForStatement: public IterationStatement {
   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_;
@@ -612,13 +645,6 @@ class ForStatement: public IterationStatement {
 
 class ForInStatement: public IterationStatement {
  public:
-  ForInStatement(Isolate* isolate, ZoneStringList* labels)
-      : IterationStatement(isolate, labels),
-        each_(NULL),
-        enumerable_(NULL),
-        assignment_id_(GetNextId(isolate)) {
-  }
-
   DECLARE_NODE_TYPE(ForInStatement)
 
   void Initialize(Expression* each, Expression* enumerable, Statement* body) {
@@ -629,13 +655,22 @@ class ForInStatement: public IterationStatement {
 
   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(); }
 
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  ForInStatement(Isolate* isolate, ZoneStringList* labels)
+      : IterationStatement(isolate, labels),
+        each_(NULL),
+        enumerable_(NULL),
+        assignment_id_(GetNextId(isolate)) {
+  }
+
  private:
   Expression* each_;
   Expression* enumerable_;
@@ -645,16 +680,17 @@ class ForInStatement: public IterationStatement {
 
 class ExpressionStatement: public Statement {
  public:
-  explicit ExpressionStatement(Expression* expression)
-      : expression_(expression) { }
-
   DECLARE_NODE_TYPE(ExpressionStatement)
 
-  virtual bool IsInlineable() const;
-
   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_;
 };
@@ -662,13 +698,15 @@ class ExpressionStatement: public Statement {
 
 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_;
@@ -677,13 +715,15 @@ class ContinueStatement: public Statement {
 
 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_;
@@ -692,13 +732,15 @@ class BreakStatement: public Statement {
 
 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_;
@@ -707,15 +749,17 @@ class ReturnStatement: public Statement {
 
 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_;
@@ -771,13 +815,6 @@ class CaseClause: public ZoneObject {
 
 class SwitchStatement: public BreakableStatement {
  public:
-  SwitchStatement(Isolate* isolate, ZoneStringList* labels)
-      : BreakableStatement(isolate, labels, TARGET_FOR_ANONYMOUS),
-        tag_(NULL),
-        cases_(NULL) {
-  }
-
-
   DECLARE_NODE_TYPE(SwitchStatement)
 
   void Initialize(Expression* tag, ZoneList<CaseClause*>* cases) {
@@ -787,7 +824,14 @@ class SwitchStatement: public BreakableStatement {
 
   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_;
@@ -802,22 +846,8 @@ class SwitchStatement: public BreakableStatement {
 // 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(); }
 
@@ -829,6 +859,21 @@ class IfStatement: public Statement {
   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_;
@@ -843,7 +888,7 @@ class IfStatement: public Statement {
 // 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
@@ -855,7 +900,6 @@ class TargetCollector: public AstNode {
   virtual TargetCollector* AsTargetCollector() { return this; }
 
   ZoneList<Label*>* targets() { return &targets_; }
-  virtual bool IsInlineable() const;
 
  private:
   ZoneList<Label*> targets_;
@@ -864,12 +908,6 @@ class TargetCollector: public AstNode {
 
 class TryStatement: public Statement {
  public:
-  explicit TryStatement(int index, Block* try_block)
-      : index_(index),
-        try_block_(try_block),
-        escaping_targets_(NULL) {
-  }
-
   void set_escaping_targets(ZoneList<Label*>* targets) {
     escaping_targets_ = targets;
   }
@@ -877,7 +915,12 @@ class TryStatement: public Statement {
   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.
@@ -890,6 +933,15 @@ class TryStatement: public Statement {
 
 class TryCatchStatement: public TryStatement {
  public:
+  DECLARE_NODE_TYPE(TryCatchStatement)
+
+  Scope* scope() { return scope_; }
+  Variable* variable() { return variable_; }
+  Block* catch_block() const { return catch_block_; }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
   TryCatchStatement(int index,
                     Block* try_block,
                     Scope* scope,
@@ -901,13 +953,6 @@ class TryCatchStatement: public TryStatement {
         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;
-
  private:
   Scope* scope_;
   Variable* variable_;
@@ -917,14 +962,16 @@ class TryCatchStatement: public TryStatement {
 
 class TryFinallyStatement: public TryStatement {
  public:
-  TryFinallyStatement(int index, Block* try_block, Block* finally_block)
-      : TryStatement(index, 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_;
@@ -934,7 +981,11 @@ class TryFinallyStatement: public TryStatement {
 class DebuggerStatement: public Statement {
  public:
   DECLARE_NODE_TYPE(DebuggerStatement)
-  virtual bool IsInlineable() const;
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  DebuggerStatement() {}
 };
 
 
@@ -942,15 +993,15 @@ class EmptyStatement: public Statement {
  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)
 
   // Check if this literal is identical to the other literal.
@@ -989,7 +1040,13 @@ class Literal: public Expression {
   }
 
   Handle<Object> handle() const { return handle_; }
-  virtual bool IsInlineable() const;
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  Literal(Isolate* isolate, Handle<Object> handle)
+      : Expression(isolate),
+        handle_(handle) { }
 
  private:
   Handle<Object> handle_;
@@ -999,15 +1056,6 @@ class Literal: public Expression {
 // 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_; }
@@ -1017,7 +1065,16 @@ class MaterializedLiteral: public Expression {
   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_;
@@ -1044,7 +1101,6 @@ class ObjectLiteral: public MaterializedLiteral {
     };
 
     Property(Literal* key, Expression* value);
-    Property(bool is_getter, FunctionLiteral* value);
 
     Literal* key() { return key_; }
     Expression* value() { return value_; }
@@ -1055,6 +1111,12 @@ class ObjectLiteral: public MaterializedLiteral {
     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_;
@@ -1062,20 +1124,6 @@ class ObjectLiteral: public MaterializedLiteral {
     bool emit_store_;
   };
 
-  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 {
@@ -1098,6 +1146,23 @@ class ObjectLiteral: public MaterializedLiteral {
     kHasFunction = 1 << 1
   };
 
+ 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_;
@@ -1109,6 +1174,14 @@ class ObjectLiteral: public MaterializedLiteral {
 // 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,
@@ -1117,11 +1190,6 @@ class RegExpLiteral: public MaterializedLiteral {
         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_;
@@ -1131,6 +1199,17 @@ class RegExpLiteral: public MaterializedLiteral {
 // 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,
@@ -1142,14 +1221,6 @@ class ArrayLiteral: public MaterializedLiteral {
         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_;
@@ -1159,21 +1230,12 @@ class ArrayLiteral: public MaterializedLiteral {
 
 class VariableProxy: public Expression {
  public:
-  VariableProxy(Isolate* isolate, Variable* var);
-
-  VariableProxy(Isolate* isolate,
-                Handle<String> name,
-                bool is_this,
-                int position = RelocInfo::kNoPosition);
-
   DECLARE_NODE_TYPE(VariableProxy)
 
   virtual bool IsValidLeftHandSide() {
     return var_ == NULL ? true : var_->IsValidLeftHandSide();
   }
 
-  virtual bool IsInlineable() const;
-
   bool IsVariable(Handle<String> n) {
     return !is_this() && name().is_identical_to(n);
   }
@@ -1196,6 +1258,15 @@ class VariableProxy: public Expression {
   void BindTo(Variable* var);
 
  protected:
+  template<class> friend class AstNodeFactory;
+
+  VariableProxy(Isolate* isolate, Variable* var);
+
+  VariableProxy(Isolate* isolate,
+                Handle<String> name,
+                bool is_this,
+                int position);
+
   Handle<String> name_;
   Variable* var_;  // resolved variable, or NULL
   bool is_this_;
@@ -1209,24 +1280,9 @@ class VariableProxy: public Expression {
 
 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_; }
@@ -1242,6 +1298,23 @@ class Property: public Expression {
   virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
   bool IsArrayLength() { return is_array_length_; }
 
+ 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_array_length_(false),
+        is_string_length_(false),
+        is_string_access_(false),
+        is_function_prototype_(false) { }
+
  private:
   Expression* obj_;
   Expression* key_;
@@ -1258,23 +1331,8 @@ class Property: public Expression {
 
 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_; }
@@ -1299,6 +1357,21 @@ class Call: public Expression {
   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_;
@@ -1317,6 +1390,15 @@ class Call: public Expression {
 
 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_; }
+
+ protected:
+  template<class> friend class AstNodeFactory;
+
   CallNew(Isolate* isolate,
           Expression* expression,
           ZoneList<Expression*>* arguments,
@@ -1326,14 +1408,6 @@ class CallNew: public 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_; }
-
  private:
   Expression* expression_;
   ZoneList<Expression*>* arguments_;
@@ -1347,6 +1421,16 @@ class CallNew: public Expression {
 // 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,
@@ -1356,15 +1440,6 @@ class CallRuntime: public Expression {
         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_;
@@ -1374,6 +1449,20 @@ class CallRuntime: public Expression {
 
 class UnaryOperation: public Expression {
  public:
+  DECLARE_NODE_TYPE(UnaryOperation)
+
+  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,
@@ -1391,19 +1480,6 @@ class UnaryOperation: public Expression {
     }
   }
 
-  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_; }
-
  private:
   Token::Value op_;
   Expression* expression_;
@@ -1418,22 +1494,8 @@ class UnaryOperation: public Expression {
 
 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_; }
@@ -1444,6 +1506,21 @@ class BinaryOperation: public Expression {
   // 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_;
@@ -1457,19 +1534,6 @@ class BinaryOperation: public Expression {
 
 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_; }
@@ -1485,8 +1549,6 @@ class CountOperation: public Expression {
 
   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_; }
@@ -1495,6 +1557,22 @@ class CountOperation: public Expression {
   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_;
@@ -1508,21 +1586,7 @@ class CountOperation: public Expression {
 
 
 class CompareOperation: public Expression {
- public:
-  CompareOperation(Isolate* isolate,
-                   Token::Value op,
-                   Expression* left,
-                   Expression* right,
-                   int pos)
-      : Expression(isolate),
-        op_(op),
-        left_(left),
-        right_(right),
-        pos_(pos),
-        compare_type_(NONE) {
-    ASSERT(Token::IsCompareOp(op));
-  }
-
+ public:
   DECLARE_NODE_TYPE(CompareOperation)
 
   Token::Value op() const { return op_; }
@@ -1530,8 +1594,6 @@ class CompareOperation: public Expression {
   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; }
@@ -1542,6 +1604,23 @@ class CompareOperation: public Expression {
   bool IsLiteralCompareUndefined(Expression** expr);
   bool IsLiteralCompareNull(Expression** expr);
 
+ protected:
+  template<class> friend class AstNodeFactory;
+
+  CompareOperation(Isolate* isolate,
+                   Token::Value op,
+                   Expression* left,
+                   Expression* right,
+                   int pos)
+      : Expression(isolate),
+        op_(op),
+        left_(left),
+        right_(right),
+        pos_(pos),
+        compare_type_(NONE) {
+    ASSERT(Token::IsCompareOp(op));
+  }
+
  private:
   Token::Value op_;
   Expression* left_;
@@ -1555,6 +1634,21 @@ class CompareOperation: public 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,
@@ -1568,22 +1662,7 @@ class Conditional: public Expression {
         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_;
@@ -1598,16 +1677,8 @@ class Conditional: public Expression {
 
 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;
@@ -1639,6 +1710,25 @@ class Assignment: public Expression {
   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_;
@@ -1658,14 +1748,16 @@ class Assignment: public Expression {
 
 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_;
@@ -1681,38 +1773,6 @@ class FunctionLiteral: public Expression {
     DECLARATION
   };
 
-  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,
-                  bool has_duplicate_parameters)
-      : 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);
-  }
-
   DECLARE_NODE_TYPE(FunctionLiteral)
 
   Handle<String> name() const { return name_; }
@@ -1752,18 +1812,61 @@ class FunctionLiteral: public Expression {
 
   bool pretenure() { return Pretenure::decode(bitfield_); }
   void set_pretenure() { bitfield_ |= Pretenure::encode(true); }
-  virtual bool IsInlineable() const;
 
   bool has_duplicate_parameters() {
     return HasDuplicateParameters::decode(bitfield_);
   }
 
+  bool ShouldSelfOptimize();
+
+  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,
+                  bool has_duplicate_parameters)
+      : 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);
+  }
+
  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_;
@@ -1782,17 +1885,20 @@ class FunctionLiteral: public Expression {
 
 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_;
@@ -1801,9 +1907,12 @@ class SharedFunctionInfoLiteral: public Expression {
 
 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) {}
 };
 
 
@@ -2207,6 +2316,342 @@ class AstVisitor BASE_EMBEDDED {
 };
 
 
+// ----------------------------------------------------------------------------
+// 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;
+
+  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)
+  }
+
+  Declaration* NewDeclaration(VariableProxy* proxy,
+                              VariableMode mode,
+                              FunctionLiteral* fun,
+                              Scope* scope) {
+    Declaration* decl = new(zone_) Declaration(proxy, mode, fun, scope);
+    VISIT_AND_RETURN(Declaration, decl)
+  }
+
+#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) {
+    VariableProxy* proxy =
+        new(zone_) VariableProxy(isolate_, name, is_this, position);
+    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,
+      bool has_duplicate_parameters,
+      FunctionLiteral::Type type,
+      bool visit_with_visitor) {
+    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);
+    if (visit_with_visitor) {
+      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_
index ba4d202..9b8b1a4 100644 (file)
@@ -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:
@@ -652,6 +652,8 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
         // Check the function has compiled code.
         ASSERT(shared->is_compiled());
         shared->set_code_age(0);
+        shared->set_dont_crankshaft(lit->flags()->Contains(kDontOptimize));
+        shared->set_dont_inline(lit->flags()->Contains(kDontInline));
 
         if (info->AllowOptimize() && !shared->optimization_disabled()) {
           // If we're asked to always optimize, we compile the optimized
@@ -750,6 +752,9 @@ void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
   function_info->set_language_mode(lit->language_mode());
   function_info->set_uses_arguments(lit->scope()->arguments() != NULL);
   function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
+  function_info->set_ast_node_count(lit->ast_node_count());
+  function_info->set_dont_crankshaft(lit->flags()->Contains(kDontOptimize));
+  function_info->set_dont_inline(lit->flags()->Contains(kDontInline));
 }
 
 
index 4cea933..042069c 100644 (file)
@@ -2865,7 +2865,8 @@ MaybeObject* Heap::AllocateSharedFunctionInfo(Object* name) {
   share->set_inferred_name(empty_string(), SKIP_WRITE_BARRIER);
   share->set_initial_map(undefined_value(), SKIP_WRITE_BARRIER);
   share->set_this_property_assignments(undefined_value(), SKIP_WRITE_BARRIER);
-  share->set_deopt_counter(Smi::FromInt(FLAG_deopt_every_n_times));
+  share->set_deopt_counter(FLAG_deopt_every_n_times);
+  share->set_ast_node_count(0);
 
   // Set integer fields (smi or int, depending on the architecture).
   share->set_length(0);
index fdfadfa..d859c4c 100644 (file)
@@ -4796,8 +4796,8 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
 
   // Do a quick check on source code length to avoid parsing large
   // inlining candidates.
-  if ((FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize)
-      || target->shared()->SourceSize() > kUnlimitedMaxSourceSize) {
+  if ((FLAG_limit_inlining && target_shared->SourceSize() > kMaxSourceSize)
+      || target_shared->SourceSize() > kUnlimitedMaxSourceSize) {
     TraceInline(target, caller, "target text too big");
     return false;
   }
@@ -4807,6 +4807,17 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
     TraceInline(target, caller, "target not inlineable");
     return false;
   }
+  if (target_shared->dont_inline() || target_shared->dont_crankshaft()) {
+    TraceInline(target, caller, "target contains unsupported syntax [early]");
+    return false;
+  }
+
+  int nodes_added = target_shared->ast_node_count();
+  if ((FLAG_limit_inlining && nodes_added > kMaxInlinedSize) ||
+      nodes_added > kUnlimitedMaxInlinedSize) {
+    TraceInline(target, caller, "target AST is too large [early]");
+    return false;
+  }
 
 #if !defined(V8_TARGET_ARCH_IA32)
   // Target must be able to use caller's context.
@@ -4851,8 +4862,6 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
     return false;
   }
 
-  int count_before = AstNode::Count();
-
   // Parse and allocate variables.
   CompilationInfo target_info(target);
   if (!ParserApi::Parse(&target_info, kNoParsingFlags) ||
@@ -4872,11 +4881,17 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
   }
   FunctionLiteral* function = target_info.function();
 
-  // Count the number of AST nodes added by inlining this call.
-  int nodes_added = AstNode::Count() - count_before;
+  // The following conditions must be checked again after re-parsing, because
+  // earlier the information might not have been complete due to lazy parsing.
+  nodes_added = function->ast_node_count();
   if ((FLAG_limit_inlining && nodes_added > kMaxInlinedSize) ||
       nodes_added > kUnlimitedMaxInlinedSize) {
-    TraceInline(target, caller, "target AST is too large");
+    TraceInline(target, caller, "target AST is too large [late]");
+    return false;
+  }
+  AstProperties::Flags* flags(function->flags());
+  if (flags->Contains(kDontInline) || flags->Contains(kDontOptimize)) {
+    TraceInline(target, caller, "target contains unsupported syntax [late]");
     return false;
   }
 
@@ -4895,13 +4910,6 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
       return false;
     }
   }
-  // All statements in the body must be inlineable.
-  for (int i = 0, count = function->body()->length(); i < count; ++i) {
-    if (!function->body()->at(i)->IsInlineable()) {
-      TraceInline(target, caller, "target contains unsupported syntax");
-      return false;
-    }
-  }
 
   // Generate the deoptimization data for the unoptimized version of
   // the target function if we don't already have it.
index 295adca..5612630 100644 (file)
@@ -362,7 +362,7 @@ typedef List<HeapObject*, PreallocatedStorage> DebugObjectCache;
   /* Serializer state. */                                                      \
   V(ExternalReferenceTable*, external_reference_table, NULL)                   \
   /* AstNode state. */                                                         \
-  V(unsigned, ast_node_id, 0)                                                  \
+  V(int, ast_node_id, 0)                                                       \
   V(unsigned, ast_node_count, 0)                                               \
   /* SafeStackFrameIterator activations count. */                              \
   V(int, safe_stack_iterator_counter, 0)                                       \
index 6eeba20..baaa5ab 100644 (file)
@@ -3576,6 +3576,8 @@ SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
 SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
               kThisPropertyAssignmentsCountOffset)
 SMI_ACCESSORS(SharedFunctionInfo, opt_count, kOptCountOffset)
+SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
+SMI_ACCESSORS(SharedFunctionInfo, deopt_counter, kDeoptCounterOffset)
 #else
 
 #define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset)             \
@@ -3626,6 +3628,9 @@ PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
                         this_property_assignments_count,
                         kThisPropertyAssignmentsCountOffset)
 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, opt_count, kOptCountOffset)
+
+PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
+PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, deopt_counter, kDeoptCounterOffset)
 #endif
 
 
@@ -3708,6 +3713,9 @@ BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
                kNameShouldPrintAsAnonymous)
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, bound, kBoundFunction)
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous)
+BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_crankshaft,
+               kDontCrankshaft)
+BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_inline, kDontInline)
 
 ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
 ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
@@ -3777,16 +3785,6 @@ void SharedFunctionInfo::set_scope_info(ScopeInfo* value,
 }
 
 
-Smi* SharedFunctionInfo::deopt_counter() {
-  return reinterpret_cast<Smi*>(READ_FIELD(this, kDeoptCounterOffset));
-}
-
-
-void SharedFunctionInfo::set_deopt_counter(Smi* value) {
-  WRITE_FIELD(this, kDeoptCounterOffset, value);
-}
-
-
 bool SharedFunctionInfo::is_compiled() {
   return code() !=
       Isolate::Current()->builtins()->builtin(Builtins::kLazyCompile);
index 97954cd..76ac347 100644 (file)
@@ -5203,8 +5203,11 @@ class SharedFunctionInfo: public HeapObject {
 
   // A counter used to determine when to stress the deoptimizer with a
   // deopt.
-  inline Smi* deopt_counter();
-  inline void set_deopt_counter(Smi* counter);
+  inline int deopt_counter();
+  inline void set_deopt_counter(int counter);
+
+  inline int ast_node_count();
+  inline void set_ast_node_count(int count);
 
   // Add information on assignments of the form this.x = ...;
   void SetThisPropertyAssignmentsInfo(
@@ -5278,6 +5281,12 @@ class SharedFunctionInfo: public HeapObject {
   // through the API, which does not change this flag).
   DECL_BOOLEAN_ACCESSORS(is_anonymous)
 
+  // Indicates that the function cannot be crankshafted.
+  DECL_BOOLEAN_ACCESSORS(dont_crankshaft)
+
+  // Indicates that the function cannot be inlined.
+  DECL_BOOLEAN_ACCESSORS(dont_inline)
+
   // Indicates whether or not the code in the shared function support
   // deoptimization.
   inline bool has_deoptimization_support();
@@ -5372,12 +5381,10 @@ class SharedFunctionInfo: public HeapObject {
       kInferredNameOffset + kPointerSize;
   static const int kThisPropertyAssignmentsOffset =
       kInitialMapOffset + kPointerSize;
-  static const int kDeoptCounterOffset =
-      kThisPropertyAssignmentsOffset + kPointerSize;
 #if V8_HOST_ARCH_32_BIT
   // Smi fields.
   static const int kLengthOffset =
-      kDeoptCounterOffset + kPointerSize;
+      kThisPropertyAssignmentsOffset + kPointerSize;
   static const int kFormalParameterCountOffset = kLengthOffset + kPointerSize;
   static const int kExpectedNofPropertiesOffset =
       kFormalParameterCountOffset + kPointerSize;
@@ -5395,8 +5402,11 @@ class SharedFunctionInfo: public HeapObject {
       kCompilerHintsOffset + kPointerSize;
   static const int kOptCountOffset =
       kThisPropertyAssignmentsCountOffset + kPointerSize;
+  static const int kAstNodeCountOffset = kOptCountOffset + kPointerSize;
+  static const int kDeoptCounterOffset =
+      kAstNodeCountOffset + kPointerSize;
   // Total size.
-  static const int kSize = kOptCountOffset + kPointerSize;
+  static const int kSize = kDeoptCounterOffset + kPointerSize;
 #else
   // The only reason to use smi fields instead of int fields
   // is to allow iteration without maps decoding during
@@ -5408,7 +5418,7 @@ class SharedFunctionInfo: public HeapObject {
   // word is not set and thus this word cannot be treated as pointer
   // to HeapObject during old space traversal.
   static const int kLengthOffset =
-      kDeoptCounterOffset + kPointerSize;
+      kThisPropertyAssignmentsOffset + kPointerSize;
   static const int kFormalParameterCountOffset =
       kLengthOffset + kIntSize;
 
@@ -5432,8 +5442,11 @@ class SharedFunctionInfo: public HeapObject {
   static const int kOptCountOffset =
       kThisPropertyAssignmentsCountOffset + kIntSize;
 
+  static const int kAstNodeCountOffset = kOptCountOffset + kIntSize;
+  static const int kDeoptCounterOffset = kAstNodeCountOffset + kIntSize;
+
   // Total size.
-  static const int kSize = kOptCountOffset + kIntSize;
+  static const int kSize = kDeoptCounterOffset + kIntSize;
 
 #endif
 
@@ -5480,6 +5493,8 @@ class SharedFunctionInfo: public HeapObject {
     kBoundFunction,
     kIsAnonymous,
     kNameShouldPrintAsAnonymous,
+    kDontCrankshaft,
+    kDontInline,
     kCompilerHintsCount  // Pseudo entry
   };
 
index c6a332d..25a409d 100644 (file)
@@ -481,62 +481,6 @@ class Parser::BlockState BASE_EMBEDDED {
 };
 
 
-class Parser::FunctionState BASE_EMBEDDED {
- public:
-  FunctionState(Parser* parser, Scope* scope, Isolate* isolate);
-  ~FunctionState();
-
-  int NextMaterializedLiteralIndex() {
-    return next_materialized_literal_index_++;
-  }
-  int materialized_literal_count() {
-    return next_materialized_literal_index_ - JSFunction::kLiteralsPrefixSize;
-  }
-
-  int NextHandlerIndex() { return next_handler_index_++; }
-  int handler_count() { return next_handler_index_; }
-
-  void SetThisPropertyAssignmentInfo(
-      bool only_simple_this_property_assignments,
-      Handle<FixedArray> this_property_assignments) {
-    only_simple_this_property_assignments_ =
-        only_simple_this_property_assignments;
-    this_property_assignments_ = this_property_assignments;
-  }
-  bool only_simple_this_property_assignments() {
-    return only_simple_this_property_assignments_;
-  }
-  Handle<FixedArray> this_property_assignments() {
-    return this_property_assignments_;
-  }
-
-  void AddProperty() { expected_property_count_++; }
-  int expected_property_count() { return expected_property_count_; }
-
- private:
-  // Used to assign an index to each literal that needs materialization in
-  // the function.  Includes regexp literals, and boilerplate for object and
-  // array literals.
-  int next_materialized_literal_index_;
-
-  // Used to assign a per-function index to try and catch handlers.
-  int next_handler_index_;
-
-  // Properties count estimation.
-  int expected_property_count_;
-
-  // Keeps track of assignments to properties of this. Used for
-  // optimizing constructors.
-  bool only_simple_this_property_assignments_;
-  Handle<FixedArray> this_property_assignments_;
-
-  Parser* parser_;
-  FunctionState* outer_function_state_;
-  Scope* outer_scope_;
-  unsigned saved_ast_node_id_;
-};
-
-
 Parser::FunctionState::FunctionState(Parser* parser,
                                      Scope* scope,
                                      Isolate* isolate)
@@ -548,7 +492,8 @@ Parser::FunctionState::FunctionState(Parser* parser,
       parser_(parser),
       outer_function_state_(parser->current_function_state_),
       outer_scope_(parser->top_scope_),
-      saved_ast_node_id_(isolate->ast_node_id()) {
+      saved_ast_node_id_(isolate->ast_node_id()),
+      factory_(isolate) {
   parser->top_scope_ = scope;
   parser->current_function_state_ = this;
   isolate->set_ast_node_id(AstNode::kDeclarationsId + 1);
@@ -674,8 +619,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
     }
 
     if (ok) {
-      result = new(zone()) FunctionLiteral(
-          isolate(),
+      result = factory()->NewFunctionLiteral(
           no_name,
           top_scope_,
           body,
@@ -685,8 +629,10 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
           function_state.only_simple_this_property_assignments(),
           function_state.this_property_assignments(),
           0,
+          false,  // Does not have duplicate parameters.
           FunctionLiteral::ANONYMOUS_EXPRESSION,
-          false);  // Does not have duplicate parameters.
+          false);  // Top-level literal doesn't count for the AST's properties.
+      result->set_ast_properties(factory()->visitor()->ast_properties());
     } else if (stack_overflow_) {
       isolate()->StackOverflow();
     }
@@ -1274,7 +1220,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
 
     case Token::SEMICOLON:
       Next();
-      return EmptyStatement();
+      return factory()->NewEmptyStatement();
 
     case Token::IF:
       stmt = ParseIfStatement(labels, ok);
@@ -1322,7 +1268,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
       // one must take great care not to treat it as a
       // fall-through. It is much easier just to wrap the entire
       // try-statement in a statement block and put the labels there
-      Block* result = new(zone()) Block(isolate(), labels, 1, false);
+      Block* result = factory()->NewBlock(labels, 1, false);
       Target target(&this->target_stack_, result);
       TryStatement* statement = ParseTryStatement(CHECK_OK);
       if (statement) {
@@ -1454,9 +1400,9 @@ VariableProxy* Parser::Declare(Handle<String> name,
   // a performance issue since it may lead to repeated
   // Runtime::DeclareContextSlot() calls.
   VariableProxy* proxy = declaration_scope->NewUnresolved(
-      name, scanner().location().beg_pos);
+      factory(), name, scanner().location().beg_pos);
   declaration_scope->AddDeclaration(
-      new(zone()) Declaration(proxy, mode, fun, top_scope_));
+      factory()->NewDeclaration(proxy, mode, fun, top_scope_));
 
   if ((mode == CONST || mode == CONST_HARMONY) &&
       declaration_scope->is_global_scope()) {
@@ -1564,10 +1510,11 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
   // introduced dynamically when we meet their declarations, whereas
   // other functions are set up when entering the surrounding scope.
   SharedFunctionInfoLiteral* lit =
-      new(zone()) SharedFunctionInfoLiteral(isolate(), shared);
+      factory()->NewSharedFunctionInfoLiteral(shared);
   VariableProxy* var = Declare(name, VAR, NULL, true, CHECK_OK);
-  return new(zone()) ExpressionStatement(new(zone()) Assignment(
-      isolate(), Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
+  return factory()->NewExpressionStatement(
+      factory()->NewAssignment(
+          Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
 }
 
 
@@ -1589,7 +1536,7 @@ Statement* Parser::ParseFunctionDeclaration(bool* ok) {
   // initial value upon entering the corresponding scope.
   VariableMode mode = is_extended_mode() ? LET : VAR;
   Declare(name, mode, fun, true, CHECK_OK);
-  return EmptyStatement();
+  return factory()->NewEmptyStatement();
 }
 
 
@@ -1603,7 +1550,7 @@ Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
   // (ECMA-262, 3rd, 12.2)
   //
   // Construct block expecting 16 statements.
-  Block* result = new(zone()) Block(isolate(), labels, 16, false);
+  Block* result = factory()->NewBlock(labels, 16, false);
   Target target(&this->target_stack_, result);
   Expect(Token::LBRACE, CHECK_OK);
   InitializationBlockFinder block_finder(top_scope_, target_stack_);
@@ -1626,7 +1573,7 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
   //   '{' SourceElement* '}'
 
   // Construct block expecting 16 statements.
-  Block* body = new(zone()) Block(isolate(), labels, 16, false);
+  Block* body = factory()->NewBlock(labels, 16, false);
   Scope* block_scope = NewScope(top_scope_, BLOCK_SCOPE);
 
   // Parse the statements and collect escaping labels.
@@ -1786,7 +1733,7 @@ Block* Parser::ParseVariableDeclarations(
   // is inside an initializer block, it is ignored.
   //
   // Create new block with one expected declaration.
-  Block* block = new(zone()) Block(isolate(), NULL, 1, true);
+  Block* block = factory()->NewBlock(NULL, 1, true);
   int nvars = 0;  // the number of variables declared
   Handle<String> name;
   do {
@@ -1907,7 +1854,7 @@ Block* Parser::ParseVariableDeclarations(
       // Compute the arguments for the runtime call.
       ZoneList<Expression*>* arguments = new(zone()) ZoneList<Expression*>(3);
       // We have at least 1 parameter.
-      arguments->Add(NewLiteral(name));
+      arguments->Add(factory()->NewLiteral(name));
       CallRuntime* initialize;
 
       if (is_const) {
@@ -1918,17 +1865,15 @@ Block* Parser::ParseVariableDeclarations(
         // and add it to the initialization statement block.
         // Note that the function does different things depending on
         // the number of arguments (1 or 2).
-        initialize =
-            new(zone()) CallRuntime(
-                isolate(),
-                isolate()->factory()->InitializeConstGlobal_symbol(),
-                Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
-                arguments);
+        initialize = factory()->NewCallRuntime(
+            isolate()->factory()->InitializeConstGlobal_symbol(),
+            Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
+            arguments);
       } else {
         // Add strict mode.
         // We may want to pass singleton to avoid Literal allocations.
         LanguageMode language_mode = initialization_scope->language_mode();
-        arguments->Add(NewNumberLiteral(language_mode));
+        arguments->Add(factory()->NewNumberLiteral(language_mode));
 
         // Be careful not to assign a value to the global variable if
         // we're in a with. The initialization value should not
@@ -1943,15 +1888,13 @@ Block* Parser::ParseVariableDeclarations(
         // and add it to the initialization statement block.
         // Note that the function does different things depending on
         // the number of arguments (2 or 3).
-        initialize =
-            new(zone()) CallRuntime(
-                isolate(),
-                isolate()->factory()->InitializeVarGlobal_symbol(),
-                Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
-                arguments);
+        initialize = factory()->NewCallRuntime(
+            isolate()->factory()->InitializeVarGlobal_symbol(),
+            Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
+            arguments);
       }
 
-      block->AddStatement(new(zone()) ExpressionStatement(initialize));
+      block->AddStatement(factory()->NewExpressionStatement(initialize));
     } else if (needs_init) {
       // Constant initializations always assign to the declared constant which
       // is always at the function scope level. This is only relevant for
@@ -1964,8 +1907,8 @@ Block* Parser::ParseVariableDeclarations(
       ASSERT(proxy->var() != NULL);
       ASSERT(value != NULL);
       Assignment* assignment =
-          new(zone()) Assignment(isolate(), init_op, proxy, value, position);
-      block->AddStatement(new(zone()) ExpressionStatement(assignment));
+          factory()->NewAssignment(init_op, proxy, value, position);
+      block->AddStatement(factory()->NewExpressionStatement(assignment));
       value = NULL;
     }
 
@@ -1976,10 +1919,11 @@ Block* Parser::ParseVariableDeclarations(
       // 'var' initializations are simply assignments (with all the consequences
       // if they are inside a 'with' statement - they may change a 'with' object
       // property).
-      VariableProxy* proxy = initialization_scope->NewUnresolved(name);
+      VariableProxy* proxy =
+          initialization_scope->NewUnresolved(factory(), name);
       Assignment* assignment =
-          new(zone()) Assignment(isolate(), init_op, proxy, value, position);
-      block->AddStatement(new(zone()) ExpressionStatement(assignment));
+          factory()->NewAssignment(init_op, proxy, value, position);
+      block->AddStatement(factory()->NewExpressionStatement(assignment));
     }
 
     if (fni_ != NULL) fni_->Leave();
@@ -2059,7 +2003,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
 
   // Parsed expression statement.
   ExpectSemicolon(CHECK_OK);
-  return new(zone()) ExpressionStatement(expr);
+  return factory()->NewExpressionStatement(expr);
 }
 
 
@@ -2077,10 +2021,9 @@ IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
     Next();
     else_statement = ParseStatement(labels, CHECK_OK);
   } else {
-    else_statement = EmptyStatement();
+    else_statement = factory()->NewEmptyStatement();
   }
-  return new(zone()) IfStatement(
-      isolate(), condition, then_statement, else_statement);
+  return factory()->NewIfStatement(condition, then_statement, else_statement);
 }
 
 
@@ -2110,7 +2053,7 @@ Statement* Parser::ParseContinueStatement(bool* ok) {
     return NULL;
   }
   ExpectSemicolon(CHECK_OK);
-  return new(zone()) ContinueStatement(target);
+  return factory()->NewContinueStatement(target);
 }
 
 
@@ -2129,7 +2072,7 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
   // empty statements, e.g. 'l1: l2: l3: break l2;'
   if (!label.is_null() && ContainsLabel(labels, label)) {
     ExpectSemicolon(CHECK_OK);
-    return EmptyStatement();
+    return factory()->NewEmptyStatement();
   }
   BreakableStatement* target = NULL;
   target = LookupBreakTarget(label, CHECK_OK);
@@ -2146,7 +2089,7 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
     return NULL;
   }
   ExpectSemicolon(CHECK_OK);
-  return new(zone()) BreakStatement(target);
+  return factory()->NewBreakStatement(target);
 }
 
 
@@ -2166,11 +2109,11 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
       tok == Token::RBRACE ||
       tok == Token::EOS) {
     ExpectSemicolon(CHECK_OK);
-    result = new(zone()) ReturnStatement(GetLiteralUndefined());
+    result = factory()->NewReturnStatement(GetLiteralUndefined());
   } else {
     Expression* expr = ParseExpression(true, CHECK_OK);
     ExpectSemicolon(CHECK_OK);
-    result = new(zone()) ReturnStatement(expr);
+    result = factory()->NewReturnStatement(expr);
   }
 
   // An ECMAScript program is considered syntactically incorrect if it
@@ -2183,7 +2126,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
       declaration_scope->is_eval_scope()) {
     Handle<String> type = isolate()->factory()->illegal_return_symbol();
     Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
-    return new(zone()) ExpressionStatement(throw_error);
+    return factory()->NewExpressionStatement(throw_error);
   }
   return result;
 }
@@ -2213,7 +2156,7 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
     stmt = ParseStatement(labels, CHECK_OK);
     with_scope->set_end_position(scanner().location().end_pos);
   }
-  return new(zone()) WithStatement(expr, stmt);
+  return factory()->NewWithStatement(expr, stmt);
 }
 
 
@@ -2255,7 +2198,7 @@ SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
   // SwitchStatement ::
   //   'switch' '(' Expression ')' '{' CaseClause* '}'
 
-  SwitchStatement* statement = new(zone()) SwitchStatement(isolate(), labels);
+  SwitchStatement* statement = factory()->NewSwitchStatement(labels);
   Target target(&this->target_stack_, statement);
 
   Expect(Token::SWITCH, CHECK_OK);
@@ -2291,8 +2234,7 @@ Statement* Parser::ParseThrowStatement(bool* ok) {
   Expression* exception = ParseExpression(true, CHECK_OK);
   ExpectSemicolon(CHECK_OK);
 
-  return new(zone()) ExpressionStatement(
-      new(zone()) Throw(isolate(), exception, pos));
+  return factory()->NewExpressionStatement(factory()->NewThrow(exception, pos));
 }
 
 
@@ -2379,13 +2321,10 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
     // If we have both, create an inner try/catch.
     ASSERT(catch_scope != NULL && catch_variable != NULL);
     int index = current_function_state_->NextHandlerIndex();
-    TryCatchStatement* statement = new(zone()) TryCatchStatement(index,
-                                                                 try_block,
-                                                                 catch_scope,
-                                                                 catch_variable,
-                                                                 catch_block);
+    TryCatchStatement* statement = factory()->NewTryCatchStatement(
+        index, try_block, catch_scope, catch_variable, catch_block);
     statement->set_escaping_targets(try_collector.targets());
-    try_block = new(zone()) Block(isolate(), NULL, 1, false);
+    try_block = factory()->NewBlock(NULL, 1, false);
     try_block->AddStatement(statement);
     catch_block = NULL;  // Clear to indicate it's been handled.
   }
@@ -2395,17 +2334,12 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
     ASSERT(finally_block == NULL);
     ASSERT(catch_scope != NULL && catch_variable != NULL);
     int index = current_function_state_->NextHandlerIndex();
-    result = new(zone()) TryCatchStatement(index,
-                                           try_block,
-                                           catch_scope,
-                                           catch_variable,
-                                           catch_block);
+    result = factory()->NewTryCatchStatement(
+        index, try_block, catch_scope, catch_variable, catch_block);
   } else {
     ASSERT(finally_block != NULL);
     int index = current_function_state_->NextHandlerIndex();
-    result = new(zone()) TryFinallyStatement(index,
-                                             try_block,
-                                             finally_block);
+    result = factory()->NewTryFinallyStatement(index, try_block, finally_block);
     // Combine the jump targets of the try block and the possible catch block.
     try_collector.targets()->AddAll(*catch_collector.targets());
   }
@@ -2420,7 +2354,7 @@ DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
   // DoStatement ::
   //   'do' Statement 'while' '(' Expression ')' ';'
 
-  DoWhileStatement* loop = new(zone()) DoWhileStatement(isolate(), labels);
+  DoWhileStatement* loop = factory()->NewDoWhileStatement(labels);
   Target target(&this->target_stack_, loop);
 
   Expect(Token::DO, CHECK_OK);
@@ -2451,7 +2385,7 @@ WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
   // WhileStatement ::
   //   'while' '(' Expression ')' Statement
 
-  WhileStatement* loop = new(zone()) WhileStatement(isolate(), labels);
+  WhileStatement* loop = factory()->NewWhileStatement(labels);
   Target target(&this->target_stack_, loop);
 
   Expect(Token::WHILE, CHECK_OK);
@@ -2486,8 +2420,8 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
           ParseVariableDeclarations(kForStatement, NULL, &name, CHECK_OK);
 
       if (peek() == Token::IN && !name.is_null()) {
-        VariableProxy* each = top_scope_->NewUnresolved(name);
-        ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
+        VariableProxy* each = top_scope_->NewUnresolved(factory(), name);
+        ForInStatement* loop = factory()->NewForInStatement(labels);
         Target target(&this->target_stack_, loop);
 
         Expect(Token::IN, CHECK_OK);
@@ -2496,7 +2430,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
 
         Statement* body = ParseStatement(NULL, CHECK_OK);
         loop->Initialize(each, enumerable, body);
-        Block* result = new(zone()) Block(isolate(), NULL, 2, false);
+        Block* result = factory()->NewBlock(NULL, 2, false);
         result->AddStatement(variable_statement);
         result->AddStatement(loop);
         top_scope_ = saved_scope;
@@ -2534,9 +2468,9 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
         // TODO(keuchel): Move the temporary variable to the block scope, after
         // implementing stack allocated block scoped variables.
         Variable* temp = top_scope_->DeclarationScope()->NewTemporary(name);
-        VariableProxy* temp_proxy = new(zone()) VariableProxy(isolate(), temp);
-        VariableProxy* each = top_scope_->NewUnresolved(name);
-        ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
+        VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
+        VariableProxy* each = top_scope_->NewUnresolved(factory(), name);
+        ForInStatement* loop = factory()->NewForInStatement(labels);
         Target target(&this->target_stack_, loop);
 
         Expect(Token::IN, CHECK_OK);
@@ -2544,14 +2478,11 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
         Expect(Token::RPAREN, CHECK_OK);
 
         Statement* body = ParseStatement(NULL, CHECK_OK);
-        Block* body_block = new(zone()) Block(isolate(), NULL, 3, false);
-        Assignment* assignment = new(zone()) Assignment(isolate(),
-                                                        Token::ASSIGN,
-                                                        each,
-                                                        temp_proxy,
-                                                        RelocInfo::kNoPosition);
+        Block* body_block = factory()->NewBlock(NULL, 3, false);
+        Assignment* assignment = factory()->NewAssignment(
+            Token::ASSIGN, each, temp_proxy, RelocInfo::kNoPosition);
         Statement* assignment_statement =
-            new(zone()) ExpressionStatement(assignment);
+            factory()->NewExpressionStatement(assignment);
         body_block->AddStatement(variable_statement);
         body_block->AddStatement(assignment_statement);
         body_block->AddStatement(body);
@@ -2578,7 +2509,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
               isolate()->factory()->invalid_lhs_in_for_in_symbol();
           expression = NewThrowReferenceError(type);
         }
-        ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
+        ForInStatement* loop = factory()->NewForInStatement(labels);
         Target target(&this->target_stack_, loop);
 
         Expect(Token::IN, CHECK_OK);
@@ -2595,13 +2526,13 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
         return loop;
 
       } else {
-        init = new(zone()) ExpressionStatement(expression);
+        init = factory()->NewExpressionStatement(expression);
       }
     }
   }
 
   // Standard 'for' loop
-  ForStatement* loop = new(zone()) ForStatement(isolate(), labels);
+  ForStatement* loop = factory()->NewForStatement(labels);
   Target target(&this->target_stack_, loop);
 
   // Parsed initializer at this point.
@@ -2616,7 +2547,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
   Statement* next = NULL;
   if (peek() != Token::RPAREN) {
     Expression* exp = ParseExpression(true, CHECK_OK);
-    next = new(zone()) ExpressionStatement(exp);
+    next = factory()->NewExpressionStatement(exp);
   }
   Expect(Token::RPAREN, CHECK_OK);
 
@@ -2636,7 +2567,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
     //     for (; c; n) b
     //   }
     ASSERT(init != NULL);
-    Block* result = new(zone()) Block(isolate(), NULL, 2, false);
+    Block* result = factory()->NewBlock(NULL, 2, false);
     result->AddStatement(init);
     result->AddStatement(loop);
     result->set_block_scope(for_scope);
@@ -2660,8 +2591,8 @@ Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
     Expect(Token::COMMA, CHECK_OK);
     int position = scanner().location().beg_pos;
     Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
-    result = new(zone()) BinaryOperation(
-        isolate(), Token::COMMA, result, right, position);
+    result =
+        factory()->NewBinaryOperation(Token::COMMA, result, right, position);
   }
   return result;
 }
@@ -2736,7 +2667,7 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
     fni_->Leave();
   }
 
-  return new(zone()) Assignment(isolate(), op, expression, right, pos);
+  return factory()->NewAssignment(op, expression, right, pos);
 }
 
 
@@ -2758,8 +2689,8 @@ Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
   Expect(Token::COLON, CHECK_OK);
   int right_position = scanner().peek_location().beg_pos;
   Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
-  return new(zone()) Conditional(
-      isolate(), expression, left, right, left_position, right_position);
+  return factory()->NewConditional(
+      expression, left, right, left_position, right_position);
 }
 
 
@@ -2790,41 +2721,47 @@ Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
 
         switch (op) {
           case Token::ADD:
-            x = NewNumberLiteral(x_val + y_val);
+            x = factory()->NewNumberLiteral(x_val + y_val);
             continue;
           case Token::SUB:
-            x = NewNumberLiteral(x_val - y_val);
+            x = factory()->NewNumberLiteral(x_val - y_val);
             continue;
           case Token::MUL:
-            x = NewNumberLiteral(x_val * y_val);
+            x = factory()->NewNumberLiteral(x_val * y_val);
             continue;
           case Token::DIV:
-            x = NewNumberLiteral(x_val / y_val);
+            x = factory()->NewNumberLiteral(x_val / y_val);
             continue;
-          case Token::BIT_OR:
-            x = NewNumberLiteral(DoubleToInt32(x_val) | DoubleToInt32(y_val));
+          case Token::BIT_OR: {
+            int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
+            x = factory()->NewNumberLiteral(value);
             continue;
-          case Token::BIT_AND:
-            x = NewNumberLiteral(DoubleToInt32(x_val) & DoubleToInt32(y_val));
+          }
+          case Token::BIT_AND: {
+            int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
+            x = factory()->NewNumberLiteral(value);
             continue;
-          case Token::BIT_XOR:
-            x = NewNumberLiteral(DoubleToInt32(x_val) ^ DoubleToInt32(y_val));
+          }
+          case Token::BIT_XOR: {
+            int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
+            x = factory()->NewNumberLiteral(value);
             continue;
+          }
           case Token::SHL: {
             int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
-            x = NewNumberLiteral(value);
+            x = factory()->NewNumberLiteral(value);
             continue;
           }
           case Token::SHR: {
             uint32_t shift = DoubleToInt32(y_val) & 0x1f;
             uint32_t value = DoubleToUint32(x_val) >> shift;
-            x = NewNumberLiteral(value);
+            x = factory()->NewNumberLiteral(value);
             continue;
           }
           case Token::SAR: {
             uint32_t shift = DoubleToInt32(y_val) & 0x1f;
             int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
-            x = NewNumberLiteral(value);
+            x = factory()->NewNumberLiteral(value);
             continue;
           }
           default:
@@ -2843,15 +2780,15 @@ Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
           case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
           default: break;
         }
-        x = new(zone()) CompareOperation(isolate(), cmp, x, y, position);
+        x = factory()->NewCompareOperation(cmp, x, y, position);
         if (cmp != op) {
           // The comparison was negated - add a NOT.
-          x = new(zone()) UnaryOperation(isolate(), Token::NOT, x, position);
+          x = factory()->NewUnaryOperation(Token::NOT, x, position);
         }
 
       } else {
         // We have a "normal" binary operation.
-        x = new(zone()) BinaryOperation(isolate(), op, x, y, position);
+        x = factory()->NewBinaryOperation(op, x, y, position);
       }
     }
   }
@@ -2884,7 +2821,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
         // Convert the literal to a boolean condition and negate it.
         bool condition = literal->ToBoolean()->IsTrue();
         Handle<Object> result(isolate()->heap()->ToBoolean(!condition));
-        return NewLiteral(result);
+        return factory()->NewLiteral(result);
       } else if (literal->IsNumber()) {
         // Compute some expressions involving only number literals.
         double value = literal->Number();
@@ -2892,9 +2829,9 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
           case Token::ADD:
             return expression;
           case Token::SUB:
-            return NewNumberLiteral(-value);
+            return factory()->NewNumberLiteral(-value);
           case Token::BIT_NOT:
-            return NewNumberLiteral(~DoubleToInt32(value));
+            return factory()->NewNumberLiteral(~DoubleToInt32(value));
           default:
             break;
         }
@@ -2911,7 +2848,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
       }
     }
 
-    return new(zone()) UnaryOperation(isolate(), op, expression, position);
+    return factory()->NewUnaryOperation(op, expression, position);
 
   } else if (Token::IsCountOp(op)) {
     op = Next();
@@ -2933,11 +2870,10 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
     MarkAsLValue(expression);
 
     int position = scanner().location().beg_pos;
-    return new(zone()) CountOperation(isolate(),
-                                      op,
-                                      true /* prefix */,
-                                      expression,
-                                      position);
+    return factory()->NewCountOperation(op,
+                                        true /* prefix */,
+                                        expression,
+                                        position);
 
   } else {
     return ParsePostfixExpression(ok);
@@ -2971,11 +2907,10 @@ Expression* Parser::ParsePostfixExpression(bool* ok) {
     Token::Value next = Next();
     int position = scanner().location().beg_pos;
     expression =
-        new(zone()) CountOperation(isolate(),
-                                   next,
-                                   false /* postfix */,
-                                   expression,
-                                   position);
+        factory()->NewCountOperation(next,
+                                     false /* postfix */,
+                                     expression,
+                                     position);
   }
   return expression;
 }
@@ -2998,7 +2933,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
         Consume(Token::LBRACK);
         int pos = scanner().location().beg_pos;
         Expression* index = ParseExpression(true, CHECK_OK);
-        result = new(zone()) Property(isolate(), result, index, pos);
+        result = factory()->NewProperty(result, index, pos);
         Expect(Token::RBRACK, CHECK_OK);
         break;
       }
@@ -3031,7 +2966,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
             callee->IsVariable(isolate()->factory()->eval_symbol())) {
           top_scope_->DeclarationScope()->RecordEvalCall();
         }
-        result = NewCall(result, args, pos);
+        result = factory()->NewCall(result, args, pos);
         break;
       }
 
@@ -3039,10 +2974,8 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
         Consume(Token::PERIOD);
         int pos = scanner().location().beg_pos;
         Handle<String> name = ParseIdentifierName(CHECK_OK);
-        result = new(zone()) Property(isolate(),
-                                      result,
-                                      NewLiteral(name),
-                                      pos);
+        result =
+            factory()->NewProperty(result, factory()->NewLiteral(name), pos);
         if (fni_ != NULL) fni_->PushLiteralName(name);
         break;
       }
@@ -3078,10 +3011,8 @@ Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
 
   if (!stack->is_empty()) {
     int last = stack->pop();
-    result = new(zone()) CallNew(isolate(),
-                                 result,
-                                 new(zone()) ZoneList<Expression*>(0),
-                                 last);
+    result = factory()->NewCallNew(
+        result, new(zone()) ZoneList<Expression*>(0), last);
   }
   return result;
 }
@@ -3133,7 +3064,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
         Consume(Token::LBRACK);
         int pos = scanner().location().beg_pos;
         Expression* index = ParseExpression(true, CHECK_OK);
-        result = new(zone()) Property(isolate(), result, index, pos);
+        result = factory()->NewProperty(result, index, pos);
         if (fni_ != NULL) {
           if (index->IsPropertyName()) {
             fni_->PushLiteralName(index->AsLiteral()->AsPropertyName());
@@ -3149,10 +3080,8 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
         Consume(Token::PERIOD);
         int pos = scanner().location().beg_pos;
         Handle<String> name = ParseIdentifierName(CHECK_OK);
-        result = new(zone()) Property(isolate(),
-                                      result,
-                                      NewLiteral(name),
-                                      pos);
+        result =
+            factory()->NewProperty(result, factory()->NewLiteral(name), pos);
         if (fni_ != NULL) fni_->PushLiteralName(name);
         break;
       }
@@ -3161,7 +3090,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
         // Consume one of the new prefixes (already parsed).
         ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
         int last = stack->pop();
-        result = new(zone()) CallNew(isolate(), result, args, last);
+        result = factory()->NewCallNew(result, args, last);
         break;
       }
       default:
@@ -3180,7 +3109,7 @@ DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
 
   Expect(Token::DEBUGGER, CHECK_OK);
   ExpectSemicolon(CHECK_OK);
-  return new(zone()) DebuggerStatement();
+  return factory()->NewDebuggerStatement();
 }
 
 
@@ -3245,33 +3174,31 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
   switch (peek()) {
     case Token::THIS: {
       Consume(Token::THIS);
-      result = new(zone()) VariableProxy(isolate(), top_scope_->receiver());
+      result = factory()->NewVariableProxy(top_scope_->receiver());
       break;
     }
 
     case Token::NULL_LITERAL:
       Consume(Token::NULL_LITERAL);
-      result = new(zone()) Literal(
-          isolate(), isolate()->factory()->null_value());
+      result = factory()->NewLiteral(isolate()->factory()->null_value());
       break;
 
     case Token::TRUE_LITERAL:
       Consume(Token::TRUE_LITERAL);
-      result = new(zone()) Literal(
-          isolate(), isolate()->factory()->true_value());
+      result = factory()->NewLiteral(isolate()->factory()->true_value());
       break;
 
     case Token::FALSE_LITERAL:
       Consume(Token::FALSE_LITERAL);
-      result = new(zone()) Literal(
-          isolate(), isolate()->factory()->false_value());
+      result = factory()->NewLiteral(isolate()->factory()->false_value());
       break;
 
     case Token::IDENTIFIER:
     case Token::FUTURE_STRICT_RESERVED_WORD: {
       Handle<String> name = ParseIdentifier(CHECK_OK);
       if (fni_ != NULL) fni_->PushVariableName(name);
-      result = top_scope_->NewUnresolved(name, scanner().location().beg_pos);
+      result = top_scope_->NewUnresolved(
+          factory(), name, scanner().location().beg_pos);
       break;
     }
 
@@ -3281,14 +3208,14 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
       double value = StringToDouble(isolate()->unicode_cache(),
                                     scanner().literal_ascii_string(),
                                     ALLOW_HEX | ALLOW_OCTALS);
-      result = NewNumberLiteral(value);
+      result = factory()->NewNumberLiteral(value);
       break;
     }
 
     case Token::STRING: {
       Consume(Token::STRING);
       Handle<String> symbol = GetSymbol(CHECK_OK);
-      result = NewLiteral(symbol);
+      result = factory()->NewLiteral(symbol);
       if (fni_ != NULL) fni_->PushLiteralName(symbol);
       break;
     }
@@ -3482,8 +3409,8 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
   literals->set(0, Smi::FromInt(elements_kind));
   literals->set(1, *element_values);
 
-  return new(zone()) ArrayLiteral(
-      isolate(), literals, values, literal_index, is_simple, depth);
+  return factory()->NewArrayLiteral(
+      literals, values, literal_index, is_simple, depth);
 }
 
 
@@ -3760,9 +3687,7 @@ ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
                              CHECK_OK);
     // Allow any number of parameters for compatibilty with JSC.
     // Specification only allows zero parameters for get and one for set.
-    ObjectLiteral::Property* property =
-        new(zone()) ObjectLiteral::Property(is_getter, value);
-    return property;
+    return factory()->NewObjectLiteralProperty(is_getter, value);
   } else {
     ReportUnexpectedToken(next);
     *ok = false;
@@ -3827,7 +3752,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
         }
         // Failed to parse as get/set property, so it's just a property
         // called "get" or "set".
-        key = NewLiteral(id);
+        key = factory()->NewLiteral(id);
         break;
       }
       case Token::STRING: {
@@ -3836,10 +3761,10 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
         if (fni_ != NULL) fni_->PushLiteralName(string);
         uint32_t index;
         if (!string.is_null() && string->AsArrayIndex(&index)) {
-          key = NewNumberLiteral(index);
+          key = factory()->NewNumberLiteral(index);
           break;
         }
-        key = NewLiteral(string);
+        key = factory()->NewLiteral(string);
         break;
       }
       case Token::NUMBER: {
@@ -3848,14 +3773,14 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
         double value = StringToDouble(isolate()->unicode_cache(),
                                       scanner().literal_ascii_string(),
                                       ALLOW_HEX | ALLOW_OCTALS);
-        key = NewNumberLiteral(value);
+        key = factory()->NewNumberLiteral(value);
         break;
       }
       default:
         if (Token::IsKeyword(next)) {
           Consume(next);
           Handle<String> string = GetSymbol(CHECK_OK);
-          key = NewLiteral(string);
+          key = factory()->NewLiteral(string);
         } else {
           // Unexpected token.
           Token::Value next = Next();
@@ -3910,14 +3835,13 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
                                        &is_simple,
                                        &fast_elements,
                                        &depth);
-  return new(zone()) ObjectLiteral(isolate(),
-                                   constant_properties,
-                                   properties,
-                                   literal_index,
-                                   is_simple,
-                                   fast_elements,
-                                   depth,
-                                   has_function);
+  return factory()->NewObjectLiteral(constant_properties,
+                                     properties,
+                                     literal_index,
+                                     is_simple,
+                                     fast_elements,
+                                     depth,
+                                     has_function);
 }
 
 
@@ -3936,8 +3860,7 @@ Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
   Handle<String> js_flags = NextLiteralString(TENURED);
   Next();
 
-  return new(zone()) RegExpLiteral(
-      isolate(), js_pattern, js_flags, literal_index);
+  return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index);
 }
 
 
@@ -3968,7 +3891,7 @@ ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
 class SingletonLogger : public ParserRecorder {
  public:
   SingletonLogger() : has_error_(false), start_(-1), end_(-1) { }
-  ~SingletonLogger() { }
+  virtual ~SingletonLogger() { }
 
   void Reset() { has_error_ = false; }
 
@@ -4089,6 +4012,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
   bool only_simple_this_property_assignments;
   Handle<FixedArray> this_property_assignments;
   bool has_duplicate_parameters = false;
+  AstProperties ast_properties;
   // Parse function body.
   { FunctionState function_state(this, scope, isolate());
     top_scope_->SetScopeName(function_name);
@@ -4151,7 +4075,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
       } else {
         fvar_mode = CONST;
       }
-      fvar = top_scope_->DeclareFunctionVar(function_name, fvar_mode);
+      fvar =
+          top_scope_->DeclareFunctionVar(function_name, fvar_mode, factory());
     }
 
     // Determine whether the function will be lazily compiled.
@@ -4238,14 +4163,14 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
     if (!is_lazily_compiled) {
       body = new(zone()) ZoneList<Statement*>(8);
       if (fvar != NULL) {
-        VariableProxy* fproxy = top_scope_->NewUnresolved(function_name);
+        VariableProxy* fproxy =
+            top_scope_->NewUnresolved(factory(), function_name);
         fproxy->BindTo(fvar);
-        body->Add(new(zone()) ExpressionStatement(
-            new(zone()) Assignment(isolate(),
-                                   fvar_init_op,
-                                   fproxy,
-                                   new(zone()) ThisFunction(isolate()),
-                                   RelocInfo::kNoPosition)));
+        body->Add(factory()->NewExpressionStatement(
+            factory()->NewAssignment(fvar_init_op,
+                                     fproxy,
+                                     factory()->NewThisFunction(),
+                                     RelocInfo::kNoPosition)));
       }
       ParseSourceElements(body, Token::RBRACE, CHECK_OK);
 
@@ -4306,6 +4231,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
                         scope->end_position(),
                         CHECK_OK);
     }
+    ast_properties = *factory()->visitor()->ast_properties();
   }
 
   if (is_extended_mode()) {
@@ -4313,19 +4239,20 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
   }
 
   FunctionLiteral* function_literal =
-      new(zone()) FunctionLiteral(isolate(),
-                                  function_name,
-                                  scope,
-                                  body,
-                                  materialized_literal_count,
-                                  expected_property_count,
-                                  handler_count,
-                                  only_simple_this_property_assignments,
-                                  this_property_assignments,
-                                  num_parameters,
-                                  type,
-                                  has_duplicate_parameters);
+      factory()->NewFunctionLiteral(function_name,
+                                    scope,
+                                    body,
+                                    materialized_literal_count,
+                                    expected_property_count,
+                                    handler_count,
+                                    only_simple_this_property_assignments,
+                                    this_property_assignments,
+                                    num_parameters,
+                                    has_duplicate_parameters,
+                                    type,
+                                    true);
   function_literal->set_function_token_position(function_token_position);
+  function_literal->set_ast_properties(&ast_properties);
 
   if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
   return function_literal;
@@ -4395,7 +4322,7 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
   }
 
   // We have a valid intrinsics call or a call to a builtin.
-  return new(zone()) CallRuntime(isolate(), name, function, args);
+  return factory()->NewCallRuntime(name, function, args);
 }
 
 
@@ -4451,17 +4378,12 @@ void Parser::ExpectSemicolon(bool* ok) {
 
 
 Literal* Parser::GetLiteralUndefined() {
-  return NewLiteral(isolate()->factory()->undefined_value());
+  return factory()->NewLiteral(isolate()->factory()->undefined_value());
 }
 
 
 Literal* Parser::GetLiteralTheHole() {
-  return NewLiteral(isolate()->factory()->the_hole_value());
-}
-
-
-Literal* Parser::GetLiteralNumber(double value) {
-  return NewNumberLiteral(value);
+  return factory()->NewLiteral(isolate()->factory()->the_hole_value());
 }
 
 
@@ -4639,11 +4561,6 @@ void Parser::RegisterTargetUse(Label* target, Target* stop) {
 }
 
 
-Literal* Parser::NewNumberLiteral(double number) {
-  return NewLiteral(isolate()->factory()->NewNumber(number, TENURED));
-}
-
-
 Expression* Parser::NewThrowReferenceError(Handle<String> type) {
   return NewThrowError(isolate()->factory()->MakeReferenceError_symbol(),
                        type, HandleVector<Object>(NULL, 0));
@@ -4687,15 +4604,11 @@ Expression* Parser::NewThrowError(Handle<String> constructor,
       elements, FAST_ELEMENTS, TENURED);
 
   ZoneList<Expression*>* args = new(zone()) ZoneList<Expression*>(2);
-  args->Add(NewLiteral(type));
-  args->Add(NewLiteral(array));
-  CallRuntime* call_constructor = new(zone()) CallRuntime(isolate(),
-                                                          constructor,
-                                                          NULL,
-                                                          args);
-  return new(zone()) Throw(isolate(),
-                           call_constructor,
-                           scanner().location().beg_pos);
+  args->Add(factory()->NewLiteral(type));
+  args->Add(factory()->NewLiteral(array));
+  CallRuntime* call_constructor =
+      factory()->NewCallRuntime(constructor, NULL, args);
+  return factory()->NewThrow(call_constructor, scanner().location().beg_pos);
 }
 
 // ----------------------------------------------------------------------------
@@ -5667,7 +5580,7 @@ bool ParserApi::Parse(CompilationInfo* info, int parsing_flags) {
     parsing_flags |= EXTENDED_MODE;
   }
   if (FLAG_allow_natives_syntax || info->is_native()) {
-    // We requre %identifier(..) syntax.
+    // We require %identifier(..) syntax.
     parsing_flags |= kAllowNativesSyntax;
   }
   if (info->is_lazy()) {
index 16c2eff..bc2af61 100644 (file)
@@ -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:
@@ -435,9 +435,8 @@ class Parser {
          v8::Extension* extension,
          ScriptDataImpl* pre_data);
   virtual ~Parser() {
-    if (reusable_preparser_ != NULL) {
-      delete reusable_preparser_;
-    }
+    delete reusable_preparser_;
+    reusable_preparser_ = NULL;
   }
 
   // Returns NULL if parsing failed.
@@ -477,7 +476,69 @@ class Parser {
   };
 
   class BlockState;
-  class FunctionState;
+
+  class FunctionState BASE_EMBEDDED {
+   public:
+    FunctionState(Parser* parser,
+                  Scope* scope,
+                  Isolate* isolate);
+    ~FunctionState();
+
+    int NextMaterializedLiteralIndex() {
+      return next_materialized_literal_index_++;
+    }
+    int materialized_literal_count() {
+      return next_materialized_literal_index_ - JSFunction::kLiteralsPrefixSize;
+    }
+
+    int NextHandlerIndex() { return next_handler_index_++; }
+    int handler_count() { return next_handler_index_; }
+
+    void SetThisPropertyAssignmentInfo(
+        bool only_simple_this_property_assignments,
+        Handle<FixedArray> this_property_assignments) {
+      only_simple_this_property_assignments_ =
+          only_simple_this_property_assignments;
+      this_property_assignments_ = this_property_assignments;
+    }
+    bool only_simple_this_property_assignments() {
+      return only_simple_this_property_assignments_;
+    }
+    Handle<FixedArray> this_property_assignments() {
+      return this_property_assignments_;
+    }
+
+    void AddProperty() { expected_property_count_++; }
+    int expected_property_count() { return expected_property_count_; }
+
+    AstNodeFactory<AstConstructionVisitor>* factory() { return &factory_; }
+
+   private:
+    // Used to assign an index to each literal that needs materialization in
+    // the function.  Includes regexp literals, and boilerplate for object and
+    // array literals.
+    int next_materialized_literal_index_;
+
+    // Used to assign a per-function index to try and catch handlers.
+    int next_handler_index_;
+
+    // Properties count estimation.
+    int expected_property_count_;
+
+    // Keeps track of assignments to properties of this. Used for
+    // optimizing constructors.
+    bool only_simple_this_property_assignments_;
+    Handle<FixedArray> this_property_assignments_;
+
+    Parser* parser_;
+    FunctionState* outer_function_state_;
+    Scope* outer_scope_;
+    int saved_ast_node_id_;
+    AstNodeFactory<AstConstructionVisitor> factory_;
+  };
+
+
+
 
   FunctionLiteral* ParseLazy(CompilationInfo* info,
                              UC16CharacterStream* source,
@@ -651,7 +712,6 @@ class Parser {
   // Get odd-ball literals.
   Literal* GetLiteralUndefined();
   Literal* GetLiteralTheHole();
-  Literal* GetLiteralNumber(double value);
 
   Handle<String> ParseIdentifier(bool* ok);
   Handle<String> ParseIdentifierOrStrictReservedWord(
@@ -699,31 +759,12 @@ class Parser {
 
   // Factory methods.
 
-  Statement* EmptyStatement() {
-    static v8::internal::EmptyStatement* empty =
-        ::new v8::internal::EmptyStatement();
-    return empty;
-  }
-
   Scope* NewScope(Scope* parent, ScopeType type);
 
   Handle<String> LookupSymbol(int symbol_id);
 
   Handle<String> LookupCachedSymbol(int symbol_id);
 
-  Expression* NewCall(Expression* expression,
-                      ZoneList<Expression*>* arguments,
-                      int pos) {
-    return new(zone()) Call(isolate(), expression, arguments, pos);
-  }
-
-  inline Literal* NewLiteral(Handle<Object> handle) {
-    return new(zone()) Literal(isolate(), handle);
-  }
-
-  // Create a number literal.
-  Literal* NewNumberLiteral(double value);
-
   // Generate AST node that throw a ReferenceError with the given type.
   Expression* NewThrowReferenceError(Handle<String> type);
 
@@ -746,6 +787,10 @@ class Parser {
   preparser::PreParser::PreParseResult LazyParseFunctionLiteral(
        SingletonLogger* logger);
 
+  AstNodeFactory<AstConstructionVisitor>* factory() {
+    return current_function_state_->factory();
+  }
+
   Isolate* isolate_;
   ZoneList<Handle<String> > symbol_cache_;
 
index a70cd82..8e0c637 100644 (file)
@@ -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:
@@ -42,12 +42,18 @@ class Processor: public AstVisitor {
       : result_(result),
         result_assigned_(false),
         is_set_(false),
-        in_try_(false) {
-  }
+        in_try_(false),
+        factory_(isolate()) { }
+
+  virtual ~Processor() { }
 
   void Process(ZoneList<Statement*>* statements);
   bool result_assigned() const { return result_assigned_; }
 
+  AstNodeFactory<AstNullVisitor>* factory() {
+    return &factory_;
+  }
+
  private:
   Variable* result_;
 
@@ -64,15 +70,13 @@ class Processor: public AstVisitor {
   bool is_set_;
   bool in_try_;
 
+  AstNodeFactory<AstNullVisitor> factory_;
+
   Expression* SetResult(Expression* value) {
     result_assigned_ = true;
-    Zone* zone = isolate()->zone();
-    VariableProxy* result_proxy = new(zone) VariableProxy(isolate(), result_);
-    return new(zone) Assignment(isolate(),
-                                Token::ASSIGN,
-                                result_proxy,
-                                value,
-                                RelocInfo::kNoPosition);
+    VariableProxy* result_proxy = factory()->NewVariableProxy(result_);
+    return factory()->NewAssignment(
+        Token::ASSIGN, result_proxy, value, RelocInfo::kNoPosition);
   }
 
   // Node visitors.
@@ -237,8 +241,6 @@ bool Rewriter::Rewrite(CompilationInfo* info) {
 
     if (processor.result_assigned()) {
       ASSERT(function->end_position() != RelocInfo::kNoPosition);
-      Isolate* isolate = info->isolate();
-      Zone* zone = isolate->zone();
       // Set the position of the assignment statement one character past the
       // source code, such that it definitely is not in the source code range
       // of an immediate inner scope. For example in
@@ -246,10 +248,11 @@ bool Rewriter::Rewrite(CompilationInfo* info) {
       // the end position of the function generated for executing the eval code
       // coincides with the end of the with scope which is the position of '1'.
       int position = function->end_position();
-      VariableProxy* result_proxy = new(zone) VariableProxy(
-          isolate, result->name(), false, position);
+      VariableProxy* result_proxy = processor.factory()->NewVariableProxy(
+          result->name(), false, position);
       result_proxy->BindTo(result);
-      Statement* result_statement = new(zone) ReturnStatement(result_proxy);
+      Statement* result_statement =
+          processor.factory()->NewReturnStatement(result_proxy);
       result_statement->set_statement_pos(position);
       body->Add(result_statement);
     }
index a7ff287..35d804d 100644 (file)
@@ -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:
@@ -272,8 +272,11 @@ bool Scope::Analyze(CompilationInfo* info) {
     top = top->outer_scope();
   }
 
-  // Allocated the variables.
-  top->AllocateVariables(info->global_scope());
+  // Allocate the variables.
+  {
+    AstNodeFactory<AstNullVisitor> ast_node_factory(info->isolate());
+    top->AllocateVariables(info->global_scope(), &ast_node_factory);
+  }
 
 #ifdef DEBUG
   if (info->isolate()->bootstrapper()->IsActive()
@@ -415,7 +418,8 @@ Variable* Scope::LocalLookup(Handle<String> name) {
 }
 
 
-Variable* Scope::LookupFunctionVar(Handle<String> name) {
+Variable* Scope::LookupFunctionVar(Handle<String> name,
+                                   AstNodeFactory<AstNullVisitor>* factory) {
   if (function_ != NULL && function_->name().is_identical_to(name)) {
     return function_->var();
   } else if (!scope_info_.is_null()) {
@@ -423,7 +427,7 @@ Variable* Scope::LookupFunctionVar(Handle<String> name) {
     VariableMode mode;
     int index = scope_info_->FunctionContextSlotIndex(*name, &mode);
     if (index < 0) return NULL;
-    Variable* var = DeclareFunctionVar(name, mode);
+    Variable* var = DeclareFunctionVar(name, mode, factory);
     var->AllocateTo(Variable::CONTEXT, index);
     return var;
   } else {
@@ -443,15 +447,6 @@ Variable* Scope::Lookup(Handle<String> name) {
 }
 
 
-Variable* Scope::DeclareFunctionVar(Handle<String> name, VariableMode mode) {
-  ASSERT(is_function_scope() && function_ == NULL);
-  Variable* function_var = new Variable(
-      this, name, mode, true, Variable::NORMAL, kCreatedInitialized);
-  function_ = new(isolate_->zone()) VariableProxy(isolate_, function_var);
-  return function_var;
-}
-
-
 void Scope::DeclareParameter(Handle<String> name, VariableMode mode) {
   ASSERT(!already_resolved());
   ASSERT(is_function_scope());
@@ -489,18 +484,6 @@ Variable* Scope::DeclareGlobal(Handle<String> name) {
 }
 
 
-VariableProxy* Scope::NewUnresolved(Handle<String> name, int position) {
-  // Note that we must not share the unresolved variables with
-  // the same name because they may be removed selectively via
-  // RemoveUnresolved().
-  ASSERT(!already_resolved());
-  VariableProxy* proxy = new(isolate_->zone()) VariableProxy(
-      isolate_, name, false, position);
-  unresolved_.Add(proxy);
-  return proxy;
-}
-
-
 void Scope::RemoveUnresolved(VariableProxy* var) {
   // Most likely (always?) any variable we want to remove
   // was just added before, so we search backwards.
@@ -623,7 +606,8 @@ void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals,
 }
 
 
-void Scope::AllocateVariables(Scope* global_scope) {
+void Scope::AllocateVariables(Scope* global_scope,
+                              AstNodeFactory<AstNullVisitor>* factory) {
   // 1) Propagate scope information.
   bool outer_scope_calls_non_strict_eval = false;
   if (outer_scope_ != NULL) {
@@ -634,7 +618,7 @@ void Scope::AllocateVariables(Scope* global_scope) {
   PropagateScopeInfo(outer_scope_calls_non_strict_eval);
 
   // 2) Resolve variables.
-  ResolveVariablesRecursively(global_scope);
+  ResolveVariablesRecursively(global_scope, factory);
 
   // 3) Allocate variables.
   AllocateVariablesRecursively();
@@ -897,7 +881,8 @@ Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) {
 
 
 Variable* Scope::LookupRecursive(Handle<String> name,
-                                 BindingKind* binding_kind) {
+                                 BindingKind* binding_kind,
+                                 AstNodeFactory<AstNullVisitor>* factory) {
   ASSERT(binding_kind != NULL);
   // Try to find the variable in this scope.
   Variable* var = LocalLookup(name);
@@ -914,11 +899,11 @@ Variable* Scope::LookupRecursive(Handle<String> name,
   // if any. We can do this for all scopes, since the function variable is
   // only present - if at all - for function scopes.
   *binding_kind = UNBOUND;
-  var = LookupFunctionVar(name);
+  var = LookupFunctionVar(name, factory);
   if (var != NULL) {
     *binding_kind = BOUND;
   } else if (outer_scope_ != NULL) {
-    var = outer_scope_->LookupRecursive(name, binding_kind);
+    var = outer_scope_->LookupRecursive(name, binding_kind, factory);
     if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) {
       var->ForceContextAllocation();
     }
@@ -951,7 +936,8 @@ Variable* Scope::LookupRecursive(Handle<String> name,
 
 
 void Scope::ResolveVariable(Scope* global_scope,
-                            VariableProxy* proxy) {
+                            VariableProxy* proxy,
+                            AstNodeFactory<AstNullVisitor>* factory) {
   ASSERT(global_scope == NULL || global_scope->is_global_scope());
 
   // If the proxy is already resolved there's nothing to do
@@ -960,7 +946,7 @@ void Scope::ResolveVariable(Scope* global_scope,
 
   // Otherwise, try to resolve the variable.
   BindingKind binding_kind;
-  Variable* var = LookupRecursive(proxy->name(), &binding_kind);
+  Variable* var = LookupRecursive(proxy->name(), &binding_kind, factory);
   switch (binding_kind) {
     case BOUND:
       // We found a variable binding.
@@ -1001,17 +987,19 @@ void Scope::ResolveVariable(Scope* global_scope,
 }
 
 
-void Scope::ResolveVariablesRecursively(Scope* global_scope) {
+void Scope::ResolveVariablesRecursively(
+    Scope* global_scope,
+    AstNodeFactory<AstNullVisitor>* factory) {
   ASSERT(global_scope == NULL || global_scope->is_global_scope());
 
   // Resolve unresolved variables for this scope.
   for (int i = 0; i < unresolved_.length(); i++) {
-    ResolveVariable(global_scope, unresolved_[i]);
+    ResolveVariable(global_scope, unresolved_[i], factory);
   }
 
   // Resolve unresolved variables for inner scopes.
   for (int i = 0; i < inner_scopes_.length(); i++) {
-    inner_scopes_[i]->ResolveVariablesRecursively(global_scope);
+    inner_scopes_[i]->ResolveVariablesRecursively(global_scope, factory);
   }
 }
 
index af0449e..06202c4 100644 (file)
@@ -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:
@@ -115,7 +115,8 @@ class Scope: public ZoneObject {
   // between this scope and the outer scope. (ECMA-262, 3rd., requires that
   // the name of named function literal is kept in an intermediate scope
   // in between this scope and the next outer scope.)
-  Variable* LookupFunctionVar(Handle<String> name);
+  Variable* LookupFunctionVar(Handle<String> name,
+                              AstNodeFactory<AstNullVisitor>* factory);
 
   // Lookup a variable in this scope or outer scopes.
   // Returns the variable or NULL if not found.
@@ -124,7 +125,16 @@ class Scope: public ZoneObject {
   // Declare the function variable for a function literal. This variable
   // is in an intermediate scope between this function scope and the the
   // outer scope. Only possible for function scopes; at most one variable.
-  Variable* DeclareFunctionVar(Handle<String> name, VariableMode mode);
+  template<class Visitor>
+  Variable* DeclareFunctionVar(Handle<String> name,
+                               VariableMode mode,
+                               AstNodeFactory<Visitor>* factory) {
+    ASSERT(is_function_scope() && function_ == NULL);
+    Variable* function_var = new Variable(
+        this, name, mode, true, Variable::NORMAL, kCreatedInitialized);
+    function_ = factory->NewVariableProxy(function_var);
+    return function_var;
+  }
 
   // Declare a parameter in this scope.  When there are duplicated
   // parameters the rightmost one 'wins'.  However, the implementation
@@ -144,8 +154,18 @@ class Scope: public ZoneObject {
   Variable* DeclareGlobal(Handle<String> name);
 
   // Create a new unresolved variable.
-  VariableProxy* NewUnresolved(Handle<String> name,
-                               int position = RelocInfo::kNoPosition);
+  template<class Visitor>
+  VariableProxy* NewUnresolved(AstNodeFactory<Visitor>* factory,
+                               Handle<String> name,
+                               int position = RelocInfo::kNoPosition) {
+    // Note that we must not share the unresolved variables with
+    // the same name because they may be removed selectively via
+    // RemoveUnresolved().
+    ASSERT(!already_resolved());
+    VariableProxy* proxy = factory->NewVariableProxy(name, false, position);
+    unresolved_.Add(proxy);
+    return proxy;
+  }
 
   // Remove a unresolved variable. During parsing, an unresolved variable
   // may have been added optimistically, but then only the variable name
@@ -332,7 +352,8 @@ class Scope: public ZoneObject {
   // In the case of code compiled and run using 'eval', the context
   // parameter is the context in which eval was called.  In all other
   // cases the context parameter is an empty handle.
-  void AllocateVariables(Scope* global_scope);
+  void AllocateVariables(Scope* global_scope,
+                         AstNodeFactory<AstNullVisitor>* factory);
 
   // Current number of var or const locals.
   int num_var_or_const() { return num_var_or_const_; }
@@ -519,10 +540,13 @@ class Scope: public ZoneObject {
   // scope. If the code is executed because of a call to 'eval', the context
   // parameter should be set to the calling context of 'eval'.
   Variable* LookupRecursive(Handle<String> name,
-                            BindingKind* binding_kind);
+                            BindingKind* binding_kind,
+                            AstNodeFactory<AstNullVisitor>* factory);
   void ResolveVariable(Scope* global_scope,
-                       VariableProxy* proxy);
-  void ResolveVariablesRecursively(Scope* global_scope);
+                       VariableProxy* proxy,
+                       AstNodeFactory<AstNullVisitor>* factory);
+  void ResolveVariablesRecursively(Scope* global_scope,
+                                   AstNodeFactory<AstNullVisitor>* factory);
 
   // Scope analysis.
   bool PropagateScopeInfo(bool outer_scope_calls_non_strict_eval);
index 2aa7207..80c7fdf 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 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:
@@ -40,7 +40,8 @@ TEST(List) {
   CHECK_EQ(0, list->length());
 
   ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
-  AstNode* node = new(ZONE) EmptyStatement();
+  AstNodeFactory<AstNullVisitor> factory(Isolate::Current());
+  AstNode* node = factory.NewEmptyStatement();
   list->Add(node);
   CHECK_EQ(1, list->length());
   CHECK_EQ(node, list->at(0));