Version 3.29.92 (based on bleeding_edge revision r24256)

Performance and stability improvements on all platforms.

git-svn-id: https://v8.googlecode.com/svn/trunk@24258 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index c7316ed..92b11644 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2014-09-29: Version 3.29.92
+
+        Performance and stability improvements on all platforms.
+
+
 2014-09-26: Version 3.29.91
 
         Performance and stability improvements on all platforms.
diff --git a/src/api.cc b/src/api.cc
index f1d81dd..bda34bd 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -5483,21 +5483,15 @@
 }
 
 
-static i::Handle<i::String> NewExternalStringHandle(
-    i::Isolate* isolate,
-    v8::String::ExternalStringResource* resource) {
-  // We do not expect this to fail. Change this if it does.
-  return isolate->factory()->NewExternalStringFromTwoByte(
-      resource).ToHandleChecked();
+static i::MaybeHandle<i::String> NewExternalStringHandle(
+    i::Isolate* isolate, v8::String::ExternalStringResource* resource) {
+  return isolate->factory()->NewExternalStringFromTwoByte(resource);
 }
 
 
-static i::Handle<i::String> NewExternalOneByteStringHandle(
+static i::MaybeHandle<i::String> NewExternalOneByteStringHandle(
     i::Isolate* isolate, v8::String::ExternalOneByteStringResource* resource) {
-  // We do not expect this to fail. Change this if it does.
-  return isolate->factory()
-      ->NewExternalStringFromOneByte(resource)
-      .ToHandleChecked();
+  return isolate->factory()->NewExternalStringFromOneByte(resource);
 }
 
 
@@ -5508,9 +5502,13 @@
   LOG_API(i_isolate, "String::NewExternal");
   ENTER_V8(i_isolate);
   CHECK(resource && resource->data());
-  i::Handle<i::String> result = NewExternalStringHandle(i_isolate, resource);
-  i_isolate->heap()->external_string_table()->AddString(*result);
-  return Utils::ToLocal(result);
+  EXCEPTION_PREAMBLE(i_isolate);
+  i::Handle<i::String> string;
+  has_pending_exception =
+      !NewExternalStringHandle(i_isolate, resource).ToHandle(&string);
+  EXCEPTION_BAILOUT_CHECK(i_isolate, Local<String>());
+  i_isolate->heap()->external_string_table()->AddString(*string);
+  return Utils::ToLocal(string);
 }
 
 
@@ -5546,10 +5544,13 @@
   LOG_API(i_isolate, "String::NewExternal");
   ENTER_V8(i_isolate);
   CHECK(resource && resource->data());
-  i::Handle<i::String> result =
-      NewExternalOneByteStringHandle(i_isolate, resource);
-  i_isolate->heap()->external_string_table()->AddString(*result);
-  return Utils::ToLocal(result);
+  EXCEPTION_PREAMBLE(i_isolate);
+  i::Handle<i::String> string;
+  has_pending_exception =
+      !NewExternalOneByteStringHandle(i_isolate, resource).ToHandle(&string);
+  EXCEPTION_BAILOUT_CHECK(i_isolate, Local<String>());
+  i_isolate->heap()->external_string_table()->AddString(*string);
+  return Utils::ToLocal(string);
 }
 
 
diff --git a/src/compiler/graph-reducer-unittest.cc b/src/compiler/graph-reducer-unittest.cc
index 6567203..2729d58 100644
--- a/src/compiler/graph-reducer-unittest.cc
+++ b/src/compiler/graph-reducer-unittest.cc
@@ -97,15 +97,16 @@
 
 
 TEST_F(GraphReducerTest, ReduceAgainAfterChanged) {
-  Sequence s1, s2;
+  Sequence s1, s2, s3;
   StrictMock<MockReducer> r1, r2, r3;
   Node* node0 = graph()->NewNode(&OP0);
   EXPECT_CALL(r1, Reduce(node0));
   EXPECT_CALL(r2, Reduce(node0));
-  EXPECT_CALL(r3, Reduce(node0)).InSequence(s1, s2).WillOnce(
+  EXPECT_CALL(r3, Reduce(node0)).InSequence(s1, s2, s3).WillOnce(
       Return(Reducer::Changed(node0)));
   EXPECT_CALL(r1, Reduce(node0)).InSequence(s1);
   EXPECT_CALL(r2, Reduce(node0)).InSequence(s2);
+  EXPECT_CALL(r3, Reduce(node0)).InSequence(s3);
   ReduceNode(node0, &r1, &r2, &r3);
 }
 
diff --git a/src/compiler/graph-reducer.cc b/src/compiler/graph-reducer.cc
index 36a54e0..07e8923 100644
--- a/src/compiler/graph-reducer.cc
+++ b/src/compiler/graph-reducer.cc
@@ -22,7 +22,6 @@
 
 
 void GraphReducer::ReduceNode(Node* node) {
-  ZoneVector<Reducer*>::iterator skip = reducers_.end();
   static const unsigned kMaxAttempts = 16;
   bool reduce = true;
   for (unsigned attempts = 0; attempts <= kMaxAttempts; ++attempts) {
@@ -31,17 +30,15 @@
     int before = graph_->NodeCount();
     for (ZoneVector<Reducer*>::iterator i = reducers_.begin();
          i != reducers_.end(); ++i) {
-      if (i == skip) continue;  // Skip this reducer.
       Reduction reduction = (*i)->Reduce(node);
       Node* replacement = reduction.replacement();
       if (replacement == NULL) {
         // No change from this reducer.
       } else if (replacement == node) {
         // {replacement == node} represents an in-place reduction.
-        // Rerun all the reducers except the current one for this node,
-        // as now there may be more opportunities for reduction.
+        // Rerun all the reducers for this node, as now there may be more
+        // opportunities for reduction.
         reduce = true;
-        skip = i;
         break;
       } else {
         if (node == graph_->start()) graph_->SetStart(replacement);
@@ -63,7 +60,6 @@
           node->Kill();
         }
         // Rerun all the reductions on the {replacement}.
-        skip = reducers_.end();
         node = replacement;
         reduce = true;
         break;
diff --git a/src/compiler/graph-unittest.cc b/src/compiler/graph-unittest.cc
index 0071b81..35585e8 100644
--- a/src/compiler/graph-unittest.cc
+++ b/src/compiler/graph-unittest.cc
@@ -744,6 +744,7 @@
         new IsBinopMatcher(IrOpcode::k##Name, lhs_matcher, rhs_matcher)); \
   }
 IS_BINOP_MATCHER(NumberLessThan)
+IS_BINOP_MATCHER(NumberSubtract)
 IS_BINOP_MATCHER(Word32And)
 IS_BINOP_MATCHER(Word32Sar)
 IS_BINOP_MATCHER(Word32Shl)
diff --git a/src/compiler/graph-unittest.h b/src/compiler/graph-unittest.h
index 04d4af0..b821165 100644
--- a/src/compiler/graph-unittest.h
+++ b/src/compiler/graph-unittest.h
@@ -87,6 +87,8 @@
 
 Matcher<Node*> IsNumberLessThan(const Matcher<Node*>& lhs_matcher,
                                 const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsNumberSubtract(const Matcher<Node*>& lhs_matcher,
+                                const Matcher<Node*>& rhs_matcher);
 
 Matcher<Node*> IsLoad(const Matcher<LoadRepresentation>& rep_matcher,
                       const Matcher<Node*>& base_matcher,
diff --git a/src/compiler/js-builtin-reducer-unittest.cc b/src/compiler/js-builtin-reducer-unittest.cc
index 598a553..5177d8d 100644
--- a/src/compiler/js-builtin-reducer-unittest.cc
+++ b/src/compiler/js-builtin-reducer-unittest.cc
@@ -60,6 +60,39 @@
 
 
 // -----------------------------------------------------------------------------
+// Math.abs
+
+
+TEST_F(JSBuiltinReducerTest, MathAbs) {
+  Handle<JSFunction> f(isolate()->context()->math_abs_fun());
+
+  TRACED_FOREACH(Type*, t0, kNumberTypes) {
+    Node* p0 = Parameter(t0, 0);
+    Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
+    Node* call = graph()->NewNode(javascript()->Call(3, NO_CALL_FUNCTION_FLAGS),
+                                  fun, UndefinedConstant(), p0);
+    Reduction r = Reduce(call);
+
+    if (t0->Is(Type::Unsigned32())) {
+      ASSERT_TRUE(r.Changed());
+      EXPECT_THAT(r.replacement(), p0);
+    } else {
+      Capture<Node*> branch;
+      ASSERT_TRUE(r.Changed());
+      EXPECT_THAT(
+          r.replacement(),
+          IsPhi(kMachNone, p0, IsNumberSubtract(IsNumberConstant(0), p0),
+                IsMerge(IsIfTrue(CaptureEq(&branch)),
+                        IsIfFalse(AllOf(
+                            CaptureEq(&branch),
+                            IsBranch(IsNumberLessThan(IsNumberConstant(0), p0),
+                                     graph()->start()))))));
+    }
+  }
+}
+
+
+// -----------------------------------------------------------------------------
 // Math.sqrt
 
 
diff --git a/src/compiler/js-builtin-reducer.cc b/src/compiler/js-builtin-reducer.cc
index f1aef31..ec73742 100644
--- a/src/compiler/js-builtin-reducer.cc
+++ b/src/compiler/js-builtin-reducer.cc
@@ -95,6 +95,33 @@
 };
 
 
+// ECMA-262, section 15.8.2.1.
+Reduction JSBuiltinReducer::ReduceMathAbs(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchOne(Type::Unsigned32())) {
+    // Math.abs(a:uint32) -> a
+    return Replace(r.left());
+  }
+  if (r.InputsMatchOne(Type::Number())) {
+    // Math.abs(a:number) -> (a > 0 ? a : 0 - a)
+    Node* value = r.left();
+    Node* zero = jsgraph()->ZeroConstant();
+    Node* control = graph()->start();
+    Node* tag = graph()->NewNode(simplified()->NumberLessThan(), zero, value);
+
+    Node* branch = graph()->NewNode(common()->Branch(), tag, control);
+    Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+    Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+    Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+
+    Node* neg = graph()->NewNode(simplified()->NumberSubtract(), zero, value);
+    value = graph()->NewNode(common()->Phi(kMachNone, 2), value, neg, merge);
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+
 // ECMA-262, section 15.8.2.17.
 Reduction JSBuiltinReducer::ReduceMathSqrt(Node* node) {
   JSCallReduction r(node);
@@ -170,6 +197,8 @@
   // Dispatch according to the BuiltinFunctionId if present.
   if (!r.HasBuiltinFunctionId()) return NoChange();
   switch (r.GetBuiltinFunctionId()) {
+    case kMathAbs:
+      return ReplaceWithPureReduction(node, ReduceMathAbs(node));
     case kMathSqrt:
       return ReplaceWithPureReduction(node, ReduceMathSqrt(node));
     case kMathMax:
diff --git a/src/compiler/js-builtin-reducer.h b/src/compiler/js-builtin-reducer.h
index e5a1b83..f3b862f 100644
--- a/src/compiler/js-builtin-reducer.h
+++ b/src/compiler/js-builtin-reducer.h
@@ -30,6 +30,7 @@
   MachineOperatorBuilder* machine() const { return jsgraph_->machine(); }
   SimplifiedOperatorBuilder* simplified() { return &simplified_; }
 
+  Reduction ReduceMathAbs(Node* node);
   Reduction ReduceMathSqrt(Node* node);
   Reduction ReduceMathMax(Node* node);
   Reduction ReduceMathImul(Node* node);
diff --git a/src/compiler/machine-operator-reducer-unittest.cc b/src/compiler/machine-operator-reducer-unittest.cc
index f3073ab..5a76342 100644
--- a/src/compiler/machine-operator-reducer-unittest.cc
+++ b/src/compiler/machine-operator-reducer-unittest.cc
@@ -521,6 +521,49 @@
 
 
 // -----------------------------------------------------------------------------
+// Word32Shl
+
+
+TEST_F(MachineOperatorReducerTest, Word32ShlWithZeroShift) {
+  Node* p0 = Parameter(0);
+  Node* node = graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(0));
+  Reduction r = Reduce(node);
+  ASSERT_TRUE(r.Changed());
+  EXPECT_EQ(p0, r.replacement());
+}
+
+
+TEST_F(MachineOperatorReducerTest, Word32ShlWithWord32Sar) {
+  Node* p0 = Parameter(0);
+  TRACED_FORRANGE(int32_t, x, 1, 31) {
+    Node* node = graph()->NewNode(
+        machine()->Word32Shl(),
+        graph()->NewNode(machine()->Word32Sar(), p0, Int32Constant(x)),
+        Int32Constant(x));
+    Reduction r = Reduce(node);
+    ASSERT_TRUE(r.Changed());
+    int32_t m = bit_cast<int32_t>(~((1U << x) - 1U));
+    EXPECT_THAT(r.replacement(), IsWord32And(p0, IsInt32Constant(m)));
+  }
+}
+
+
+TEST_F(MachineOperatorReducerTest, Word32ShlWithWord32Shr) {
+  Node* p0 = Parameter(0);
+  TRACED_FORRANGE(int32_t, x, 1, 31) {
+    Node* node = graph()->NewNode(
+        machine()->Word32Shl(),
+        graph()->NewNode(machine()->Word32Shr(), p0, Int32Constant(x)),
+        Int32Constant(x));
+    Reduction r = Reduce(node);
+    ASSERT_TRUE(r.Changed());
+    int32_t m = bit_cast<int32_t>(~((1U << x) - 1U));
+    EXPECT_THAT(r.replacement(), IsWord32And(p0, IsInt32Constant(m)));
+  }
+}
+
+
+// -----------------------------------------------------------------------------
 // Int32AddWithOverflow
 
 
diff --git a/src/compiler/machine-operator-reducer.cc b/src/compiler/machine-operator-reducer.cc
index 9328547..9764341 100644
--- a/src/compiler/machine-operator-reducer.cc
+++ b/src/compiler/machine-operator-reducer.cc
@@ -131,6 +131,20 @@
       if (m.IsFoldable()) {                                  // K << K => K
         return ReplaceInt32(m.left().Value() << m.right().Value());
       }
+      if (m.right().IsInRange(1, 31)) {
+        // (x >>> K) << K => x & ~(2^K - 1)
+        // (x >> K) << K => x & ~(2^K - 1)
+        if (m.left().IsWord32Sar() || m.left().IsWord32Shr()) {
+          Int32BinopMatcher mleft(m.left().node());
+          if (mleft.right().Is(m.right().Value())) {
+            node->set_op(machine()->Word32And());
+            node->ReplaceInput(0, mleft.left().node());
+            node->ReplaceInput(
+                1, Uint32Constant(~((1U << m.right().Value()) - 1U)));
+            return Changed(node);
+          }
+        }
+      }
       break;
     }
     case IrOpcode::kWord32Shr: {
diff --git a/src/compiler/machine-operator-reducer.h b/src/compiler/machine-operator-reducer.h
index c79ceae..e40ad65 100644
--- a/src/compiler/machine-operator-reducer.h
+++ b/src/compiler/machine-operator-reducer.h
@@ -31,6 +31,9 @@
   Node* Float64Constant(volatile double value);
   Node* Int32Constant(int32_t value);
   Node* Int64Constant(int64_t value);
+  Node* Uint32Constant(uint32_t value) {
+    return Int32Constant(bit_cast<uint32_t>(value));
+  }
 
   Reduction ReplaceBool(bool value) { return ReplaceInt32(value ? 1 : 0); }
   Reduction ReplaceFloat32(volatile float value) {
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 49f0714..6c90912 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -336,11 +336,7 @@
 DEFINE_BOOL(turbo_asm, false, "enable TurboFan for asm.js code")
 DEFINE_BOOL(turbo_verify, false, "verify TurboFan graphs at each phase")
 DEFINE_BOOL(turbo_stats, false, "print TurboFan statistics")
-#if V8_TURBOFAN_BACKEND
 DEFINE_BOOL(turbo_types, true, "use typed lowering in TurboFan")
-#else
-DEFINE_BOOL(turbo_types, false, "use typed lowering in TurboFan")
-#endif
 DEFINE_BOOL(turbo_source_positions, false,
             "track source code positions when building TurboFan IR")
 DEFINE_BOOL(context_specialization, false,
@@ -669,6 +665,7 @@
 DEFINE_NEG_IMPLICATION(predictable, concurrent_osr)
 DEFINE_NEG_IMPLICATION(predictable, concurrent_sweeping)
 DEFINE_NEG_IMPLICATION(predictable, parallel_sweeping)
+DEFINE_NEG_IMPLICATION(predictable, job_based_sweeping)
 
 
 //
diff --git a/src/scanner-character-streams.cc b/src/scanner-character-streams.cc
index 31b4ee4..d06f479 100644
--- a/src/scanner-character-streams.cc
+++ b/src/scanner-character-streams.cc
@@ -411,13 +411,17 @@
 
   // Move bytes which are part of an incomplete character from the end of the
   // current chunk to utf8_split_char_buffer_. They will be converted when the
-  // next data chunk arrives.
+  // next data chunk arrives. Note that all valid UTF-8 characters are at most 4
+  // bytes long, but if the data is invalid, we can have character values bigger
+  // than unibrow::Utf8::kMaxOneByteChar for more than 4 consecutive bytes.
   while (current_data_length_ > current_data_offset_ &&
          (c = current_data_[current_data_length_ - 1]) >
-             unibrow::Utf8::kMaxOneByteChar) {
+             unibrow::Utf8::kMaxOneByteChar &&
+         utf8_split_char_buffer_length_ < 4) {
     --current_data_length_;
     ++utf8_split_char_buffer_length_;
   }
+  CHECK(utf8_split_char_buffer_length_ <= 4);
   for (unsigned i = 0; i < utf8_split_char_buffer_length_; ++i) {
     utf8_split_char_buffer_[i] = current_data_[current_data_length_ + i];
   }
diff --git a/src/test/run-all-unittests.cc b/src/test/run-all-unittests.cc
index 8c361dd..de56365 100644
--- a/src/test/run-all-unittests.cc
+++ b/src/test/run-all-unittests.cc
@@ -5,6 +5,7 @@
 #include "include/libplatform/libplatform.h"
 #include "include/v8.h"
 #include "src/base/compiler-specific.h"
+#include "src/v8.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace {
@@ -38,6 +39,9 @@
 
 
 int main(int argc, char** argv) {
+  // This forces some thread local key initialization that may be needed to
+  // print out the names of the unit tests.
+  i::V8::Initialize();
   testing::InitGoogleMock(&argc, argv);
   testing::AddGlobalTestEnvironment(new DefaultPlatformEnvironment);
   v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
diff --git a/src/version.cc b/src/version.cc
index d2aaaea..2b8d99c 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,8 +34,8 @@
 // system so their names cannot be changed without changing the scripts.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     29
-#define BUILD_NUMBER      91
-#define PATCH_LEVEL       1
+#define BUILD_NUMBER      92
+#define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
diff --git a/src/x87/assembler-x87.cc b/src/x87/assembler-x87.cc
index 9e1c883..110b813 100644
--- a/src/x87/assembler-x87.cc
+++ b/src/x87/assembler-x87.cc
@@ -1897,11 +1897,6 @@
 }
 
 
-void Assembler::Print() {
-  Disassembler::Decode(isolate(), stdout, buffer_, pc_);
-}
-
-
 void Assembler::RecordJSReturn() {
   positions_recorder()->WriteRecordedPositions();
   EnsureSpace ensure_space(this);
diff --git a/src/x87/assembler-x87.h b/src/x87/assembler-x87.h
index 8c7630b..a292388 100644
--- a/src/x87/assembler-x87.h
+++ b/src/x87/assembler-x87.h
@@ -916,9 +916,6 @@
 
   // TODO(lrn): Need SFENCE for movnt?
 
-  // Debugging
-  void Print();
-
   // Check the code size generated from label to here.
   int SizeOfCodeGeneratedSince(Label* label) {
     return pc_offset() - label->pos();
diff --git a/test/cctest/compiler/test-graph-reducer.cc b/test/cctest/compiler/test-graph-reducer.cc
index eabfd22..b94ca45 100644
--- a/test/cctest/compiler/test-graph-reducer.cc
+++ b/test/cctest/compiler/test-graph-reducer.cc
@@ -621,41 +621,3 @@
     }
   }
 }
-
-
-// Tests that a reducer is only applied once.
-class OneTimeReducer : public Reducer {
- public:
-  OneTimeReducer(Reducer* reducer, Zone* zone)
-      : reducer_(reducer),
-        nodes_(NodeSet::key_compare(), NodeSet::allocator_type(zone)) {}
-  virtual Reduction Reduce(Node* node) {
-    CHECK_EQ(0, static_cast<int>(nodes_.count(node)));
-    nodes_.insert(node);
-    return reducer_->Reduce(node);
-  }
-  Reducer* reducer_;
-  NodeSet nodes_;
-};
-
-
-TEST(OneTimeReduce1) {
-  GraphTester graph;
-
-  Node* n1 = graph.NewNode(&OPA0);
-  Node* end = graph.NewNode(&OPA1, n1);
-  graph.SetEnd(end);
-
-  GraphReducer reducer(&graph);
-  InPlaceABReducer r;
-  OneTimeReducer once(&r, graph.zone());
-  reducer.AddReducer(&once);
-
-  // Tests A* => B* with in-place updates. Should only be applied once.
-  int before = graph.NodeCount();
-  reducer.ReduceGraph();
-  CHECK_EQ(before, graph.NodeCount());
-  CHECK_EQ(&OPB0, n1->op());
-  CHECK_EQ(&OPB1, end->op());
-  CHECK_EQ(n1, end->InputAt(0));
-}
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 8fd8743..66dc5a0 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -742,6 +742,53 @@
 }
 
 
+class DummyResource : public v8::String::ExternalStringResource {
+ public:
+  virtual const uint16_t* data() const { return string_; }
+  virtual size_t length() const { return 1 << 30; }
+
+ private:
+  uint16_t string_[10];
+};
+
+
+class DummyOneByteResource : public v8::String::ExternalOneByteStringResource {
+ public:
+  virtual const char* data() const { return string_; }
+  virtual size_t length() const { return 1 << 30; }
+
+ private:
+  char string_[10];
+};
+
+
+THREADED_TEST(NewExternalForVeryLongString) {
+  {
+    LocalContext env;
+    v8::HandleScope scope(env->GetIsolate());
+    v8::TryCatch try_catch;
+    DummyOneByteResource r;
+    v8::Local<v8::String> str = v8::String::NewExternal(CcTest::isolate(), &r);
+    CHECK(str.IsEmpty());
+    CHECK(try_catch.HasCaught());
+    String::Utf8Value exception_value(try_catch.Exception());
+    CHECK_EQ("RangeError: Invalid string length", *exception_value);
+  }
+
+  {
+    LocalContext env;
+    v8::HandleScope scope(env->GetIsolate());
+    v8::TryCatch try_catch;
+    DummyResource r;
+    v8::Local<v8::String> str = v8::String::NewExternal(CcTest::isolate(), &r);
+    CHECK(str.IsEmpty());
+    CHECK(try_catch.HasCaught());
+    String::Utf8Value exception_value(try_catch.Exception());
+    CHECK_EQ("RangeError: Invalid string length", *exception_value);
+  }
+}
+
+
 THREADED_TEST(ScavengeExternalString) {
   i::FLAG_stress_compaction = false;
   i::FLAG_gc_global = false;
@@ -23334,3 +23381,23 @@
   CHECK(cached_data->data != NULL);
   CHECK_GT(cached_data->length, 0);
 }
+
+
+TEST(StreamingScriptWithInvalidUtf8) {
+  // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
+  // chunk don't produce a crash.
+  const char* reference = "\xeb\x91\x80\x80\x80";
+  char chunk1[] =
+      "function foo() {\n"
+      "  // This function will contain an UTF-8 character which is not in\n"
+      "  // ASCII.\n"
+      "  var foobXXXXX";  // Too many bytes which look like incomplete chars!
+  char chunk2[] =
+      "r = 13;\n"
+      "  return foob\xeb\x91\x80\x80\x80r;\n"
+      "}\n";
+  for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
+
+  const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
+  RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
+}
diff --git a/test/mjsunit/asm/int32array-unaligned.js b/test/mjsunit/asm/int32array-unaligned.js
new file mode 100644
index 0000000..698ec5e
--- /dev/null
+++ b/test/mjsunit/asm/int32array-unaligned.js
@@ -0,0 +1,43 @@
+// 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.
+
+function Module(stdlib, foreign, heap) {
+  "use asm";
+  var MEM32 = new stdlib.Int32Array(heap);
+  function load(i) {
+    i = i|0;
+    i = MEM32[i >> 2] | 0;
+    return i;
+  }
+  function store(i, v) {
+    i = i|0;
+    v = v|0;
+    MEM32[i >> 2] = v;
+  }
+  return { load: load, store: store };
+}
+
+var m = Module(this, {}, new ArrayBuffer(1024));
+
+m.store(0, 0x12345678);
+m.store(4, -1);
+m.store(8, -1);
+for (var i = 0; i < 4; ++i) {
+  assertEquals(0x12345678, m.load(i));
+}
+for (var i = 4; i < 12; ++i) {
+  assertEquals(-1, m.load(i));
+}
+for (var j = 4; j < 8; ++j) {
+  m.store(j, 0x11223344);
+  for (var i = 0; i < 4; ++i) {
+    assertEquals(0x12345678, m.load(i));
+  }
+  for (var i = 4; i < 8; ++i) {
+    assertEquals(0x11223344, m.load(i));
+  }
+  for (var i = 8; i < 12; ++i) {
+    assertEquals(-1, m.load(i));
+  }
+}
diff --git a/test/mjsunit/asm/math-abs.js b/test/mjsunit/asm/math-abs.js
new file mode 100644
index 0000000..6387749
--- /dev/null
+++ b/test/mjsunit/asm/math-abs.js
@@ -0,0 +1,84 @@
+// 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.
+
+function Module(stdlib) {
+  "use asm";
+
+  var abs = stdlib.Math.abs;
+
+  // f: double -> double
+  function f(a) {
+    a = +a;
+    return +abs(a);
+  }
+
+  // g: unsigned -> double
+  function g(a) {
+    a = a>>>0;
+    return +abs(a);
+  }
+
+  // h: signed -> double
+  function h(a) {
+    a = a|0;
+    return +abs(a);
+  }
+
+  return { f: f, g: g, h: h };
+}
+
+var m = Module({ Math: Math });
+var f = m.f;
+var g = m.g;
+var h = m.h;
+
+assertTrue(isNaN(f(NaN)));
+assertTrue(isNaN(f(undefined)));
+assertTrue(isNaN(f(function() {})));
+
+assertEquals("Infinity", String(1/f(0)));
+assertEquals("Infinity", String(1/f(-0)));
+assertEquals("Infinity", String(f(Infinity)));
+assertEquals("Infinity", String(f(-Infinity)));
+
+assertEquals(0,   f(0));
+assertEquals(0.1, f(0.1));
+assertEquals(0.5, f(0.5));
+assertEquals(0.1, f(-0.1));
+assertEquals(0.5, f(-0.5));
+assertEquals(1,   f(1));
+assertEquals(1.1, f(1.1));
+assertEquals(1.5, f(1.5));
+assertEquals(1,   f(-1));
+assertEquals(1.1, f(-1.1));
+assertEquals(1.5, f(-1.5));
+
+assertEquals(0,          g(0));
+assertEquals(0,          g(0.1));
+assertEquals(0,          g(0.5));
+assertEquals(0,          g(-0.1));
+assertEquals(0,          g(-0.5));
+assertEquals(1,          g(1));
+assertEquals(1,          g(1.1));
+assertEquals(1,          g(1.5));
+assertEquals(4294967295, g(-1));
+assertEquals(4294967295, g(-1.1));
+assertEquals(4294967295, g(-1.5));
+
+assertEquals(0, h(0));
+assertEquals(0, h(0.1));
+assertEquals(0, h(0.5));
+assertEquals(0, h(-0.1));
+assertEquals(0, h(-0.5));
+assertEquals(1, h(1));
+assertEquals(1, h(1.1));
+assertEquals(1, h(1.5));
+assertEquals(1, h(-1));
+assertEquals(1, h(-1.1));
+assertEquals(1, h(-1.5));
+
+assertEquals(Number.MIN_VALUE, f(Number.MIN_VALUE));
+assertEquals(Number.MIN_VALUE, f(-Number.MIN_VALUE));
+assertEquals(Number.MAX_VALUE, f(Number.MAX_VALUE));
+assertEquals(Number.MAX_VALUE, f(-Number.MAX_VALUE));
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index bba86bd..04c0977 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -70,9 +70,10 @@
   'harmony/block-let-crankshaft': [PASS, NO_VARIANTS],
   'harmony/empty-for': [PASS, NO_VARIANTS],
 
-  # Some tests are over-restrictive about object layout.
+  # TODO(verwaest): Some tests are over-restrictive about object layout.
   'array-constructor-feedback': [PASS, NO_VARIANTS],
   'array-feedback': [PASS, NO_VARIANTS],
+  'compare-known-objects-slow': [PASS, NO_VARIANTS],
   'elements-kind': [PASS, NO_VARIANTS],
 
   # Some tests are just too slow to run for now.
diff --git a/tools/push-to-trunk/common_includes.py b/tools/push-to-trunk/common_includes.py
index c1c2aa5..7ea39f7 100644
--- a/tools/push-to-trunk/common_includes.py
+++ b/tools/push-to-trunk/common_includes.py
@@ -346,6 +346,45 @@
     self.step.GitSVNTag(tag)
 
 
+class GitReadOnlyMixin(VCInterface):
+  def Pull(self):
+    self.step.GitPull()
+
+  def Fetch(self):
+    self.step.Git("fetch")
+
+  def GetTags(self):
+     return self.step.Git("tag").strip().splitlines()
+
+  def GetBranches(self):
+    # Get relevant remote branches, e.g. "origin/branch-heads/3.25".
+    branches = filter(
+        lambda s: re.match(r"^origin/branch\-heads/\d+\.\d+$", s),
+        self.step.GitRemotes())
+    # Remove 'origin/branch-heads/' prefix.
+    return map(lambda s: s[20:], branches)
+
+  def RemoteMasterBranch(self):
+    return "origin/master"
+
+  def RemoteCandidateBranch(self):
+    return "origin/candidates"
+
+  def RemoteBranch(self, name):
+    if name in ["candidates", "master"]:
+      return "origin/%s" % name
+    return "origin/branch-heads/%s" % name
+
+
+class GitReadSvnWriteInterface(GitReadOnlyMixin, GitSvnInterface):
+  pass
+
+
+VC_INTERFACES = {
+  "git_svn": GitSvnInterface,
+  "git_read_svn_write": GitReadSvnWriteInterface,
+}
+
 
 class Step(GitRecipesMixin):
   def __init__(self, text, number, config, state, options, handler):
@@ -355,7 +394,7 @@
     self._state = state
     self._options = options
     self._side_effect_handler = handler
-    self.vc = GitSvnInterface()
+    self.vc = VC_INTERFACES[options.vc_interface]()
     self.vc.InjectStep(self)
 
     # The testing configuration might set a different default cwd.
@@ -740,6 +779,9 @@
     parser.add_argument("-s", "--step",
         help="Specify the step where to start work. Default: 0.",
         default=0, type=int)
+    parser.add_argument("--vc-interface",
+                        help=("Choose VC interface out of git_svn|"
+                              "git_read_svn_write."))
     self._PrepareOptions(parser)
 
     if args is None:  # pragma: no cover
@@ -776,6 +818,9 @@
     if not self._ProcessOptions(options):
       parser.print_help()
       return None
+
+    if not options.vc_interface:
+      options.vc_interface = "git_svn"
     return options
 
   def RunSteps(self, step_classes, args=None):
diff --git a/tools/push-to-trunk/git_recipes.py b/tools/push-to-trunk/git_recipes.py
index d146748..a1e6256 100644
--- a/tools/push-to-trunk/git_recipes.py
+++ b/tools/push-to-trunk/git_recipes.py
@@ -207,7 +207,7 @@
     if bypass_hooks:
       args.append("--bypass-hooks")
     if cc:
-      args += ["-cc", Quoted(cc)]
+      args += ["--cc", Quoted(cc)]
     # TODO(machenbach): Check output in forced mode. Verify that all required
     # base files were uploaded, if not retry.
     self.Git(MakeArgs(args), pipe=False, **kwargs)
@@ -295,8 +295,11 @@
   @Strip
   def GitSVNFindGitHash(self, revision, branch="", **kwargs):
     assert revision
-    return self.Git(
-        MakeArgs(["svn find-rev", "r%s" % revision, branch]), **kwargs)
+    args = MakeArgs(["svn find-rev", "r%s" % revision, branch])
+
+    # Pick the last line if multiple lines are available. The first lines might
+    # print information about rebuilding the svn-git mapping.
+    return self.Git(args, **kwargs).splitlines()[-1]
 
   @Strip
   def GitSVNFindSVNRev(self, git_hash, branch="", **kwargs):
diff --git a/tools/push-to-trunk/test_scripts.py b/tools/push-to-trunk/test_scripts.py
index 5475c49..4edb348 100644
--- a/tools/push-to-trunk/test_scripts.py
+++ b/tools/push-to-trunk/test_scripts.py
@@ -1137,7 +1137,7 @@
       Cmd("git commit -aF \"%s\"" % TEST_CONFIG["COMMITMSG_FILE"], ""),
       RL("reviewer@chromium.org"),  # V8 reviewer.
       Cmd("git cl upload --send-mail -r \"reviewer@chromium.org\" "
-          "--bypass-hooks -cc \"ulan@chromium.org\"", ""),
+          "--bypass-hooks --cc \"ulan@chromium.org\"", ""),
       Cmd("git checkout -f %s" % TEST_CONFIG["BRANCHNAME"], ""),
       RL("LGTM"),  # Enter LGTM for V8 CL.
       Cmd("git cl presubmit", "Presubmit successfull\n"),
@@ -1150,8 +1150,137 @@
 
     # r12345 and r34567 are patches. r23456 (included) and r45678 are the MIPS
     # ports of r12345. r56789 is the MIPS port of r34567.
-    args = ["-f", "-p", extra_patch, "--branch", "trunk", "12345", "23456",
-            "34567"]
+    args = ["-f", "-p", extra_patch, "--branch", "trunk",
+            "--vc-interface", "git_svn", "12345", "23456", "34567"]
+
+    # The first run of the script stops because of the svn being down.
+    self.assertRaises(GitFailedException,
+        lambda: MergeToBranch(TEST_CONFIG, self).Run(args))
+
+    # Test that state recovery after restarting the script works.
+    args += ["-s", "3"]
+    MergeToBranch(TEST_CONFIG, self).Run(args)
+
+  def testMergeToBranchNewGit(self):
+    TEST_CONFIG["ALREADY_MERGING_SENTINEL_FILE"] = self.MakeEmptyTempFile()
+    TextToFile("", os.path.join(TEST_CONFIG["DEFAULT_CWD"], ".git"))
+    self.WriteFakeVersionFile(build=5)
+    os.environ["EDITOR"] = "vi"
+    extra_patch = self.MakeEmptyTempFile()
+
+    def VerifyPatch(patch):
+      return lambda: self.assertEquals(patch,
+          FileToText(TEST_CONFIG["TEMPORARY_PATCH_FILE"]))
+
+    msg = """Version 3.22.5.1 (merged r12345, r23456, r34567, r45678, r56789)
+
+Title4
+
+Title2
+
+Title3
+
+Title1
+
+Revert "Something"
+
+BUG=123,234,345,456,567,v8:123
+LOG=N
+"""
+
+    def VerifySVNCommit():
+      commit = FileToText(TEST_CONFIG["COMMITMSG_FILE"])
+      self.assertEquals(msg, 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.assertTrue(re.search(r"#define PATCH_LEVEL\s+1", version))
+      self.assertTrue(re.search(r"#define IS_CANDIDATE_VERSION\s+0", version))
+
+    self.Expect([
+      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 checkout -b %s origin/candidates" %
+          TEST_CONFIG["BRANCHNAME"], ""),
+      Cmd(("git log --format=%H --grep=\"Port r12345\" "
+           "--reverse origin/master"),
+          "hash1\nhash2"),
+      Cmd("git svn find-rev hash1 origin/master", "45678"),
+      Cmd("git log -1 --format=%s hash1", "Title1"),
+      Cmd("git svn find-rev hash2 origin/master", "23456"),
+      Cmd("git log -1 --format=%s hash2", "Title2"),
+      Cmd(("git log --format=%H --grep=\"Port r23456\" "
+           "--reverse origin/master"),
+          ""),
+      Cmd(("git log --format=%H --grep=\"Port r34567\" "
+           "--reverse origin/master"),
+          "hash3"),
+      Cmd("git svn find-rev hash3 origin/master", "56789"),
+      Cmd("git log -1 --format=%s hash3", "Title3"),
+      RL("Y"),  # Automatically add corresponding ports (34567, 56789)?
+      Cmd("git svn find-rev r12345 origin/master",
+          "Partial-rebuilding bla\nDone rebuilding blub\nhash4"),
+      # Simulate svn being down which stops the script.
+      Cmd("git svn find-rev r23456 origin/master", None),
+      # Restart script in the failing step.
+      Cmd("git svn find-rev r12345 origin/master", "hash4"),
+      Cmd("git svn find-rev r23456 origin/master", "hash2"),
+      Cmd("git svn find-rev r34567 origin/master", "hash3"),
+      Cmd("git svn find-rev r45678 origin/master", "hash1"),
+      Cmd("git svn find-rev r56789 origin/master", "hash5"),
+      Cmd("git log -1 --format=%s hash4", "Title4"),
+      Cmd("git log -1 --format=%s hash2", "Title2"),
+      Cmd("git log -1 --format=%s hash3", "Title3"),
+      Cmd("git log -1 --format=%s hash1", "Title1"),
+      Cmd("git log -1 --format=%s hash5", "Revert \"Something\""),
+      Cmd("git log -1 hash4", "Title4\nBUG=123\nBUG=234"),
+      Cmd("git log -1 hash2", "Title2\n BUG = v8:123,345"),
+      Cmd("git log -1 hash3", "Title3\nLOG=n\nBUG=567, 456"),
+      Cmd("git log -1 hash1", "Title1\nBUG="),
+      Cmd("git log -1 hash5", "Revert \"Something\"\nBUG=none"),
+      Cmd("git log -1 -p hash4", "patch4"),
+      Cmd(("git apply --index --reject \"%s\"" %
+           TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
+          "", cb=VerifyPatch("patch4")),
+      Cmd("git log -1 -p hash2", "patch2"),
+      Cmd(("git apply --index --reject \"%s\"" %
+           TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
+          "", cb=VerifyPatch("patch2")),
+      Cmd("git log -1 -p hash3", "patch3"),
+      Cmd(("git apply --index --reject \"%s\"" %
+           TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
+          "", cb=VerifyPatch("patch3")),
+      Cmd("git log -1 -p hash1", "patch1"),
+      Cmd(("git apply --index --reject \"%s\"" %
+           TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
+          "", cb=VerifyPatch("patch1")),
+      Cmd("git log -1 -p hash5", "patch5\n"),
+      Cmd(("git apply --index --reject \"%s\"" %
+           TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
+          "", cb=VerifyPatch("patch5\n")),
+      Cmd("git apply --index --reject \"%s\"" % extra_patch, ""),
+      RL("Y"),  # Automatically increment patch level?
+      Cmd("git commit -aF \"%s\"" % TEST_CONFIG["COMMITMSG_FILE"], ""),
+      RL("reviewer@chromium.org"),  # V8 reviewer.
+      Cmd("git cl upload --send-mail -r \"reviewer@chromium.org\" "
+          "--bypass-hooks --cc \"ulan@chromium.org\"", ""),
+      Cmd("git checkout -f %s" % TEST_CONFIG["BRANCHNAME"], ""),
+      RL("LGTM"),  # Enter LGTM for V8 CL.
+      Cmd("git cl presubmit", "Presubmit successfull\n"),
+      Cmd("git cl dcommit -f --bypass-hooks", "Closing issue\n",
+          cb=VerifySVNCommit),
+      Cmd("git svn tag 3.22.5.1 -m \"Tagging version 3.22.5.1\"", ""),
+      Cmd("git checkout -f some_branch", ""),
+      Cmd("git branch -D %s" % TEST_CONFIG["BRANCHNAME"], ""),
+    ])
+
+    # r12345 and r34567 are patches. r23456 (included) and r45678 are the MIPS
+    # ports of r12345. r56789 is the MIPS port of r34567.
+    args = ["-f", "-p", extra_patch, "--branch", "candidates",
+            "--vc-interface", "git_read_svn_write", "12345", "23456", "34567"]
 
     # The first run of the script stops because of the svn being down.
     self.assertRaises(GitFailedException,
@@ -1521,7 +1650,10 @@
 
 class SystemTest(unittest.TestCase):
   def testReload(self):
+    options = ScriptsBase(
+        TEST_CONFIG, DEFAULT_SIDE_EFFECT_HANDLER, {}).MakeOptions([])
     step = MakeStep(step_class=PrepareChangeLog, number=0, state={}, config={},
+                    options=options,
                     side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER)
     body = step.Reload(
 """------------------------------------------------------------------------
diff --git a/tools/testrunner/local/testsuite.py b/tools/testrunner/local/testsuite.py
index 47bc08f..148697b 100644
--- a/tools/testrunner/local/testsuite.py
+++ b/tools/testrunner/local/testsuite.py
@@ -234,7 +234,7 @@
     if output.exit_code != 0:
       print output.stdout
       print output.stderr
-      return []
+      raise Exception("Test executable failed to list the tests.")
     tests = []
     test_case = ''
     for line in output.stdout.splitlines():
diff --git a/tools/whitespace.txt b/tools/whitespace.txt
index 54d0867..8b0db48 100644
--- a/tools/whitespace.txt
+++ b/tools/whitespace.txt
@@ -1,8 +1,8 @@
-You can modify this file to create no-op changelists..
+You can modify this file to create no-op changelists.
 
 Try to write something funny. And please don't add trailing whitespace.
 
 A Smi walks into a bar and says:
 "I'm so deoptimized today!"
 The doubles heard this and started to unbox.
-The Smi looked at them when a crazy v8-autoroll account showed up.............
+The Smi looked at them when a crazy v8-autoroll account showed up.