Version 3.22.12

Added histograms to track fraction of heap spaces and percentage of generated crankshaft code.

Moved v8_optimized_debug default value to standalone.gypi.

Track JS allocations as they arrive with no affection on performance when tracking is switched off (Chromium issue 277984).

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@17205 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 7263730..fc2d8ee 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2013-10-15: Version 3.22.12
+
+        Added histograms to track fraction of heap spaces and percentage of
+        generated crankshaft code.
+
+        Moved v8_optimized_debug default value to standalone.gypi.
+
+        Track JS allocations as they arrive with no affection on performance
+        when tracking is switched off (Chromium issue 277984).
+
+        Performance and stability improvements on all platforms.
+
+
 2013-10-14: Version 3.22.11
 
         Performance and stability improvements on all platforms.
diff --git a/build/standalone.gypi b/build/standalone.gypi
index 3d4f804..4cb5e00 100644
--- a/build/standalone.gypi
+++ b/build/standalone.gypi
@@ -77,6 +77,20 @@
     # as errors.
     'v8_code%': 0,
 
+    # Speeds up Debug builds:
+    # 0 - Compiler optimizations off (debuggable) (default). This may
+    #     be 5x slower than Release (or worse).
+    # 1 - Turn on compiler optimizations. This may be hard or impossible to
+    #     debug. This may still be 2x slower than Release (or worse).
+    # 2 - Turn on optimizations, and also #undef DEBUG / #define NDEBUG
+    #     (but leave V8_ENABLE_CHECKS and most other assertions enabled.
+    #     This may cause some v8 tests to fail in the Debug configuration.
+    #     This roughly matches the performance of a Release build and can
+    #     be used by embedders that need to build their own code as debug
+    #     but don't want or need a debug version of V8. This should produce
+    #     near-release speeds.
+    'v8_optimized_debug%': 0,
+
     # Relative path to icu.gyp from this file.
     'icu_gyp_path': '../third_party/icu/icu.gyp',
 
diff --git a/build/toolchain.gypi b/build/toolchain.gypi
index c1066eb..e1903f3 100644
--- a/build/toolchain.gypi
+++ b/build/toolchain.gypi
@@ -60,20 +60,6 @@
 
     'v8_enable_backtrace%': 0,
 
-    # Speeds up Debug builds:
-    # 0 - Compiler optimizations off (debuggable) (default). This may
-    #     be 5x slower than Release (or worse).
-    # 1 - Turn on compiler optimizations. This may be hard or impossible to
-    #     debug. This may still be 2x slower than Release (or worse).
-    # 2 - Turn on optimizations, and also #undef DEBUG / #define NDEBUG
-    #     (but leave V8_ENABLE_CHECKS and most other assertions enabled.
-    #     This may cause some v8 tests to fail in the Debug configuration.
-    #     This roughly matches the performance of a Release build and can
-    #     be used by embedders that need to build their own code as debug
-    #     but don't want or need a debug version of V8. This should produce
-    #     near-release speeds.
-    'v8_optimized_debug%': 0,
-
     # Enable profiling support. Only required on Windows.
     'v8_enable_prof%': 0,
 
diff --git a/include/v8-profiler.h b/include/v8-profiler.h
index 7016a79..0882d64 100644
--- a/include/v8-profiler.h
+++ b/include/v8-profiler.h
@@ -475,6 +475,19 @@
    */
   void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
 
+  /**
+   * Starts recording JS allocations immediately as they arrive and tracking of
+   * heap objects population statistics.
+   */
+  void StartRecordingHeapAllocations();
+
+  /**
+   * Stops recording JS allocations and tracking of heap objects population
+   * statistics, cleans all collected heap objects population statistics data.
+   */
+  void StopRecordingHeapAllocations();
+
+
  private:
   HeapProfiler();
   ~HeapProfiler();
diff --git a/include/v8.h b/include/v8.h
index 5ab8d40..1ec0481 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -5393,7 +5393,7 @@
   static const int kNullValueRootIndex = 7;
   static const int kTrueValueRootIndex = 8;
   static const int kFalseValueRootIndex = 9;
-  static const int kEmptyStringRootIndex = 131;
+  static const int kEmptyStringRootIndex = 132;
 
   static const int kNodeClassIdOffset = 1 * kApiPointerSize;
   static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3;
@@ -5404,7 +5404,7 @@
   static const int kNodeIsIndependentShift = 4;
   static const int kNodeIsPartiallyDependentShift = 5;
 
-  static const int kJSObjectType = 0xb1;
+  static const int kJSObjectType = 0xb2;
   static const int kFirstNonstringType = 0x80;
   static const int kOddballType = 0x83;
   static const int kForeignType = 0x87;
diff --git a/src/api.cc b/src/api.cc
index 32a3db6..469c7a1 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -7300,6 +7300,16 @@
 }
 
 
+void HeapProfiler::StartRecordingHeapAllocations() {
+  reinterpret_cast<i::HeapProfiler*>(this)->StartHeapAllocationsRecording();
+}
+
+
+void HeapProfiler::StopRecordingHeapAllocations() {
+  reinterpret_cast<i::HeapProfiler*>(this)->StopHeapAllocationsRecording();
+}
+
+
 v8::Testing::StressType internal::Testing::stress_type_ =
     v8::Testing::kStressTypeOpt;
 
diff --git a/src/assembler.cc b/src/assembler.cc
index c6228eb..54ee69a 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -1333,6 +1333,14 @@
 }
 
 
+ExternalReference ExternalReference::record_object_allocation_function(
+  Isolate* isolate) {
+  return ExternalReference(
+      Redirect(isolate,
+               FUNCTION_ADDR(HeapProfiler::RecordObjectAllocationFromMasm)));
+}
+
+
 #ifndef V8_INTERPRETED_REGEXP
 
 ExternalReference ExternalReference::re_check_stack_guard_state(
diff --git a/src/assembler.h b/src/assembler.h
index 3bba98b..9888ac2 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -728,6 +728,9 @@
 
   static ExternalReference get_make_code_young_function(Isolate* isolate);
 
+  // New heap objects tracking support.
+  static ExternalReference record_object_allocation_function(Isolate* isolate);
+
   // Deoptimization support.
   static ExternalReference new_deoptimizer_function(Isolate* isolate);
   static ExternalReference compute_output_frames_function(Isolate* isolate);
diff --git a/src/ast.cc b/src/ast.cc
index 1093b3c..0d667cc 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -82,14 +82,13 @@
 }
 
 
-VariableProxy::VariableProxy(Isolate* isolate, Variable* var)
-    : Expression(isolate),
+VariableProxy::VariableProxy(Isolate* isolate, Variable* var, int position)
+    : Expression(isolate, position),
       name_(var->name()),
       var_(NULL),  // Will be set by the call to BindTo.
       is_this_(var->is_this()),
       is_trivial_(false),
       is_lvalue_(false),
-      position_(RelocInfo::kNoPosition),
       interface_(var->interface()) {
   BindTo(var);
 }
@@ -100,13 +99,12 @@
                              bool is_this,
                              Interface* interface,
                              int position)
-    : Expression(isolate),
+    : Expression(isolate, position),
       name_(name),
       var_(NULL),
       is_this_(is_this),
       is_trivial_(false),
       is_lvalue_(false),
-      position_(position),
       interface_(interface) {
   // Names must be canonicalized for fast equality checks.
   ASSERT(name->IsInternalizedString());
@@ -133,11 +131,10 @@
                        Expression* target,
                        Expression* value,
                        int pos)
-    : Expression(isolate),
+    : Expression(isolate, pos),
       op_(op),
       target_(target),
       value_(value),
-      pos_(pos),
       binary_operation_(NULL),
       assignment_id_(GetNextId(isolate)),
       is_monomorphic_(false),
@@ -444,8 +441,7 @@
   } else if (oracle->LoadIsBuiltin(this, Builtins::kKeyedLoadIC_String)) {
     is_string_access_ = true;
   } else if (is_monomorphic_) {
-    receiver_types_.Add(oracle->LoadMonomorphicReceiverType(this),
-                        zone);
+    receiver_types_.Add(oracle->LoadMonomorphicReceiverType(this), zone);
   } else if (oracle->LoadIsPolymorphic(this)) {
     receiver_types_.Reserve(kMaxKeyedPolymorphism, zone);
     oracle->CollectKeyedReceiverTypes(PropertyFeedbackId(), &receiver_types_);
@@ -1037,9 +1033,9 @@
                        Expression* label,
                        ZoneList<Statement*>* statements,
                        int pos)
-    : label_(label),
+    : AstNode(pos),
+      label_(label),
       statements_(statements),
-      position_(pos),
       compare_type_(Type::None(), isolate),
       compare_id_(AstNode::GetNextId(isolate)),
       entry_id_(AstNode::GetNextId(isolate)) {
@@ -1081,6 +1077,7 @@
 REGULAR_NODE(BreakStatement)
 REGULAR_NODE(ReturnStatement)
 REGULAR_NODE(SwitchStatement)
+REGULAR_NODE(CaseClause)
 REGULAR_NODE(Conditional)
 REGULAR_NODE(Literal)
 REGULAR_NODE(ArrayLiteral)
diff --git a/src/ast.h b/src/ast.h
index 7432b0b..4b2010f 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -117,11 +117,15 @@
   V(CompareOperation)                           \
   V(ThisFunction)
 
+#define AUXILIARY_NODE_LIST(V)                  \
+  V(CaseClause)
+
 #define AST_NODE_LIST(V)                        \
   DECLARATION_NODE_LIST(V)                      \
   MODULE_NODE_LIST(V)                           \
   STATEMENT_NODE_LIST(V)                        \
-  EXPRESSION_NODE_LIST(V)
+  EXPRESSION_NODE_LIST(V)                       \
+  AUXILIARY_NODE_LIST(V)
 
 // Forward declarations
 class AstConstructionVisitor;
@@ -206,12 +210,12 @@
     return zone->New(static_cast<int>(size));
   }
 
-  AstNode() {}
-
+  explicit AstNode(int position): position_(position) {}
   virtual ~AstNode() {}
 
   virtual void Accept(AstVisitor* v) = 0;
   virtual NodeType node_type() const = 0;
+  int position() const { return position_; }
 
   // Type testing & conversion functions overridden by concrete subclasses.
 #define DECLARE_NODE_FUNCTIONS(type)                  \
@@ -248,21 +252,17 @@
   void* operator new(size_t size);
 
   friend class CaseClause;  // Generates AST IDs.
+
+  int position_;
 };
 
 
 class Statement : public AstNode {
  public:
-  Statement() : statement_pos_(RelocInfo::kNoPosition) {}
+  explicit Statement(int position) : AstNode(position) {}
 
   bool IsEmpty() { return AsEmptyStatement() != NULL; }
   virtual bool IsJump() const { return false; }
-
-  void set_statement_pos(int statement_pos) { statement_pos_ = statement_pos; }
-  int statement_pos() const { return statement_pos_; }
-
- private:
-  int statement_pos_;
 };
 
 
@@ -329,11 +329,6 @@
     kTest
   };
 
-  virtual int position() const {
-    UNREACHABLE();
-    return 0;
-  }
-
   virtual bool IsValidLeftHandSide() { return false; }
 
   // Helpers for ToBoolean conversion.
@@ -387,8 +382,9 @@
   TypeFeedbackId test_id() const { return test_id_; }
 
  protected:
-  explicit Expression(Isolate* isolate)
-      : bounds_(Bounds::Unbounded(isolate)),
+  Expression(Isolate* isolate, int pos)
+      : AstNode(pos),
+        bounds_(Bounds::Unbounded(isolate)),
         id_(GetNextId(isolate)),
         test_id_(GetNextId(isolate)) {}
   void set_to_boolean_types(byte types) { to_boolean_types_ = types; }
@@ -431,8 +427,10 @@
 
  protected:
   BreakableStatement(
-      Isolate* isolate, ZoneStringList* labels, BreakableType breakable_type)
-      : labels_(labels),
+      Isolate* isolate, ZoneStringList* labels,
+      BreakableType breakable_type, int position)
+      : Statement(position),
+        labels_(labels),
         breakable_type_(breakable_type),
         entry_id_(GetNextId(isolate)),
         exit_id_(GetNextId(isolate)) {
@@ -473,8 +471,9 @@
         ZoneStringList* labels,
         int capacity,
         bool is_initializer_block,
+        int pos,
         Zone* zone)
-      : BreakableStatement(isolate, labels, TARGET_FOR_NAMED_ONLY),
+      : BreakableStatement(isolate, labels, TARGET_FOR_NAMED_ONLY, pos),
         statements_(capacity, zone),
         is_initializer_block_(is_initializer_block),
         scope_(NULL) {
@@ -498,8 +497,10 @@
  protected:
   Declaration(VariableProxy* proxy,
               VariableMode mode,
-              Scope* scope)
-      : proxy_(proxy),
+              Scope* scope,
+              int pos)
+      : AstNode(pos),
+        proxy_(proxy),
         mode_(mode),
         scope_(scope) {
     ASSERT(IsDeclaredVariableMode(mode));
@@ -525,8 +526,9 @@
  protected:
   VariableDeclaration(VariableProxy* proxy,
                       VariableMode mode,
-                      Scope* scope)
-      : Declaration(proxy, mode, scope) {
+                      Scope* scope,
+                      int pos)
+      : Declaration(proxy, mode, scope, pos) {
   }
 };
 
@@ -545,8 +547,9 @@
   FunctionDeclaration(VariableProxy* proxy,
                       VariableMode mode,
                       FunctionLiteral* fun,
-                      Scope* scope)
-      : Declaration(proxy, mode, scope),
+                      Scope* scope,
+                      int pos)
+      : Declaration(proxy, mode, scope, pos),
         fun_(fun) {
     // At the moment there are no "const functions" in JavaScript...
     ASSERT(mode == VAR || mode == LET);
@@ -570,8 +573,9 @@
  protected:
   ModuleDeclaration(VariableProxy* proxy,
                     Module* module,
-                    Scope* scope)
-      : Declaration(proxy, MODULE, scope),
+                    Scope* scope,
+                    int pos)
+      : Declaration(proxy, MODULE, scope, pos),
         module_(module) {
   }
 
@@ -592,8 +596,9 @@
  protected:
   ImportDeclaration(VariableProxy* proxy,
                     Module* module,
-                    Scope* scope)
-      : Declaration(proxy, LET, scope),
+                    Scope* scope,
+                    int pos)
+      : Declaration(proxy, LET, scope, pos),
         module_(module) {
   }
 
@@ -611,8 +616,8 @@
   }
 
  protected:
-  ExportDeclaration(VariableProxy* proxy, Scope* scope)
-      : Declaration(proxy, LET, scope) {}
+  ExportDeclaration(VariableProxy* proxy, Scope* scope, int pos)
+      : Declaration(proxy, LET, scope, pos) {}
 };
 
 
@@ -622,11 +627,13 @@
   Block* body() const { return body_; }
 
  protected:
-  explicit Module(Zone* zone)
-      : interface_(Interface::NewModule(zone)),
+  Module(Zone* zone, int pos)
+      : AstNode(pos),
+        interface_(Interface::NewModule(zone)),
         body_(NULL) {}
-  explicit Module(Interface* interface, Block* body = NULL)
-      : interface_(interface),
+  Module(Interface* interface, int pos, Block* body = NULL)
+      : AstNode(pos),
+        interface_(interface),
         body_(body) {}
 
  private:
@@ -640,7 +647,8 @@
   DECLARE_NODE_TYPE(ModuleLiteral)
 
  protected:
-  ModuleLiteral(Block* body, Interface* interface) : Module(interface, body) {}
+  ModuleLiteral(Block* body, Interface* interface, int pos)
+      : Module(interface, pos, body) {}
 };
 
 
@@ -651,7 +659,7 @@
   VariableProxy* proxy() const { return proxy_; }
 
  protected:
-  inline explicit ModuleVariable(VariableProxy* proxy);
+  inline ModuleVariable(VariableProxy* proxy, int pos);
 
  private:
   VariableProxy* proxy_;
@@ -666,8 +674,8 @@
   Handle<String> name() const { return name_; }
 
  protected:
-  ModulePath(Module* module, Handle<String> name, Zone* zone)
-      : Module(zone),
+  ModulePath(Module* module, Handle<String> name, Zone* zone, int pos)
+      : Module(zone, pos),
         module_(module),
         name_(name) {
   }
@@ -685,8 +693,8 @@
   Handle<String> url() const { return url_; }
 
  protected:
-  ModuleUrl(Handle<String> url, Zone* zone)
-      : Module(zone), url_(url) {
+  ModuleUrl(Handle<String> url, Zone* zone, int pos)
+      : Module(zone, pos), url_(url) {
   }
 
  private:
@@ -702,8 +710,9 @@
   Block* body() const { return body_; }
 
  protected:
-  ModuleStatement(VariableProxy* proxy, Block* body)
-      : proxy_(proxy),
+  ModuleStatement(VariableProxy* proxy, Block* body, int pos)
+      : Statement(pos),
+        proxy_(proxy),
         body_(body) {
   }
 
@@ -730,8 +739,8 @@
   Label* continue_target()  { return &continue_target_; }
 
  protected:
-  IterationStatement(Isolate* isolate, ZoneStringList* labels)
-      : BreakableStatement(isolate, labels, TARGET_FOR_ANONYMOUS),
+  IterationStatement(Isolate* isolate, ZoneStringList* labels, int pos)
+      : BreakableStatement(isolate, labels, TARGET_FOR_ANONYMOUS, pos),
         body_(NULL),
         osr_entry_id_(GetNextId(isolate)) {
   }
@@ -759,20 +768,14 @@
 
   Expression* cond() const { return cond_; }
 
-  // Position where condition expression starts. We need it to make
-  // the loop's condition a breakable location.
-  int condition_position() { return condition_position_; }
-  void set_condition_position(int pos) { condition_position_ = pos; }
-
   virtual BailoutId ContinueId() const V8_OVERRIDE { return continue_id_; }
   virtual BailoutId StackCheckId() const V8_OVERRIDE { return back_edge_id_; }
   BailoutId BackEdgeId() const { return back_edge_id_; }
 
  protected:
-  DoWhileStatement(Isolate* isolate, ZoneStringList* labels)
-      : IterationStatement(isolate, labels),
+  DoWhileStatement(Isolate* isolate, ZoneStringList* labels, int pos)
+      : IterationStatement(isolate, labels, pos),
         cond_(NULL),
-        condition_position_(-1),
         continue_id_(GetNextId(isolate)),
         back_edge_id_(GetNextId(isolate)) {
   }
@@ -780,8 +783,6 @@
  private:
   Expression* cond_;
 
-  int condition_position_;
-
   const BailoutId continue_id_;
   const BailoutId back_edge_id_;
 };
@@ -809,8 +810,8 @@
   BailoutId BodyId() const { return body_id_; }
 
  protected:
-  WhileStatement(Isolate* isolate, ZoneStringList* labels)
-      : IterationStatement(isolate, labels),
+  WhileStatement(Isolate* isolate, ZoneStringList* labels, int pos)
+      : IterationStatement(isolate, labels, pos),
         cond_(NULL),
         may_have_function_literal_(true),
         body_id_(GetNextId(isolate)) {
@@ -860,8 +861,8 @@
   void set_loop_variable(Variable* var) { loop_variable_ = var; }
 
  protected:
-  ForStatement(Isolate* isolate, ZoneStringList* labels)
-      : IterationStatement(isolate, labels),
+  ForStatement(Isolate* isolate, ZoneStringList* labels, int pos)
+      : IterationStatement(isolate, labels, pos),
         init_(NULL),
         cond_(NULL),
         next_(NULL),
@@ -902,8 +903,8 @@
   Expression* subject() const { return subject_; }
 
  protected:
-  ForEachStatement(Isolate* isolate, ZoneStringList* labels)
-      : IterationStatement(isolate, labels),
+  ForEachStatement(Isolate* isolate, ZoneStringList* labels, int pos)
+      : IterationStatement(isolate, labels, pos),
         each_(NULL),
         subject_(NULL) {
   }
@@ -933,8 +934,8 @@
   virtual BailoutId StackCheckId() const V8_OVERRIDE { return body_id_; }
 
  protected:
-  ForInStatement(Isolate* isolate, ZoneStringList* labels)
-      : ForEachStatement(isolate, labels),
+  ForInStatement(Isolate* isolate, ZoneStringList* labels, int pos)
+      : ForEachStatement(isolate, labels, pos),
         for_in_type_(SLOW_FOR_IN),
         body_id_(GetNextId(isolate)),
         prepare_id_(GetNextId(isolate)) {
@@ -994,8 +995,8 @@
   BailoutId BackEdgeId() const { return back_edge_id_; }
 
  protected:
-  ForOfStatement(Isolate* isolate, ZoneStringList* labels)
-      : ForEachStatement(isolate, labels),
+  ForOfStatement(Isolate* isolate, ZoneStringList* labels, int pos)
+      : ForEachStatement(isolate, labels, pos),
         assign_iterator_(NULL),
         next_result_(NULL),
         result_done_(NULL),
@@ -1020,8 +1021,8 @@
   virtual bool IsJump() const V8_OVERRIDE { return expression_->IsThrow(); }
 
  protected:
-  explicit ExpressionStatement(Expression* expression)
-      : expression_(expression) { }
+  ExpressionStatement(Expression* expression, int pos)
+      : Statement(pos), expression_(expression) { }
 
  private:
   Expression* expression_;
@@ -1033,7 +1034,7 @@
   virtual bool IsJump() const V8_FINAL V8_OVERRIDE { return true; }
 
  protected:
-  JumpStatement() {}
+  explicit JumpStatement(int pos) : Statement(pos) {}
 };
 
 
@@ -1044,8 +1045,8 @@
   IterationStatement* target() const { return target_; }
 
  protected:
-  explicit ContinueStatement(IterationStatement* target)
-      : target_(target) { }
+  explicit ContinueStatement(IterationStatement* target, int pos)
+      : JumpStatement(pos), target_(target) { }
 
  private:
   IterationStatement* target_;
@@ -1059,8 +1060,8 @@
   BreakableStatement* target() const { return target_; }
 
  protected:
-  explicit BreakStatement(BreakableStatement* target)
-      : target_(target) { }
+  explicit BreakStatement(BreakableStatement* target, int pos)
+      : JumpStatement(pos), target_(target) { }
 
  private:
   BreakableStatement* target_;
@@ -1074,8 +1075,8 @@
   Expression* expression() const { return expression_; }
 
  protected:
-  explicit ReturnStatement(Expression* expression)
-      : expression_(expression) { }
+  explicit ReturnStatement(Expression* expression, int pos)
+      : JumpStatement(pos), expression_(expression) { }
 
  private:
   Expression* expression_;
@@ -1091,8 +1092,10 @@
   Statement* statement() const { return statement_; }
 
  protected:
-  WithStatement(Scope* scope, Expression* expression, Statement* statement)
-      : scope_(scope),
+  WithStatement(
+      Scope* scope, Expression* expression, Statement* statement, int pos)
+      : Statement(pos),
+        scope_(scope),
         expression_(expression),
         statement_(statement) { }
 
@@ -1103,12 +1106,9 @@
 };
 
 
-class CaseClause V8_FINAL : public ZoneObject {
+class CaseClause V8_FINAL : public AstNode {
  public:
-  CaseClause(Isolate* isolate,
-             Expression* label,
-             ZoneList<Statement*>* statements,
-             int pos);
+  DECLARE_NODE_TYPE(CaseClause)
 
   bool is_default() const { return label_ == NULL; }
   Expression* label() const {
@@ -1118,9 +1118,6 @@
   Label* body_target() { return &body_target_; }
   ZoneList<Statement*>* statements() const { return statements_; }
 
-  int position() const { return position_; }
-  void set_position(int pos) { position_ = pos; }
-
   BailoutId EntryId() const { return entry_id_; }
 
   // Type feedback information.
@@ -1129,10 +1126,14 @@
   Handle<Type> compare_type() { return compare_type_; }
 
  private:
+  CaseClause(Isolate* isolate,
+             Expression* label,
+             ZoneList<Statement*>* statements,
+             int pos);
+
   Expression* label_;
   Label body_target_;
   ZoneList<Statement*>* statements_;
-  int position_;
   Handle<Type> compare_type_;
 
   const TypeFeedbackId compare_id_;
@@ -1158,8 +1159,8 @@
   void set_switch_type(SwitchType switch_type) { switch_type_ = switch_type; }
 
  protected:
-  SwitchStatement(Isolate* isolate, ZoneStringList* labels)
-      : BreakableStatement(isolate, labels, TARGET_FOR_ANONYMOUS),
+  SwitchStatement(Isolate* isolate, ZoneStringList* labels, int pos)
+      : BreakableStatement(isolate, labels, TARGET_FOR_ANONYMOUS, pos),
         tag_(NULL),
         cases_(NULL) { }
 
@@ -1199,8 +1200,10 @@
   IfStatement(Isolate* isolate,
               Expression* condition,
               Statement* then_statement,
-              Statement* else_statement)
-      : condition_(condition),
+              Statement* else_statement,
+              int pos)
+      : Statement(pos),
+        condition_(condition),
         then_statement_(then_statement),
         else_statement_(else_statement),
         if_id_(GetNextId(isolate)),
@@ -1222,7 +1225,8 @@
 // stack in the compiler; this should probably be reworked.
 class TargetCollector V8_FINAL : public AstNode {
  public:
-  explicit TargetCollector(Zone* zone) : targets_(0, zone) { }
+  explicit TargetCollector(Zone* zone)
+      : AstNode(RelocInfo::kNoPosition), targets_(0, zone) { }
 
   // 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
@@ -1252,8 +1256,9 @@
   ZoneList<Label*>* escaping_targets() const { return escaping_targets_; }
 
  protected:
-  TryStatement(int index, Block* try_block)
-      : index_(index),
+  TryStatement(int index, Block* try_block, int pos)
+      : Statement(pos),
+        index_(index),
         try_block_(try_block),
         escaping_targets_(NULL) { }
 
@@ -1279,8 +1284,9 @@
                     Block* try_block,
                     Scope* scope,
                     Variable* variable,
-                    Block* catch_block)
-      : TryStatement(index, try_block),
+                    Block* catch_block,
+                    int pos)
+      : TryStatement(index, try_block, pos),
         scope_(scope),
         variable_(variable),
         catch_block_(catch_block) {
@@ -1300,8 +1306,9 @@
   Block* finally_block() const { return finally_block_; }
 
  protected:
-  TryFinallyStatement(int index, Block* try_block, Block* finally_block)
-      : TryStatement(index, try_block),
+  TryFinallyStatement(
+      int index, Block* try_block, Block* finally_block, int pos)
+      : TryStatement(index, try_block, pos),
         finally_block_(finally_block) { }
 
  private:
@@ -1314,7 +1321,7 @@
   DECLARE_NODE_TYPE(DebuggerStatement)
 
  protected:
-  DebuggerStatement() {}
+  explicit DebuggerStatement(int pos): Statement(pos) {}
 };
 
 
@@ -1323,7 +1330,7 @@
   DECLARE_NODE_TYPE(EmptyStatement)
 
  protected:
-  EmptyStatement() {}
+  explicit EmptyStatement(int pos): Statement(pos) {}
 };
 
 
@@ -1380,8 +1387,9 @@
   TypeFeedbackId LiteralFeedbackId() const { return reuse(id()); }
 
  protected:
-  Literal(Isolate* isolate, Handle<Object> value)
-      : Expression(isolate),
+  Literal(
+      Isolate* isolate, Handle<Object> value, int position)
+      : Expression(isolate, position),
         value_(value),
         isolate_(isolate) { }
 
@@ -1411,8 +1419,9 @@
   MaterializedLiteral(Isolate* isolate,
                       int literal_index,
                       bool is_simple,
-                      int depth)
-      : Expression(isolate),
+                      int depth,
+                      int pos)
+      : Expression(isolate, pos),
         literal_index_(literal_index),
         is_simple_(is_simple),
         depth_(depth) {}
@@ -1510,8 +1519,9 @@
                 bool fast_elements,
                 int depth,
                 bool may_store_doubles,
-                bool has_function)
-      : MaterializedLiteral(isolate, literal_index, is_simple, depth),
+                bool has_function,
+                int pos)
+      : MaterializedLiteral(isolate, literal_index, is_simple, depth, pos),
         constant_properties_(constant_properties),
         properties_(properties),
         fast_elements_(fast_elements),
@@ -1539,8 +1549,9 @@
   RegExpLiteral(Isolate* isolate,
                 Handle<String> pattern,
                 Handle<String> flags,
-                int literal_index)
-      : MaterializedLiteral(isolate, literal_index, false, 1),
+                int literal_index,
+                int pos)
+      : MaterializedLiteral(isolate, literal_index, false, 1, pos),
         pattern_(pattern),
         flags_(flags) {}
 
@@ -1549,6 +1560,7 @@
   Handle<String> flags_;
 };
 
+
 // An array literal has a literals object that is used
 // for minimizing the work when constructing it at runtime.
 class ArrayLiteral V8_FINAL : public MaterializedLiteral {
@@ -1569,8 +1581,9 @@
                ZoneList<Expression*>* values,
                int literal_index,
                bool is_simple,
-               int depth)
-      : MaterializedLiteral(isolate, literal_index, is_simple, depth),
+               int depth,
+               int pos)
+      : MaterializedLiteral(isolate, literal_index, is_simple, depth, pos),
         constant_elements_(constant_elements),
         values_(values),
         first_element_id_(ReserveIdRange(isolate, values->length())) {}
@@ -1603,7 +1616,6 @@
   Handle<String> name() const { return name_; }
   Variable* var() const { return var_; }
   bool is_this() const { return is_this_; }
-  int position() const { return position_; }
   Interface* interface() const { return interface_; }
 
 
@@ -1614,7 +1626,7 @@
   void BindTo(Variable* var);
 
  protected:
-  VariableProxy(Isolate* isolate, Variable* var);
+  VariableProxy(Isolate* isolate, Variable* var, int position);
 
   VariableProxy(Isolate* isolate,
                 Handle<String> name,
@@ -1629,7 +1641,6 @@
   // True if this variable proxy is being used in an assignment
   // or with a increment/decrement operator.
   bool is_lvalue_;
-  int position_;
   Interface* interface_;
 };
 
@@ -1642,7 +1653,6 @@
 
   Expression* obj() const { return obj_; }
   Expression* key() const { return key_; }
-  virtual int position() const V8_OVERRIDE { return pos_; }
 
   BailoutId LoadId() const { return load_id_; }
 
@@ -1666,10 +1676,9 @@
            Expression* obj,
            Expression* key,
            int pos)
-      : Expression(isolate),
+      : Expression(isolate, pos),
         obj_(obj),
         key_(key),
-        pos_(pos),
         load_id_(GetNextId(isolate)),
         is_monomorphic_(false),
         is_uninitialized_(false),
@@ -1679,7 +1688,6 @@
  private:
   Expression* obj_;
   Expression* key_;
-  int pos_;
   const BailoutId load_id_;
 
   SmallMapList receiver_types_;
@@ -1696,7 +1704,6 @@
 
   Expression* expression() const { return expression_; }
   ZoneList<Expression*>* arguments() const { return arguments_; }
-  virtual int position() const V8_FINAL { return pos_; }
 
   // Type feedback information.
   TypeFeedbackId CallFeedbackId() const { return reuse(id()); }
@@ -1751,10 +1758,9 @@
        Expression* expression,
        ZoneList<Expression*>* arguments,
        int pos)
-      : Expression(isolate),
+      : Expression(isolate, pos),
         expression_(expression),
         arguments_(arguments),
-        pos_(pos),
         is_monomorphic_(false),
         check_type_(RECEIVER_MAP_CHECK),
         return_id_(GetNextId(isolate)) { }
@@ -1762,7 +1768,6 @@
  private:
   Expression* expression_;
   ZoneList<Expression*>* arguments_;
-  int pos_;
 
   bool is_monomorphic_;
   CheckType check_type_;
@@ -1781,7 +1786,6 @@
 
   Expression* expression() const { return expression_; }
   ZoneList<Expression*>* arguments() const { return arguments_; }
-  virtual int position() const V8_OVERRIDE { return pos_; }
 
   // Type feedback information.
   TypeFeedbackId CallNewFeedbackId() const { return reuse(id()); }
@@ -1800,10 +1804,9 @@
           Expression* expression,
           ZoneList<Expression*>* arguments,
           int pos)
-      : Expression(isolate),
+      : Expression(isolate, pos),
         expression_(expression),
         arguments_(arguments),
-        pos_(pos),
         is_monomorphic_(false),
         elements_kind_(GetInitialFastElementsKind()),
         return_id_(GetNextId(isolate)) { }
@@ -1811,7 +1814,6 @@
  private:
   Expression* expression_;
   ZoneList<Expression*>* arguments_;
-  int pos_;
 
   bool is_monomorphic_;
   Handle<JSFunction> target_;
@@ -1841,8 +1843,9 @@
   CallRuntime(Isolate* isolate,
               Handle<String> name,
               const Runtime::Function* function,
-              ZoneList<Expression*>* arguments)
-      : Expression(isolate),
+              ZoneList<Expression*>* arguments,
+              int pos)
+      : Expression(isolate, pos),
         name_(name),
         function_(function),
         arguments_(arguments) { }
@@ -1860,7 +1863,6 @@
 
   Token::Value op() const { return op_; }
   Expression* expression() const { return expression_; }
-  virtual int position() const V8_OVERRIDE { return pos_; }
 
   BailoutId MaterializeTrueId() { return materialize_true_id_; }
   BailoutId MaterializeFalseId() { return materialize_false_id_; }
@@ -1873,10 +1875,9 @@
                  Token::Value op,
                  Expression* expression,
                  int pos)
-      : Expression(isolate),
+      : Expression(isolate, pos),
         op_(op),
         expression_(expression),
-        pos_(pos),
         materialize_true_id_(GetNextId(isolate)),
         materialize_false_id_(GetNextId(isolate)) {
     ASSERT(Token::IsUnaryOp(op));
@@ -1885,7 +1886,6 @@
  private:
   Token::Value op_;
   Expression* expression_;
-  int pos_;
 
   // For unary not (Token::NOT), the AST ids where true and false will
   // actually be materialized, respectively.
@@ -1903,7 +1903,6 @@
   Token::Value op() const { return op_; }
   Expression* left() const { return left_; }
   Expression* right() const { return right_; }
-  virtual int position() const V8_OVERRIDE { return pos_; }
 
   BailoutId RightId() const { return right_id_; }
 
@@ -1920,11 +1919,10 @@
                   Expression* left,
                   Expression* right,
                   int pos)
-      : Expression(isolate),
+      : Expression(isolate, pos),
         op_(op),
         left_(left),
         right_(right),
-        pos_(pos),
         right_id_(GetNextId(isolate)) {
     ASSERT(Token::IsBinaryOp(op));
   }
@@ -1933,7 +1931,6 @@
   Token::Value op_;
   Expression* left_;
   Expression* right_;
-  int pos_;
 
   // TODO(rossberg): the fixed arg should probably be represented as a Constant
   // type for the RHS.
@@ -1958,7 +1955,6 @@
   }
 
   Expression* expression() const { return expression_; }
-  virtual int position() const V8_OVERRIDE { return pos_; }
 
   void RecordTypeFeedback(TypeFeedbackOracle* oracle, Zone* zone);
   virtual bool IsMonomorphic() V8_OVERRIDE { return is_monomorphic_; }
@@ -1981,13 +1977,12 @@
                  bool is_prefix,
                  Expression* expr,
                  int pos)
-      : Expression(isolate),
+      : Expression(isolate, pos),
         op_(op),
         is_prefix_(is_prefix),
         is_monomorphic_(false),
         store_mode_(STANDARD_STORE),
         expression_(expr),
-        pos_(pos),
         assignment_id_(GetNextId(isolate)),
         count_id_(GetNextId(isolate)) {}
 
@@ -2000,7 +1995,6 @@
   Handle<Type> type_;
 
   Expression* expression_;
-  int pos_;
   const BailoutId assignment_id_;
   const TypeFeedbackId count_id_;
   SmallMapList receiver_types_;
@@ -2014,7 +2008,6 @@
   Token::Value op() const { return op_; }
   Expression* left() const { return left_; }
   Expression* right() const { return right_; }
-  virtual int position() const V8_OVERRIDE { return pos_; }
 
   // Type feedback information.
   TypeFeedbackId CompareOperationFeedbackId() const { return reuse(id()); }
@@ -2032,12 +2025,11 @@
                    Expression* left,
                    Expression* right,
                    int pos)
-      : Expression(isolate),
+      : Expression(isolate, pos),
         op_(op),
         left_(left),
         right_(right),
-        pos_(pos),
-        combined_type_(Type::Null(), isolate) {
+        combined_type_(Type::None(), isolate) {
     ASSERT(Token::IsCompareOp(op));
   }
 
@@ -2045,7 +2037,6 @@
   Token::Value op_;
   Expression* left_;
   Expression* right_;
-  int pos_;
 
   Handle<Type> combined_type_;
 };
@@ -2059,9 +2050,6 @@
   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_; }
-
   BailoutId ThenId() const { return then_id_; }
   BailoutId ElseId() const { return else_id_; }
 
@@ -2070,14 +2058,11 @@
               Expression* condition,
               Expression* then_expression,
               Expression* else_expression,
-              int then_expression_position,
-              int else_expression_position)
-      : Expression(isolate),
+              int position)
+      : Expression(isolate, position),
         condition_(condition),
         then_expression_(then_expression),
         else_expression_(else_expression),
-        then_expression_position_(then_expression_position),
-        else_expression_position_(else_expression_position),
         then_id_(GetNextId(isolate)),
         else_id_(GetNextId(isolate)) { }
 
@@ -2085,8 +2070,6 @@
   Expression* condition_;
   Expression* then_expression_;
   Expression* else_expression_;
-  int then_expression_position_;
-  int else_expression_position_;
   const BailoutId then_id_;
   const BailoutId else_id_;
 };
@@ -2103,7 +2086,6 @@
   Token::Value op() const { return op_; }
   Expression* target() const { return target_; }
   Expression* value() const { return value_; }
-  virtual int position() const V8_OVERRIDE { return pos_; }
   BinaryOperation* binary_operation() const { return binary_operation_; }
 
   // This check relies on the definition order of token in token.h.
@@ -2134,8 +2116,8 @@
   void Init(Isolate* isolate, AstNodeFactory<Visitor>* factory) {
     ASSERT(Token::IsAssignmentOp(op_));
     if (is_compound()) {
-      binary_operation_ =
-          factory->NewBinaryOperation(binary_op(), target_, value_, pos_ + 1);
+      binary_operation_ = factory->NewBinaryOperation(
+          binary_op(), target_, value_, position() + 1);
     }
   }
 
@@ -2143,7 +2125,6 @@
   Token::Value op_;
   Expression* target_;
   Expression* value_;
-  int pos_;
   BinaryOperation* binary_operation_;
   const BailoutId assignment_id_;
 
@@ -2169,7 +2150,6 @@
   Expression* generator_object() const { return generator_object_; }
   Expression* expression() const { return expression_; }
   Kind yield_kind() const { return yield_kind_; }
-  virtual int position() const V8_OVERRIDE { return pos_; }
 
   // Delegating yield surrounds the "yield" in a "try/catch".  This index
   // locates the catch handler in the handler table, and is equivalent to
@@ -2189,19 +2169,17 @@
         Expression* expression,
         Kind yield_kind,
         int pos)
-      : Expression(isolate),
+      : Expression(isolate, pos),
         generator_object_(generator_object),
         expression_(expression),
         yield_kind_(yield_kind),
-        index_(-1),
-        pos_(pos) { }
+        index_(-1) { }
 
  private:
   Expression* generator_object_;
   Expression* expression_;
   Kind yield_kind_;
   int index_;
-  int pos_;
 };
 
 
@@ -2210,15 +2188,13 @@
   DECLARE_NODE_TYPE(Throw)
 
   Expression* exception() const { return exception_; }
-  virtual int position() const V8_OVERRIDE { return pos_; }
 
  protected:
   Throw(Isolate* isolate, Expression* exception, int pos)
-      : Expression(isolate), exception_(exception), pos_(pos) {}
+      : Expression(isolate, pos), exception_(exception) {}
 
  private:
   Expression* exception_;
-  int pos_;
 };
 
 
@@ -2333,8 +2309,9 @@
                   ParameterFlag has_duplicate_parameters,
                   IsFunctionFlag is_function,
                   IsParenthesizedFlag is_parenthesized,
-                  IsGeneratorFlag is_generator)
-      : Expression(isolate),
+                  IsGeneratorFlag is_generator,
+                  int position)
+      : Expression(isolate, position),
         name_(name),
         scope_(scope),
         body_(body),
@@ -2389,8 +2366,8 @@
 
  protected:
   NativeFunctionLiteral(
-      Isolate* isolate, Handle<String> name, v8::Extension* extension)
-      : Expression(isolate), name_(name), extension_(extension) { }
+      Isolate* isolate, Handle<String> name, v8::Extension* extension, int pos)
+      : Expression(isolate, pos), name_(name), extension_(extension) {}
 
  private:
   Handle<String> name_;
@@ -2403,7 +2380,7 @@
   DECLARE_NODE_TYPE(ThisFunction)
 
  protected:
-  explicit ThisFunction(Isolate* isolate): Expression(isolate) {}
+  explicit ThisFunction(Isolate* isolate, int pos): Expression(isolate, pos) {}
 };
 
 #undef DECLARE_NODE_TYPE
@@ -2770,8 +2747,8 @@
 // ----------------------------------------------------------------------------
 // Out-of-line inline constructors (to side-step cyclic dependencies).
 
-inline ModuleVariable::ModuleVariable(VariableProxy* proxy)
-    : Module(proxy->interface()),
+inline ModuleVariable::ModuleVariable(VariableProxy* proxy, int pos)
+    : Module(proxy->interface(), pos),
       proxy_(proxy) {
 }
 
@@ -2888,75 +2865,81 @@
 
   VariableDeclaration* NewVariableDeclaration(VariableProxy* proxy,
                                               VariableMode mode,
-                                              Scope* scope) {
+                                              Scope* scope,
+                                              int pos) {
     VariableDeclaration* decl =
-        new(zone_) VariableDeclaration(proxy, mode, scope);
+        new(zone_) VariableDeclaration(proxy, mode, scope, pos);
     VISIT_AND_RETURN(VariableDeclaration, decl)
   }
 
   FunctionDeclaration* NewFunctionDeclaration(VariableProxy* proxy,
                                               VariableMode mode,
                                               FunctionLiteral* fun,
-                                              Scope* scope) {
+                                              Scope* scope,
+                                              int pos) {
     FunctionDeclaration* decl =
-        new(zone_) FunctionDeclaration(proxy, mode, fun, scope);
+        new(zone_) FunctionDeclaration(proxy, mode, fun, scope, pos);
     VISIT_AND_RETURN(FunctionDeclaration, decl)
   }
 
   ModuleDeclaration* NewModuleDeclaration(VariableProxy* proxy,
                                           Module* module,
-                                          Scope* scope) {
+                                          Scope* scope,
+                                          int pos) {
     ModuleDeclaration* decl =
-        new(zone_) ModuleDeclaration(proxy, module, scope);
+        new(zone_) ModuleDeclaration(proxy, module, scope, pos);
     VISIT_AND_RETURN(ModuleDeclaration, decl)
   }
 
   ImportDeclaration* NewImportDeclaration(VariableProxy* proxy,
                                           Module* module,
-                                          Scope* scope) {
+                                          Scope* scope,
+                                          int pos) {
     ImportDeclaration* decl =
-        new(zone_) ImportDeclaration(proxy, module, scope);
+        new(zone_) ImportDeclaration(proxy, module, scope, pos);
     VISIT_AND_RETURN(ImportDeclaration, decl)
   }
 
   ExportDeclaration* NewExportDeclaration(VariableProxy* proxy,
-                                          Scope* scope) {
+                                          Scope* scope,
+                                          int pos) {
     ExportDeclaration* decl =
-        new(zone_) ExportDeclaration(proxy, scope);
+        new(zone_) ExportDeclaration(proxy, scope, pos);
     VISIT_AND_RETURN(ExportDeclaration, decl)
   }
 
-  ModuleLiteral* NewModuleLiteral(Block* body, Interface* interface) {
-    ModuleLiteral* module = new(zone_) ModuleLiteral(body, interface);
+  ModuleLiteral* NewModuleLiteral(Block* body, Interface* interface, int pos) {
+    ModuleLiteral* module = new(zone_) ModuleLiteral(body, interface, pos);
     VISIT_AND_RETURN(ModuleLiteral, module)
   }
 
-  ModuleVariable* NewModuleVariable(VariableProxy* proxy) {
-    ModuleVariable* module = new(zone_) ModuleVariable(proxy);
+  ModuleVariable* NewModuleVariable(VariableProxy* proxy, int pos) {
+    ModuleVariable* module = new(zone_) ModuleVariable(proxy, pos);
     VISIT_AND_RETURN(ModuleVariable, module)
   }
 
-  ModulePath* NewModulePath(Module* origin, Handle<String> name) {
-    ModulePath* module = new(zone_) ModulePath(origin, name, zone_);
+  ModulePath* NewModulePath(Module* origin, Handle<String> name, int pos) {
+    ModulePath* module = new(zone_) ModulePath(origin, name, zone_, pos);
     VISIT_AND_RETURN(ModulePath, module)
   }
 
-  ModuleUrl* NewModuleUrl(Handle<String> url) {
-    ModuleUrl* module = new(zone_) ModuleUrl(url, zone_);
+  ModuleUrl* NewModuleUrl(Handle<String> url, int pos) {
+    ModuleUrl* module = new(zone_) ModuleUrl(url, zone_, pos);
     VISIT_AND_RETURN(ModuleUrl, module)
   }
 
   Block* NewBlock(ZoneStringList* labels,
                   int capacity,
-                  bool is_initializer_block) {
+                  bool is_initializer_block,
+                  int pos) {
     Block* block = new(zone_) Block(
-        isolate_, labels, capacity, is_initializer_block, zone_);
+        isolate_, labels, capacity, is_initializer_block, pos, zone_);
     VISIT_AND_RETURN(Block, block)
   }
 
 #define STATEMENT_WITH_LABELS(NodeType) \
-  NodeType* New##NodeType(ZoneStringList* labels) { \
-    NodeType* stmt = new(zone_) NodeType(isolate_, labels); \
+  NodeType* New##NodeType(ZoneStringList* labels, int pos) { \
+    NodeType* stmt = new(zone_) NodeType(isolate_, labels, pos); \
     VISIT_AND_RETURN(NodeType, stmt); \
   }
   STATEMENT_WITH_LABELS(DoWhileStatement)
@@ -2966,14 +2949,15 @@
 #undef STATEMENT_WITH_LABELS
 
   ForEachStatement* NewForEachStatement(ForEachStatement::VisitMode visit_mode,
-                                        ZoneStringList* labels) {
+                                        ZoneStringList* labels,
+                                        int pos) {
     switch (visit_mode) {
       case ForEachStatement::ENUMERATE: {
-        ForInStatement* stmt = new(zone_) ForInStatement(isolate_, labels);
+        ForInStatement* stmt = new(zone_) ForInStatement(isolate_, labels, pos);
         VISIT_AND_RETURN(ForInStatement, stmt);
       }
       case ForEachStatement::ITERATE: {
-        ForOfStatement* stmt = new(zone_) ForOfStatement(isolate_, labels);
+        ForOfStatement* stmt = new(zone_) ForOfStatement(isolate_, labels, pos);
         VISIT_AND_RETURN(ForOfStatement, stmt);
       }
     }
@@ -2981,44 +2965,47 @@
     return NULL;
   }
 
-  ModuleStatement* NewModuleStatement(VariableProxy* proxy, Block* body) {
-    ModuleStatement* stmt = new(zone_) ModuleStatement(proxy, body);
+  ModuleStatement* NewModuleStatement(
+      VariableProxy* proxy, Block* body, int pos) {
+    ModuleStatement* stmt = new(zone_) ModuleStatement(proxy, body, pos);
     VISIT_AND_RETURN(ModuleStatement, stmt)
   }
 
-  ExpressionStatement* NewExpressionStatement(Expression* expression) {
-    ExpressionStatement* stmt = new(zone_) ExpressionStatement(expression);
+  ExpressionStatement* NewExpressionStatement(Expression* expression, int pos) {
+    ExpressionStatement* stmt = new(zone_) ExpressionStatement(expression, pos);
     VISIT_AND_RETURN(ExpressionStatement, stmt)
   }
 
-  ContinueStatement* NewContinueStatement(IterationStatement* target) {
-    ContinueStatement* stmt = new(zone_) ContinueStatement(target);
+  ContinueStatement* NewContinueStatement(IterationStatement* target, int pos) {
+    ContinueStatement* stmt = new(zone_) ContinueStatement(target, pos);
     VISIT_AND_RETURN(ContinueStatement, stmt)
   }
 
-  BreakStatement* NewBreakStatement(BreakableStatement* target) {
-    BreakStatement* stmt = new(zone_) BreakStatement(target);
+  BreakStatement* NewBreakStatement(BreakableStatement* target, int pos) {
+    BreakStatement* stmt = new(zone_) BreakStatement(target, pos);
     VISIT_AND_RETURN(BreakStatement, stmt)
   }
 
-  ReturnStatement* NewReturnStatement(Expression* expression) {
-    ReturnStatement* stmt = new(zone_) ReturnStatement(expression);
+  ReturnStatement* NewReturnStatement(Expression* expression, int pos) {
+    ReturnStatement* stmt = new(zone_) ReturnStatement(expression, pos);
     VISIT_AND_RETURN(ReturnStatement, stmt)
   }
 
   WithStatement* NewWithStatement(Scope* scope,
                                   Expression* expression,
-                                  Statement* statement) {
+                                  Statement* statement,
+                                  int pos) {
     WithStatement* stmt = new(zone_) WithStatement(
-        scope, expression, statement);
+        scope, expression, statement, pos);
     VISIT_AND_RETURN(WithStatement, stmt)
   }
 
   IfStatement* NewIfStatement(Expression* condition,
                               Statement* then_statement,
-                              Statement* else_statement) {
+                              Statement* else_statement,
+                              int pos) {
     IfStatement* stmt = new(zone_) IfStatement(
-        isolate_, condition, then_statement, else_statement);
+        isolate_, condition, then_statement, else_statement, pos);
     VISIT_AND_RETURN(IfStatement, stmt)
   }
 
@@ -3026,36 +3013,45 @@
                                           Block* try_block,
                                           Scope* scope,
                                           Variable* variable,
-                                          Block* catch_block) {
+                                          Block* catch_block,
+                                          int pos) {
     TryCatchStatement* stmt = new(zone_) TryCatchStatement(
-        index, try_block, scope, variable, catch_block);
+        index, try_block, scope, variable, catch_block, pos);
     VISIT_AND_RETURN(TryCatchStatement, stmt)
   }
 
   TryFinallyStatement* NewTryFinallyStatement(int index,
                                               Block* try_block,
-                                              Block* finally_block) {
+                                              Block* finally_block,
+                                              int pos) {
     TryFinallyStatement* stmt =
-        new(zone_) TryFinallyStatement(index, try_block, finally_block);
+        new(zone_) TryFinallyStatement(index, try_block, finally_block, pos);
     VISIT_AND_RETURN(TryFinallyStatement, stmt)
   }
 
-  DebuggerStatement* NewDebuggerStatement() {
-    DebuggerStatement* stmt = new(zone_) DebuggerStatement();
+  DebuggerStatement* NewDebuggerStatement(int pos) {
+    DebuggerStatement* stmt = new(zone_) DebuggerStatement(pos);
     VISIT_AND_RETURN(DebuggerStatement, stmt)
   }
 
-  EmptyStatement* NewEmptyStatement() {
-    return new(zone_) EmptyStatement();
+  EmptyStatement* NewEmptyStatement(int pos) {
+    return new(zone_) EmptyStatement(pos);
   }
 
-  Literal* NewLiteral(Handle<Object> handle) {
-    Literal* lit = new(zone_) Literal(isolate_, handle);
+  CaseClause* NewCaseClause(
+      Expression* label, ZoneList<Statement*>* statements, int pos) {
+    CaseClause* clause =
+        new(zone_) CaseClause(isolate_, label, statements, pos);
+    VISIT_AND_RETURN(CaseClause, clause)
+  }
+
+  Literal* NewLiteral(Handle<Object> handle, int pos) {
+    Literal* lit = new(zone_) Literal(isolate_, handle, pos);
     VISIT_AND_RETURN(Literal, lit)
   }
 
-  Literal* NewNumberLiteral(double number) {
-    return NewLiteral(isolate_->factory()->NewNumber(number, TENURED));
+  Literal* NewNumberLiteral(double number, int pos) {
+    return NewLiteral(isolate_->factory()->NewNumber(number, TENURED), pos);
   }
 
   ObjectLiteral* NewObjectLiteral(
@@ -3066,26 +3062,29 @@
       bool fast_elements,
       int depth,
       bool may_store_doubles,
-      bool has_function) {
+      bool has_function,
+      int pos) {
     ObjectLiteral* lit = new(zone_) ObjectLiteral(
         isolate_, constant_properties, properties, literal_index,
-        is_simple, fast_elements, depth, may_store_doubles, has_function);
+        is_simple, fast_elements, depth, may_store_doubles, has_function, pos);
     VISIT_AND_RETURN(ObjectLiteral, lit)
   }
 
   ObjectLiteral::Property* NewObjectLiteralProperty(bool is_getter,
-                                                    FunctionLiteral* value) {
+                                                    FunctionLiteral* value,
+                                                    int pos) {
     ObjectLiteral::Property* prop =
         new(zone_) ObjectLiteral::Property(is_getter, value);
-    prop->set_key(NewLiteral(value->name()));
+    prop->set_key(NewLiteral(value->name(), pos));
     return prop;  // Not an AST node, will not be visited.
   }
 
   RegExpLiteral* NewRegExpLiteral(Handle<String> pattern,
                                   Handle<String> flags,
-                                  int literal_index) {
+                                  int literal_index,
+                                  int pos) {
     RegExpLiteral* lit =
-        new(zone_) RegExpLiteral(isolate_, pattern, flags, literal_index);
+        new(zone_) RegExpLiteral(isolate_, pattern, flags, literal_index, pos);
     VISIT_AND_RETURN(RegExpLiteral, lit);
   }
 
@@ -3093,14 +3092,17 @@
                                 ZoneList<Expression*>* values,
                                 int literal_index,
                                 bool is_simple,
-                                int depth) {
+                                int depth,
+                                int pos) {
     ArrayLiteral* lit = new(zone_) ArrayLiteral(
-        isolate_, constant_elements, values, literal_index, is_simple, depth);
+        isolate_, constant_elements, values, literal_index, is_simple,
+        depth, pos);
     VISIT_AND_RETURN(ArrayLiteral, lit)
   }
 
-  VariableProxy* NewVariableProxy(Variable* var) {
-    VariableProxy* proxy = new(zone_) VariableProxy(isolate_, var);
+  VariableProxy* NewVariableProxy(Variable* var,
+                                  int pos = RelocInfo::kNoPosition) {
+    VariableProxy* proxy = new(zone_) VariableProxy(isolate_, var, pos);
     VISIT_AND_RETURN(VariableProxy, proxy)
   }
 
@@ -3134,9 +3136,10 @@
 
   CallRuntime* NewCallRuntime(Handle<String> name,
                               const Runtime::Function* function,
-                              ZoneList<Expression*>* arguments) {
+                              ZoneList<Expression*>* arguments,
+                              int pos) {
     CallRuntime* call =
-        new(zone_) CallRuntime(isolate_, name, function, arguments);
+        new(zone_) CallRuntime(isolate_, name, function, arguments, pos);
     VISIT_AND_RETURN(CallRuntime, call)
   }
 
@@ -3178,11 +3181,9 @@
   Conditional* NewConditional(Expression* condition,
                               Expression* then_expression,
                               Expression* else_expression,
-                              int then_expression_position,
-                              int else_expression_position) {
+                              int position) {
     Conditional* cond = new(zone_) Conditional(
-        isolate_, condition, then_expression, else_expression,
-        then_expression_position, else_expression_position);
+        isolate_, condition, then_expression, else_expression, position);
     VISIT_AND_RETURN(Conditional, cond)
   }
 
@@ -3222,12 +3223,13 @@
       FunctionLiteral::FunctionType function_type,
       FunctionLiteral::IsFunctionFlag is_function,
       FunctionLiteral::IsParenthesizedFlag is_parenthesized,
-      FunctionLiteral::IsGeneratorFlag is_generator) {
+      FunctionLiteral::IsGeneratorFlag is_generator,
+      int position) {
     FunctionLiteral* lit = new(zone_) FunctionLiteral(
         isolate_, name, scope, body,
         materialized_literal_count, expected_property_count, handler_count,
         parameter_count, function_type, has_duplicate_parameters, is_function,
-        is_parenthesized, is_generator);
+        is_parenthesized, is_generator, position);
     // Top-level literal doesn't count for the AST's properties.
     if (is_function == FunctionLiteral::kIsFunction) {
       visitor_.VisitFunctionLiteral(lit);
@@ -3235,15 +3237,15 @@
     return lit;
   }
 
-  NativeFunctionLiteral* NewNativeFunctionLiteral(Handle<String> name,
-                                                  v8::Extension* extension) {
+  NativeFunctionLiteral* NewNativeFunctionLiteral(
+      Handle<String> name, v8::Extension* extension, int pos) {
     NativeFunctionLiteral* lit =
-        new(zone_) NativeFunctionLiteral(isolate_, name, extension);
+        new(zone_) NativeFunctionLiteral(isolate_, name, extension, pos);
     VISIT_AND_RETURN(NativeFunctionLiteral, lit)
   }
 
-  ThisFunction* NewThisFunction() {
-    ThisFunction* fun = new(zone_) ThisFunction(isolate_);
+  ThisFunction* NewThisFunction(int pos) {
+    ThisFunction* fun = new(zone_) ThisFunction(isolate_, pos);
     VISIT_AND_RETURN(ThisFunction, fun)
   }
 
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 332131a..c48385c 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -824,7 +824,7 @@
 // work in the snapshot case is done in HookUpInnerGlobal.
 void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
                                Handle<JSFunction> empty_function) {
-  // --- G l o b a l   C o n t e x t ---
+  // --- N a t i v e   C o n t e x t ---
   // Use the empty function as closure (no scope info).
   native_context()->set_closure(*empty_function);
   native_context()->set_previous(NULL);
diff --git a/src/builtins.cc b/src/builtins.cc
index 518c893..aaa8bc4 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -274,7 +274,8 @@
   }
 
   HEAP_PROFILE(heap, ObjectMoveEvent(elms->address(),
-                                     elms->address() + size_delta));
+                                     elms->address() + size_delta,
+                                     elms->Size()));
   return FixedArrayBase::cast(HeapObject::FromAddress(
       elms->address() + to_trim * entry_size));
 }
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index c9529a8..f8fde15 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -932,17 +932,15 @@
     result = EnforceNumberType(result, result_type);
   }
 
-  // Reuse the double box if we are allowed to (i.e. chained binops).
+  // Reuse the double box of one of the operands if we are allowed to (i.e.
+  // chained binops).
   if (stub->CanReuseDoubleBox()) {
-    HValue* reuse = (stub->mode() == OVERWRITE_LEFT) ? left : right;
+    HValue* operand = (stub->mode() == OVERWRITE_LEFT) ? left : right;
     IfBuilder if_heap_number(this);
-    if_heap_number.IfNot<HIsSmiAndBranch>(reuse);
+    if_heap_number.IfNot<HIsSmiAndBranch>(operand);
     if_heap_number.Then();
-    HValue* res_val = Add<HForceRepresentation>(result,
-                                                Representation::Double());
-    HObjectAccess access = HObjectAccess::ForHeapNumberValue();
-    Add<HStoreNamedField>(reuse, access, res_val);
-    Push(reuse);
+    Add<HStoreNamedField>(operand, HObjectAccess::ForHeapNumberValue(), result);
+    Push(operand);
     if_heap_number.Else();
     Push(result);
     if_heap_number.End();
diff --git a/src/codegen.cc b/src/codegen.cc
index d33c7f0..b15324c 100644
--- a/src/codegen.cc
+++ b/src/codegen.cc
@@ -116,6 +116,8 @@
                                   false, is_crankshafted);
   isolate->counters()->total_compiled_code_size()->Increment(
       code->instruction_size());
+  isolate->heap()->IncrementCodeGeneratedBytes(is_crankshafted,
+      code->instruction_size());
   code->set_prologue_offset(info->prologue_offset());
   return code;
 }
diff --git a/src/factory.cc b/src/factory.cc
index 116434c..bb998a4 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -79,6 +79,21 @@
 }
 
 
+Handle<ConstantPoolArray> Factory::NewConstantPoolArray(
+    int number_of_int64_entries,
+    int number_of_ptr_entries,
+    int number_of_int32_entries) {
+  ASSERT(number_of_int64_entries > 0 || number_of_ptr_entries > 0 ||
+         number_of_int32_entries > 0);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateConstantPoolArray(number_of_int64_entries,
+                                                   number_of_ptr_entries,
+                                                   number_of_int32_entries),
+      ConstantPoolArray);
+}
+
+
 Handle<NameDictionary> Factory::NewNameDictionary(int at_least_space_for) {
   ASSERT(0 <= at_least_space_for);
   CALL_HEAP_FUNCTION(isolate(),
@@ -624,6 +639,12 @@
 }
 
 
+Handle<ConstantPoolArray> Factory::CopyConstantPoolArray(
+    Handle<ConstantPoolArray> array) {
+  CALL_HEAP_FUNCTION(isolate(), array->Copy(), ConstantPoolArray);
+}
+
+
 Handle<JSFunction> Factory::BaseNewFunctionFromSharedFunctionInfo(
     Handle<SharedFunctionInfo> function_info,
     Handle<Map> function_map,
diff --git a/src/factory.h b/src/factory.h
index a4f60bd..b2b426d 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -59,6 +59,11 @@
       int size,
       PretenureFlag pretenure = NOT_TENURED);
 
+  Handle<ConstantPoolArray> NewConstantPoolArray(
+      int number_of_int64_entries,
+      int number_of_ptr_entries,
+      int number_of_int32_entries);
+
   Handle<SeededNumberDictionary> NewSeededNumberDictionary(
       int at_least_space_for);
 
@@ -273,6 +278,9 @@
   Handle<FixedDoubleArray> CopyFixedDoubleArray(
       Handle<FixedDoubleArray> array);
 
+  Handle<ConstantPoolArray> CopyConstantPoolArray(
+      Handle<ConstantPoolArray> array);
+
   // Numbers (e.g. literals) are pretenured by the parser.
   Handle<Object> NewNumber(double value,
                            PretenureFlag pretenure = NOT_TENURED);
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 7450ef9..63cf4a6 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -328,6 +328,8 @@
            "the length of the concurrent compilation queue")
 DEFINE_int(concurrent_recompilation_delay, 0,
            "artificial compilation delay in ms")
+DEFINE_bool(block_concurrent_recompilation, false,
+            "block queued jobs until released")
 DEFINE_bool(concurrent_osr, false,
             "concurrent on-stack replacement")
 DEFINE_implication(concurrent_osr, concurrent_recompilation)
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index f3e1bd7..f87cf88 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -193,6 +193,10 @@
 }
 
 
+void BreakableStatementChecker::VisitCaseClause(CaseClause* clause) {
+}
+
+
 void BreakableStatementChecker::VisitFunctionLiteral(FunctionLiteral* expr) {
 }
 
@@ -826,7 +830,7 @@
 void FullCodeGenerator::SetStatementPosition(Statement* stmt) {
 #ifdef ENABLE_DEBUGGER_SUPPORT
   if (!isolate()->debugger()->IsDebuggerActive()) {
-    CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
+    CodeGenerator::RecordPositions(masm_, stmt->position());
   } else {
     // Check if the statement will be breakable without adding a debug break
     // slot.
@@ -836,7 +840,7 @@
     // breakable. For breakable statements the actual recording of the
     // position will be postponed to the breakable code (typically an IC).
     bool position_recorded = CodeGenerator::RecordPositions(
-        masm_, stmt->statement_pos(), !checker.is_breakable());
+        masm_, stmt->position(), !checker.is_breakable());
     // If the position recording did record a new position generate a debug
     // break slot to make the statement breakable.
     if (position_recorded) {
@@ -844,15 +848,15 @@
     }
   }
 #else
-  CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
+  CodeGenerator::RecordPositions(masm_, stmt->position());
 #endif
 }
 
 
-void FullCodeGenerator::SetExpressionPosition(Expression* expr, int pos) {
+void FullCodeGenerator::SetExpressionPosition(Expression* expr) {
 #ifdef ENABLE_DEBUGGER_SUPPORT
   if (!isolate()->debugger()->IsDebuggerActive()) {
-    CodeGenerator::RecordPositions(masm_, pos);
+    CodeGenerator::RecordPositions(masm_, expr->position());
   } else {
     // Check if the expression will be breakable without adding a debug break
     // slot.
@@ -866,7 +870,7 @@
     // statement positions this is used for e.g. the condition expression of
     // a do while loop.
     bool position_recorded = CodeGenerator::RecordPositions(
-        masm_, pos, !checker.is_breakable());
+        masm_, expr->position(), !checker.is_breakable());
     // If the position recording did record a new position generate a debug
     // break slot to make the statement breakable.
     if (position_recorded) {
@@ -1293,7 +1297,7 @@
   // possible to break on the condition.
   __ bind(loop_statement.continue_label());
   PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
-  SetExpressionPosition(stmt->cond(), stmt->condition_position());
+  SetExpressionPosition(stmt->cond());
   VisitForControl(stmt->cond(),
                   &book_keeping,
                   loop_statement.break_label(),
@@ -1515,6 +1519,11 @@
 }
 
 
+void FullCodeGenerator::VisitCaseClause(CaseClause* clause) {
+  UNREACHABLE();
+}
+
+
 void FullCodeGenerator::VisitConditional(Conditional* expr) {
   Comment cmnt(masm_, "[ Conditional");
   Label true_case, false_case, done;
@@ -1522,8 +1531,7 @@
 
   PrepareForBailoutForId(expr->ThenId(), NO_REGISTERS);
   __ bind(&true_case);
-  SetExpressionPosition(expr->then_expression(),
-                        expr->then_expression_position());
+  SetExpressionPosition(expr->then_expression());
   if (context()->IsTest()) {
     const TestContext* for_test = TestContext::cast(context());
     VisitForControl(expr->then_expression(),
@@ -1537,8 +1545,7 @@
 
   PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS);
   __ bind(&false_case);
-  SetExpressionPosition(expr->else_expression(),
-                        expr->else_expression_position());
+  SetExpressionPosition(expr->else_expression());
   VisitInDuplicateContext(expr->else_expression());
   // If control flow falls through Visit, merge it with true case here.
   if (!context()->IsTest()) {
diff --git a/src/full-codegen.h b/src/full-codegen.h
index 93a2528..e27662e 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -576,7 +576,7 @@
   void SetFunctionPosition(FunctionLiteral* fun);
   void SetReturnPosition(FunctionLiteral* fun);
   void SetStatementPosition(Statement* stmt);
-  void SetExpressionPosition(Expression* expr, int pos);
+  void SetExpressionPosition(Expression* expr);
   void SetStatementPosition(int pos);
   void SetSourcePosition(int pos);
 
diff --git a/src/globals.h b/src/globals.h
index d06c6d7..701fdee 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -232,6 +232,8 @@
 const int kCharSize      = sizeof(char);      // NOLINT
 const int kShortSize     = sizeof(short);     // NOLINT
 const int kIntSize       = sizeof(int);       // NOLINT
+const int kInt32Size     = sizeof(int32_t);   // NOLINT
+const int kInt64Size     = sizeof(int64_t);   // NOLINT
 const int kDoubleSize    = sizeof(double);    // NOLINT
 const int kIntptrSize    = sizeof(intptr_t);  // NOLINT
 const int kPointerSize   = sizeof(void*);     // NOLINT
diff --git a/src/heap-inl.h b/src/heap-inl.h
index e260746..1f0f93f 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -206,6 +206,11 @@
 }
 
 
+MaybeObject* Heap::CopyConstantPoolArray(ConstantPoolArray* src) {
+  return CopyConstantPoolArrayWithMap(src, src->map());
+}
+
+
 MaybeObject* Heap::AllocateRaw(int size_in_bytes,
                                AllocationSpace space,
                                AllocationSpace retry_space) {
diff --git a/src/heap-profiler.cc b/src/heap-profiler.cc
index e66af33..6b159a9 100644
--- a/src/heap-profiler.cc
+++ b/src/heap-profiler.cc
@@ -27,6 +27,7 @@
 
 #include "v8.h"
 
+#include "deoptimizer.h"
 #include "heap-profiler.h"
 #include "heap-snapshot-generator-inl.h"
 
@@ -35,7 +36,8 @@
 
 HeapProfiler::HeapProfiler(Heap* heap)
     : snapshots_(new HeapSnapshotsCollection(heap)),
-      next_snapshot_uid_(1) {
+      next_snapshot_uid_(1),
+      is_tracking_allocations_(false) {
 }
 
 
@@ -132,14 +134,86 @@
 }
 
 
-void HeapProfiler::ObjectMoveEvent(Address from, Address to) {
-  snapshots_->ObjectMoveEvent(from, to);
+void HeapProfiler::ObjectMoveEvent(Address from, Address to, int size) {
+  snapshots_->ObjectMoveEvent(from, to, size);
 }
 
+
+void HeapProfiler::NewObjectEvent(Address addr, int size) {
+  snapshots_->NewObjectEvent(addr, size);
+}
+
+
+void HeapProfiler::UpdateObjectSizeEvent(Address addr, int size) {
+  snapshots_->UpdateObjectSizeEvent(addr, size);
+}
+
+
 void HeapProfiler::SetRetainedObjectInfo(UniqueId id,
                                          RetainedObjectInfo* info) {
   // TODO(yurus, marja): Don't route this information through GlobalHandles.
   heap()->isolate()->global_handles()->SetRetainedObjectInfo(id, info);
 }
 
+
+void HeapProfiler::StartHeapAllocationsRecording() {
+  StartHeapObjectsTracking();
+  is_tracking_allocations_ = true;
+  DropCompiledCode();
+  snapshots_->UpdateHeapObjectsMap();
+}
+
+
+void HeapProfiler::StopHeapAllocationsRecording() {
+  StopHeapObjectsTracking();
+  is_tracking_allocations_ = false;
+  DropCompiledCode();
+}
+
+
+void HeapProfiler::RecordObjectAllocationFromMasm(Isolate* isolate,
+                                                  Address obj,
+                                                  int size) {
+  isolate->heap_profiler()->NewObjectEvent(obj, size);
+}
+
+
+void HeapProfiler::DropCompiledCode() {
+  Isolate* isolate = heap()->isolate();
+  HandleScope scope(isolate);
+
+  if (FLAG_concurrent_recompilation) {
+    isolate->optimizing_compiler_thread()->Flush();
+  }
+
+  Deoptimizer::DeoptimizeAll(isolate);
+
+  Handle<Code> lazy_compile =
+      Handle<Code>(isolate->builtins()->builtin(Builtins::kLazyCompile));
+
+  heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
+                            "switch allocations tracking");
+
+  DisallowHeapAllocation no_allocation;
+
+  HeapIterator iterator(heap());
+  HeapObject* obj = NULL;
+  while (((obj = iterator.next()) != NULL)) {
+    if (obj->IsJSFunction()) {
+      JSFunction* function = JSFunction::cast(obj);
+      SharedFunctionInfo* shared = function->shared();
+
+      if (!shared->allows_lazy_compilation()) continue;
+      if (!shared->script()->IsScript()) continue;
+
+      Code::Kind kind = function->code()->kind();
+      if (kind == Code::FUNCTION || kind == Code::BUILTIN) {
+        function->set_code(*lazy_compile);
+        shared->set_code(*lazy_compile);
+      }
+    }
+  }
+}
+
+
 } }  // namespace v8::internal
diff --git a/src/heap-profiler.h b/src/heap-profiler.h
index 5ae60fa..96ae273 100644
--- a/src/heap-profiler.h
+++ b/src/heap-profiler.h
@@ -63,13 +63,22 @@
 
   void StartHeapObjectsTracking();
   void StopHeapObjectsTracking();
+
+  static void RecordObjectAllocationFromMasm(Isolate* isolate,
+                                             Address obj,
+                                             int size);
+
   SnapshotObjectId PushHeapObjectsStats(OutputStream* stream);
   int GetSnapshotsCount();
   HeapSnapshot* GetSnapshot(int index);
   SnapshotObjectId GetSnapshotObjectId(Handle<Object> obj);
   void DeleteAllSnapshots();
 
-  void ObjectMoveEvent(Address from, Address to);
+  void ObjectMoveEvent(Address from, Address to, int size);
+
+  void NewObjectEvent(Address addr, int size);
+
+  void UpdateObjectSizeEvent(Address addr, int size);
 
   void DefineWrapperClass(
       uint16_t class_id, v8::HeapProfiler::WrapperInfoCallback callback);
@@ -82,12 +91,26 @@
 
   void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
 
+  bool is_tracking_allocations() {
+    return is_tracking_allocations_;
+  }
+
+  void StartHeapAllocationsRecording();
+  void StopHeapAllocationsRecording();
+
+  int FindUntrackedObjects() {
+    return snapshots_->FindUntrackedObjects();
+  }
+
+  void DropCompiledCode();
+
  private:
   Heap* heap() const { return snapshots_->heap(); }
 
   HeapSnapshotsCollection* snapshots_;
   unsigned next_snapshot_uid_;
   List<v8::HeapProfiler::WrapperInfoCallback> wrapper_callbacks_;
+  bool is_tracking_allocations_;
 };
 
 } }  // namespace v8::internal
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
index 5570362..444bebf 100644
--- a/src/heap-snapshot-generator.cc
+++ b/src/heap-snapshot-generator.cc
@@ -397,7 +397,7 @@
 }
 
 
-void HeapObjectsMap::MoveObject(Address from, Address to) {
+void HeapObjectsMap::MoveObject(Address from, Address to, int object_size) {
   ASSERT(to != NULL);
   ASSERT(from != NULL);
   if (from == to) return;
@@ -428,11 +428,26 @@
     int from_entry_info_index =
         static_cast<int>(reinterpret_cast<intptr_t>(from_value));
     entries_.at(from_entry_info_index).addr = to;
+    // Size of an object can change during its life, so to keep information
+    // about the object in entries_ consistent, we have to adjust size when the
+    // object is migrated.
+    entries_.at(from_entry_info_index).size = object_size;
     to_entry->value = from_value;
   }
 }
 
 
+void HeapObjectsMap::NewObject(Address addr, int size) {
+  ASSERT(addr != NULL);
+  FindOrAddEntry(addr, size, false);
+}
+
+
+void HeapObjectsMap::UpdateObjectSize(Address addr, int size) {
+  FindOrAddEntry(addr, size, false);
+}
+
+
 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) {
   HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr),
                                               false);
@@ -445,7 +460,8 @@
 
 
 SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr,
-                                                unsigned int size) {
+                                                unsigned int size,
+                                                bool accessed) {
   ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy());
   HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr),
                                               true);
@@ -453,14 +469,14 @@
     int entry_index =
         static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
     EntryInfo& entry_info = entries_.at(entry_index);
-    entry_info.accessed = true;
+    entry_info.accessed = accessed;
     entry_info.size = size;
     return entry_info.id;
   }
   entry->value = reinterpret_cast<void*>(entries_.length());
   SnapshotObjectId id = next_id_;
   next_id_ += kObjectIdStep;
-  entries_.Add(EntryInfo(id, addr, size));
+  entries_.Add(EntryInfo(id, addr, size, accessed));
   ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy());
   return id;
 }
@@ -484,6 +500,27 @@
 }
 
 
+int HeapObjectsMap::FindUntrackedObjects() {
+  HeapIterator iterator(heap_);
+  int untracked = 0;
+  for (HeapObject* obj = iterator.next();
+       obj != NULL;
+       obj = iterator.next()) {
+    HashMap::Entry* entry = entries_map_.Lookup(
+      obj->address(), ComputePointerHash(obj->address()), false);
+    if (entry == NULL) {
+      untracked++;
+    } else {
+      int entry_index = static_cast<int>(
+          reinterpret_cast<intptr_t>(entry->value));
+      EntryInfo& entry_info = entries_.at(entry_index);
+      CHECK_EQ(obj->Size(), static_cast<int>(entry_info.size));
+    }
+  }
+  return untracked;
+}
+
+
 SnapshotObjectId HeapObjectsMap::PushHeapObjectsStats(OutputStream* stream) {
   UpdateHeapObjectsMap();
   time_intervals_.Add(TimeInterval(next_id_));
diff --git a/src/heap-snapshot-generator.h b/src/heap-snapshot-generator.h
index c323f3c..602d6fd 100644
--- a/src/heap-snapshot-generator.h
+++ b/src/heap-snapshot-generator.h
@@ -227,8 +227,12 @@
 
   void SnapshotGenerationFinished();
   SnapshotObjectId FindEntry(Address addr);
-  SnapshotObjectId FindOrAddEntry(Address addr, unsigned int size);
-  void MoveObject(Address from, Address to);
+  SnapshotObjectId FindOrAddEntry(Address addr,
+                                  unsigned int size,
+                                  bool accessed = true);
+  void MoveObject(Address from, Address to, int size);
+  void NewObject(Address addr, int size);
+  void UpdateObjectSize(Address addr, int size);
   SnapshotObjectId last_assigned_id() const {
     return next_id_ - kObjectIdStep;
   }
@@ -247,6 +251,10 @@
   static const SnapshotObjectId kGcRootsFirstSubrootId;
   static const SnapshotObjectId kFirstAvailableObjectId;
 
+  int FindUntrackedObjects();
+
+  void UpdateHeapObjectsMap();
+
  private:
   struct EntryInfo {
   EntryInfo(SnapshotObjectId id, Address addr, unsigned int size)
@@ -265,7 +273,6 @@
     uint32_t count;
   };
 
-  void UpdateHeapObjectsMap();
   void RemoveDeadEntries();
 
   SnapshotObjectId next_id_;
@@ -306,12 +313,22 @@
     return ids_.FindOrAddEntry(object_addr, object_size);
   }
   Handle<HeapObject> FindHeapObjectById(SnapshotObjectId id);
-  void ObjectMoveEvent(Address from, Address to) { ids_.MoveObject(from, to); }
+  void ObjectMoveEvent(Address from, Address to, int size) {
+    ids_.MoveObject(from, to, size);
+  }
+  void NewObjectEvent(Address addr, int size) { ids_.NewObject(addr, size); }
+  void UpdateObjectSizeEvent(Address addr, int size) {
+    ids_.UpdateObjectSize(addr, size);
+  }
   SnapshotObjectId last_assigned_id() const {
     return ids_.last_assigned_id();
   }
   size_t GetUsedMemorySize() const;
 
+  int FindUntrackedObjects() { return ids_.FindUntrackedObjects(); }
+
+  void UpdateHeapObjectsMap() { ids_.UpdateHeapObjectsMap(); }
+
  private:
   bool is_tracking_objects_;  // Whether tracking object moves is needed.
   List<HeapSnapshot*> snapshots_;
diff --git a/src/heap.cc b/src/heap.cc
index b0335d0..76f34b2 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -141,6 +141,8 @@
       mark_sweeps_since_idle_round_started_(0),
       gc_count_at_last_idle_gc_(0),
       scavenges_since_last_idle_round_(kIdleScavengeThreshold),
+      full_codegen_bytes_generated_(0),
+      crankshaft_codegen_bytes_generated_(0),
       gcs_since_last_deopt_(0),
 #ifdef VERIFY_HEAP
       no_weak_object_verification_scope_depth_(0),
@@ -508,10 +510,31 @@
   isolate_->counters()->number_of_symbols()->Set(
       string_table()->NumberOfElements());
 
+  if (full_codegen_bytes_generated_ + crankshaft_codegen_bytes_generated_ > 0) {
+    isolate_->counters()->codegen_fraction_crankshaft()->AddSample(
+        static_cast<int>((crankshaft_codegen_bytes_generated_ * 100.0) /
+            (crankshaft_codegen_bytes_generated_
+            + full_codegen_bytes_generated_)));
+  }
+
   if (CommittedMemory() > 0) {
     isolate_->counters()->external_fragmentation_total()->AddSample(
         static_cast<int>(100 - (SizeOfObjects() * 100.0) / CommittedMemory()));
 
+    isolate_->counters()->heap_fraction_new_space()->
+        AddSample(static_cast<int>(
+            (new_space()->CommittedMemory() * 100.0) / CommittedMemory()));
+    isolate_->counters()->heap_fraction_old_pointer_space()->AddSample(
+        static_cast<int>(
+            (old_pointer_space()->CommittedMemory() * 100.0) /
+            CommittedMemory()));
+    isolate_->counters()->heap_fraction_old_data_space()->AddSample(
+        static_cast<int>(
+            (old_data_space()->CommittedMemory() * 100.0) /
+            CommittedMemory()));
+    isolate_->counters()->heap_fraction_code_space()->
+        AddSample(static_cast<int>(
+            (code_space()->CommittedMemory() * 100.0) / CommittedMemory()));
     isolate_->counters()->heap_fraction_map_space()->AddSample(
         static_cast<int>(
             (map_space()->CommittedMemory() * 100.0) / CommittedMemory()));
@@ -522,6 +545,9 @@
         AddSample(static_cast<int>(
             (property_cell_space()->CommittedMemory() * 100.0) /
             CommittedMemory()));
+    isolate_->counters()->heap_fraction_lo_space()->
+        AddSample(static_cast<int>(
+            (lo_space()->CommittedMemory() * 100.0) / CommittedMemory()));
 
     isolate_->counters()->heap_sample_total_committed()->AddSample(
         static_cast<int>(CommittedMemory() / KB));
@@ -535,6 +561,8 @@
         heap_sample_property_cell_space_committed()->
             AddSample(static_cast<int>(
                 property_cell_space()->CommittedMemory() / KB));
+    isolate_->counters()->heap_sample_code_space_committed()->AddSample(
+        static_cast<int>(code_space()->CommittedMemory() / KB));
   }
 
 #define UPDATE_COUNTERS_FOR_SPACE(space)                                       \
@@ -1957,6 +1985,7 @@
 
 
 STATIC_ASSERT((FixedDoubleArray::kHeaderSize & kDoubleAlignmentMask) == 0);
+STATIC_ASSERT((ConstantPoolArray::kHeaderSize & kDoubleAlignmentMask) == 0);
 
 
 INLINE(static HeapObject* EnsureDoubleAligned(Heap* heap,
@@ -2101,7 +2130,8 @@
     if (logging_and_profiling_mode == LOGGING_AND_PROFILING_ENABLED) {
       // Update NewSpace stats if necessary.
       RecordCopiedObject(heap, target);
-      HEAP_PROFILE(heap, ObjectMoveEvent(source->address(), target->address()));
+      HEAP_PROFILE(heap,
+                   ObjectMoveEvent(source->address(), target->address(), size));
       Isolate* isolate = heap->isolate();
       if (isolate->logger()->is_logging_code_events() ||
           isolate->cpu_profiler()->is_profiling()) {
@@ -2657,6 +2687,12 @@
   set_fixed_double_array_map(Map::cast(obj));
 
   { MaybeObject* maybe_obj =
+        AllocateMap(CONSTANT_POOL_ARRAY_TYPE, kVariableSizeSentinel);
+    if (!maybe_obj->ToObject(&obj)) return false;
+  }
+  set_constant_pool_array_map(Map::cast(obj));
+
+  { MaybeObject* maybe_obj =
         AllocateMap(BYTE_ARRAY_TYPE, kVariableSizeSentinel);
     if (!maybe_obj->ToObject(&obj)) return false;
   }
@@ -4927,6 +4963,13 @@
       alloc_memento->set_map_no_write_barrier(allocation_memento_map());
       ASSERT(site->map() == allocation_site_map());
       alloc_memento->set_allocation_site(site, SKIP_WRITE_BARRIER);
+      HeapProfiler* profiler = isolate()->heap_profiler();
+      if (profiler->is_tracking_allocations()) {
+        profiler->UpdateObjectSizeEvent(HeapObject::cast(clone)->address(),
+                                        object_size);
+        profiler->NewObjectEvent(alloc_memento->address(),
+                                 AllocationMemento::kSize);
+      }
     }
   }
 
@@ -5376,6 +5419,27 @@
 }
 
 
+MaybeObject* Heap::CopyConstantPoolArrayWithMap(ConstantPoolArray* src,
+                                                Map* map) {
+  int int64_entries = src->count_of_int64_entries();
+  int ptr_entries = src->count_of_ptr_entries();
+  int int32_entries = src->count_of_int32_entries();
+  Object* obj;
+  { MaybeObject* maybe_obj =
+        AllocateConstantPoolArray(int64_entries, ptr_entries, int32_entries);
+    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+  }
+  HeapObject* dst = HeapObject::cast(obj);
+  dst->set_map_no_write_barrier(map);
+  CopyBlock(
+      dst->address() + ConstantPoolArray::kLengthOffset,
+      src->address() + ConstantPoolArray::kLengthOffset,
+      ConstantPoolArray::SizeFor(int64_entries, ptr_entries, int32_entries)
+          - ConstantPoolArray::kLengthOffset);
+  return obj;
+}
+
+
 MaybeObject* Heap::AllocateRawFixedArray(int length, PretenureFlag pretenure) {
   if (length < 0 || length > FixedArray::kMaxLength) {
     return Failure::OutOfMemoryException(0xe);
@@ -5507,6 +5571,40 @@
 }
 
 
+MaybeObject* Heap::AllocateConstantPoolArray(int number_of_int64_entries,
+                                             int number_of_ptr_entries,
+                                             int number_of_int32_entries) {
+  ASSERT(number_of_int64_entries > 0 || number_of_ptr_entries > 0 ||
+         number_of_int32_entries > 0);
+  int size = ConstantPoolArray::SizeFor(number_of_int64_entries,
+                                        number_of_ptr_entries,
+                                        number_of_int32_entries);
+#ifndef V8_HOST_ARCH_64_BIT
+  size += kPointerSize;
+#endif
+
+  HeapObject* object;
+  { MaybeObject* maybe_object = old_pointer_space_->AllocateRaw(size);
+    if (!maybe_object->To<HeapObject>(&object)) return maybe_object;
+  }
+  object = EnsureDoubleAligned(this, object, size);
+  HeapObject::cast(object)->set_map_no_write_barrier(constant_pool_array_map());
+
+  ConstantPoolArray* constant_pool =
+      reinterpret_cast<ConstantPoolArray*>(object);
+  constant_pool->SetEntryCounts(number_of_int64_entries,
+                                number_of_ptr_entries,
+                                number_of_int32_entries);
+  MemsetPointer(
+      HeapObject::RawField(
+          constant_pool,
+          constant_pool->OffsetOfElementAt(constant_pool->first_ptr_index())),
+      undefined_value(),
+      number_of_ptr_entries);
+  return constant_pool;
+}
+
+
 MaybeObject* Heap::AllocateHashTable(int length, PretenureFlag pretenure) {
   Object* result;
   { MaybeObject* maybe_result = AllocateFixedArray(length, pretenure);
diff --git a/src/heap.h b/src/heap.h
index f5b99d6..2344488 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -71,6 +71,7 @@
   V(Map, scope_info_map, ScopeInfoMap)                                         \
   V(Map, fixed_cow_array_map, FixedCOWArrayMap)                                \
   V(Map, fixed_double_array_map, FixedDoubleArrayMap)                          \
+  V(Map, constant_pool_array_map, ConstantPoolArrayMap)                        \
   V(Object, no_interceptor_result_sentinel, NoInterceptorResultSentinel)       \
   V(Map, hash_table_map, HashTableMap)                                         \
   V(FixedArray, empty_fixed_array, EmptyFixedArray)                            \
@@ -943,6 +944,16 @@
   MUST_USE_RESULT MaybeObject* CopyFixedDoubleArrayWithMap(
       FixedDoubleArray* src, Map* map);
 
+  // Make a copy of src and return it. Returns
+  // Failure::RetryAfterGC(requested_bytes, space) if the allocation failed.
+  MUST_USE_RESULT inline MaybeObject* CopyConstantPoolArray(
+      ConstantPoolArray* src);
+
+  // Make a copy of src, set the map, and return the copy. Returns
+  // Failure::RetryAfterGC(requested_bytes, space) if the allocation failed.
+  MUST_USE_RESULT MaybeObject* CopyConstantPoolArrayWithMap(
+      ConstantPoolArray* src, Map* map);
+
   // Allocates a fixed array initialized with the hole values.
   // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
   // failed.
@@ -951,6 +962,11 @@
       int length,
       PretenureFlag pretenure = NOT_TENURED);
 
+  MUST_USE_RESULT MaybeObject* AllocateConstantPoolArray(
+      int first_int64_index,
+      int first_ptr_index,
+      int first_int32_index);
+
   // Allocates a fixed double array with uninitialized values. Returns
   // Failure::RetryAfterGC(requested_bytes, space) if the allocation failed.
   // Please note this does not perform a garbage collection.
@@ -1660,6 +1676,14 @@
     total_regexp_code_generated_ += size;
   }
 
+  void IncrementCodeGeneratedBytes(bool is_crankshafted, int size) {
+    if (is_crankshafted) {
+      crankshaft_codegen_bytes_generated_ += size;
+    } else {
+      full_codegen_bytes_generated_ += size;
+    }
+  }
+
   // Returns maximum GC pause.
   double get_max_gc_pause() { return max_gc_pause_; }
 
@@ -2355,6 +2379,10 @@
   unsigned int gc_count_at_last_idle_gc_;
   int scavenges_since_last_idle_round_;
 
+  // These two counters are monotomically increasing and never reset.
+  size_t full_codegen_bytes_generated_;
+  size_t crankshaft_codegen_bytes_generated_;
+
   // If the --deopt_every_n_garbage_collections flag is set to a positive value,
   // this variable holds the number of garbage collections since the last
   // deoptimization triggered by garbage collection.
diff --git a/src/hydrogen-dce.cc b/src/hydrogen-dce.cc
index 0e7253d..cba9e42 100644
--- a/src/hydrogen-dce.cc
+++ b/src/hydrogen-dce.cc
@@ -31,56 +31,60 @@
 namespace v8 {
 namespace internal {
 
-bool HDeadCodeEliminationPhase::MarkLive(HValue* ref, HValue* instr) {
-  if (instr->CheckFlag(HValue::kIsLive)) return false;
-  instr->SetFlag(HValue::kIsLive);
+void HDeadCodeEliminationPhase::MarkLive(
+    HValue* instr, ZoneList<HValue*>* worklist) {
+  if (instr->CheckFlag(HValue::kIsLive)) return;  // Already live.
 
-  if (FLAG_trace_dead_code_elimination) {
-    HeapStringAllocator allocator;
-    StringStream stream(&allocator);
-    if (ref != NULL) {
-      ref->PrintTo(&stream);
-    } else {
-      stream.Add("root ");
+  if (FLAG_trace_dead_code_elimination) PrintLive(NULL, instr);
+
+  // Transitively mark all inputs of live instructions live.
+  worklist->Add(instr, zone());
+  while (!worklist->is_empty()) {
+    HValue* instr = worklist->RemoveLast();
+    instr->SetFlag(HValue::kIsLive);
+    for (int i = 0; i < instr->OperandCount(); ++i) {
+      HValue* input = instr->OperandAt(i);
+      if (!input->CheckFlag(HValue::kIsLive)) {
+        input->SetFlag(HValue::kIsLive);
+        worklist->Add(input, zone());
+        if (FLAG_trace_dead_code_elimination) PrintLive(instr, input);
+      }
     }
-    stream.Add(" -> ");
-    instr->PrintTo(&stream);
-    PrintF("[MarkLive %s]\n", *stream.ToCString());
   }
+}
 
-  return true;
+
+void HDeadCodeEliminationPhase::PrintLive(HValue* ref, HValue* instr) {
+  HeapStringAllocator allocator;
+  StringStream stream(&allocator);
+  if (ref != NULL) {
+    ref->PrintTo(&stream);
+  } else {
+    stream.Add("root ");
+  }
+  stream.Add(" -> ");
+  instr->PrintTo(&stream);
+  PrintF("[MarkLive %s]\n", *stream.ToCString());
 }
 
 
 void HDeadCodeEliminationPhase::MarkLiveInstructions() {
-  ZoneList<HValue*> worklist(graph()->blocks()->length(), zone());
+  ZoneList<HValue*> worklist(10, zone());
 
-  // Mark initial root instructions for dead code elimination.
+  // Transitively mark all live instructions, starting from roots.
   for (int i = 0; i < graph()->blocks()->length(); ++i) {
     HBasicBlock* block = graph()->blocks()->at(i);
     for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
       HInstruction* instr = it.Current();
-      if (instr->CannotBeEliminated() && MarkLive(NULL, instr)) {
-        worklist.Add(instr, zone());
-      }
+      if (instr->CannotBeEliminated()) MarkLive(instr, &worklist);
     }
     for (int j = 0; j < block->phis()->length(); j++) {
       HPhi* phi = block->phis()->at(j);
-      if (phi->CannotBeEliminated() && MarkLive(NULL, phi)) {
-        worklist.Add(phi, zone());
-      }
+      if (phi->CannotBeEliminated()) MarkLive(phi, &worklist);
     }
   }
 
-  // Transitively mark all inputs of live instructions live.
-  while (!worklist.is_empty()) {
-    HValue* instr = worklist.RemoveLast();
-    for (int i = 0; i < instr->OperandCount(); ++i) {
-      if (MarkLive(instr, instr->OperandAt(i))) {
-        worklist.Add(instr->OperandAt(i), zone());
-      }
-    }
-  }
+  ASSERT(worklist.is_empty());  // Should have processed everything.
 }
 
 
diff --git a/src/hydrogen-dce.h b/src/hydrogen-dce.h
index 19749f2..2d73b38 100644
--- a/src/hydrogen-dce.h
+++ b/src/hydrogen-dce.h
@@ -45,7 +45,8 @@
   }
 
  private:
-  bool MarkLive(HValue* ref, HValue* instr);
+  void MarkLive(HValue* instr, ZoneList<HValue*>* worklist);
+  void PrintLive(HValue* ref, HValue* instr);
   void MarkLiveInstructions();
   void RemoveDeadInstructions();
 };
diff --git a/src/hydrogen-flow-engine.h b/src/hydrogen-flow-engine.h
index 8b836d2..dfe43ec 100644
--- a/src/hydrogen-flow-engine.h
+++ b/src/hydrogen-flow-engine.h
@@ -107,7 +107,7 @@
     for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
       state = state->Process(it.Current(), zone_);
     }
-    return StateAt(block);
+    return state;
   }
 
   // Global analysis. Iterates over all blocks that are dominated by the given
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index db8de3f..c25d7a1 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -3969,6 +3969,11 @@
 }
 
 
+void HOptimizedGraphBuilder::VisitCaseClause(CaseClause* clause) {
+  UNREACHABLE();
+}
+
+
 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo(
     Code* unoptimized_code, FunctionLiteral* expr) {
   int start_position = expr->start_position();
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 65d838c..2f8f5d7 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -2759,7 +2759,7 @@
                                          Address src,
                                          int size,
                                          AllocationSpace dest) {
-  HEAP_PROFILE(heap(), ObjectMoveEvent(src, dst));
+  HEAP_PROFILE(heap(), ObjectMoveEvent(src, dst, size));
   ASSERT(heap()->AllowedToBeMigrated(HeapObject::FromAddress(src), dest));
   ASSERT(dest != LO_SPACE && size <= Page::kMaxNonCodeHeapObjectSize);
   if (dest == OLD_POINTER_SPACE) {
@@ -2942,7 +2942,9 @@
   ASSERT(target_space == heap()->old_pointer_space() ||
          target_space == heap()->old_data_space());
   Object* result;
-  MaybeObject* maybe_result = target_space->AllocateRaw(object_size);
+  MaybeObject* maybe_result = target_space->AllocateRaw(
+      object_size,
+      PagedSpace::MOVE_OBJECT);
   if (maybe_result->ToObject(&result)) {
     HeapObject* target = HeapObject::cast(result);
     MigrateObject(target->address(),
@@ -3015,7 +3017,7 @@
 
       int size = object->Size();
 
-      MaybeObject* target = space->AllocateRaw(size);
+      MaybeObject* target = space->AllocateRaw(size, PagedSpace::MOVE_OBJECT);
       if (target->IsFailure()) {
         // OS refused to give us memory.
         V8::FatalProcessOutOfMemory("Evacuation");
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index caf0baf..90b0193 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -95,6 +95,9 @@
     case FIXED_DOUBLE_ARRAY_TYPE:
       FixedDoubleArray::cast(this)->FixedDoubleArrayVerify();
       break;
+    case CONSTANT_POOL_ARRAY_TYPE:
+      ConstantPoolArray::cast(this)->ConstantPoolArrayVerify();
+      break;
     case BYTE_ARRAY_TYPE:
       ByteArray::cast(this)->ByteArrayVerify();
       break;
@@ -439,6 +442,11 @@
 }
 
 
+void ConstantPoolArray::ConstantPoolArrayVerify() {
+  CHECK(IsConstantPoolArray());
+}
+
+
 void JSGeneratorObject::JSGeneratorObjectVerify() {
   // In an expression like "new g()", there can be a point where a generator
   // object is allocated but its fields are all undefined, as it hasn't yet been
diff --git a/src/objects-inl.h b/src/objects-inl.h
index c16275b..006aff3 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -133,7 +133,7 @@
 
 
 bool Object::IsFixedArrayBase() {
-  return IsFixedArray() || IsFixedDoubleArray();
+  return IsFixedArray() || IsFixedDoubleArray() || IsConstantPoolArray();
 }
 
 
@@ -571,6 +571,7 @@
 TYPE_CHECKER(Map, MAP_TYPE)
 TYPE_CHECKER(FixedArray, FIXED_ARRAY_TYPE)
 TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
+TYPE_CHECKER(ConstantPoolArray, CONSTANT_POOL_ARRAY_TYPE)
 
 
 bool Object::IsJSWeakCollection() {
@@ -1027,6 +1028,12 @@
 #define WRITE_UINT32_FIELD(p, offset, value) \
   (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
 
+#define READ_INT32_FIELD(p, offset) \
+  (*reinterpret_cast<int32_t*>(FIELD_ADDR(p, offset)))
+
+#define WRITE_INT32_FIELD(p, offset, value) \
+  (*reinterpret_cast<int32_t*>(FIELD_ADDR(p, offset)) = value)
+
 #define READ_INT64_FIELD(p, offset) \
   (*reinterpret_cast<int64_t*>(FIELD_ADDR(p, offset)))
 
@@ -1887,7 +1894,8 @@
 
 
 FixedArrayBase* FixedArrayBase::cast(Object* object) {
-  ASSERT(object->IsFixedArray() || object->IsFixedDoubleArray());
+  ASSERT(object->IsFixedArray() || object->IsFixedDoubleArray() ||
+         object->IsConstantPoolArray());
   return reinterpret_cast<FixedArrayBase*>(object);
 }
 
@@ -1986,6 +1994,98 @@
 }
 
 
+SMI_ACCESSORS(ConstantPoolArray, first_ptr_index, kFirstPointerIndexOffset)
+SMI_ACCESSORS(ConstantPoolArray, first_int32_index, kFirstInt32IndexOffset)
+
+
+int ConstantPoolArray::first_int64_index() {
+  return 0;
+}
+
+
+int ConstantPoolArray::count_of_int64_entries() {
+  return first_ptr_index();
+}
+
+
+int ConstantPoolArray::count_of_ptr_entries() {
+  return first_int32_index() - first_ptr_index();
+}
+
+
+int ConstantPoolArray::count_of_int32_entries() {
+  return length() - first_int32_index();
+}
+
+
+void ConstantPoolArray::SetEntryCounts(int number_of_int64_entries,
+                                       int number_of_ptr_entries,
+                                       int number_of_int32_entries) {
+  set_first_ptr_index(number_of_int64_entries);
+  set_first_int32_index(number_of_int64_entries + number_of_ptr_entries);
+  set_length(number_of_int64_entries + number_of_ptr_entries +
+             number_of_int32_entries);
+}
+
+
+int64_t ConstantPoolArray::get_int64_entry(int index) {
+  ASSERT(map() == GetHeap()->constant_pool_array_map());
+  ASSERT(index >= 0 && index < first_ptr_index());
+  return READ_INT64_FIELD(this, OffsetOfElementAt(index));
+}
+
+double ConstantPoolArray::get_int64_entry_as_double(int index) {
+  STATIC_ASSERT(kDoubleSize == kInt64Size);
+  ASSERT(map() == GetHeap()->constant_pool_array_map());
+  ASSERT(index >= 0 && index < first_ptr_index());
+  return READ_DOUBLE_FIELD(this, OffsetOfElementAt(index));
+}
+
+
+Object* ConstantPoolArray::get_ptr_entry(int index) {
+  ASSERT(map() == GetHeap()->constant_pool_array_map());
+  ASSERT(index >= first_ptr_index() && index < first_int32_index());
+  return READ_FIELD(this, OffsetOfElementAt(index));
+}
+
+
+int32_t ConstantPoolArray::get_int32_entry(int index) {
+  ASSERT(map() == GetHeap()->constant_pool_array_map());
+  ASSERT(index >= first_int32_index() && index < length());
+  return READ_INT32_FIELD(this, OffsetOfElementAt(index));
+}
+
+
+void ConstantPoolArray::set(int index, Object* value) {
+  ASSERT(map() == GetHeap()->constant_pool_array_map());
+  ASSERT(index >= first_ptr_index() && index < first_int32_index());
+  WRITE_FIELD(this, OffsetOfElementAt(index), value);
+  WRITE_BARRIER(GetHeap(), this, OffsetOfElementAt(index), value);
+}
+
+
+void ConstantPoolArray::set(int index, int64_t value) {
+  ASSERT(map() == GetHeap()->constant_pool_array_map());
+  ASSERT(index >= first_int64_index() && index < first_ptr_index());
+  WRITE_INT64_FIELD(this, OffsetOfElementAt(index), value);
+}
+
+
+void ConstantPoolArray::set(int index, double value) {
+  STATIC_ASSERT(kDoubleSize == kInt64Size);
+  ASSERT(map() == GetHeap()->constant_pool_array_map());
+  ASSERT(index >= first_int64_index() && index < first_ptr_index());
+  WRITE_DOUBLE_FIELD(this, OffsetOfElementAt(index), value);
+}
+
+
+void ConstantPoolArray::set(int index, int32_t value) {
+  ASSERT(map() == GetHeap()->constant_pool_array_map());
+  ASSERT(index >= this->first_int32_index() && index < length());
+  WRITE_INT32_FIELD(this, OffsetOfElementAt(index), value);
+}
+
+
 WriteBarrierMode HeapObject::GetWriteBarrierMode(
     const DisallowHeapAllocation& promise) {
   Heap* heap = GetHeap();
@@ -2478,6 +2578,7 @@
 
 CAST_ACCESSOR(FixedArray)
 CAST_ACCESSOR(FixedDoubleArray)
+CAST_ACCESSOR(ConstantPoolArray)
 CAST_ACCESSOR(DescriptorArray)
 CAST_ACCESSOR(DeoptimizationInputData)
 CAST_ACCESSOR(DeoptimizationOutputData)
@@ -3373,6 +3474,12 @@
     return FixedDoubleArray::SizeFor(
         reinterpret_cast<FixedDoubleArray*>(this)->length());
   }
+  if (instance_type == CONSTANT_POOL_ARRAY_TYPE) {
+    return ConstantPoolArray::SizeFor(
+        reinterpret_cast<ConstantPoolArray*>(this)->count_of_int64_entries(),
+        reinterpret_cast<ConstantPoolArray*>(this)->count_of_ptr_entries(),
+        reinterpret_cast<ConstantPoolArray*>(this)->count_of_int32_entries());
+  }
   ASSERT(instance_type == CODE_TYPE);
   return reinterpret_cast<Code*>(this)->CodeSize();
 }
@@ -6052,6 +6159,12 @@
 }
 
 
+MaybeObject* ConstantPoolArray::Copy() {
+  if (length() == 0) return this;
+  return GetHeap()->CopyConstantPoolArray(this);
+}
+
+
 void TypeFeedbackCells::SetAstId(int index, TypeFeedbackId id) {
   set(1 + index * 2, Smi::FromInt(id.ToInt()));
 }
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index f4b4a4f..60c1ef4 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -95,6 +95,9 @@
     case FIXED_DOUBLE_ARRAY_TYPE:
       FixedDoubleArray::cast(this)->FixedDoubleArrayPrint(out);
       break;
+    case CONSTANT_POOL_ARRAY_TYPE:
+      ConstantPoolArray::cast(this)->ConstantPoolArrayPrint(out);
+      break;
     case FIXED_ARRAY_TYPE:
       FixedArray::cast(this)->FixedArrayPrint(out);
       break;
@@ -630,6 +633,23 @@
 }
 
 
+void ConstantPoolArray::ConstantPoolArrayPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "ConstantPoolArray");
+  PrintF(out, " - length: %d", length());
+  for (int i = 0; i < length(); i++) {
+    if (i < first_ptr_index()) {
+      PrintF(out, "\n  [%d]: double: %g", i, get_int64_entry_as_double(i));
+    } else if (i < first_int32_index()) {
+      PrintF(out, "\n  [%d]: pointer: %p", i,
+             reinterpret_cast<void*>(get_ptr_entry(i)));
+    } else {
+      PrintF(out, "\n  [%d]: int32: %d", i, get_int32_entry(i));
+    }
+  }
+  PrintF(out, "\n");
+}
+
+
 void JSValue::JSValuePrint(FILE* out) {
   HeapObject::PrintHeader(out, "ValueObject");
   value()->Print(out);
diff --git a/src/objects-visiting-inl.h b/src/objects-visiting-inl.h
index d5dd44e..93b7cb9 100644
--- a/src/objects-visiting-inl.h
+++ b/src/objects-visiting-inl.h
@@ -185,6 +185,8 @@
 
   table_.Register(kVisitFixedDoubleArray, &DataObjectVisitor::Visit);
 
+  table_.Register(kVisitConstantPoolArray, &VisitConstantPoolArray);
+
   table_.Register(kVisitNativeContext, &VisitNativeContext);
 
   table_.Register(kVisitAllocationSite,
@@ -450,6 +452,22 @@
 
 
 template<typename StaticVisitor>
+void StaticMarkingVisitor<StaticVisitor>::VisitConstantPoolArray(
+    Map* map, HeapObject* object) {
+  Heap* heap = map->GetHeap();
+  ConstantPoolArray* constant_pool = ConstantPoolArray::cast(object);
+  int first_ptr_offset = constant_pool->OffsetOfElementAt(
+      constant_pool->first_ptr_index());
+  int last_ptr_offset = constant_pool->OffsetOfElementAt(
+      constant_pool->first_ptr_index() + constant_pool->count_of_ptr_entries());
+  StaticVisitor::VisitPointers(
+      heap,
+      HeapObject::RawField(object, first_ptr_offset),
+      HeapObject::RawField(object, last_ptr_offset));
+}
+
+
+template<typename StaticVisitor>
 void StaticMarkingVisitor<StaticVisitor>::VisitJSFunction(
     Map* map, HeapObject* object) {
   Heap* heap = map->GetHeap();
diff --git a/src/objects-visiting.cc b/src/objects-visiting.cc
index cd46013..5ced2cf 100644
--- a/src/objects-visiting.cc
+++ b/src/objects-visiting.cc
@@ -82,6 +82,9 @@
     case FIXED_DOUBLE_ARRAY_TYPE:
       return kVisitFixedDoubleArray;
 
+    case CONSTANT_POOL_ARRAY_TYPE:
+      return kVisitConstantPoolArray;
+
     case ODDBALL_TYPE:
       return kVisitOddball;
 
diff --git a/src/objects-visiting.h b/src/objects-visiting.h
index 2175737..60e6f67 100644
--- a/src/objects-visiting.h
+++ b/src/objects-visiting.h
@@ -54,6 +54,7 @@
   V(FreeSpace)                \
   V(FixedArray)               \
   V(FixedDoubleArray)         \
+  V(ConstantPoolArray)        \
   V(NativeContext)            \
   V(AllocationSite)           \
   V(DataObject2)              \
@@ -416,6 +417,7 @@
   INLINE(static void VisitMap(Map* map, HeapObject* object));
   INLINE(static void VisitCode(Map* map, HeapObject* object));
   INLINE(static void VisitSharedFunctionInfo(Map* map, HeapObject* object));
+  INLINE(static void VisitConstantPoolArray(Map* map, HeapObject* object));
   INLINE(static void VisitJSFunction(Map* map, HeapObject* object));
   INLINE(static void VisitJSRegExp(Map* map, HeapObject* object));
   INLINE(static void VisitJSArrayBuffer(Map* map, HeapObject* object));
diff --git a/src/objects.cc b/src/objects.cc
index f39b760..26cb3c5 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1737,6 +1737,9 @@
     case FIXED_ARRAY_TYPE:
       FixedArray::BodyDescriptor::IterateBody(this, object_size, v);
       break;
+    case CONSTANT_POOL_ARRAY_TYPE:
+      reinterpret_cast<ConstantPoolArray*>(this)->ConstantPoolIterateBody(v);
+      break;
     case FIXED_DOUBLE_ARRAY_TYPE:
       break;
     case JS_OBJECT_TYPE:
@@ -2284,6 +2287,13 @@
       MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta);
     }
   }
+
+  // The array may not be moved during GC,
+  // and size has to be adjusted nevertheless.
+  HeapProfiler* profiler = heap->isolate()->heap_profiler();
+  if (profiler->is_tracking_allocations()) {
+    profiler->UpdateObjectSizeEvent(elms->address(), elms->Size());
+  }
 }
 
 
@@ -9355,6 +9365,16 @@
 }
 
 
+void ConstantPoolArray::ConstantPoolIterateBody(ObjectVisitor* v) {
+  int first_ptr_offset = OffsetOfElementAt(first_ptr_index());
+  int last_ptr_offset =
+      OffsetOfElementAt(first_ptr_index() + count_of_ptr_entries());
+  v->VisitPointers(
+      HeapObject::RawField(this, first_ptr_offset),
+      HeapObject::RawField(this, last_ptr_offset));
+}
+
+
 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
   // Iterate over all fields in the body but take care in dealing with
   // the code entry.
diff --git a/src/objects.h b/src/objects.h
index 0d1b251..2925c54 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -405,6 +405,7 @@
                                                                                \
   V(FIXED_ARRAY_TYPE)                                                          \
   V(FIXED_DOUBLE_ARRAY_TYPE)                                                   \
+  V(CONSTANT_POOL_ARRAY_TYPE)                                                  \
   V(SHARED_FUNCTION_INFO_TYPE)                                                 \
                                                                                \
   V(JS_MESSAGE_OBJECT_TYPE)                                                    \
@@ -715,6 +716,7 @@
   EXTERNAL_DOUBLE_ARRAY_TYPE,
   EXTERNAL_PIXEL_ARRAY_TYPE,  // LAST_EXTERNAL_ARRAY_TYPE
   FIXED_DOUBLE_ARRAY_TYPE,
+  CONSTANT_POOL_ARRAY_TYPE,
   FILLER_TYPE,  // LAST_DATA_TYPE
 
   // Structs.
@@ -1000,6 +1002,7 @@
   V(TypeFeedbackCells)                         \
   V(FixedArray)                                \
   V(FixedDoubleArray)                          \
+  V(ConstantPoolArray)                         \
   V(Context)                                   \
   V(NativeContext)                             \
   V(ScopeInfo)                                 \
@@ -3032,6 +3035,100 @@
 };
 
 
+// ConstantPoolArray describes a fixed-sized array containing constant pool
+// entires.
+// The format of the pool is:
+//   [0]: Field holding the first index which is a pointer entry
+//   [1]: Field holding the first index which is a int32 entry
+//   [2] ... [first_ptr_index() - 1]: 64 bit entries
+//   [first_ptr_index()] ... [first_int32_index() - 1]: pointer entries
+//   [first_int32_index()] ... [length - 1]: 32 bit entries
+class ConstantPoolArray: public FixedArrayBase {
+ public:
+  // Getters for the field storing the first index for different type entries.
+  inline int first_ptr_index();
+  inline int first_int64_index();
+  inline int first_int32_index();
+
+  // Getters for counts of different type entries.
+  inline int count_of_ptr_entries();
+  inline int count_of_int64_entries();
+  inline int count_of_int32_entries();
+
+  // Setter and getter for pool elements.
+  inline Object* get_ptr_entry(int index);
+  inline int64_t get_int64_entry(int index);
+  inline int32_t get_int32_entry(int index);
+  inline double get_int64_entry_as_double(int index);
+
+  inline void set(int index, Object* value);
+  inline void set(int index, int64_t value);
+  inline void set(int index, double value);
+  inline void set(int index, int32_t value);
+
+  // Set up initial state.
+  inline void SetEntryCounts(int number_of_int64_entries,
+                             int number_of_ptr_entries,
+                             int number_of_int32_entries);
+
+  // Copy operations
+  MUST_USE_RESULT inline MaybeObject* Copy();
+
+  // Garbage collection support.
+  inline static int SizeFor(int number_of_int64_entries,
+                            int number_of_ptr_entries,
+                            int number_of_int32_entries) {
+    return RoundUp(OffsetAt(number_of_int64_entries,
+                            number_of_ptr_entries,
+                            number_of_int32_entries),
+                   kPointerSize);
+  }
+
+  // Code Generation support.
+  inline int OffsetOfElementAt(int index) {
+    ASSERT(index < length());
+    if (index >= first_int32_index()) {
+      return OffsetAt(count_of_int64_entries(), count_of_ptr_entries(),
+                      index - first_int32_index());
+    } else if (index >= first_ptr_index()) {
+      return OffsetAt(count_of_int64_entries(), index - first_ptr_index(), 0);
+    } else {
+      return OffsetAt(index, 0, 0);
+    }
+  }
+
+  // Casting.
+  static inline ConstantPoolArray* cast(Object* obj);
+
+  // Layout description.
+  static const int kFirstPointerIndexOffset = FixedArray::kHeaderSize;
+  static const int kFirstInt32IndexOffset =
+      kFirstPointerIndexOffset + kPointerSize;
+  static const int kFirstOffset = kFirstInt32IndexOffset + kPointerSize;
+
+  // Dispatched behavior.
+  void ConstantPoolIterateBody(ObjectVisitor* v);
+
+  DECLARE_PRINTER(ConstantPoolArray)
+  DECLARE_VERIFIER(ConstantPoolArray)
+
+ private:
+  inline void set_first_ptr_index(int value);
+  inline void set_first_int32_index(int value);
+
+  inline static int OffsetAt(int number_of_int64_entries,
+                             int number_of_ptr_entries,
+                             int number_of_int32_entries) {
+    return kFirstOffset
+        + (number_of_int64_entries * kInt64Size)
+        + (number_of_ptr_entries * kPointerSize)
+        + (number_of_int32_entries * kInt32Size);
+  }
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolArray);
+};
+
+
 // DescriptorArrays are fixed arrays used to hold instance descriptors.
 // The format of the these objects is:
 //   [0]: Number of descriptors
diff --git a/src/optimizing-compiler-thread.cc b/src/optimizing-compiler-thread.cc
index 202e6e5..0053148 100644
--- a/src/optimizing-compiler-thread.cc
+++ b/src/optimizing-compiler-thread.cc
@@ -168,6 +168,7 @@
 void OptimizingCompilerThread::Flush() {
   ASSERT(!IsOptimizerThread());
   Release_Store(&stop_thread_, static_cast<AtomicWord>(FLUSH));
+  if (FLAG_block_concurrent_recompilation) Unblock();
   input_queue_semaphore_.Signal();
   stop_semaphore_.Wait();
   FlushOutputQueue(true);
@@ -181,6 +182,7 @@
 void OptimizingCompilerThread::Stop() {
   ASSERT(!IsOptimizerThread());
   Release_Store(&stop_thread_, static_cast<AtomicWord>(STOP));
+  if (FLAG_block_concurrent_recompilation) Unblock();
   input_queue_semaphore_.Signal();
   stop_semaphore_.Wait();
 
@@ -252,7 +254,20 @@
     info->closure()->MarkInRecompileQueue();
   }
   input_queue_.Enqueue(job);
-  input_queue_semaphore_.Signal();
+  if (FLAG_block_concurrent_recompilation) {
+    blocked_jobs_++;
+  } else {
+    input_queue_semaphore_.Signal();
+  }
+}
+
+
+void OptimizingCompilerThread::Unblock() {
+  ASSERT(!IsOptimizerThread());
+  while (blocked_jobs_ > 0) {
+    input_queue_semaphore_.Signal();
+    blocked_jobs_--;
+  }
 }
 
 
diff --git a/src/optimizing-compiler-thread.h b/src/optimizing-compiler-thread.h
index d98a8b2..8992142 100644
--- a/src/optimizing-compiler-thread.h
+++ b/src/optimizing-compiler-thread.h
@@ -55,7 +55,8 @@
       input_queue_semaphore_(0),
       osr_cursor_(0),
       osr_hits_(0),
-      osr_attempts_(0) {
+      osr_attempts_(0),
+      blocked_jobs_(0) {
     NoBarrier_Store(&stop_thread_, static_cast<AtomicWord>(CONTINUE));
     NoBarrier_Store(&queue_length_, static_cast<AtomicWord>(0));
     if (FLAG_concurrent_osr) {
@@ -73,6 +74,7 @@
   void Stop();
   void Flush();
   void QueueForOptimization(RecompileJob* optimizing_compiler);
+  void Unblock();
   void InstallOptimizedFunctions();
   RecompileJob* FindReadyOSRCandidate(Handle<JSFunction> function,
                                       uint32_t osr_pc_offset);
@@ -141,6 +143,8 @@
 
   int osr_hits_;
   int osr_attempts_;
+
+  int blocked_jobs_;
 };
 
 } }  // namespace v8::internal
diff --git a/src/parser.cc b/src/parser.cc
index 96b1aa8..1f60163 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -536,7 +536,8 @@
 // Implementation of Parser
 
 Parser::Parser(CompilationInfo* info)
-    : isolate_(info->isolate()),
+    : ParserBase(&scanner_, info->isolate()->stack_guard()->real_climit()),
+      isolate_(info->isolate()),
       symbol_cache_(0, info->zone()),
       script_(info->script()),
       scanner_(isolate_->unicode_cache()),
@@ -548,11 +549,6 @@
       extension_(info->extension()),
       pre_parse_data_(NULL),
       fni_(NULL),
-      allow_natives_syntax_(false),
-      allow_lazy_(false),
-      allow_generators_(false),
-      allow_for_of_(false),
-      stack_overflow_(false),
       parenthesized_function_(false),
       zone_(info->zone()),
       info_(info) {
@@ -652,10 +648,10 @@
     top_scope_->SetLanguageMode(info->language_mode());
     ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
     bool ok = true;
-    int beg_loc = scanner().location().beg_pos;
+    int beg_pos = scanner().location().beg_pos;
     ParseSourceElements(body, Token::EOS, info->is_eval(), true, &ok);
     if (ok && !top_scope_->is_classic_mode()) {
-      CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok);
+      CheckOctalLiteral(beg_pos, scanner().location().end_pos, &ok);
     }
 
     if (ok && is_extended_mode()) {
@@ -685,11 +681,12 @@
           FunctionLiteral::ANONYMOUS_EXPRESSION,
           FunctionLiteral::kGlobalOrEval,
           FunctionLiteral::kNotParenthesized,
-          FunctionLiteral::kNotGenerator);
+          FunctionLiteral::kNotGenerator,
+          0);
       result->set_ast_properties(factory()->visitor()->ast_properties());
       result->set_dont_optimize_reason(
           factory()->visitor()->dont_optimize_reason());
-    } else if (stack_overflow_) {
+    } else if (stack_overflow()) {
       isolate()->StackOverflow();
     }
   }
@@ -786,7 +783,7 @@
   ASSERT(target_stack_ == NULL);
 
   if (result == NULL) {
-    if (stack_overflow_) isolate()->StackOverflow();
+    if (stack_overflow()) isolate()->StackOverflow();
   } else {
     Handle<String> inferred_name(shared_info->inferred_name());
     result->set_inferred_name(inferred_name);
@@ -984,6 +981,7 @@
   // ModuleDeclaration:
   //    'module' Identifier Module
 
+  int pos = peek_position();
   Handle<String> name = ParseIdentifier(CHECK_OK);
 
 #ifdef DEBUG
@@ -994,7 +992,7 @@
   Module* module = ParseModule(CHECK_OK);
   VariableProxy* proxy = NewUnresolved(name, MODULE, module->interface());
   Declaration* declaration =
-      factory()->NewModuleDeclaration(proxy, module, top_scope_);
+      factory()->NewModuleDeclaration(proxy, module, top_scope_, pos);
   Declare(declaration, true, CHECK_OK);
 
 #ifdef DEBUG
@@ -1009,9 +1007,9 @@
 
   if (names) names->Add(name, zone());
   if (module->body() == NULL)
-    return factory()->NewEmptyStatement();
+    return factory()->NewEmptyStatement(pos);
   else
-    return factory()->NewModuleStatement(proxy, module->body());
+    return factory()->NewModuleStatement(proxy, module->body(), pos);
 }
 
 
@@ -1046,8 +1044,9 @@
   // Module:
   //    '{' ModuleElement '}'
 
+  int pos = peek_position();
   // Construct block expecting 16 statements.
-  Block* body = factory()->NewBlock(NULL, 16, false);
+  Block* body = factory()->NewBlock(NULL, 16, false, RelocInfo::kNoPosition);
 #ifdef DEBUG
   if (FLAG_print_interface_details) PrintF("# Literal ");
 #endif
@@ -1092,7 +1091,7 @@
   ASSERT(*ok);
   interface->Freeze(ok);
   ASSERT(*ok);
-  return factory()->NewModuleLiteral(body, interface);
+  return factory()->NewModuleLiteral(body, interface, pos);
 }
 
 
@@ -1101,6 +1100,7 @@
   //    Identifier
   //    ModulePath '.' Identifier
 
+  int pos = peek_position();
   Module* result = ParseModuleVariable(CHECK_OK);
   while (Check(Token::PERIOD)) {
     Handle<String> name = ParseIdentifierName(CHECK_OK);
@@ -1108,7 +1108,7 @@
     if (FLAG_print_interface_details)
       PrintF("# Path .%s ", name->ToAsciiArray());
 #endif
-    Module* member = factory()->NewModulePath(result, name);
+    Module* member = factory()->NewModulePath(result, name, pos);
     result->interface()->Add(name, member->interface(), zone(), ok);
     if (!*ok) {
 #ifdef DEBUG
@@ -1134,6 +1134,7 @@
   // ModulePath:
   //    Identifier
 
+  int pos = peek_position();
   Handle<String> name = ParseIdentifier(CHECK_OK);
 #ifdef DEBUG
   if (FLAG_print_interface_details)
@@ -1143,7 +1144,7 @@
       factory(), name, Interface::NewModule(zone()),
       scanner().location().beg_pos);
 
-  return factory()->NewModuleVariable(proxy);
+  return factory()->NewModuleVariable(proxy, pos);
 }
 
 
@@ -1151,6 +1152,7 @@
   // Module:
   //    String
 
+  int pos = peek_position();
   Expect(Token::STRING, CHECK_OK);
   Handle<String> symbol = GetSymbol();
 
@@ -1163,10 +1165,10 @@
   // Create an empty literal as long as the feature isn't finished.
   USE(symbol);
   Scope* scope = NewScope(top_scope_, MODULE_SCOPE);
-  Block* body = factory()->NewBlock(NULL, 1, false);
+  Block* body = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
   body->set_scope(scope);
   Interface* interface = scope->interface();
-  Module* result = factory()->NewModuleLiteral(body, interface);
+  Module* result = factory()->NewModuleLiteral(body, interface, pos);
   interface->Freeze(ok);
   ASSERT(*ok);
   interface->Unify(scope->interface(), zone(), ok);
@@ -1194,6 +1196,7 @@
   //
   // TODO(ES6): implement destructuring ImportSpecifiers
 
+  int pos = peek_position();
   Expect(Token::IMPORT, CHECK_OK);
   ZoneStringList names(1, zone());
 
@@ -1211,7 +1214,7 @@
 
   // Generate a separate declaration for each identifier.
   // TODO(ES6): once we implement destructuring, make that one declaration.
-  Block* block = factory()->NewBlock(NULL, 1, true);
+  Block* block = factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
   for (int i = 0; i < names.length(); ++i) {
 #ifdef DEBUG
     if (FLAG_print_interface_details)
@@ -1232,7 +1235,7 @@
     }
     VariableProxy* proxy = NewUnresolved(names[i], LET, interface);
     Declaration* declaration =
-        factory()->NewImportDeclaration(proxy, module, top_scope_);
+        factory()->NewImportDeclaration(proxy, module, top_scope_, pos);
     Declare(declaration, true, CHECK_OK);
   }
 
@@ -1256,6 +1259,7 @@
   ZoneStringList names(1, zone());
   switch (peek()) {
     case Token::IDENTIFIER: {
+      int pos = position();
       Handle<String> name = ParseIdentifier(CHECK_OK);
       // Handle 'module' as a context-sensitive keyword.
       if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("module"))) {
@@ -1266,7 +1270,7 @@
           names.Add(name, zone());
         }
         ExpectSemicolon(CHECK_OK);
-        result = factory()->NewEmptyStatement();
+        result = factory()->NewEmptyStatement(pos);
       } else {
         result = ParseModuleDeclaration(&names, CHECK_OK);
       }
@@ -1305,7 +1309,7 @@
     // TODO(rossberg): Rethink whether we actually need to store export
     // declarations (for compilation?).
     // ExportDeclaration* declaration =
-    //     factory()->NewExportDeclaration(proxy, top_scope_);
+    //     factory()->NewExportDeclaration(proxy, top_scope_, position);
     // top_scope_->AddDeclaration(declaration);
   }
 
@@ -1363,10 +1367,6 @@
   // labels can be simply ignored in all other cases; except for
   // trivial labeled break statements 'label: break label' which is
   // parsed into an empty statement.
-
-  // Keep the source position of the statement
-  int statement_pos = scanner().peek_location().beg_pos;
-  Statement* stmt = NULL;
   switch (peek()) {
     case Token::LBRACE:
       return ParseBlock(labels, ok);
@@ -1374,52 +1374,41 @@
     case Token::CONST:  // fall through
     case Token::LET:
     case Token::VAR:
-      stmt = ParseVariableStatement(kStatement, NULL, ok);
-      break;
+      return ParseVariableStatement(kStatement, NULL, ok);
 
     case Token::SEMICOLON:
       Next();
-      return factory()->NewEmptyStatement();
+      return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
 
     case Token::IF:
-      stmt = ParseIfStatement(labels, ok);
-      break;
+      return ParseIfStatement(labels, ok);
 
     case Token::DO:
-      stmt = ParseDoWhileStatement(labels, ok);
-      break;
+      return ParseDoWhileStatement(labels, ok);
 
     case Token::WHILE:
-      stmt = ParseWhileStatement(labels, ok);
-      break;
+      return ParseWhileStatement(labels, ok);
 
     case Token::FOR:
-      stmt = ParseForStatement(labels, ok);
-      break;
+      return ParseForStatement(labels, ok);
 
     case Token::CONTINUE:
-      stmt = ParseContinueStatement(ok);
-      break;
+      return ParseContinueStatement(ok);
 
     case Token::BREAK:
-      stmt = ParseBreakStatement(labels, ok);
-      break;
+      return ParseBreakStatement(labels, ok);
 
     case Token::RETURN:
-      stmt = ParseReturnStatement(ok);
-      break;
+      return ParseReturnStatement(ok);
 
     case Token::WITH:
-      stmt = ParseWithStatement(labels, ok);
-      break;
+      return ParseWithStatement(labels, ok);
 
     case Token::SWITCH:
-      stmt = ParseSwitchStatement(labels, ok);
-      break;
+      return ParseSwitchStatement(labels, ok);
 
     case Token::THROW:
-      stmt = ParseThrowStatement(ok);
-      break;
+      return ParseThrowStatement(ok);
 
     case Token::TRY: {
       // NOTE: It is somewhat complicated to have labels on
@@ -1427,12 +1416,10 @@
       // 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 = factory()->NewBlock(labels, 1, false);
+      Block* result =
+          factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition);
       Target target(&this->target_stack_, result);
       TryStatement* statement = ParseTryStatement(CHECK_OK);
-      if (statement) {
-        statement->set_statement_pos(statement_pos);
-      }
       if (result) result->AddStatement(statement, zone());
       return result;
     }
@@ -1459,16 +1446,11 @@
     }
 
     case Token::DEBUGGER:
-      stmt = ParseDebuggerStatement(ok);
-      break;
+      return ParseDebuggerStatement(ok);
 
     default:
-      stmt = ParseExpressionOrLabelledStatement(labels, ok);
+      return ParseExpressionOrLabelledStatement(labels, ok);
   }
-
-  // Store the source position of the statement
-  if (stmt != NULL) stmt->set_statement_pos(statement_pos);
-  return stmt;
 }
 
 
@@ -1480,7 +1462,7 @@
   // Let/const variables in harmony mode are always added to the immediately
   // enclosing scope.
   return DeclarationScope(mode)->NewUnresolved(
-      factory(), name, interface, scanner().location().beg_pos);
+      factory(), name, interface, position());
 }
 
 
@@ -1647,6 +1629,7 @@
 // declaration is resolved by looking up the function through a
 // callback provided by the extension.
 Statement* Parser::ParseNativeDeclaration(bool* ok) {
+  int pos = peek_position();
   Expect(Token::FUNCTION, CHECK_OK);
   Handle<String> name = ParseIdentifier(CHECK_OK);
   Expect(Token::LPAREN, CHECK_OK);
@@ -1672,13 +1655,14 @@
   // other functions are set up when entering the surrounding scope.
   VariableProxy* proxy = NewUnresolved(name, VAR, Interface::NewValue());
   Declaration* declaration =
-      factory()->NewVariableDeclaration(proxy, VAR, top_scope_);
+      factory()->NewVariableDeclaration(proxy, VAR, top_scope_, pos);
   Declare(declaration, true, CHECK_OK);
-  NativeFunctionLiteral* lit =
-      factory()->NewNativeFunctionLiteral(name, extension_);
+  NativeFunctionLiteral* lit = factory()->NewNativeFunctionLiteral(
+      name, extension_, RelocInfo::kNoPosition);
   return factory()->NewExpressionStatement(
       factory()->NewAssignment(
-          Token::INIT_VAR, proxy, lit, RelocInfo::kNoPosition));
+          Token::INIT_VAR, proxy, lit, RelocInfo::kNoPosition),
+      pos);
 }
 
 
@@ -1689,7 +1673,7 @@
   //   'function' '*' Identifier '(' FormalParameterListopt ')'
   //      '{' FunctionBody '}'
   Expect(Token::FUNCTION, CHECK_OK);
-  int function_token_position = scanner().location().beg_pos;
+  int pos = position();
   bool is_generator = allow_generators() && Check(Token::MUL);
   bool is_strict_reserved = false;
   Handle<String> name = ParseIdentifierOrStrictReservedWord(
@@ -1697,7 +1681,7 @@
   FunctionLiteral* fun = ParseFunctionLiteral(name,
                                               is_strict_reserved,
                                               is_generator,
-                                              function_token_position,
+                                              pos,
                                               FunctionLiteral::DECLARATION,
                                               CHECK_OK);
   // Even if we're not at the top-level of the global or a function
@@ -1709,10 +1693,10 @@
       is_extended_mode() && !top_scope_->is_global_scope() ? LET : VAR;
   VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue());
   Declaration* declaration =
-      factory()->NewFunctionDeclaration(proxy, mode, fun, top_scope_);
+      factory()->NewFunctionDeclaration(proxy, mode, fun, top_scope_, pos);
   Declare(declaration, true, CHECK_OK);
   if (names) names->Add(name, zone());
-  return factory()->NewEmptyStatement();
+  return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
 }
 
 
@@ -1726,7 +1710,8 @@
   // (ECMA-262, 3rd, 12.2)
   //
   // Construct block expecting 16 statements.
-  Block* result = factory()->NewBlock(labels, 16, false);
+  Block* result =
+      factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition);
   Target target(&this->target_stack_, result);
   Expect(Token::LBRACE, CHECK_OK);
   while (peek() != Token::RBRACE) {
@@ -1747,7 +1732,8 @@
   //   '{' BlockElement* '}'
 
   // Construct block expecting 16 statements.
-  Block* body = factory()->NewBlock(labels, 16, false);
+  Block* body =
+      factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition);
   Scope* block_scope = NewScope(top_scope_, BLOCK_SCOPE);
 
   // Parse the statements and collect escaping labels.
@@ -1817,6 +1803,8 @@
   // TODO(ES6):
   // ConstBinding ::
   //   BindingPattern '=' AssignmentExpression
+
+  int pos = peek_position();
   VariableMode mode = VAR;
   // True if the binding needs initialization. 'let' and 'const' declared
   // bindings are created uninitialized by their declaration nodes and
@@ -1902,7 +1890,7 @@
   // is inside an initializer block, it is ignored.
   //
   // Create new block with one expected declaration.
-  Block* block = factory()->NewBlock(NULL, 1, true);
+  Block* block = factory()->NewBlock(NULL, 1, true, pos);
   int nvars = 0;  // the number of variables declared
   Handle<String> name;
   do {
@@ -1939,7 +1927,7 @@
         is_const ? Interface::NewConst() : Interface::NewValue();
     VariableProxy* proxy = NewUnresolved(name, mode, interface);
     Declaration* declaration =
-        factory()->NewVariableDeclaration(proxy, mode, top_scope_);
+        factory()->NewVariableDeclaration(proxy, mode, top_scope_, pos);
     Declare(declaration, mode != VAR, CHECK_OK);
     nvars++;
     if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
@@ -1979,11 +1967,11 @@
 
     Scope* initialization_scope = is_const ? declaration_scope : top_scope_;
     Expression* value = NULL;
-    int position = -1;
+    int pos = -1;
     // Harmony consts have non-optional initializers.
     if (peek() == Token::ASSIGN || mode == CONST_HARMONY) {
       Expect(Token::ASSIGN, CHECK_OK);
-      position = scanner().location().beg_pos;
+      pos = position();
       value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
       // Don't infer if it is "a = function(){...}();"-like expression.
       if (fni_ != NULL &&
@@ -1998,12 +1986,12 @@
 
     // Record the end position of the initializer.
     if (proxy->var() != NULL) {
-      proxy->var()->set_initializer_position(scanner().location().end_pos);
+      proxy->var()->set_initializer_position(position());
     }
 
     // Make sure that 'const x' and 'let x' initialize 'x' to undefined.
     if (value == NULL && needs_init) {
-      value = GetLiteralUndefined();
+      value = GetLiteralUndefined(position());
     }
 
     // Global variable declarations must be compiled in a specific
@@ -2031,7 +2019,7 @@
       ZoneList<Expression*>* arguments =
           new(zone()) ZoneList<Expression*>(3, zone());
       // We have at least 1 parameter.
-      arguments->Add(factory()->NewLiteral(name), zone());
+      arguments->Add(factory()->NewLiteral(name, pos), zone());
       CallRuntime* initialize;
 
       if (is_const) {
@@ -2045,12 +2033,12 @@
         initialize = factory()->NewCallRuntime(
             isolate()->factory()->InitializeConstGlobal_string(),
             Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
-            arguments);
+            arguments, pos);
       } else {
         // Add strict mode.
         // We may want to pass singleton to avoid Literal allocations.
         LanguageMode language_mode = initialization_scope->language_mode();
-        arguments->Add(factory()->NewNumberLiteral(language_mode), zone());
+        arguments->Add(factory()->NewNumberLiteral(language_mode, pos), zone());
 
         // Be careful not to assign a value to the global variable if
         // we're in a with. The initialization value should not
@@ -2068,11 +2056,12 @@
         initialize = factory()->NewCallRuntime(
             isolate()->factory()->InitializeVarGlobal_string(),
             Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
-            arguments);
+            arguments, pos);
       }
 
-      block->AddStatement(factory()->NewExpressionStatement(initialize),
-                          zone());
+      block->AddStatement(
+          factory()->NewExpressionStatement(initialize, RelocInfo::kNoPosition),
+          zone());
     } 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
@@ -2085,9 +2074,10 @@
       ASSERT(proxy->var() != NULL);
       ASSERT(value != NULL);
       Assignment* assignment =
-          factory()->NewAssignment(init_op, proxy, value, position);
-      block->AddStatement(factory()->NewExpressionStatement(assignment),
-                          zone());
+          factory()->NewAssignment(init_op, proxy, value, pos);
+      block->AddStatement(
+          factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
+          zone());
       value = NULL;
     }
 
@@ -2101,9 +2091,10 @@
       VariableProxy* proxy =
           initialization_scope->NewUnresolved(factory(), name, interface);
       Assignment* assignment =
-          factory()->NewAssignment(init_op, proxy, value, position);
-      block->AddStatement(factory()->NewExpressionStatement(assignment),
-                          zone());
+          factory()->NewAssignment(init_op, proxy, value, pos);
+      block->AddStatement(
+          factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
+          zone());
     }
 
     if (fni_ != NULL) fni_->Leave();
@@ -2135,6 +2126,7 @@
   // ExpressionStatement | LabelledStatement ::
   //   Expression ';'
   //   Identifier ':' Statement
+  int pos = peek_position();
   bool starts_with_idenfifier = peek_any_identifier();
   Expression* expr = ParseExpression(true, CHECK_OK);
   if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL &&
@@ -2194,7 +2186,7 @@
       scanner().literal_contains_escapes()) {
     ExpectSemicolon(CHECK_OK);
   }
-  return factory()->NewExpressionStatement(expr);
+  return factory()->NewExpressionStatement(expr, pos);
 }
 
 
@@ -2202,6 +2194,7 @@
   // IfStatement ::
   //   'if' '(' Expression ')' Statement ('else' Statement)?
 
+  int pos = peek_position();
   Expect(Token::IF, CHECK_OK);
   Expect(Token::LPAREN, CHECK_OK);
   Expression* condition = ParseExpression(true, CHECK_OK);
@@ -2212,9 +2205,10 @@
     Next();
     else_statement = ParseStatement(labels, CHECK_OK);
   } else {
-    else_statement = factory()->NewEmptyStatement();
+    else_statement = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
   }
-  return factory()->NewIfStatement(condition, then_statement, else_statement);
+  return factory()->NewIfStatement(
+      condition, then_statement, else_statement, pos);
 }
 
 
@@ -2222,6 +2216,7 @@
   // ContinueStatement ::
   //   'continue' Identifier? ';'
 
+  int pos = peek_position();
   Expect(Token::CONTINUE, CHECK_OK);
   Handle<String> label = Handle<String>::null();
   Token::Value tok = peek();
@@ -2244,7 +2239,7 @@
     return NULL;
   }
   ExpectSemicolon(CHECK_OK);
-  return factory()->NewContinueStatement(target);
+  return factory()->NewContinueStatement(target, pos);
 }
 
 
@@ -2252,6 +2247,7 @@
   // BreakStatement ::
   //   'break' Identifier? ';'
 
+  int pos = peek_position();
   Expect(Token::BREAK, CHECK_OK);
   Handle<String> label;
   Token::Value tok = peek();
@@ -2263,7 +2259,7 @@
   // empty statements, e.g. 'l1: l2: l3: break l2;'
   if (!label.is_null() && ContainsLabel(labels, label)) {
     ExpectSemicolon(CHECK_OK);
-    return factory()->NewEmptyStatement();
+    return factory()->NewEmptyStatement(pos);
   }
   BreakableStatement* target = NULL;
   target = LookupBreakTarget(label, CHECK_OK);
@@ -2280,7 +2276,7 @@
     return NULL;
   }
   ExpectSemicolon(CHECK_OK);
-  return factory()->NewBreakStatement(target);
+  return factory()->NewBreakStatement(target, pos);
 }
 
 
@@ -2288,10 +2284,11 @@
   // ReturnStatement ::
   //   'return' Expression? ';'
 
-  // Consume the return token. It is necessary to do the before
+  // Consume the return token. It is necessary to do that before
   // reporting any errors on it, because of the way errors are
   // reported (underlining).
   Expect(Token::RETURN, CHECK_OK);
+  int pos = position();
 
   Token::Value tok = peek();
   Statement* result;
@@ -2300,7 +2297,7 @@
       tok == Token::SEMICOLON ||
       tok == Token::RBRACE ||
       tok == Token::EOS) {
-    return_value = GetLiteralUndefined();
+    return_value = GetLiteralUndefined(position());
   } else {
     return_value = ParseExpression(true, CHECK_OK);
   }
@@ -2309,10 +2306,10 @@
     Expression* generator = factory()->NewVariableProxy(
         current_function_state_->generator_object_variable());
     Expression* yield = factory()->NewYield(
-        generator, return_value, Yield::FINAL, RelocInfo::kNoPosition);
-    result = factory()->NewExpressionStatement(yield);
+        generator, return_value, Yield::FINAL, pos);
+    result = factory()->NewExpressionStatement(yield, pos);
   } else {
-    result = factory()->NewReturnStatement(return_value);
+    result = factory()->NewReturnStatement(return_value, pos);
   }
 
   // An ECMAScript program is considered syntactically incorrect if it
@@ -2326,7 +2323,7 @@
     Handle<String> message = isolate()->factory()->illegal_return_string();
     Expression* throw_error =
         NewThrowSyntaxError(message, Handle<Object>::null());
-    return factory()->NewExpressionStatement(throw_error);
+    return factory()->NewExpressionStatement(throw_error, pos);
   }
   return result;
 }
@@ -2337,6 +2334,7 @@
   //   'with' '(' Expression ')' Statement
 
   Expect(Token::WITH, CHECK_OK);
+  int pos = position();
 
   if (!top_scope_->is_classic_mode()) {
     ReportMessage("strict_mode_with", Vector<const char*>::empty());
@@ -2356,7 +2354,7 @@
     stmt = ParseStatement(labels, CHECK_OK);
     with_scope->set_end_position(scanner().location().end_pos);
   }
-  return factory()->NewWithStatement(with_scope, expr, stmt);
+  return factory()->NewWithStatement(with_scope, expr, stmt, pos);
 }
 
 
@@ -2380,7 +2378,7 @@
     *default_seen_ptr = true;
   }
   Expect(Token::COLON, CHECK_OK);
-  int pos = scanner().location().beg_pos;
+  int pos = position();
   ZoneList<Statement*>* statements =
       new(zone()) ZoneList<Statement*>(5, zone());
   while (peek() != Token::CASE &&
@@ -2390,7 +2388,7 @@
     statements->Add(stat, zone());
   }
 
-  return new(zone()) CaseClause(isolate(), label, statements, pos);
+  return factory()->NewCaseClause(label, statements, pos);
 }
 
 
@@ -2399,7 +2397,8 @@
   // SwitchStatement ::
   //   'switch' '(' Expression ')' '{' CaseClause* '}'
 
-  SwitchStatement* statement = factory()->NewSwitchStatement(labels);
+  SwitchStatement* statement =
+      factory()->NewSwitchStatement(labels, peek_position());
   Target target(&this->target_stack_, statement);
 
   Expect(Token::SWITCH, CHECK_OK);
@@ -2426,7 +2425,7 @@
   //   'throw' Expression ';'
 
   Expect(Token::THROW, CHECK_OK);
-  int pos = scanner().location().beg_pos;
+  int pos = position();
   if (scanner().HasAnyLineTerminatorBeforeNext()) {
     ReportMessage("newline_after_throw", Vector<const char*>::empty());
     *ok = false;
@@ -2435,7 +2434,8 @@
   Expression* exception = ParseExpression(true, CHECK_OK);
   ExpectSemicolon(CHECK_OK);
 
-  return factory()->NewExpressionStatement(factory()->NewThrow(exception, pos));
+  return factory()->NewExpressionStatement(
+      factory()->NewThrow(exception, pos), pos);
 }
 
 
@@ -2452,6 +2452,7 @@
   //   'finally' Block
 
   Expect(Token::TRY, CHECK_OK);
+  int pos = position();
 
   TargetCollector try_collector(zone());
   Block* try_block;
@@ -2523,9 +2524,10 @@
     ASSERT(catch_scope != NULL && catch_variable != NULL);
     int index = current_function_state_->NextHandlerIndex();
     TryCatchStatement* statement = factory()->NewTryCatchStatement(
-        index, try_block, catch_scope, catch_variable, catch_block);
+        index, try_block, catch_scope, catch_variable, catch_block,
+        RelocInfo::kNoPosition);
     statement->set_escaping_targets(try_collector.targets());
-    try_block = factory()->NewBlock(NULL, 1, false);
+    try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
     try_block->AddStatement(statement, zone());
     catch_block = NULL;  // Clear to indicate it's been handled.
   }
@@ -2536,11 +2538,12 @@
     ASSERT(catch_scope != NULL && catch_variable != NULL);
     int index = current_function_state_->NextHandlerIndex();
     result = factory()->NewTryCatchStatement(
-        index, try_block, catch_scope, catch_variable, catch_block);
+        index, try_block, catch_scope, catch_variable, catch_block, pos);
   } else {
     ASSERT(finally_block != NULL);
     int index = current_function_state_->NextHandlerIndex();
-    result = factory()->NewTryFinallyStatement(index, try_block, finally_block);
+    result = factory()->NewTryFinallyStatement(
+        index, try_block, finally_block, pos);
     // Combine the jump targets of the try block and the possible catch block.
     try_collector.targets()->AddAll(*catch_collector.targets(), zone());
   }
@@ -2555,7 +2558,8 @@
   // DoStatement ::
   //   'do' Statement 'while' '(' Expression ')' ';'
 
-  DoWhileStatement* loop = factory()->NewDoWhileStatement(labels);
+  DoWhileStatement* loop =
+      factory()->NewDoWhileStatement(labels, peek_position());
   Target target(&this->target_stack_, loop);
 
   Expect(Token::DO, CHECK_OK);
@@ -2563,11 +2567,6 @@
   Expect(Token::WHILE, CHECK_OK);
   Expect(Token::LPAREN, CHECK_OK);
 
-  if (loop != NULL) {
-    int position = scanner().location().beg_pos;
-    loop->set_condition_position(position);
-  }
-
   Expression* cond = ParseExpression(true, CHECK_OK);
   Expect(Token::RPAREN, CHECK_OK);
 
@@ -2586,7 +2585,7 @@
   // WhileStatement ::
   //   'while' '(' Expression ')' Statement
 
-  WhileStatement* loop = factory()->NewWhileStatement(labels);
+  WhileStatement* loop = factory()->NewWhileStatement(labels, peek_position());
   Target target(&this->target_stack_, loop);
 
   Expect(Token::WHILE, CHECK_OK);
@@ -2645,8 +2644,8 @@
     // var result = iterator.next();
     {
       Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
-      Expression* next_literal =
-          factory()->NewLiteral(heap_factory->next_string());
+      Expression* next_literal = factory()->NewLiteral(
+          heap_factory->next_string(), RelocInfo::kNoPosition);
       Expression* next_property = factory()->NewProperty(
           iterator_proxy, next_literal, RelocInfo::kNoPosition);
       ZoneList<Expression*>* next_arguments =
@@ -2660,8 +2659,8 @@
 
     // result.done
     {
-      Expression* done_literal =
-          factory()->NewLiteral(heap_factory->done_string());
+      Expression* done_literal = factory()->NewLiteral(
+          heap_factory->done_string(), RelocInfo::kNoPosition);
       Expression* result_proxy = factory()->NewVariableProxy(result);
       result_done = factory()->NewProperty(
           result_proxy, done_literal, RelocInfo::kNoPosition);
@@ -2669,8 +2668,8 @@
 
     // each = result.value
     {
-      Expression* value_literal =
-          factory()->NewLiteral(heap_factory->value_string());
+      Expression* value_literal = factory()->NewLiteral(
+          heap_factory->value_string(), RelocInfo::kNoPosition);
       Expression* result_proxy = factory()->NewVariableProxy(result);
       Expression* result_value = factory()->NewProperty(
           result_proxy, value_literal, RelocInfo::kNoPosition);
@@ -2690,6 +2689,7 @@
   // ForStatement ::
   //   'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
 
+  int pos = peek_position();
   Statement* init = NULL;
 
   // Create an in-between scope for let-bound iteration variables.
@@ -2714,7 +2714,8 @@
       if (!name.is_null() && CheckInOrOf(accept_OF, &mode)) {
         Interface* interface =
             is_const ? Interface::NewConst() : Interface::NewValue();
-        ForEachStatement* loop = factory()->NewForEachStatement(mode, labels);
+        ForEachStatement* loop =
+            factory()->NewForEachStatement(mode, labels, pos);
         Target target(&this->target_stack_, loop);
 
         Expression* enumerable = ParseExpression(true, CHECK_OK);
@@ -2724,7 +2725,8 @@
             top_scope_->NewUnresolved(factory(), name, interface);
         Statement* body = ParseStatement(NULL, CHECK_OK);
         InitializeForEachStatement(loop, each, enumerable, body);
-        Block* result = factory()->NewBlock(NULL, 2, false);
+        Block* result =
+            factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
         result->AddStatement(variable_statement, zone());
         result->AddStatement(loop, zone());
         top_scope_ = saved_scope;
@@ -2768,7 +2770,8 @@
         Handle<String> tempname = heap_factory->InternalizeString(tempstr);
         Variable* temp = top_scope_->DeclarationScope()->NewTemporary(tempname);
         VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
-        ForEachStatement* loop = factory()->NewForEachStatement(mode, labels);
+        ForEachStatement* loop =
+            factory()->NewForEachStatement(mode, labels, pos);
         Target target(&this->target_stack_, loop);
 
         // The expression does not see the loop variable.
@@ -2780,11 +2783,12 @@
         VariableProxy* each =
             top_scope_->NewUnresolved(factory(), name, Interface::NewValue());
         Statement* body = ParseStatement(NULL, CHECK_OK);
-        Block* body_block = factory()->NewBlock(NULL, 3, false);
+        Block* body_block =
+            factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
         Assignment* assignment = factory()->NewAssignment(
             Token::ASSIGN, each, temp_proxy, RelocInfo::kNoPosition);
-        Statement* assignment_statement =
-            factory()->NewExpressionStatement(assignment);
+        Statement* assignment_statement = factory()->NewExpressionStatement(
+            assignment, RelocInfo::kNoPosition);
         body_block->AddStatement(variable_statement, zone());
         body_block->AddStatement(assignment_statement, zone());
         body_block->AddStatement(body, zone());
@@ -2814,7 +2818,8 @@
               isolate()->factory()->invalid_lhs_in_for_in_string();
           expression = NewThrowReferenceError(message);
         }
-        ForEachStatement* loop = factory()->NewForEachStatement(mode, labels);
+        ForEachStatement* loop =
+            factory()->NewForEachStatement(mode, labels, pos);
         Target target(&this->target_stack_, loop);
 
         Expression* enumerable = ParseExpression(true, CHECK_OK);
@@ -2830,13 +2835,14 @@
         return loop;
 
       } else {
-        init = factory()->NewExpressionStatement(expression);
+        init = factory()->NewExpressionStatement(
+            expression, RelocInfo::kNoPosition);
       }
     }
   }
 
   // Standard 'for' loop
-  ForStatement* loop = factory()->NewForStatement(labels);
+  ForStatement* loop = factory()->NewForStatement(labels, pos);
   Target target(&this->target_stack_, loop);
 
   // Parsed initializer at this point.
@@ -2851,7 +2857,7 @@
   Statement* next = NULL;
   if (peek() != Token::RPAREN) {
     Expression* exp = ParseExpression(true, CHECK_OK);
-    next = factory()->NewExpressionStatement(exp);
+    next = factory()->NewExpressionStatement(exp, RelocInfo::kNoPosition);
   }
   Expect(Token::RPAREN, CHECK_OK);
 
@@ -2871,7 +2877,7 @@
     //     for (; c; n) b
     //   }
     ASSERT(init != NULL);
-    Block* result = factory()->NewBlock(NULL, 2, false);
+    Block* result = factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
     result->AddStatement(init, zone());
     result->AddStatement(loop, zone());
     result->set_scope(for_scope);
@@ -2893,10 +2899,9 @@
   Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK);
   while (peek() == Token::COMMA) {
     Expect(Token::COMMA, CHECK_OK);
-    int position = scanner().location().beg_pos;
+    int pos = position();
     Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
-    result =
-        factory()->NewBinaryOperation(Token::COMMA, result, right, position);
+    result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos);
   }
   return result;
 }
@@ -2940,7 +2945,7 @@
   MarkAsLValue(expression);
 
   Token::Value op = Next();  // Get assignment operator.
-  int pos = scanner().location().beg_pos;
+  int pos = position();
   Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
 
   // TODO(1231235): We try to estimate the set of properties set by
@@ -2984,15 +2989,14 @@
 Expression* Parser::ParseYieldExpression(bool* ok) {
   // YieldExpression ::
   //   'yield' '*'? AssignmentExpression
-  int position = scanner().peek_location().beg_pos;
+  int pos = peek_position();
   Expect(Token::YIELD, CHECK_OK);
   Yield::Kind kind =
       Check(Token::MUL) ? Yield::DELEGATING : Yield::SUSPEND;
   Expression* generator_object = factory()->NewVariableProxy(
       current_function_state_->generator_object_variable());
   Expression* expression = ParseAssignmentExpression(false, CHECK_OK);
-  Yield* yield =
-      factory()->NewYield(generator_object, expression, kind, position);
+  Yield* yield = factory()->NewYield(generator_object, expression, kind, pos);
   if (kind == Yield::DELEGATING) {
     yield->set_index(current_function_state_->NextHandlerIndex());
   }
@@ -3006,6 +3010,7 @@
   //   LogicalOrExpression
   //   LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
 
+  int pos = peek_position();
   // We start using the binary expression parser for prec >= 4 only!
   Expression* expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
   if (peek() != Token::CONDITIONAL) return expression;
@@ -3013,13 +3018,10 @@
   // In parsing the first assignment expression in conditional
   // expressions we always accept the 'in' keyword; see ECMA-262,
   // section 11.12, page 58.
-  int left_position = scanner().peek_location().beg_pos;
   Expression* left = ParseAssignmentExpression(true, CHECK_OK);
   Expect(Token::COLON, CHECK_OK);
-  int right_position = scanner().peek_location().beg_pos;
   Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
-  return factory()->NewConditional(
-      expression, left, right, left_position, right_position);
+  return factory()->NewConditional(expression, left, right, pos);
 }
 
 
@@ -3039,7 +3041,7 @@
     // prec1 >= 4
     while (Precedence(peek(), accept_IN) == prec1) {
       Token::Value op = Next();
-      int position = scanner().location().beg_pos;
+      int pos = position();
       Expression* y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
 
       // Compute some expressions involving only number literals.
@@ -3050,47 +3052,47 @@
 
         switch (op) {
           case Token::ADD:
-            x = factory()->NewNumberLiteral(x_val + y_val);
+            x = factory()->NewNumberLiteral(x_val + y_val, pos);
             continue;
           case Token::SUB:
-            x = factory()->NewNumberLiteral(x_val - y_val);
+            x = factory()->NewNumberLiteral(x_val - y_val, pos);
             continue;
           case Token::MUL:
-            x = factory()->NewNumberLiteral(x_val * y_val);
+            x = factory()->NewNumberLiteral(x_val * y_val, pos);
             continue;
           case Token::DIV:
-            x = factory()->NewNumberLiteral(x_val / y_val);
+            x = factory()->NewNumberLiteral(x_val / y_val, pos);
             continue;
           case Token::BIT_OR: {
             int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
-            x = factory()->NewNumberLiteral(value);
+            x = factory()->NewNumberLiteral(value, pos);
             continue;
           }
           case Token::BIT_AND: {
             int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
-            x = factory()->NewNumberLiteral(value);
+            x = factory()->NewNumberLiteral(value, pos);
             continue;
           }
           case Token::BIT_XOR: {
             int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
-            x = factory()->NewNumberLiteral(value);
+            x = factory()->NewNumberLiteral(value, pos);
             continue;
           }
           case Token::SHL: {
             int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
-            x = factory()->NewNumberLiteral(value);
+            x = factory()->NewNumberLiteral(value, pos);
             continue;
           }
           case Token::SHR: {
             uint32_t shift = DoubleToInt32(y_val) & 0x1f;
             uint32_t value = DoubleToUint32(x_val) >> shift;
-            x = factory()->NewNumberLiteral(value);
+            x = factory()->NewNumberLiteral(value, pos);
             continue;
           }
           case Token::SAR: {
             uint32_t shift = DoubleToInt32(y_val) & 0x1f;
             int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
-            x = factory()->NewNumberLiteral(value);
+            x = factory()->NewNumberLiteral(value, pos);
             continue;
           }
           default:
@@ -3109,15 +3111,15 @@
           case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
           default: break;
         }
-        x = factory()->NewCompareOperation(cmp, x, y, position);
+        x = factory()->NewCompareOperation(cmp, x, y, pos);
         if (cmp != op) {
           // The comparison was negated - add a NOT.
-          x = factory()->NewUnaryOperation(Token::NOT, x, position);
+          x = factory()->NewUnaryOperation(Token::NOT, x, pos);
         }
 
       } else {
         // We have a "normal" binary operation.
-        x = factory()->NewBinaryOperation(op, x, y, position);
+        x = factory()->NewBinaryOperation(op, x, y, pos);
       }
     }
   }
@@ -3141,7 +3143,7 @@
   Token::Value op = peek();
   if (Token::IsUnaryOp(op)) {
     op = Next();
-    int position = scanner().location().beg_pos;
+    int pos = position();
     Expression* expression = ParseUnaryExpression(CHECK_OK);
 
     if (expression != NULL && (expression->AsLiteral() != NULL)) {
@@ -3150,7 +3152,7 @@
         // Convert the literal to a boolean condition and negate it.
         bool condition = literal->BooleanValue();
         Handle<Object> result = isolate()->factory()->ToBoolean(!condition);
-        return factory()->NewLiteral(result);
+        return factory()->NewLiteral(result, pos);
       } else if (literal->IsNumber()) {
         // Compute some expressions involving only number literals.
         double value = literal->Number();
@@ -3158,9 +3160,9 @@
           case Token::ADD:
             return expression;
           case Token::SUB:
-            return factory()->NewNumberLiteral(-value);
+            return factory()->NewNumberLiteral(-value, pos);
           case Token::BIT_NOT:
-            return factory()->NewNumberLiteral(~DoubleToInt32(value));
+            return factory()->NewNumberLiteral(~DoubleToInt32(value), pos);
           default:
             break;
         }
@@ -3183,25 +3185,25 @@
     if (op == Token::ADD) {
       return factory()->NewBinaryOperation(Token::MUL,
                                            expression,
-                                           factory()->NewNumberLiteral(1),
-                                           position);
+                                           factory()->NewNumberLiteral(1, pos),
+                                           pos);
     }
     // The same idea for '-foo' => 'foo*(-1)'.
     if (op == Token::SUB) {
       return factory()->NewBinaryOperation(Token::MUL,
                                            expression,
-                                           factory()->NewNumberLiteral(-1),
-                                           position);
+                                           factory()->NewNumberLiteral(-1, pos),
+                                           pos);
     }
     // ...and one more time for '~foo' => 'foo^(~0)'.
     if (op == Token::BIT_NOT) {
       return factory()->NewBinaryOperation(Token::BIT_XOR,
                                            expression,
-                                           factory()->NewNumberLiteral(~0),
-                                           position);
+                                           factory()->NewNumberLiteral(~0, pos),
+                                           pos);
     }
 
-    return factory()->NewUnaryOperation(op, expression, position);
+    return factory()->NewUnaryOperation(op, expression, pos);
 
   } else if (Token::IsCountOp(op)) {
     op = Next();
@@ -3222,11 +3224,10 @@
     }
     MarkAsLValue(expression);
 
-    int position = scanner().location().beg_pos;
     return factory()->NewCountOperation(op,
                                         true /* prefix */,
                                         expression,
-                                        position);
+                                        position());
 
   } else {
     return ParsePostfixExpression(ok);
@@ -3258,12 +3259,11 @@
     MarkAsLValue(expression);
 
     Token::Value next = Next();
-    int position = scanner().location().beg_pos;
     expression =
         factory()->NewCountOperation(next,
                                      false /* postfix */,
                                      expression,
-                                     position);
+                                     position());
   }
   return expression;
 }
@@ -3284,7 +3284,7 @@
     switch (peek()) {
       case Token::LBRACK: {
         Consume(Token::LBRACK);
-        int pos = scanner().location().beg_pos;
+        int pos = position();
         Expression* index = ParseExpression(true, CHECK_OK);
         result = factory()->NewProperty(result, index, pos);
         Expect(Token::RBRACK, CHECK_OK);
@@ -3296,14 +3296,14 @@
         if (scanner().current_token() == Token::IDENTIFIER) {
           // For call of an identifier we want to report position of
           // the identifier as position of the call in the stack trace.
-          pos = scanner().location().beg_pos;
+          pos = position();
         } else {
           // For other kinds of calls we record position of the parenthesis as
           // position of the call.  Note that this is extremely important for
           // expressions of the form function(){...}() for which call position
           // should not point to the closing brace otherwise it will intersect
           // with positions recorded for function literal and confuse debugger.
-          pos = scanner().peek_location().beg_pos;
+          pos = peek_position();
           // Also the trailing parenthesis are a hint that the function will
           // be called immediately. If we happen to have parsed a preceding
           // function literal eagerly, we can also compile it eagerly.
@@ -3332,10 +3332,10 @@
 
       case Token::PERIOD: {
         Consume(Token::PERIOD);
-        int pos = scanner().location().beg_pos;
+        int pos = position();
         Handle<String> name = ParseIdentifierName(CHECK_OK);
-        result =
-            factory()->NewProperty(result, factory()->NewLiteral(name), pos);
+        result = factory()->NewProperty(
+            result, factory()->NewLiteral(name, pos), pos);
         if (fni_ != NULL) fni_->PushLiteralName(name);
         break;
       }
@@ -3360,7 +3360,7 @@
   // member expression parser, which is only allowed to match argument
   // lists as long as it has 'new' prefixes left
   Expect(Token::NEW, CHECK_OK);
-  PositionStack::Element pos(stack, scanner().location().beg_pos);
+  PositionStack::Element pos(stack, position());
 
   Expression* result;
   if (peek() == Token::NEW) {
@@ -3399,7 +3399,7 @@
   Expression* result = NULL;
   if (peek() == Token::FUNCTION) {
     Expect(Token::FUNCTION, CHECK_OK);
-    int function_token_position = scanner().location().beg_pos;
+    int function_token_position = position();
     bool is_generator = allow_generators() && Check(Token::MUL);
     Handle<String> name;
     bool is_strict_reserved_name = false;
@@ -3424,7 +3424,7 @@
     switch (peek()) {
       case Token::LBRACK: {
         Consume(Token::LBRACK);
-        int pos = scanner().location().beg_pos;
+        int pos = position();
         Expression* index = ParseExpression(true, CHECK_OK);
         result = factory()->NewProperty(result, index, pos);
         if (fni_ != NULL) {
@@ -3440,10 +3440,10 @@
       }
       case Token::PERIOD: {
         Consume(Token::PERIOD);
-        int pos = scanner().location().beg_pos;
+        int pos = position();
         Handle<String> name = ParseIdentifierName(CHECK_OK);
-        result =
-            factory()->NewProperty(result, factory()->NewLiteral(name), pos);
+        result = factory()->NewProperty(
+            result, factory()->NewLiteral(name, pos), pos);
         if (fni_ != NULL) fni_->PushLiteralName(name);
         break;
       }
@@ -3451,8 +3451,8 @@
         if ((stack == NULL) || stack->is_empty()) return result;
         // Consume one of the new prefixes (already parsed).
         ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
-        int last = stack->pop();
-        result = factory()->NewCallNew(result, args, last);
+        int pos = stack->pop();
+        result = factory()->NewCallNew(result, args, pos);
         break;
       }
       default:
@@ -3469,9 +3469,10 @@
   // DebuggerStatement ::
   //   'debugger' ';'
 
+  int pos = peek_position();
   Expect(Token::DEBUGGER, CHECK_OK);
   ExpectSemicolon(CHECK_OK);
-  return factory()->NewDebuggerStatement();
+  return factory()->NewDebuggerStatement(pos);
 }
 
 
@@ -3479,7 +3480,7 @@
   // We don't report stack overflows here, to avoid increasing the
   // stack depth even further.  Instead we report it after parsing is
   // over, in ParseProgram/ParseJson.
-  if (token == Token::ILLEGAL && stack_overflow_) return;
+  if (token == Token::ILLEGAL && stack_overflow()) return;
   // Four of the tokens are treated specially
   switch (token) {
     case Token::EOS:
@@ -3533,6 +3534,7 @@
   //   RegExpLiteral
   //   '(' Expression ')'
 
+  int pos = peek_position();
   Expression* result = NULL;
   switch (peek()) {
     case Token::THIS: {
@@ -3543,17 +3545,17 @@
 
     case Token::NULL_LITERAL:
       Consume(Token::NULL_LITERAL);
-      result = factory()->NewLiteral(isolate()->factory()->null_value());
+      result = factory()->NewLiteral(isolate()->factory()->null_value(), pos);
       break;
 
     case Token::TRUE_LITERAL:
       Consume(Token::TRUE_LITERAL);
-      result = factory()->NewLiteral(isolate()->factory()->true_value());
+      result = factory()->NewLiteral(isolate()->factory()->true_value(), pos);
       break;
 
     case Token::FALSE_LITERAL:
       Consume(Token::FALSE_LITERAL);
-      result = factory()->NewLiteral(isolate()->factory()->false_value());
+      result = factory()->NewLiteral(isolate()->factory()->false_value(), pos);
       break;
 
     case Token::IDENTIFIER:
@@ -3567,8 +3569,7 @@
         PrintF("# Variable %s ", name->ToAsciiArray());
 #endif
       Interface* interface = Interface::NewUnknown(zone());
-      result = top_scope_->NewUnresolved(
-          factory(), name, interface, scanner().location().beg_pos);
+      result = top_scope_->NewUnresolved(factory(), name, interface, pos);
       break;
     }
 
@@ -3579,14 +3580,14 @@
                                     scanner().literal_ascii_string(),
                                     ALLOW_HEX | ALLOW_OCTAL |
                                         ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
-      result = factory()->NewNumberLiteral(value);
+      result = factory()->NewNumberLiteral(value, pos);
       break;
     }
 
     case Token::STRING: {
       Consume(Token::STRING);
       Handle<String> symbol = GetSymbol();
-      result = factory()->NewLiteral(symbol);
+      result = factory()->NewLiteral(symbol, pos);
       if (fni_ != NULL) fni_->PushLiteralName(symbol);
       break;
     }
@@ -3640,12 +3641,13 @@
   // ArrayLiteral ::
   //   '[' Expression? (',' Expression?)* ']'
 
+  int pos = peek_position();
   ZoneList<Expression*>* values = new(zone()) ZoneList<Expression*>(4, zone());
   Expect(Token::LBRACK, CHECK_OK);
   while (peek() != Token::RBRACK) {
     Expression* elem;
     if (peek() == Token::COMMA) {
-      elem = GetLiteralTheHole();
+      elem = GetLiteralTheHole(peek_position());
     } else {
       elem = ParseAssignmentExpression(true, CHECK_OK);
     }
@@ -3707,7 +3709,7 @@
   literals->set(1, *element_values);
 
   return factory()->NewArrayLiteral(
-      literals, values, literal_index, is_simple, depth);
+      literals, values, literal_index, is_simple, depth, pos);
 }
 
 
@@ -3855,6 +3857,7 @@
   //     | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
   //    )*[','] '}'
 
+  int pos = peek_position();
   ZoneList<ObjectLiteral::Property*>* properties =
       new(zone()) ZoneList<ObjectLiteral::Property*>(4, zone());
   int number_of_boilerplate_properties = 0;
@@ -3870,6 +3873,7 @@
 
     Literal* key = NULL;
     Token::Value next = peek();
+    int next_pos = peek_position();
 
     switch (next) {
       case Token::FUTURE_RESERVED_WORD:
@@ -3914,7 +3918,7 @@
           // Allow any number of parameters for compatibilty with JSC.
           // Specification only allows zero parameters for get and one for set.
           ObjectLiteral::Property* property =
-              factory()->NewObjectLiteralProperty(is_getter, value);
+              factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
           if (IsBoilerplateProperty(property)) {
             number_of_boilerplate_properties++;
           }
@@ -3929,7 +3933,7 @@
         }
         // Failed to parse as get/set property, so it's just a property
         // called "get" or "set".
-        key = factory()->NewLiteral(id);
+        key = factory()->NewLiteral(id, next_pos);
         break;
       }
       case Token::STRING: {
@@ -3938,10 +3942,10 @@
         if (fni_ != NULL) fni_->PushLiteralName(string);
         uint32_t index;
         if (!string.is_null() && string->AsArrayIndex(&index)) {
-          key = factory()->NewNumberLiteral(index);
+          key = factory()->NewNumberLiteral(index, next_pos);
           break;
         }
-        key = factory()->NewLiteral(string);
+        key = factory()->NewLiteral(string, next_pos);
         break;
       }
       case Token::NUMBER: {
@@ -3951,14 +3955,14 @@
                                       scanner().literal_ascii_string(),
                                       ALLOW_HEX | ALLOW_OCTAL |
                                           ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
-        key = factory()->NewNumberLiteral(value);
+        key = factory()->NewNumberLiteral(value, next_pos);
         break;
       }
       default:
         if (Token::IsKeyword(next)) {
           Consume(next);
           Handle<String> string = GetSymbol();
-          key = factory()->NewLiteral(string);
+          key = factory()->NewLiteral(string, next_pos);
         } else {
           // Unexpected token.
           Token::Value next = Next();
@@ -4023,11 +4027,13 @@
                                      fast_elements,
                                      depth,
                                      may_store_doubles,
-                                     has_function);
+                                     has_function,
+                                     pos);
 }
 
 
 Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
+  int pos = peek_position();
   if (!scanner().ScanRegExpPattern(seen_equal)) {
     Next();
     ReportMessage("unterminated_regexp", Vector<const char*>::empty());
@@ -4042,7 +4048,7 @@
   Handle<String> js_flags = NextLiteralString(TENURED);
   Next();
 
-  return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index);
+  return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
 }
 
 
@@ -4167,12 +4173,15 @@
     Handle<String> function_name,
     bool name_is_strict_reserved,
     bool is_generator,
-    int function_token_position,
+    int function_token_pos,
     FunctionLiteral::FunctionType function_type,
     bool* ok) {
   // Function ::
   //   '(' FormalParameterList? ')' '{' FunctionBody '}'
 
+  int pos = function_token_pos == RelocInfo::kNoPosition
+      ? peek_position() : function_token_pos;
+
   // Anonymous functions were passed either the empty symbol or a null
   // handle as the function name.  Remember if we were passed a non-empty
   // handle to decide whether to invoke function name inference.
@@ -4310,8 +4319,8 @@
          function_name, fvar_mode, true /* is valid LHS */,
          Variable::NORMAL, kCreatedInitialized, Interface::NewConst());
       VariableProxy* proxy = factory()->NewVariableProxy(fvar);
-      VariableDeclaration* fvar_declaration =
-          factory()->NewVariableDeclaration(proxy, fvar_mode, top_scope_);
+      VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
+          proxy, fvar_mode, top_scope_, RelocInfo::kNoPosition);
       top_scope_->DeclareFunctionVar(fvar_declaration);
     }
 
@@ -4332,7 +4341,7 @@
     parenthesized_function_ = false;  // The bit was set for this function only.
 
     if (is_lazily_compiled) {
-      int function_block_pos = scanner().location().beg_pos;
+      int function_block_pos = position();
       FunctionEntry entry;
       if (pre_parse_data_ != NULL) {
         // If we have pre_parse_data_, we use it to skip parsing the function
@@ -4362,11 +4371,10 @@
         // building an AST. This gathers the data needed to build a lazy
         // function.
         SingletonLogger logger;
-        preparser::PreParser::PreParseResult result =
-            LazyParseFunctionLiteral(&logger);
-        if (result == preparser::PreParser::kPreParseStackOverflow) {
+        PreParser::PreParseResult result = LazyParseFunctionLiteral(&logger);
+        if (result == PreParser::kPreParseStackOverflow) {
           // Propagate stack overflow.
-          stack_overflow_ = true;
+          set_stack_overflow();
           *ok = false;
           return NULL;
         }
@@ -4401,9 +4409,9 @@
         body->Add(factory()->NewExpressionStatement(
             factory()->NewAssignment(fvar_init_op,
                                      fproxy,
-                                     factory()->NewThisFunction(),
-                                     RelocInfo::kNoPosition)),
-                                     zone());
+                                     factory()->NewThisFunction(pos),
+                                     RelocInfo::kNoPosition),
+            RelocInfo::kNoPosition), zone());
       }
 
       // For generators, allocate and yield an iterator on function entry.
@@ -4413,7 +4421,7 @@
         CallRuntime* allocation = factory()->NewCallRuntime(
             isolate()->factory()->empty_string(),
             Runtime::FunctionForId(Runtime::kCreateJSGeneratorObject),
-            arguments);
+            arguments, pos);
         VariableProxy* init_proxy = factory()->NewVariableProxy(
             current_function_state_->generator_object_variable());
         Assignment* assignment = factory()->NewAssignment(
@@ -4422,7 +4430,8 @@
             current_function_state_->generator_object_variable());
         Yield* yield = factory()->NewYield(
             get_proxy, assignment, Yield::INITIAL, RelocInfo::kNoPosition);
-        body->Add(factory()->NewExpressionStatement(yield), zone());
+        body->Add(factory()->NewExpressionStatement(
+            yield, RelocInfo::kNoPosition), zone());
       }
 
       ParseSourceElements(body, Token::RBRACE, false, false, CHECK_OK);
@@ -4431,10 +4440,11 @@
         VariableProxy* get_proxy = factory()->NewVariableProxy(
             current_function_state_->generator_object_variable());
         Expression *undefined = factory()->NewLiteral(
-            isolate()->factory()->undefined_value());
+            isolate()->factory()->undefined_value(), RelocInfo::kNoPosition);
         Yield* yield = factory()->NewYield(
             get_proxy, undefined, Yield::FINAL, RelocInfo::kNoPosition);
-        body->Add(factory()->NewExpressionStatement(yield), zone());
+        body->Add(factory()->NewExpressionStatement(
+            yield, RelocInfo::kNoPosition), zone());
       }
 
       materialized_literal_count = function_state.materialized_literal_count();
@@ -4449,9 +4459,8 @@
     if (!top_scope_->is_classic_mode()) {
       if (IsEvalOrArguments(function_name)) {
         int start_pos = scope->start_position();
-        int position = function_token_position != RelocInfo::kNoPosition
-            ? function_token_position
-            : (start_pos > 0 ? start_pos - 1 : start_pos);
+        int position = function_token_pos != RelocInfo::kNoPosition
+            ? function_token_pos : (start_pos > 0 ? start_pos - 1 : start_pos);
         Scanner::Location location = Scanner::Location(position, start_pos);
         ReportMessageAt(location,
                         "strict_function_name", Vector<const char*>::empty());
@@ -4472,9 +4481,8 @@
       }
       if (name_is_strict_reserved) {
         int start_pos = scope->start_position();
-        int position = function_token_position != RelocInfo::kNoPosition
-            ? function_token_position
-            : (start_pos > 0 ? start_pos - 1 : start_pos);
+        int position = function_token_pos != RelocInfo::kNoPosition
+            ? function_token_pos : (start_pos > 0 ? start_pos - 1 : start_pos);
         Scanner::Location location = Scanner::Location(position, start_pos);
         ReportMessageAt(location, "strict_reserved_word",
                         Vector<const char*>::empty());
@@ -4511,8 +4519,9 @@
                                     function_type,
                                     FunctionLiteral::kIsFunction,
                                     parenthesized,
-                                    generator);
-  function_literal->set_function_token_position(function_token_position);
+                                    generator,
+                                    pos);
+  function_literal->set_function_token_position(function_token_pos);
   function_literal->set_ast_properties(&ast_properties);
   function_literal->set_dont_optimize_reason(dont_optimize_reason);
 
@@ -4521,16 +4530,14 @@
 }
 
 
-preparser::PreParser::PreParseResult Parser::LazyParseFunctionLiteral(
+PreParser::PreParseResult Parser::LazyParseFunctionLiteral(
     SingletonLogger* logger) {
   HistogramTimerScope preparse_scope(isolate()->counters()->pre_parse());
   ASSERT_EQ(Token::LBRACE, scanner().current_token());
 
   if (reusable_preparser_ == NULL) {
     intptr_t stack_limit = isolate()->stack_guard()->real_climit();
-    reusable_preparser_ = new preparser::PreParser(&scanner_,
-                                                   NULL,
-                                                   stack_limit);
+    reusable_preparser_ = new PreParser(&scanner_, NULL, stack_limit);
     reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping());
     reusable_preparser_->set_allow_modules(allow_modules());
     reusable_preparser_->set_allow_natives_syntax(allow_natives_syntax());
@@ -4540,7 +4547,7 @@
     reusable_preparser_->set_allow_harmony_numeric_literals(
         allow_harmony_numeric_literals());
   }
-  preparser::PreParser::PreParseResult result =
+  PreParser::PreParseResult result =
       reusable_preparser_->PreParseLazyFunction(top_scope_->language_mode(),
                                                 is_generator(),
                                                 logger);
@@ -4552,6 +4559,7 @@
   // CallRuntime ::
   //   '%' Identifier Arguments
 
+  int pos = peek_position();
   Expect(Token::MOD, CHECK_OK);
   Handle<String> name = ParseIdentifier(CHECK_OK);
   ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
@@ -4597,11 +4605,11 @@
   }
 
   // We have a valid intrinsics call or a call to a builtin.
-  return factory()->NewCallRuntime(name, function, args);
+  return factory()->NewCallRuntime(name, function, args, pos);
 }
 
 
-bool Parser::peek_any_identifier() {
+bool ParserBase::peek_any_identifier() {
   Token::Value next = peek();
   return next == Token::IDENTIFIER ||
          next == Token::FUTURE_RESERVED_WORD ||
@@ -4610,32 +4618,6 @@
 }
 
 
-void Parser::Consume(Token::Value token) {
-  Token::Value next = Next();
-  USE(next);
-  USE(token);
-  ASSERT(next == token);
-}
-
-
-void Parser::Expect(Token::Value token, bool* ok) {
-  Token::Value next = Next();
-  if (next == token) return;
-  ReportUnexpectedToken(next);
-  *ok = false;
-}
-
-
-bool Parser::Check(Token::Value token) {
-  Token::Value next = peek();
-  if (next == token) {
-    Consume(next);
-    return true;
-  }
-  return false;
-}
-
-
 bool Parser::CheckContextualKeyword(Vector<const char> keyword) {
   if (peek() == Token::IDENTIFIER &&
       scanner().is_next_contextual_keyword(keyword)) {
@@ -4646,7 +4628,7 @@
 }
 
 
-void Parser::ExpectSemicolon(bool* ok) {
+void ParserBase::ExpectSemicolon(bool* ok) {
   // Check for automatic semicolon insertion according to
   // the rules given in ECMA-262, section 7.9, page 21.
   Token::Value tok = peek();
@@ -4654,7 +4636,7 @@
     Next();
     return;
   }
-  if (scanner().HasAnyLineTerminatorBeforeNext() ||
+  if (scanner()->HasAnyLineTerminatorBeforeNext() ||
       tok == Token::RBRACE ||
       tok == Token::EOS) {
     return;
@@ -4673,13 +4655,15 @@
 }
 
 
-Literal* Parser::GetLiteralUndefined() {
-  return factory()->NewLiteral(isolate()->factory()->undefined_value());
+Literal* Parser::GetLiteralUndefined(int position) {
+  return factory()->NewLiteral(
+      isolate()->factory()->undefined_value(), position);
 }
 
 
-Literal* Parser::GetLiteralTheHole() {
-  return factory()->NewLiteral(isolate()->factory()->the_hole_value());
+Literal* Parser::GetLiteralTheHole(int position) {
+  return factory()->NewLiteral(
+      isolate()->factory()->the_hole_value(), RelocInfo::kNoPosition);
 }
 
 
@@ -4908,12 +4892,13 @@
   Handle<JSArray> array = isolate()->factory()->NewJSArrayWithElements(
       elements, FAST_ELEMENTS, TENURED);
 
+  int pos = position();
   ZoneList<Expression*>* args = new(zone()) ZoneList<Expression*>(2, zone());
-  args->Add(factory()->NewLiteral(message), zone());
-  args->Add(factory()->NewLiteral(array), zone());
+  args->Add(factory()->NewLiteral(message, pos), zone());
+  args->Add(factory()->NewLiteral(array, pos), zone());
   CallRuntime* call_constructor =
-      factory()->NewCallRuntime(constructor, NULL, args);
-  return factory()->NewThrow(call_constructor, scanner().location().beg_pos);
+      factory()->NewCallRuntime(constructor, NULL, args, pos);
+  return factory()->NewThrow(call_constructor, pos);
 }
 
 
@@ -5803,15 +5788,15 @@
   HistogramTimerScope timer(isolate->counters()->pre_parse());
   Scanner scanner(isolate->unicode_cache());
   intptr_t stack_limit = isolate->stack_guard()->real_climit();
-  preparser::PreParser preparser(&scanner, &recorder, stack_limit);
+  PreParser preparser(&scanner, &recorder, stack_limit);
   preparser.set_allow_lazy(true);
   preparser.set_allow_generators(FLAG_harmony_generators);
   preparser.set_allow_for_of(FLAG_harmony_iteration);
   preparser.set_allow_harmony_scoping(FLAG_harmony_scoping);
   preparser.set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
   scanner.Initialize(source);
-  preparser::PreParser::PreParseResult result = preparser.PreParseProgram();
-  if (result == preparser::PreParser::kPreParseStackOverflow) {
+  PreParser::PreParseResult result = preparser.PreParseProgram();
+  if (result == PreParser::kPreParseStackOverflow) {
     isolate->StackOverflow();
     return NULL;
   }
diff --git a/src/parser.h b/src/parser.h
index e5853bd..6c65ec3 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -425,7 +425,7 @@
 // Forward declaration.
 class SingletonLogger;
 
-class Parser BASE_EMBEDDED {
+class Parser : public ParserBase {
  public:
   explicit Parser(CompilationInfo* info);
   ~Parser() {
@@ -433,28 +433,6 @@
     reusable_preparser_ = NULL;
   }
 
-  bool allow_natives_syntax() const { return allow_natives_syntax_; }
-  bool allow_lazy() const { return allow_lazy_; }
-  bool allow_modules() { return scanner().HarmonyModules(); }
-  bool allow_harmony_scoping() { return scanner().HarmonyScoping(); }
-  bool allow_generators() const { return allow_generators_; }
-  bool allow_for_of() const { return allow_for_of_; }
-  bool allow_harmony_numeric_literals() {
-    return scanner().HarmonyNumericLiterals();
-  }
-
-  void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; }
-  void set_allow_lazy(bool allow) { allow_lazy_ = allow; }
-  void set_allow_modules(bool allow) { scanner().SetHarmonyModules(allow); }
-  void set_allow_harmony_scoping(bool allow) {
-    scanner().SetHarmonyScoping(allow);
-  }
-  void set_allow_generators(bool allow) { allow_generators_ = allow; }
-  void set_allow_for_of(bool allow) { allow_for_of_ = allow; }
-  void set_allow_harmony_numeric_literals(bool allow) {
-    scanner().SetHarmonyNumericLiterals(allow);
-  }
-
   // Parses the source code represented by the compilation info and sets its
   // function literal.  Returns false (and deallocates any allocated AST
   // nodes) if parsing failed.
@@ -592,6 +570,8 @@
 
   bool inside_with() const { return top_scope_->inside_with(); }
   Scanner& scanner()  { return scanner_; }
+  int position() { return scanner_.location().beg_pos; }
+  int peek_position() { return scanner_.peek_location().beg_pos; }
   Mode mode() const { return mode_; }
   ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
   bool is_extended_mode() {
@@ -710,37 +690,10 @@
   // Magical syntax support.
   Expression* ParseV8Intrinsic(bool* ok);
 
-  INLINE(Token::Value peek()) {
-    if (stack_overflow_) return Token::ILLEGAL;
-    return scanner().peek();
-  }
-
-  INLINE(Token::Value Next()) {
-    // BUG 1215673: Find a thread safe way to set a stack limit in
-    // pre-parse mode. Otherwise, we cannot safely pre-parse from other
-    // threads.
-    if (stack_overflow_) {
-      return Token::ILLEGAL;
-    }
-    if (StackLimitCheck(isolate()).HasOverflowed()) {
-      // Any further calls to Next or peek will return the illegal token.
-      // The current call must return the next token, which might already
-      // have been peek'ed.
-      stack_overflow_ = true;
-    }
-    return scanner().Next();
-  }
-
   bool is_generator() const { return current_function_state_->is_generator(); }
 
   bool CheckInOrOf(bool accept_OF, ForEachStatement::VisitMode* visit_mode);
 
-  bool peek_any_identifier();
-
-  INLINE(void Consume(Token::Value token));
-  void Expect(Token::Value token, bool* ok);
-  bool Check(Token::Value token);
-  void ExpectSemicolon(bool* ok);
   bool CheckContextualKeyword(Vector<const char> keyword);
   void ExpectContextualKeyword(Vector<const char> keyword, bool* ok);
 
@@ -767,8 +720,8 @@
   Handle<String> GetSymbol();
 
   // Get odd-ball literals.
-  Literal* GetLiteralUndefined();
-  Literal* GetLiteralTheHole();
+  Literal* GetLiteralUndefined(int position);
+  Literal* GetLiteralTheHole(int position);
 
   Handle<String> ParseIdentifier(bool* ok);
   Handle<String> ParseIdentifierOrStrictReservedWord(
@@ -841,7 +794,7 @@
                             Handle<String> type,
                             Vector< Handle<Object> > arguments);
 
-  preparser::PreParser::PreParseResult LazyParseFunctionLiteral(
+  PreParser::PreParseResult LazyParseFunctionLiteral(
        SingletonLogger* logger);
 
   AstNodeFactory<AstConstructionVisitor>* factory() {
@@ -853,7 +806,7 @@
 
   Handle<Script> script_;
   Scanner scanner_;
-  preparser::PreParser* reusable_preparser_;
+  PreParser* reusable_preparser_;
   Scope* top_scope_;
   Scope* original_scope_;  // for ES5 function declarations in sloppy eval
   FunctionState* current_function_state_;
@@ -863,11 +816,6 @@
   FuncNameInferrer* fni_;
 
   Mode mode_;
-  bool allow_natives_syntax_;
-  bool allow_lazy_;
-  bool allow_generators_;
-  bool allow_for_of_;
-  bool stack_overflow_;
   // If true, the next (and immediately following) function literal is
   // preceded by a parenthesis.
   // Heuristically that means that the function will be called immediately,
diff --git a/src/preparser.cc b/src/preparser.cc
index 11f5595..2d670ac 100644
--- a/src/preparser.cc
+++ b/src/preparser.cc
@@ -53,8 +53,7 @@
 #endif
 
 namespace v8 {
-
-namespace preparser {
+namespace internal {
 
 PreParser::PreParseResult PreParser::PreParseLazyFunction(
     i::LanguageMode mode, bool is_generator, i::ParserRecorder* log) {
@@ -64,17 +63,17 @@
   set_language_mode(mode);
   Scope function_scope(&scope_, kFunctionScope);
   function_scope.set_is_generator(is_generator);
-  ASSERT_EQ(i::Token::LBRACE, scanner_->current_token());
+  ASSERT_EQ(i::Token::LBRACE, scanner()->current_token());
   bool ok = true;
-  int start_position = scanner_->peek_location().beg_pos;
+  int start_position = scanner()->peek_location().beg_pos;
   ParseLazyFunctionLiteralBody(&ok);
-  if (stack_overflow_) return kPreParseStackOverflow;
+  if (stack_overflow()) return kPreParseStackOverflow;
   if (!ok) {
-    ReportUnexpectedToken(scanner_->current_token());
+    ReportUnexpectedToken(scanner()->current_token());
   } else {
-    ASSERT_EQ(i::Token::RBRACE, scanner_->peek());
+    ASSERT_EQ(i::Token::RBRACE, scanner()->peek());
     if (!is_classic_mode()) {
-      int end_pos = scanner_->location().end_pos;
+      int end_pos = scanner()->location().end_pos;
       CheckOctalLiteral(start_position, end_pos, &ok);
       if (ok) {
         CheckDelayedStrictModeViolation(start_position, end_pos, &ok);
@@ -102,10 +101,10 @@
   // We don't report stack overflows here, to avoid increasing the
   // stack depth even further.  Instead we report it after parsing is
   // over, in ParseProgram.
-  if (token == i::Token::ILLEGAL && stack_overflow_) {
+  if (token == i::Token::ILLEGAL && stack_overflow()) {
     return;
   }
-  i::Scanner::Location source_location = scanner_->location();
+  i::Scanner::Location source_location = scanner()->location();
 
   // Four of the tokens are treated specially
   switch (token) {
@@ -133,10 +132,10 @@
 // Checks whether octal literal last seen is between beg_pos and end_pos.
 // If so, reports an error.
 void PreParser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
-  i::Scanner::Location octal = scanner_->octal_position();
+  i::Scanner::Location octal = scanner()->octal_position();
   if (beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) {
     ReportMessageAt(octal, "strict_octal_literal", NULL);
-    scanner_->clear_octal_position();
+    scanner()->clear_octal_position();
     *ok = false;
   }
 }
@@ -275,9 +274,9 @@
       return ParseTryStatement(ok);
 
     case i::Token::FUNCTION: {
-      i::Scanner::Location start_location = scanner_->peek_location();
+      i::Scanner::Location start_location = scanner()->peek_location();
       Statement statement = ParseFunctionDeclaration(CHECK_OK);
-      i::Scanner::Location end_location = scanner_->location();
+      i::Scanner::Location end_location = scanner()->location();
       if (!is_classic_mode()) {
         ReportMessageAt(start_location.beg_pos, end_location.end_pos,
                         "strict_function", NULL);
@@ -305,9 +304,9 @@
   //      '{' FunctionBody '}'
   Expect(i::Token::FUNCTION, CHECK_OK);
 
-  bool is_generator = allow_generators_ && Check(i::Token::MUL);
+  bool is_generator = allow_generators() && Check(i::Token::MUL);
   Identifier identifier = ParseIdentifier(CHECK_OK);
-  i::Scanner::Location location = scanner_->location();
+  i::Scanner::Location location = scanner()->location();
 
   Expression function_value = ParseFunctionLiteral(is_generator, CHECK_OK);
 
@@ -403,7 +402,7 @@
       case i::CLASSIC_MODE:
         break;
       case i::STRICT_MODE: {
-        i::Scanner::Location location = scanner_->peek_location();
+        i::Scanner::Location location = scanner()->peek_location();
         ReportMessageAt(location, "strict_const", NULL);
         *ok = false;
         return Statement::Default();
@@ -411,7 +410,7 @@
       case i::EXTENDED_MODE:
         if (var_context != kSourceElement &&
             var_context != kForStatement) {
-          i::Scanner::Location location = scanner_->peek_location();
+          i::Scanner::Location location = scanner()->peek_location();
           ReportMessageAt(location.beg_pos, location.end_pos,
                           "unprotected_const", NULL);
           *ok = false;
@@ -428,7 +427,7 @@
     // * It is a Syntax Error if the code that matches this production is not
     //   contained in extended code.
     if (!is_extended_mode()) {
-      i::Scanner::Location location = scanner_->peek_location();
+      i::Scanner::Location location = scanner()->peek_location();
       ReportMessageAt(location.beg_pos, location.end_pos,
                       "illegal_let", NULL);
       *ok = false;
@@ -437,7 +436,7 @@
     Consume(i::Token::LET);
     if (var_context != kSourceElement &&
         var_context != kForStatement) {
-      i::Scanner::Location location = scanner_->peek_location();
+      i::Scanner::Location location = scanner()->peek_location();
       ReportMessageAt(location.beg_pos, location.end_pos,
                       "unprotected_let", NULL);
       *ok = false;
@@ -458,7 +457,7 @@
     if (nvars > 0) Consume(i::Token::COMMA);
     Identifier identifier  = ParseIdentifier(CHECK_OK);
     if (!is_classic_mode() && !identifier.IsValidStrictVariable()) {
-      StrictModeIdentifierViolation(scanner_->location(),
+      StrictModeIdentifierViolation(scanner()->location(),
                                     "strict_var_name",
                                     identifier,
                                     ok);
@@ -525,7 +524,7 @@
 
   Expect(i::Token::CONTINUE, CHECK_OK);
   i::Token::Value tok = peek();
-  if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
+  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
       tok != i::Token::SEMICOLON &&
       tok != i::Token::RBRACE &&
       tok != i::Token::EOS) {
@@ -542,7 +541,7 @@
 
   Expect(i::Token::BREAK, CHECK_OK);
   i::Token::Value tok = peek();
-  if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
+  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
       tok != i::Token::SEMICOLON &&
       tok != i::Token::RBRACE &&
       tok != i::Token::EOS) {
@@ -568,7 +567,7 @@
   // This is not handled during preparsing.
 
   i::Token::Value tok = peek();
-  if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
+  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
       tok != i::Token::SEMICOLON &&
       tok != i::Token::RBRACE &&
       tok != i::Token::EOS) {
@@ -584,7 +583,7 @@
   //   'with' '(' Expression ')' Statement
   Expect(i::Token::WITH, CHECK_OK);
   if (!is_classic_mode()) {
-    i::Scanner::Location location = scanner_->location();
+    i::Scanner::Location location = scanner()->location();
     ReportMessageAt(location, "strict_mode_with", NULL);
     *ok = false;
     return Statement::Default();
@@ -662,7 +661,7 @@
 bool PreParser::CheckInOrOf(bool accept_OF) {
   if (peek() == i::Token::IN ||
       (allow_for_of() && accept_OF && peek() == i::Token::IDENTIFIER &&
-       scanner_->is_next_contextual_keyword(v8::internal::CStrVector("of")))) {
+       scanner()->is_next_contextual_keyword(v8::internal::CStrVector("of")))) {
     Next();
     return true;
   }
@@ -729,8 +728,8 @@
   //   'throw' [no line terminator] Expression ';'
 
   Expect(i::Token::THROW, CHECK_OK);
-  if (scanner_->HasAnyLineTerminatorBeforeNext()) {
-    i::Scanner::Location pos = scanner_->location();
+  if (scanner()->HasAnyLineTerminatorBeforeNext()) {
+    i::Scanner::Location pos = scanner()->location();
     ReportMessageAt(pos, "newline_after_throw", NULL);
     *ok = false;
     return Statement::Default();
@@ -766,7 +765,7 @@
     Expect(i::Token::LPAREN, CHECK_OK);
     Identifier id = ParseIdentifier(CHECK_OK);
     if (!is_classic_mode() && !id.IsValidStrictVariable()) {
-      StrictModeIdentifierViolation(scanner_->location(),
+      StrictModeIdentifierViolation(scanner()->location(),
                                     "strict_catch_variable",
                                     id,
                                     ok);
@@ -839,7 +838,7 @@
     return ParseYieldExpression(ok);
   }
 
-  i::Scanner::Location before = scanner_->peek_location();
+  i::Scanner::Location before = scanner()->peek_location();
   Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK);
 
   if (!i::Token::IsAssignmentOp(peek())) {
@@ -850,7 +849,7 @@
   if (!is_classic_mode() &&
       expression.IsIdentifier() &&
       expression.AsIdentifier().IsEvalOrArguments()) {
-    i::Scanner::Location after = scanner_->location();
+    i::Scanner::Location after = scanner()->location();
     ReportMessageAt(before.beg_pos, after.end_pos,
                     "strict_lhs_assignment", NULL);
     *ok = false;
@@ -947,12 +946,12 @@
     return Expression::Default();
   } else if (i::Token::IsCountOp(op)) {
     op = Next();
-    i::Scanner::Location before = scanner_->peek_location();
+    i::Scanner::Location before = scanner()->peek_location();
     Expression expression = ParseUnaryExpression(CHECK_OK);
     if (!is_classic_mode() &&
         expression.IsIdentifier() &&
         expression.AsIdentifier().IsEvalOrArguments()) {
-      i::Scanner::Location after = scanner_->location();
+      i::Scanner::Location after = scanner()->location();
       ReportMessageAt(before.beg_pos, after.end_pos,
                       "strict_lhs_prefix", NULL);
       *ok = false;
@@ -968,14 +967,14 @@
   // PostfixExpression ::
   //   LeftHandSideExpression ('++' | '--')?
 
-  i::Scanner::Location before = scanner_->peek_location();
+  i::Scanner::Location before = scanner()->peek_location();
   Expression expression = ParseLeftHandSideExpression(CHECK_OK);
-  if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
+  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
       i::Token::IsCountOp(peek())) {
     if (!is_classic_mode() &&
         expression.IsIdentifier() &&
         expression.AsIdentifier().IsEvalOrArguments()) {
-      i::Scanner::Location after = scanner_->location();
+      i::Scanner::Location after = scanner()->location();
       ReportMessageAt(before.beg_pos, after.end_pos,
                       "strict_lhs_postfix", NULL);
       *ok = false;
@@ -1075,14 +1074,14 @@
   if (peek() == i::Token::FUNCTION) {
     Consume(i::Token::FUNCTION);
 
-    bool is_generator = allow_generators_ && Check(i::Token::MUL);
+    bool is_generator = allow_generators() && Check(i::Token::MUL);
     Identifier identifier = Identifier::Default();
     if (peek_any_identifier()) {
       identifier = ParseIdentifier(CHECK_OK);
     }
     result = ParseFunctionLiteral(is_generator, CHECK_OK);
     if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) {
-      StrictModeIdentifierViolation(scanner_->location(),
+      StrictModeIdentifierViolation(scanner()->location(),
                                     "strict_function_name",
                                     identifier,
                                     ok);
@@ -1239,7 +1238,7 @@
   //     | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
   //    )*[','] '}'
 
-  i::ObjectLiteralChecker<PreParser> checker(this, scanner_, language_mode());
+  i::ObjectLiteralChecker<PreParser> checker(this, scanner(), language_mode());
 
   Expect(i::Token::LBRACE, CHECK_OK);
   while (peek() != i::Token::RBRACE) {
@@ -1313,18 +1312,18 @@
 
 PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal,
                                                     bool* ok) {
-  if (!scanner_->ScanRegExpPattern(seen_equal)) {
+  if (!scanner()->ScanRegExpPattern(seen_equal)) {
     Next();
-    ReportMessageAt(scanner_->location(), "unterminated_regexp", NULL);
+    ReportMessageAt(scanner()->location(), "unterminated_regexp", NULL);
     *ok = false;
     return Expression::Default();
   }
 
   scope_->NextMaterializedLiteralIndex();
 
-  if (!scanner_->ScanRegExpFlags()) {
+  if (!scanner()->ScanRegExpFlags()) {
     Next();
-    ReportMessageAt(scanner_->location(), "invalid_regexp_flags", NULL);
+    ReportMessageAt(scanner()->location(), "invalid_regexp_flags", NULL);
     *ok = false;
     return Expression::Default();
   }
@@ -1369,28 +1368,28 @@
   //  FormalParameterList ::
   //    '(' (Identifier)*[','] ')'
   Expect(i::Token::LPAREN, CHECK_OK);
-  int start_position = scanner_->location().beg_pos;
+  int start_position = scanner()->location().beg_pos;
   bool done = (peek() == i::Token::RPAREN);
-  i::DuplicateFinder duplicate_finder(scanner_->unicode_cache());
+  i::DuplicateFinder duplicate_finder(scanner()->unicode_cache());
   while (!done) {
     Identifier id = ParseIdentifier(CHECK_OK);
     if (!id.IsValidStrictVariable()) {
-      StrictModeIdentifierViolation(scanner_->location(),
+      StrictModeIdentifierViolation(scanner()->location(),
                                     "strict_param_name",
                                     id,
                                     CHECK_OK);
     }
     int prev_value;
-    if (scanner_->is_literal_ascii()) {
+    if (scanner()->is_literal_ascii()) {
       prev_value =
-          duplicate_finder.AddAsciiSymbol(scanner_->literal_ascii_string(), 1);
+          duplicate_finder.AddAsciiSymbol(scanner()->literal_ascii_string(), 1);
     } else {
       prev_value =
-          duplicate_finder.AddUtf16Symbol(scanner_->literal_utf16_string(), 1);
+          duplicate_finder.AddUtf16Symbol(scanner()->literal_utf16_string(), 1);
     }
 
     if (prev_value != 0) {
-      SetStrictModeViolation(scanner_->location(),
+      SetStrictModeViolation(scanner()->location(),
                              "strict_param_dupe",
                              CHECK_OK);
     }
@@ -1405,7 +1404,7 @@
   // Currently only happens to top-level functions.
   // Optimistically assume that all top-level functions are lazily compiled.
   bool is_lazily_compiled = (outer_scope_type == kTopLevelScope &&
-                             !inside_with && allow_lazy_ &&
+                             !inside_with && allow_lazy() &&
                              !parenthesized_function_);
   parenthesized_function_ = false;
 
@@ -1418,7 +1417,7 @@
   Expect(i::Token::RBRACE, CHECK_OK);
 
   if (!is_classic_mode()) {
-    int end_position = scanner_->location().end_pos;
+    int end_position = scanner()->location().end_pos;
     CheckOctalLiteral(start_position, end_position, CHECK_OK);
     CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK);
     return Expression::StrictFunction();
@@ -1429,15 +1428,15 @@
 
 
 void PreParser::ParseLazyFunctionLiteralBody(bool* ok) {
-  int body_start = scanner_->location().beg_pos;
+  int body_start = scanner()->location().beg_pos;
   log_->PauseRecording();
   ParseSourceElements(i::Token::RBRACE, ok);
   log_->ResumeRecording();
   if (!*ok) return;
 
   // Position right after terminal '}'.
-  ASSERT_EQ(i::Token::RBRACE, scanner_->peek());
-  int body_end = scanner_->peek_location().end_pos;
+  ASSERT_EQ(i::Token::RBRACE, scanner()->peek());
+  int body_end = scanner()->peek_location().end_pos;
   log_->LogFunction(body_start, body_end,
                     scope_->materialized_literal_count(),
                     scope_->expected_properties(),
@@ -1449,7 +1448,7 @@
   // CallRuntime ::
   //   '%' Identifier Arguments
   Expect(i::Token::MOD, CHECK_OK);
-  if (!allow_natives_syntax_) {
+  if (!allow_natives_syntax()) {
     *ok = false;
     return Expression::Default();
   }
@@ -1462,29 +1461,12 @@
 #undef CHECK_OK
 
 
-void PreParser::ExpectSemicolon(bool* ok) {
-  // Check for automatic semicolon insertion according to
-  // the rules given in ECMA-262, section 7.9, page 21.
-  i::Token::Value tok = peek();
-  if (tok == i::Token::SEMICOLON) {
-    Next();
-    return;
-  }
-  if (scanner_->HasAnyLineTerminatorBeforeNext() ||
-      tok == i::Token::RBRACE ||
-      tok == i::Token::EOS) {
-    return;
-  }
-  Expect(i::Token::SEMICOLON, ok);
-}
-
-
 void PreParser::LogSymbol() {
-  int identifier_pos = scanner_->location().beg_pos;
-  if (scanner_->is_literal_ascii()) {
-    log_->LogAsciiSymbol(identifier_pos, scanner_->literal_ascii_string());
+  int identifier_pos = scanner()->location().beg_pos;
+  if (scanner()->is_literal_ascii()) {
+    log_->LogAsciiSymbol(identifier_pos, scanner()->literal_ascii_string());
   } else {
-    log_->LogUtf16Symbol(identifier_pos, scanner_->literal_utf16_string());
+    log_->LogUtf16Symbol(identifier_pos, scanner()->literal_utf16_string());
   }
 }
 
@@ -1493,10 +1475,10 @@
   const int kUseStrictLength = 10;
   const char* kUseStrictChars = "use strict";
   LogSymbol();
-  if (scanner_->is_literal_ascii() &&
-      scanner_->literal_length() == kUseStrictLength &&
-      !scanner_->literal_contains_escapes() &&
-      !strncmp(scanner_->literal_ascii_string().start(), kUseStrictChars,
+  if (scanner()->is_literal_ascii() &&
+      scanner()->literal_length() == kUseStrictLength &&
+      !scanner()->literal_contains_escapes() &&
+      !strncmp(scanner()->literal_ascii_string().start(), kUseStrictChars,
                kUseStrictLength)) {
     return Expression::UseStrictStringLiteral();
   }
@@ -1506,22 +1488,22 @@
 
 PreParser::Identifier PreParser::GetIdentifierSymbol() {
   LogSymbol();
-  if (scanner_->current_token() == i::Token::FUTURE_RESERVED_WORD) {
+  if (scanner()->current_token() == i::Token::FUTURE_RESERVED_WORD) {
     return Identifier::FutureReserved();
-  } else if (scanner_->current_token() ==
+  } else if (scanner()->current_token() ==
              i::Token::FUTURE_STRICT_RESERVED_WORD) {
     return Identifier::FutureStrictReserved();
-  } else if (scanner_->current_token() == i::Token::YIELD) {
+  } else if (scanner()->current_token() == i::Token::YIELD) {
     return Identifier::Yield();
   }
-  if (scanner_->is_literal_ascii()) {
+  if (scanner()->is_literal_ascii()) {
     // Detect strict-mode poison words.
-    if (scanner_->literal_length() == 4 &&
-        !strncmp(scanner_->literal_ascii_string().start(), "eval", 4)) {
+    if (scanner()->literal_length() == 4 &&
+        !strncmp(scanner()->literal_ascii_string().start(), "eval", 4)) {
       return Identifier::Eval();
     }
-    if (scanner_->literal_length() == 9 &&
-        !strncmp(scanner_->literal_ascii_string().start(), "arguments", 9)) {
+    if (scanner()->literal_length() == 9 &&
+        !strncmp(scanner()->literal_ascii_string().start(), "arguments", 9)) {
       return Identifier::Arguments();
     }
   }
@@ -1533,7 +1515,7 @@
   i::Token::Value next = Next();
   switch (next) {
     case i::Token::FUTURE_RESERVED_WORD: {
-      i::Scanner::Location location = scanner_->location();
+      i::Scanner::Location location = scanner()->location();
       ReportMessageAt(location.beg_pos, location.end_pos,
                       "reserved_word", NULL);
       *ok = false;
@@ -1542,14 +1524,14 @@
     case i::Token::YIELD:
       if (scope_->is_generator()) {
         // 'yield' in a generator is only valid as part of a YieldExpression.
-        ReportMessageAt(scanner_->location(), "unexpected_token", "yield");
+        ReportMessageAt(scanner()->location(), "unexpected_token", "yield");
         *ok = false;
         return Identifier::Yield();
       }
       // FALLTHROUGH
     case i::Token::FUTURE_STRICT_RESERVED_WORD:
       if (!is_classic_mode()) {
-        i::Scanner::Location location = scanner_->location();
+        i::Scanner::Location location = scanner()->location();
         ReportMessageAt(location.beg_pos, location.end_pos,
                         "strict_reserved_word", NULL);
         *ok = false;
@@ -1620,7 +1602,7 @@
 PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
   i::Token::Value next = Next();
   if (i::Token::IsKeyword(next)) {
-    int pos = scanner_->location().beg_pos;
+    int pos = scanner()->location().beg_pos;
     const char* keyword = i::Token::String(next);
     log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword,
                                                     i::StrLength(keyword)));
@@ -1645,9 +1627,9 @@
                                                                bool* ok) {
   Identifier result = ParseIdentifierName(ok);
   if (!*ok) return Identifier::Default();
-  if (scanner_->is_literal_ascii() &&
-      scanner_->literal_length() == 3) {
-    const char* token = scanner_->literal_ascii_string().start();
+  if (scanner()->is_literal_ascii() &&
+      scanner()->literal_length() == 3) {
+    const char* token = scanner()->literal_ascii_string().start();
     *is_get = strncmp(token, "get", 3) == 0;
     *is_set = !*is_get && strncmp(token, "set", 3) == 0;
   }
@@ -1655,12 +1637,4 @@
 }
 
 
-bool PreParser::peek_any_identifier() {
-  i::Token::Value next = peek();
-  return next == i::Token::IDENTIFIER ||
-         next == i::Token::FUTURE_RESERVED_WORD ||
-         next == i::Token::FUTURE_STRICT_RESERVED_WORD ||
-         next == i::Token::YIELD;
-}
-
-} }  // v8::preparser
+} }  // v8::internal
diff --git a/src/preparser.h b/src/preparser.h
index 08766e9..74cffa2 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -33,7 +33,6 @@
 #include "scanner.h"
 
 namespace v8 {
-
 namespace internal {
 
 // Used to detect duplicates in object literals. Each of the values
@@ -125,11 +124,112 @@
   }
 }
 
-}  // v8::internal
 
-namespace preparser {
+// Common base class shared between parser and pre-parser.
+class ParserBase {
+ public:
+  ParserBase(Scanner* scanner, uintptr_t stack_limit)
+      : scanner_(scanner),
+        stack_limit_(stack_limit),
+        stack_overflow_(false),
+        allow_lazy_(false),
+        allow_natives_syntax_(false),
+        allow_generators_(false),
+        allow_for_of_(false) { }
+  // TODO(mstarzinger): Only virtual until message reporting has been unified.
+  virtual ~ParserBase() { }
 
-typedef uint8_t byte;
+  // Getters that indicate whether certain syntactical constructs are
+  // allowed to be parsed by this instance of the parser.
+  bool allow_lazy() const { return allow_lazy_; }
+  bool allow_natives_syntax() const { return allow_natives_syntax_; }
+  bool allow_generators() const { return allow_generators_; }
+  bool allow_for_of() const { return allow_for_of_; }
+  bool allow_modules() const { return scanner()->HarmonyModules(); }
+  bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); }
+  bool allow_harmony_numeric_literals() const {
+    return scanner()->HarmonyNumericLiterals();
+  }
+
+  // Setters that determine whether certain syntactical constructs are
+  // allowed to be parsed by this instance of the parser.
+  void set_allow_lazy(bool allow) { allow_lazy_ = allow; }
+  void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; }
+  void set_allow_generators(bool allow) { allow_generators_ = allow; }
+  void set_allow_for_of(bool allow) { allow_for_of_ = allow; }
+  void set_allow_modules(bool allow) { scanner()->SetHarmonyModules(allow); }
+  void set_allow_harmony_scoping(bool allow) {
+    scanner()->SetHarmonyScoping(allow);
+  }
+  void set_allow_harmony_numeric_literals(bool allow) {
+    scanner()->SetHarmonyNumericLiterals(allow);
+  }
+
+ protected:
+  Scanner* scanner() const { return scanner_; }
+  bool stack_overflow() const { return stack_overflow_; }
+  void set_stack_overflow() { stack_overflow_ = true; }
+
+  INLINE(Token::Value peek()) {
+    if (stack_overflow_) return Token::ILLEGAL;
+    return scanner()->peek();
+  }
+
+  INLINE(Token::Value Next()) {
+    if (stack_overflow_) return Token::ILLEGAL;
+    {
+      int marker;
+      if (reinterpret_cast<uintptr_t>(&marker) < stack_limit_) {
+        // Any further calls to Next or peek will return the illegal token.
+        // The current call must return the next token, which might already
+        // have been peek'ed.
+        stack_overflow_ = true;
+      }
+    }
+    return scanner()->Next();
+  }
+
+  void Consume(Token::Value token) {
+    Token::Value next = Next();
+    USE(next);
+    USE(token);
+    ASSERT(next == token);
+  }
+
+  bool Check(Token::Value token) {
+    Token::Value next = peek();
+    if (next == token) {
+      Consume(next);
+      return true;
+    }
+    return false;
+  }
+
+  void Expect(Token::Value token, bool* ok) {
+    Token::Value next = Next();
+    if (next != token) {
+      ReportUnexpectedToken(next);
+      *ok = false;
+    }
+  }
+
+  bool peek_any_identifier();
+  void ExpectSemicolon(bool* ok);
+
+  // Report syntax errors.
+  virtual void ReportUnexpectedToken(Token::Value token) = 0;
+
+ private:
+  Scanner* scanner_;
+  uintptr_t stack_limit_;
+  bool stack_overflow_;
+
+  bool allow_lazy_;
+  bool allow_natives_syntax_;
+  bool allow_generators_;
+  bool allow_for_of_;
+};
+
 
 // Preparsing checks a JavaScript program and emits preparse-data that helps
 // a later parsing to be faster.
@@ -144,9 +244,10 @@
 // That means that contextual checks (like a label being declared where
 // it is used) are generally omitted.
 
+typedef uint8_t byte;
 namespace i = v8::internal;
 
-class PreParser {
+class PreParser : public ParserBase {
  public:
   enum PreParseResult {
     kPreParseStackOverflow,
@@ -157,43 +258,15 @@
   PreParser(i::Scanner* scanner,
             i::ParserRecorder* log,
             uintptr_t stack_limit)
-      : scanner_(scanner),
+      : ParserBase(scanner, stack_limit),
         log_(log),
         scope_(NULL),
-        stack_limit_(stack_limit),
         strict_mode_violation_location_(i::Scanner::Location::invalid()),
         strict_mode_violation_type_(NULL),
-        stack_overflow_(false),
-        allow_lazy_(false),
-        allow_natives_syntax_(false),
-        allow_generators_(false),
-        allow_for_of_(false),
         parenthesized_function_(false) { }
 
   ~PreParser() {}
 
-  bool allow_natives_syntax() const { return allow_natives_syntax_; }
-  bool allow_lazy() const { return allow_lazy_; }
-  bool allow_modules() const { return scanner_->HarmonyModules(); }
-  bool allow_harmony_scoping() const { return scanner_->HarmonyScoping(); }
-  bool allow_generators() const { return allow_generators_; }
-  bool allow_for_of() const { return allow_for_of_; }
-  bool allow_harmony_numeric_literals() const {
-    return scanner_->HarmonyNumericLiterals();
-  }
-
-  void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; }
-  void set_allow_lazy(bool allow) { allow_lazy_ = allow; }
-  void set_allow_modules(bool allow) { scanner_->SetHarmonyModules(allow); }
-  void set_allow_harmony_scoping(bool allow) {
-    scanner_->SetHarmonyScoping(allow);
-  }
-  void set_allow_generators(bool allow) { allow_generators_ = allow; }
-  void set_allow_for_of(bool allow) { allow_for_of_ = allow; }
-  void set_allow_harmony_numeric_literals(bool allow) {
-    scanner_->SetHarmonyNumericLiterals(allow);
-  }
-
   // Pre-parse the program from the character stream; returns true on
   // success (even if parsing failed, the pre-parse data successfully
   // captured the syntax error), and false if a stack-overflow happened
@@ -201,13 +274,13 @@
   PreParseResult PreParseProgram() {
     Scope top_scope(&scope_, kTopLevelScope);
     bool ok = true;
-    int start_position = scanner_->peek_location().beg_pos;
+    int start_position = scanner()->peek_location().beg_pos;
     ParseSourceElements(i::Token::EOS, &ok);
-    if (stack_overflow_) return kPreParseStackOverflow;
+    if (stack_overflow()) return kPreParseStackOverflow;
     if (!ok) {
-      ReportUnexpectedToken(scanner_->current_token());
+      ReportUnexpectedToken(scanner()->current_token());
     } else if (!scope_->is_classic_mode()) {
-      CheckOctalLiteral(start_position, scanner_->location().end_pos, &ok);
+      CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok);
     }
     return kPreParseSuccess;
   }
@@ -609,27 +682,6 @@
   // Log the currently parsed string literal.
   Expression GetStringSymbol();
 
-  i::Token::Value peek() {
-    if (stack_overflow_) return i::Token::ILLEGAL;
-    return scanner_->peek();
-  }
-
-  i::Token::Value Next() {
-    if (stack_overflow_) return i::Token::ILLEGAL;
-    {
-      int marker;
-      if (reinterpret_cast<uintptr_t>(&marker) < stack_limit_) {
-        // Further calls to peek/Next will return illegal token.
-        // The current one will still be returned. It might already
-        // have been seen using peek.
-        stack_overflow_ = true;
-      }
-    }
-    return scanner_->Next();
-  }
-
-  bool peek_any_identifier();
-
   void set_language_mode(i::LanguageMode language_mode) {
     scope_->set_language_mode(language_mode);
   }
@@ -644,24 +696,6 @@
 
   i::LanguageMode language_mode() { return scope_->language_mode(); }
 
-  void Consume(i::Token::Value token) { Next(); }
-
-  void Expect(i::Token::Value token, bool* ok) {
-    if (Next() != token) {
-      *ok = false;
-    }
-  }
-
-  bool Check(i::Token::Value token) {
-    i::Token::Value next = peek();
-    if (next == token) {
-      Consume(next);
-      return true;
-    }
-    return false;
-  }
-  void ExpectSemicolon(bool* ok);
-
   bool CheckInOrOf(bool accept_OF);
 
   static int Precedence(i::Token::Value tok, bool accept_IN);
@@ -677,22 +711,15 @@
                                      Identifier identifier,
                                      bool* ok);
 
-  i::Scanner* scanner_;
   i::ParserRecorder* log_;
   Scope* scope_;
-  uintptr_t stack_limit_;
   i::Scanner::Location strict_mode_violation_location_;
   const char* strict_mode_violation_type_;
-  bool stack_overflow_;
-  bool allow_lazy_;
-  bool allow_natives_syntax_;
-  bool allow_generators_;
-  bool allow_for_of_;
   bool parenthesized_function_;
 
   friend class i::ObjectLiteralChecker<PreParser>;
 };
 
-} }  // v8::preparser
+} }  // v8::internal
 
 #endif  // V8_PREPARSER_H
diff --git a/src/prettyprinter.cc b/src/prettyprinter.cc
index 14ad707..4b441b9 100644
--- a/src/prettyprinter.cc
+++ b/src/prettyprinter.cc
@@ -200,11 +200,25 @@
   Print(") { ");
   ZoneList<CaseClause*>* cases = node->cases();
   for (int i = 0; i < cases->length(); i++)
-    PrintCaseClause(cases->at(i));
+    Visit(cases->at(i));
   Print("}");
 }
 
 
+void PrettyPrinter::VisitCaseClause(CaseClause* clause) {
+  if (clause->is_default()) {
+    Print("default");
+  } else {
+    Print("case ");
+    Visit(clause->label());
+  }
+  Print(": ");
+  PrintStatements(clause->statements());
+  if (clause->statements()->length() > 0)
+    Print(" ");
+}
+
+
 void PrettyPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
   PrintLabels(node->labels());
   Print("do ");
@@ -620,20 +634,6 @@
 }
 
 
-void PrettyPrinter::PrintCaseClause(CaseClause* clause) {
-  if (clause->is_default()) {
-    Print("default");
-  } else {
-    Print("case ");
-    Visit(clause->label());
-  }
-  Print(": ");
-  PrintStatements(clause->statements());
-  if (clause->statements()->length() > 0)
-    Print(" ");
-}
-
-
 //-----------------------------------------------------------------------------
 
 class IndentedScope BASE_EMBEDDED {
@@ -761,18 +761,6 @@
 }
 
 
-void AstPrinter::PrintCaseClause(CaseClause* clause) {
-  if (clause->is_default()) {
-    IndentedScope indent(this, "DEFAULT");
-    PrintStatements(clause->statements());
-  } else {
-    IndentedScope indent(this, "CASE");
-    Visit(clause->label());
-    PrintStatements(clause->statements());
-  }
-}
-
-
 void AstPrinter::VisitBlock(Block* node) {
   const char* block_txt = node->is_initializer_block() ? "BLOCK INIT" : "BLOCK";
   IndentedScope indent(this, block_txt);
@@ -900,7 +888,19 @@
   PrintLabelsIndented(node->labels());
   PrintIndentedVisit("TAG", node->tag());
   for (int i = 0; i < node->cases()->length(); i++) {
-    PrintCaseClause(node->cases()->at(i));
+    Visit(node->cases()->at(i));
+  }
+}
+
+
+void AstPrinter::VisitCaseClause(CaseClause* clause) {
+  if (clause->is_default()) {
+    IndentedScope indent(this, "DEFAULT");
+    PrintStatements(clause->statements());
+  } else {
+    IndentedScope indent(this, "CASE");
+    Visit(clause->label());
+    PrintStatements(clause->statements());
   }
 }
 
diff --git a/src/profile-generator-inl.h b/src/profile-generator-inl.h
index 76a9fb1..ac23ee3 100644
--- a/src/profile-generator-inl.h
+++ b/src/profile-generator-inl.h
@@ -79,25 +79,6 @@
       children_(CodeEntriesMatch),
       id_(tree->next_node_id()) { }
 
-
-CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) {
-  switch (tag) {
-    case GC:
-      return gc_entry_;
-    case JS:
-    case COMPILER:
-    // DOM events handlers are reported as OTHER / EXTERNAL entries.
-    // To avoid confusing people, let's put all these entries into
-    // one bucket.
-    case OTHER:
-    case EXTERNAL:
-      return program_entry_;
-    case IDLE:
-      return idle_entry_;
-    default: return NULL;
-  }
-}
-
 } }  // namespace v8::internal
 
 #endif  // V8_PROFILE_GENERATOR_INL_H_
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index d8e8c12..cf268af 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -141,15 +141,6 @@
 }
 
 
-void CodeEntry::CopyData(const CodeEntry& source) {
-  tag_ = source.tag_;
-  name_prefix_ = source.name_prefix_;
-  name_ = source.name_;
-  resource_name_ = source.resource_name_;
-  line_number_ = source.line_number_;
-}
-
-
 uint32_t CodeEntry::GetCallUid() const {
   uint32_t hash = ComputeIntegerHash(tag_, v8::internal::kZeroHashSeed);
   if (shared_id_ != 0) {
@@ -662,4 +653,22 @@
 }
 
 
+CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) {
+  switch (tag) {
+    case GC:
+      return gc_entry_;
+    case JS:
+    case COMPILER:
+    // DOM events handlers are reported as OTHER / EXTERNAL entries.
+    // To avoid confusing people, let's put all these entries into
+    // one bucket.
+    case OTHER:
+    case EXTERNAL:
+      return program_entry_;
+    case IDLE:
+      return idle_entry_;
+    default: return NULL;
+  }
+}
+
 } }  // namespace v8::internal
diff --git a/src/profile-generator.h b/src/profile-generator.h
index b9536ab..890fb2e 100644
--- a/src/profile-generator.h
+++ b/src/profile-generator.h
@@ -56,7 +56,7 @@
  private:
   static const int kMaxNameSize = 1024;
 
-  INLINE(static bool StringsMatch(void* key1, void* key2)) {
+  static bool StringsMatch(void* key1, void* key2) {
     return strcmp(reinterpret_cast<char*>(key1),
                   reinterpret_cast<char*>(key2)) == 0;
   }
@@ -73,31 +73,30 @@
 class CodeEntry {
  public:
   // CodeEntry doesn't own name strings, just references them.
-  INLINE(CodeEntry(Logger::LogEventsAndTags tag,
+  inline CodeEntry(Logger::LogEventsAndTags tag,
                    const char* name,
                    const char* name_prefix = CodeEntry::kEmptyNamePrefix,
                    const char* resource_name = CodeEntry::kEmptyResourceName,
                    int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
-                   int column_number =
-                       v8::CpuProfileNode::kNoColumnNumberInfo));
+                   int column_number = v8::CpuProfileNode::kNoColumnNumberInfo);
   ~CodeEntry();
 
-  INLINE(bool is_js_function() const) { return is_js_function_tag(tag_); }
-  INLINE(const char* name_prefix() const) { return name_prefix_; }
-  INLINE(bool has_name_prefix() const) { return name_prefix_[0] != '\0'; }
-  INLINE(const char* name() const) { return name_; }
-  INLINE(const char* resource_name() const) { return resource_name_; }
-  INLINE(int line_number() const) { return line_number_; }
+  bool is_js_function() const { return is_js_function_tag(tag_); }
+  const char* name_prefix() const { return name_prefix_; }
+  bool has_name_prefix() const { return name_prefix_[0] != '\0'; }
+  const char* name() const { return name_; }
+  const char* resource_name() const { return resource_name_; }
+  int line_number() const { return line_number_; }
   int column_number() const { return column_number_; }
-  INLINE(void set_shared_id(int shared_id)) { shared_id_ = shared_id; }
-  INLINE(int script_id() const) { return script_id_; }
-  INLINE(void set_script_id(int script_id)) { script_id_ = script_id; }
-  INLINE(void set_bailout_reason(const char* bailout_reason)) {
+  void set_shared_id(int shared_id) { shared_id_ = shared_id; }
+  int script_id() const { return script_id_; }
+  void set_script_id(int script_id) { script_id_ = script_id; }
+  void set_bailout_reason(const char* bailout_reason) {
     bailout_reason_ = bailout_reason;
   }
-  INLINE(const char* bailout_reason() const) { return bailout_reason_; }
+  const char* bailout_reason() const { return bailout_reason_; }
 
-  INLINE(static bool is_js_function_tag(Logger::LogEventsAndTags tag));
+  static inline bool is_js_function_tag(Logger::LogEventsAndTags tag);
 
   List<OffsetRange>* no_frame_ranges() const { return no_frame_ranges_; }
   void set_no_frame_ranges(List<OffsetRange>* ranges) {
@@ -107,7 +106,6 @@
   void SetBuiltinId(Builtins::Name id);
   Builtins::Name builtin_id() const { return builtin_id_; }
 
-  void CopyData(const CodeEntry& source);
   uint32_t GetCallUid() const;
   bool IsSameAs(CodeEntry* entry) const;
 
@@ -136,27 +134,27 @@
 
 class ProfileNode {
  public:
-  INLINE(ProfileNode(ProfileTree* tree, CodeEntry* entry));
+  inline ProfileNode(ProfileTree* tree, CodeEntry* entry);
 
   ProfileNode* FindChild(CodeEntry* entry);
   ProfileNode* FindOrAddChild(CodeEntry* entry);
-  INLINE(void IncrementSelfTicks()) { ++self_ticks_; }
-  INLINE(void IncreaseSelfTicks(unsigned amount)) { self_ticks_ += amount; }
+  void IncrementSelfTicks() { ++self_ticks_; }
+  void IncreaseSelfTicks(unsigned amount) { self_ticks_ += amount; }
 
-  INLINE(CodeEntry* entry() const) { return entry_; }
-  INLINE(unsigned self_ticks() const) { return self_ticks_; }
-  INLINE(const List<ProfileNode*>* children() const) { return &children_list_; }
+  CodeEntry* entry() const { return entry_; }
+  unsigned self_ticks() const { return self_ticks_; }
+  const List<ProfileNode*>* children() const { return &children_list_; }
   unsigned id() const { return id_; }
 
   void Print(int indent);
 
  private:
-  INLINE(static bool CodeEntriesMatch(void* entry1, void* entry2)) {
+  static bool CodeEntriesMatch(void* entry1, void* entry2) {
     return reinterpret_cast<CodeEntry*>(entry1)->IsSameAs(
         reinterpret_cast<CodeEntry*>(entry2));
   }
 
-  INLINE(static uint32_t CodeEntryHash(CodeEntry* entry)) {
+  static uint32_t CodeEntryHash(CodeEntry* entry) {
     return entry->GetCallUid();
   }
 
@@ -336,7 +334,7 @@
 
   void RecordTickSample(const TickSample& sample);
 
-  INLINE(CodeMap* code_map()) { return &code_map_; }
+  CodeMap* code_map() { return &code_map_; }
 
   static const char* const kAnonymousFunctionName;
   static const char* const kProgramEntryName;
@@ -347,7 +345,7 @@
   static const char* const kUnresolvedFunctionName;
 
  private:
-  INLINE(CodeEntry* EntryForVMState(StateTag tag));
+  CodeEntry* EntryForVMState(StateTag tag);
 
   CpuProfilesCollection* profiles_;
   CodeMap code_map_;
diff --git a/src/rewriter.cc b/src/rewriter.cc
index 06335a8..70b362f 100644
--- a/src/rewriter.cc
+++ b/src/rewriter.cc
@@ -207,6 +207,11 @@
 }
 
 
+void Processor::VisitCaseClause(CaseClause* clause) {
+  UNREACHABLE();
+}
+
+
 void Processor::VisitContinueStatement(ContinueStatement* node) {
   is_set_ = false;
 }
@@ -271,13 +276,12 @@
       //   eval('with ({x:1}) x = 1');
       // 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();
+      int pos = function->end_position();
       VariableProxy* result_proxy = processor.factory()->NewVariableProxy(
-          result->name(), false, result->interface(), position);
+          result->name(), false, result->interface(), pos);
       result_proxy->BindTo(result);
       Statement* result_statement =
-          processor.factory()->NewReturnStatement(result_proxy);
-      result_statement->set_statement_pos(position);
+          processor.factory()->NewReturnStatement(result_proxy, pos);
       body->Add(result_statement, info->zone());
     }
   }
diff --git a/src/runtime.cc b/src/runtime.cc
index 77014b1..be0281b 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -8579,6 +8579,13 @@
 }
 
 
+RUNTIME_FUNCTION(MaybeObject*, Runtime_UnblockConcurrentRecompilation) {
+  RUNTIME_ASSERT(FLAG_block_concurrent_recompilation);
+  isolate->optimizing_compiler_thread()->Unblock();
+  return isolate->heap()->undefined_value();
+}
+
+
 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) {
   HandleScope scope(isolate);
   ASSERT(args.length() == 1);
diff --git a/src/runtime.h b/src/runtime.h
index 5566226..1b7e32e 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -99,6 +99,7 @@
   F(NeverOptimizeFunction, 1, 1) \
   F(GetOptimizationStatus, -1, 1) \
   F(GetOptimizationCount, 1, 1) \
+  F(UnblockConcurrentRecompilation, 0, 1) \
   F(CompileForOnStackReplacement, 2, 1) \
   F(SetAllocationTimeout, 2, 1) \
   F(AllocateInNewSpace, 1, 1) \
diff --git a/src/scopes.cc b/src/scopes.cc
index ce1741a..ee327fb 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -437,8 +437,8 @@
         this, name, mode, true /* is valid LHS */,
         Variable::NORMAL, kCreatedInitialized);
     VariableProxy* proxy = factory->NewVariableProxy(var);
-    VariableDeclaration* declaration =
-        factory->NewVariableDeclaration(proxy, mode, this);
+    VariableDeclaration* declaration = factory->NewVariableDeclaration(
+        proxy, mode, this, RelocInfo::kNoPosition);
     DeclareFunctionVar(declaration);
     var->AllocateTo(Variable::CONTEXT, index);
     return var;
diff --git a/src/serialize.cc b/src/serialize.cc
index ef1461f..e7dbbe5 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -581,6 +581,10 @@
       UNCLASSIFIED,
       63,
       "Heap::allocation_sites_list_address()");
+  Add(ExternalReference::record_object_allocation_function(isolate).address(),
+      UNCLASSIFIED,
+      64,
+      "HeapProfiler::RecordObjectAllocationFromMasm");
 
   // Add a small set of deopt entry addresses to encoder without generating the
   // deopt table code, which isn't possible at deserialization time.
@@ -591,7 +595,7 @@
         entry,
         Deoptimizer::LAZY,
         Deoptimizer::CALCULATE_ENTRY_ADDRESS);
-    Add(address, LAZY_DEOPTIMIZATION, 64 + entry, "lazy_deopt");
+    Add(address, LAZY_DEOPTIMIZATION, 65 + entry, "lazy_deopt");
   }
 }
 
diff --git a/src/serialize.h b/src/serialize.h
index 020a744..9d6685b 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -366,6 +366,10 @@
   Address Allocate(int space_index, int size) {
     Address address = high_water_[space_index];
     high_water_[space_index] = address + size;
+    HeapProfiler* profiler = isolate_->heap_profiler();
+    if (profiler->is_tracking_allocations()) {
+      profiler->NewObjectEvent(address, size);
+    }
     return address;
   }
 
diff --git a/src/spaces-inl.h b/src/spaces-inl.h
index be2ae2a..7178b57 100644
--- a/src/spaces-inl.h
+++ b/src/spaces-inl.h
@@ -28,6 +28,7 @@
 #ifndef V8_SPACES_INL_H_
 #define V8_SPACES_INL_H_
 
+#include "heap-profiler.h"
 #include "isolate.h"
 #include "spaces.h"
 #include "v8memory.h"
@@ -273,12 +274,18 @@
 
 
 // Raw allocation.
-MaybeObject* PagedSpace::AllocateRaw(int size_in_bytes) {
+MaybeObject* PagedSpace::AllocateRaw(int size_in_bytes,
+                                     AllocationType event) {
+  HeapProfiler* profiler = heap()->isolate()->heap_profiler();
+
   HeapObject* object = AllocateLinearly(size_in_bytes);
   if (object != NULL) {
     if (identity() == CODE_SPACE) {
       SkipList::Update(object->address(), size_in_bytes);
     }
+    if (event == NEW_OBJECT && profiler->is_tracking_allocations()) {
+      profiler->NewObjectEvent(object->address(), size_in_bytes);
+    }
     return object;
   }
 
@@ -291,6 +298,9 @@
     if (identity() == CODE_SPACE) {
       SkipList::Update(object->address(), size_in_bytes);
     }
+    if (event == NEW_OBJECT && profiler->is_tracking_allocations()) {
+      profiler->NewObjectEvent(object->address(), size_in_bytes);
+    }
     return object;
   }
 
@@ -299,6 +309,9 @@
     if (identity() == CODE_SPACE) {
       SkipList::Update(object->address(), size_in_bytes);
     }
+    if (event == NEW_OBJECT && profiler->is_tracking_allocations()) {
+      profiler->NewObjectEvent(object->address(), size_in_bytes);
+    }
     return object;
   }
 
@@ -332,10 +345,15 @@
     return SlowAllocateRaw(size_in_bytes);
   }
 
-  Object* obj = HeapObject::FromAddress(old_top);
+  HeapObject* obj = HeapObject::FromAddress(old_top);
   allocation_info_.top += size_in_bytes;
   ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_);
 
+  HeapProfiler* profiler = heap()->isolate()->heap_profiler();
+  if (profiler != NULL && profiler->is_tracking_allocations()) {
+    profiler->NewObjectEvent(obj->address(), size_in_bytes);
+  }
+
   return obj;
 }
 
diff --git a/src/spaces.cc b/src/spaces.cc
index b7fa32d..d8aecf3 100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -1527,20 +1527,18 @@
 bool SemiSpace::Commit() {
   ASSERT(!is_committed());
   int pages = capacity_ / Page::kPageSize;
-  Address end = start_ + maximum_capacity_;
-  Address start = end - pages * Page::kPageSize;
-  if (!heap()->isolate()->memory_allocator()->CommitBlock(start,
+  if (!heap()->isolate()->memory_allocator()->CommitBlock(start_,
                                                           capacity_,
                                                           executable())) {
     return false;
   }
 
-  NewSpacePage* page = anchor();
-  for (int i = 1; i <= pages; i++) {
+  NewSpacePage* current = anchor();
+  for (int i = 0; i < pages; i++) {
     NewSpacePage* new_page =
-      NewSpacePage::Initialize(heap(), end - i * Page::kPageSize, this);
-    new_page->InsertAfter(page);
-    page = new_page;
+      NewSpacePage::Initialize(heap(), start_ + i * Page::kPageSize, this);
+    new_page->InsertAfter(current);
+    current = new_page;
   }
 
   committed_ = true;
@@ -1584,20 +1582,18 @@
   int pages_before = capacity_ / Page::kPageSize;
   int pages_after = new_capacity / Page::kPageSize;
 
-  Address end = start_ + maximum_capacity_;
-  Address start = end - new_capacity;
   size_t delta = new_capacity - capacity_;
 
   ASSERT(IsAligned(delta, OS::AllocateAlignment()));
   if (!heap()->isolate()->memory_allocator()->CommitBlock(
-      start, delta, executable())) {
+      start_ + capacity_, delta, executable())) {
     return false;
   }
   capacity_ = new_capacity;
   NewSpacePage* last_page = anchor()->prev_page();
   ASSERT(last_page != anchor());
-  for (int i = pages_before + 1; i <= pages_after; i++) {
-    Address page_address = end - i * Page::kPageSize;
+  for (int i = pages_before; i < pages_after; i++) {
+    Address page_address = start_ + i * Page::kPageSize;
     NewSpacePage* new_page = NewSpacePage::Initialize(heap(),
                                                       page_address,
                                                       this);
@@ -1617,25 +1613,20 @@
   ASSERT(new_capacity >= initial_capacity_);
   ASSERT(new_capacity < capacity_);
   if (is_committed()) {
-    // Semispaces grow backwards from the end of their allocated capacity,
-    // so we find the before and after start addresses relative to the
-    // end of the space.
-    Address space_end = start_ + maximum_capacity_;
-    Address old_start = space_end - capacity_;
     size_t delta = capacity_ - new_capacity;
     ASSERT(IsAligned(delta, OS::AllocateAlignment()));
 
     MemoryAllocator* allocator = heap()->isolate()->memory_allocator();
-    if (!allocator->UncommitBlock(old_start, delta)) {
+    if (!allocator->UncommitBlock(start_ + new_capacity, delta)) {
       return false;
     }
 
     int pages_after = new_capacity / Page::kPageSize;
     NewSpacePage* new_last_page =
-        NewSpacePage::FromAddress(space_end - pages_after * Page::kPageSize);
+        NewSpacePage::FromAddress(start_ + (pages_after - 1) * Page::kPageSize);
     new_last_page->set_next_page(anchor());
     anchor()->set_prev_page(new_last_page);
-    ASSERT((current_page_ <= first_page()) && (current_page_ >= new_last_page));
+    ASSERT((current_page_ >= first_page()) && (current_page_ <= new_last_page));
   }
 
   capacity_ = new_capacity;
diff --git a/src/spaces.h b/src/spaces.h
index 43f44a5..6144c95 100644
--- a/src/spaces.h
+++ b/src/spaces.h
@@ -1714,9 +1714,16 @@
   Address* allocation_top_address() { return &allocation_info_.top; }
   Address* allocation_limit_address() { return &allocation_info_.limit; }
 
+  enum AllocationType {
+    NEW_OBJECT,
+    MOVE_OBJECT
+  };
+
   // Allocate the requested number of bytes in the space if possible, return a
   // failure object if not.
-  MUST_USE_RESULT inline MaybeObject* AllocateRaw(int size_in_bytes);
+  MUST_USE_RESULT inline MaybeObject* AllocateRaw(
+      int size_in_bytes,
+      AllocationType event = NEW_OBJECT);
 
   virtual bool ReserveSpace(int bytes);
 
diff --git a/src/store-buffer-inl.h b/src/store-buffer-inl.h
index e1fcdee..7e5432c 100644
--- a/src/store-buffer-inl.h
+++ b/src/store-buffer-inl.h
@@ -41,6 +41,7 @@
 void StoreBuffer::Mark(Address addr) {
   ASSERT(!heap_->cell_space()->Contains(addr));
   ASSERT(!heap_->code_space()->Contains(addr));
+  ASSERT(!heap_->old_data_space()->Contains(addr));
   Address* top = reinterpret_cast<Address*>(heap_->store_buffer_top());
   *top++ = addr;
   heap_->public_set_store_buffer_top(top);
diff --git a/src/types.cc b/src/types.cc
index 9716686..17a19b2 100644
--- a/src/types.cc
+++ b/src/types.cc
@@ -240,6 +240,7 @@
 // Check this <= that.
 bool Type::SlowIs(Type* that) {
   // Fast path for bitsets.
+  if (this->is_none()) return true;
   if (that->is_bitset()) {
     return (this->LubBitset() | that->as_bitset()) == that->as_bitset();
   }
@@ -526,9 +527,13 @@
     }
     PrintF(out, "}");
   } else if (is_constant()) {
-    PrintF(out, "Constant(%p)", static_cast<void*>(*as_constant()));
+    PrintF(out, "Constant(%p : ", static_cast<void*>(*as_constant()));
+    from_bitset(LubBitset())->TypePrint(out);
+    PrintF(")");
   } else if (is_class()) {
-    PrintF(out, "Class(%p)", static_cast<void*>(*as_class()));
+    PrintF(out, "Class(%p < ", static_cast<void*>(*as_class()));
+    from_bitset(LubBitset())->TypePrint(out);
+    PrintF(")");
   } else if (is_union()) {
     PrintF(out, "{");
     Handle<Unioned> unioned = as_union();
diff --git a/src/types.h b/src/types.h
index 80772d8..5d437e2 100644
--- a/src/types.h
+++ b/src/types.h
@@ -226,6 +226,7 @@
     kUnusedEOL = 0
   };
 
+  bool is_none() { return this == None(); }
   bool is_bitset() { return this->IsSmi(); }
   bool is_class() { return this->IsMap(); }
   bool is_constant() { return this->IsBox(); }
@@ -299,10 +300,18 @@
   Handle<Type> upper;
 
   Bounds() {}
-  Bounds(Handle<Type> l, Handle<Type> u) : lower(l), upper(u) {}
-  Bounds(Type* l, Type* u, Isolate* isl) : lower(l, isl), upper(u, isl) {}
-  explicit Bounds(Handle<Type> t) : lower(t), upper(t) {}
-  Bounds(Type* t, Isolate* isl) : lower(t, isl), upper(t, isl) {}
+  Bounds(Handle<Type> l, Handle<Type> u) : lower(l), upper(u) {
+    ASSERT(lower->Is(upper));
+  }
+  Bounds(Type* l, Type* u, Isolate* isl) : lower(l, isl), upper(u, isl) {
+    ASSERT(lower->Is(upper));
+  }
+  explicit Bounds(Handle<Type> t) : lower(t), upper(t) {
+    ASSERT(lower->Is(upper));
+  }
+  Bounds(Type* t, Isolate* isl) : lower(t, isl), upper(t, isl) {
+    ASSERT(lower->Is(upper));
+  }
 
   // Unrestricted bounds.
   static Bounds Unbounded(Isolate* isl) {
@@ -311,9 +320,11 @@
 
   // Meet: both b1 and b2 are known to hold.
   static Bounds Both(Bounds b1, Bounds b2, Isolate* isl) {
-    return Bounds(
-        handle(Type::Union(b1.lower, b2.lower), isl),
-        handle(Type::Intersect(b1.upper, b2.upper), isl));
+    Handle<Type> lower(Type::Union(b1.lower, b2.lower), isl);
+    Handle<Type> upper(Type::Intersect(b1.upper, b2.upper), isl);
+    // Lower bounds are considered approximate, correct as necessary.
+    lower = handle(Type::Intersect(lower, upper), isl);
+    return Bounds(lower, upper);
   }
 
   // Join: either b1 or b2 is known to hold.
@@ -324,10 +335,14 @@
   }
 
   static Bounds NarrowLower(Bounds b, Handle<Type> t, Isolate* isl) {
+    // Lower bounds are considered approximate, correct as necessary.
+    t = handle(Type::Intersect(t, b.upper), isl);
     return Bounds(handle(Type::Union(b.lower, t), isl), b.upper);
   }
   static Bounds NarrowUpper(Bounds b, Handle<Type> t, Isolate* isl) {
-    return Bounds(b.lower, handle(Type::Intersect(b.upper, t), isl));
+    return Bounds(
+        handle(Type::Intersect(b.lower, t), isl),
+        handle(Type::Intersect(b.upper, t), isl));
   }
 };
 
diff --git a/src/typing.cc b/src/typing.cc
index e9da680..c3fd9c0 100644
--- a/src/typing.cc
+++ b/src/typing.cc
@@ -206,6 +206,11 @@
 }
 
 
+void AstTyper::VisitCaseClause(CaseClause* clause) {
+  UNREACHABLE();
+}
+
+
 void AstTyper::VisitDoWhileStatement(DoWhileStatement* stmt) {
   // Collect type feedback.
   if (!stmt->cond()->ToBooleanIsTrue()) {
@@ -247,8 +252,8 @@
     RECURSE(Visit(stmt->cond()));
   }
   RECURSE(Visit(stmt->body()));
-  store_.Forget();  // Control may transfer here via 'continue'.
   if (stmt->next() != NULL) {
+    store_.Forget();  // Control may transfer here via 'continue'.
     RECURSE(Visit(stmt->next()));
   }
   store_.Forget();  // Control may transfer here via termination or 'break'.
@@ -577,10 +582,15 @@
     case Token::BIT_AND: {
       RECURSE(Visit(expr->left()));
       RECURSE(Visit(expr->right()));
-      Type* upper = Type::Union(
-          expr->left()->bounds().upper, expr->right()->bounds().upper);
-      if (!upper->Is(Type::Signed32())) upper = Type::Signed32();
-      NarrowType(expr, Bounds(Type::Smi(), upper, isolate_));
+      Handle<Type> upper(
+          Type::Union(
+              expr->left()->bounds().upper, expr->right()->bounds().upper),
+          isolate_);
+      if (!upper->Is(Type::Signed32()))
+        upper = handle(Type::Signed32(), isolate_);
+      Handle<Type> lower(Type::Intersect(
+          handle(Type::Smi(), isolate_), upper), isolate_);
+      NarrowType(expr, Bounds(lower, upper));
       break;
     }
     case Token::BIT_XOR:
@@ -593,7 +603,8 @@
     case Token::SHR:
       RECURSE(Visit(expr->left()));
       RECURSE(Visit(expr->right()));
-      NarrowType(expr, Bounds(Type::Smi(), Type::Unsigned32(), isolate_));
+      // TODO(rossberg): we could use an UnsignedSmi as lower bound here...
+      NarrowType(expr, Bounds(Type::Unsigned32(), isolate_));
       break;
     case Token::ADD: {
       RECURSE(Visit(expr->left()));
@@ -601,15 +612,17 @@
       Bounds l = expr->left()->bounds();
       Bounds r = expr->right()->bounds();
       Type* lower =
-          l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) ?
-              Type::Smi() :
+          l.lower->Is(Type::None()) || r.lower->Is(Type::None()) ?
+              Type::None() :
           l.lower->Is(Type::String()) || r.lower->Is(Type::String()) ?
-              Type::String() : Type::None();
+              Type::String() :
+          l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) ?
+              Type::Smi() : Type::None();
       Type* upper =
-          l.upper->Is(Type::Number()) && r.upper->Is(Type::Number()) ?
-              Type::Number() :
           l.upper->Is(Type::String()) || r.upper->Is(Type::String()) ?
-              Type::String() : Type::NumberOrString();
+              Type::String() :
+          l.upper->Is(Type::Number()) && r.upper->Is(Type::Number()) ?
+              Type::Number() : Type::NumberOrString();
       NarrowType(expr, Bounds(lower, upper, isolate_));
       break;
     }
diff --git a/src/v8-counters.h b/src/v8-counters.h
index c1541b0..04f57f7 100644
--- a/src/v8-counters.h
+++ b/src/v8-counters.h
@@ -51,6 +51,7 @@
   HT(compile_lazy, V8.CompileLazy)
 
 #define HISTOGRAM_PERCENTAGE_LIST(HP)                                 \
+  /* Heap fragmentation. */                                           \
   HP(external_fragmentation_total,                                    \
      V8.MemoryExternalFragmentationTotal)                             \
   HP(external_fragmentation_old_pointer_space,                        \
@@ -67,12 +68,26 @@
      V8.MemoryExternalFragmentationPropertyCellSpace)                 \
   HP(external_fragmentation_lo_space,                                 \
      V8.MemoryExternalFragmentationLoSpace)                           \
+  /* Percentages of heap committed to each space. */                  \
+  HP(heap_fraction_new_space,                                         \
+     V8.MemoryHeapFractionNewSpace)                                   \
+  HP(heap_fraction_old_pointer_space,                                 \
+     V8.MemoryHeapFractionOldPointerSpace)                            \
+  HP(heap_fraction_old_data_space,                                    \
+     V8.MemoryHeapFractionOldDataSpace)                               \
+  HP(heap_fraction_code_space,                                        \
+     V8.MemoryHeapFractionCodeSpace)                                  \
   HP(heap_fraction_map_space,                                         \
      V8.MemoryHeapFractionMapSpace)                                   \
   HP(heap_fraction_cell_space,                                        \
      V8.MemoryHeapFractionCellSpace)                                  \
   HP(heap_fraction_property_cell_space,                               \
      V8.MemoryHeapFractionPropertyCellSpace)                          \
+  HP(heap_fraction_lo_space,                                          \
+     V8.MemoryHeapFractionLoSpace)                                    \
+  /* Percentage of crankshafted codegen. */                           \
+  HP(codegen_fraction_crankshaft,                                     \
+     V8.CodegenFractionCrankshaft)                                    \
 
 
 #define HISTOGRAM_MEMORY_LIST(HM)                                     \
@@ -84,6 +99,8 @@
      V8.MemoryHeapSampleCellSpaceCommitted)                           \
   HM(heap_sample_property_cell_space_committed,                       \
      V8.MemoryHeapSamplePropertyCellSpaceCommitted)                   \
+  HM(heap_sample_code_space_committed,                                \
+     V8.MemoryHeapSampleCodeSpaceCommitted)                           \
 
 
 // WARNING: STATS_COUNTER_LIST_* is a very large macro that is causing MSVC
diff --git a/src/version.cc b/src/version.cc
index a646938..1ec0ab0 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
 // system so their names cannot be changed without changing the scripts.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     22
-#define BUILD_NUMBER      11
+#define BUILD_NUMBER      12
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index 1bdfda9..7e6b63c 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -4226,9 +4226,15 @@
     STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
     STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
     __ testb(rbx, Immediate(kStringEncodingMask));
-    __ j(zero, &two_byte_slice, Label::kNear);
+    // Make long jumps when allocations tracking is on due to
+    // RecordObjectAllocation inside MacroAssembler::Allocate.
+    Label::Distance jump_distance =
+        masm->isolate()->heap_profiler()->is_tracking_allocations()
+        ? Label::kFar
+        : Label::kNear;
+    __ j(zero, &two_byte_slice, jump_distance);
     __ AllocateAsciiSlicedString(rax, rbx, r14, &runtime);
-    __ jmp(&set_slice_header, Label::kNear);
+    __ jmp(&set_slice_header, jump_distance);
     __ bind(&two_byte_slice);
     __ AllocateTwoByteSlicedString(rax, rbx, r14, &runtime);
     __ bind(&set_slice_header);
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index b301f29..b3336e6 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -4093,6 +4093,10 @@
   // Load address of new object into result.
   LoadAllocationTopHelper(result, scratch, flags);
 
+  if (isolate()->heap_profiler()->is_tracking_allocations()) {
+    RecordObjectAllocation(isolate(), result, object_size);
+  }
+
   // Align the next allocation. Storing the filler map without checking top is
   // safe in new-space because the limit of the heap is aligned there.
   if (((flags & DOUBLE_ALIGNMENT) != 0) && FLAG_debug_code) {
@@ -4172,6 +4176,10 @@
   // Load address of new object into result.
   LoadAllocationTopHelper(result, scratch, flags);
 
+  if (isolate()->heap_profiler()->is_tracking_allocations()) {
+    RecordObjectAllocation(isolate(), result, object_size);
+  }
+
   // Align the next allocation. Storing the filler map without checking top is
   // safe in new-space because the limit of the heap is aligned there.
   if (((flags & DOUBLE_ALIGNMENT) != 0) && FLAG_debug_code) {
@@ -4933,6 +4941,38 @@
 }
 
 
+void MacroAssembler::RecordObjectAllocation(Isolate* isolate,
+                                            Register object,
+                                            Register object_size) {
+  FrameScope frame(this, StackFrame::EXIT);
+  PushSafepointRegisters();
+  PrepareCallCFunction(3);
+  // In case object is rdx
+  movq(kScratchRegister, object);
+  movq(arg_reg_3, object_size);
+  movq(arg_reg_2, kScratchRegister);
+  movq(arg_reg_1, isolate, RelocInfo::EXTERNAL_REFERENCE);
+  CallCFunction(
+      ExternalReference::record_object_allocation_function(isolate), 3);
+  PopSafepointRegisters();
+}
+
+
+void MacroAssembler::RecordObjectAllocation(Isolate* isolate,
+                                            Register object,
+                                            int object_size) {
+  FrameScope frame(this, StackFrame::EXIT);
+  PushSafepointRegisters();
+  PrepareCallCFunction(3);
+  movq(arg_reg_2, object);
+  movq(arg_reg_3, Immediate(object_size));
+  movq(arg_reg_1, isolate, RelocInfo::EXTERNAL_REFERENCE);
+  CallCFunction(
+      ExternalReference::record_object_allocation_function(isolate), 3);
+  PopSafepointRegisters();
+}
+
+
 } }  // namespace v8::internal
 
 #endif  // V8_TARGET_ARCH_X64
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index 3d5a456..931a4eb 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -1115,6 +1115,15 @@
                 Label* gc_required,
                 AllocationFlags flags);
 
+  // Record a JS object allocation if allocations tracking mode is on.
+  void RecordObjectAllocation(Isolate* isolate,
+                              Register object,
+                              Register object_size);
+
+  void RecordObjectAllocation(Isolate* isolate,
+                              Register object,
+                              int object_size);
+
   // Undo allocation in new space. The object passed and objects allocated after
   // it will no longer be allocated. Make sure that no pointers are left to the
   // object(s) no longer allocated as they would be invalid when allocation is
diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp
index c8f6e57..fbe38f2 100644
--- a/test/cctest/cctest.gyp
+++ b/test/cctest/cctest.gyp
@@ -56,6 +56,7 @@
         'test-circular-queue.cc',
         'test-compiler.cc',
         'test-condition-variable.cc',
+        'test-constantpool.cc',
         'test-conversions.cc',
         'test-cpu.cc',
         'test-cpu-profiler.cc',
diff --git a/test/cctest/cctest.h b/test/cctest/cctest.h
index bc80039..7f84c25 100644
--- a/test/cctest/cctest.h
+++ b/test/cctest/cctest.h
@@ -348,4 +348,26 @@
 }
 
 
+// Helper class for new allocations tracking and checking.
+// To use checking of JS allocations tracking in a test,
+// just create an instance of this class.
+class HeapObjectsTracker {
+ public:
+  HeapObjectsTracker() {
+    heap_profiler_ = i::Isolate::Current()->heap_profiler();
+    CHECK_NE(NULL, heap_profiler_);
+    heap_profiler_->StartHeapAllocationsRecording();
+  }
+
+  ~HeapObjectsTracker() {
+    i::Isolate::Current()->heap()->CollectAllAvailableGarbage();
+    CHECK_EQ(0, heap_profiler_->FindUntrackedObjects());
+    heap_profiler_->StopHeapAllocationsRecording();
+  }
+
+ private:
+  i::HeapProfiler* heap_profiler_;
+};
+
+
 #endif  // ifndef CCTEST_H_
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 22e2077..ae6dbfa 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -14323,129 +14323,6 @@
 }
 
 
-class RegExpInterruptTest {
- public:
-  RegExpInterruptTest() : block_(0) {}
-  ~RegExpInterruptTest() {}
-  void RunTest() {
-    gc_count_ = 0;
-    gc_during_regexp_ = 0;
-    regexp_success_ = false;
-    gc_success_ = false;
-    GCThread gc_thread(this);
-    gc_thread.Start();
-    v8::Isolate* isolate = CcTest::isolate();
-    v8::Locker::StartPreemption(isolate, 1);
-
-    LongRunningRegExp();
-    {
-      v8::Unlocker unlock(isolate);
-      gc_thread.Join();
-    }
-    v8::Locker::StopPreemption(isolate);
-    CHECK(regexp_success_);
-    CHECK(gc_success_);
-  }
-
- private:
-  // Number of garbage collections required.
-  static const int kRequiredGCs = 5;
-
-  class GCThread : public i::Thread {
-   public:
-    explicit GCThread(RegExpInterruptTest* test)
-        : Thread("GCThread"), test_(test) {}
-    virtual void Run() {
-      test_->CollectGarbage();
-    }
-   private:
-     RegExpInterruptTest* test_;
-  };
-
-  void CollectGarbage() {
-    block_.Wait();
-    while (gc_during_regexp_ < kRequiredGCs) {
-      {
-        v8::Locker lock(CcTest::isolate());
-        v8::Isolate::Scope isolate_scope(CcTest::isolate());
-        // TODO(lrn): Perhaps create some garbage before collecting.
-        CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
-        gc_count_++;
-      }
-      i::OS::Sleep(1);
-    }
-    gc_success_ = true;
-  }
-
-  void LongRunningRegExp() {
-    block_.Signal();  // Enable garbage collection thread on next preemption.
-    int rounds = 0;
-    while (gc_during_regexp_ < kRequiredGCs) {
-      int gc_before = gc_count_;
-      {
-        // Match 15-30 "a"'s against 14 and a "b".
-        const char* c_source =
-            "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
-            ".exec('aaaaaaaaaaaaaaab') === null";
-        Local<String> source = String::New(c_source);
-        Local<Script> script = Script::Compile(source);
-        Local<Value> result = script->Run();
-        if (!result->BooleanValue()) {
-          gc_during_regexp_ = kRequiredGCs;  // Allow gc thread to exit.
-          return;
-        }
-      }
-      {
-        // Match 15-30 "a"'s against 15 and a "b".
-        const char* c_source =
-            "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
-            ".exec('aaaaaaaaaaaaaaaab')[0] === 'aaaaaaaaaaaaaaaa'";
-        Local<String> source = String::New(c_source);
-        Local<Script> script = Script::Compile(source);
-        Local<Value> result = script->Run();
-        if (!result->BooleanValue()) {
-          gc_during_regexp_ = kRequiredGCs;
-          return;
-        }
-      }
-      int gc_after = gc_count_;
-      gc_during_regexp_ += gc_after - gc_before;
-      rounds++;
-      i::OS::Sleep(1);
-    }
-    regexp_success_ = true;
-  }
-
-  i::Semaphore block_;
-  int gc_count_;
-  int gc_during_regexp_;
-  bool regexp_success_;
-  bool gc_success_;
-};
-
-
-// Test that a regular expression execution can be interrupted and
-// survive a garbage collection.
-TEST(RegExpInterruption) {
-  v8::Locker lock(CcTest::isolate());
-  v8::HandleScope scope(CcTest::isolate());
-  Local<Context> local_env;
-  {
-    LocalContext env;
-    local_env = env.local();
-  }
-
-  // Local context should still be live.
-  CHECK(!local_env.IsEmpty());
-  local_env->Enter();
-
-  // Should complete without problems.
-  RegExpInterruptTest().RunTest();
-
-  local_env->Exit();
-}
-
-
 class ApplyInterruptTest {
  public:
   ApplyInterruptTest() : block_(0) {}
@@ -14735,142 +14612,73 @@
 }
 
 
-class RegExpStringModificationTest {
+struct RegExpInterruptionData {
+  int loop_count;
+  UC16VectorResource* string_resource;
+  v8::Persistent<v8::String> string;
+} regexp_interruption_data;
+
+
+class RegExpInterruptionThread : public i::Thread {
  public:
-  RegExpStringModificationTest()
-      : block_(0),
-        morphs_(0),
-        morphs_during_regexp_(0),
-        ascii_resource_(i::Vector<const char>("aaaaaaaaaaaaaab", 15)),
-        uc16_resource_(i::Vector<const uint16_t>(two_byte_content_, 15)) {}
-  ~RegExpStringModificationTest() {}
-  void RunTest() {
-    v8::Isolate* isolate = CcTest::isolate();
-    i::Factory* factory = CcTest::i_isolate()->factory();
+  explicit RegExpInterruptionThread(v8::Isolate* isolate)
+      : Thread("TimeoutThread"), isolate_(isolate) {}
 
-    regexp_success_ = false;
-    morph_success_ = false;
-
-    // Initialize the contents of two_byte_content_ to be a uc16 representation
-    // of "aaaaaaaaaaaaaab".
-    for (int i = 0; i < 14; i++) {
-      two_byte_content_[i] = 'a';
+  virtual void Run() {
+    for (regexp_interruption_data.loop_count = 0;
+         regexp_interruption_data.loop_count < 7;
+         regexp_interruption_data.loop_count++) {
+      i::OS::Sleep(50);  // Wait a bit before requesting GC.
+      reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
     }
-    two_byte_content_[14] = 'b';
-
-    // Create the input string for the regexp - the one we are going to change
-    // properties of.
-    input_ = factory->NewExternalStringFromAscii(&ascii_resource_);
-
-    // Inject the input as a global variable.
-    i::Handle<i::String> input_name =
-        factory->NewStringFromAscii(i::Vector<const char>("input", 5));
-    i::JSReceiver::SetProperty(
-        i::handle(CcTest::i_isolate()->native_context()->global_object()),
-        input_name,
-        input_,
-        NONE,
-        i::kNonStrictMode);
-
-    MorphThread morph_thread(this);
-    morph_thread.Start();
-    v8::Locker::StartPreemption(isolate, 1);
-    LongRunningRegExp();
-    {
-      v8::Unlocker unlock(isolate);
-      morph_thread.Join();
-    }
-    v8::Locker::StopPreemption(isolate);
-    CHECK(regexp_success_);
-    CHECK(morph_success_);
+    i::OS::Sleep(50);  // Wait a bit before terminating.
+    v8::V8::TerminateExecution(isolate_);
   }
 
  private:
-  // Number of string modifications required.
-  static const int kRequiredModifications = 5;
-  static const int kMaxModifications = 100;
-
-  class MorphThread : public i::Thread {
-   public:
-    explicit MorphThread(RegExpStringModificationTest* test)
-        : Thread("MorphThread"), test_(test) {}
-    virtual void Run() {
-      test_->MorphString();
-    }
-   private:
-     RegExpStringModificationTest* test_;
-  };
-
-  void MorphString() {
-    block_.Wait();
-    while (morphs_during_regexp_ < kRequiredModifications &&
-           morphs_ < kMaxModifications) {
-      {
-        v8::Locker lock(CcTest::isolate());
-        v8::Isolate::Scope isolate_scope(CcTest::isolate());
-        // Swap string between ascii and two-byte representation.
-        i::String* string = *input_;
-        MorphAString(string, &ascii_resource_, &uc16_resource_);
-        morphs_++;
-      }
-      i::OS::Sleep(1);
-    }
-    morph_success_ = true;
-  }
-
-  void LongRunningRegExp() {
-    block_.Signal();  // Enable morphing thread on next preemption.
-    while (morphs_during_regexp_ < kRequiredModifications &&
-           morphs_ < kMaxModifications) {
-      int morphs_before = morphs_;
-      {
-        v8::HandleScope scope(CcTest::isolate());
-        // Match 15-30 "a"'s against 14 and a "b".
-        const char* c_source =
-            "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
-            ".exec(input) === null";
-        Local<String> source = String::New(c_source);
-        Local<Script> script = Script::Compile(source);
-        Local<Value> result = script->Run();
-        CHECK(result->IsTrue());
-      }
-      int morphs_after = morphs_;
-      morphs_during_regexp_ += morphs_after - morphs_before;
-    }
-    regexp_success_ = true;
-  }
-
-  i::uc16 two_byte_content_[15];
-  i::Semaphore block_;
-  int morphs_;
-  int morphs_during_regexp_;
-  bool regexp_success_;
-  bool morph_success_;
-  i::Handle<i::String> input_;
-  AsciiVectorResource ascii_resource_;
-  UC16VectorResource uc16_resource_;
+  v8::Isolate* isolate_;
 };
 
 
-// Test that a regular expression execution can be interrupted and
-// the string changed without failing.
-TEST(RegExpStringModification) {
-  v8::Locker lock(CcTest::isolate());
+void RunBeforeGC(v8::GCType type, v8::GCCallbackFlags flags) {
+  if (regexp_interruption_data.loop_count != 2) return;
   v8::HandleScope scope(CcTest::isolate());
-  Local<Context> local_env;
-  {
-    LocalContext env;
-    local_env = env.local();
-  }
+  v8::Local<v8::String> string = v8::Local<v8::String>::New(
+      CcTest::isolate(), regexp_interruption_data.string);
+  string->MakeExternal(regexp_interruption_data.string_resource);
+}
 
-  // Local context should still be live.
-  CHECK(!local_env.IsEmpty());
-  local_env->Enter();
 
-  // Should complete without problems.
-  RegExpStringModificationTest().RunTest();
+// Test that RegExp execution can be interrupted.  Specifically, we test
+// * interrupting with GC
+// * turn the subject string from one-byte internal to two-byte external string
+// * force termination
+TEST(RegExpInterruption) {
+  v8::HandleScope scope(CcTest::isolate());
+  LocalContext env;
 
-  local_env->Exit();
+  RegExpInterruptionThread timeout_thread(CcTest::isolate());
+
+  v8::V8::AddGCPrologueCallback(RunBeforeGC);
+  static const char* ascii_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+  i::uc16* uc16_content = AsciiToTwoByteString(ascii_content);
+  v8::Local<v8::String> string = v8_str(ascii_content);
+
+  CcTest::global()->Set(v8_str("a"), string);
+  regexp_interruption_data.string.Reset(CcTest::isolate(), string);
+  regexp_interruption_data.string_resource = new UC16VectorResource(
+      i::Vector<const i::uc16>(uc16_content, i::StrLength(ascii_content)));
+
+  v8::TryCatch try_catch;
+  timeout_thread.Start();
+
+  CompileRun("/((a*)*)*b/.exec(a)");
+  CHECK(try_catch.HasTerminated());
+
+  timeout_thread.Join();
+
+  delete regexp_interruption_data.string_resource;
+  regexp_interruption_data.string.Dispose();
 }
 
 
diff --git a/test/cctest/test-ast.cc b/test/cctest/test-ast.cc
index 36766cb..299f2a8 100644
--- a/test/cctest/test-ast.cc
+++ b/test/cctest/test-ast.cc
@@ -42,7 +42,7 @@
   Isolate* isolate = CcTest::i_isolate();
   Zone zone(isolate);
   AstNodeFactory<AstNullVisitor> factory(isolate, &zone);
-  AstNode* node = factory.NewEmptyStatement();
+  AstNode* node = factory.NewEmptyStatement(RelocInfo::kNoPosition);
   list->Add(node);
   CHECK_EQ(1, list->length());
   CHECK_EQ(node, list->at(0));
diff --git a/test/cctest/test-constantpool.cc b/test/cctest/test-constantpool.cc
new file mode 100644
index 0000000..9f2436c
--- /dev/null
+++ b/test/cctest/test-constantpool.cc
@@ -0,0 +1,50 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+
+// Test constant pool array code.
+
+#include "v8.h"
+
+#include "factory.h"
+#include "objects.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+
+TEST(ConstantPool) {
+  LocalContext context;
+  Isolate* isolate = CcTest::i_isolate();
+  Heap* heap = isolate->heap();
+  Factory* factory = isolate->factory();
+  v8::HandleScope scope(context->GetIsolate());
+
+  // Check construction.
+  Handle<ConstantPoolArray> array = factory->NewConstantPoolArray(3, 2, 1);
+  CHECK_EQ(array->count_of_int64_entries(), 3);
+  CHECK_EQ(array->count_of_ptr_entries(), 2);
+  CHECK_EQ(array->count_of_int32_entries(), 1);
+  CHECK_EQ(array->length(), 6);
+  CHECK_EQ(array->first_int64_index(), 0);
+  CHECK_EQ(array->first_ptr_index(), 3);
+  CHECK_EQ(array->first_int32_index(), 5);
+
+  // Check getters and setters.
+  int64_t big_number = V8_2PART_UINT64_C(0x12345678, 9ABCDEF0);
+  Handle<Object> object = factory->NewHeapNumber(4.0);
+  array->set(0, big_number);
+  array->set(1, 0.5);
+  array->set(3, *object);
+  array->set(5, 50);
+  CHECK_EQ(array->get_int64_entry(0), big_number);
+  CHECK_EQ(array->get_int64_entry_as_double(1), 0.5);
+  CHECK_EQ(array->get_ptr_entry(3), *object);
+  CHECK_EQ(array->get_int32_entry(5), 50);
+
+  // Check pointers are updated on GC.
+  Object* old_ptr = array->get_ptr_entry(3);
+  CHECK_EQ(*object, old_ptr);
+  heap->CollectGarbage(NEW_SPACE);
+  Object* new_ptr = array->get_ptr_entry(3);
+  CHECK_NE(*object, old_ptr);
+  CHECK_EQ(*object, new_ptr);
+}
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index d24f28e..1bd1dc3 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -2850,7 +2850,7 @@
   foo->Call(env->Global(), kArgc, args);
 
   // With stepping all break locations are hit.
-  CHECK_EQ(34, break_point_hit_count);
+  CHECK_EQ(35, break_point_hit_count);
 
   v8::Debug::SetDebugEventListener2(NULL);
   CheckDebuggerUnloaded();
@@ -2897,7 +2897,7 @@
   foo->Call(env->Global(), kArgc, args);
 
   // With stepping all break locations are hit.
-  CHECK_EQ(33, break_point_hit_count);
+  CHECK_EQ(34, break_point_hit_count);
 
   v8::Debug::SetDebugEventListener2(NULL);
   CheckDebuggerUnloaded();
@@ -2941,7 +2941,7 @@
   foo->Call(env->Global(), 0, NULL);
 
   // With stepping all break locations are hit.
-  CHECK_EQ(54, break_point_hit_count);
+  CHECK_EQ(55, break_point_hit_count);
 
   v8::Debug::SetDebugEventListener2(NULL);
   CheckDebuggerUnloaded();
@@ -2985,7 +2985,7 @@
 
 // Test of the stepping mechanism for named load in a loop.
 TEST(DebugStepNamedStoreLoop) {
-  DoDebugStepNamedStoreLoop(23);
+  DoDebugStepNamedStoreLoop(24);
 }
 
 
@@ -3358,7 +3358,7 @@
   v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(10) };
   result = foo->Call(env->Global(), argc, argv_10);
   CHECK_EQ(5, result->Int32Value());
-  CHECK_EQ(51, break_point_hit_count);
+  CHECK_EQ(52, break_point_hit_count);
 
   // Looping 100 times.
   step_action = StepIn;
@@ -3366,7 +3366,7 @@
   v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(100) };
   result = foo->Call(env->Global(), argc, argv_100);
   CHECK_EQ(50, result->Int32Value());
-  CHECK_EQ(456, break_point_hit_count);
+  CHECK_EQ(457, break_point_hit_count);
 
   // Get rid of the debug event listener.
   v8::Debug::SetDebugEventListener2(NULL);
@@ -3410,7 +3410,7 @@
   v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(10) };
   result = foo->Call(env->Global(), argc, argv_10);
   CHECK_EQ(9, result->Int32Value());
-  CHECK_EQ(54, break_point_hit_count);
+  CHECK_EQ(55, break_point_hit_count);
 
   // Looping 100 times.
   step_action = StepIn;
@@ -3418,7 +3418,7 @@
   v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(100) };
   result = foo->Call(env->Global(), argc, argv_100);
   CHECK_EQ(99, result->Int32Value());
-  CHECK_EQ(504, break_point_hit_count);
+  CHECK_EQ(505, break_point_hit_count);
 
   // Get rid of the debug event listener.
   v8::Debug::SetDebugEventListener2(NULL);
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index 59f7a25..6b45296 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -2005,3 +2005,19 @@
       GetProperty(foo_func, v8::HeapGraphEdge::kInternal, "code");
   CHECK_NE(NULL, code);
 }
+
+
+// This is an example of using checking of JS allocations tracking in a test.
+TEST(HeapObjectsTracker) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  HeapObjectsTracker tracker;
+  CompileRun("var a = 1.2");
+  CompileRun("var a = 1.2; var b = 1.0; var c = 1.0;");
+  CompileRun(
+    "var a = [];"
+    "for (var i = 0; i < 5; ++i)"
+    "    a[i] = i;\n"
+    "for (var i = 0; i < 3; ++i)"
+    "    a.shift();\n");
+}
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index f84b8ad..04e64cf 100644
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -264,12 +264,11 @@
     i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
     scanner.Initialize(&stream);
 
-    v8::preparser::PreParser preparser(&scanner, &log, stack_limit);
+    i::PreParser preparser(&scanner, &log, stack_limit);
     preparser.set_allow_lazy(true);
     preparser.set_allow_natives_syntax(true);
-    v8::preparser::PreParser::PreParseResult result =
-        preparser.PreParseProgram();
-    CHECK_EQ(v8::preparser::PreParser::kPreParseSuccess, result);
+    i::PreParser::PreParseResult result = preparser.PreParseProgram();
+    CHECK_EQ(i::PreParser::kPreParseSuccess, result);
     i::ScriptDataImpl data(log.ExtractData());
     CHECK(!data.has_error());
   }
@@ -300,11 +299,10 @@
     scanner.Initialize(&stream);
 
     // Preparser defaults to disallowing natives syntax.
-    v8::preparser::PreParser preparser(&scanner, &log, stack_limit);
+    i::PreParser preparser(&scanner, &log, stack_limit);
     preparser.set_allow_lazy(true);
-    v8::preparser::PreParser::PreParseResult result =
-        preparser.PreParseProgram();
-    CHECK_EQ(v8::preparser::PreParser::kPreParseSuccess, result);
+    i::PreParser::PreParseResult result = preparser.PreParseProgram();
+    CHECK_EQ(i::PreParser::kPreParseSuccess, result);
     i::ScriptDataImpl data(log.ExtractData());
     // Data contains syntax error.
     CHECK(data.has_error());
@@ -402,11 +400,10 @@
   i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
   scanner.Initialize(&stream);
 
-  v8::preparser::PreParser preparser(&scanner, &log, stack_limit);
+  i::PreParser preparser(&scanner, &log, stack_limit);
   preparser.set_allow_lazy(true);
-  v8::preparser::PreParser::PreParseResult result =
-      preparser.PreParseProgram();
-  CHECK_EQ(v8::preparser::PreParser::kPreParseStackOverflow, result);
+  i::PreParser::PreParseResult result = preparser.PreParseProgram();
+  CHECK_EQ(i::PreParser::kPreParseStackOverflow, result);
 }
 
 
@@ -1121,12 +1118,11 @@
   {
     i::Scanner scanner(isolate->unicode_cache());
     i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
-    v8::preparser::PreParser preparser(&scanner, &log, stack_limit);
+    i::PreParser preparser(&scanner, &log, stack_limit);
     SET_PARSER_FLAGS(preparser, flags);
     scanner.Initialize(&stream);
-    v8::preparser::PreParser::PreParseResult result =
-        preparser.PreParseProgram();
-    CHECK_EQ(v8::preparser::PreParser::kPreParseSuccess, result);
+    i::PreParser::PreParseResult result = preparser.PreParseProgram();
+    CHECK_EQ(i::PreParser::kPreParseSuccess, result);
   }
   i::ScriptDataImpl data(log.ExtractData());
 
diff --git a/test/cctest/test-types.cc b/test/cctest/test-types.cc
index 823af0b..264d2ed 100644
--- a/test/cctest/test-types.cc
+++ b/test/cctest/test-types.cc
@@ -318,6 +318,11 @@
   CheckUnordered(T.Array, T.Function);
 
   // Structured subtyping
+  CheckSub(T.None, T.ObjectClass);
+  CheckSub(T.None, T.ObjectConstant1);
+  CheckSub(T.ObjectClass, T.Any);
+  CheckSub(T.ObjectConstant1, T.Any);
+
   CheckSub(T.ObjectClass, T.Object);
   CheckSub(T.ArrayClass, T.Object);
   CheckUnordered(T.ObjectClass, T.ArrayClass);
@@ -384,6 +389,9 @@
   CheckDisjoint(T.Object, T.Proxy);
   CheckDisjoint(T.Array, T.Function);
 
+  CheckOverlap(T.ObjectClass, T.Any);
+  CheckOverlap(T.ObjectConstant1, T.Any);
+
   CheckOverlap(T.ObjectClass, T.Object);
   CheckOverlap(T.ArrayClass, T.Object);
   CheckOverlap(T.ObjectClass, T.ObjectClass);
@@ -432,6 +440,8 @@
   CHECK(IsUnion(Type::Union(T.ObjectClass, T.ArrayClass)));
 
   CheckEqual(T.Union(T.ObjectClass, T.ObjectClass), T.ObjectClass);
+  CheckSub(T.None, T.Union(T.ObjectClass, T.ArrayClass));
+  CheckSub(T.Union(T.ObjectClass, T.ArrayClass), T.Any);
   CheckSub(T.ObjectClass, T.Union(T.ObjectClass, T.ArrayClass));
   CheckSub(T.ArrayClass, T.Union(T.ObjectClass, T.ArrayClass));
   CheckSub(T.Union(T.ObjectClass, T.ArrayClass), T.Object);
@@ -447,6 +457,8 @@
   CheckEqual(T.Union(T.ObjectConstant1, T.ObjectConstant1), T.ObjectConstant1);
   CheckEqual(T.Union(T.ArrayConstant1, T.ArrayConstant1), T.ArrayConstant1);
   CheckEqual(T.Union(T.ArrayConstant1, T.ArrayConstant1), T.ArrayConstant2);
+  CheckSub(T.None, T.Union(T.ObjectConstant1, T.ObjectConstant2));
+  CheckSub(T.Union(T.ObjectConstant1, T.ObjectConstant2), T.Any);
   CheckSub(T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2));
   CheckSub(T.ObjectConstant2, T.Union(T.ObjectConstant1, T.ObjectConstant2));
   CheckSub(T.ArrayConstant2, T.Union(T.ArrayConstant1, T.ObjectConstant2));
@@ -463,6 +475,7 @@
   CHECK(IsUnion(Type::Union(T.ObjectClass, T.Number)));
 
   CheckEqual(T.Union(T.ObjectClass, T.Object), T.Object);
+  CheckSub(T.None, T.Union(T.ObjectClass, T.Number));
   CheckSub(T.Union(T.ObjectClass, T.Number), T.Any);
   CheckSub(T.Union(T.ObjectClass, T.Smi), T.Union(T.Object, T.Number));
   CheckSub(T.Union(T.ObjectClass, T.Array), T.Object);
@@ -477,6 +490,7 @@
 
   CheckEqual(T.Union(T.SmiConstant, T.Number), T.Number);
   CheckEqual(T.Union(T.ObjectConstant1, T.Object), T.Object);
+  CheckSub(T.None, T.Union(T.ObjectConstant1, T.Number));
   CheckSub(T.Union(T.ObjectConstant1, T.Number), T.Any);
   CheckSub(T.Union(T.ObjectConstant1, T.Signed32), T.Union(T.Object, T.Number));
   CheckSub(T.Union(T.ObjectConstant1, T.Array), T.Object);
@@ -489,6 +503,8 @@
   CHECK(IsUnion(Type::Union(T.ObjectConstant1, T.ObjectClass)));
   CHECK(IsUnion(Type::Union(T.ArrayClass, T.ObjectConstant2)));
 
+  CheckSub(T.None, T.Union(T.ObjectConstant1, T.ArrayClass));
+  CheckSub(T.Union(T.ObjectConstant1, T.ArrayClass), T.Any);
   CheckSub(T.Union(T.ObjectConstant1, T.ArrayClass), T.Object);
   CheckSub(T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ArrayClass));
   CheckSub(T.ArrayClass, T.Union(T.ObjectConstant1, T.ArrayClass));
@@ -518,6 +534,9 @@
       T.ObjectConstant1,
       T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Double));
   CheckSub(
+      T.None,
+      T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Double));
+  CheckSub(
       T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Double),
       T.Any);
   CheckSub(
@@ -534,6 +553,12 @@
       T.Union(T.ObjectClass, T.Union(T.ObjectConstant1, T.ObjectClass)),
       T.Union(T.ObjectClass, T.ObjectConstant1));
   CheckSub(
+      T.None,
+      T.Union(T.ObjectClass, T.Union(T.ObjectConstant1, T.ObjectClass)));
+  CheckSub(
+      T.Union(T.ObjectClass, T.Union(T.ObjectConstant1, T.ObjectClass)),
+      T.Any);
+  CheckSub(
       T.Union(T.ObjectClass, T.Union(T.ObjectConstant1, T.ObjectClass)),
       T.Object);
   CheckEqual(
diff --git a/test/mjsunit/parallel-invalidate-transition-map.js b/test/mjsunit/compiler/concurrent-invalidate-transition-map.js
similarity index 86%
rename from test/mjsunit/parallel-invalidate-transition-map.js
rename to test/mjsunit/compiler/concurrent-invalidate-transition-map.js
index 9a5d310..699534f 100644
--- a/test/mjsunit/parallel-invalidate-transition-map.js
+++ b/test/mjsunit/compiler/concurrent-invalidate-transition-map.js
@@ -26,7 +26,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --track-fields --track-double-fields --allow-natives-syntax
-// Flags: --concurrent-recompilation --concurrent-recompilation-delay=100
+// Flags: --concurrent-recompilation --block-concurrent-recompilation
 
 if (!%IsConcurrentRecompilationSupported()) {
   print("Concurrent recompilation is disabled. Skipping this test.");
@@ -49,9 +49,13 @@
 %OptimizeFunctionOnNextCall(add_field, "concurrent");
 
 var o = new_object();
-// Trigger optimization in the background thread.
+// Kick off recompilation.
 add_field(o);
-// Invalidate transition map while optimization is underway.
+// Invalidate transition map after compile graph has been created.
 o.c = 2.2;
+// In the mean time, concurrent recompiling is still blocked.
+assertUnoptimized(add_field, "no sync");
+// Let concurrent recompilation proceed.
+%UnblockConcurrentRecompilation();
 // Sync with background thread to conclude optimization that bailed out.
 assertUnoptimized(add_field, "sync");
diff --git a/test/mjsunit/compiler/parallel-proto-change.js b/test/mjsunit/compiler/concurrent-proto-change.js
similarity index 87%
rename from test/mjsunit/compiler/parallel-proto-change.js
rename to test/mjsunit/compiler/concurrent-proto-change.js
index 7602279..e126465 100644
--- a/test/mjsunit/compiler/parallel-proto-change.js
+++ b/test/mjsunit/compiler/concurrent-proto-change.js
@@ -26,7 +26,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --allow-natives-syntax
-// Flags: --concurrent-recompilation --concurrent-recompilation-delay=50
+// Flags: --concurrent-recompilation --block-concurrent-recompilation
 
 if (!%IsConcurrentRecompilationSupported()) {
   print("Concurrent recompilation is disabled. Skipping this test.");
@@ -43,12 +43,14 @@
 
 // Mark for concurrent optimization.
 %OptimizeFunctionOnNextCall(f, "concurrent");
-// Trigger optimization in the background thread.
+// Kick off recompilation.
 assertEquals(1, f(o));
-// While concurrent recompilation is running, optimization not yet done.
-assertUnoptimized(f, "no sync");
-// Change the prototype chain during optimization to trigger map invalidation.
+// Change the prototype chain after compile graph has been created.
 o.__proto__.__proto__ = { bar: function() { return 2; } };
+// At this point, concurrent recompilation thread has not yet done its job.
+assertUnoptimized(f, "no sync");
+// Let the background thread proceed.
+%UnblockConcurrentRecompilation();
 // Optimization eventually bails out due to map dependency.
 assertUnoptimized(f, "sync");
 assertEquals(2, f(o));
diff --git a/test/mjsunit/manual-parallel-recompile.js b/test/mjsunit/compiler/manual-concurrent-recompile.js
similarity index 87%
rename from test/mjsunit/manual-parallel-recompile.js
rename to test/mjsunit/compiler/manual-concurrent-recompile.js
index 0a0e61d..b2b6398 100644
--- a/test/mjsunit/manual-parallel-recompile.js
+++ b/test/mjsunit/compiler/manual-concurrent-recompile.js
@@ -26,7 +26,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --allow-natives-syntax --expose-gc
-// Flags: --concurrent-recompilation --concurrent-recompilation-delay=50
+// Flags: --concurrent-recompilation --block-concurrent-recompilation
 
 if (!%IsConcurrentRecompilationSupported()) {
   print("Concurrent recompilation is disabled. Skipping this test.");
@@ -55,10 +55,13 @@
 
 %OptimizeFunctionOnNextCall(f, "concurrent");
 %OptimizeFunctionOnNextCall(g, "concurrent");
-f(g(2));  // Trigger optimization.
+f(g(2));  // Kick off recompilation.
 
-assertUnoptimized(f, "no sync");  // Not yet optimized while background thread
-assertUnoptimized(g, "no sync");  // is running.
+assertUnoptimized(f, "no sync");  // Not yet optimized since recompilation
+assertUnoptimized(g, "no sync");  // is still blocked.
+
+// Let concurrent recompilation proceed.
+%UnblockConcurrentRecompilation();
 
 assertOptimized(f, "sync");  // Optimized once we sync with the
 assertOptimized(g, "sync");  // background thread.
diff --git a/test/mjsunit/parallel-initial-prototype-change.js b/test/mjsunit/concurrent-initial-prototype-change.js
similarity index 86%
rename from test/mjsunit/parallel-initial-prototype-change.js
rename to test/mjsunit/concurrent-initial-prototype-change.js
index 625b590..d5b1b99 100644
--- a/test/mjsunit/parallel-initial-prototype-change.js
+++ b/test/mjsunit/concurrent-initial-prototype-change.js
@@ -26,7 +26,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --allow-natives-syntax
-// Flags: --concurrent-recompilation --concurrent-recompilation-delay=100
+// Flags: --concurrent-recompilation --block-concurrent-recompilation
 
 if (!%IsConcurrentRecompilationSupported()) {
   print("Concurrent recompilation is disabled. Skipping this test.");
@@ -43,12 +43,15 @@
 
 // Optimized code of f1 depends on initial object and array maps.
 %OptimizeFunctionOnNextCall(f1, "concurrent");
-// Trigger optimization in the background thread
+// Kick off recompilation;
 assertEquals(0.5, f1(arr, 0));
-Object.prototype[1] = 1.5;  // Invalidate current initial object map.
+// Invalidate current initial object map after compile graph has been created.
+Object.prototype[1] = 1.5;
 assertEquals(2, f1(arr, 1));
-// Not yet optimized while background thread is running.
+// Not yet optimized since concurrent recompilation is blocked.
 assertUnoptimized(f1, "no sync");
+// Let concurrent recompilation proceed.
+%UnblockConcurrentRecompilation();
 // Sync with background thread to conclude optimization, which bails out
 // due to map dependency.
 assertUnoptimized(f1, "sync");
diff --git a/test/mjsunit/regress/regress-embedded-cons-string.js b/test/mjsunit/regress/regress-embedded-cons-string.js
index 32b900b..b08a942 100644
--- a/test/mjsunit/regress/regress-embedded-cons-string.js
+++ b/test/mjsunit/regress/regress-embedded-cons-string.js
@@ -27,7 +27,7 @@
 
 // Flags: --fold-constants --nodead-code-elimination
 // Flags: --expose-gc --allow-natives-syntax
-// Flags: --concurrent-recompilation --concurrent-recompilation-delay=600
+// Flags: --concurrent-recompilation --block-concurrent-recompilation
 
 if (!%IsConcurrentRecompilationSupported()) {
   print("Concurrent recompilation is disabled. Skipping this test.");
@@ -39,12 +39,14 @@
   fun();
   // Mark for concurrent optimization.
   %OptimizeFunctionOnNextCall(fun, "concurrent");
-  //Trigger optimization in the background.
+  // Kick off recompilation.
   fun();
-  //Tenure cons string.
+  // Tenure cons string after compile graph has been created.
   gc();
-  // In the mean time, concurrent recompiling is not complete yet.
+  // In the mean time, concurrent recompiling is still blocked.
   assertUnoptimized(fun, "no sync");
+  // Let concurrent recompilation proceed.
+  %UnblockConcurrentRecompilation();
   // Concurrent recompilation eventually finishes, embeds tenured cons string.
   assertOptimized(fun, "sync");
   // Visit embedded cons string during mark compact.
diff --git a/test/mjsunit/regress/regress-opt-after-debug-deopt.js b/test/mjsunit/regress/regress-opt-after-debug-deopt.js
index 8bf95ec..c637be5 100644
--- a/test/mjsunit/regress/regress-opt-after-debug-deopt.js
+++ b/test/mjsunit/regress/regress-opt-after-debug-deopt.js
@@ -26,7 +26,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --expose-debug-as debug --allow-natives-syntax
-// Flags: --concurrent-recompilation --concurrent-recompilation-delay=100
+// Flags: --concurrent-recompilation --block-concurrent-recompilation
 
 if (!%IsConcurrentRecompilationSupported()) {
   print("Concurrent recompilation is disabled. Skipping this test.");
@@ -60,8 +60,14 @@
 %OptimizeFunctionOnNextCall(f, "concurrent");  // Mark with builtin.
 f();                           // Kick off concurrent recompilation.
 
+// After compile graph has been created...
 Debug.setListener(listener);   // Activate debugger.
 Debug.setBreakPoint(f, 2, 0);  // Force deopt.
+
+// At this point, concurrent recompilation is still being blocked.
+assertUnoptimized(f, "no sync");
+// Let concurrent recompilation proceed.
+%UnblockConcurrentRecompilation();
 // Sync with optimization thread.  But no optimized code is installed.
 assertUnoptimized(f, "sync");
 
diff --git a/test/mjsunit/regress/regress-prepare-break-while-recompile.js b/test/mjsunit/regress/regress-prepare-break-while-recompile.js
index 2fad5ca..a9c20ec 100644
--- a/test/mjsunit/regress/regress-prepare-break-while-recompile.js
+++ b/test/mjsunit/regress/regress-prepare-break-while-recompile.js
@@ -26,7 +26,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --expose-debug-as debug --allow-natives-syntax
-// Flags: --concurrent-recompilation-delay=300
+// Flags: --block-concurrent-recompilation
 
 if (!%IsConcurrentRecompilationSupported()) {
   print("Concurrent recompilation is disabled. Skipping this test.");
@@ -46,17 +46,22 @@
 }
 
 foo();
-// Mark and trigger concurrent optimization.
+// Mark and kick off recompilation.
 %OptimizeFunctionOnNextCall(foo, "concurrent");
 foo();
 
 // Set break points on an unrelated function. This clears both optimized
 // and (shared) unoptimized code on foo, and sets both to lazy-compile builtin.
 // Clear the break point immediately after to deactivate the debugger.
+// Do all of this after compile graph has been created.
 Debug.setBreakPoint(bar, 0, 0);
 Debug.clearAllBreakPoints();
 
+// At this point, concurrent recompilation is still blocked.
+assertUnoptimized(foo, "no sync");
+// Let concurrent recompilation proceed.
+%UnblockConcurrentRecompilation();
+
 // Install optimized code when concurrent optimization finishes.
 // This needs to be able to deal with shared code being a builtin.
 assertUnoptimized(foo, "sync");
-
diff --git a/tools/gen-postmortem-metadata.py b/tools/gen-postmortem-metadata.py
index 0acb658..2837727 100644
--- a/tools/gen-postmortem-metadata.py
+++ b/tools/gen-postmortem-metadata.py
@@ -68,6 +68,7 @@
     { 'name': 'SeqStringTag',           'value': 'kSeqStringTag' },
     { 'name': 'ConsStringTag',          'value': 'kConsStringTag' },
     { 'name': 'ExternalStringTag',      'value': 'kExternalStringTag' },
+    { 'name': 'SlicedStringTag',        'value': 'kSlicedStringTag' },
 
     { 'name': 'FailureTag',             'value': 'kFailureTag' },
     { 'name': 'FailureTagMask',         'value': 'kFailureTagMask' },
@@ -88,6 +89,15 @@
     { 'name': 'prop_type_mask',
         'value': 'PropertyDetails::TypeField::kMask' },
 
+    { 'name': 'prop_desc_key',
+        'value': 'DescriptorArray::kDescriptorKey' },
+    { 'name': 'prop_desc_details',
+        'value': 'DescriptorArray::kDescriptorDetails' },
+    { 'name': 'prop_desc_value',
+        'value': 'DescriptorArray::kDescriptorValue' },
+    { 'name': 'prop_desc_size',
+        'value': 'DescriptorArray::kDescriptorSize' },
+
     { 'name': 'off_fp_context',
         'value': 'StandardFrameConstants::kContextOffset' },
     { 'name': 'off_fp_marker',
@@ -113,7 +123,9 @@
     'ConsString, second, String, kSecondOffset',
     'ExternalString, resource, Object, kResourceOffset',
     'SeqOneByteString, chars, char, kHeaderSize',
+    'SeqTwoByteString, chars, char, kHeaderSize',
     'SharedFunctionInfo, code, Code, kCodeOffset',
+    'SlicedString, parent, String, kParentOffset',
     'Code, instruction_start, uintptr_t, kHeaderSize',
     'Code, instruction_size, int, kInstructionSizeOffset',
 ];
diff --git a/tools/v8heapconst.py b/tools/v8heapconst.py
index 1f72c37..06141c2 100644
--- a/tools/v8heapconst.py
+++ b/tools/v8heapconst.py
@@ -71,53 +71,54 @@
   144: "EXTERNAL_FLOAT_ARRAY_TYPE",
   145: "EXTERNAL_DOUBLE_ARRAY_TYPE",
   146: "EXTERNAL_PIXEL_ARRAY_TYPE",
-  148: "FILLER_TYPE",
-  149: "DECLARED_ACCESSOR_DESCRIPTOR_TYPE",
-  150: "DECLARED_ACCESSOR_INFO_TYPE",
-  151: "EXECUTABLE_ACCESSOR_INFO_TYPE",
-  152: "ACCESSOR_PAIR_TYPE",
-  153: "ACCESS_CHECK_INFO_TYPE",
-  154: "INTERCEPTOR_INFO_TYPE",
-  155: "CALL_HANDLER_INFO_TYPE",
-  156: "FUNCTION_TEMPLATE_INFO_TYPE",
-  157: "OBJECT_TEMPLATE_INFO_TYPE",
-  158: "SIGNATURE_INFO_TYPE",
-  159: "TYPE_SWITCH_INFO_TYPE",
-  161: "ALLOCATION_MEMENTO_TYPE",
-  160: "ALLOCATION_SITE_TYPE",
-  162: "SCRIPT_TYPE",
-  163: "CODE_CACHE_TYPE",
-  164: "POLYMORPHIC_CODE_CACHE_TYPE",
-  165: "TYPE_FEEDBACK_INFO_TYPE",
-  166: "ALIASED_ARGUMENTS_ENTRY_TYPE",
-  167: "BOX_TYPE",
-  170: "FIXED_ARRAY_TYPE",
+  149: "FILLER_TYPE",
+  150: "DECLARED_ACCESSOR_DESCRIPTOR_TYPE",
+  151: "DECLARED_ACCESSOR_INFO_TYPE",
+  152: "EXECUTABLE_ACCESSOR_INFO_TYPE",
+  153: "ACCESSOR_PAIR_TYPE",
+  154: "ACCESS_CHECK_INFO_TYPE",
+  155: "INTERCEPTOR_INFO_TYPE",
+  156: "CALL_HANDLER_INFO_TYPE",
+  157: "FUNCTION_TEMPLATE_INFO_TYPE",
+  158: "OBJECT_TEMPLATE_INFO_TYPE",
+  159: "SIGNATURE_INFO_TYPE",
+  160: "TYPE_SWITCH_INFO_TYPE",
+  162: "ALLOCATION_MEMENTO_TYPE",
+  161: "ALLOCATION_SITE_TYPE",
+  163: "SCRIPT_TYPE",
+  164: "CODE_CACHE_TYPE",
+  165: "POLYMORPHIC_CODE_CACHE_TYPE",
+  166: "TYPE_FEEDBACK_INFO_TYPE",
+  167: "ALIASED_ARGUMENTS_ENTRY_TYPE",
+  168: "BOX_TYPE",
+  171: "FIXED_ARRAY_TYPE",
   147: "FIXED_DOUBLE_ARRAY_TYPE",
-  171: "SHARED_FUNCTION_INFO_TYPE",
-  172: "JS_MESSAGE_OBJECT_TYPE",
-  175: "JS_VALUE_TYPE",
-  176: "JS_DATE_TYPE",
-  177: "JS_OBJECT_TYPE",
-  178: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
-  179: "JS_GENERATOR_OBJECT_TYPE",
-  180: "JS_MODULE_TYPE",
-  181: "JS_GLOBAL_OBJECT_TYPE",
-  182: "JS_BUILTINS_OBJECT_TYPE",
-  183: "JS_GLOBAL_PROXY_TYPE",
-  184: "JS_ARRAY_TYPE",
-  185: "JS_ARRAY_BUFFER_TYPE",
-  186: "JS_TYPED_ARRAY_TYPE",
-  187: "JS_DATA_VIEW_TYPE",
-  174: "JS_PROXY_TYPE",
-  188: "JS_SET_TYPE",
-  189: "JS_MAP_TYPE",
-  190: "JS_WEAK_MAP_TYPE",
-  191: "JS_WEAK_SET_TYPE",
-  192: "JS_REGEXP_TYPE",
-  193: "JS_FUNCTION_TYPE",
-  173: "JS_FUNCTION_PROXY_TYPE",
-  168: "DEBUG_INFO_TYPE",
-  169: "BREAK_POINT_INFO_TYPE",
+  148: "CONSTANT_POOL_ARRAY_TYPE",
+  172: "SHARED_FUNCTION_INFO_TYPE",
+  173: "JS_MESSAGE_OBJECT_TYPE",
+  176: "JS_VALUE_TYPE",
+  177: "JS_DATE_TYPE",
+  178: "JS_OBJECT_TYPE",
+  179: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
+  180: "JS_GENERATOR_OBJECT_TYPE",
+  181: "JS_MODULE_TYPE",
+  182: "JS_GLOBAL_OBJECT_TYPE",
+  183: "JS_BUILTINS_OBJECT_TYPE",
+  184: "JS_GLOBAL_PROXY_TYPE",
+  185: "JS_ARRAY_TYPE",
+  186: "JS_ARRAY_BUFFER_TYPE",
+  187: "JS_TYPED_ARRAY_TYPE",
+  188: "JS_DATA_VIEW_TYPE",
+  175: "JS_PROXY_TYPE",
+  189: "JS_SET_TYPE",
+  190: "JS_MAP_TYPE",
+  191: "JS_WEAK_MAP_TYPE",
+  192: "JS_WEAK_SET_TYPE",
+  193: "JS_REGEXP_TYPE",
+  194: "JS_FUNCTION_TYPE",
+  174: "JS_FUNCTION_PROXY_TYPE",
+  169: "DEBUG_INFO_TYPE",
+  170: "BREAK_POINT_INFO_TYPE",
 }
 
 # List of known V8 maps.
@@ -126,85 +127,86 @@
   0x080a9: (129, "MetaMap"),
   0x080d1: (131, "OddballMap"),
   0x080f9: (4, "AsciiInternalizedStringMap"),
-  0x08121: (170, "FixedArrayMap"),
+  0x08121: (171, "FixedArrayMap"),
   0x08149: (134, "HeapNumberMap"),
   0x08171: (137, "FreeSpaceMap"),
-  0x08199: (148, "OnePointerFillerMap"),
-  0x081c1: (148, "TwoPointerFillerMap"),
+  0x08199: (149, "OnePointerFillerMap"),
+  0x081c1: (149, "TwoPointerFillerMap"),
   0x081e9: (132, "CellMap"),
   0x08211: (133, "GlobalPropertyCellMap"),
-  0x08239: (171, "SharedFunctionInfoMap"),
-  0x08261: (170, "NativeContextMap"),
+  0x08239: (172, "SharedFunctionInfoMap"),
+  0x08261: (171, "NativeContextMap"),
   0x08289: (130, "CodeMap"),
-  0x082b1: (170, "ScopeInfoMap"),
-  0x082d9: (170, "FixedCOWArrayMap"),
+  0x082b1: (171, "ScopeInfoMap"),
+  0x082d9: (171, "FixedCOWArrayMap"),
   0x08301: (147, "FixedDoubleArrayMap"),
-  0x08329: (170, "HashTableMap"),
-  0x08351: (128, "SymbolMap"),
-  0x08379: (64, "StringMap"),
-  0x083a1: (68, "AsciiStringMap"),
-  0x083c9: (65, "ConsStringMap"),
-  0x083f1: (69, "ConsAsciiStringMap"),
-  0x08419: (67, "SlicedStringMap"),
-  0x08441: (71, "SlicedAsciiStringMap"),
-  0x08469: (66, "ExternalStringMap"),
-  0x08491: (74, "ExternalStringWithOneByteDataMap"),
-  0x084b9: (70, "ExternalAsciiStringMap"),
-  0x084e1: (82, "ShortExternalStringMap"),
-  0x08509: (90, "ShortExternalStringWithOneByteDataMap"),
-  0x08531: (0, "InternalizedStringMap"),
-  0x08559: (1, "ConsInternalizedStringMap"),
-  0x08581: (5, "ConsAsciiInternalizedStringMap"),
-  0x085a9: (2, "ExternalInternalizedStringMap"),
-  0x085d1: (10, "ExternalInternalizedStringWithOneByteDataMap"),
-  0x085f9: (6, "ExternalAsciiInternalizedStringMap"),
-  0x08621: (18, "ShortExternalInternalizedStringMap"),
-  0x08649: (26, "ShortExternalInternalizedStringWithOneByteDataMap"),
-  0x08671: (22, "ShortExternalAsciiInternalizedStringMap"),
-  0x08699: (86, "ShortExternalAsciiStringMap"),
-  0x086c1: (64, "UndetectableStringMap"),
-  0x086e9: (68, "UndetectableAsciiStringMap"),
-  0x08711: (138, "ExternalByteArrayMap"),
-  0x08739: (139, "ExternalUnsignedByteArrayMap"),
-  0x08761: (140, "ExternalShortArrayMap"),
-  0x08789: (141, "ExternalUnsignedShortArrayMap"),
-  0x087b1: (142, "ExternalIntArrayMap"),
-  0x087d9: (143, "ExternalUnsignedIntArrayMap"),
-  0x08801: (144, "ExternalFloatArrayMap"),
-  0x08829: (145, "ExternalDoubleArrayMap"),
-  0x08851: (146, "ExternalPixelArrayMap"),
-  0x08879: (170, "NonStrictArgumentsElementsMap"),
-  0x088a1: (170, "FunctionContextMap"),
-  0x088c9: (170, "CatchContextMap"),
-  0x088f1: (170, "WithContextMap"),
-  0x08919: (170, "BlockContextMap"),
-  0x08941: (170, "ModuleContextMap"),
-  0x08969: (170, "GlobalContextMap"),
-  0x08991: (172, "JSMessageObjectMap"),
-  0x089b9: (135, "ForeignMap"),
-  0x089e1: (177, "NeanderMap"),
-  0x08a09: (161, "AllocationMementoMap"),
-  0x08a31: (160, "AllocationSiteMap"),
-  0x08a59: (164, "PolymorphicCodeCacheMap"),
-  0x08a81: (162, "ScriptMap"),
-  0x08ad1: (177, "ExternalMap"),
-  0x08af9: (167, "BoxMap"),
-  0x08b21: (149, "DeclaredAccessorDescriptorMap"),
-  0x08b49: (150, "DeclaredAccessorInfoMap"),
-  0x08b71: (151, "ExecutableAccessorInfoMap"),
-  0x08b99: (152, "AccessorPairMap"),
-  0x08bc1: (153, "AccessCheckInfoMap"),
-  0x08be9: (154, "InterceptorInfoMap"),
-  0x08c11: (155, "CallHandlerInfoMap"),
-  0x08c39: (156, "FunctionTemplateInfoMap"),
-  0x08c61: (157, "ObjectTemplateInfoMap"),
-  0x08c89: (158, "SignatureInfoMap"),
-  0x08cb1: (159, "TypeSwitchInfoMap"),
-  0x08cd9: (163, "CodeCacheMap"),
-  0x08d01: (165, "TypeFeedbackInfoMap"),
-  0x08d29: (166, "AliasedArgumentsEntryMap"),
-  0x08d51: (168, "DebugInfoMap"),
-  0x08d79: (169, "BreakPointInfoMap"),
+  0x08329: (148, "ConstantPoolArrayMap"),
+  0x08351: (171, "HashTableMap"),
+  0x08379: (128, "SymbolMap"),
+  0x083a1: (64, "StringMap"),
+  0x083c9: (68, "AsciiStringMap"),
+  0x083f1: (65, "ConsStringMap"),
+  0x08419: (69, "ConsAsciiStringMap"),
+  0x08441: (67, "SlicedStringMap"),
+  0x08469: (71, "SlicedAsciiStringMap"),
+  0x08491: (66, "ExternalStringMap"),
+  0x084b9: (74, "ExternalStringWithOneByteDataMap"),
+  0x084e1: (70, "ExternalAsciiStringMap"),
+  0x08509: (82, "ShortExternalStringMap"),
+  0x08531: (90, "ShortExternalStringWithOneByteDataMap"),
+  0x08559: (0, "InternalizedStringMap"),
+  0x08581: (1, "ConsInternalizedStringMap"),
+  0x085a9: (5, "ConsAsciiInternalizedStringMap"),
+  0x085d1: (2, "ExternalInternalizedStringMap"),
+  0x085f9: (10, "ExternalInternalizedStringWithOneByteDataMap"),
+  0x08621: (6, "ExternalAsciiInternalizedStringMap"),
+  0x08649: (18, "ShortExternalInternalizedStringMap"),
+  0x08671: (26, "ShortExternalInternalizedStringWithOneByteDataMap"),
+  0x08699: (22, "ShortExternalAsciiInternalizedStringMap"),
+  0x086c1: (86, "ShortExternalAsciiStringMap"),
+  0x086e9: (64, "UndetectableStringMap"),
+  0x08711: (68, "UndetectableAsciiStringMap"),
+  0x08739: (138, "ExternalByteArrayMap"),
+  0x08761: (139, "ExternalUnsignedByteArrayMap"),
+  0x08789: (140, "ExternalShortArrayMap"),
+  0x087b1: (141, "ExternalUnsignedShortArrayMap"),
+  0x087d9: (142, "ExternalIntArrayMap"),
+  0x08801: (143, "ExternalUnsignedIntArrayMap"),
+  0x08829: (144, "ExternalFloatArrayMap"),
+  0x08851: (145, "ExternalDoubleArrayMap"),
+  0x08879: (146, "ExternalPixelArrayMap"),
+  0x088a1: (171, "NonStrictArgumentsElementsMap"),
+  0x088c9: (171, "FunctionContextMap"),
+  0x088f1: (171, "CatchContextMap"),
+  0x08919: (171, "WithContextMap"),
+  0x08941: (171, "BlockContextMap"),
+  0x08969: (171, "ModuleContextMap"),
+  0x08991: (171, "GlobalContextMap"),
+  0x089b9: (173, "JSMessageObjectMap"),
+  0x089e1: (135, "ForeignMap"),
+  0x08a09: (178, "NeanderMap"),
+  0x08a31: (162, "AllocationMementoMap"),
+  0x08a59: (161, "AllocationSiteMap"),
+  0x08a81: (165, "PolymorphicCodeCacheMap"),
+  0x08aa9: (163, "ScriptMap"),
+  0x08af9: (178, "ExternalMap"),
+  0x08b21: (168, "BoxMap"),
+  0x08b49: (150, "DeclaredAccessorDescriptorMap"),
+  0x08b71: (151, "DeclaredAccessorInfoMap"),
+  0x08b99: (152, "ExecutableAccessorInfoMap"),
+  0x08bc1: (153, "AccessorPairMap"),
+  0x08be9: (154, "AccessCheckInfoMap"),
+  0x08c11: (155, "InterceptorInfoMap"),
+  0x08c39: (156, "CallHandlerInfoMap"),
+  0x08c61: (157, "FunctionTemplateInfoMap"),
+  0x08c89: (158, "ObjectTemplateInfoMap"),
+  0x08cb1: (159, "SignatureInfoMap"),
+  0x08cd9: (160, "TypeSwitchInfoMap"),
+  0x08d01: (164, "CodeCacheMap"),
+  0x08d29: (166, "TypeFeedbackInfoMap"),
+  0x08d51: (167, "AliasedArgumentsEntryMap"),
+  0x08d79: (169, "DebugInfoMap"),
+  0x08da1: (170, "BreakPointInfoMap"),
 }
 
 # List of known V8 objects.
@@ -250,6 +252,6 @@
   ("OLD_DATA_SPACE", 0x082c9): "EmptyExternalPixelArray",
   ("OLD_DATA_SPACE", 0x082d5): "InfinityValue",
   ("OLD_DATA_SPACE", 0x082e1): "MinusZeroValue",
-  ("CODE_SPACE", 0x11141): "JsConstructEntryCode",
-  ("CODE_SPACE", 0x18da1): "JsEntryCode",
+  ("CODE_SPACE", 0x111a1): "JsConstructEntryCode",
+  ("CODE_SPACE", 0x18bc1): "JsEntryCode",
 }