Assign bailout and type feedback IDs in a post-pass
authorwingo@igalia.com <wingo@igalia.com>
Tue, 21 Oct 2014 12:16:37 +0000 (12:16 +0000)
committerwingo@igalia.com <wingo@igalia.com>
Tue, 21 Oct 2014 12:16:37 +0000 (12:16 +0000)
This will allow us to move expressions from one function to another, for
example when the parser determines that a given cover grammar instance
is actually the default value initializer for an arrow function.

This is a re-land of https://codereview.chromium.org/636403003/ with a
fix for the arm64 code generator.

R=svenpanne@chromium.org
BUG=

Review URL: https://codereview.chromium.org/663373003

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

23 files changed:
BUILD.gn
src/arm64/full-codegen-arm64.cc
src/ast-numbering.cc [new file with mode: 0644]
src/ast-numbering.h [new file with mode: 0644]
src/ast-value-factory.h
src/ast.cc
src/ast.h
src/compiler.cc
src/compiler.h
src/compiler/js-inlining.cc
src/full-codegen.cc
src/hydrogen.cc
src/parser.cc
src/preparser.cc
src/preparser.h
src/rewriter.cc
src/scopes.cc
test/cctest/compiler/function-tester.h
test/cctest/compiler/test-codegen-deopt.cc
test/cctest/compiler/test-pipeline.cc
test/cctest/test-ast.cc
test/cctest/test-parsing.cc
tools/gyp/v8.gyp

index c8b0292..01972a0 100644 (file)
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -433,6 +433,8 @@ source_set("v8_base") {
     "src/assembler.h",
     "src/assert-scope.h",
     "src/assert-scope.cc",
+    "src/ast-numbering.cc",
+    "src/ast-numbering.h",
     "src/ast-value-factory.cc",
     "src/ast-value-factory.h",
     "src/ast.cc",
index fb698a3..0b7cfa0 100644 (file)
@@ -299,24 +299,24 @@ void FullCodeGenerator::Generate() {
       }
       VisitDeclarations(scope()->declarations());
     }
-  }
 
-  { Comment cmnt(masm_, "[ Stack check");
-    PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
-    Label ok;
-    DCHECK(jssp.Is(__ StackPointer()));
-    __ CompareRoot(jssp, Heap::kStackLimitRootIndex);
-    __ B(hs, &ok);
-    PredictableCodeSizeScope predictable(masm_,
-                                         Assembler::kCallSizeWithRelocation);
-    __ Call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET);
-    __ Bind(&ok);
-  }
+    { Comment cmnt(masm_, "[ Stack check");
+      PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
+      Label ok;
+      DCHECK(jssp.Is(__ StackPointer()));
+      __ CompareRoot(jssp, Heap::kStackLimitRootIndex);
+      __ B(hs, &ok);
+      PredictableCodeSizeScope predictable(masm_,
+                                           Assembler::kCallSizeWithRelocation);
+      __ Call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET);
+      __ Bind(&ok);
+    }
 
-  { Comment cmnt(masm_, "[ Body");
-    DCHECK(loop_depth() == 0);
-    VisitStatements(function()->body());
-    DCHECK(loop_depth() == 0);
+    { Comment cmnt(masm_, "[ Body");
+      DCHECK(loop_depth() == 0);
+      VisitStatements(function()->body());
+      DCHECK(loop_depth() == 0);
+    }
   }
 
   // Always emit a 'return undefined' in case control fell off the end of
diff --git a/src/ast-numbering.cc b/src/ast-numbering.cc
new file mode 100644 (file)
index 0000000..e878424
--- /dev/null
@@ -0,0 +1,416 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#include "src/ast.h"
+#include "src/ast-numbering.h"
+#include "src/compiler.h"
+#include "src/scopes.h"
+
+namespace v8 {
+namespace internal {
+
+
+class AstNumberingVisitor FINAL : public AstVisitor {
+ public:
+  explicit AstNumberingVisitor(Zone* zone)
+      : AstVisitor(), next_id_(BailoutId::FirstUsable().ToInt()) {
+    InitializeAstVisitor(zone);
+  }
+
+  void Renumber(FunctionLiteral* node);
+
+ private:
+// AST node visitor interface.
+#define DEFINE_VISIT(type) virtual void Visit##type(type* node);
+  AST_NODE_LIST(DEFINE_VISIT)
+#undef DEFINE_VISIT
+
+  void VisitStatements(ZoneList<Statement*>* statements);
+  void VisitDeclarations(ZoneList<Declaration*>* declarations);
+  void VisitArguments(ZoneList<Expression*>* arguments);
+  void VisitObjectLiteralProperty(ObjectLiteralProperty* property);
+
+  int ReserveIdRange(int n) {
+    int tmp = next_id_;
+    next_id_ += n;
+    return tmp;
+  }
+
+  int next_id_;
+
+  DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
+  DISALLOW_COPY_AND_ASSIGN(AstNumberingVisitor);
+};
+
+
+void AstNumberingVisitor::VisitVariableDeclaration(VariableDeclaration* node) {
+  VisitVariableProxy(node->proxy());
+}
+
+
+void AstNumberingVisitor::VisitExportDeclaration(ExportDeclaration* node) {
+  VisitVariableProxy(node->proxy());
+}
+
+
+void AstNumberingVisitor::VisitModuleUrl(ModuleUrl* node) {}
+
+
+void AstNumberingVisitor::VisitEmptyStatement(EmptyStatement* node) {}
+
+
+void AstNumberingVisitor::VisitContinueStatement(ContinueStatement* node) {}
+
+
+void AstNumberingVisitor::VisitBreakStatement(BreakStatement* node) {}
+
+
+void AstNumberingVisitor::VisitDebuggerStatement(DebuggerStatement* node) {
+  node->set_base_id(ReserveIdRange(DebuggerStatement::num_ids()));
+}
+
+
+void AstNumberingVisitor::VisitNativeFunctionLiteral(
+    NativeFunctionLiteral* node) {
+  node->set_base_id(ReserveIdRange(NativeFunctionLiteral::num_ids()));
+}
+
+
+void AstNumberingVisitor::VisitLiteral(Literal* node) {
+  node->set_base_id(ReserveIdRange(Literal::num_ids()));
+}
+
+
+void AstNumberingVisitor::VisitRegExpLiteral(RegExpLiteral* node) {
+  node->set_base_id(ReserveIdRange(RegExpLiteral::num_ids()));
+}
+
+
+void AstNumberingVisitor::VisitVariableProxy(VariableProxy* node) {
+  node->set_base_id(ReserveIdRange(VariableProxy::num_ids()));
+}
+
+
+void AstNumberingVisitor::VisitThisFunction(ThisFunction* node) {
+  node->set_base_id(ReserveIdRange(ThisFunction::num_ids()));
+}
+
+
+void AstNumberingVisitor::VisitSuperReference(SuperReference* node) {
+  node->set_base_id(ReserveIdRange(SuperReference::num_ids()));
+  Visit(node->this_var());
+}
+
+
+void AstNumberingVisitor::VisitModuleDeclaration(ModuleDeclaration* node) {
+  VisitVariableProxy(node->proxy());
+  Visit(node->module());
+}
+
+
+void AstNumberingVisitor::VisitImportDeclaration(ImportDeclaration* node) {
+  VisitVariableProxy(node->proxy());
+  Visit(node->module());
+}
+
+
+void AstNumberingVisitor::VisitModuleVariable(ModuleVariable* node) {
+  Visit(node->proxy());
+}
+
+
+void AstNumberingVisitor::VisitModulePath(ModulePath* node) {
+  Visit(node->module());
+}
+
+
+void AstNumberingVisitor::VisitModuleStatement(ModuleStatement* node) {
+  Visit(node->body());
+}
+
+
+void AstNumberingVisitor::VisitExpressionStatement(ExpressionStatement* node) {
+  Visit(node->expression());
+}
+
+
+void AstNumberingVisitor::VisitReturnStatement(ReturnStatement* node) {
+  Visit(node->expression());
+}
+
+
+void AstNumberingVisitor::VisitYield(Yield* node) {
+  node->set_base_id(ReserveIdRange(Yield::num_ids()));
+  Visit(node->generator_object());
+  Visit(node->expression());
+}
+
+
+void AstNumberingVisitor::VisitThrow(Throw* node) {
+  node->set_base_id(ReserveIdRange(Throw::num_ids()));
+  Visit(node->exception());
+}
+
+
+void AstNumberingVisitor::VisitUnaryOperation(UnaryOperation* node) {
+  node->set_base_id(ReserveIdRange(UnaryOperation::num_ids()));
+  Visit(node->expression());
+}
+
+
+void AstNumberingVisitor::VisitCountOperation(CountOperation* node) {
+  node->set_base_id(ReserveIdRange(CountOperation::num_ids()));
+  Visit(node->expression());
+}
+
+
+void AstNumberingVisitor::VisitBlock(Block* node) {
+  node->set_base_id(ReserveIdRange(Block::num_ids()));
+  if (node->scope() != NULL) VisitDeclarations(node->scope()->declarations());
+  VisitStatements(node->statements());
+}
+
+
+void AstNumberingVisitor::VisitFunctionDeclaration(FunctionDeclaration* node) {
+  VisitVariableProxy(node->proxy());
+  VisitFunctionLiteral(node->fun());
+}
+
+
+void AstNumberingVisitor::VisitModuleLiteral(ModuleLiteral* node) {
+  VisitBlock(node->body());
+}
+
+
+void AstNumberingVisitor::VisitCallRuntime(CallRuntime* node) {
+  node->set_base_id(ReserveIdRange(CallRuntime::num_ids()));
+  VisitArguments(node->arguments());
+}
+
+
+void AstNumberingVisitor::VisitWithStatement(WithStatement* node) {
+  Visit(node->expression());
+  Visit(node->statement());
+}
+
+
+void AstNumberingVisitor::VisitDoWhileStatement(DoWhileStatement* node) {
+  node->set_base_id(ReserveIdRange(DoWhileStatement::num_ids()));
+  Visit(node->body());
+  Visit(node->cond());
+}
+
+
+void AstNumberingVisitor::VisitWhileStatement(WhileStatement* node) {
+  node->set_base_id(ReserveIdRange(WhileStatement::num_ids()));
+  Visit(node->cond());
+  Visit(node->body());
+}
+
+
+void AstNumberingVisitor::VisitTryCatchStatement(TryCatchStatement* node) {
+  Visit(node->try_block());
+  Visit(node->catch_block());
+}
+
+
+void AstNumberingVisitor::VisitTryFinallyStatement(TryFinallyStatement* node) {
+  Visit(node->try_block());
+  Visit(node->finally_block());
+}
+
+
+void AstNumberingVisitor::VisitProperty(Property* node) {
+  node->set_base_id(ReserveIdRange(Property::num_ids()));
+  Visit(node->key());
+  Visit(node->obj());
+}
+
+
+void AstNumberingVisitor::VisitAssignment(Assignment* node) {
+  node->set_base_id(ReserveIdRange(Assignment::num_ids()));
+  if (node->is_compound()) VisitBinaryOperation(node->binary_operation());
+  Visit(node->target());
+  Visit(node->value());
+}
+
+
+void AstNumberingVisitor::VisitBinaryOperation(BinaryOperation* node) {
+  node->set_base_id(ReserveIdRange(BinaryOperation::num_ids()));
+  Visit(node->left());
+  Visit(node->right());
+}
+
+
+void AstNumberingVisitor::VisitCompareOperation(CompareOperation* node) {
+  node->set_base_id(ReserveIdRange(CompareOperation::num_ids()));
+  Visit(node->left());
+  Visit(node->right());
+}
+
+
+void AstNumberingVisitor::VisitForInStatement(ForInStatement* node) {
+  node->set_base_id(ReserveIdRange(ForInStatement::num_ids()));
+  Visit(node->each());
+  Visit(node->enumerable());
+  Visit(node->body());
+}
+
+
+void AstNumberingVisitor::VisitForOfStatement(ForOfStatement* node) {
+  node->set_base_id(ReserveIdRange(ForOfStatement::num_ids()));
+  Visit(node->assign_iterator());
+  Visit(node->next_result());
+  Visit(node->result_done());
+  Visit(node->assign_each());
+  Visit(node->body());
+}
+
+
+void AstNumberingVisitor::VisitConditional(Conditional* node) {
+  node->set_base_id(ReserveIdRange(Conditional::num_ids()));
+  Visit(node->condition());
+  Visit(node->then_expression());
+  Visit(node->else_expression());
+}
+
+
+void AstNumberingVisitor::VisitIfStatement(IfStatement* node) {
+  node->set_base_id(ReserveIdRange(IfStatement::num_ids()));
+  Visit(node->condition());
+  Visit(node->then_statement());
+  if (node->HasElseStatement()) {
+    Visit(node->else_statement());
+  }
+}
+
+
+void AstNumberingVisitor::VisitSwitchStatement(SwitchStatement* node) {
+  node->set_base_id(ReserveIdRange(SwitchStatement::num_ids()));
+  Visit(node->tag());
+  ZoneList<CaseClause*>* cases = node->cases();
+  for (int i = 0; i < cases->length(); i++) {
+    VisitCaseClause(cases->at(i));
+  }
+}
+
+
+void AstNumberingVisitor::VisitCaseClause(CaseClause* node) {
+  node->set_base_id(ReserveIdRange(CaseClause::num_ids()));
+  if (!node->is_default()) Visit(node->label());
+  VisitStatements(node->statements());
+}
+
+
+void AstNumberingVisitor::VisitForStatement(ForStatement* node) {
+  node->set_base_id(ReserveIdRange(ForStatement::num_ids()));
+  if (node->init() != NULL) Visit(node->init());
+  if (node->cond() != NULL) Visit(node->cond());
+  if (node->next() != NULL) Visit(node->next());
+  Visit(node->body());
+}
+
+
+void AstNumberingVisitor::VisitClassLiteral(ClassLiteral* node) {
+  node->set_base_id(ReserveIdRange(ClassLiteral::num_ids()));
+  if (node->extends()) Visit(node->extends());
+  if (node->constructor()) Visit(node->constructor());
+  for (int i = 0; i < node->properties()->length(); i++) {
+    VisitObjectLiteralProperty(node->properties()->at(i));
+  }
+}
+
+
+void AstNumberingVisitor::VisitObjectLiteral(ObjectLiteral* node) {
+  node->set_base_id(ReserveIdRange(ObjectLiteral::num_ids()));
+  for (int i = 0; i < node->properties()->length(); i++) {
+    VisitObjectLiteralProperty(node->properties()->at(i));
+  }
+}
+
+
+void AstNumberingVisitor::VisitObjectLiteralProperty(
+    ObjectLiteralProperty* node) {
+  Visit(node->key());
+  Visit(node->value());
+}
+
+
+void AstNumberingVisitor::VisitArrayLiteral(ArrayLiteral* node) {
+  node->set_base_id(ReserveIdRange(node->num_ids()));
+  for (int i = 0; i < node->values()->length(); i++) {
+    Visit(node->values()->at(i));
+  }
+}
+
+
+void AstNumberingVisitor::VisitCall(Call* node) {
+  node->set_base_id(ReserveIdRange(Call::num_ids()));
+  Visit(node->expression());
+  VisitArguments(node->arguments());
+}
+
+
+void AstNumberingVisitor::VisitCallNew(CallNew* node) {
+  node->set_base_id(ReserveIdRange(CallNew::num_ids()));
+  Visit(node->expression());
+  VisitArguments(node->arguments());
+}
+
+
+void AstNumberingVisitor::VisitStatements(ZoneList<Statement*>* statements) {
+  if (statements == NULL) return;
+  for (int i = 0; i < statements->length(); i++) {
+    Visit(statements->at(i));
+  }
+}
+
+
+void AstNumberingVisitor::VisitDeclarations(
+    ZoneList<Declaration*>* declarations) {
+  for (int i = 0; i < declarations->length(); i++) {
+    Visit(declarations->at(i));
+  }
+}
+
+
+void AstNumberingVisitor::VisitArguments(ZoneList<Expression*>* arguments) {
+  for (int i = 0; i < arguments->length(); i++) {
+    Visit(arguments->at(i));
+  }
+}
+
+
+void AstNumberingVisitor::VisitFunctionLiteral(FunctionLiteral* node) {
+  node->set_base_id(ReserveIdRange(FunctionLiteral::num_ids()));
+  // We don't recurse into the declarations or body of the function literal:
+  // you have to separately Renumber() each FunctionLiteral that you compile.
+}
+
+
+void AstNumberingVisitor::Renumber(FunctionLiteral* node) {
+  if (node->scope()->HasIllegalRedeclaration()) {
+    node->scope()->VisitIllegalRedeclaration(this);
+    return;
+  }
+
+  Scope* scope = node->scope();
+  VisitDeclarations(scope->declarations());
+  if (scope->is_function_scope() && scope->function() != NULL) {
+    // Visit the name of the named function expression.
+    Visit(scope->function());
+  }
+  VisitStatements(node->body());
+}
+
+
+bool AstNumbering::Renumber(FunctionLiteral* function, Zone* zone) {
+  AstNumberingVisitor visitor(zone);
+  visitor.Renumber(function);
+  return !visitor.HasStackOverflow();
+}
+}
+}  // namespace v8::internal
diff --git a/src/ast-numbering.h b/src/ast-numbering.h
new file mode 100644 (file)
index 0000000..ab97c22
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_AST_NUMBERING_H_
+#define V8_AST_NUMBERING_H_
+
+namespace v8 {
+namespace internal {
+
+namespace AstNumbering {
+// Assign type feedback IDs and bailout IDs to an AST node tree.
+//
+bool Renumber(FunctionLiteral* function, Zone* zone);
+}
+}
+}  // namespace v8::internal
+
+#endif  // V8_AST_NUMBERING_H_
index 09702eb..de8a442 100644 (file)
@@ -282,6 +282,8 @@ class AstValueFactory {
 #undef F
   }
 
+  Zone* zone() const { return zone_; }
+
   const AstRawString* GetOneByteString(Vector<const uint8_t> literal);
   const AstRawString* GetOneByteString(const char* string) {
     return GetOneByteString(Vector<const uint8_t>(
index 722742e..11bb4ef 100644 (file)
@@ -59,9 +59,8 @@ bool Expression::IsUndefinedLiteral(Isolate* isolate) const {
 }
 
 
-VariableProxy::VariableProxy(Zone* zone, Variable* var, int position,
-                             IdGen* id_gen)
-    : Expression(zone, position, 0, id_gen),
+VariableProxy::VariableProxy(Zone* zone, Variable* var, int position)
+    : Expression(zone, position),
       is_this_(var->is_this()),
       is_assigned_(false),
       is_resolved_(false),
@@ -73,8 +72,8 @@ VariableProxy::VariableProxy(Zone* zone, Variable* var, int position,
 
 
 VariableProxy::VariableProxy(Zone* zone, const AstRawString* name, bool is_this,
-                             Interface* interface, int position, IdGen* id_gen)
-    : Expression(zone, position, 0, id_gen),
+                             Interface* interface, int position)
+    : Expression(zone, position),
       is_this_(is_this),
       is_assigned_(false),
       is_resolved_(false),
@@ -98,8 +97,8 @@ void VariableProxy::BindTo(Variable* var) {
 
 
 Assignment::Assignment(Zone* zone, Token::Value op, Expression* target,
-                       Expression* value, int pos, IdGen* id_gen)
-    : Expression(zone, pos, num_ids(), id_gen),
+                       Expression* value, int pos)
+    : Expression(zone, pos),
       is_uninitialized_(false),
       key_type_(ELEMENT),
       store_mode_(STANDARD_STORE),
@@ -990,8 +989,8 @@ RegExpAlternative::RegExpAlternative(ZoneList<RegExpTree*>* nodes)
 
 
 CaseClause::CaseClause(Zone* zone, Expression* label,
-                       ZoneList<Statement*>* statements, int pos, IdGen* id_gen)
-    : Expression(zone, pos, num_ids(), id_gen),
+                       ZoneList<Statement*>* statements, int pos)
+    : Expression(zone, pos),
       label_(label),
       statements_(statements),
       compare_type_(Type::None(zone)) {}
index fe9a7fd..f997c44 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -199,23 +199,6 @@ class AstProperties FINAL BASE_EMBEDDED {
 
 class AstNode: public ZoneObject {
  public:
-  // For generating IDs for AstNodes.
-  class IdGen {
-   public:
-    IdGen() : id_(BailoutId::FirstUsable().ToInt()) {}
-
-    int ReserveIdRange(int n) {
-      int tmp = id_;
-      id_ += n;
-      return tmp;
-    }
-
-   private:
-    int id_;
-
-    DISALLOW_COPY_AND_ASSIGN(IdGen);
-  };
-
 #define DECLARE_TYPE_ENUM(type) k##type,
   enum NodeType {
     AST_NODE_LIST(DECLARE_TYPE_ENUM)
@@ -405,24 +388,30 @@ class Expression : public AstNode {
   virtual void RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle);
   byte to_boolean_types() const { return to_boolean_types_; }
 
-  BailoutId id() const { return BailoutId(base_id() + 0); }
-  TypeFeedbackId test_id() const { return TypeFeedbackId(base_id() + 1); }
+  void set_base_id(int id) { base_id_ = id; }
+  static int num_ids() { return parent_num_ids() + 2; }
+  BailoutId id() const { return BailoutId(local_id(0)); }
+  TypeFeedbackId test_id() const { return TypeFeedbackId(local_id(1)); }
 
  protected:
-  Expression(Zone* zone, int pos, int num_ids_needed_by_subclass, IdGen* id_gen)
+  Expression(Zone* zone, int pos)
       : AstNode(pos),
-        base_id_(
-            id_gen->ReserveIdRange(num_ids_needed_by_subclass + num_ids())),
+        base_id_(BailoutId::None().ToInt()),
         bounds_(Bounds::Unbounded(zone)),
         is_parenthesized_(false),
         is_multi_parenthesized_(false) {}
+  static int parent_num_ids() { return 0; }
   void set_to_boolean_types(byte types) { to_boolean_types_ = types; }
 
-  static int num_ids() { return 2; }
-  int base_id() const { return base_id_; }
+  int base_id() const {
+    DCHECK(!BailoutId(base_id_).IsNone());
+    return base_id_;
+  }
 
  private:
-  const int base_id_;
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
+  int base_id_;
   Bounds bounds_;
   byte to_boolean_types_;
   bool is_parenthesized_ : 1;
@@ -454,29 +443,34 @@ class BreakableStatement : public Statement {
     return breakable_type_ == TARGET_FOR_ANONYMOUS;
   }
 
-  BailoutId EntryId() const { return BailoutId(base_id() + 0); }
-  BailoutId ExitId() const { return BailoutId(base_id() + 1); }
+  void set_base_id(int id) { base_id_ = id; }
+  static int num_ids() { return parent_num_ids() + 2; }
+  BailoutId EntryId() const { return BailoutId(local_id(0)); }
+  BailoutId ExitId() const { return BailoutId(local_id(1)); }
 
  protected:
   BreakableStatement(Zone* zone, ZoneList<const AstRawString*>* labels,
-                     BreakableType breakable_type, int position,
-                     int num_ids_needed_by_subclass, IdGen* id_gen)
+                     BreakableType breakable_type, int position)
       : Statement(zone, position),
         labels_(labels),
         breakable_type_(breakable_type),
-        base_id_(
-            id_gen->ReserveIdRange(num_ids_needed_by_subclass + num_ids())) {
+        base_id_(BailoutId::None().ToInt()) {
     DCHECK(labels == NULL || labels->length() > 0);
   }
+  static int parent_num_ids() { return 0; }
 
-  static int num_ids() { return 2; }
-  int base_id() const { return base_id_; }
+  int base_id() const {
+    DCHECK(!BailoutId(base_id_).IsNone());
+    return base_id_;
+  }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   ZoneList<const AstRawString*>* labels_;
   BreakableType breakable_type_;
   Label break_target_;
-  const int base_id_;
+  int base_id_;
 };
 
 
@@ -491,7 +485,8 @@ class Block FINAL : public BreakableStatement {
   ZoneList<Statement*>* statements() { return &statements_; }
   bool is_initializer_block() const { return is_initializer_block_; }
 
-  BailoutId DeclsId() const { return BailoutId(base_id() + 0); }
+  static int num_ids() { return parent_num_ids() + 1; }
+  BailoutId DeclsId() const { return BailoutId(local_id(0)); }
 
   virtual bool IsJump() const OVERRIDE {
     return !statements_.is_empty() && statements_.last()->IsJump()
@@ -503,19 +498,16 @@ class Block FINAL : public BreakableStatement {
 
  protected:
   Block(Zone* zone, ZoneList<const AstRawString*>* labels, int capacity,
-        bool is_initializer_block, int pos, IdGen* id_gen)
-      : BreakableStatement(zone, labels, TARGET_FOR_NAMED_ONLY, pos, num_ids(),
-                           id_gen),
+        bool is_initializer_block, int pos)
+      : BreakableStatement(zone, labels, TARGET_FOR_NAMED_ONLY, pos),
         statements_(capacity, zone),
         is_initializer_block_(is_initializer_block),
         scope_(NULL) {}
-
-  static int num_ids() { return 1; }
-  int base_id() const {
-    return BreakableStatement::base_id() + BreakableStatement::num_ids();
-  }
+  static int parent_num_ids() { return BreakableStatement::num_ids(); }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   ZoneList<Statement*> statements_;
   bool is_initializer_block_;
   Scope* scope_;
@@ -763,7 +755,8 @@ class IterationStatement : public BreakableStatement {
 
   Statement* body() const { return body_; }
 
-  BailoutId OsrEntryId() const { return BailoutId(base_id() + 0); }
+  static int num_ids() { return parent_num_ids() + 1; }
+  BailoutId OsrEntryId() const { return BailoutId(local_id(0)); }
   virtual BailoutId ContinueId() const = 0;
   virtual BailoutId StackCheckId() const = 0;
 
@@ -771,22 +764,15 @@ class IterationStatement : public BreakableStatement {
   Label* continue_target()  { return &continue_target_; }
 
  protected:
-  IterationStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos,
-                     int num_ids_needed_by_subclass, IdGen* id_gen)
-      : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos,
-                           num_ids_needed_by_subclass + num_ids(), id_gen),
+  IterationStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
+      : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos),
         body_(NULL) {}
-
-  void Initialize(Statement* body) {
-    body_ = body;
-  }
-
-  static int num_ids() { return 1; }
-  int base_id() const {
-    return BreakableStatement::base_id() + BreakableStatement::num_ids();
-  }
+  static int parent_num_ids() { return BreakableStatement::num_ids(); }
+  void Initialize(Statement* body) { body_ = body; }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   Statement* body_;
   Label continue_target_;
 };
@@ -803,23 +789,21 @@ class DoWhileStatement FINAL : public IterationStatement {
 
   Expression* cond() const { return cond_; }
 
+  static int num_ids() { return parent_num_ids() + 2; }
   virtual BailoutId ContinueId() const OVERRIDE {
-    return BailoutId(base_id() + 0);
+    return BailoutId(local_id(0));
   }
   virtual BailoutId StackCheckId() const OVERRIDE { return BackEdgeId(); }
-  BailoutId BackEdgeId() const { return BailoutId(base_id() + 1); }
+  BailoutId BackEdgeId() const { return BailoutId(local_id(1)); }
 
  protected:
-  DoWhileStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos,
-                   IdGen* id_gen)
-      : IterationStatement(zone, labels, pos, num_ids(), id_gen), cond_(NULL) {}
-
-  static int num_ids() { return 2; }
-  int base_id() const {
-    return IterationStatement::base_id() + IterationStatement::num_ids();
-  }
+  DoWhileStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
+      : IterationStatement(zone, labels, pos), cond_(NULL) {}
+  static int parent_num_ids() { return IterationStatement::num_ids(); }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   Expression* cond_;
 };
 
@@ -841,23 +825,21 @@ class WhileStatement FINAL : public IterationStatement {
     may_have_function_literal_ = value;
   }
 
+  static int num_ids() { return parent_num_ids() + 1; }
   virtual BailoutId ContinueId() const OVERRIDE { return EntryId(); }
   virtual BailoutId StackCheckId() const OVERRIDE { return BodyId(); }
-  BailoutId BodyId() const { return BailoutId(base_id() + 0); }
+  BailoutId BodyId() const { return BailoutId(local_id(0)); }
 
  protected:
-  WhileStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos,
-                 IdGen* id_gen)
-      : IterationStatement(zone, labels, pos, num_ids(), id_gen),
+  WhileStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
+      : IterationStatement(zone, labels, pos),
         cond_(NULL),
         may_have_function_literal_(true) {}
-
-  static int num_ids() { return 1; }
-  int base_id() const {
-    return IterationStatement::base_id() + IterationStatement::num_ids();
-  }
+  static int parent_num_ids() { return IterationStatement::num_ids(); }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   Expression* cond_;
 
   // True if there is a function literal subexpression in the condition.
@@ -890,32 +872,30 @@ class ForStatement FINAL : public IterationStatement {
     may_have_function_literal_ = value;
   }
 
+  static int num_ids() { return parent_num_ids() + 2; }
   virtual BailoutId ContinueId() const OVERRIDE {
-    return BailoutId(base_id() + 0);
+    return BailoutId(local_id(0));
   }
   virtual BailoutId StackCheckId() const OVERRIDE { return BodyId(); }
-  BailoutId BodyId() const { return BailoutId(base_id() + 1); }
+  BailoutId BodyId() const { return BailoutId(local_id(1)); }
 
   bool is_fast_smi_loop() { return loop_variable_ != NULL; }
   Variable* loop_variable() { return loop_variable_; }
   void set_loop_variable(Variable* var) { loop_variable_ = var; }
 
  protected:
-  ForStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos,
-               IdGen* id_gen)
-      : IterationStatement(zone, labels, pos, num_ids(), id_gen),
+  ForStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
+      : IterationStatement(zone, labels, pos),
         init_(NULL),
         cond_(NULL),
         next_(NULL),
         may_have_function_literal_(true),
         loop_variable_(NULL) {}
-
-  static int num_ids() { return 2; }
-  int base_id() const {
-    return IterationStatement::base_id() + IterationStatement::num_ids();
-  }
+  static int parent_num_ids() { return IterationStatement::num_ids(); }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   Statement* init_;
   Expression* cond_;
   Statement* next_;
@@ -943,12 +923,8 @@ class ForEachStatement : public IterationStatement {
   Expression* subject() const { return subject_; }
 
  protected:
-  ForEachStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos,
-                   int num_ids_needed_by_subclass, IdGen* id_gen)
-      : IterationStatement(zone, labels, pos, num_ids_needed_by_subclass,
-                           id_gen),
-        each_(NULL),
-        subject_(NULL) {}
+  ForEachStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
+      : IterationStatement(zone, labels, pos), each_(NULL), subject_(NULL) {}
 
  private:
   Expression* each_;
@@ -981,24 +957,22 @@ class ForInStatement FINAL : public ForEachStatement {
   ForInType for_in_type() const { return for_in_type_; }
   void set_for_in_type(ForInType type) { for_in_type_ = type; }
 
-  BailoutId BodyId() const { return BailoutId(base_id() + 0); }
-  BailoutId PrepareId() const { return BailoutId(base_id() + 1); }
+  static int num_ids() { return parent_num_ids() + 2; }
+  BailoutId BodyId() const { return BailoutId(local_id(0)); }
+  BailoutId PrepareId() const { return BailoutId(local_id(1)); }
   virtual BailoutId ContinueId() const OVERRIDE { return EntryId(); }
   virtual BailoutId StackCheckId() const OVERRIDE { return BodyId(); }
 
  protected:
-  ForInStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos,
-                 IdGen* id_gen)
-      : ForEachStatement(zone, labels, pos, num_ids(), id_gen),
+  ForInStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
+      : ForEachStatement(zone, labels, pos),
         for_in_type_(SLOW_FOR_IN),
         for_in_feedback_slot_(FeedbackVectorSlot::Invalid()) {}
-
-  static int num_ids() { return 2; }
-  int base_id() const {
-    return ForEachStatement::base_id() + ForEachStatement::num_ids();
-  }
+  static int parent_num_ids() { return ForEachStatement::num_ids(); }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   ForInType for_in_type_;
   FeedbackVectorSlot for_in_feedback_slot_;
 };
@@ -1049,23 +1023,21 @@ class ForOfStatement FINAL : public ForEachStatement {
   virtual BailoutId ContinueId() const OVERRIDE { return EntryId(); }
   virtual BailoutId StackCheckId() const OVERRIDE { return BackEdgeId(); }
 
-  BailoutId BackEdgeId() const { return BailoutId(base_id() + 0); }
+  static int num_ids() { return parent_num_ids() + 1; }
+  BailoutId BackEdgeId() const { return BailoutId(local_id(0)); }
 
  protected:
-  ForOfStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos,
-                 IdGen* id_gen)
-      : ForEachStatement(zone, labels, pos, num_ids(), id_gen),
+  ForOfStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
+      : ForEachStatement(zone, labels, pos),
         assign_iterator_(NULL),
         next_result_(NULL),
         result_done_(NULL),
         assign_each_(NULL) {}
-
-  static int num_ids() { return 1; }
-  int base_id() const {
-    return ForEachStatement::base_id() + ForEachStatement::num_ids();
-  }
+  static int parent_num_ids() { return ForEachStatement::num_ids(); }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   Expression* assign_iterator_;
   Expression* next_result_;
   Expression* result_done_;
@@ -1180,18 +1152,20 @@ class CaseClause FINAL : public Expression {
   Label* body_target() { return &body_target_; }
   ZoneList<Statement*>* statements() const { return statements_; }
 
-  BailoutId EntryId() const { return BailoutId(base_id() + 0); }
-  TypeFeedbackId CompareId() { return TypeFeedbackId(base_id() + 1); }
+  static int num_ids() { return parent_num_ids() + 2; }
+  BailoutId EntryId() const { return BailoutId(local_id(0)); }
+  TypeFeedbackId CompareId() { return TypeFeedbackId(local_id(1)); }
 
   Type* compare_type() { return compare_type_; }
   void set_compare_type(Type* type) { compare_type_ = type; }
 
+ protected:
+  static int parent_num_ids() { return Expression::num_ids(); }
+
  private:
   CaseClause(Zone* zone, Expression* label, ZoneList<Statement*>* statements,
-             int pos, IdGen* id_gen);
-
-  static int num_ids() { return 2; }
-  int base_id() const { return Expression::base_id() + Expression::num_ids(); }
+             int pos);
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
 
   Expression* label_;
   Label body_target_;
@@ -1213,9 +1187,8 @@ class SwitchStatement FINAL : public BreakableStatement {
   ZoneList<CaseClause*>* cases() const { return cases_; }
 
  protected:
-  SwitchStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos,
-                  IdGen* id_gen)
-      : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos, 0, id_gen),
+  SwitchStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
+      : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos),
         tag_(NULL),
         cases_(NULL) {}
 
@@ -1246,27 +1219,34 @@ class IfStatement FINAL : public Statement {
         && HasElseStatement() && else_statement()->IsJump();
   }
 
-  BailoutId IfId() const { return BailoutId(base_id() + 0); }
-  BailoutId ThenId() const { return BailoutId(base_id() + 1); }
-  BailoutId ElseId() const { return BailoutId(base_id() + 2); }
+  void set_base_id(int id) { base_id_ = id; }
+  static int num_ids() { return parent_num_ids() + 3; }
+  BailoutId IfId() const { return BailoutId(local_id(0)); }
+  BailoutId ThenId() const { return BailoutId(local_id(1)); }
+  BailoutId ElseId() const { return BailoutId(local_id(2)); }
 
  protected:
   IfStatement(Zone* zone, Expression* condition, Statement* then_statement,
-              Statement* else_statement, int pos, IdGen* id_gen)
+              Statement* else_statement, int pos)
       : Statement(zone, pos),
         condition_(condition),
         then_statement_(then_statement),
         else_statement_(else_statement),
-        base_id_(id_gen->ReserveIdRange(num_ids())) {}
+        base_id_(BailoutId::None().ToInt()) {}
+  static int parent_num_ids() { return 0; }
 
-  static int num_ids() { return 3; }
-  int base_id() const { return base_id_; }
+  int base_id() const {
+    DCHECK(!BailoutId(base_id_).IsNone());
+    return base_id_;
+  }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   Expression* condition_;
   Statement* then_statement_;
   Statement* else_statement_;
-  const int base_id_;
+  int base_id_;
 };
 
 
@@ -1370,17 +1350,24 @@ class DebuggerStatement FINAL : public Statement {
  public:
   DECLARE_NODE_TYPE(DebuggerStatement)
 
-  BailoutId DebugBreakId() const { return BailoutId(base_id() + 0); }
+  void set_base_id(int id) { base_id_ = id; }
+  static int num_ids() { return parent_num_ids() + 1; }
+  BailoutId DebugBreakId() const { return BailoutId(local_id(0)); }
 
  protected:
-  explicit DebuggerStatement(Zone* zone, int pos, IdGen* id_gen)
-      : Statement(zone, pos), base_id_(id_gen->ReserveIdRange(num_ids())) {}
+  explicit DebuggerStatement(Zone* zone, int pos)
+      : Statement(zone, pos), base_id_(BailoutId::None().ToInt()) {}
+  static int parent_num_ids() { return 0; }
 
-  static int num_ids() { return 1; }
-  int base_id() const { return base_id_; }
+  int base_id() const {
+    DCHECK(!BailoutId(base_id_).IsNone());
+    return base_id_;
+  }
 
  private:
-  const int base_id_;
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
+  int base_id_;
 };
 
 
@@ -1426,18 +1413,19 @@ class Literal FINAL : public Expression {
   uint32_t Hash();
   static bool Match(void* literal1, void* literal2);
 
+  static int num_ids() { return parent_num_ids() + 1; }
   TypeFeedbackId LiteralFeedbackId() const {
-    return TypeFeedbackId(base_id() + 0);
+    return TypeFeedbackId(local_id(0));
   }
 
  protected:
-  Literal(Zone* zone, const AstValue* value, int position, IdGen* id_gen)
-      : Expression(zone, position, num_ids(), id_gen), value_(value) {}
-
-  static int num_ids() { return 1; }
-  int base_id() const { return Expression::base_id() + Expression::num_ids(); }
+  Literal(Zone* zone, const AstValue* value, int position)
+      : Expression(zone, position), value_(value) {}
+  static int parent_num_ids() { return Expression::num_ids(); }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   const AstValue* value_;
 };
 
@@ -1456,9 +1444,8 @@ class MaterializedLiteral : public Expression {
   }
 
  protected:
-  MaterializedLiteral(Zone* zone, int literal_index, int pos,
-                      int num_ids_needed_by_subclass, IdGen* id_gen)
-      : Expression(zone, pos, num_ids_needed_by_subclass, id_gen),
+  MaterializedLiteral(Zone* zone, int literal_index, int pos)
+      : Expression(zone, pos),
         literal_index_(literal_index),
         is_simple_(false),
         depth_(0) {}
@@ -1588,9 +1575,8 @@ class ObjectLiteral FINAL : public MaterializedLiteral {
 
  protected:
   ObjectLiteral(Zone* zone, ZoneList<Property*>* properties, int literal_index,
-                int boilerplate_properties, bool has_function, int pos,
-                IdGen* id_gen)
-      : MaterializedLiteral(zone, literal_index, pos, 0, id_gen),
+                int boilerplate_properties, bool has_function, int pos)
+      : MaterializedLiteral(zone, literal_index, pos),
         properties_(properties),
         boilerplate_properties_(boilerplate_properties),
         fast_elements_(false),
@@ -1617,9 +1603,8 @@ class RegExpLiteral FINAL : public MaterializedLiteral {
 
  protected:
   RegExpLiteral(Zone* zone, const AstRawString* pattern,
-                const AstRawString* flags, int literal_index, int pos,
-                IdGen* id_gen)
-      : MaterializedLiteral(zone, literal_index, pos, 0, id_gen),
+                const AstRawString* flags, int literal_index, int pos)
+      : MaterializedLiteral(zone, literal_index, pos),
         pattern_(pattern),
         flags_(flags) {
     set_depth(1);
@@ -1640,8 +1625,12 @@ class ArrayLiteral FINAL : public MaterializedLiteral {
   Handle<FixedArray> constant_elements() const { return constant_elements_; }
   ZoneList<Expression*>* values() const { return values_; }
 
+  // Unlike other AST nodes, this number of bailout IDs allocated for an
+  // ArrayLiteral can vary, so num_ids() is not a static method.
+  int num_ids() const { return parent_num_ids() + values()->length(); }
+
   // Return an AST id for an element that is used in simulate instructions.
-  BailoutId GetIdForElement(int i) { return BailoutId(base_id() + i); }
+  BailoutId GetIdForElement(int i) { return BailoutId(local_id(i)); }
 
   // Populate the constant elements fixed array.
   void BuildConstantElements(Isolate* isolate);
@@ -1661,16 +1650,13 @@ class ArrayLiteral FINAL : public MaterializedLiteral {
 
  protected:
   ArrayLiteral(Zone* zone, ZoneList<Expression*>* values, int literal_index,
-               int pos, IdGen* id_gen)
-      : MaterializedLiteral(zone, literal_index, pos, num_ids(values), id_gen),
-        values_(values) {}
-
-  static int num_ids(ZoneList<Expression*>* values) { return values->length(); }
-  int base_id() const {
-    return MaterializedLiteral::base_id() + MaterializedLiteral::num_ids();
-  }
+               int pos)
+      : MaterializedLiteral(zone, literal_index, pos), values_(values) {}
+  static int parent_num_ids() { return MaterializedLiteral::num_ids(); }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   Handle<FixedArray> constant_elements_;
   ZoneList<Expression*>* values_;
 };
@@ -1726,10 +1712,10 @@ class VariableProxy FINAL : public Expression {
   }
 
  protected:
-  VariableProxy(Zone* zone, Variable* var, int position, IdGen* id_gen);
+  VariableProxy(Zone* zone, Variable* var, int position);
 
   VariableProxy(Zone* zone, const AstRawString* name, bool is_this,
-                Interface* interface, int position, IdGen* id_gen);
+                Interface* interface, int position);
 
   bool is_this_ : 1;
   bool is_assigned_ : 1;
@@ -1752,9 +1738,9 @@ class Property FINAL : public Expression {
   Expression* obj() const { return obj_; }
   Expression* key() const { return key_; }
 
-  BailoutId LoadId() const { return BailoutId(base_id() + 0); }
-  TypeFeedbackId PropertyFeedbackId() { return TypeFeedbackId(base_id() + 1); }
-
+  static int num_ids() { return parent_num_ids() + 2; }
+  BailoutId LoadId() const { return BailoutId(local_id(0)); }
+  TypeFeedbackId PropertyFeedbackId() { return TypeFeedbackId(local_id(1)); }
 
   bool IsStringAccess() const { return is_string_access_; }
 
@@ -1797,19 +1783,19 @@ class Property FINAL : public Expression {
   }
 
  protected:
-  Property(Zone* zone, Expression* obj, Expression* key, int pos, IdGen* id_gen)
-      : Expression(zone, pos, num_ids(), id_gen),
+  Property(Zone* zone, Expression* obj, Expression* key, int pos)
+      : Expression(zone, pos),
         is_for_call_(false),
         is_uninitialized_(false),
         is_string_access_(false),
         property_feedback_slot_(FeedbackVectorICSlot::Invalid()),
         obj_(obj),
         key_(key) {}
-
-  static int num_ids() { return 2; }
-  int base_id() const { return Expression::base_id() + Expression::num_ids(); }
+  static int parent_num_ids() { return Expression::num_ids(); }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   bool is_for_call_ : 1;
   bool is_uninitialized_ : 1;
   bool is_string_access_ : 1;
@@ -1873,8 +1859,9 @@ class Call FINAL : public Expression {
   }
   bool ComputeGlobalTarget(Handle<GlobalObject> global, LookupIterator* it);
 
-  BailoutId ReturnId() const { return BailoutId(base_id() + 0); }
-  BailoutId EvalOrLookupId() const { return BailoutId(base_id() + 1); }
+  static int num_ids() { return parent_num_ids() + 2; }
+  BailoutId ReturnId() const { return BailoutId(local_id(0)); }
+  BailoutId EvalOrLookupId() const { return BailoutId(local_id(1)); }
 
   enum CallType {
     POSSIBLY_EVAL_CALL,
@@ -1896,8 +1883,8 @@ class Call FINAL : public Expression {
 
  protected:
   Call(Zone* zone, Expression* expression, ZoneList<Expression*>* arguments,
-       int pos, IdGen* id_gen)
-      : Expression(zone, pos, num_ids(), id_gen),
+       int pos)
+      : Expression(zone, pos),
         call_feedback_slot_(FeedbackVectorICSlot::Invalid()),
         expression_(expression),
         arguments_(arguments) {
@@ -1905,11 +1892,11 @@ class Call FINAL : public Expression {
       expression->AsProperty()->mark_for_call();
     }
   }
-
-  static int num_ids() { return 2; }
-  int base_id() const { return Expression::base_id() + Expression::num_ids(); }
+  static int parent_num_ids() { return Expression::num_ids(); }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   FeedbackVectorICSlot call_feedback_slot_;
   Expression* expression_;
   ZoneList<Expression*>* arguments_;
@@ -1947,23 +1934,24 @@ class CallNew FINAL : public Expression {
     return allocation_site_;
   }
 
+  static int num_ids() { return parent_num_ids() + 1; }
   static int feedback_slots() { return 1; }
-
-  BailoutId ReturnId() const { return BailoutId(base_id() + 0); }
+  BailoutId ReturnId() const { return BailoutId(local_id(0)); }
 
  protected:
   CallNew(Zone* zone, Expression* expression, ZoneList<Expression*>* arguments,
-          int pos, IdGen* id_gen)
-      : Expression(zone, pos, num_ids(), id_gen),
+          int pos)
+      : Expression(zone, pos),
         expression_(expression),
         arguments_(arguments),
         is_monomorphic_(false),
         callnew_feedback_slot_(FeedbackVectorSlot::Invalid()) {}
 
-  static int num_ids() { return 1; }
-  int base_id() const { return Expression::base_id() + Expression::num_ids(); }
+  static int parent_num_ids() { return Expression::num_ids(); }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   Expression* expression_;
   ZoneList<Expression*>* arguments_;
   bool is_monomorphic_;
@@ -2000,24 +1988,25 @@ class CallRuntime FINAL : public Expression {
     return callruntime_feedback_slot_;
   }
 
+  static int num_ids() { return parent_num_ids() + 1; }
   TypeFeedbackId CallRuntimeFeedbackId() const {
-    return TypeFeedbackId(base_id() + 0);
+    return TypeFeedbackId(local_id(0));
   }
 
  protected:
   CallRuntime(Zone* zone, const AstRawString* name,
               const Runtime::Function* function,
-              ZoneList<Expression*>* arguments, int pos, IdGen* id_gen)
-      : Expression(zone, pos, num_ids(), id_gen),
+              ZoneList<Expression*>* arguments, int pos)
+      : Expression(zone, pos),
         raw_name_(name),
         function_(function),
         arguments_(arguments),
         callruntime_feedback_slot_(FeedbackVectorICSlot::Invalid()) {}
-
-  static int num_ids() { return 1; }
-  int base_id() const { return Expression::base_id() + Expression::num_ids(); }
+  static int parent_num_ids() { return Expression::num_ids(); }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   const AstRawString* raw_name_;
   const Runtime::Function* function_;
   ZoneList<Expression*>* arguments_;
@@ -2034,25 +2023,23 @@ class UnaryOperation FINAL : public Expression {
 
   // For unary not (Token::NOT), the AST ids where true and false will
   // actually be materialized, respectively.
-  BailoutId MaterializeTrueId() const { return BailoutId(base_id() + 0); }
-  BailoutId MaterializeFalseId() const { return BailoutId(base_id() + 1); }
+  static int num_ids() { return parent_num_ids() + 2; }
+  BailoutId MaterializeTrueId() const { return BailoutId(local_id(0)); }
+  BailoutId MaterializeFalseId() const { return BailoutId(local_id(1)); }
 
   virtual void RecordToBooleanTypeFeedback(
       TypeFeedbackOracle* oracle) OVERRIDE;
 
  protected:
-  UnaryOperation(Zone* zone, Token::Value op, Expression* expression, int pos,
-                 IdGen* id_gen)
-      : Expression(zone, pos, num_ids(), id_gen),
-        op_(op),
-        expression_(expression) {
+  UnaryOperation(Zone* zone, Token::Value op, Expression* expression, int pos)
+      : Expression(zone, pos), op_(op), expression_(expression) {
     DCHECK(Token::IsUnaryOp(op));
   }
-
-  static int num_ids() { return 2; }
-  int base_id() const { return Expression::base_id() + Expression::num_ids(); }
+  static int parent_num_ids() { return Expression::num_ids(); }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   Token::Value op_;
   Expression* expression_;
 };
@@ -2074,10 +2061,11 @@ class BinaryOperation FINAL : public Expression {
 
   // The short-circuit logical operations need an AST ID for their
   // right-hand subexpression.
-  BailoutId RightId() const { return BailoutId(base_id() + 0); }
+  static int num_ids() { return parent_num_ids() + 2; }
+  BailoutId RightId() const { return BailoutId(local_id(0)); }
 
   TypeFeedbackId BinaryOperationFeedbackId() const {
-    return TypeFeedbackId(base_id() + 1);
+    return TypeFeedbackId(local_id(1));
   }
   Maybe<int> fixed_right_arg() const {
     return has_fixed_right_arg_ ? Maybe<int>(fixed_right_arg_value_)
@@ -2093,18 +2081,18 @@ class BinaryOperation FINAL : public Expression {
 
  protected:
   BinaryOperation(Zone* zone, Token::Value op, Expression* left,
-                  Expression* right, int pos, IdGen* id_gen)
-      : Expression(zone, pos, num_ids(), id_gen),
+                  Expression* right, int pos)
+      : Expression(zone, pos),
         op_(static_cast<byte>(op)),
         left_(left),
         right_(right) {
     DCHECK(Token::IsBinaryOp(op));
   }
-
-  static int num_ids() { return 2; }
-  int base_id() const { return Expression::base_id() + Expression::num_ids(); }
+  static int parent_num_ids() { return Expression::num_ids(); }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   const byte op_;  // actually Token::Value
   // TODO(rossberg): the fixed arg should probably be represented as a Constant
   // type for the RHS. Currenty it's actually a Maybe<int>
@@ -2145,28 +2133,29 @@ class CountOperation FINAL : public Expression {
   void set_store_mode(KeyedAccessStoreMode mode) { store_mode_ = mode; }
   void set_type(Type* type) { type_ = type; }
 
-  BailoutId AssignmentId() const { return BailoutId(base_id() + 0); }
+  static int num_ids() { return parent_num_ids() + 3; }
+  BailoutId AssignmentId() const { return BailoutId(local_id(0)); }
   TypeFeedbackId CountBinOpFeedbackId() const {
-    return TypeFeedbackId(base_id() + 1);
+    return TypeFeedbackId(local_id(1));
   }
   TypeFeedbackId CountStoreFeedbackId() const {
-    return TypeFeedbackId(base_id() + 2);
+    return TypeFeedbackId(local_id(2));
   }
 
  protected:
   CountOperation(Zone* zone, Token::Value op, bool is_prefix, Expression* expr,
-                 int pos, IdGen* id_gen)
-      : Expression(zone, pos, num_ids(), id_gen),
+                 int pos)
+      : Expression(zone, pos),
         op_(op),
         is_prefix_(is_prefix),
         key_type_(ELEMENT),
         store_mode_(STANDARD_STORE),
         expression_(expr) {}
-
-  static int num_ids() { return 3; }
-  int base_id() const { return Expression::base_id() + Expression::num_ids(); }
+  static int parent_num_ids() { return Expression::num_ids(); }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   Token::Value op_;
   bool is_prefix_ : 1;
   IcCheckType key_type_ : 1;
@@ -2187,8 +2176,9 @@ class CompareOperation FINAL : public Expression {
   Expression* right() const { return right_; }
 
   // Type feedback information.
+  static int num_ids() { return parent_num_ids() + 1; }
   TypeFeedbackId CompareOperationFeedbackId() const {
-    return TypeFeedbackId(base_id() + 0);
+    return TypeFeedbackId(local_id(0));
   }
   Type* combined_type() const { return combined_type_; }
   void set_combined_type(Type* type) { combined_type_ = type; }
@@ -2200,19 +2190,19 @@ class CompareOperation FINAL : public Expression {
 
  protected:
   CompareOperation(Zone* zone, Token::Value op, Expression* left,
-                   Expression* right, int pos, IdGen* id_gen)
-      : Expression(zone, pos, num_ids(), id_gen),
+                   Expression* right, int pos)
+      : Expression(zone, pos),
         op_(op),
         left_(left),
         right_(right),
         combined_type_(Type::None(zone)) {
     DCHECK(Token::IsCompareOp(op));
   }
-
-  static int num_ids() { return 1; }
-  int base_id() const { return Expression::base_id() + Expression::num_ids(); }
+  static int parent_num_ids() { return Expression::num_ids(); }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   Token::Value op_;
   Expression* left_;
   Expression* right_;
@@ -2229,21 +2219,22 @@ class Conditional FINAL : public Expression {
   Expression* then_expression() const { return then_expression_; }
   Expression* else_expression() const { return else_expression_; }
 
-  BailoutId ThenId() const { return BailoutId(base_id() + 0); }
-  BailoutId ElseId() const { return BailoutId(base_id() + 1); }
+  static int num_ids() { return parent_num_ids() + 2; }
+  BailoutId ThenId() const { return BailoutId(local_id(0)); }
+  BailoutId ElseId() const { return BailoutId(local_id(1)); }
 
  protected:
   Conditional(Zone* zone, Expression* condition, Expression* then_expression,
-              Expression* else_expression, int position, IdGen* id_gen)
-      : Expression(zone, position, num_ids(), id_gen),
+              Expression* else_expression, int position)
+      : Expression(zone, position),
         condition_(condition),
         then_expression_(then_expression),
         else_expression_(else_expression) {}
-
-  static int num_ids() { return 2; }
-  int base_id() const { return Expression::base_id() + Expression::num_ids(); }
+  static int parent_num_ids() { return Expression::num_ids(); }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   Expression* condition_;
   Expression* then_expression_;
   Expression* else_expression_;
@@ -2266,12 +2257,11 @@ class Assignment FINAL : public Expression {
   // This check relies on the definition order of token in token.h.
   bool is_compound() const { return op() > Token::ASSIGN; }
 
-  BailoutId AssignmentId() const { return BailoutId(base_id() + 0); }
+  static int num_ids() { return parent_num_ids() + 2; }
+  BailoutId AssignmentId() const { return BailoutId(local_id(0)); }
 
   // Type feedback information.
-  TypeFeedbackId AssignmentFeedbackId() {
-    return TypeFeedbackId(base_id() + 1);
-  }
+  TypeFeedbackId AssignmentFeedbackId() { return TypeFeedbackId(local_id(1)); }
   virtual bool IsMonomorphic() OVERRIDE {
     return receiver_types_.length() == 1;
   }
@@ -2292,13 +2282,11 @@ class Assignment FINAL : public Expression {
 
  protected:
   Assignment(Zone* zone, Token::Value op, Expression* target, Expression* value,
-             int pos, IdGen* id_gen);
-
-  static int num_ids() { return 2; }
-  int base_id() const { return Expression::base_id() + Expression::num_ids(); }
+             int pos);
+  static int parent_num_ids() { return Expression::num_ids(); }
 
-  template<class Visitor>
-  void Init(Zone* zone, AstNodeFactory<Visitor>* factory) {
+  template <class Visitor>
+  void Init(AstNodeFactory<Visitor>* factory) {
     DCHECK(Token::IsAssignmentOp(op_));
     if (is_compound()) {
       binary_operation_ = factory->NewBinaryOperation(
@@ -2307,6 +2295,8 @@ class Assignment FINAL : public Expression {
   }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   bool is_uninitialized_ : 1;
   IcCheckType key_type_ : 1;
   KeyedAccessStoreMode store_mode_ : 5;  // Windows treats as signed,
@@ -2367,8 +2357,8 @@ class Yield FINAL : public Expression {
 
  protected:
   Yield(Zone* zone, Expression* generator_object, Expression* expression,
-        Kind yield_kind, int pos, IdGen* id_gen)
-      : Expression(zone, pos, 0, id_gen),
+        Kind yield_kind, int pos)
+      : Expression(zone, pos),
         generator_object_(generator_object),
         expression_(expression),
         yield_kind_(yield_kind),
@@ -2391,8 +2381,8 @@ class Throw FINAL : public Expression {
   Expression* exception() const { return exception_; }
 
  protected:
-  Throw(Zone* zone, Expression* exception, int pos, IdGen* id_gen)
-      : Expression(zone, pos, 0, id_gen), exception_(exception) {}
+  Throw(Zone* zone, Expression* exception, int pos)
+      : Expression(zone, pos), exception_(exception) {}
 
  private:
   Expression* exception_;
@@ -2546,8 +2536,8 @@ class FunctionLiteral FINAL : public Expression {
                   ParameterFlag has_duplicate_parameters,
                   IsFunctionFlag is_function,
                   IsParenthesizedFlag is_parenthesized, FunctionKind kind,
-                  int position, IdGen* id_gen)
-      : Expression(zone, position, 0, id_gen),
+                  int position)
+      : Expression(zone, position),
         raw_name_(name),
         scope_(scope),
         body_(body),
@@ -2613,8 +2603,8 @@ class ClassLiteral FINAL : public Expression {
  protected:
   ClassLiteral(Zone* zone, const AstRawString* name, Expression* extends,
                Expression* constructor, ZoneList<Property*>* properties,
-               int start_position, int end_position, IdGen* id_gen)
-      : Expression(zone, start_position, 0, id_gen),
+               int start_position, int end_position)
+      : Expression(zone, start_position),
         raw_name_(name),
         extends_(extends),
         constructor_(constructor),
@@ -2639,8 +2629,8 @@ class NativeFunctionLiteral FINAL : public Expression {
 
  protected:
   NativeFunctionLiteral(Zone* zone, const AstRawString* name,
-                        v8::Extension* extension, int pos, IdGen* id_gen)
-      : Expression(zone, pos, 0, id_gen), name_(name), extension_(extension) {}
+                        v8::Extension* extension, int pos)
+      : Expression(zone, pos), name_(name), extension_(extension) {}
 
  private:
   const AstRawString* name_;
@@ -2653,8 +2643,7 @@ class ThisFunction FINAL : public Expression {
   DECLARE_NODE_TYPE(ThisFunction)
 
  protected:
-  ThisFunction(Zone* zone, int pos, IdGen* id_gen)
-      : Expression(zone, pos, 0, id_gen) {}
+  ThisFunction(Zone* zone, int pos) : Expression(zone, pos) {}
 };
 
 
@@ -2664,9 +2653,8 @@ class SuperReference FINAL : public Expression {
 
   VariableProxy* this_var() const { return this_var_; }
 
-  TypeFeedbackId HomeObjectFeedbackId() {
-    return TypeFeedbackId(base_id() + 0);
-  }
+  static int num_ids() { return parent_num_ids() + 1; }
+  TypeFeedbackId HomeObjectFeedbackId() { return TypeFeedbackId(local_id(0)); }
 
   // Type feedback information.
   virtual FeedbackVectorRequirements ComputeFeedbackRequirements() {
@@ -2682,17 +2670,17 @@ class SuperReference FINAL : public Expression {
   }
 
  protected:
-  SuperReference(Zone* zone, VariableProxy* this_var, int pos, IdGen* id_gen)
-      : Expression(zone, pos, num_ids(), id_gen),
+  SuperReference(Zone* zone, VariableProxy* this_var, int pos)
+      : Expression(zone, pos),
         this_var_(this_var),
         homeobject_feedback_slot_(FeedbackVectorICSlot::Invalid()) {
     DCHECK(this_var->is_this());
   }
-
-  static int num_ids() { return 1; }
-  int base_id() const { return Expression::base_id() + Expression::num_ids(); }
+  static int parent_num_ids() { return Expression::num_ids(); }
 
  private:
+  int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+
   VariableProxy* this_var_;
   FeedbackVectorICSlot homeobject_feedback_slot_;
 };
@@ -3194,9 +3182,9 @@ class AstNullVisitor BASE_EMBEDDED {
 template<class Visitor>
 class AstNodeFactory FINAL BASE_EMBEDDED {
  public:
-  AstNodeFactory(Zone* zone, AstValueFactory* ast_value_factory,
-                 AstNode::IdGen* id_gen)
-      : zone_(zone), ast_value_factory_(ast_value_factory), id_gen_(id_gen) {}
+  explicit AstNodeFactory(AstValueFactory* ast_value_factory)
+      : zone_(ast_value_factory->zone()),
+        ast_value_factory_(ast_value_factory) {}
 
   Visitor* visitor() { return &visitor_; }
 
@@ -3274,14 +3262,14 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
                   int capacity,
                   bool is_initializer_block,
                   int pos) {
-    Block* block = new (zone_)
-        Block(zone_, labels, capacity, is_initializer_block, pos, id_gen_);
+    Block* block =
+        new (zone_) Block(zone_, labels, capacity, is_initializer_block, pos);
     VISIT_AND_RETURN(Block, block)
   }
 
 #define STATEMENT_WITH_LABELS(NodeType)                                     \
   NodeType* New##NodeType(ZoneList<const AstRawString*>* labels, int pos) { \
-    NodeType* stmt = new (zone_) NodeType(zone_, labels, pos, id_gen_);     \
+    NodeType* stmt = new (zone_) NodeType(zone_, labels, pos);              \
     VISIT_AND_RETURN(NodeType, stmt);                                       \
   }
   STATEMENT_WITH_LABELS(DoWhileStatement)
@@ -3295,13 +3283,11 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
                                         int pos) {
     switch (visit_mode) {
       case ForEachStatement::ENUMERATE: {
-        ForInStatement* stmt =
-            new (zone_) ForInStatement(zone_, labels, pos, id_gen_);
+        ForInStatement* stmt = new (zone_) ForInStatement(zone_, labels, pos);
         VISIT_AND_RETURN(ForInStatement, stmt);
       }
       case ForEachStatement::ITERATE: {
-        ForOfStatement* stmt =
-            new (zone_) ForOfStatement(zone_, labels, pos, id_gen_);
+        ForOfStatement* stmt = new (zone_) ForOfStatement(zone_, labels, pos);
         VISIT_AND_RETURN(ForOfStatement, stmt);
       }
     }
@@ -3349,8 +3335,8 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
                               Statement* then_statement,
                               Statement* else_statement,
                               int pos) {
-    IfStatement* stmt = new (zone_) IfStatement(
-        zone_, condition, then_statement, else_statement, pos, id_gen_);
+    IfStatement* stmt = new (zone_)
+        IfStatement(zone_, condition, then_statement, else_statement, pos);
     VISIT_AND_RETURN(IfStatement, stmt)
   }
 
@@ -3375,8 +3361,7 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
   }
 
   DebuggerStatement* NewDebuggerStatement(int pos) {
-    DebuggerStatement* stmt =
-        new (zone_) DebuggerStatement(zone_, pos, id_gen_);
+    DebuggerStatement* stmt = new (zone_) DebuggerStatement(zone_, pos);
     VISIT_AND_RETURN(DebuggerStatement, stmt)
   }
 
@@ -3386,64 +3371,63 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
 
   CaseClause* NewCaseClause(
       Expression* label, ZoneList<Statement*>* statements, int pos) {
-    CaseClause* clause =
-        new (zone_) CaseClause(zone_, label, statements, pos, id_gen_);
+    CaseClause* clause = new (zone_) CaseClause(zone_, label, statements, pos);
     VISIT_AND_RETURN(CaseClause, clause)
   }
 
   Literal* NewStringLiteral(const AstRawString* string, int pos) {
-    Literal* lit = new (zone_)
-        Literal(zone_, ast_value_factory_->NewString(string), pos, id_gen_);
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewString(string), pos);
     VISIT_AND_RETURN(Literal, lit)
   }
 
   // A JavaScript symbol (ECMA-262 edition 6).
   Literal* NewSymbolLiteral(const char* name, int pos) {
-    Literal* lit = new (zone_)
-        Literal(zone_, ast_value_factory_->NewSymbol(name), pos, id_gen_);
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewSymbol(name), pos);
     VISIT_AND_RETURN(Literal, lit)
   }
 
   Literal* NewNumberLiteral(double number, int pos) {
-    Literal* lit = new (zone_)
-        Literal(zone_, ast_value_factory_->NewNumber(number), pos, id_gen_);
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewNumber(number), pos);
     VISIT_AND_RETURN(Literal, lit)
   }
 
   Literal* NewSmiLiteral(int number, int pos) {
-    Literal* lit = new (zone_)
-        Literal(zone_, ast_value_factory_->NewSmi(number), pos, id_gen_);
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewSmi(number), pos);
     VISIT_AND_RETURN(Literal, lit)
   }
 
   Literal* NewBooleanLiteral(bool b, int pos) {
-    Literal* lit = new (zone_)
-        Literal(zone_, ast_value_factory_->NewBoolean(b), pos, id_gen_);
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewBoolean(b), pos);
     VISIT_AND_RETURN(Literal, lit)
   }
 
   Literal* NewStringListLiteral(ZoneList<const AstRawString*>* strings,
                                 int pos) {
-    Literal* lit = new (zone_) Literal(
-        zone_, ast_value_factory_->NewStringList(strings), pos, id_gen_);
+    Literal* lit = new (zone_)
+        Literal(zone_, ast_value_factory_->NewStringList(strings), pos);
     VISIT_AND_RETURN(Literal, lit)
   }
 
   Literal* NewNullLiteral(int pos) {
     Literal* lit =
-        new (zone_) Literal(zone_, ast_value_factory_->NewNull(), pos, id_gen_);
+        new (zone_) Literal(zone_, ast_value_factory_->NewNull(), pos);
     VISIT_AND_RETURN(Literal, lit)
   }
 
   Literal* NewUndefinedLiteral(int pos) {
-    Literal* lit = new (zone_)
-        Literal(zone_, ast_value_factory_->NewUndefined(), pos, id_gen_);
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewUndefined(), pos);
     VISIT_AND_RETURN(Literal, lit)
   }
 
   Literal* NewTheHoleLiteral(int pos) {
-    Literal* lit = new (zone_)
-        Literal(zone_, ast_value_factory_->NewTheHole(), pos, id_gen_);
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewTheHole(), pos);
     VISIT_AND_RETURN(Literal, lit)
   }
 
@@ -3453,9 +3437,9 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
       int boilerplate_properties,
       bool has_function,
       int pos) {
-    ObjectLiteral* lit = new (zone_)
-        ObjectLiteral(zone_, properties, literal_index, boilerplate_properties,
-                      has_function, pos, id_gen_);
+    ObjectLiteral* lit =
+        new (zone_) ObjectLiteral(zone_, properties, literal_index,
+                                  boilerplate_properties, has_function, pos);
     VISIT_AND_RETURN(ObjectLiteral, lit)
   }
 
@@ -3479,8 +3463,8 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
                                   const AstRawString* flags,
                                   int literal_index,
                                   int pos) {
-    RegExpLiteral* lit = new (zone_)
-        RegExpLiteral(zone_, pattern, flags, literal_index, pos, id_gen_);
+    RegExpLiteral* lit =
+        new (zone_) RegExpLiteral(zone_, pattern, flags, literal_index, pos);
     VISIT_AND_RETURN(RegExpLiteral, lit);
   }
 
@@ -3488,13 +3472,13 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
                                 int literal_index,
                                 int pos) {
     ArrayLiteral* lit =
-        new (zone_) ArrayLiteral(zone_, values, literal_index, pos, id_gen_);
+        new (zone_) ArrayLiteral(zone_, values, literal_index, pos);
     VISIT_AND_RETURN(ArrayLiteral, lit)
   }
 
   VariableProxy* NewVariableProxy(Variable* var,
                                   int pos = RelocInfo::kNoPosition) {
-    VariableProxy* proxy = new (zone_) VariableProxy(zone_, var, pos, id_gen_);
+    VariableProxy* proxy = new (zone_) VariableProxy(zone_, var, pos);
     VISIT_AND_RETURN(VariableProxy, proxy)
   }
 
@@ -3502,28 +3486,27 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
                                   bool is_this,
                                   Interface* interface = Interface::NewValue(),
                                   int position = RelocInfo::kNoPosition) {
-    VariableProxy* proxy = new (zone_)
-        VariableProxy(zone_, name, is_this, interface, position, id_gen_);
+    VariableProxy* proxy =
+        new (zone_) VariableProxy(zone_, name, is_this, interface, position);
     VISIT_AND_RETURN(VariableProxy, proxy)
   }
 
   Property* NewProperty(Expression* obj, Expression* key, int pos) {
-    Property* prop = new (zone_) Property(zone_, obj, key, pos, id_gen_);
+    Property* prop = new (zone_) Property(zone_, obj, key, pos);
     VISIT_AND_RETURN(Property, prop)
   }
 
   Call* NewCall(Expression* expression,
                 ZoneList<Expression*>* arguments,
                 int pos) {
-    Call* call = new (zone_) Call(zone_, expression, arguments, pos, id_gen_);
+    Call* call = new (zone_) Call(zone_, expression, arguments, pos);
     VISIT_AND_RETURN(Call, call)
   }
 
   CallNew* NewCallNew(Expression* expression,
                       ZoneList<Expression*>* arguments,
                       int pos) {
-    CallNew* call =
-        new (zone_) CallNew(zone_, expression, arguments, pos, id_gen_);
+    CallNew* call = new (zone_) CallNew(zone_, expression, arguments, pos);
     VISIT_AND_RETURN(CallNew, call)
   }
 
@@ -3532,7 +3515,7 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
                               ZoneList<Expression*>* arguments,
                               int pos) {
     CallRuntime* call =
-        new (zone_) CallRuntime(zone_, name, function, arguments, pos, id_gen_);
+        new (zone_) CallRuntime(zone_, name, function, arguments, pos);
     VISIT_AND_RETURN(CallRuntime, call)
   }
 
@@ -3540,7 +3523,7 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
                                     Expression* expression,
                                     int pos) {
     UnaryOperation* node =
-        new (zone_) UnaryOperation(zone_, op, expression, pos, id_gen_);
+        new (zone_) UnaryOperation(zone_, op, expression, pos);
     VISIT_AND_RETURN(UnaryOperation, node)
   }
 
@@ -3549,7 +3532,7 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
                                       Expression* right,
                                       int pos) {
     BinaryOperation* node =
-        new (zone_) BinaryOperation(zone_, op, left, right, pos, id_gen_);
+        new (zone_) BinaryOperation(zone_, op, left, right, pos);
     VISIT_AND_RETURN(BinaryOperation, node)
   }
 
@@ -3558,7 +3541,7 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
                                     Expression* expr,
                                     int pos) {
     CountOperation* node =
-        new (zone_) CountOperation(zone_, op, is_prefix, expr, pos, id_gen_);
+        new (zone_) CountOperation(zone_, op, is_prefix, expr, pos);
     VISIT_AND_RETURN(CountOperation, node)
   }
 
@@ -3567,7 +3550,7 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
                                         Expression* right,
                                         int pos) {
     CompareOperation* node =
-        new (zone_) CompareOperation(zone_, op, left, right, pos, id_gen_);
+        new (zone_) CompareOperation(zone_, op, left, right, pos);
     VISIT_AND_RETURN(CompareOperation, node)
   }
 
@@ -3576,7 +3559,7 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
                               Expression* else_expression,
                               int position) {
     Conditional* cond = new (zone_) Conditional(
-        zone_, condition, then_expression, else_expression, position, id_gen_);
+        zone_, condition, then_expression, else_expression, position);
     VISIT_AND_RETURN(Conditional, cond)
   }
 
@@ -3584,9 +3567,8 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
                             Expression* target,
                             Expression* value,
                             int pos) {
-    Assignment* assign =
-        new (zone_) Assignment(zone_, op, target, value, pos, id_gen_);
-    assign->Init(zone_, this);
+    Assignment* assign = new (zone_) Assignment(zone_, op, target, value, pos);
+    assign->Init(this);
     VISIT_AND_RETURN(Assignment, assign)
   }
 
@@ -3595,13 +3577,13 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
                   Yield::Kind yield_kind,
                   int pos) {
     if (!expression) expression = NewUndefinedLiteral(pos);
-    Yield* yield = new (zone_)
-        Yield(zone_, generator_object, expression, yield_kind, pos, id_gen_);
+    Yield* yield =
+        new (zone_) Yield(zone_, generator_object, expression, yield_kind, pos);
     VISIT_AND_RETURN(Yield, yield)
   }
 
   Throw* NewThrow(Expression* exception, int pos) {
-    Throw* t = new (zone_) Throw(zone_, exception, pos, id_gen_);
+    Throw* t = new (zone_) Throw(zone_, exception, pos);
     VISIT_AND_RETURN(Throw, t)
   }
 
@@ -3617,8 +3599,8 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
     FunctionLiteral* lit = new (zone_) FunctionLiteral(
         zone_, name, ast_value_factory, scope, body, materialized_literal_count,
         expected_property_count, handler_count, parameter_count, function_type,
-        has_duplicate_parameters, is_function, is_parenthesized, kind, position,
-        id_gen_);
+        has_duplicate_parameters, is_function, is_parenthesized, kind,
+        position);
     // Top-level literal doesn't count for the AST's properties.
     if (is_function == FunctionLiteral::kIsFunction) {
       visitor_.VisitFunctionLiteral(lit);
@@ -3632,7 +3614,7 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
                                 int start_position, int end_position) {
     ClassLiteral* lit =
         new (zone_) ClassLiteral(zone_, name, extends, constructor, properties,
-                                 start_position, end_position, id_gen_);
+                                 start_position, end_position);
     VISIT_AND_RETURN(ClassLiteral, lit)
   }
 
@@ -3640,18 +3622,17 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
                                                   v8::Extension* extension,
                                                   int pos) {
     NativeFunctionLiteral* lit =
-        new (zone_) NativeFunctionLiteral(zone_, name, extension, pos, id_gen_);
+        new (zone_) NativeFunctionLiteral(zone_, name, extension, pos);
     VISIT_AND_RETURN(NativeFunctionLiteral, lit)
   }
 
   ThisFunction* NewThisFunction(int pos) {
-    ThisFunction* fun = new (zone_) ThisFunction(zone_, pos, id_gen_);
+    ThisFunction* fun = new (zone_) ThisFunction(zone_, pos);
     VISIT_AND_RETURN(ThisFunction, fun)
   }
 
   SuperReference* NewSuperReference(VariableProxy* this_var, int pos) {
-    SuperReference* super =
-        new (zone_) SuperReference(zone_, this_var, pos, id_gen_);
+    SuperReference* super = new (zone_) SuperReference(zone_, this_var, pos);
     VISIT_AND_RETURN(SuperReference, super);
   }
 
@@ -3661,7 +3642,6 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
   Zone* zone_;
   Visitor visitor_;
   AstValueFactory* ast_value_factory_;
-  AstNode::IdGen* id_gen_;
 };
 
 
index 0e6c3a3..8e94f76 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "src/compiler.h"
 
+#include "src/ast-numbering.h"
 #include "src/bootstrapper.h"
 #include "src/codegen.h"
 #include "src/compilation-cache.h"
@@ -746,6 +747,7 @@ static bool CompileOptimizedPrologue(CompilationInfo* info) {
   if (!Parser::Parse(info)) return false;
   if (!Rewriter::Rewrite(info)) return false;
   if (!Scope::Analyze(info)) return false;
+  if (!AstNumbering::Renumber(info->function(), info->zone())) return false;
   DCHECK(info->scope() != NULL);
   return true;
 }
index 4564b90..47579bd 100644 (file)
@@ -391,8 +391,6 @@ class CompilationInfo {
     ast_value_factory_owned_ = owned;
   }
 
-  AstNode::IdGen* ast_node_id_gen() { return &ast_node_id_gen_; }
-
  protected:
   CompilationInfo(Handle<Script> script,
                   Zone* zone);
@@ -512,7 +510,6 @@ class CompilationInfo {
 
   AstValueFactory* ast_value_factory_;
   bool ast_value_factory_owned_;
-  AstNode::IdGen ast_node_id_gen_;
 
   // This flag is used by the main thread to track whether this compilation
   // should be abandoned due to dependency change.
index f834602..f4e6d40 100644 (file)
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "src/ast.h"
+#include "src/ast-numbering.h"
 #include "src/compiler/access-builder.h"
 #include "src/compiler/ast-graph-builder.h"
 #include "src/compiler/common-operator.h"
@@ -63,6 +65,7 @@ static void Parse(Handle<JSFunction> function, CompilationInfoWithZone* info) {
   CHECK(Parser::Parse(info));
   CHECK(Rewriter::Rewrite(info));
   CHECK(Scope::Analyze(info));
+  CHECK(AstNumbering::Renumber(info->function(), info->zone()));
   CHECK(Compiler::EnsureDeoptimizationSupport(info));
 }
 
index 89ae329..9d31cd5 100644 (file)
@@ -4,6 +4,8 @@
 
 #include "src/v8.h"
 
+#include "src/ast.h"
+#include "src/ast-numbering.h"
 #include "src/code-factory.h"
 #include "src/codegen.h"
 #include "src/compiler.h"
@@ -306,6 +308,11 @@ bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
 
   TimerEventScope<TimerEventCompileFullCode> timer(info->isolate());
 
+  if (!AstNumbering::Renumber(info->function(), info->zone())) {
+    DCHECK(!isolate->has_pending_exception());
+    return false;
+  }
+
   Handle<Script> script = info->script();
   if (!script->IsUndefined() && !script->source()->IsUndefined()) {
     int len = String::cast(script->source())->length();
index 3f9d32d..663bafb 100644 (file)
@@ -9,6 +9,7 @@
 #include "src/v8.h"
 
 #include "src/allocation-site-scopes.h"
+#include "src/ast-numbering.h"
 #include "src/full-codegen.h"
 #include "src/hydrogen-bce.h"
 #include "src/hydrogen-bch.h"
@@ -7830,7 +7831,8 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
   // step, but don't transfer ownership to target_info.
   target_info.SetAstValueFactory(top_info()->ast_value_factory(), false);
   Handle<SharedFunctionInfo> target_shared(target->shared());
-  if (!Parser::Parse(&target_info) || !Scope::Analyze(&target_info)) {
+  if (!Parser::Parse(&target_info) || !Scope::Analyze(&target_info) ||
+      !AstNumbering::Renumber(target_info.function(), target_info.zone())) {
     if (target_info.isolate()->has_pending_exception()) {
       // Parse or scope error, never optimize this function.
       SetStackOverflow();
index a972a62..bec0a4b 100644 (file)
@@ -736,8 +736,7 @@ FunctionLiteral* ParserTraits::ParseFunctionLiteral(
 
 Parser::Parser(CompilationInfo* info, ParseInfo* parse_info)
     : ParserBase<ParserTraits>(&scanner_, parse_info->stack_limit,
-                               info->extension(), NULL, info->zone(),
-                               info->ast_node_id_gen(), this),
+                               info->extension(), NULL, info->zone(), this),
       scanner_(parse_info->unicode_cache),
       reusable_preparser_(NULL),
       original_scope_(NULL),
@@ -879,7 +878,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope,
 
     // Enters 'scope'.
     AstNodeFactory<AstConstructionVisitor> function_factory(
-        zone(), ast_value_factory(), info->ast_node_id_gen());
+        ast_value_factory());
     FunctionState function_state(&function_state_, &scope_, *scope,
                                  &function_factory);
 
@@ -994,7 +993,7 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
     }
     original_scope_ = scope;
     AstNodeFactory<AstConstructionVisitor> function_factory(
-        zone(), ast_value_factory(), info()->ast_node_id_gen());
+        ast_value_factory());
     FunctionState function_state(&function_state_, &scope_, scope,
                                  &function_factory);
     DCHECK(scope->strict_mode() == SLOPPY || info()->strict_mode() == STRICT);
@@ -3496,7 +3495,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
   // Parse function body.
   {
     AstNodeFactory<AstConstructionVisitor> function_factory(
-        zone(), ast_value_factory(), info()->ast_node_id_gen());
+        ast_value_factory());
     FunctionState function_state(&function_state_, &scope_, scope,
                                  &function_factory);
     scope_->SetScopeName(function_name);
index a75ff30..987900a 100644 (file)
@@ -104,11 +104,11 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction(
   log_ = log;
   // Lazy functions always have trivial outer scopes (no with/catch scopes).
   PreParserScope top_scope(scope_, GLOBAL_SCOPE);
-  PreParserFactory top_factory(NULL, NULL, NULL);
+  PreParserFactory top_factory(NULL);
   FunctionState top_state(&function_state_, &scope_, &top_scope, &top_factory);
   scope_->SetStrictMode(strict_mode);
   PreParserScope function_scope(scope_, FUNCTION_SCOPE);
-  PreParserFactory function_factory(NULL, NULL, NULL);
+  PreParserFactory function_factory(NULL);
   FunctionState function_state(&function_state_, &scope_, &function_scope,
                                &function_factory);
   function_state.set_is_generator(is_generator);
@@ -813,7 +813,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
   // Parse function body.
   ScopeType outer_scope_type = scope_->type();
   PreParserScope function_scope(scope_, FUNCTION_SCOPE);
-  PreParserFactory factory(NULL, NULL, NULL);
+  PreParserFactory factory(NULL);
   FunctionState function_state(&function_state_, &scope_, &function_scope,
                                &factory);
   function_state.set_is_generator(IsGeneratorFunction(kind));
index 20bf9e9..fd82651 100644 (file)
@@ -70,7 +70,6 @@ class ParserBase : public Traits {
 
   ParserBase(Scanner* scanner, uintptr_t stack_limit, v8::Extension* extension,
              ParserRecorder* log, typename Traits::Type::Zone* zone,
-             AstNode::IdGen* ast_node_id_gen,
              typename Traits::Type::Parser this_object)
       : Traits(this_object),
         parenthesized_function_(false),
@@ -87,8 +86,7 @@ class ParserBase : public Traits {
         allow_natives_syntax_(false),
         allow_arrow_functions_(false),
         allow_harmony_object_literals_(false),
-        zone_(zone),
-        ast_node_id_gen_(ast_node_id_gen) {}
+        zone_(zone) {}
 
   // Getters that indicate whether certain syntactical constructs are
   // allowed to be parsed by this instance of the parser.
@@ -277,7 +275,6 @@ class ParserBase : public Traits {
   void set_stack_overflow() { stack_overflow_ = true; }
   Mode mode() const { return mode_; }
   typename Traits::Type::Zone* zone() const { return zone_; }
-  AstNode::IdGen* ast_node_id_gen() const { return ast_node_id_gen_; }
 
   INLINE(Token::Value peek()) {
     if (stack_overflow_) return Token::ILLEGAL;
@@ -580,7 +577,6 @@ class ParserBase : public Traits {
   bool allow_harmony_object_literals_;
 
   typename Traits::Type::Zone* zone_;  // Only used by Parser.
-  AstNode::IdGen* ast_node_id_gen_;
 };
 
 
@@ -972,7 +968,7 @@ class PreParserScope {
 
 class PreParserFactory {
  public:
-  PreParserFactory(void*, void*, void*) {}
+  explicit PreParserFactory(void* unused_value_factory) {}
   PreParserExpression NewStringLiteral(PreParserIdentifier identifier,
                                        int pos) {
     return PreParserExpression::Default();
@@ -1417,7 +1413,7 @@ class PreParser : public ParserBase<PreParserTraits> {
   };
 
   PreParser(Scanner* scanner, ParserRecorder* log, uintptr_t stack_limit)
-      : ParserBase<PreParserTraits>(scanner, stack_limit, NULL, log, NULL, NULL,
+      : ParserBase<PreParserTraits>(scanner, stack_limit, NULL, log, NULL,
                                     this) {}
 
   // Pre-parse the program from the character stream; returns true on
@@ -1426,7 +1422,7 @@ class PreParser : public ParserBase<PreParserTraits> {
   // during parsing.
   PreParseResult PreParseProgram() {
     PreParserScope scope(scope_, GLOBAL_SCOPE);
-    PreParserFactory factory(NULL, NULL, NULL);
+    PreParserFactory factory(NULL);
     FunctionState top_scope(&function_state_, &scope_, &scope, &factory);
     bool ok = true;
     int start_position = scanner()->peek_location().beg_pos;
@@ -2616,8 +2612,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<
   int handler_count = 0;
 
   {
-    typename Traits::Type::Factory function_factory(
-        zone(), this->ast_value_factory(), ast_node_id_gen_);
+    typename Traits::Type::Factory function_factory(this->ast_value_factory());
     FunctionState function_state(&function_state_, &scope_,
                                  Traits::Type::ptr_to_scope(scope),
                                  &function_factory);
index 8616960..e870e90 100644 (file)
@@ -15,15 +15,13 @@ namespace internal {
 
 class Processor: public AstVisitor {
  public:
-  Processor(Variable* result, Zone* zone, AstNode::IdGen* ast_node_id_gen)
+  Processor(Variable* result, AstValueFactory* ast_value_factory)
       : result_(result),
         result_assigned_(false),
         is_set_(false),
         in_try_(false),
-        // Passing a null AstValueFactory is fine, because Processor doesn't
-        // need to create strings or literals.
-        factory_(zone, NULL, ast_node_id_gen) {
-    InitializeAstVisitor(zone);
+        factory_(ast_value_factory) {
+    InitializeAstVisitor(ast_value_factory->zone());
   }
 
   virtual ~Processor() { }
@@ -240,7 +238,7 @@ bool Rewriter::Rewrite(CompilationInfo* info) {
         scope->NewTemporary(info->ast_value_factory()->dot_result_string());
     // The name string must be internalized at this point.
     DCHECK(!result->name().is_null());
-    Processor processor(result, info->zone(), info->ast_node_id_gen());
+    Processor processor(result, info->ast_value_factory());
     processor.Process(body);
     if (processor.HasStackOverflow()) return false;
 
index fd803b3..51c0065 100644 (file)
@@ -275,8 +275,7 @@ bool Scope::Analyze(CompilationInfo* info) {
 
   // Allocate the variables.
   {
-    AstNodeFactory<AstNullVisitor> ast_node_factory(
-        info->zone(), info->ast_value_factory(), info->ast_node_id_gen());
+    AstNodeFactory<AstNullVisitor> ast_node_factory(info->ast_value_factory());
     if (!top->AllocateVariables(info, &ast_node_factory)) return false;
   }
 
index a5a71a7..34c663f 100644 (file)
@@ -8,6 +8,7 @@
 #include "src/v8.h"
 #include "test/cctest/cctest.h"
 
+#include "src/ast-numbering.h"
 #include "src/compiler.h"
 #include "src/compiler/linkage.h"
 #include "src/compiler/pipeline.h"
@@ -166,6 +167,7 @@ class FunctionTester : public InitializedHandleScope {
     }
     CHECK(Rewriter::Rewrite(&info));
     CHECK(Scope::Analyze(&info));
+    CHECK(AstNumbering::Renumber(info.function(), info.zone()));
     CHECK(Compiler::EnsureDeoptimizationSupport(&info));
 
     Pipeline pipeline(&info);
@@ -215,6 +217,7 @@ class FunctionTester : public InitializedHandleScope {
                        Handle<Code>(function->shared()->code()));
     CHECK(Rewriter::Rewrite(&info));
     CHECK(Scope::Analyze(&info));
+    CHECK(AstNumbering::Renumber(info.function(), info.zone()));
     CHECK(Compiler::EnsureDeoptimizationSupport(&info));
 
     Pipeline pipeline(&info);
index 3b5a737..0d2d5d1 100644 (file)
@@ -16,6 +16,7 @@
 #include "src/compiler/register-allocator.h"
 #include "src/compiler/schedule.h"
 
+#include "src/ast-numbering.h"
 #include "src/full-codegen.h"
 #include "src/parser.h"
 #include "src/rewriter.h"
@@ -48,6 +49,7 @@ class DeoptCodegenTester {
     info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
     CHECK(Rewriter::Rewrite(&info));
     CHECK(Scope::Analyze(&info));
+    CHECK(AstNumbering::Renumber(info.function(), info.zone()));
     CHECK(Compiler::EnsureDeoptimizationSupport(&info));
 
     DCHECK(info.shared_info()->has_deoptimization_support());
index f0b750a..9d8a2d1 100644 (file)
@@ -5,6 +5,7 @@
 #include "src/v8.h"
 #include "test/cctest/cctest.h"
 
+#include "src/ast-numbering.h"
 #include "src/compiler.h"
 #include "src/compiler/pipeline.h"
 #include "src/handles.h"
@@ -25,6 +26,7 @@ TEST(PipelineAdd) {
   CHECK(Parser::Parse(&info));
   CHECK(Rewriter::Rewrite(&info));
   CHECK(Scope::Analyze(&info));
+  CHECK(AstNumbering::Renumber(info.function(), info.zone()));
   CHECK_NE(NULL, info.scope());
 
   Pipeline pipeline(&info);
index 24819df..31d5eba 100644 (file)
@@ -40,8 +40,8 @@ TEST(List) {
 
   Isolate* isolate = CcTest::i_isolate();
   Zone zone(isolate);
-  AstNode::IdGen id_gen;
-  AstNodeFactory<AstNullVisitor> factory(&zone, NULL, &id_gen);
+  AstValueFactory value_factory(&zone, 0);
+  AstNodeFactory<AstNullVisitor> factory(&value_factory);
   AstNode* node = factory.NewEmptyStatement(RelocInfo::kNoPosition);
   list->Add(node);
   CHECK_EQ(1, list->length());
index d33d037..700d104 100644 (file)
@@ -31,6 +31,8 @@
 
 #include "src/v8.h"
 
+#include "src/ast.h"
+#include "src/ast-numbering.h"
 #include "src/ast-value-factory.h"
 #include "src/compiler.h"
 #include "src/execution.h"
@@ -3273,6 +3275,7 @@ TEST(InnerAssignment) {
           CHECK(parser.Parse());
           CHECK(i::Rewriter::Rewrite(&info));
           CHECK(i::Scope::Analyze(&info));
+          CHECK(i::AstNumbering::Renumber(info.function(), info.zone()));
           CHECK(info.function() != NULL);
 
           i::Scope* scope = info.function()->scope();
index b8317cb..57296e7 100644 (file)
         '../../src/assert-scope.cc',
         '../../src/ast-value-factory.cc',
         '../../src/ast-value-factory.h',
+        '../../src/ast-numbering.cc',
+        '../../src/ast-numbering.h',
         '../../src/ast.cc',
         '../../src/ast.h',
         '../../src/background-parsing-task.cc',