Merge v8 from https://chromium.googlesource.com/v8/v8.git at 8955e55db30b31cae138a39218f4086c7774c32a

This commit was generated by merge_from_chromium.py.

Change-Id: I3fd7f4a2c5824d8ae8501ca311b8669da43b8e37
diff --git a/BUILD.gn b/BUILD.gn
index 3a9fa66..5742de7 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -450,6 +450,8 @@
     "src/bignum-dtoa.h",
     "src/bignum.cc",
     "src/bignum.h",
+    "src/bit-vector.cc",
+    "src/bit-vector.h",
     "src/bootstrapper.cc",
     "src/bootstrapper.h",
     "src/builtins.cc",
@@ -602,8 +604,6 @@
     "src/cpu-profiler-inl.h",
     "src/cpu-profiler.cc",
     "src/cpu-profiler.h",
-    "src/data-flow.cc",
-    "src/data-flow.h",
     "src/date.cc",
     "src/date.h",
     "src/dateparser-inl.h",
diff --git a/ChangeLog b/ChangeLog
index 54c3456..fd2aaa4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2014-11-02: Version 3.30.27
+
+        Performance and stability improvements on all platforms.
+
+
+2014-11-02: Version 3.30.26
+
+        Performance and stability improvements on all platforms.
+
+
+2014-11-01: Version 3.30.25
+
+        Performance and stability improvements on all platforms.
+
+
+2014-11-01: Version 3.30.24
+
+        Ensure we don't try to inline raw access to indexed interceptor
+        receivers (Chromium issue 419220).
+
+        Performance and stability improvements on all platforms.
+
+
 2014-10-31: Version 3.30.23
 
         Introduce v8::Exception::GetMessage to find location of an error object
diff --git a/src/data-flow.cc b/src/bit-vector.cc
similarity index 74%
rename from src/data-flow.cc
rename to src/bit-vector.cc
index bd92ea0..198b242 100644
--- a/src/data-flow.cc
+++ b/src/bit-vector.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "src/data-flow.h"
+#include "src/bit-vector.h"
 
 #include "src/base/bits.h"
 #include "src/scopes.h"
@@ -28,12 +28,12 @@
 
 void BitVector::Iterator::Advance() {
   current_++;
-  uint32_t val = current_value_;
+  uintptr_t val = current_value_;
   while (val == 0) {
     current_index_++;
     if (Done()) return;
     val = target_->data_[current_index_];
-    current_ = current_index_ << 5;
+    current_ = current_index_ << kDataBitShift;
   }
   val = SkipZeroBytes(val);
   val = SkipZeroBits(val);
@@ -44,8 +44,12 @@
 int BitVector::Count() const {
   int count = 0;
   for (int i = 0; i < data_length_; i++) {
-    int data = data_[i];
-    if (data != 0) count += base::bits::CountPopulation32(data);
+    uintptr_t data = data_[i];
+    if (sizeof(data) == 8) {
+      count += base::bits::CountPopulation64(data);
+    } else {
+      count += base::bits::CountPopulation32(static_cast<uint32_t>(data));
+    }
   }
   return count;
 }
diff --git a/src/data-flow.h b/src/bit-vector.h
similarity index 78%
rename from src/data-flow.h
rename to src/bit-vector.h
index bfd238d..9fc747d 100644
--- a/src/data-flow.h
+++ b/src/bit-vector.h
@@ -15,7 +15,7 @@
 namespace v8 {
 namespace internal {
 
-class BitVector: public ZoneObject {
+class BitVector : public ZoneObject {
  public:
   // Iterator for the elements of this BitVector.
   class Iterator BASE_EMBEDDED {
@@ -28,7 +28,7 @@
       DCHECK(target->data_length_ > 0);
       Advance();
     }
-    ~Iterator() { }
+    ~Iterator() {}
 
     bool Done() const { return current_index_ >= target_->data_length_; }
     void Advance();
@@ -39,14 +39,14 @@
     }
 
    private:
-    uint32_t SkipZeroBytes(uint32_t val) {
+    uintptr_t SkipZeroBytes(uintptr_t val) {
       while ((val & 0xFF) == 0) {
         val >>= 8;
         current_ += 8;
       }
       return val;
     }
-    uint32_t SkipZeroBits(uint32_t val) {
+    uintptr_t SkipZeroBits(uintptr_t val) {
       while ((val & 0x1) == 0) {
         val >>= 1;
         current_++;
@@ -56,16 +56,20 @@
 
     BitVector* target_;
     int current_index_;
-    uint32_t current_value_;
+    uintptr_t current_value_;
     int current_;
 
     friend class BitVector;
   };
 
+  static const int kDataBits = kPointerSize * 8;
+  static const int kDataBitShift = kPointerSize == 8 ? 6 : 5;
+  static const uintptr_t kOne = 1;  // This saves some static_casts.
+
   BitVector(int length, Zone* zone)
       : length_(length),
         data_length_(SizeFor(length)),
-        data_(zone->NewArray<uint32_t>(data_length_)) {
+        data_(zone->NewArray<uintptr_t>(data_length_)) {
     DCHECK(length > 0);
     Clear();
   }
@@ -73,18 +77,11 @@
   BitVector(const BitVector& other, Zone* zone)
       : length_(other.length()),
         data_length_(SizeFor(length_)),
-        data_(zone->NewArray<uint32_t>(data_length_)) {
+        data_(zone->NewArray<uintptr_t>(data_length_)) {
     CopyFrom(other);
   }
 
-  static int SizeFor(int length) {
-    return 1 + ((length - 1) / 32);
-  }
-
-  BitVector& operator=(const BitVector& rhs) {
-    if (this != &rhs) CopyFrom(rhs);
-    return *this;
-  }
+  static int SizeFor(int length) { return 1 + ((length - 1) / kDataBits); }
 
   void CopyFrom(const BitVector& other) {
     DCHECK(other.length() <= length());
@@ -98,18 +95,18 @@
 
   bool Contains(int i) const {
     DCHECK(i >= 0 && i < length());
-    uint32_t block = data_[i / 32];
-    return (block & (1U << (i % 32))) != 0;
+    uintptr_t block = data_[i / kDataBits];
+    return (block & (kOne << (i % kDataBits))) != 0;
   }
 
   void Add(int i) {
     DCHECK(i >= 0 && i < length());
-    data_[i / 32] |= (1U << (i % 32));
+    data_[i / kDataBits] |= (kOne << (i % kDataBits));
   }
 
   void Remove(int i) {
     DCHECK(i >= 0 && i < length());
-    data_[i / 32] &= ~(1U << (i % 32));
+    data_[i / kDataBits] &= ~(kOne << (i % kDataBits));
   }
 
   void Union(const BitVector& other) {
@@ -123,7 +120,7 @@
     DCHECK(other.length() == length());
     bool changed = false;
     for (int i = 0; i < data_length_; i++) {
-      uint32_t old_data = data_[i];
+      uintptr_t old_data = data_[i];
       data_[i] |= other.data_[i];
       if (data_[i] != old_data) changed = true;
     }
@@ -141,7 +138,7 @@
     DCHECK(other.length() == length());
     bool changed = false;
     for (int i = 0; i < data_length_; i++) {
-      uint32_t old_data = data_[i];
+      uintptr_t old_data = data_[i];
       data_[i] &= other.data_[i];
       if (data_[i] != old_data) changed = true;
     }
@@ -184,9 +181,11 @@
 #endif
 
  private:
-  int length_;
-  int data_length_;
-  uint32_t* data_;
+  const int length_;
+  const int data_length_;
+  uintptr_t* const data_;
+
+  DISALLOW_COPY_AND_ASSIGN(BitVector);
 };
 
 
@@ -195,19 +194,19 @@
   class Iterator BASE_EMBEDDED {
    public:
     Iterator(const GrowableBitVector* target, Zone* zone)
-        : it_(target->bits_ == NULL
-              ? new(zone) BitVector(1, zone)
-              : target->bits_) { }
+        : it_(target->bits_ == NULL ? new (zone) BitVector(1, zone)
+                                    : target->bits_) {}
     bool Done() const { return it_.Done(); }
     void Advance() { it_.Advance(); }
     int Current() const { return it_.Current(); }
+
    private:
     BitVector::Iterator it_;
   };
 
-  GrowableBitVector() : bits_(NULL) { }
+  GrowableBitVector() : bits_(NULL) {}
   GrowableBitVector(int length, Zone* zone)
-      : bits_(new(zone) BitVector(length, zone)) { }
+      : bits_(new (zone) BitVector(length, zone)) {}
 
   bool Contains(int value) const {
     if (!InBitsRange(value)) return false;
@@ -225,7 +224,9 @@
     }
   }
 
-  void Clear() { if (bits_ != NULL) bits_->Clear(); }
+  void Clear() {
+    if (bits_ != NULL) bits_->Clear();
+  }
 
  private:
   static const int kInitialLength = 1024;
@@ -238,7 +239,7 @@
     if (InBitsRange(value)) return;
     int new_length = bits_ == NULL ? kInitialLength : bits_->length();
     while (new_length <= value) new_length *= 2;
-    BitVector* new_bits = new(zone) BitVector(new_length, zone);
+    BitVector* new_bits = new (zone) BitVector(new_length, zone);
     if (bits_ != NULL) new_bits->CopyFrom(*bits_);
     bits_ = new_bits;
   }
diff --git a/src/compilation-cache.cc b/src/compilation-cache.cc
index aab2fe5..6c9f95a 100644
--- a/src/compilation-cache.cc
+++ b/src/compilation-cache.cc
@@ -13,11 +13,6 @@
 
 
 // The number of generations for each sub cache.
-// The number of ScriptGenerations is carefully chosen based on histograms.
-// See issue 458: http://code.google.com/p/v8/issues/detail?id=458
-static const int kScriptGenerations = 5;
-static const int kEvalGlobalGenerations = 2;
-static const int kEvalContextualGenerations = 2;
 static const int kRegExpGenerations = 2;
 
 // Initial size of each compilation cache table allocated.
@@ -26,9 +21,9 @@
 
 CompilationCache::CompilationCache(Isolate* isolate)
     : isolate_(isolate),
-      script_(isolate, kScriptGenerations),
-      eval_global_(isolate, kEvalGlobalGenerations),
-      eval_contextual_(isolate, kEvalContextualGenerations),
+      script_(isolate, 1),
+      eval_global_(isolate, 1),
+      eval_contextual_(isolate, 1),
       reg_exp_(isolate, kRegExpGenerations),
       enabled_(true) {
   CompilationSubCache* subcaches[kSubCacheCount] =
@@ -58,6 +53,14 @@
 
 
 void CompilationSubCache::Age() {
+  // Don't directly age single-generation caches.
+  if (generations_ == 1) {
+    if (tables_[0] != isolate()->heap()->undefined_value()) {
+      CompilationCacheTable::cast(tables_[0])->Age();
+    }
+    return;
+  }
+
   // Age the generations implicitly killing off the oldest.
   for (int i = generations_ - 1; i > 0; i--) {
     tables_[i] = tables_[i - 1];
@@ -102,9 +105,7 @@
 
 CompilationCacheScript::CompilationCacheScript(Isolate* isolate,
                                                int generations)
-    : CompilationSubCache(isolate, generations),
-      script_histogram_(NULL),
-      script_histogram_initialized_(false) { }
+    : CompilationSubCache(isolate, generations) {}
 
 
 // We only re-use a cached function for some script source code if the
@@ -173,20 +174,6 @@
     }
   }
 
-  if (!script_histogram_initialized_) {
-    script_histogram_ = isolate()->stats_table()->CreateHistogram(
-        "V8.ScriptCache",
-        0,
-        kScriptGenerations,
-        kScriptGenerations + 1);
-    script_histogram_initialized_ = true;
-  }
-
-  if (script_histogram_ != NULL) {
-    // The level NUMBER_OF_SCRIPT_GENERATIONS is equivalent to a cache miss.
-    isolate()->stats_table()->AddHistogramSample(script_histogram_, generation);
-  }
-
   // Once outside the manacles of the handle scope, we need to recheck
   // to see if we actually found a cached script. If so, we return a
   // handle created in the caller's handle scope.
diff --git a/src/compilation-cache.h b/src/compilation-cache.h
index 6799b1c..a7c84b7 100644
--- a/src/compilation-cache.h
+++ b/src/compilation-cache.h
@@ -89,9 +89,6 @@
                  int column_offset,
                  bool is_shared_cross_origin);
 
-  void* script_histogram_;
-  bool script_histogram_initialized_;
-
   DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheScript);
 };
 
diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc
index d7bae5a..7b5abd1 100644
--- a/src/compiler/ast-graph-builder.cc
+++ b/src/compiler/ast-graph-builder.cc
@@ -339,24 +339,40 @@
 
 void AstGraphBuilder::VisitForValue(Expression* expr) {
   AstValueContext for_value(this);
-  if (!HasStackOverflow()) {
+  if (!CheckStackOverflow()) {
     expr->Accept(this);
+  } else {
+    ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
   }
 }
 
 
 void AstGraphBuilder::VisitForEffect(Expression* expr) {
   AstEffectContext for_effect(this);
-  if (!HasStackOverflow()) {
+  if (!CheckStackOverflow()) {
     expr->Accept(this);
+  } else {
+    ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
   }
 }
 
 
 void AstGraphBuilder::VisitForTest(Expression* expr) {
   AstTestContext for_condition(this);
-  if (!HasStackOverflow()) {
+  if (!CheckStackOverflow()) {
     expr->Accept(this);
+  } else {
+    ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
+  }
+}
+
+
+void AstGraphBuilder::Visit(Expression* expr) {
+  // Reuses enclosing AstContext.
+  if (!CheckStackOverflow()) {
+    expr->Accept(this);
+  } else {
+    ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
   }
 }
 
diff --git a/src/compiler/ast-graph-builder.h b/src/compiler/ast-graph-builder.h
index 441917f..6e51723 100644
--- a/src/compiler/ast-graph-builder.h
+++ b/src/compiler/ast-graph-builder.h
@@ -159,6 +159,7 @@
   void VisitIfNotNull(Statement* stmt);
 
   // Visit expressions.
+  void Visit(Expression* expr);
   void VisitForTest(Expression* expr);
   void VisitForEffect(Expression* expr);
   void VisitForValue(Expression* expr);
diff --git a/src/compiler/ast-loop-assignment-analyzer.h b/src/compiler/ast-loop-assignment-analyzer.h
index daa94f9..10b9d83 100644
--- a/src/compiler/ast-loop-assignment-analyzer.h
+++ b/src/compiler/ast-loop-assignment-analyzer.h
@@ -6,7 +6,7 @@
 #define V8_COMPILER_AST_LOOP_ASSIGNMENT_ANALYZER_H_
 
 #include "src/ast.h"
-#include "src/data-flow.h"
+#include "src/bit-vector.h"
 #include "src/v8.h"
 #include "src/zone-containers.h"
 
diff --git a/src/compiler/frame.h b/src/compiler/frame.h
index afcbc37..df9a01f 100644
--- a/src/compiler/frame.h
+++ b/src/compiler/frame.h
@@ -7,7 +7,7 @@
 
 #include "src/v8.h"
 
-#include "src/data-flow.h"
+#include "src/bit-vector.h"
 
 namespace v8 {
 namespace internal {
diff --git a/src/compiler/ia32/code-generator-ia32.cc b/src/compiler/ia32/code-generator-ia32.cc
index 0044483..fd46636 100644
--- a/src/compiler/ia32/code-generator-ia32.cc
+++ b/src/compiler/ia32/code-generator-ia32.cc
@@ -314,16 +314,16 @@
       __ ucomisd(i.InputDoubleRegister(0), i.InputOperand(1));
       break;
     case kSSEFloat64Add:
-      __ addsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
+      __ addsd(i.InputDoubleRegister(0), i.InputOperand(1));
       break;
     case kSSEFloat64Sub:
-      __ subsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
+      __ subsd(i.InputDoubleRegister(0), i.InputOperand(1));
       break;
     case kSSEFloat64Mul:
-      __ mulsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
+      __ mulsd(i.InputDoubleRegister(0), i.InputOperand(1));
       break;
     case kSSEFloat64Div:
-      __ divsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
+      __ divsd(i.InputDoubleRegister(0), i.InputOperand(1));
       break;
     case kSSEFloat64Mod: {
       // TODO(dcarney): alignment is wrong.
diff --git a/src/compiler/ia32/instruction-selector-ia32.cc b/src/compiler/ia32/instruction-selector-ia32.cc
index ca33ab0..f4358ea 100644
--- a/src/compiler/ia32/instruction-selector-ia32.cc
+++ b/src/compiler/ia32/instruction-selector-ia32.cc
@@ -736,28 +736,28 @@
 void InstructionSelector::VisitFloat64Add(Node* node) {
   IA32OperandGenerator g(this);
   Emit(kSSEFloat64Add, g.DefineSameAsFirst(node),
-       g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
+       g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
 }
 
 
 void InstructionSelector::VisitFloat64Sub(Node* node) {
   IA32OperandGenerator g(this);
   Emit(kSSEFloat64Sub, g.DefineSameAsFirst(node),
-       g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
+       g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
 }
 
 
 void InstructionSelector::VisitFloat64Mul(Node* node) {
   IA32OperandGenerator g(this);
   Emit(kSSEFloat64Mul, g.DefineSameAsFirst(node),
-       g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
+       g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
 }
 
 
 void InstructionSelector::VisitFloat64Div(Node* node) {
   IA32OperandGenerator g(this);
   Emit(kSSEFloat64Div, g.DefineSameAsFirst(node),
-       g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
+       g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
 }
 
 
diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc
index 0dcb408..d1df843 100644
--- a/src/compiler/pipeline.cc
+++ b/src/compiler/pipeline.cc
@@ -319,7 +319,7 @@
     ZonePool::Scope zone_scope(data.zone_pool());
     AstGraphBuilderWithPositions graph_builder(
         zone_scope.zone(), info(), data.jsgraph(), data.source_positions());
-    graph_builder.CreateGraph();
+    if (!graph_builder.CreateGraph()) return Handle<Code>::null();
     context_node = graph_builder.GetFunctionContext();
   }
 
diff --git a/src/compiler/scheduler.cc b/src/compiler/scheduler.cc
index 109f50d..4bab8f5 100644
--- a/src/compiler/scheduler.cc
+++ b/src/compiler/scheduler.cc
@@ -7,12 +7,12 @@
 
 #include "src/compiler/scheduler.h"
 
+#include "src/bit-vector.h"
 #include "src/compiler/graph.h"
 #include "src/compiler/graph-inl.h"
 #include "src/compiler/node.h"
 #include "src/compiler/node-properties.h"
 #include "src/compiler/node-properties-inl.h"
-#include "src/data-flow.h"
 
 namespace v8 {
 namespace internal {
@@ -147,8 +147,6 @@
     // schedulable. If all the uses of a node have been scheduled, then the node
     // itself can be scheduled.
     for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) {
-      // TODO(mstarzinger): Another cheap hack for use counts.
-      if (GetData(*i)->placement_ == kFixed) continue;
       DecrementUnscheduledUseCount(*i, i.index(), i.edge().from());
     }
   }
@@ -167,6 +165,9 @@
   // Make sure that control edges from coupled nodes are not counted.
   if (IsCoupledControlEdge(from, index)) return;
 
+  // Tracking use counts for fixed nodes is useless.
+  if (GetPlacement(node) == kFixed) return;
+
   // Use count for coupled nodes is summed up on their control.
   if (GetPlacement(node) == kCoupled) {
     Node* control = NodeProperties::GetControlInput(node);
@@ -187,6 +188,9 @@
   // Make sure that control edges from coupled nodes are not counted.
   if (IsCoupledControlEdge(from, index)) return;
 
+  // Tracking use counts for fixed nodes is useless.
+  if (GetPlacement(node) == kFixed) return;
+
   // Use count for coupled nodes is summed up on their control.
   if (GetPlacement(node) == kCoupled) {
     Node* control = NodeProperties::GetControlInput(node);
@@ -1014,7 +1018,7 @@
       scheduler_->schedule_root_nodes_.push_back(node);
       if (!schedule_->IsScheduled(node)) {
         // Make sure root nodes are scheduled in their respective blocks.
-        Trace("  Scheduling fixed position node #%d:%s\n", node->id(),
+        Trace("Scheduling fixed position node #%d:%s\n", node->id(),
               node->op()->mnemonic());
         IrOpcode::Value opcode = node->opcode();
         BasicBlock* block =
diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc
index ff48d34..0f784c6 100644
--- a/src/compiler/simplified-lowering.cc
+++ b/src/compiler/simplified-lowering.cc
@@ -296,61 +296,46 @@
   void VisitInt64Cmp(Node* node) { VisitBinop(node, kMachInt64, kRepBit); }
   void VisitUint64Cmp(Node* node) { VisitBinop(node, kMachUint64, kRepBit); }
 
+  // Infer representation for phi-like nodes.
+  MachineType GetRepresentationForPhi(Node* node, MachineTypeUnion use) {
+    // Phis adapt to the output representation their uses demand.
+    Type* upper = NodeProperties::GetBounds(node).upper;
+    if ((use & kRepMask) == kRepTagged) {
+      // only tagged uses.
+      return kRepTagged;
+    } else if (IsSafeIntAdditiveOperand(node)) {
+      // Integer within [-2^52, 2^52] range.
+      if ((use & kRepMask) == kRepFloat64) {
+        // only float64 uses.
+        return kRepFloat64;
+      } else if (upper->Is(Type::Signed32()) || upper->Is(Type::Unsigned32())) {
+        // multiple uses, but we are within 32 bits range => pick kRepWord32.
+        return kRepWord32;
+      } else if ((use & kRepMask) == kRepWord32 ||
+                 (use & kTypeMask) == kTypeInt32 ||
+                 (use & kTypeMask) == kTypeUint32) {
+        // The type is a safe integer, but we only use 32 bits.
+        return kRepWord32;
+      } else {
+        return kRepFloat64;
+      }
+    } else if (upper->Is(Type::Boolean())) {
+      // multiple uses => pick kRepBit.
+      return kRepBit;
+    } else if (upper->Is(Type::Number())) {
+      // multiple uses => pick kRepFloat64.
+      return kRepFloat64;
+    }
+    return kRepTagged;
+  }
+
   // Helper for handling selects.
-  // TODO(turbofan): Share some code with VisitPhi() below?
   void VisitSelect(Node* node, MachineTypeUnion use,
                    SimplifiedLowering* lowering) {
     ProcessInput(node, 0, kRepBit);
+    MachineType output = GetRepresentationForPhi(node, use);
 
-    // Selects adapt to the output representation their uses demand, pushing
-    // representation changes to their inputs.
     Type* upper = NodeProperties::GetBounds(node).upper;
-    MachineType output = kMachNone;
-    MachineType propagate = kMachNone;
-
-    if (upper->Is(Type::Signed32()) || upper->Is(Type::Unsigned32())) {
-      // legal = kRepTagged | kRepFloat64 | kRepWord32;
-      if ((use & kRepMask) == kRepTagged) {
-        // only tagged uses.
-        output = kRepTagged;
-        propagate = kRepTagged;
-      } else if ((use & kRepMask) == kRepFloat64) {
-        // only float64 uses.
-        output = kRepFloat64;
-        propagate = kRepFloat64;
-      } else {
-        // multiple uses.
-        output = kRepWord32;
-        propagate = kRepWord32;
-      }
-    } else if (upper->Is(Type::Boolean())) {
-      // legal = kRepTagged | kRepBit;
-      if ((use & kRepMask) == kRepTagged) {
-        // only tagged uses.
-        output = kRepTagged;
-        propagate = kRepTagged;
-      } else {
-        // multiple uses.
-        output = kRepBit;
-        propagate = kRepBit;
-      }
-    } else if (upper->Is(Type::Number())) {
-      // legal = kRepTagged | kRepFloat64;
-      if ((use & kRepMask) == kRepTagged) {
-        // only tagged uses.
-        output = kRepTagged;
-        propagate = kRepTagged;
-      } else {
-        // multiple uses.
-        output = kRepFloat64;
-        propagate = kRepFloat64;
-      }
-    } else {
-      // legal = kRepTagged;
-      output = kRepTagged;
-      propagate = kRepTagged;
-    }
-
     MachineType output_type =
         static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output);
     SetOutput(node, output_type);
@@ -369,7 +354,7 @@
     } else {
       // Propagate {use} of the select to value inputs.
       MachineType use_type =
-          static_cast<MachineType>((use & kTypeMask) | propagate);
+          static_cast<MachineType>((use & kTypeMask) | output);
       ProcessInput(node, 1, use_type);
       ProcessInput(node, 2, use_type);
     }
@@ -378,55 +363,9 @@
   // Helper for handling phis.
   void VisitPhi(Node* node, MachineTypeUnion use,
                 SimplifiedLowering* lowering) {
-    // Phis adapt to the output representation their uses demand, pushing
-    // representation changes to their inputs.
+    MachineType output = GetRepresentationForPhi(node, use);
+
     Type* upper = NodeProperties::GetBounds(node).upper;
-    MachineType output = kMachNone;
-    MachineType propagate = kMachNone;
-
-    if (upper->Is(Type::Signed32()) || upper->Is(Type::Unsigned32())) {
-      // legal = kRepTagged | kRepFloat64 | kRepWord32;
-      if ((use & kRepMask) == kRepTagged) {
-        // only tagged uses.
-        output = kRepTagged;
-        propagate = kRepTagged;
-      } else if ((use & kRepMask) == kRepFloat64) {
-        // only float64 uses.
-        output = kRepFloat64;
-        propagate = kRepFloat64;
-      } else {
-        // multiple uses.
-        output = kRepWord32;
-        propagate = kRepWord32;
-      }
-    } else if (upper->Is(Type::Boolean())) {
-      // legal = kRepTagged | kRepBit;
-      if ((use & kRepMask) == kRepTagged) {
-        // only tagged uses.
-        output = kRepTagged;
-        propagate = kRepTagged;
-      } else {
-        // multiple uses.
-        output = kRepBit;
-        propagate = kRepBit;
-      }
-    } else if (upper->Is(Type::Number())) {
-      // legal = kRepTagged | kRepFloat64;
-      if ((use & kRepMask) == kRepTagged) {
-        // only tagged uses.
-        output = kRepTagged;
-        propagate = kRepTagged;
-      } else {
-        // multiple uses.
-        output = kRepFloat64;
-        propagate = kRepFloat64;
-      }
-    } else {
-      // legal = kRepTagged;
-      output = kRepTagged;
-      propagate = kRepTagged;
-    }
-
     MachineType output_type =
         static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output);
     SetOutput(node, output_type);
@@ -451,7 +390,7 @@
       // Propagate {use} of the phi to value inputs, and 0 to control.
       Node::Inputs inputs = node->inputs();
       MachineType use_type =
-          static_cast<MachineType>((use & kTypeMask) | propagate);
+          static_cast<MachineType>((use & kTypeMask) | output);
       for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end();
            ++iter, --values) {
         // TODO(titzer): it'd be nice to have distinguished edge kinds here.
@@ -725,13 +664,15 @@
       case IrOpcode::kNumberToInt32: {
         MachineTypeUnion use_rep = use & kRepMask;
         Node* input = node->InputAt(0);
+        Type* in_upper = NodeProperties::GetBounds(input).upper;
         MachineTypeUnion in = GetInfo(input)->output;
-        if (NodeProperties::GetBounds(input).upper->Is(Type::Signed32())) {
+        if (in_upper->Is(Type::Signed32())) {
           // If the input has type int32, pass through representation.
           VisitUnop(node, kTypeInt32 | use_rep, kTypeInt32 | use_rep);
           if (lower()) DeferReplacement(node, node->InputAt(0));
         } else if ((in & kTypeMask) == kTypeUint32 ||
                    (in & kTypeMask) == kTypeInt32 ||
+                   in_upper->Is(Type::Unsigned32()) ||
                    (in & kRepMask) == kRepWord32) {
           // Just change representation if necessary.
           VisitUnop(node, kTypeInt32 | kRepWord32, kTypeInt32 | kRepWord32);
@@ -748,13 +689,15 @@
       case IrOpcode::kNumberToUint32: {
         MachineTypeUnion use_rep = use & kRepMask;
         Node* input = node->InputAt(0);
+        Type* in_upper = NodeProperties::GetBounds(input).upper;
         MachineTypeUnion in = GetInfo(input)->output;
-        if (NodeProperties::GetBounds(input).upper->Is(Type::Unsigned32())) {
+        if (in_upper->Is(Type::Unsigned32())) {
           // If the input has type uint32, pass through representation.
           VisitUnop(node, kTypeUint32 | use_rep, kTypeUint32 | use_rep);
           if (lower()) DeferReplacement(node, node->InputAt(0));
         } else if ((in & kTypeMask) == kTypeUint32 ||
                    (in & kTypeMask) == kTypeInt32 ||
+                   in_upper->Is(Type::Signed32()) ||
                    (in & kRepMask) == kRepWord32) {
           // Just change representation if necessary.
           VisitUnop(node, kTypeUint32 | kRepWord32, kTypeUint32 | kRepWord32);
diff --git a/src/compiler/verifier.cc b/src/compiler/verifier.cc
index 1f573b1..2934276 100644
--- a/src/compiler/verifier.cc
+++ b/src/compiler/verifier.cc
@@ -9,6 +9,7 @@
 #include <sstream>
 #include <string>
 
+#include "src/bit-vector.h"
 #include "src/compiler/generic-algorithm.h"
 #include "src/compiler/generic-node-inl.h"
 #include "src/compiler/generic-node.h"
@@ -21,7 +22,6 @@
 #include "src/compiler/operator.h"
 #include "src/compiler/schedule.h"
 #include "src/compiler/simplified-operator.h"
-#include "src/data-flow.h"
 #include "src/ostreams.h"
 
 namespace v8 {
diff --git a/src/compiler/x64/code-generator-x64.cc b/src/compiler/x64/code-generator-x64.cc
index 3e54859..b684bdf 100644
--- a/src/compiler/x64/code-generator-x64.cc
+++ b/src/compiler/x64/code-generator-x64.cc
@@ -197,6 +197,16 @@
   } while (0)
 
 
+#define ASSEMBLE_DOUBLE_BINOP(asm_instr)                                \
+  do {                                                                  \
+    if (instr->InputAt(1)->IsDoubleRegister()) {                        \
+      __ asm_instr(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); \
+    } else {                                                            \
+      __ asm_instr(i.InputDoubleRegister(0), i.InputOperand(1));        \
+    }                                                                   \
+  } while (0)
+
+
 // Assembles an instruction after register allocation, producing machine code.
 void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
   X64OperandConverter i(this, instr);
@@ -346,23 +356,19 @@
       ASSEMBLE_SHIFT(rorq, 6);
       break;
     case kSSEFloat64Cmp:
-      if (instr->InputAt(1)->IsDoubleRegister()) {
-        __ ucomisd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
-      } else {
-        __ ucomisd(i.InputDoubleRegister(0), i.InputOperand(1));
-      }
+      ASSEMBLE_DOUBLE_BINOP(ucomisd);
       break;
     case kSSEFloat64Add:
-      __ addsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
+      ASSEMBLE_DOUBLE_BINOP(addsd);
       break;
     case kSSEFloat64Sub:
-      __ subsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
+      ASSEMBLE_DOUBLE_BINOP(subsd);
       break;
     case kSSEFloat64Mul:
-      __ mulsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
+      ASSEMBLE_DOUBLE_BINOP(mulsd);
       break;
     case kSSEFloat64Div:
-      __ divsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
+      ASSEMBLE_DOUBLE_BINOP(divsd);
       break;
     case kSSEFloat64Mod: {
       __ subq(rsp, Immediate(kDoubleSize));
@@ -441,16 +447,15 @@
         __ cvttsd2si(i.OutputRegister(), i.InputOperand(0));
       }
       break;
-    case kSSEFloat64ToUint32:
+    case kSSEFloat64ToUint32: {
       if (instr->InputAt(0)->IsDoubleRegister()) {
         __ cvttsd2siq(i.OutputRegister(), i.InputDoubleRegister(0));
       } else {
         __ cvttsd2siq(i.OutputRegister(), i.InputOperand(0));
       }
-      __ andl(i.OutputRegister(), i.OutputRegister());  // clear upper bits.
-      // TODO(turbofan): generated code should not look at the upper 32 bits
-      // of the result, but those bits could escape to the outside world.
+      __ AssertZeroExtended(i.OutputRegister());
       break;
+    }
     case kSSEInt32ToFloat64:
       if (instr->InputAt(0)->IsRegister()) {
         __ cvtlsi2sd(i.OutputDoubleRegister(), i.InputRegister(0));
diff --git a/src/compiler/x64/instruction-selector-x64.cc b/src/compiler/x64/instruction-selector-x64.cc
index 17c63d2..f49f8bf 100644
--- a/src/compiler/x64/instruction-selector-x64.cc
+++ b/src/compiler/x64/instruction-selector-x64.cc
@@ -591,28 +591,28 @@
 void InstructionSelector::VisitFloat64Add(Node* node) {
   X64OperandGenerator g(this);
   Emit(kSSEFloat64Add, g.DefineSameAsFirst(node),
-       g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
+       g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
 }
 
 
 void InstructionSelector::VisitFloat64Sub(Node* node) {
   X64OperandGenerator g(this);
   Emit(kSSEFloat64Sub, g.DefineSameAsFirst(node),
-       g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
+       g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
 }
 
 
 void InstructionSelector::VisitFloat64Mul(Node* node) {
   X64OperandGenerator g(this);
   Emit(kSSEFloat64Mul, g.DefineSameAsFirst(node),
-       g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
+       g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
 }
 
 
 void InstructionSelector::VisitFloat64Div(Node* node) {
   X64OperandGenerator g(this);
   Emit(kSSEFloat64Div, g.DefineSameAsFirst(node),
-       g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
+       g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
 }
 
 
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index bd38467..58e5e97 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -346,6 +346,11 @@
   info->SetCode(code);
   void* line_info = masm.positions_recorder()->DetachJITHandlerData();
   LOG_CODE_EVENT(isolate, CodeEndLinePosInfoRecordEvent(*code, line_info));
+
+#ifdef DEBUG
+  // Check that no context-specific object has been embedded.
+  code->VerifyEmbeddedObjectsInFullCode();
+#endif  // DEBUG
   return true;
 }
 
diff --git a/src/full-codegen.h b/src/full-codegen.h
index 8399d7d..f032854 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -10,10 +10,10 @@
 #include "src/allocation.h"
 #include "src/assert-scope.h"
 #include "src/ast.h"
+#include "src/bit-vector.h"
 #include "src/code-stubs.h"
 #include "src/codegen.h"
 #include "src/compiler.h"
-#include "src/data-flow.h"
 #include "src/globals.h"
 #include "src/objects.h"
 
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
index 94c8937..93e00d2 100644
--- a/src/heap/heap.cc
+++ b/src/heap/heap.cc
@@ -939,6 +939,8 @@
         for (auto& chunk : *reservation) {
           AllocationResult allocation;
           int size = chunk.size;
+          DCHECK_LE(size, MemoryAllocator::PageAreaSize(
+                              static_cast<AllocationSpace>(space)));
           if (space == NEW_SPACE) {
             allocation = new_space()->AllocateRaw(size);
           } else {
diff --git a/src/heap/spaces.cc b/src/heap/spaces.cc
index 85281aa..430f31d 100644
--- a/src/heap/spaces.cc
+++ b/src/heap/spaces.cc
@@ -892,18 +892,14 @@
 // -----------------------------------------------------------------------------
 // PagedSpace implementation
 
-PagedSpace::PagedSpace(Heap* heap, intptr_t max_capacity, AllocationSpace id,
+PagedSpace::PagedSpace(Heap* heap, intptr_t max_capacity, AllocationSpace space,
                        Executability executable)
-    : Space(heap, id, executable),
+    : Space(heap, space, executable),
       free_list_(this),
       unswept_free_bytes_(0),
       end_of_unswept_pages_(NULL),
       emergency_memory_(NULL) {
-  if (id == CODE_SPACE) {
-    area_size_ = heap->isolate()->memory_allocator()->CodePageAreaSize();
-  } else {
-    area_size_ = Page::kPageSize - Page::kObjectStartOffset;
-  }
+  area_size_ = MemoryAllocator::PageAreaSize(space);
   max_capacity_ =
       (RoundDown(max_capacity, Page::kPageSize) / Page::kPageSize) * AreaSize();
   accounting_stats_.Clear();
diff --git a/src/heap/spaces.h b/src/heap/spaces.h
index 5be9c3a..1944464 100644
--- a/src/heap/spaces.h
+++ b/src/heap/spaces.h
@@ -1104,6 +1104,12 @@
     return CodePageAreaEndOffset() - CodePageAreaStartOffset();
   }
 
+  static int PageAreaSize(AllocationSpace space) {
+    DCHECK_NE(LO_SPACE, space);
+    return (space == CODE_SPACE) ? CodePageAreaSize()
+                                 : Page::kMaxRegularHeapObjectSize;
+  }
+
   MUST_USE_RESULT bool CommitExecutableMemory(base::VirtualMemory* vm,
                                               Address start, size_t commit_size,
                                               size_t reserved_size);
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index d6acd1e..810a2fd 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -11,9 +11,9 @@
 
 #include "src/allocation.h"
 #include "src/base/bits.h"
+#include "src/bit-vector.h"
 #include "src/code-stubs.h"
 #include "src/conversions.h"
-#include "src/data-flow.h"
 #include "src/deoptimizer.h"
 #include "src/hydrogen-types.h"
 #include "src/small-pointer-list.h"
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index d058ae0..9dab155 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -6941,6 +6941,12 @@
 }
 
 
+static bool CanInlineElementAccess(Handle<Map> map) {
+  return map->IsJSObjectMap() && !map->has_slow_elements_kind() &&
+         !map->has_indexed_interceptor();
+}
+
+
 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
     HValue* object,
     HValue* key,
@@ -6958,7 +6964,7 @@
   Handle<Map> most_general_consolidated_map;
   for (int i = 0; i < maps->length(); ++i) {
     Handle<Map> map = maps->at(i);
-    if (!map->IsJSObjectMap()) return NULL;
+    if (!CanInlineElementAccess(map)) return NULL;
     // Don't allow mixing of JSArrays with JSObjects.
     if (map->instance_type() == JS_ARRAY_TYPE) {
       if (has_non_js_array_access) return NULL;
@@ -7036,7 +7042,7 @@
     Handle<Map> map = maps->at(i);
     DCHECK(!map->IsStringMap());
     ElementsKind elements_kind = map->elements_kind();
-    if (IsFastElementsKind(elements_kind) &&
+    if (CanInlineElementAccess(map) && IsFastElementsKind(elements_kind) &&
         elements_kind != GetInitialFastElementsKind()) {
       possible_transitioned_maps.Add(map);
     }
@@ -7077,8 +7083,7 @@
   if (untransitionable_maps.length() == 1) {
     Handle<Map> untransitionable_map = untransitionable_maps[0];
     HInstruction* instr = NULL;
-    if (untransitionable_map->has_slow_elements_kind() ||
-        !untransitionable_map->IsJSObjectMap()) {
+    if (!CanInlineElementAccess(untransitionable_map)) {
       instr = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key,
                                                val));
     } else {
@@ -7094,7 +7099,6 @@
 
   for (int i = 0; i < untransitionable_maps.length(); ++i) {
     Handle<Map> map = untransitionable_maps[i];
-    if (!map->IsJSObjectMap()) continue;
     ElementsKind elements_kind = map->elements_kind();
     HBasicBlock* this_map = graph()->CreateBasicBlock();
     HBasicBlock* other_map = graph()->CreateBasicBlock();
@@ -7104,7 +7108,7 @@
 
     set_current_block(this_map);
     HInstruction* access = NULL;
-    if (IsDictionaryElementsKind(elements_kind)) {
+    if (!CanInlineElementAccess(map)) {
       access = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key,
                                                 val));
     } else {
@@ -7215,7 +7219,7 @@
 
   if (monomorphic) {
     Handle<Map> map = types->first();
-    if (map->has_slow_elements_kind() || !map->IsJSObjectMap()) {
+    if (!CanInlineElementAccess(map)) {
       instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key,
                                                val));
     } else {
diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc
index aa78837..50c834f 100644
--- a/src/ia32/assembler-ia32.cc
+++ b/src/ia32/assembler-ia32.cc
@@ -1969,15 +1969,6 @@
 }
 
 
-void Assembler::addsd(XMMRegister dst, XMMRegister src) {
-  EnsureSpace ensure_space(this);
-  EMIT(0xF2);
-  EMIT(0x0F);
-  EMIT(0x58);
-  emit_sse_operand(dst, src);
-}
-
-
 void Assembler::addsd(XMMRegister dst, const Operand& src) {
   EnsureSpace ensure_space(this);
   EMIT(0xF2);
@@ -1987,15 +1978,6 @@
 }
 
 
-void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
-  EnsureSpace ensure_space(this);
-  EMIT(0xF2);
-  EMIT(0x0F);
-  EMIT(0x59);
-  emit_sse_operand(dst, src);
-}
-
-
 void Assembler::mulsd(XMMRegister dst, const Operand& src) {
   EnsureSpace ensure_space(this);
   EMIT(0xF2);
@@ -2005,15 +1987,6 @@
 }
 
 
-void Assembler::subsd(XMMRegister dst, XMMRegister src) {
-  EnsureSpace ensure_space(this);
-  EMIT(0xF2);
-  EMIT(0x0F);
-  EMIT(0x5C);
-  emit_sse_operand(dst, src);
-}
-
-
 void Assembler::subsd(XMMRegister dst, const Operand& src) {
   EnsureSpace ensure_space(this);
   EMIT(0xF2);
@@ -2023,7 +1996,7 @@
 }
 
 
-void Assembler::divsd(XMMRegister dst, XMMRegister src) {
+void Assembler::divsd(XMMRegister dst, const Operand& src) {
   EnsureSpace ensure_space(this);
   EMIT(0xF2);
   EMIT(0x0F);
@@ -2097,15 +2070,6 @@
 }
 
 
-void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) {
-  EnsureSpace ensure_space(this);
-  EMIT(0xF2);
-  EMIT(0x0F);
-  EMIT(0x51);
-  emit_sse_operand(dst, src);
-}
-
-
 void Assembler::sqrtsd(XMMRegister dst, const Operand& src) {
   EnsureSpace ensure_space(this);
   EMIT(0xF2);
diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h
index 1b1d350..00ee959 100644
--- a/src/ia32/assembler-ia32.h
+++ b/src/ia32/assembler-ia32.h
@@ -966,15 +966,16 @@
   void cvtsd2ss(XMMRegister dst, XMMRegister src) {
     cvtsd2ss(dst, Operand(src));
   }
-  void addsd(XMMRegister dst, XMMRegister src);
+  void addsd(XMMRegister dst, XMMRegister src) { addsd(dst, Operand(src)); }
   void addsd(XMMRegister dst, const Operand& src);
-  void subsd(XMMRegister dst, XMMRegister src);
+  void subsd(XMMRegister dst, XMMRegister src) { subsd(dst, Operand(src)); }
   void subsd(XMMRegister dst, const Operand& src);
-  void mulsd(XMMRegister dst, XMMRegister src);
+  void mulsd(XMMRegister dst, XMMRegister src) { mulsd(dst, Operand(src)); }
   void mulsd(XMMRegister dst, const Operand& src);
-  void divsd(XMMRegister dst, XMMRegister src);
+  void divsd(XMMRegister dst, XMMRegister src) { divsd(dst, Operand(src)); }
+  void divsd(XMMRegister dst, const Operand& src);
   void xorpd(XMMRegister dst, XMMRegister src);
-  void sqrtsd(XMMRegister dst, XMMRegister src);
+  void sqrtsd(XMMRegister dst, XMMRegister src) { sqrtsd(dst, Operand(src)); }
   void sqrtsd(XMMRegister dst, const Operand& src);
 
   void andpd(XMMRegister dst, XMMRegister src);
diff --git a/src/messages.js b/src/messages.js
index a9da851..b15ccc6 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -20,6 +20,7 @@
   unexpected_strict_reserved:    ["Unexpected strict mode reserved word"],
   unexpected_eos:                ["Unexpected end of input"],
   malformed_regexp:              ["Invalid regular expression: /", "%0", "/: ", "%1"],
+  malformed_regexp_flags:        ["Invalid regular expression flags"],
   unterminated_regexp:           ["Invalid regular expression: missing /"],
   regexp_flags:                  ["Cannot supply flags when constructing one RegExp from another"],
   incompatible_method_receiver:  ["Method ", "%0", " called on incompatible receiver ", "%1"],
diff --git a/src/mips64/builtins-mips64.cc b/src/mips64/builtins-mips64.cc
index e5f733c..f4bd386 100644
--- a/src/mips64/builtins-mips64.cc
+++ b/src/mips64/builtins-mips64.cc
@@ -782,11 +782,6 @@
     // a3: argc
     // s0: argv, i.e. points to first arg
     Label loop, entry;
-    // TODO(plind): At least on simulator, argc in a3 is an int32_t with junk
-    //    in upper bits. Should fix the root cause, rather than use below
-    //    workaround to clear upper bits.
-    __ dsll32(a3, a3, 0);  // int32_t -> int64_t.
-    __ dsrl32(a3, a3, 0);
     __ dsll(a4, a3, kPointerSizeLog2);
     __ daddu(a6, s0, a4);
     __ b(&entry);
diff --git a/src/mips64/simulator-mips64.h b/src/mips64/simulator-mips64.h
index 5241554..3087dcd 100644
--- a/src/mips64/simulator-mips64.h
+++ b/src/mips64/simulator-mips64.h
@@ -436,9 +436,12 @@
 
 // When running with the simulator transition into simulated execution at this
 // point.
-#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
-    reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->Call( \
-      FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4))
+#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4)                    \
+  reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->Call( \
+      FUNCTION_ADDR(entry), 5, reinterpret_cast<int64_t*>(p0),            \
+      reinterpret_cast<int64_t*>(p1), reinterpret_cast<int64_t*>(p2),     \
+      reinterpret_cast<int64_t*>(p3), reinterpret_cast<int64_t*>(p4)))
+
 
 #ifdef MIPS_ABI_N64
 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index 92bd97a..353cfda 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -1218,6 +1218,24 @@
 }
 
 
+void Code::VerifyEmbeddedObjectsInFullCode() {
+  // Check that no context-specific object has been embedded.
+  Heap* heap = GetIsolate()->heap();
+  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
+  for (RelocIterator it(this, mask); !it.done(); it.next()) {
+    Object* obj = it.rinfo()->target_object();
+    if (obj->IsCell()) obj = Cell::cast(obj)->value();
+    if (obj->IsPropertyCell()) obj = PropertyCell::cast(obj)->value();
+    if (!obj->IsHeapObject()) continue;
+    Map* map = obj->IsMap() ? Map::cast(obj) : HeapObject::cast(obj)->map();
+    int i = 0;
+    while (map != heap->roots_array_start()[i++]) {
+      CHECK_LT(i, Heap::kStrongRootListLength);
+    }
+  }
+}
+
+
 #endif  // DEBUG
 
 } }  // namespace v8::internal
diff --git a/src/objects.cc b/src/objects.cc
index ea07582..7cc9266 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -13643,7 +13643,11 @@
 
   bool IsMatch(Object* other) OVERRIDE {
     DisallowHeapAllocation no_allocation;
-    if (!other->IsFixedArray()) return false;
+    if (!other->IsFixedArray()) {
+      if (!other->IsNumber()) return false;
+      uint32_t other_hash = static_cast<uint32_t>(other->Number());
+      return Hash() == other_hash;
+    }
     FixedArray* other_array = FixedArray::cast(other);
     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
     if (shared != *shared_) return false;
@@ -13683,6 +13687,9 @@
 
   uint32_t HashForObject(Object* obj) OVERRIDE {
     DisallowHeapAllocation no_allocation;
+    if (obj->IsNumber()) {
+      return static_cast<uint32_t>(obj->Number());
+    }
     FixedArray* other_array = FixedArray::cast(obj);
     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
     String* source = String::cast(other_array->get(1));
@@ -14841,7 +14848,9 @@
                       RelocInfo::kNoPosition);
   int entry = FindEntry(&key);
   if (entry == kNotFound) return isolate->factory()->undefined_value();
-  return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
+  int index = EntryToIndex(entry);
+  if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
+  return Handle<Object>(get(index + 1), isolate);
 }
 
 
@@ -14854,6 +14863,8 @@
   StringSharedKey key(src, outer_info, strict_mode, scope_position);
   int entry = FindEntry(&key);
   if (entry == kNotFound) return isolate->factory()->undefined_value();
+  int index = EntryToIndex(entry);
+  if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
 }
 
@@ -14876,11 +14887,20 @@
   Handle<SharedFunctionInfo> shared(context->closure()->shared());
   StringSharedKey key(src, shared, FLAG_use_strict ? STRICT : SLOPPY,
                       RelocInfo::kNoPosition);
+  int entry = cache->FindEntry(&key);
+  if (entry != kNotFound) {
+    Handle<Object> k = key.AsHandle(isolate);
+    cache->set(EntryToIndex(entry), *k);
+    cache->set(EntryToIndex(entry) + 1, *value);
+    return cache;
+  }
+
   cache = EnsureCapacity(cache, 1, &key);
-  Handle<Object> k = key.AsHandle(isolate);
-  int entry = cache->FindInsertionEntry(key.Hash());
+  entry = cache->FindInsertionEntry(key.Hash());
+  Handle<Object> k =
+      isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
   cache->set(EntryToIndex(entry), *k);
-  cache->set(EntryToIndex(entry) + 1, *value);
+  cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
   cache->ElementAdded();
   return cache;
 }
@@ -14892,11 +14912,20 @@
     int scope_position) {
   Isolate* isolate = cache->GetIsolate();
   StringSharedKey key(src, outer_info, value->strict_mode(), scope_position);
+  int entry = cache->FindEntry(&key);
+  if (entry != kNotFound) {
+    Handle<Object> k = key.AsHandle(isolate);
+    cache->set(EntryToIndex(entry), *k);
+    cache->set(EntryToIndex(entry) + 1, *value);
+    return cache;
+  }
+
   cache = EnsureCapacity(cache, 1, &key);
-  Handle<Object> k = key.AsHandle(isolate);
-  int entry = cache->FindInsertionEntry(key.Hash());
+  entry = cache->FindInsertionEntry(key.Hash());
+  Handle<Object> k =
+      isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
   cache->set(EntryToIndex(entry), *k);
-  cache->set(EntryToIndex(entry) + 1, *value);
+  cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
   cache->ElementAdded();
   return cache;
 }
@@ -14917,6 +14946,35 @@
 }
 
 
+void CompilationCacheTable::Age() {
+  DisallowHeapAllocation no_allocation;
+  Object* the_hole_value = GetHeap()->the_hole_value();
+  for (int entry = 0, size = Capacity(); entry < size; entry++) {
+    int entry_index = EntryToIndex(entry);
+    int value_index = entry_index + 1;
+
+    if (get(entry_index)->IsNumber()) {
+      Smi* count = Smi::cast(get(value_index));
+      count = Smi::FromInt(count->value() - 1);
+      if (count->value() == 0) {
+        NoWriteBarrierSet(this, entry_index, the_hole_value);
+        NoWriteBarrierSet(this, value_index, the_hole_value);
+        ElementRemoved();
+      } else {
+        NoWriteBarrierSet(this, value_index, count);
+      }
+    } else if (get(entry_index)->IsFixedArray()) {
+      SharedFunctionInfo* info = SharedFunctionInfo::cast(get(value_index));
+      if (info->code()->kind() != Code::FUNCTION || info->code()->IsOld()) {
+        NoWriteBarrierSet(this, entry_index, the_hole_value);
+        NoWriteBarrierSet(this, value_index, the_hole_value);
+        ElementRemoved();
+      }
+    }
+  }
+}
+
+
 void CompilationCacheTable::Remove(Object* value) {
   DisallowHeapAllocation no_allocation;
   Object* the_hole_value = GetHeap()->the_hole_value();
diff --git a/src/objects.h b/src/objects.h
index d513f97..985d227 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -5362,6 +5362,10 @@
   void VerifyEmbeddedObjectsDependency();
 #endif
 
+#ifdef DEBUG
+  void VerifyEmbeddedObjectsInFullCode();
+#endif  // DEBUG
+
   inline bool CanContainWeakObjects() {
     return is_optimized_code() || is_weak_stub();
   }
@@ -7937,6 +7941,17 @@
 };
 
 
+// This cache is used in two different variants. For regexp caching, it simply
+// maps identifying info of the regexp to the cached regexp object. Scripts and
+// eval code only gets cached after a second probe for the code object. To do
+// so, on first "put" only a hash identifying the source is entered into the
+// cache, mapping it to a lifetime count of the hash. On each call to Age all
+// such lifetimes get reduced, and removed once they reach zero. If a second put
+// is called while such a hash is live in the cache, the hash gets replaced by
+// an actual cache entry. Age also removes stale live entries from the cache.
+// Such entries are identified by SharedFunctionInfos pointing to either the
+// recompilation stub, or to "old" code. This avoids memory leaks due to
+// premature caching of scripts and eval strings that are never needed later.
 class CompilationCacheTable: public HashTable<CompilationCacheTable,
                                               CompilationCacheShape,
                                               HashTableKey*> {
@@ -7958,6 +7973,8 @@
       Handle<CompilationCacheTable> cache, Handle<String> src,
       JSRegExp::Flags flags, Handle<FixedArray> value);
   void Remove(Object* value);
+  void Age();
+  static const int kHashGenerations = 10;
 
   DECLARE_CAST(CompilationCacheTable)
 
diff --git a/src/preparser.h b/src/preparser.h
index 2db88e7..3a2e28f 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -1704,7 +1704,7 @@
   IdentifierT js_pattern = this->GetNextSymbol(scanner());
   if (!scanner()->ScanRegExpFlags()) {
     Next();
-    ReportMessage("invalid_regexp_flags");
+    ReportMessage("malformed_regexp_flags");
     *ok = false;
     return Traits::EmptyExpression();
   }
diff --git a/src/runtime/runtime-collections.cc b/src/runtime/runtime-collections.cc
index c4f7418..c1a63dc 100644
--- a/src/runtime/runtime-collections.cc
+++ b/src/runtime/runtime-collections.cc
@@ -288,6 +288,10 @@
   Handle<ObjectHashTable> new_table =
       ObjectHashTable::Remove(table, key, &was_present);
   weak_collection->set_table(*new_table);
+  if (*table != *new_table) {
+    // Zap the old table since we didn't record slots for its elements.
+    table->FillWithHoles(0, table->length());
+  }
   return isolate->heap()->ToBoolean(was_present);
 }
 
@@ -304,6 +308,10 @@
   RUNTIME_ASSERT(table->IsKey(*key));
   Handle<ObjectHashTable> new_table = ObjectHashTable::Put(table, key, value);
   weak_collection->set_table(*new_table);
+  if (*table != *new_table) {
+    // Zap the old table since we didn't record slots for its elements.
+    table->FillWithHoles(0, table->length());
+  }
   return *weak_collection;
 }
 
diff --git a/src/scanner.cc b/src/scanner.cc
index 0709939..dc15e37 100644
--- a/src/scanner.cc
+++ b/src/scanner.cc
@@ -57,20 +57,10 @@
 uc32 Scanner::ScanHexNumber(int expected_length) {
   DCHECK(expected_length <= 4);  // prevent overflow
 
-  uc32 digits[4] = { 0, 0, 0, 0 };
   uc32 x = 0;
   for (int i = 0; i < expected_length; i++) {
-    digits[i] = c0_;
     int d = HexValue(c0_);
     if (d < 0) {
-      // According to ECMA-262, 3rd, 7.8.4, page 18, these hex escapes
-      // should be illegal, but other JS VMs just return the
-      // non-escaped version of the original character.
-
-      // Push back digits that we have advanced past.
-      for (int j = i-1; j >= 0; j--) {
-        PushBack(digits[j]);
-      }
       return -1;
     }
     x = x * 16 + d;
@@ -894,9 +884,7 @@
   Advance();
   if (c0_ != 'u') return -1;
   Advance();
-  uc32 result = ScanHexNumber(4);
-  if (result < 0) PushBack('u');
-  return result;
+  return ScanHexNumber(4);
 }
 
 
@@ -1145,31 +1133,19 @@
 
 bool Scanner::ScanLiteralUnicodeEscape() {
   DCHECK(c0_ == '\\');
-  uc32 chars_read[6] = {'\\', 'u', 0, 0, 0, 0};
+  AddLiteralChar(c0_);
   Advance();
-  int i = 1;
+  int hex_digits_read = 0;
   if (c0_ == 'u') {
-    i++;
-    while (i < 6) {
+    AddLiteralChar(c0_);
+    while (hex_digits_read < 4) {
       Advance();
       if (!IsHexDigit(c0_)) break;
-      chars_read[i] = c0_;
-      i++;
+      AddLiteralChar(c0_);
+      ++hex_digits_read;
     }
   }
-  if (i < 6) {
-    // Incomplete escape. Undo all advances and return false.
-    while (i > 0) {
-      i--;
-      PushBack(chars_read[i]);
-    }
-    return false;
-  }
-  // Complete escape. Add all chars to current literal buffer.
-  for (int i = 0; i < 6; i++) {
-    AddLiteralChar(chars_read[i]);
-  }
-  return true;
+  return hex_digits_read == 4;
 }
 
 
@@ -1181,7 +1157,7 @@
       AddLiteralCharAdvance();
     } else {
       if (!ScanLiteralUnicodeEscape()) {
-        break;
+        return false;
       }
       Advance();
     }
diff --git a/src/serialize.cc b/src/serialize.cc
index 86045d3..df62adb 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -1258,10 +1258,15 @@
       external_reference_encoder_(new ExternalReferenceEncoder(isolate)),
       root_index_map_(isolate),
       code_address_map_(NULL),
+      large_objects_total_size_(0),
       seen_large_objects_index_(0) {
   // The serializer is meant to be used only to generate initial heap images
   // from a context in which there is only one isolate.
-  for (int i = 0; i < kNumberOfSpaces; i++) pending_chunk_[i] = 0;
+  for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
+    pending_chunk_[i] = 0;
+    max_chunk_size_[i] = static_cast<uint32_t>(
+        MemoryAllocator::PageAreaSize(static_cast<AllocationSpace>(i)));
+  }
 }
 
 
@@ -1336,8 +1341,7 @@
 
 
 void Serializer::FinalizeAllocation() {
-  DCHECK_EQ(0, completed_chunks_[LO_SPACE].length());  // Not yet finalized.
-  for (int i = 0; i < kNumberOfSpaces; i++) {
+  for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
     // Complete the last pending chunk and if there are no completed chunks,
     // make sure there is at least one empty chunk.
     if (pending_chunk_[i] > 0 || completed_chunks_[i].length() == 0) {
@@ -1906,16 +1910,16 @@
 BackReference Serializer::AllocateLargeObject(int size) {
   // Large objects are allocated one-by-one when deserializing. We do not
   // have to keep track of multiple chunks.
-  pending_chunk_[LO_SPACE] += size;
+  large_objects_total_size_ += size;
   return BackReference::LargeObjectReference(seen_large_objects_index_++);
 }
 
 
 BackReference Serializer::Allocate(AllocationSpace space, int size) {
   CHECK(space >= 0 && space < kNumberOfPreallocatedSpaces);
-  DCHECK(size > 0 && size <= Page::kMaxRegularHeapObjectSize);
+  DCHECK(size > 0 && size <= static_cast<int>(max_chunk_size(space)));
   uint32_t new_chunk_size = pending_chunk_[space] + size;
-  if (new_chunk_size > static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize)) {
+  if (new_chunk_size > max_chunk_size(space)) {
     // The new chunk size would not fit onto a single page. Complete the
     // current chunk and start a new one.
     completed_chunks_[space].Add(pending_chunk_[space]);
@@ -1929,15 +1933,6 @@
 }
 
 
-int Serializer::SpaceAreaSize(int space) {
-  if (space == CODE_SPACE) {
-    return isolate_->memory_allocator()->CodePageAreaSize();
-  } else {
-    return Page::kPageSize - Page::kObjectStartOffset;
-  }
-}
-
-
 void Serializer::Pad() {
   // The non-branching GetInt will read up to 3 bytes too far, so we need
   // to pad the snapshot to make sure we don't read over the end.
@@ -2273,9 +2268,6 @@
   for (int i = 0; i < SerializerDeserializer::kNumberOfSpaces; i++) {
     Vector<const uint32_t> chunks = cs->FinalAllocationChunks(i);
     for (int j = 0; j < chunks.length(); j++) {
-      DCHECK(i == LO_SPACE ||
-             chunks[j] <=
-                 static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize));
       uint32_t chunk = ChunkSizeBits::encode(chunks[j]) |
                        IsLastChunkBits::encode(j == chunks.length() - 1);
       reservations.Add(chunk);
diff --git a/src/serialize.h b/src/serialize.h
index 2aa55ea..9c56118 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -404,8 +404,6 @@
   void AddReservation(int space, uint32_t chunk) {
     DCHECK(space >= 0);
     DCHECK(space < kNumberOfSpaces);
-    DCHECK(space == LO_SPACE ||
-           chunk <= static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize));
     reservations_[space].Add({chunk, NULL, NULL});
   }
 
@@ -498,9 +496,12 @@
   void FinalizeAllocation();
 
   Vector<const uint32_t> FinalAllocationChunks(int space) const {
-    DCHECK_EQ(1, completed_chunks_[LO_SPACE].length());  // Already finalized.
-    DCHECK_EQ(0, pending_chunk_[space]);                 // No pending chunks.
-    return completed_chunks_[space].ToConstVector();
+    if (space == LO_SPACE) {
+      return Vector<const uint32_t>(&large_objects_total_size_, 1);
+    } else {
+      DCHECK_EQ(0, pending_chunk_[space]);  // No pending chunks.
+      return completed_chunks_[space].ToConstVector();
+    }
   }
 
   Isolate* isolate() const { return isolate_; }
@@ -580,39 +581,48 @@
     return external_reference_encoder_->Encode(addr);
   }
 
-  int SpaceAreaSize(int space);
+  // GetInt reads 4 bytes at once, requiring padding at the end.
+  void Pad();
 
   // Some roots should not be serialized, because their actual value depends on
   // absolute addresses and they are reset after deserialization, anyway.
   bool ShouldBeSkipped(Object** current);
 
-  Isolate* isolate_;
+  // We may not need the code address map for logging for every instance
+  // of the serializer.  Initialize it on demand.
+  void InitializeCodeAddressMap();
 
-  // Objects from the same space are put into chunks for bulk-allocation
-  // when deserializing. We have to make sure that each chunk fits into a
-  // page. So we track the chunk size in pending_chunk_ of a space, but
-  // when it exceeds a page, we complete the current chunk and start a new one.
-  uint32_t pending_chunk_[kNumberOfSpaces];
-  List<uint32_t> completed_chunks_[kNumberOfSpaces];
+  inline uint32_t max_chunk_size(int space) const {
+    DCHECK_LE(0, space);
+    DCHECK_LT(space, kNumberOfSpaces);
+    return max_chunk_size_[space];
+  }
+
+  Isolate* isolate_;
 
   SnapshotByteSink* sink_;
   ExternalReferenceEncoder* external_reference_encoder_;
 
   BackReferenceMap back_reference_map_;
   RootIndexMap root_index_map_;
-  void Pad();
 
   friend class ObjectSerializer;
   friend class Deserializer;
 
-  // We may not need the code address map for logging for every instance
-  // of the serializer.  Initialize it on demand.
-  void InitializeCodeAddressMap();
-
  private:
   CodeAddressMap* code_address_map_;
+  // Objects from the same space are put into chunks for bulk-allocation
+  // when deserializing. We have to make sure that each chunk fits into a
+  // page. So we track the chunk size in pending_chunk_ of a space, but
+  // when it exceeds a page, we complete the current chunk and start a new one.
+  uint32_t pending_chunk_[kNumberOfPreallocatedSpaces];
+  List<uint32_t> completed_chunks_[kNumberOfPreallocatedSpaces];
+  uint32_t max_chunk_size_[kNumberOfPreallocatedSpaces];
+
   // We map serialized large objects to indexes for back-referencing.
+  uint32_t large_objects_total_size_;
   uint32_t seen_large_objects_index_;
+
   DISALLOW_COPY_AND_ASSIGN(Serializer);
 };
 
diff --git a/src/version.cc b/src/version.cc
index 86ffc02..3be87c9 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     30
-#define BUILD_NUMBER      23
+#define BUILD_NUMBER      28
 #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/assembler-x64.cc b/src/x64/assembler-x64.cc
index 7965e77..6e12458 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -2875,6 +2875,16 @@
 }
 
 
+void Assembler::subsd(XMMRegister dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  emit(0xF2);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x5C);
+  emit_sse_operand(dst, src);
+}
+
+
 void Assembler::divsd(XMMRegister dst, XMMRegister src) {
   EnsureSpace ensure_space(this);
   emit(0xF2);
@@ -2885,6 +2895,16 @@
 }
 
 
+void Assembler::divsd(XMMRegister dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  emit(0xF2);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x5E);
+  emit_sse_operand(dst, src);
+}
+
+
 void Assembler::andpd(XMMRegister dst, XMMRegister src) {
   EnsureSpace ensure_space(this);
   emit(0x66);
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index c046771..d938046 100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -1087,9 +1087,11 @@
   void addsd(XMMRegister dst, XMMRegister src);
   void addsd(XMMRegister dst, const Operand& src);
   void subsd(XMMRegister dst, XMMRegister src);
+  void subsd(XMMRegister dst, const Operand& src);
   void mulsd(XMMRegister dst, XMMRegister src);
   void mulsd(XMMRegister dst, const Operand& src);
   void divsd(XMMRegister dst, XMMRegister src);
+  void divsd(XMMRegister dst, const Operand& src);
 
   void andpd(XMMRegister dst, XMMRegister src);
   void orpd(XMMRegister dst, XMMRegister src);
diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp
index 1dcd35b..d762c45 100644
--- a/test/cctest/cctest.gyp
+++ b/test/cctest/cctest.gyp
@@ -102,13 +102,13 @@
         'test-atomicops.cc',
         'test-bignum.cc',
         'test-bignum-dtoa.cc',
+        'test-bit-vector.cc',
         'test-checks.cc',
         'test-circular-queue.cc',
         'test-compiler.cc',
         'test-constantpool.cc',
         'test-conversions.cc',
         'test-cpu-profiler.cc',
-        'test-dataflow.cc',
         'test-date.cc',
         'test-debug.cc',
         'test-declarative-accessors.cc',
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index b61be30..0b76995 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -299,6 +299,16 @@
 }],  # 'arch == mipsel or arch == mips'
 
 ##############################################################################
+['arch == mips', {
+  # Too slow with TF.
+  'test-api/ExternalArrays': [PASS, NO_VARIANTS],
+
+  # TODO(mips-team): Currently fails on mips board.
+  'test-simplified-lowering/RunNumberMultiply_TruncatingToUint32': [SKIP],
+  'test-parsing/TooManyArguments': [SKIP],
+}],  # 'arch == mips'
+
+##############################################################################
 ['arch == mips64el', {
 
   # BUG(2657): Test sometimes times out on MIPS simulator.
diff --git a/test/cctest/compiler/test-simplified-lowering.cc b/test/cctest/compiler/test-simplified-lowering.cc
index dcbb9c8..5ddc10d 100644
--- a/test/cctest/compiler/test-simplified-lowering.cc
+++ b/test/cctest/compiler/test-simplified-lowering.cc
@@ -1957,3 +1957,51 @@
     }
   }
 }
+
+
+TEST(PhiRepresentation) {
+  HandleAndZoneScope scope;
+  Zone* z = scope.main_zone();
+
+  Factory* f = z->isolate()->factory();
+  Handle<Object> range_min = f->NewNumber(-1e13);
+  Handle<Object> range_max = f->NewNumber(1e+15);
+  Type* range = Type::Range(range_min, range_max, z);
+
+  struct TestData {
+    Type* arg1;
+    Type* arg2;
+    MachineType use;
+    MachineTypeUnion expected;
+  };
+
+  TestData test_data[] = {
+      {Type::Signed32(), Type::Unsigned32(), kMachInt32,
+       kRepWord32 | kTypeNumber},
+      {range, range, kMachUint32, kRepWord32 | kTypeNumber},
+      {Type::Signed32(), Type::Signed32(), kMachInt32, kMachInt32},
+      {Type::Unsigned32(), Type::Unsigned32(), kMachInt32, kMachUint32},
+      {Type::Number(), Type::Signed32(), kMachInt32, kMachFloat64},
+      {Type::Signed32(), Type::String(), kMachInt32, kMachAnyTagged}};
+
+  for (auto const d : test_data) {
+    TestingGraph t(d.arg1, d.arg2, Type::Boolean());
+
+    Node* br = t.graph()->NewNode(t.common()->Branch(), t.p2, t.start);
+    Node* tb = t.graph()->NewNode(t.common()->IfTrue(), br);
+    Node* fb = t.graph()->NewNode(t.common()->IfFalse(), br);
+    Node* m = t.graph()->NewNode(t.common()->Merge(2), tb, fb);
+
+    Node* phi =
+        t.graph()->NewNode(t.common()->Phi(kMachAnyTagged, 2), t.p0, t.p1, m);
+
+    Bounds phi_bounds = Bounds::Either(Bounds(d.arg1), Bounds(d.arg2), z);
+    NodeProperties::SetBounds(phi, phi_bounds);
+
+    Node* use = t.Use(phi, d.use);
+    t.Return(use);
+    t.Lower();
+
+    CHECK_EQ(d.expected, OpParameter<MachineType>(phi));
+  }
+}
diff --git a/test/cctest/test-dataflow.cc b/test/cctest/test-bit-vector.cc
similarity index 98%
rename from test/cctest/test-dataflow.cc
rename to test/cctest/test-bit-vector.cc
index 43d950d..ac00fab 100644
--- a/test/cctest/test-dataflow.cc
+++ b/test/cctest/test-bit-vector.cc
@@ -29,7 +29,7 @@
 
 #include "src/v8.h"
 
-#include "src/data-flow.h"
+#include "src/bit-vector.h"
 #include "test/cctest/cctest.h"
 
 using namespace v8::internal;
@@ -83,7 +83,7 @@
     BitVector v(15, &zone);
     v.Add(0);
     BitVector w(15, &zone);
-    w = v;
+    w.CopyFrom(v);
     CHECK(w.Contains(0));
     w.Add(1);
     BitVector u(w, &zone);
diff --git a/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc
index 01628d2..755c9d5 100644
--- a/test/cctest/test-disasm-ia32.cc
+++ b/test/cctest/test-disasm-ia32.cc
@@ -424,10 +424,13 @@
     __ movdqu(Operand(ebx, ecx, times_4, 10000), xmm0);
 
     __ addsd(xmm1, xmm0);
+    __ addsd(xmm1, Operand(ebx, ecx, times_4, 10000));
     __ mulsd(xmm1, xmm0);
+    __ mulsd(xmm1, Operand(ebx, ecx, times_4, 10000));
     __ subsd(xmm1, xmm0);
     __ subsd(xmm1, Operand(ebx, ecx, times_4, 10000));
     __ divsd(xmm1, xmm0);
+    __ divsd(xmm1, Operand(ebx, ecx, times_4, 10000));
     __ ucomisd(xmm0, xmm1);
     __ cmpltsd(xmm0, xmm1);
 
diff --git a/test/cctest/test-disasm-x64.cc b/test/cctest/test-disasm-x64.cc
index 004229d..4ae3608 100644
--- a/test/cctest/test-disasm-x64.cc
+++ b/test/cctest/test-disasm-x64.cc
@@ -417,9 +417,13 @@
     __ movdqa(Operand(rbx, rcx, times_4, 10000), xmm0);
 
     __ addsd(xmm1, xmm0);
+    __ addsd(xmm1, Operand(rbx, rcx, times_4, 10000));
     __ mulsd(xmm1, xmm0);
+    __ mulsd(xmm1, Operand(rbx, rcx, times_4, 10000));
     __ subsd(xmm1, xmm0);
+    __ subsd(xmm1, Operand(rbx, rcx, times_4, 10000));
     __ divsd(xmm1, xmm0);
+    __ divsd(xmm1, Operand(rbx, rcx, times_4, 10000));
     __ ucomisd(xmm0, xmm1);
 
     __ andpd(xmm0, xmm1);
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index ac121e0..6ba59cb 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -1375,6 +1375,98 @@
 }
 
 
+TEST(CompilationCacheCachingBehavior) {
+  // If we do not flush code, or have the compilation cache turned off, this
+  // test is invalid.
+  if (!FLAG_flush_code || !FLAG_flush_code_incrementally ||
+      !FLAG_compilation_cache) {
+    return;
+  }
+  CcTest::InitializeVM();
+  Isolate* isolate = CcTest::i_isolate();
+  Factory* factory = isolate->factory();
+  Heap* heap = isolate->heap();
+  CompilationCache* compilation_cache = isolate->compilation_cache();
+
+  v8::HandleScope scope(CcTest::isolate());
+  const char* raw_source =
+      "function foo() {"
+      "  var x = 42;"
+      "  var y = 42;"
+      "  var z = x + y;"
+      "};"
+      "foo()";
+  Handle<String> source = factory->InternalizeUtf8String(raw_source);
+  Handle<Context> native_context = isolate->native_context();
+
+  {
+    v8::HandleScope scope(CcTest::isolate());
+    CompileRun(raw_source);
+  }
+
+  // On first compilation, only a hash is inserted in the code cache. We can't
+  // find that value.
+  MaybeHandle<SharedFunctionInfo> info = compilation_cache->LookupScript(
+      source, Handle<Object>(), 0, 0, true, native_context);
+  CHECK(info.is_null());
+
+  {
+    v8::HandleScope scope(CcTest::isolate());
+    CompileRun(raw_source);
+  }
+
+  // On second compilation, the hash is replaced by a real cache entry mapping
+  // the source to the shared function info containing the code.
+  info = compilation_cache->LookupScript(source, Handle<Object>(), 0, 0, true,
+                                         native_context);
+  CHECK(!info.is_null());
+
+  heap->CollectAllGarbage(Heap::kNoGCFlags);
+
+  // On second compilation, the hash is replaced by a real cache entry mapping
+  // the source to the shared function info containing the code.
+  info = compilation_cache->LookupScript(source, Handle<Object>(), 0, 0, true,
+                                         native_context);
+  CHECK(!info.is_null());
+
+  while (!info.ToHandleChecked()->code()->IsOld()) {
+    info.ToHandleChecked()->code()->MakeOlder(NO_MARKING_PARITY);
+  }
+
+  heap->CollectAllGarbage(Heap::kNoGCFlags);
+  // Ensure code aging cleared the entry from the cache.
+  info = compilation_cache->LookupScript(source, Handle<Object>(), 0, 0, true,
+                                         native_context);
+  CHECK(info.is_null());
+
+  {
+    v8::HandleScope scope(CcTest::isolate());
+    CompileRun(raw_source);
+  }
+
+  // On first compilation, only a hash is inserted in the code cache. We can't
+  // find that value.
+  info = compilation_cache->LookupScript(source, Handle<Object>(), 0, 0, true,
+                                         native_context);
+  CHECK(info.is_null());
+
+  for (int i = 0; i < CompilationCacheTable::kHashGenerations; i++) {
+    compilation_cache->MarkCompactPrologue();
+  }
+
+  {
+    v8::HandleScope scope(CcTest::isolate());
+    CompileRun(raw_source);
+  }
+
+  // If we aged the cache before caching the script, ensure that we didn't cache
+  // on next compilation.
+  info = compilation_cache->LookupScript(source, Handle<Object>(), 0, 0, true,
+                                         native_context);
+  CHECK(info.is_null());
+}
+
+
 // Count the number of native contexts in the weak list of native contexts.
 int CountNativeContexts() {
   int count = 0;
@@ -4608,6 +4700,46 @@
 }
 
 
+TEST(Regress3631) {
+  i::FLAG_expose_gc = true;
+  CcTest::InitializeVM();
+  v8::HandleScope scope(CcTest::isolate());
+  Isolate* isolate = CcTest::i_isolate();
+  Heap* heap = isolate->heap();
+  IncrementalMarking* marking = CcTest::heap()->incremental_marking();
+  v8::Local<v8::Value> result = CompileRun(
+      "var weak_map = new WeakMap();"
+      "var future_keys = [];"
+      "for (var i = 0; i < 50; i++) {"
+      "  var key = {'k' : i + 0.1};"
+      "  weak_map.set(key, 1);"
+      "  future_keys.push({'x' : i + 0.2});"
+      "}"
+      "weak_map");
+  if (marking->IsStopped()) {
+    marking->Start();
+  }
+  // Incrementally mark the backing store.
+  Handle<JSObject> obj =
+      v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(result));
+  Handle<JSWeakCollection> weak_map(reinterpret_cast<JSWeakCollection*>(*obj));
+  while (!Marking::IsBlack(
+             Marking::MarkBitFrom(HeapObject::cast(weak_map->table()))) &&
+         !marking->IsStopped()) {
+    marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
+  }
+  // Stash the backing store in a handle.
+  Handle<Object> save(weak_map->table(), isolate);
+  // The following line will update the backing store.
+  CompileRun(
+      "for (var i = 0; i < 50; i++) {"
+      "  weak_map.set(future_keys[i], i);"
+      "}");
+  heap->incremental_marking()->set_should_hurry(true);
+  heap->CollectGarbage(OLD_POINTER_SPACE);
+}
+
+
 #ifdef DEBUG
 TEST(PathTracer) {
   CcTest::InitializeVM();
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index e45e9eb..b9adb17 100644
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -4253,3 +4253,17 @@
   RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
                     arraysize(always_flags));
 }
+
+
+TEST(InvalidUnicodeEscapes) {
+  const char* context_data[][2] = {{"", ""},
+                                   {"'use strict';", ""},
+                                   {NULL, NULL}};
+  const char* data[] = {
+    "var foob\\u123r = 0;",
+    "var \\u123roo = 0;",
+    "\"foob\\u123rr\"",
+    "/regex/g\\u123r",
+    NULL};
+  RunParserSyncTest(context_data, data, kError);
+}
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index e79627d..9e3435d 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -426,6 +426,12 @@
 }],  # 'arch == mipsel or arch == mips'
 
 ##############################################################################
+['arch == mips', {
+  # Flaky with TF.
+  'mirror-script': [PASS, NO_VARIANTS],
+}],  # 'arch == mips'
+
+##############################################################################
 ['arch == mips64el', {
 
   # Slow tests which times out in debug mode.
diff --git a/test/mjsunit/regress/regress-crbug-429159.js b/test/mjsunit/regress/regress-crbug-429159.js
new file mode 100644
index 0000000..69f1856
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-429159.js
@@ -0,0 +1,12 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+try {
+  var src = "return " + Array(12000).join("src,") + "src";
+  var fun = Function(src);
+  assertEquals(src, fun());
+} catch (e) {
+  // Some architectures throw a RangeError, that is fine.
+  assertInstanceof(e, RangeError);
+}
diff --git a/test/test262-es6/README b/test/test262-es6/README
index 089b166..86fa0dc 100644
--- a/test/test262-es6/README
+++ b/test/test262-es6/README
@@ -4,13 +4,13 @@
 
   https://github.com/tc39/test262
 
-at hash e2b675f443 (2014/10/15 revision) as 'data' in this directory.  Using later
+at hash 61113db (2014/10/23 revision) as 'data' in this directory.  Using later
 version may be possible but the tests are only known to pass (and indeed run)
 with that revision.
 
   git clone https://github.com/tc39/test262 data
   cd data
-  git checkout e2b675f443
+  git checkout 61113db
 
 If you do update to a newer revision you may have to change the test
 harness adapter code since it uses internal functionality from the
diff --git a/test/test262-es6/testcfg.py b/test/test262-es6/testcfg.py
index 6087794..0a89410 100644
--- a/test/test262-es6/testcfg.py
+++ b/test/test262-es6/testcfg.py
@@ -37,8 +37,8 @@
 from testrunner.local import utils
 from testrunner.objects import testcase
 
-TEST_262_ARCHIVE_REVISION = "e2b675f"  # This is the 2014-10-15 revision.
-TEST_262_ARCHIVE_MD5 = "98f4427d0c88628561cd1c0104cf0614"
+TEST_262_ARCHIVE_REVISION = "61113db"  # This is the 2014-10-23 revision.
+TEST_262_ARCHIVE_MD5 = "261e69b4a97a4bfc18225cf3938daf50"
 TEST_262_URL = "https://github.com/tc39/test262/tarball/%s"
 TEST_262_HARNESS_FILES = ["sta.js"]
 
@@ -147,9 +147,11 @@
       with open(archive_name, "rb") as f:
         for chunk in iter(lambda: f.read(8192), ""):
           md5.update(chunk)
+      print "MD5 hash is %s" % md5.hexdigest()
       if md5.hexdigest() != TEST_262_ARCHIVE_MD5:
         os.remove(archive_name)
-        raise Exception("Hash mismatch of test data file")
+        print "MD5 expected %s" % TEST_262_ARCHIVE_MD5
+        raise Exception("MD5 hash mismatch of test data file")
       archive = tarfile.open(archive_name, "r:gz")
       if sys.platform in ("win32", "cygwin"):
         # Magic incantation to allow longer path names on Windows.
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index d2d5e5a..39639d8 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -363,6 +363,8 @@
         '../../src/bignum-dtoa.h',
         '../../src/bignum.cc',
         '../../src/bignum.h',
+        '../../src/bit-vector.cc',
+        '../../src/bit-vector.h',
         '../../src/bootstrapper.cc',
         '../../src/bootstrapper.h',
         '../../src/builtins.cc',
@@ -515,8 +517,6 @@
         '../../src/cpu-profiler-inl.h',
         '../../src/cpu-profiler.cc',
         '../../src/cpu-profiler.h',
-        '../../src/data-flow.cc',
-        '../../src/data-flow.h',
         '../../src/date.cc',
         '../../src/date.h',
         '../../src/dateparser-inl.h',
diff --git a/tools/push-to-trunk/auto_push.py b/tools/push-to-trunk/auto_push.py
index fef3b53..cec1489 100755
--- a/tools/push-to-trunk/auto_push.py
+++ b/tools/push-to-trunk/auto_push.py
@@ -36,7 +36,7 @@
 from common_includes import *
 import push_to_trunk
 
-PUSH_MESSAGE_RE = re.compile(r".* \(based on bleeding_edge revision r(\d+)\)$")
+PUSH_MESSAGE_RE = re.compile(r".* \(based on ([a-fA-F0-9]+)\)$")
 
 class Preparation(Step):
   MESSAGE = "Preparation."
@@ -94,28 +94,34 @@
       self.Die("Could not retrieve bleeding edge revision for trunk push %s"
                % last_push)
 
-    # TODO(machenbach): This metric counts all revisions. It could be
-    # improved by counting only the revisions on bleeding_edge.
-    if int(self["lkgr"]) - int(last_push_be) < 10:  # pragma: no cover
-      # This makes sure the script doesn't push twice in a row when the cron
-      # job retries several times.
-      self.Die("Last push too recently: %s" % last_push_be)
+    if self["lkgr"] == last_push_be:
+      print "Already pushed current lkgr %s" % last_push_be
+      return True
 
 
-class PushToTrunk(Step):
-  MESSAGE = "Pushing to trunk if specified."
+class PushToCandidates(Step):
+  MESSAGE = "Pushing to candidates if specified."
 
   def RunStep(self):
-    print "Pushing lkgr %s to trunk." % self["lkgr"]
+    print "Pushing lkgr %s to candidates." % self["lkgr"]
+
+    args = [
+      "--author", self._options.author,
+      "--reviewer", self._options.reviewer,
+      "--revision", self["lkgr"],
+      "--force",
+    ]
+
+    if self._options.svn:
+      args.extend(["--svn", self._options.svn])
+    if self._options.svn_config:
+      args.extend(["--svn-config", self._options.svn_config])
+    if self._options.vc_interface:
+      args.extend(["--vc-interface", self._options.vc_interface])
 
     # TODO(machenbach): Update the script before calling it.
     if self._options.push:
-      self._side_effect_handler.Call(
-          push_to_trunk.PushToTrunk().Run,
-          ["--author", self._options.author,
-           "--reviewer", self._options.reviewer,
-           "--revision", self["lkgr"],
-           "--force"])
+      self._side_effect_handler.Call(push_to_trunk.PushToTrunk().Run, args)
 
 
 class AutoPush(ScriptsBase):
@@ -144,7 +150,7 @@
       CheckTreeStatus,
       FetchLKGR,
       CheckLastPush,
-      PushToTrunk,
+      PushToCandidates,
     ]
 
 
diff --git a/tools/push-to-trunk/common_includes.py b/tools/push-to-trunk/common_includes.py
index 4cbfa54..a555500 100644
--- a/tools/push-to-trunk/common_includes.py
+++ b/tools/push-to-trunk/common_includes.py
@@ -400,12 +400,15 @@
       return "origin/%s" % name
     return "branch-heads/%s" % name
 
+  def PushRef(self, ref):
+    self.step.Git("push origin %s" % ref)
+
   def Tag(self, tag, remote, message):
     # Wait for the commit to appear. Assumes unique commit message titles (this
     # is the case for all automated merge and push commits - also no title is
     # the prefix of another title).
     commit = None
-    for wait_interval in [3, 7, 15, 35]:
+    for wait_interval in [3, 7, 15, 35, 35]:
       self.step.Git("fetch")
       commit = self.step.GitLog(n=1, format="%H", grep=message, branch=remote)
       if commit:
@@ -418,16 +421,40 @@
                     "git updater is lagging behind?")
 
     self.step.Git("tag %s %s" % (tag, commit))
-    self.step.Git("push origin %s" % tag)
+    self.PushRef(tag)
 
 
 class GitReadSvnWriteInterface(GitTagsOnlyMixin, GitSvnInterface):
   pass
 
 
+class GitInterface(GitTagsOnlyMixin):
+  def Fetch(self):
+    self.step.Git("fetch")
+
+  def GitSvn(self, hsh, branch=""):
+    return ""
+
+  def SvnGit(self, rev, branch=""):
+    raise NotImplementedError()
+
+  def Land(self):
+    # FIXME(machenbach): This will not work with checkouts from bot_update
+    # after flag day because it will push to the cache. Investigate if it
+    # will work with "cl land".
+    self.step.Git("push origin")
+
+  def CLLand(self):
+    self.step.GitCLLand()
+
+  def PushRef(self, ref):
+    self.step.Git("push https://chromium.googlesource.com/v8/v8 %s" % ref)
+
+
 VC_INTERFACES = {
   "git_svn": GitSvnInterface,
   "git_read_svn_write": GitReadSvnWriteInterface,
+  "git": GitInterface,
 }
 
 
@@ -708,6 +735,8 @@
                         (root, self._config["PATCH_FILE"]),
                         cwd=self._options.svn):
       self.Die("Could not apply patch.")
+    # Recursively add possibly newly added files.
+    self.Command("svn", "add --force %s" % root, cwd=self._options.svn)
     self.Command(
         "svn",
         "commit --non-interactive --username=%s --config-dir=%s -m \"%s\"" %
diff --git a/tools/push-to-trunk/git_recipes.py b/tools/push-to-trunk/git_recipes.py
index d57dc84..1b1887b 100644
--- a/tools/push-to-trunk/git_recipes.py
+++ b/tools/push-to-trunk/git_recipes.py
@@ -235,6 +235,10 @@
     self.Git(
         "cl dcommit -f --bypass-hooks", retry_on=lambda x: x is None, **kwargs)
 
+  def GitCLLand(self, **kwargs):
+    self.Git(
+        "cl land -f --bypass-hooks", retry_on=lambda x: x is None, **kwargs)
+
   def GitDiff(self, loc1, loc2, **kwargs):
     return self.Git(MakeArgs(["diff", loc1, loc2]), **kwargs)
 
diff --git a/tools/push-to-trunk/push_to_trunk.py b/tools/push-to-trunk/push_to_trunk.py
index ea481e0..0df548b 100755
--- a/tools/push-to-trunk/push_to_trunk.py
+++ b/tools/push-to-trunk/push_to_trunk.py
@@ -362,7 +362,10 @@
   MESSAGE = "Commit to SVN."
 
   def RunStep(self):
-    result = self.vc.Land()
+    if self._options.svn:
+      self.SVNCommit("trunk", self["commit_title"])
+    else:
+      self.vc.Land()
 
 
 class TagRevision(Step):
diff --git a/tools/push-to-trunk/test_scripts.py b/tools/push-to-trunk/test_scripts.py
index 0724cf5..d92c388 100644
--- a/tools/push-to-trunk/test_scripts.py
+++ b/tools/push-to-trunk/test_scripts.py
@@ -849,6 +849,136 @@
   def testPushToTrunkForced(self):
     self._PushToTrunk(force=True)
 
+  def testPushToTrunkGit(self):
+    svn_root = self.MakeEmptyTempDirectory()
+    TextToFile("", os.path.join(TEST_CONFIG["DEFAULT_CWD"], ".git"))
+
+    # The version file on bleeding edge has build level 5, while the version
+    # file from trunk has build level 4.
+    self.WriteFakeVersionFile(build=5)
+
+    TEST_CONFIG["CHANGELOG_ENTRY_FILE"] = self.MakeEmptyTempFile()
+    TEST_CONFIG["CHANGELOG_FILE"] = self.MakeEmptyTempFile()
+    bleeding_edge_change_log = "2014-03-17: Sentinel\n"
+    TextToFile(bleeding_edge_change_log, TEST_CONFIG["CHANGELOG_FILE"])
+
+    def ResetChangeLog():
+      """On 'git co -b new_branch svn/trunk', and 'git checkout -- ChangeLog',
+      the ChangLog will be reset to its content on trunk."""
+      trunk_change_log = """1999-04-05: Version 3.22.4
+
+        Performance and stability improvements on all platforms.\n"""
+      TextToFile(trunk_change_log, TEST_CONFIG["CHANGELOG_FILE"])
+
+    def ResetToTrunk():
+      ResetChangeLog()
+      self.WriteFakeVersionFile()
+
+    def CheckSVNCommit():
+      commit = FileToText(TEST_CONFIG["COMMITMSG_FILE"])
+      self.assertEquals(
+"""Version 3.22.5 (based on push_hash)
+
+Log text 1 (issue 321).
+
+Performance and stability improvements on all platforms.""", commit)
+      version = FileToText(
+          os.path.join(TEST_CONFIG["DEFAULT_CWD"], VERSION_FILE))
+      self.assertTrue(re.search(r"#define MINOR_VERSION\s+22", version))
+      self.assertTrue(re.search(r"#define BUILD_NUMBER\s+5", version))
+      self.assertFalse(re.search(r"#define BUILD_NUMBER\s+6", version))
+      self.assertTrue(re.search(r"#define PATCH_LEVEL\s+0", version))
+      self.assertTrue(re.search(r"#define IS_CANDIDATE_VERSION\s+0", version))
+
+      # Check that the change log on the trunk branch got correctly modified.
+      change_log = FileToText(TEST_CONFIG["CHANGELOG_FILE"])
+      self.assertEquals(
+"""1999-07-31: Version 3.22.5
+
+        Log text 1 (issue 321).
+
+        Performance and stability improvements on all platforms.
+
+
+1999-04-05: Version 3.22.4
+
+        Performance and stability improvements on all platforms.\n""",
+          change_log)
+
+    expectations = [
+      Cmd("git status -s -uno", ""),
+      Cmd("git status -s -b -uno", "## some_branch\n"),
+      Cmd("git fetch", ""),
+      Cmd("git branch", "  branch1\n* branch2\n"),
+      Cmd("git branch", "  branch1\n* branch2\n"),
+      Cmd(("git new-branch %s --upstream origin/master" %
+           TEST_CONFIG["BRANCHNAME"]),
+          ""),
+      Cmd(("git log -1 --format=%H --grep="
+           "\"^Version [[:digit:]]*\.[[:digit:]]*\.[[:digit:]]* (based\" "
+           "origin/candidates"), "hash2\n"),
+      Cmd("git log -1 hash2", "Log message\n"),
+      Cmd("git log -1 --format=%s hash2",
+       "Version 3.4.5 (based on abc3)\n"),
+      Cmd("git checkout -f origin/master -- src/version.cc",
+          "", cb=self.WriteFakeVersionFile),
+      Cmd("git checkout -f hash2 -- src/version.cc", "",
+          cb=self.WriteFakeVersionFile),
+      Cmd("git log --format=%H abc3..push_hash", "rev1\n"),
+      Cmd("git log -1 --format=%s rev1", "Log text 1.\n"),
+      Cmd("git log -1 --format=%B rev1", "Text\nLOG=YES\nBUG=v8:321\nText\n"),
+      Cmd("git log -1 --format=%an rev1", "author1@chromium.org\n"),
+      Cmd("git fetch", ""),
+      Cmd("git checkout -f origin/master", ""),
+      Cmd("git diff origin/candidates push_hash", "patch content\n"),
+      Cmd(("git new-branch %s --upstream origin/candidates" %
+           TEST_CONFIG["TRUNKBRANCH"]), "", cb=ResetToTrunk),
+      Cmd("git apply --index --reject \"%s\"" % TEST_CONFIG["PATCH_FILE"], ""),
+      Cmd(("git checkout -f origin/candidates -- %s" %
+           TEST_CONFIG["CHANGELOG_FILE"]), "",
+          cb=ResetChangeLog),
+      Cmd("git checkout -f origin/candidates -- src/version.cc", "",
+          cb=self.WriteFakeVersionFile),
+      Cmd("git commit -aF \"%s\"" % TEST_CONFIG["COMMITMSG_FILE"], "",
+          cb=CheckSVNCommit),
+      # TODO(machenbach): Change test to pure git after flag day.
+      # Cmd("git push origin", ""),
+      Cmd("git diff HEAD^ HEAD", "patch content"),
+      Cmd("svn update", "", cwd=svn_root),
+      Cmd("svn status", "", cwd=svn_root),
+      Cmd("patch -d trunk -p1 -i %s" %
+          TEST_CONFIG["PATCH_FILE"], "Applied patch...", cwd=svn_root),
+      Cmd("svn add --force trunk", "", cwd=svn_root),
+      Cmd("svn commit --non-interactive --username=author@chromium.org "
+          "--config-dir=[CONFIG_DIR] "
+          "-m \"Version 3.22.5 (based on push_hash)\"",
+          "", cwd=svn_root),
+      Cmd("git fetch", ""),
+      Cmd("git log -1 --format=%H --grep="
+          "\"Version 3.22.5 (based on push_hash)\""
+          " origin/candidates", "hsh_to_tag"),
+      Cmd("git tag 3.22.5 hsh_to_tag", ""),
+      Cmd("git push https://chromium.googlesource.com/v8/v8 3.22.5", ""),
+      Cmd("git checkout -f some_branch", ""),
+      Cmd("git branch -D %s" % TEST_CONFIG["BRANCHNAME"], ""),
+      Cmd("git branch -D %s" % TEST_CONFIG["TRUNKBRANCH"], ""),
+    ]
+    self.Expect(expectations)
+
+    args = ["-a", "author@chromium.org", "--revision", "push_hash",
+            "--vc-interface", "git", "-f", "-r", "reviewer@chromium.org",
+            "--svn", svn_root, "--svn-config", "[CONFIG_DIR]"]
+    PushToTrunk(TEST_CONFIG, self).Run(args)
+
+    cl = FileToText(TEST_CONFIG["CHANGELOG_FILE"])
+    self.assertTrue(re.search(r"^\d\d\d\d\-\d+\-\d+: Version 3\.22\.5", cl))
+    self.assertTrue(re.search(r"        Log text 1 \(issue 321\).", cl))
+    self.assertTrue(re.search(r"1999\-04\-05: Version 3\.22\.4", cl))
+
+    # Note: The version file is on build number 5 again in the end of this test
+    # since the git command that merges to the bleeding edge branch is mocked
+    # out.
+
   C_V8_22624_LOG = """V8 CL.
 
 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22624 123
@@ -930,14 +1060,12 @@
            "\"^Version [[:digit:]]*\.[[:digit:]]*\.[[:digit:]]* (based\" "
            "origin/candidates"), "hash2\n"),
       Cmd("git log -1 --format=%s hash2",
-          "Version 3.4.5 (based on bleeding_edge revision r99)\n"),
+          "Version 3.4.5 (based on abc123)\n"),
     ])
 
-    self._state["lkgr"] = "101"
-
-    self.assertRaises(Exception, lambda: self.RunStep(auto_push.AutoPush,
-                                                      CheckLastPush,
-                                                      AUTO_PUSH_ARGS))
+    self._state["lkgr"] = "abc123"
+    self.assertEquals(0, self.RunStep(
+        auto_push.AutoPush, CheckLastPush, AUTO_PUSH_ARGS))
 
   def testAutoPush(self):
     TextToFile("", os.path.join(TEST_CONFIG["DEFAULT_CWD"], ".git"))
@@ -947,24 +1075,24 @@
       Cmd("git status -s -uno", ""),
       Cmd("git status -s -b -uno", "## some_branch\n"),
       Cmd("git fetch", ""),
-      Cmd("git svn fetch", ""),
       URL("https://v8-status.appspot.com/current?format=json",
           "{\"message\": \"Tree is throttled\"}"),
       URL("https://v8-status.appspot.com/lkgr", Exception("Network problem")),
-      URL("https://v8-status.appspot.com/lkgr", "100"),
+      URL("https://v8-status.appspot.com/lkgr", "abc123"),
       Cmd(("git log -1 --format=%H --grep=\""
            "^Version [[:digit:]]*\.[[:digit:]]*\.[[:digit:]]* (based\""
            " origin/candidates"), "push_hash\n"),
       Cmd("git log -1 --format=%s push_hash",
-          "Version 3.4.5 (based on bleeding_edge revision r79)\n"),
+          "Version 3.4.5 (based on abc101)\n"),
     ])
 
-    auto_push.AutoPush(TEST_CONFIG, self).Run(AUTO_PUSH_ARGS + ["--push"])
+    auto_push.AutoPush(TEST_CONFIG, self).Run(
+        AUTO_PUSH_ARGS + ["--push", "--vc-interface", "git"])
 
     state = json.loads(FileToText("%s-state.json"
                                   % TEST_CONFIG["PERSISTFILE_BASENAME"]))
 
-    self.assertEquals("100", state["lkgr"])
+    self.assertEquals("abc123", state["lkgr"])
 
   def testAutoPushStoppedBySettings(self):
     TextToFile("", os.path.join(TEST_CONFIG["DEFAULT_CWD"], ".git"))
@@ -1642,6 +1770,7 @@
       Cmd("svn status", "", cwd=svn_root),
       Cmd("patch -d branches/bleeding_edge -p1 -i %s" %
           TEST_CONFIG["PATCH_FILE"], "Applied patch...", cwd=svn_root),
+      Cmd("svn add --force branches/bleeding_edge", "", cwd=svn_root),
       Cmd("svn commit --non-interactive --username=author@chromium.org "
           "--config-dir=[CONFIG_DIR] "
           "-m \"[Auto-roll] Bump up version to 3.11.6.0\"",