Version 3.25.25 (based on bleeding_edge revision r20239)

Roll ICU 239289:258359 and add support for external ICU data tables (issue 3142, Chromium issue 72633).

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@20247 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index ff54fa5..a376aaf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2014-03-25: Version 3.25.25
+
+        Roll ICU 239289:258359 and add support for external ICU data tables
+        (issue 3142, Chromium issue 72633).
+
+        Performance and stability improvements on all platforms.
+
+
 2014-03-25: Version 3.25.24
 
         Add support for per-isolate private symbols.
diff --git a/DEPS b/DEPS
index 66d21eb..353c5c8 100644
--- a/DEPS
+++ b/DEPS
@@ -8,7 +8,7 @@
     "http://gyp.googlecode.com/svn/trunk@1831",
 
   "v8/third_party/icu":
-    "https://src.chromium.org/chrome/trunk/deps/third_party/icu46@239289",
+    "https://src.chromium.org/chrome/trunk/deps/third_party/icu46@258359",
 }
 
 deps_os = {
diff --git a/Makefile b/Makefile
index 6bd9bac..f390028 100644
--- a/Makefile
+++ b/Makefile
@@ -465,4 +465,4 @@
 	    --revision 1831
 	svn checkout --force \
 	    https://src.chromium.org/chrome/trunk/deps/third_party/icu46 \
-	    third_party/icu --revision 239289
+	    third_party/icu --revision 258359
diff --git a/include/v8.h b/include/v8.h
index 3687485..6590ed5 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -4975,8 +4975,11 @@
   /**
    * Initialize the ICU library bundled with V8. The embedder should only
    * invoke this method when using the bundled ICU. Returns true on success.
+   *
+   * If V8 was compiled with the ICU data in an external file, the location
+   * of the data file has to be provided.
    */
-  static bool InitializeICU();
+  static bool InitializeICU(const char* icu_data_file = NULL);
 
   /**
    * Sets the v8::Platform to use. This should be invoked before V8 is
diff --git a/src/api.cc b/src/api.cc
index ca50778..f5ae10d 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -5112,8 +5112,8 @@
 }
 
 
-bool v8::V8::InitializeICU() {
-  return i::InitializeICU();
+bool v8::V8::InitializeICU(const char* icu_data_file) {
+  return i::InitializeICU(icu_data_file);
 }
 
 
@@ -5403,6 +5403,8 @@
   if (length == -1) length = StringLength(data);
   i::Handle<i::String> result = NewString(
       isolate->factory(), type, i::Vector<const Char>(data, length));
+  // We do not expect this to fail. Change this if it does.
+  CHECK(!result.is_null());
   if (type == String::kUndetectableString) {
     result->MarkAsUndetectable();
   }
@@ -5460,8 +5462,8 @@
   i::Handle<i::String> right_string = Utils::OpenHandle(*right);
   i::Handle<i::String> result = isolate->factory()->NewConsString(left_string,
                                                                   right_string);
-  // We do not expect this to throw an exception. Change this if it does.
-  CHECK_NOT_EMPTY_HANDLE(isolate, result);
+  // We do not expect this to fail. Change this if it does.
+  CHECK(!result.is_null());
   return Utils::ToLocal(result);
 }
 
@@ -5469,14 +5471,22 @@
 static i::Handle<i::String> NewExternalStringHandle(
     i::Isolate* isolate,
     v8::String::ExternalStringResource* resource) {
-  return isolate->factory()->NewExternalStringFromTwoByte(resource);
+  i::Handle<i::String> result =
+      isolate->factory()->NewExternalStringFromTwoByte(resource);
+  // We do not expect this to fail. Change this if it does.
+  CHECK(!result.is_null());
+  return result;
 }
 
 
 static i::Handle<i::String> NewExternalAsciiStringHandle(
     i::Isolate* isolate,
     v8::String::ExternalAsciiStringResource* resource) {
-  return isolate->factory()->NewExternalStringFromAscii(resource);
+  i::Handle<i::String> result =
+      isolate->factory()->NewExternalStringFromAscii(resource);
+  // We do not expect this to fail. Change this if it does.
+  CHECK(!result.is_null());
+  return result;
 }
 
 
@@ -7000,8 +7010,8 @@
     i::Handle<i::String> cons = isolate->factory()->NewConsString(
         isolate->factory()->InternalizeUtf8String(entry->name_prefix()),
         isolate->factory()->InternalizeUtf8String(entry->name()));
-    // We do not expect this to throw an exception. Change this if it does.
-    CHECK_NOT_EMPTY_HANDLE(isolate, cons);
+    // We do not expect this to fail. Change this if it does.
+    CHECK(!cons.is_null());
     return ToApiHandle<String>(cons);
   }
 }
diff --git a/src/arm64/assembler-arm64.h b/src/arm64/assembler-arm64.h
index 41eaaad..1aae2f2 100644
--- a/src/arm64/assembler-arm64.h
+++ b/src/arm64/assembler-arm64.h
@@ -588,22 +588,18 @@
   CPURegister::RegisterType type_;
 
   bool IsValid() const {
-    if ((type_ == CPURegister::kRegister) ||
-        (type_ == CPURegister::kFPRegister)) {
-      bool is_valid = true;
-      // Try to create a CPURegister for each element in the list.
-      for (int i = 0; i < kRegListSizeInBits; i++) {
-        if (((list_ >> i) & 1) != 0) {
-          is_valid &= CPURegister::Create(i, size_, type_).IsValid();
-        }
-      }
-      return is_valid;
-    } else if (type_ == CPURegister::kNoRegister) {
-      // The kNoRegister type is valid only for empty lists.
-      // We can't use IsEmpty here because that asserts IsValid().
-      return list_ == 0;
-    } else {
-      return false;
+    const RegList kValidRegisters = 0x8000000ffffffff;
+    const RegList kValidFPRegisters = 0x0000000ffffffff;
+    switch (type_) {
+      case CPURegister::kRegister:
+        return (list_ & kValidRegisters) == list_;
+      case CPURegister::kFPRegister:
+        return (list_ & kValidFPRegisters) == list_;
+      case CPURegister::kNoRegister:
+        return list_ == 0;
+      default:
+        UNREACHABLE();
+        return false;
     }
   }
 };
diff --git a/src/ast.cc b/src/ast.cc
index 086d015..f6cf189 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -357,8 +357,7 @@
   // Allocate a fixed array to hold all the object literals.
   Handle<JSArray> array =
       isolate->factory()->NewJSArray(0, FAST_HOLEY_SMI_ELEMENTS);
-  isolate->factory()->SetElementsCapacityAndLength(
-      array, values()->length(), values()->length());
+  JSArray::Expand(array, values()->length());
 
   // Fill in the literals.
   bool is_simple = true;
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 7942c7f..b2a52cd 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -88,6 +88,8 @@
                                           source.length());
     Handle<String> source_code =
         isolate_->factory()->NewExternalStringFromAscii(resource);
+    // We do not expect this to throw an exception. Change this if it does.
+    CHECK_NOT_EMPTY_HANDLE(isolate_, source_code);
     heap->natives_source_cache()->set(index, *source_code);
   }
   Handle<Object> cached_source(heap->natives_source_cache()->get(index),
@@ -1463,6 +1465,7 @@
   Handle<String> source_code =
       factory->NewStringFromAscii(
           ExperimentalNatives::GetRawScriptSource(index));
+  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, source_code, false);
   return CompileNative(isolate, name, source_code);
 }
 
@@ -1512,6 +1515,7 @@
   if (cache == NULL || !cache->Lookup(name, &function_info)) {
     ASSERT(source->IsOneByteRepresentation());
     Handle<String> script_name = factory->NewStringFromUtf8(name);
+    ASSERT(!script_name.is_null());
     function_info = Compiler::CompileScript(
         source,
         script_name,
@@ -2080,8 +2084,10 @@
   ASSERT_EQ(".prototype", period_pos);
   Vector<const char> property(holder_expr,
                               static_cast<int>(period_pos - holder_expr));
+  Handle<String> property_string = factory->InternalizeUtf8String(property);
+  ASSERT(!property_string.is_null());
   Handle<JSFunction> function = Handle<JSFunction>::cast(
-      GetProperty(isolate, global, factory->InternalizeUtf8String(property)));
+      GetProperty(isolate, global, property_string));
   return Handle<JSObject>(JSObject::cast(function->prototype()));
 }
 
@@ -2349,6 +2355,8 @@
   }
   Handle<String> source_code =
       isolate->factory()->NewExternalStringFromAscii(extension->source());
+  // We do not expect this to throw an exception. Change this if it does.
+  CHECK_NOT_EMPTY_HANDLE(isolate, source_code);
   bool result = CompileScriptCached(isolate,
                                     CStrVector(extension->name()),
                                     source_code,
diff --git a/src/bootstrapper.h b/src/bootstrapper.h
index 14dd1bd..e683a45 100644
--- a/src/bootstrapper.h
+++ b/src/bootstrapper.h
@@ -73,6 +73,7 @@
     cache_->CopyTo(0, *new_array, 0, cache_->length());
     cache_ = *new_array;
     Handle<String> str = factory->NewStringFromAscii(name, TENURED);
+    ASSERT(!str.is_null());
     cache_->set(length, *str);
     cache_->set(length + 1, *shared);
     Script::cast(shared->script())->set_type(Smi::FromInt(type_));
diff --git a/src/builtins.cc b/src/builtins.cc
index b73ed6b..e460a8f 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -506,23 +506,7 @@
     uint32_t key,
     Handle<FixedArrayBase> backing_store = Handle<FixedArrayBase>::null()) {
   return accessor->HasElement(*receiver, *holder, key,
-                              backing_store.is_null() ? *backing_store : NULL);
-}
-
-
-// TODO(ishell): Temporary wrapper until handlified.
-static Handle<Object> ElementsAccessorGetWrapper(
-    Isolate* isolate,
-    ElementsAccessor* accessor,
-    Handle<Object> receiver,
-    Handle<JSObject> holder,
-    uint32_t key,
-    Handle<FixedArrayBase> backing_store = Handle<FixedArrayBase>::null()) {
-  CALL_HEAP_FUNCTION(isolate,
-                     accessor->Get(*receiver, *holder, key,
-                                   backing_store.is_null()
-                                   ? *backing_store : NULL),
-                     Object);
+                              backing_store.is_null() ? NULL : *backing_store);
 }
 
 
@@ -544,8 +528,8 @@
   Handle<Object> element;
   if (ElementsAccessorHasElementWrapper(
       accessor, array, array, new_length, elms_obj)) {
-    element = ElementsAccessorGetWrapper(
-        isolate, accessor, array, array, new_length, elms_obj);
+    element = accessor->Get(
+        array, array, new_length, elms_obj);
   } else {
     Handle<Object> proto(array->GetPrototype(), isolate);
     element = Object::GetElement(isolate, proto, len - 1);
@@ -578,11 +562,12 @@
   // Get first element
   ElementsAccessor* accessor = array->GetElementsAccessor();
   Handle<Object> first = accessor->Get(receiver, array, 0, elms_obj);
+  RETURN_IF_EMPTY_HANDLE(isolate, first);
   if (first->IsTheHole()) {
     first = isolate->factory()->undefined_value();
   }
 
-  if (!heap->lo_space()->Contains(*elms_obj)) {
+  if (!heap->CanMoveObjectStart(*elms_obj)) {
     array->set_elements(LeftTrimFixedArray(heap, *elms_obj, 1));
   } else {
     // Shift the elements.
@@ -906,8 +891,24 @@
         heap->MoveElements(*elms, delta, 0, actual_start);
       }
 
-      elms_obj = handle(LeftTrimFixedArray(heap, *elms_obj, delta));
-
+      if (heap->CanMoveObjectStart(*elms_obj)) {
+        // On the fast path we move the start of the object in memory.
+        elms_obj = handle(LeftTrimFixedArray(heap, *elms_obj, delta));
+      } else {
+        // This is the slow path. We are going to move the elements to the left
+        // by copying them. For trimmed values we store the hole.
+        if (elms_obj->IsFixedDoubleArray()) {
+          Handle<FixedDoubleArray> elms =
+              Handle<FixedDoubleArray>::cast(elms_obj);
+          MoveDoubleElements(*elms, 0, *elms, delta, len - delta);
+          FillWithHoles(*elms, len - delta, len);
+        } else {
+          Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
+          DisallowHeapAllocation no_gc;
+          heap->MoveElements(*elms, 0, delta, len - delta);
+          FillWithHoles(heap, *elms, len - delta, len);
+        }
+      }
       elms_changed = true;
     } else {
       if (elms_obj->IsFixedDoubleArray()) {
diff --git a/src/contexts.cc b/src/contexts.cc
index ada6e04..33d47e9 100644
--- a/src/contexts.cc
+++ b/src/contexts.cc
@@ -368,7 +368,7 @@
   Handle<Object> result(error_message_for_code_gen_from_strings(),
                         GetIsolate());
   if (!result->IsUndefined()) return result;
-  return GetIsolate()->factory()->NewStringFromAscii(i::CStrVector(
+  return GetIsolate()->factory()->NewStringFromOneByte(STATIC_ASCII_VECTOR(
       "Code generation from strings disallowed for this context"));
 }
 
diff --git a/src/d8.cc b/src/d8.cc
index d071105..7ac0c65 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -1440,6 +1440,9 @@
     } else if (strcmp(argv[i], "--throws") == 0) {
       options.expected_to_throw = true;
       argv[i] = NULL;
+    } else if (strncmp(argv[i], "--icu-data-file=", 16) == 0) {
+      options.icu_data_file = argv[i] + 16;
+      argv[i] = NULL;
     }
 #ifdef V8_SHARED
     else if (strcmp(argv[i], "--dump-counters") == 0) {
@@ -1674,7 +1677,7 @@
 
 int Shell::Main(int argc, char* argv[]) {
   if (!SetOptions(argc, argv)) return 1;
-  v8::V8::InitializeICU();
+  v8::V8::InitializeICU(options.icu_data_file);
 #ifndef V8_SHARED
   i::FLAG_trace_hydrogen_file = "hydrogen.cfg";
   i::FLAG_redirect_code_traces_to = "code.asm";
diff --git a/src/d8.h b/src/d8.h
index db2edb9..3edd8a7 100644
--- a/src/d8.h
+++ b/src/d8.h
@@ -233,7 +233,8 @@
      expected_to_throw(false),
      mock_arraybuffer_allocator(false),
      num_isolates(1),
-     isolate_sources(NULL) { }
+     isolate_sources(NULL),
+     icu_data_file(NULL) { }
 
   ~ShellOptions() {
 #ifndef V8_SHARED
@@ -258,6 +259,7 @@
   bool mock_arraybuffer_allocator;
   int num_isolates;
   SourceGroup* isolate_sources;
+  const char* icu_data_file;
 };
 
 #ifdef V8_SHARED
diff --git a/src/debug.cc b/src/debug.cc
index c8a99d5..d7667f1 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -754,6 +754,7 @@
       isolate->bootstrapper()->NativesSourceLookup(index);
   Vector<const char> name = Natives::GetScriptName(index);
   Handle<String> script_name = factory->NewStringFromAscii(name);
+  ASSERT(!script_name.is_null());
   Handle<Context> context = isolate->native_context();
 
   // Compile the script.
@@ -2599,6 +2600,7 @@
   // Create the execution state object.
   Handle<String> constructor_str =
       isolate_->factory()->InternalizeUtf8String(constructor_name);
+  ASSERT(!constructor_str.is_null());
   Handle<Object> constructor(
       isolate_->global_object()->GetPropertyNoExceptionThrown(*constructor_str),
       isolate_);
diff --git a/src/elements.cc b/src/elements.cc
index 527df6e..c8e28c5 100644
--- a/src/elements.cc
+++ b/src/elements.cc
@@ -766,14 +766,16 @@
       Handle<Object> length,
       Handle<FixedArrayBase> backing_store);
 
-  MUST_USE_RESULT virtual MaybeObject* SetCapacityAndLength(
-      JSArray* array,
+  virtual void SetCapacityAndLength(
+      Handle<JSArray> array,
       int capacity,
       int length) V8_FINAL V8_OVERRIDE {
-    return ElementsAccessorSubclass::SetFastElementsCapacityAndLength(
-        array,
-        capacity,
-        length);
+    CALL_HEAP_FUNCTION_VOID(
+        array->GetIsolate(),
+        ElementsAccessorSubclass::SetFastElementsCapacityAndLength(
+            *array,
+            capacity,
+            length));
   }
 
   MUST_USE_RESULT static MaybeObject* SetFastElementsCapacityAndLength(
@@ -784,6 +786,16 @@
     return obj;
   }
 
+  // TODO(ishell): Temporary wrapper until handlified.
+  MUST_USE_RESULT static Handle<Object> SetFastElementsCapacityAndLength(
+      Handle<JSObject> obj,
+      int capacity,
+      int length) {
+    CALL_HEAP_FUNCTION(obj->GetIsolate(),
+                       SetFastElementsCapacityAndLength(*obj, capacity, length),
+                       Object);
+  }
+
   MUST_USE_RESULT virtual Handle<Object> Delete(
       Handle<JSObject> obj,
       uint32_t key,
@@ -978,28 +990,28 @@
 
   // Adjusts the length of the fast backing store or returns the new length or
   // undefined in case conversion to a slow backing store should be performed.
-  static MaybeObject* SetLengthWithoutNormalize(FixedArrayBase* backing_store,
-                                                JSArray* array,
-                                                Object* length_object,
-                                                uint32_t length) {
+  static Handle<Object> SetLengthWithoutNormalize(
+      Handle<FixedArrayBase> backing_store,
+      Handle<JSArray> array,
+      Handle<Object> length_object,
+      uint32_t length) {
+    Isolate* isolate = array->GetIsolate();
     uint32_t old_capacity = backing_store->length();
-    Object* old_length = array->length();
+    Handle<Object> old_length(array->length(), isolate);
     bool same_or_smaller_size = old_length->IsSmi() &&
-        static_cast<uint32_t>(Smi::cast(old_length)->value()) >= length;
+        static_cast<uint32_t>(Handle<Smi>::cast(old_length)->value()) >= length;
     ElementsKind kind = array->GetElementsKind();
 
     if (!same_or_smaller_size && IsFastElementsKind(kind) &&
         !IsFastHoleyElementsKind(kind)) {
       kind = GetHoleyElementsKind(kind);
-      MaybeObject* maybe_obj = array->TransitionElementsKind(kind);
-      if (maybe_obj->IsFailure()) return maybe_obj;
+      JSObject::TransitionElementsKind(array, kind);
     }
 
     // Check whether the backing store should be shrunk.
     if (length <= old_capacity) {
       if (array->HasFastSmiOrObjectElements()) {
-        MaybeObject* maybe_obj = array->EnsureWritableFastElements();
-        if (!maybe_obj->To(&backing_store)) return maybe_obj;
+        backing_store = JSObject::EnsureWritableFastElements(array);
       }
       if (2 * length <= old_capacity) {
         // If more than half the elements won't be used, trim the array.
@@ -1016,7 +1028,7 @@
         // Otherwise, fill the unused tail with holes.
         int old_length = FastD2IChecked(array->length()->Number());
         for (int i = length; i < old_length; i++) {
-          BackingStore::cast(backing_store)->set_the_hole(i);
+          Handle<BackingStore>::cast(backing_store)->set_the_hole(i);
         }
       }
       return length_object;
@@ -1026,27 +1038,14 @@
     uint32_t min = JSObject::NewElementsCapacity(old_capacity);
     uint32_t new_capacity = length > min ? length : min;
     if (!array->ShouldConvertToSlowElements(new_capacity)) {
-      MaybeObject* result = FastElementsAccessorSubclass::
+      FastElementsAccessorSubclass::
           SetFastElementsCapacityAndLength(array, new_capacity, length);
-      if (result->IsFailure()) return result;
       array->ValidateElements();
       return length_object;
     }
 
     // Request conversion to slow elements.
-    return array->GetHeap()->undefined_value();
-  }
-
-  // TODO(ishell): Temporary wrapper until handlified.
-  static Handle<Object> SetLengthWithoutNormalize(
-      Handle<FixedArrayBase> backing_store,
-      Handle<JSArray> array,
-      Handle<Object> length_object,
-      uint32_t length) {
-    CALL_HEAP_FUNCTION(array->GetIsolate(),
-                       SetLengthWithoutNormalize(
-                           *backing_store, *array, *length_object, length),
-                       Object);
+    return isolate->factory()->undefined_value();
   }
 
   static Handle<Object> DeleteCommon(Handle<JSObject> obj,
@@ -1244,6 +1243,16 @@
                                                  length,
                                                  set_capacity_mode);
   }
+
+  // TODO(ishell): Temporary wrapper until handlified.
+  static Handle<Object> SetFastElementsCapacityAndLength(
+      Handle<JSObject> obj,
+      int capacity,
+      int length) {
+    CALL_HEAP_FUNCTION(obj->GetIsolate(),
+                       SetFastElementsCapacityAndLength(*obj, capacity, length),
+                       Object);
+  }
 };
 
 
@@ -1314,6 +1323,16 @@
                                                        length);
   }
 
+  // TODO(ishell): Temporary wrapper until handlified.
+  static Handle<Object> SetFastElementsCapacityAndLength(
+      Handle<JSObject> obj,
+      int capacity,
+      int length) {
+    CALL_HEAP_FUNCTION(obj->GetIsolate(),
+                       SetFastElementsCapacityAndLength(*obj, capacity, length),
+                       Object);
+  }
+
  protected:
   static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
                                        uint32_t from_start,
diff --git a/src/elements.h b/src/elements.h
index bd5e722..2ee07aa 100644
--- a/src/elements.h
+++ b/src/elements.h
@@ -126,9 +126,10 @@
   // elements. This method should only be called for array expansion OR by
   // runtime JavaScript code that use InternalArrays and don't care about
   // EcmaScript 5.1 semantics.
-  MUST_USE_RESULT virtual MaybeObject* SetCapacityAndLength(JSArray* array,
-                                                            int capacity,
-                                                            int length) = 0;
+  virtual void SetCapacityAndLength(
+      Handle<JSArray> array,
+      int capacity,
+      int length) = 0;
 
   // Deletes an element in an object, returning a new elements backing store.
   MUST_USE_RESULT virtual Handle<Object> Delete(
diff --git a/src/factory.cc b/src/factory.cc
index 5e66202..e292455 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -289,7 +289,7 @@
 
 
 Handle<SeqOneByteString> Factory::NewRawOneByteString(int length,
-                                                  PretenureFlag pretenure) {
+                                                      PretenureFlag pretenure) {
   CALL_HEAP_FUNCTION(
       isolate(),
       isolate()->heap()->AllocateRawOneByteString(length, pretenure),
@@ -411,6 +411,7 @@
     ASSERT(left->IsFlat());
     ASSERT(right->IsFlat());
 
+    STATIC_ASSERT(ConsString::kMinLength <= String::kMaxLength);
     if (is_one_byte) {
       Handle<SeqOneByteString> result = NewRawOneByteString(length);
       DisallowHeapAllocation no_gc;
@@ -496,12 +497,14 @@
   if (!FLAG_string_slices || length < SlicedString::kMinLength) {
     if (str->IsOneByteRepresentation()) {
       Handle<SeqOneByteString> result = NewRawOneByteString(length);
+      ASSERT(!result.is_null());
       uint8_t* dest = result->GetChars();
       DisallowHeapAllocation no_gc;
       String::WriteToFlat(*str, dest, begin, end);
       return result;
     } else {
       Handle<SeqTwoByteString> result = NewRawTwoByteString(length);
+      ASSERT(!result.is_null());
       uc16* dest = result->GetChars();
       DisallowHeapAllocation no_gc;
       String::WriteToFlat(*str, dest, begin, end);
@@ -1486,16 +1489,6 @@
 }
 
 
-void Factory::SetElementsCapacityAndLength(Handle<JSArray> array,
-                                           int capacity,
-                                           int length) {
-  ElementsAccessor* accessor = array->GetElementsAccessor();
-  CALL_HEAP_FUNCTION_VOID(
-      isolate(),
-      accessor->SetCapacityAndLength(*array, capacity, length));
-}
-
-
 Handle<JSGeneratorObject> Factory::NewJSGeneratorObject(
     Handle<JSFunction> function) {
   ASSERT(function->shared()->is_generator());
diff --git a/src/factory.h b/src/factory.h
index 5562ef4..e57e130 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -387,10 +387,6 @@
       int capacity,
       ArrayStorageAllocationMode mode = DONT_INITIALIZE_ARRAY_ELEMENTS);
 
-  void SetElementsCapacityAndLength(Handle<JSArray> array,
-                                    int capacity,
-                                    int length);
-
   Handle<JSGeneratorObject> NewJSGeneratorObject(Handle<JSFunction> function);
 
   Handle<JSArrayBuffer> NewJSArrayBuffer();
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 3b9ebb3..2d2cadf 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -276,6 +276,7 @@
 DEFINE_string(trace_phase, "HLZ", "trace generated IR for specified phases")
 DEFINE_bool(trace_inlining, false, "trace inlining decisions")
 DEFINE_bool(trace_load_elimination, false, "trace load elimination")
+DEFINE_bool(trace_store_elimination, false, "trace store elimination")
 DEFINE_bool(trace_alloc, false, "trace register allocator")
 DEFINE_bool(trace_all_uses, false, "trace all use positions")
 DEFINE_bool(trace_range, false, "trace range analysis")
@@ -311,6 +312,7 @@
             "analyze liveness of environment slots and zap dead values")
 DEFINE_bool(load_elimination, true, "use load elimination")
 DEFINE_bool(check_elimination, true, "use check elimination")
+DEFINE_bool(store_elimination, false, "use store elimination")
 DEFINE_bool(dead_code_elimination, true, "use dead code elimination")
 DEFINE_bool(fold_constants, true, "use constant folding")
 DEFINE_bool(trace_dead_code_elimination, false, "trace dead code elimination")
diff --git a/src/heap-inl.h b/src/heap-inl.h
index 7e465d5..063cf30 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -138,7 +138,7 @@
 MaybeObject* Heap::AllocateOneByteInternalizedString(Vector<const uint8_t> str,
                                                      uint32_t hash_field) {
   if (str.length() > String::kMaxLength) {
-    v8::internal::Heap::FatalProcessOutOfMemory("invalid string length", true);
+    return isolate()->ThrowInvalidStringLength();
   }
   // Compute map and object size.
   Map* map = ascii_internalized_string_map();
@@ -171,7 +171,7 @@
 MaybeObject* Heap::AllocateTwoByteInternalizedString(Vector<const uc16> str,
                                                      uint32_t hash_field) {
   if (str.length() > String::kMaxLength) {
-    v8::internal::Heap::FatalProcessOutOfMemory("invalid string length", true);
+    return isolate()->ThrowInvalidStringLength();
   }
   // Compute map and object size.
   Map* map = internalized_string_map();
diff --git a/src/heap.cc b/src/heap.cc
index e785629..eae7241 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -154,7 +154,6 @@
       configured_(false),
       external_string_table_(this),
       chunks_queued_for_free_(NULL),
-      relocation_mutex_(NULL),
       gc_callbacks_depth_(0) {
   // Allow build-time customization of the max semispace size. Building
   // V8 with snapshots and a non-default max semispace size is much
@@ -3866,7 +3865,7 @@
     const ExternalAsciiString::Resource* resource) {
   size_t length = resource->length();
   if (length > static_cast<size_t>(String::kMaxLength)) {
-    v8::internal::Heap::FatalProcessOutOfMemory("invalid string length", true);
+    return isolate()->ThrowInvalidStringLength();
   }
 
   Map* map = external_ascii_string_map();
@@ -3888,7 +3887,7 @@
     const ExternalTwoByteString::Resource* resource) {
   size_t length = resource->length();
   if (length > static_cast<size_t>(String::kMaxLength)) {
-    v8::internal::Heap::FatalProcessOutOfMemory("invalid string length", true);
+    return isolate()->ThrowInvalidStringLength();
   }
 
   // For small strings we check whether the resource contains only
@@ -3969,6 +3968,21 @@
 }
 
 
+bool Heap::CanMoveObjectStart(HeapObject* object) {
+  Address address = object->address();
+  bool is_in_old_pointer_space = InOldPointerSpace(address);
+  bool is_in_old_data_space = InOldDataSpace(address);
+
+  if (lo_space()->Contains(object)) return false;
+
+  // We cannot move the object start if the given old space page is
+  // concurrently swept.
+  return (!is_in_old_pointer_space && !is_in_old_data_space) ||
+      Page::FromAddress(address)->parallel_sweeping() <=
+          MemoryChunk::PARALLEL_SWEEPING_FINALIZE;
+}
+
+
 void Heap::AdjustLiveBytes(Address address, int by, InvocationMode mode) {
   if (incremental_marking()->IsMarking() &&
       Marking::IsBlack(Marking::MarkBitFrom(address))) {
@@ -4973,8 +4987,8 @@
   int size;
   Map* map;
 
-  if (chars > String::kMaxLength) {
-    v8::internal::Heap::FatalProcessOutOfMemory("invalid string length", true);
+  if (chars < 0 || chars > String::kMaxLength) {
+    return isolate()->ThrowInvalidStringLength();
   }
   if (is_one_byte) {
     map = ascii_internalized_string_map();
@@ -5022,7 +5036,7 @@
 MaybeObject* Heap::AllocateRawOneByteString(int length,
                                             PretenureFlag pretenure) {
   if (length < 0 || length > String::kMaxLength) {
-    v8::internal::Heap::FatalProcessOutOfMemory("invalid string length", true);
+    return isolate()->ThrowInvalidStringLength();
   }
   int size = SeqOneByteString::SizeFor(length);
   ASSERT(size <= SeqOneByteString::kMaxSize);
@@ -5046,7 +5060,7 @@
 MaybeObject* Heap::AllocateRawTwoByteString(int length,
                                             PretenureFlag pretenure) {
   if (length < 0 || length > String::kMaxLength) {
-    v8::internal::Heap::FatalProcessOutOfMemory("invalid string length", true);
+    return isolate()->ThrowInvalidStringLength();
   }
   int size = SeqTwoByteString::SizeFor(length);
   ASSERT(size <= SeqTwoByteString::kMaxSize);
@@ -6595,8 +6609,6 @@
 
   mark_compact_collector()->SetUp();
 
-  if (FLAG_concurrent_recompilation) relocation_mutex_ = new Mutex;
-
   return true;
 }
 
@@ -6738,9 +6750,6 @@
   incremental_marking()->TearDown();
 
   isolate_->memory_allocator()->TearDown();
-
-  delete relocation_mutex_;
-  relocation_mutex_ = NULL;
 }
 
 
diff --git a/src/heap.h b/src/heap.h
index f6cd3eb..fde95ce 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -1177,6 +1177,8 @@
   // when shortening objects.
   void CreateFillerObjectAt(Address addr, int size);
 
+  bool CanMoveObjectStart(HeapObject* object);
+
   enum InvocationMode { FROM_GC, FROM_MUTATOR };
 
   // Maintain marking consistency for IncrementalMarking.
@@ -1906,16 +1908,12 @@
   class RelocationLock {
    public:
     explicit RelocationLock(Heap* heap) : heap_(heap) {
-      if (FLAG_concurrent_recompilation) {
-        heap_->relocation_mutex_->Lock();
-      }
+      heap_->relocation_mutex_.Lock();
     }
 
 
     ~RelocationLock() {
-      if (FLAG_concurrent_recompilation) {
-        heap_->relocation_mutex_->Unlock();
-      }
+      heap_->relocation_mutex_.Unlock();
     }
 
    private:
@@ -2518,7 +2516,7 @@
 
   MemoryChunk* chunks_queued_for_free_;
 
-  Mutex* relocation_mutex_;
+  Mutex relocation_mutex_;
 
   int gc_callbacks_depth_;
 
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index cfe5f1a..b822d84 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -841,6 +841,107 @@
 #endif
 
 
+static bool HasPrimitiveRepresentation(HValue* instr) {
+  return instr->representation().IsInteger32() ||
+    instr->representation().IsDouble();
+}
+
+
+bool HInstruction::CanDeoptimize() {
+  // TODO(titzer): make this a virtual method?
+  switch (opcode()) {
+    case HValue::kAccessArgumentsAt:
+    case HValue::kApplyArguments:
+    case HValue::kArgumentsElements:
+    case HValue::kArgumentsLength:
+    case HValue::kArgumentsObject:
+    case HValue::kBoundsCheckBaseIndexInformation:
+    case HValue::kCapturedObject:
+    case HValue::kClampToUint8:
+    case HValue::kConstant:
+    case HValue::kContext:
+    case HValue::kDateField:
+    case HValue::kDebugBreak:
+    case HValue::kDeclareGlobals:
+    case HValue::kDiv:
+    case HValue::kDummyUse:
+    case HValue::kEnterInlined:
+    case HValue::kEnvironmentMarker:
+    case HValue::kForInCacheArray:
+    case HValue::kForInPrepareMap:
+    case HValue::kFunctionLiteral:
+    case HValue::kGetCachedArrayIndex:
+    case HValue::kGoto:
+    case HValue::kInnerAllocatedObject:
+    case HValue::kInstanceOf:
+    case HValue::kInstanceOfKnownGlobal:
+    case HValue::kInvokeFunction:
+    case HValue::kLeaveInlined:
+    case HValue::kLoadContextSlot:
+    case HValue::kLoadFieldByIndex:
+    case HValue::kLoadFunctionPrototype:
+    case HValue::kLoadGlobalCell:
+    case HValue::kLoadGlobalGeneric:
+    case HValue::kLoadKeyed:
+    case HValue::kLoadKeyedGeneric:
+    case HValue::kLoadNamedField:
+    case HValue::kLoadNamedGeneric:
+    case HValue::kLoadRoot:
+    case HValue::kMapEnumLength:
+    case HValue::kMathFloorOfDiv:
+    case HValue::kMathMinMax:
+    case HValue::kMod:
+    case HValue::kMul:
+    case HValue::kOsrEntry:
+    case HValue::kParameter:
+    case HValue::kPower:
+    case HValue::kPushArgument:
+    case HValue::kRor:
+    case HValue::kSar:
+    case HValue::kSeqStringGetChar:
+    case HValue::kSeqStringSetChar:
+    case HValue::kShl:
+    case HValue::kShr:
+    case HValue::kSimulate:
+    case HValue::kStackCheck:
+    case HValue::kStoreCodeEntry:
+    case HValue::kStoreContextSlot:
+    case HValue::kStoreGlobalCell:
+    case HValue::kStoreKeyed:
+    case HValue::kStoreKeyedGeneric:
+    case HValue::kStoreNamedField:
+    case HValue::kStoreNamedGeneric:
+    case HValue::kStringAdd:
+    case HValue::kStringCharCodeAt:
+    case HValue::kStringCharFromCode:
+    case HValue::kSub:
+    case HValue::kThisFunction:
+    case HValue::kToFastProperties:
+    case HValue::kTransitionElementsKind:
+    case HValue::kTrapAllocationMemento:
+    case HValue::kTypeof:
+    case HValue::kUnaryMathOperation:
+    case HValue::kUseConst:
+    case HValue::kWrapReceiver:
+      return false;
+    case HValue::kForceRepresentation:
+    case HValue::kAdd:
+    case HValue::kBitwise:
+    case HValue::kChange:
+    case HValue::kCompareGeneric:
+      // These instructions might deoptimize if they are not primitive.
+      if (!HasPrimitiveRepresentation(this)) return true;
+      for (int i = 0; i < OperandCount(); i++) {
+        HValue* input = OperandAt(i);
+        if (!HasPrimitiveRepresentation(input)) return true;
+      }
+      return false;
+    default:
+      return true;
+  }
+}
+
+
 void HDummyUse::PrintDataTo(StringStream* stream) {
   value()->PrintNameTo(stream);
 }
@@ -3923,9 +4024,15 @@
     HConstant* c_right = HConstant::cast(right);
     HConstant* c_left = HConstant::cast(left);
     if (c_left->HasStringValue() && c_right->HasStringValue()) {
-      Handle<String> concat = zone->isolate()->factory()->NewFlatConcatString(
-          c_left->StringValue(), c_right->StringValue());
-      return HConstant::New(zone, context, concat);
+      Handle<String> left_string = c_left->StringValue();
+      Handle<String> right_string = c_right->StringValue();
+      // Prevent possible exception by invalid string length.
+      if (left_string->length() + right_string->length() < String::kMaxLength) {
+        Handle<String> concat = zone->isolate()->factory()->NewFlatConcatString(
+            c_left->StringValue(), c_right->StringValue());
+        ASSERT(!concat.is_null());
+        return HConstant::New(zone, context, concat);
+      }
     }
   }
   return new(zone) HStringAdd(
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 109cff0..d22cc32 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -1271,6 +1271,8 @@
   virtual void Verify() V8_OVERRIDE;
 #endif
 
+  bool CanDeoptimize();
+
   virtual bool HasStackCheck() { return false; }
 
   DECLARE_ABSTRACT_INSTRUCTION(Instruction)
diff --git a/src/hydrogen-store-elimination.cc b/src/hydrogen-store-elimination.cc
new file mode 100644
index 0000000..2e6ee51
--- /dev/null
+++ b/src/hydrogen-store-elimination.cc
@@ -0,0 +1,139 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "hydrogen-store-elimination.h"
+#include "hydrogen-instructions.h"
+
+namespace v8 {
+namespace internal {
+
+#define TRACE(x) if (FLAG_trace_store_elimination) PrintF x
+
+// Performs a block-by-block local analysis for removable stores.
+void HStoreEliminationPhase::Run() {
+  GVNFlagSet flags;  // Use GVN flags as an approximation for some instructions.
+  flags.RemoveAll();
+
+  flags.Add(kArrayElements);
+  flags.Add(kArrayLengths);
+  flags.Add(kStringLengths);
+  flags.Add(kBackingStoreFields);
+  flags.Add(kDoubleArrayElements);
+  flags.Add(kDoubleFields);
+  flags.Add(kElementsPointer);
+  flags.Add(kInobjectFields);
+  flags.Add(kExternalMemory);
+  flags.Add(kStringChars);
+  flags.Add(kTypedArrayElements);
+
+  for (int i = 0; i < graph()->blocks()->length(); i++) {
+    unobserved_.Rewind(0);
+    HBasicBlock* block = graph()->blocks()->at(i);
+    for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+      HInstruction* instr = it.Current();
+
+      // TODO(titzer): eliminate unobserved HStoreKeyed instructions too.
+      switch (instr->opcode()) {
+        case HValue::kStoreNamedField:
+          // Remove any unobserved stores overwritten by this store.
+          ProcessStore(HStoreNamedField::cast(instr));
+          break;
+        case HValue::kLoadNamedField:
+          // Observe any unobserved stores on this object + field.
+          ProcessLoad(HLoadNamedField::cast(instr));
+          break;
+        default:
+          ProcessInstr(instr, flags);
+          break;
+      }
+    }
+  }
+}
+
+
+void HStoreEliminationPhase::ProcessStore(HStoreNamedField* store) {
+  HValue* object = store->object()->ActualValue();
+  int i = 0;
+  while (i < unobserved_.length()) {
+    HStoreNamedField* prev = unobserved_.at(i);
+    if (aliasing_->MustAlias(object, prev->object()->ActualValue()) &&
+        store->access().Equals(prev->access())) {
+      // This store is guaranteed to overwrite the previous store.
+      prev->DeleteAndReplaceWith(NULL);
+      TRACE(("++ Unobserved store S%d overwritten by S%d\n",
+             prev->id(), store->id()));
+      unobserved_.Remove(i);
+    } else {
+      // TODO(titzer): remove map word clearing from folded allocations.
+      i++;
+    }
+  }
+  // Only non-transitioning stores are removable.
+  if (!store->has_transition()) {
+    TRACE(("-- Might remove store S%d\n", store->id()));
+    unobserved_.Add(store, zone());
+  }
+}
+
+
+void HStoreEliminationPhase::ProcessLoad(HLoadNamedField* load) {
+  HValue* object = load->object()->ActualValue();
+  int i = 0;
+  while (i < unobserved_.length()) {
+    HStoreNamedField* prev = unobserved_.at(i);
+    if (aliasing_->MayAlias(object, prev->object()->ActualValue()) &&
+        load->access().Equals(prev->access())) {
+      TRACE(("-- Observed store S%d by load L%d\n", prev->id(), load->id()));
+      unobserved_.Remove(i);
+    } else {
+      i++;
+    }
+  }
+}
+
+
+void HStoreEliminationPhase::ProcessInstr(HInstruction* instr,
+    GVNFlagSet flags) {
+  if (unobserved_.length() == 0) return;  // Nothing to do.
+  if (instr->CanDeoptimize()) {
+    TRACE(("-- Observed stores at I%d (might deoptimize)\n", instr->id()));
+    unobserved_.Rewind(0);
+    return;
+  }
+  if (instr->CheckChangesFlag(kNewSpacePromotion)) {
+    TRACE(("-- Observed stores at I%d (might GC)\n", instr->id()));
+    unobserved_.Rewind(0);
+    return;
+  }
+  if (instr->ChangesFlags().ContainsAnyOf(flags)) {
+    TRACE(("-- Observed stores at I%d (GVN flags)\n", instr->id()));
+    unobserved_.Rewind(0);
+    return;
+  }
+}
+
+} }  // namespace v8::internal
diff --git a/src/hydrogen-store-elimination.h b/src/hydrogen-store-elimination.h
new file mode 100644
index 0000000..7dc871c
--- /dev/null
+++ b/src/hydrogen-store-elimination.h
@@ -0,0 +1,57 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_HYDROGEN_STORE_ELIMINATION_H_
+#define V8_HYDROGEN_STORE_ELIMINATION_H_
+
+#include "hydrogen.h"
+#include "hydrogen-alias-analysis.h"
+
+namespace v8 {
+namespace internal {
+
+class HStoreEliminationPhase : public HPhase {
+ public:
+  explicit HStoreEliminationPhase(HGraph* graph)
+    : HPhase("H_Store elimination", graph),
+      unobserved_(10, zone()),
+      aliasing_() { }
+
+  void Run();
+ private:
+  ZoneList<HStoreNamedField*> unobserved_;
+  HAliasAnalyzer* aliasing_;
+
+  void ProcessStore(HStoreNamedField* store);
+  void ProcessLoad(HLoadNamedField* load);
+  void ProcessInstr(HInstruction* instr, GVNFlagSet flags);
+};
+
+
+} }  // namespace v8::internal
+
+#endif
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 45d4b56..c669cc2 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -54,6 +54,7 @@
 #include "hydrogen-removable-simulates.h"
 #include "hydrogen-representation-changes.h"
 #include "hydrogen-sce.h"
+#include "hydrogen-store-elimination.h"
 #include "hydrogen-uint32-analysis.h"
 #include "lithium-allocator.h"
 #include "parser.h"
@@ -4039,6 +4040,8 @@
 
   if (FLAG_check_elimination) Run<HCheckEliminationPhase>();
 
+  if (FLAG_store_elimination) Run<HStoreEliminationPhase>();
+
   Run<HRangeAnalysisPhase>();
 
   Run<HComputeChangeUndefinedToNaN>();
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index de3bf9e..696c6be 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -1005,30 +1005,22 @@
   LInstruction* goto_instr = CheckElideControlInstruction(instr);
   if (goto_instr != NULL) return goto_instr;
 
-  ToBooleanStub::Types expected = instr->expected_input_types();
-
-  // Tagged values that are not known smis or booleans require a
-  // deoptimization environment. If the instruction is generic no
-  // environment is needed since all cases are handled.
   HValue* value = instr->value();
-  Representation rep = value->representation();
+  Representation r = value->representation();
   HType type = value->type();
-  if (!rep.IsTagged() || type.IsSmi() || type.IsBoolean()) {
-    return new(zone()) LBranch(UseRegister(value), NULL);
+  ToBooleanStub::Types expected = instr->expected_input_types();
+  if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic();
+
+  bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() ||
+      type.IsJSArray() || type.IsHeapNumber() || type.IsString();
+  LOperand* temp = !easy_case && expected.NeedsMap() ? TempRegister() : NULL;
+  LInstruction* branch = new(zone()) LBranch(UseRegister(value), temp);
+  if (!easy_case &&
+      ((!expected.Contains(ToBooleanStub::SMI) && expected.NeedsMap()) ||
+       !expected.IsGeneric())) {
+    branch = AssignEnvironment(branch);
   }
-
-  bool needs_temp = expected.NeedsMap() || expected.IsEmpty();
-  LOperand* temp = needs_temp ? TempRegister() : NULL;
-
-  // The Generic stub does not have a deopt, so we need no environment.
-  if (expected.IsGeneric()) {
-    return new(zone()) LBranch(UseRegister(value), temp);
-  }
-
-  // We need a temporary register when we have to access the map *or* we have
-  // no type info yet, in which case we handle all cases (including the ones
-  // involving maps).
-  return AssignEnvironment(new(zone()) LBranch(UseRegister(value), temp));
+  return branch;
 }
 
 
@@ -1221,8 +1213,12 @@
 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
   LOperand* context = UseAny(instr->context());  // Deferred use.
   LOperand* input = UseRegisterAtStart(instr->value());
-  LMathAbs* result = new(zone()) LMathAbs(context, input);
-  return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
+  LInstruction* result =
+      DefineSameAsFirst(new(zone()) LMathAbs(context, input));
+  Representation r = instr->value()->representation();
+  if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result);
+  if (!r.IsDouble()) result = AssignEnvironment(result);
+  return result;
 }
 
 
@@ -1901,8 +1897,12 @@
       LOperand* value = UseRegister(instr->value());
       // Temp register only necessary for minus zero check.
       LOperand* temp = TempRegister();
-      LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp);
-      return AssignEnvironment(DefineAsRegister(res));
+      LInstruction* result = DefineAsRegister(
+          new(zone()) LNumberUntagD(value, temp));
+      if (!instr->value()->representation().IsSmi()) {
+        result = AssignEnvironment(result);
+      }
+      return result;
     } else if (to.IsSmi()) {
       HValue* val = instr->value();
       LOperand* value = UseRegister(val);
@@ -1921,8 +1921,13 @@
         LOperand* xmm_temp =
             (CpuFeatures::IsSafeForSnapshot(SSE2) && !truncating)
                 ? FixedTemp(xmm1) : NULL;
-        LTaggedToI* res = new(zone()) LTaggedToI(UseRegister(val), xmm_temp);
-        return AssignEnvironment(DefineSameAsFirst(res));
+        LInstruction* result = DefineSameAsFirst(
+            new(zone()) LTaggedToI(UseRegister(val), xmm_temp));
+        if (!instr->value()->representation().IsSmi()) {
+          // Note: Only deopts in deferred code.
+          result = AssignEnvironment(result);
+        }
+        return result;
       }
     }
   } else if (from.IsDouble()) {
@@ -1946,8 +1951,10 @@
       LOperand* value = needs_temp ?
           UseTempRegister(instr->value()) : UseRegister(instr->value());
       LOperand* temp = needs_temp ? TempRegister() : NULL;
-      return AssignEnvironment(
-          DefineAsRegister(new(zone()) LDoubleToI(value, temp)));
+      LInstruction* result =
+          DefineAsRegister(new(zone()) LDoubleToI(value, temp));
+      if (!truncating) result = AssignEnvironment(result);
+      return result;
     }
   } else if (from.IsInteger32()) {
     info()->MarkAsDeferredCalling();
@@ -1961,11 +1968,11 @@
         LOperand* temp2 = CpuFeatures::IsSupported(SSE2) ? FixedTemp(xmm1)
                                                          : NULL;
         LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2);
-        return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
+        return AssignPointerMap(DefineSameAsFirst(result));
       } else {
         LOperand* temp = TempRegister();
         LNumberTagI* result = new(zone()) LNumberTagI(value, temp);
-        return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
+        return AssignPointerMap(DefineSameAsFirst(result));
       }
     } else if (to.IsSmi()) {
       HValue* val = instr->value();
@@ -2031,6 +2038,7 @@
   }
   LCheckMaps* result = new(zone()) LCheckMaps(value);
   if (!instr->CanOmitMapChecks()) {
+    // Note: Only deopts in deferred code.
     AssignEnvironment(result);
     if (instr->has_migration_target()) return AssignPointerMap(result);
   }
@@ -2139,7 +2147,10 @@
   LOperand* context = UseRegisterAtStart(instr->value());
   LInstruction* result =
       DefineAsRegister(new(zone()) LLoadContextSlot(context));
-  return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
+  if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
+    result = AssignEnvironment(result);
+  }
+  return result;
 }
 
 
@@ -2155,7 +2166,10 @@
     temp = NULL;
   }
   LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp);
-  return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
+  if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
+    result = AssignEnvironment(result);
+  }
+  return result;
 }
 
 
@@ -2197,11 +2211,11 @@
   LOperand* key = clobbers_key
       ? UseTempRegister(instr->key())
       : UseRegisterOrConstantAtStart(instr->key());
-  LLoadKeyed* result = NULL;
+  LInstruction* result = NULL;
 
   if (!instr->is_typed_elements()) {
     LOperand* obj = UseRegisterAtStart(instr->elements());
-    result = new(zone()) LLoadKeyed(obj, key);
+    result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key));
   } else {
     ASSERT(
         (instr->representation().IsInteger32() &&
@@ -2209,15 +2223,20 @@
         (instr->representation().IsDouble() &&
          (IsDoubleOrFloatElementsKind(instr->elements_kind()))));
     LOperand* backing_store = UseRegister(instr->elements());
-    result = new(zone()) LLoadKeyed(backing_store, key);
+    result = DefineAsRegister(new(zone()) LLoadKeyed(backing_store, key));
   }
 
-  DefineAsRegister(result);
-  bool can_deoptimize = instr->RequiresHoleCheck() ||
-      (elements_kind == EXTERNAL_UINT32_ELEMENTS);
-  // An unsigned int array load might overflow and cause a deopt, make sure it
-  // has an environment.
-  return can_deoptimize ? AssignEnvironment(result) : result;
+  if ((instr->is_external() || instr->is_fixed_typed_array()) ?
+      // see LCodeGen::DoLoadKeyedExternalArray
+      ((instr->elements_kind() == EXTERNAL_UINT32_ELEMENTS ||
+        instr->elements_kind() == UINT32_ELEMENTS) &&
+       !instr->CheckFlag(HInstruction::kUint32)) :
+      // see LCodeGen::DoLoadKeyedFixedDoubleArray and
+      // LCodeGen::DoLoadKeyedFixedArray
+      instr->RequiresHoleCheck()) {
+    result = AssignEnvironment(result);
+  }
+  return result;
 }
 
 
@@ -2408,12 +2427,14 @@
   // We need a temporary register for write barrier of the map field.
   LOperand* temp_map = needs_write_barrier_for_map ? TempRegister() : NULL;
 
-  LStoreNamedField* result =
+  LInstruction* result =
       new(zone()) LStoreNamedField(obj, val, temp, temp_map);
-  if (instr->field_representation().IsHeapObject()) {
-    if (!instr->value()->type().IsHeapObject()) {
-      return AssignEnvironment(result);
-    }
+  if (!instr->access().IsExternalMemory() &&
+      instr->field_representation().IsHeapObject() &&
+      (val->IsConstantOperand()
+       ? HConstant::cast(instr->value())->HasSmiValue()
+       : !instr->value()->type().IsHeapObject())) {
+    result = AssignEnvironment(result);
   }
   return result;
 }
@@ -2445,7 +2466,7 @@
   LOperand* context = UseAny(instr->context());
   LStringCharCodeAt* result =
       new(zone()) LStringCharCodeAt(context, string, index);
-  return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
+  return AssignPointerMap(DefineAsRegister(result));
 }
 
 
diff --git a/src/icu_util.cc b/src/icu_util.cc
index b9bd65e..6441dbd 100644
--- a/src/icu_util.cc
+++ b/src/icu_util.cc
@@ -27,12 +27,20 @@
 
 #include "icu_util.h"
 
-#if defined(_WIN32) && defined(V8_I18N_SUPPORT)
+#if defined(_WIN32)
 #include <windows.h>
+#endif
+
+#if defined(V8_I18N_SUPPORT)
+#include <stdio.h>
 
 #include "unicode/putil.h"
 #include "unicode/udata.h"
 
+#define ICU_UTIL_DATA_FILE   0
+#define ICU_UTIL_DATA_SHARED 1
+#define ICU_UTIL_DATA_STATIC 2
+
 #define ICU_UTIL_DATA_SYMBOL "icudt" U_ICU_VERSION_SHORT "_dat"
 #define ICU_UTIL_DATA_SHARED_MODULE_NAME "icudt.dll"
 #endif
@@ -41,8 +49,11 @@
 
 namespace internal {
 
-bool InitializeICU() {
-#if defined(_WIN32) && defined(V8_I18N_SUPPORT)
+bool InitializeICU(const char* icu_data_file) {
+#if !defined(V8_I18N_SUPPORT)
+  return true;
+#else
+#if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_SHARED
   // We expect to find the ICU data module alongside the current module.
   HMODULE module = LoadLibraryA(ICU_UTIL_DATA_SHARED_MODULE_NAME);
   if (!module) return false;
@@ -53,9 +64,30 @@
   UErrorCode err = U_ZERO_ERROR;
   udata_setCommonData(reinterpret_cast<void*>(addr), &err);
   return err == U_ZERO_ERROR;
-#else
+#elif ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_STATIC
   // Mac/Linux bundle the ICU data in.
   return true;
+#elif ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE
+  if (!icu_data_file) return false;
+
+  FILE* inf = fopen(icu_data_file, "rb");
+  if (!inf) return false;
+
+  fseek(inf, 0, SEEK_END);
+  size_t size = ftell(inf);
+  rewind(inf);
+
+  char* addr = new char[size];
+  if (fread(addr, 1, size, inf) != size) {
+    delete[] addr;
+    fclose(inf);
+    return false;
+  }
+  fclose(inf);
+  UErrorCode err = U_ZERO_ERROR;
+  udata_setCommonData(reinterpret_cast<void*>(addr), &err);
+  return err == U_ZERO_ERROR;
+#endif
 #endif
 }
 
diff --git a/src/icu_util.h b/src/icu_util.h
index 478abce..6b50c18 100644
--- a/src/icu_util.h
+++ b/src/icu_util.h
@@ -35,7 +35,7 @@
 
 // Call this function to load ICU's data tables for the current process.  This
 // function should be called before ICU is used.
-bool InitializeICU();
+bool InitializeICU(const char* icu_data_file);
 
 } }  // namespace v8::internal
 
diff --git a/src/json-parser.h b/src/json-parser.h
index 0973589..4c2b479 100644
--- a/src/json-parser.h
+++ b/src/json-parser.h
@@ -606,6 +606,7 @@
   int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
   Handle<StringType> seq_string =
       NewRawString<StringType>(factory(), length, pretenure_);
+  ASSERT(!seq_string.is_null());
   // Copy prefix into seq_str.
   SinkChar* dest = seq_string->GetChars();
   String::WriteToFlat(*prefix, dest, start, end);
@@ -793,6 +794,7 @@
   } while (c0_ != '"');
   int length = position_ - beg_pos;
   Handle<String> result = factory()->NewRawOneByteString(length, pretenure_);
+  ASSERT(!result.is_null());
   uint8_t* dest = SeqOneByteString::cast(*result)->GetChars();
   String::WriteToFlat(*source_, dest, beg_pos, position_);
 
diff --git a/src/json-stringifier.h b/src/json-stringifier.h
index a75b3de..3926969 100644
--- a/src/json-stringifier.h
+++ b/src/json-stringifier.h
@@ -266,6 +266,7 @@
                            factory_->ToObject(factory_->empty_string()));
   part_length_ = kInitialPartLength;
   current_part_ = factory_->NewRawOneByteString(part_length_);
+  ASSERT(!current_part_.is_null());
   tojson_string_ = factory_->toJSON_string();
   stack_ = factory_->NewJSArray(8);
 }
@@ -309,6 +310,7 @@
   if (object->IsOneByteRepresentationUnderneath()) {
     Handle<String> result =
         isolate->factory()->NewRawOneByteString(worst_case_length);
+    ASSERT(!result.is_null());
     DisallowHeapAllocation no_gc;
     return StringifyString_<SeqOneByteString>(
         isolate,
@@ -317,6 +319,7 @@
   } else {
     Handle<String> result =
         isolate->factory()->NewRawTwoByteString(worst_case_length);
+    ASSERT(!result.is_null());
     DisallowHeapAllocation no_gc;
     return StringifyString_<SeqTwoByteString>(
         isolate,
@@ -390,13 +393,16 @@
   if (check.HasOverflowed()) return STACK_OVERFLOW;
 
   int length = Smi::cast(stack_->length())->value();
-  FixedArray* elements = FixedArray::cast(stack_->elements());
-  for (int i = 0; i < length; i++) {
-    if (elements->get(i) == *object) {
-      return CIRCULAR;
+  {
+    DisallowHeapAllocation no_allocation;
+    FixedArray* elements = FixedArray::cast(stack_->elements());
+    for (int i = 0; i < length; i++) {
+      if (elements->get(i) == *object) {
+        return CIRCULAR;
+      }
     }
   }
-  stack_->EnsureSize(length + 1);
+  JSArray::EnsureSize(stack_, length + 1);
   FixedArray::cast(stack_->elements())->set(length, *object);
   stack_->set_length(Smi::FromInt(length + 1));
   return SUCCESS;
@@ -722,7 +728,6 @@
 void BasicJsonStringifier::Accumulate() {
   if (accumulator()->length() + current_part_->length() > String::kMaxLength) {
     // Screw it.  Simply set the flag and carry on.  Throw exception at the end.
-    // We most likely will trigger a real OOM before even reaching this point.
     set_accumulator(factory_->empty_string());
     overflowed_ = true;
   } else {
@@ -741,6 +746,7 @@
   } else {
     current_part_ = factory_->NewRawTwoByteString(part_length_);
   }
+  ASSERT(!current_part_.is_null());
   current_index_ = 0;
 }
 
@@ -749,6 +755,7 @@
   ShrinkCurrentPart();
   Accumulate();
   current_part_ = factory_->NewRawTwoByteString(part_length_);
+  ASSERT(!current_part_.is_null());
   current_index_ = 0;
   is_ascii_ = false;
 }
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index 012c251..a30fc26 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -466,6 +466,7 @@
     // Unable to compile regexp.
     Handle<String> error_message =
         isolate->factory()->NewStringFromUtf8(CStrVector(result.error_message));
+    ASSERT(!error_message.is_null());
     CreateRegExpErrorObjectAndThrow(re, is_ascii, error_message, isolate);
     return false;
   }
@@ -690,7 +691,8 @@
                                              int32_t* match) {
   ASSERT(last_match_info->HasFastObjectElements());
   int capture_register_count = (capture_count + 1) * 2;
-  last_match_info->EnsureSize(capture_register_count + kLastMatchOverhead);
+  JSArray::EnsureSize(last_match_info,
+                      capture_register_count + kLastMatchOverhead);
   DisallowHeapAllocation no_allocation;
   FixedArray* array = FixedArray::cast(last_match_info->elements());
   if (match != NULL) {
diff --git a/src/liveedit.cc b/src/liveedit.cc
index a812b75..5eae107 100644
--- a/src/liveedit.cc
+++ b/src/liveedit.cc
@@ -2013,8 +2013,8 @@
       DropActivationsInActiveThread(shared_info_array, result, do_drop);
   if (error_message != NULL) {
     // Add error message as an array extra element.
-    Vector<const char> vector_message(error_message, StrLength(error_message));
-    Handle<String> str = isolate->factory()->NewStringFromAscii(vector_message);
+    Handle<String> str = isolate->factory()->NewStringFromAscii(
+        CStrVector(error_message));
     SetElementSloppy(result, len, str);
   }
   return result;
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index b26ca6a..4eb178b 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -4086,6 +4086,7 @@
     if (p->TryParallelSweeping()) {
       SweepConservatively<SWEEP_IN_PARALLEL>(space, &private_free_list, p);
       free_list->Concatenate(&private_free_list);
+      p->set_parallel_sweeping(MemoryChunk::PARALLEL_SWEEPING_FINALIZE);
     }
   }
 }
@@ -4284,10 +4285,11 @@
   PageIterator it(space);
   while (it.has_next()) {
     Page* p = it.next();
-    if (p->parallel_sweeping() == MemoryChunk::PARALLEL_SWEEPING_IN_PROGRESS) {
+    if (p->parallel_sweeping() == MemoryChunk::PARALLEL_SWEEPING_FINALIZE) {
       p->set_parallel_sweeping(MemoryChunk::PARALLEL_SWEEPING_DONE);
       p->MarkSweptConservatively();
     }
+    ASSERT(p->parallel_sweeping() == MemoryChunk::PARALLEL_SWEEPING_DONE);
   }
 }
 
diff --git a/src/objects-inl.h b/src/objects-inl.h
index b3f23e6..c358ee6 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1064,25 +1064,15 @@
   // This was not always the case. This ASSERT is here to catch
   // leftover incorrect uses.
   ASSERT(AllowHeapAllocation::IsAllowed());
-  CALL_HEAP_FUNCTION(isolate,
-                     object->GetElementWithReceiver(isolate, *object, index),
-                     Object);
+  return Object::GetElementWithReceiver(isolate, object, object, index);
 }
 
 
-static Handle<Object> GetElementNoExceptionThrownHelper(Isolate* isolate,
-                                                        Handle<Object> object,
-                                                        uint32_t index) {
-  CALL_HEAP_FUNCTION(isolate,
-                     object->GetElementWithReceiver(isolate, *object, index),
-                     Object);
-}
-
 Handle<Object> Object::GetElementNoExceptionThrown(Isolate* isolate,
                                                    Handle<Object> object,
                                                    uint32_t index) {
   Handle<Object> result =
-      GetElementNoExceptionThrownHelper(isolate, object, index);
+      Object::GetElementWithReceiver(isolate, object, object, index);
   CHECK_NOT_EMPTY_HANDLE(isolate, result);
   return result;
 }
@@ -6527,20 +6517,20 @@
 }
 
 
-void JSArray::EnsureSize(int required_size) {
-  ASSERT(HasFastSmiOrObjectElements());
-  FixedArray* elts = FixedArray::cast(elements());
+void JSArray::EnsureSize(Handle<JSArray> array, int required_size) {
+  ASSERT(array->HasFastSmiOrObjectElements());
+  Handle<FixedArray> elts = handle(FixedArray::cast(array->elements()));
   const int kArraySizeThatFitsComfortablyInNewSpace = 128;
   if (elts->length() < required_size) {
     // Doubling in size would be overkill, but leave some slack to avoid
     // constantly growing.
-    Expand(required_size + (required_size >> 3));
+    Expand(array, required_size + (required_size >> 3));
     // It's a performance benefit to keep a frequently used array in new-space.
-  } else if (!GetHeap()->new_space()->Contains(elts) &&
+  } else if (!array->GetHeap()->new_space()->Contains(*elts) &&
              required_size < kArraySizeThatFitsComfortablyInNewSpace) {
     // Expand will allocate a new backing store in new space even if the size
     // we asked for isn't larger than what we had before.
-    Expand(required_size);
+    Expand(array, required_size);
   }
 }
 
diff --git a/src/objects.cc b/src/objects.cc
index c764b33..11f53b9 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -962,63 +962,70 @@
 }
 
 
-MaybeObject* Object::GetElementWithReceiver(Isolate* isolate,
-                                            Object* receiver,
-                                            uint32_t index) {
-  Heap* heap = isolate->heap();
-  Object* holder = this;
+Handle<Object> Object::GetElementWithReceiver(Isolate* isolate,
+                                              Handle<Object> object,
+                                              Handle<Object> receiver,
+                                              uint32_t index) {
+  Handle<Object> holder;
 
   // Iterate up the prototype chain until an element is found or the null
   // prototype is encountered.
-  for (holder = this;
-       holder != heap->null_value();
-       holder = holder->GetPrototype(isolate)) {
+  for (holder = object;
+       !holder->IsNull();
+       holder = Handle<Object>(holder->GetPrototype(isolate), isolate)) {
     if (!holder->IsJSObject()) {
       Context* native_context = isolate->context()->native_context();
       if (holder->IsNumber()) {
-        holder = native_context->number_function()->instance_prototype();
+        holder = Handle<Object>(
+            native_context->number_function()->instance_prototype(), isolate);
       } else if (holder->IsString()) {
-        holder = native_context->string_function()->instance_prototype();
+        holder = Handle<Object>(
+            native_context->string_function()->instance_prototype(), isolate);
       } else if (holder->IsSymbol()) {
-        holder = native_context->symbol_function()->instance_prototype();
+        holder = Handle<Object>(
+            native_context->symbol_function()->instance_prototype(), isolate);
       } else if (holder->IsBoolean()) {
-        holder = native_context->boolean_function()->instance_prototype();
+        holder = Handle<Object>(
+            native_context->boolean_function()->instance_prototype(), isolate);
       } else if (holder->IsJSProxy()) {
-        return JSProxy::cast(holder)->GetElementWithHandler(receiver, index);
+        CALL_HEAP_FUNCTION(isolate,
+            Handle<JSProxy>::cast(holder)->GetElementWithHandler(
+                *receiver, index),
+            Object);
       } else {
         // Undefined and null have no indexed properties.
         ASSERT(holder->IsUndefined() || holder->IsNull());
-        return heap->undefined_value();
+        return isolate->factory()->undefined_value();
       }
     }
 
     // Inline the case for JSObjects. Doing so significantly improves the
     // performance of fetching elements where checking the prototype chain is
     // necessary.
-    JSObject* js_object = JSObject::cast(holder);
+    Handle<JSObject> js_object = Handle<JSObject>::cast(holder);
 
     // Check access rights if needed.
     if (js_object->IsAccessCheckNeeded()) {
-      Isolate* isolate = heap->isolate();
-      if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) {
-        isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET);
-        RETURN_IF_SCHEDULED_EXCEPTION(isolate);
-        return heap->undefined_value();
+      if (!isolate->MayIndexedAccessWrapper(js_object, index, v8::ACCESS_GET)) {
+        isolate->ReportFailedAccessCheckWrapper(js_object, v8::ACCESS_GET);
+        RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
+        return isolate->factory()->undefined_value();
       }
     }
 
     if (js_object->HasIndexedInterceptor()) {
-      return js_object->GetElementWithInterceptor(receiver, index);
+      return JSObject::GetElementWithInterceptor(js_object, receiver, index);
     }
 
-    if (js_object->elements() != heap->empty_fixed_array()) {
-      MaybeObject* result = js_object->GetElementsAccessor()->Get(
+    if (js_object->elements() != isolate->heap()->empty_fixed_array()) {
+      Handle<Object> result = js_object->GetElementsAccessor()->Get(
           receiver, js_object, index);
-      if (result != heap->the_hole_value()) return result;
+      RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>());
+      if (!result->IsTheHole()) return result;
     }
   }
 
-  return heap->undefined_value();
+  return isolate->factory()->undefined_value();
 }
 
 
@@ -11279,9 +11286,9 @@
 }
 
 
-void JSArray::Expand(int required_size) {
-  GetIsolate()->factory()->SetElementsCapacityAndLength(
-      Handle<JSArray>(this), required_size, required_size);
+void JSArray::Expand(Handle<JSArray> array, int required_size) {
+  ElementsAccessor* accessor = array->GetElementsAccessor();
+  accessor->SetCapacityAndLength(array, required_size, required_size);
 }
 
 
@@ -12922,46 +12929,41 @@
 }
 
 
-MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver,
-                                                 uint32_t index) {
-  Isolate* isolate = GetIsolate();
-  HandleScope scope(isolate);
+Handle<Object> JSObject::GetElementWithInterceptor(Handle<JSObject> object,
+                                                   Handle<Object> receiver,
+                                                   uint32_t index) {
+  Isolate* isolate = object->GetIsolate();
 
   // Make sure that the top context does not change when doing
   // callbacks or interceptor calls.
   AssertNoContextChange ncc(isolate);
 
-  Handle<InterceptorInfo> interceptor(GetIndexedInterceptor(), isolate);
-  Handle<Object> this_handle(receiver, isolate);
-  Handle<JSObject> holder_handle(this, isolate);
+  Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor(), isolate);
   if (!interceptor->getter()->IsUndefined()) {
     v8::IndexedPropertyGetterCallback getter =
         v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
     LOG(isolate,
-        ApiIndexedPropertyAccess("interceptor-indexed-get", this, index));
+        ApiIndexedPropertyAccess("interceptor-indexed-get", *object, index));
     PropertyCallbackArguments
-        args(isolate, interceptor->data(), receiver, this);
+        args(isolate, interceptor->data(), *receiver, *object);
     v8::Handle<v8::Value> result = args.Call(getter, index);
-    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+    RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
     if (!result.IsEmpty()) {
       Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
       result_internal->VerifyApiCallResultType();
-      return *result_internal;
+      // Rebox handle before return.
+      return Handle<Object>(*result_internal, isolate);
     }
   }
 
-  Heap* heap = holder_handle->GetHeap();
-  ElementsAccessor* handler = holder_handle->GetElementsAccessor();
-  MaybeObject* raw_result = handler->Get(*this_handle,
-                                         *holder_handle,
-                                         index);
-  if (raw_result != heap->the_hole_value()) return raw_result;
+  ElementsAccessor* handler = object->GetElementsAccessor();
+  Handle<Object> result = handler->Get(receiver,  object, index);
+  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>());
+  if (!result->IsTheHole()) return result;
 
-  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
-
-  Object* pt = holder_handle->GetPrototype();
-  if (pt == heap->null_value()) return heap->undefined_value();
-  return pt->GetElementWithReceiver(isolate, *this_handle, index);
+  Handle<Object> proto(object->GetPrototype(), isolate);
+  if (proto->IsNull()) return isolate->factory()->undefined_value();
+  return Object::GetElementWithReceiver(isolate, proto, receiver, index);
 }
 
 
diff --git a/src/objects.h b/src/objects.h
index c4d3f25..762892c 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1589,9 +1589,11 @@
       Isolate* isolate,
       Handle<Object> object,
       uint32_t index);
-  MUST_USE_RESULT MaybeObject* GetElementWithReceiver(Isolate* isolate,
-                                                      Object* receiver,
-                                                      uint32_t index);
+
+  static Handle<Object> GetElementWithReceiver(Isolate* isolate,
+                                               Handle<Object> object,
+                                               Handle<Object> receiver,
+                                               uint32_t index);
 
   // Return the object's prototype (might be Heap::null_value()).
   Object* GetPrototype(Isolate* isolate);
@@ -2480,8 +2482,9 @@
 
   // Returns the index'th element.
   // The undefined object if index is out of bounds.
-  MUST_USE_RESULT MaybeObject* GetElementWithInterceptor(Object* receiver,
-                                                         uint32_t index);
+  static Handle<Object> GetElementWithInterceptor(Handle<JSObject> object,
+                                                  Handle<Object> receiver,
+                                                  uint32_t index);
 
   enum SetFastElementsCapacitySmiMode {
     kAllowSmiElements,
@@ -10028,9 +10031,15 @@
   // Casting.
   static inline JSArray* cast(Object* obj);
 
-  // Uses handles.  Ensures that the fixed array backing the JSArray has at
+  // Ensures that the fixed array backing the JSArray has at
   // least the stated size.
-  inline void EnsureSize(int minimum_size_of_backing_fixed_array);
+  static inline void EnsureSize(Handle<JSArray> array,
+                                int minimum_size_of_backing_fixed_array);
+
+  // Expand the fixed array backing of a fast-case JSArray to at least
+  // the requested size.
+  static void Expand(Handle<JSArray> array,
+                     int minimum_size_of_backing_fixed_array);
 
   // Dispatched behavior.
   DECLARE_PRINTER(JSArray)
@@ -10044,10 +10053,6 @@
   static const int kSize = kLengthOffset + kPointerSize;
 
  private:
-  // Expand the fixed array backing of a fast-case JSArray to at least
-  // the requested size.
-  void Expand(int minimum_size_of_backing_fixed_array);
-
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSArray);
 };
 
diff --git a/src/parser.cc b/src/parser.cc
index 56eec54..c7ea634 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -215,6 +215,7 @@
   Handle<String> result = symbol_cache_.at(symbol_id);
   if (result.is_null()) {
     result = scanner()->AllocateInternalizedString(isolate_);
+    ASSERT(!result.is_null());
     symbol_cache_.at(symbol_id) = result;
     return result;
   }
@@ -615,6 +616,7 @@
   Handle<FixedArray> elements = factory->NewFixedArray(args.length());
   for (int i = 0; i < args.length(); i++) {
     Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i]));
+    ASSERT(!arg_string.is_null());
     elements->set(i, *arg_string);
   }
   Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
@@ -672,7 +674,10 @@
       parser_->scanner()->LogSymbol(parser_->log_, parser_->position());
     }
   }
-  return parser_->scanner()->AllocateInternalizedString(parser_->isolate_);
+  Handle<String> result =
+      parser_->scanner()->AllocateInternalizedString(parser_->isolate_);
+  ASSERT(!result.is_null());
+  return result;
 }
 
 
@@ -1709,8 +1714,8 @@
         return;
       }
       Handle<String> message_string =
-          isolate()->factory()->NewStringFromUtf8(CStrVector("Variable"),
-                                                  TENURED);
+          isolate()->factory()->InternalizeOneByteString(
+              STATIC_ASCII_VECTOR("Variable"));
       Expression* expression =
           NewThrowTypeError(isolate()->factory()->redeclaration_string(),
                             message_string, name);
@@ -3816,6 +3821,7 @@
 RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
   failed_ = true;
   *error_ = isolate()->factory()->NewStringFromAscii(message, NOT_TENURED);
+  ASSERT(!error_->is_null());
   // Zip to the end to make sure the no more input is read.
   current_ = kEndMarker;
   next_pos_ = in()->length();
diff --git a/src/runtime.cc b/src/runtime.cc
index 8d98f27..a5f6f26 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -3363,8 +3363,7 @@
         array_builder_(heap->isolate(), estimated_part_count),
         subject_(subject),
         character_count_(0),
-        is_ascii_(subject->IsOneByteRepresentation()),
-        overflowed_(false) {
+        is_ascii_(subject->IsOneByteRepresentation()) {
     // Require a non-zero initial size. Ensures that doubling the size to
     // extend the array will work.
     ASSERT(estimated_part_count > 0);
@@ -3412,11 +3411,6 @@
 
 
   Handle<String> ToString() {
-    if (overflowed_) {
-      heap_->isolate()->ThrowInvalidStringLength();
-      return Handle<String>();
-    }
-
     if (array_builder_.length() == 0) {
       return heap_->isolate()->factory()->empty_string();
     }
@@ -3424,6 +3418,7 @@
     Handle<String> joined_string;
     if (is_ascii_) {
       Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_);
+      RETURN_IF_EMPTY_HANDLE_VALUE(heap_->isolate(), seq, Handle<String>());
       DisallowHeapAllocation no_gc;
       uint8_t* char_buffer = seq->GetChars();
       StringBuilderConcatHelper(*subject_,
@@ -3434,6 +3429,7 @@
     } else {
       // Non-ASCII.
       Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_);
+      RETURN_IF_EMPTY_HANDLE_VALUE(heap_->isolate(), seq, Handle<String>());
       DisallowHeapAllocation no_gc;
       uc16* char_buffer = seq->GetChars();
       StringBuilderConcatHelper(*subject_,
@@ -3448,9 +3444,11 @@
 
   void IncrementCharacterCount(int by) {
     if (character_count_ > String::kMaxLength - by) {
-      overflowed_ = true;
+      STATIC_ASSERT(String::kMaxLength < kMaxInt);
+      character_count_ = kMaxInt;
+    } else {
+      character_count_ += by;
     }
-    character_count_ += by;
   }
 
  private:
@@ -3475,7 +3473,6 @@
   Handle<String> subject_;
   int character_count_;
   bool is_ascii_;
-  bool overflowed_;
 };
 
 
@@ -3932,22 +3929,25 @@
        static_cast<int64_t>(pattern_len)) *
       static_cast<int64_t>(matches) +
       static_cast<int64_t>(subject_len);
-  if (result_len_64 > INT_MAX) {
-    v8::internal::Heap::FatalProcessOutOfMemory("invalid string length", true);
+  int result_len;
+  if (result_len_64 > static_cast<int64_t>(String::kMaxLength)) {
+    STATIC_ASSERT(String::kMaxLength < kMaxInt);
+    result_len = kMaxInt;  // Provoke exception.
+  } else {
+    result_len = static_cast<int>(result_len_64);
   }
-  int result_len = static_cast<int>(result_len_64);
 
   int subject_pos = 0;
   int result_pos = 0;
 
-  Handle<ResultSeqString> result;
+  Handle<String> result_seq;
   if (ResultSeqString::kHasAsciiEncoding) {
-    result = Handle<ResultSeqString>::cast(
-        isolate->factory()->NewRawOneByteString(result_len));
+    result_seq = isolate->factory()->NewRawOneByteString(result_len);
   } else {
-    result = Handle<ResultSeqString>::cast(
-        isolate->factory()->NewRawTwoByteString(result_len));
+    result_seq = isolate->factory()->NewRawTwoByteString(result_len);
   }
+  RETURN_IF_EMPTY_HANDLE(isolate, result_seq);
+  Handle<ResultSeqString> result = Handle<ResultSeqString>::cast(result_seq);
 
   for (int i = 0; i < matches; i++) {
     // Copy non-matched subject content.
@@ -4127,6 +4127,7 @@
     answer = Handle<ResultSeqString>::cast(
         isolate->factory()->NewRawTwoByteString(new_length));
   }
+  ASSERT(!answer.is_null());
 
   int prev = 0;
   int position = 0;
@@ -6584,7 +6585,7 @@
   if (s->IsOneByteRepresentationUnderneath()) {
     Handle<SeqOneByteString> result =
         isolate->factory()->NewRawOneByteString(length);
-
+    ASSERT(!result.is_null());  // Same length as input.
     DisallowHeapAllocation no_gc;
     String::FlatContent flat_content = s->GetFlatContent();
     ASSERT(flat_content.IsFlat());
@@ -6604,6 +6605,8 @@
   } else {
     result = isolate->factory()->NewRawTwoByteString(length);
   }
+  ASSERT(!result.is_null());  // Same length as input.
+
   MaybeObject* maybe = ConvertCaseHelper(isolate, *s, *result, length, mapping);
   Object* answer;
   if (!maybe->ToObject(&answer)) return maybe;
@@ -6617,6 +6620,7 @@
     if (length < 0) length = -length;
     result = isolate->factory()->NewRawTwoByteString(length);
   }
+  RETURN_IF_EMPTY_HANDLE(isolate, result);
   return ConvertCaseHelper(isolate, *s, *result, length, mapping);
 }
 
@@ -7261,13 +7265,16 @@
     String* element = String::cast(element_obj);
     int increment = element->length();
     if (increment > String::kMaxLength - length) {
-      return isolate->ThrowInvalidStringLength();
+      STATIC_ASSERT(String::kMaxLength < kMaxInt);
+      length = kMaxInt;  // Provoke exception;
+      break;
     }
     length += increment;
   }
 
   Handle<SeqTwoByteString> answer =
       isolate->factory()->NewRawTwoByteString(length);
+  RETURN_IF_EMPTY_HANDLE(isolate, answer);
 
   DisallowHeapAllocation no_gc;
 
@@ -8694,6 +8701,7 @@
 
 RUNTIME_FUNCTION(MaybeObject*, Runtime_UnblockConcurrentRecompilation) {
   RUNTIME_ASSERT(FLAG_block_concurrent_recompilation);
+  RUNTIME_ASSERT(isolate->concurrent_recompilation_enabled());
   isolate->optimizing_compiler_thread()->Unblock();
   return isolate->heap()->undefined_value();
 }
@@ -9512,8 +9520,9 @@
   CONVERT_SMI_ARG_CHECKED(message_id, 0);
   const char* message = GetBailoutReason(
       static_cast<BailoutReason>(message_id));
-  Handle<Name> message_handle =
+  Handle<String> message_handle =
       isolate->factory()->NewStringFromAscii(CStrVector(message));
+  RETURN_IF_EMPTY_HANDLE(isolate, message_handle);
   return isolate->Throw(*message_handle);
 }
 
@@ -11024,8 +11033,9 @@
   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
   RUNTIME_ASSERT(obj->HasIndexedInterceptor());
   CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
-
-  return obj->GetElementWithInterceptor(*obj, index);
+  Handle<Object> result = JSObject::GetElementWithInterceptor(obj, obj, index);
+  RETURN_IF_EMPTY_HANDLE(isolate, result);
+  return *result;
 }
 
 
@@ -11267,8 +11277,10 @@
       VariableMode mode;
       InitializationFlag init_flag;
       locals->set(i * 2, *name);
-      locals->set(i * 2 + 1, context->get(
-          scope_info->ContextSlotIndex(*name, &mode, &init_flag)));
+      int context_slot_index =
+          scope_info->ContextSlotIndex(*name, &mode, &init_flag);
+      Object* value = context->get(context_slot_index);
+      locals->set(i * 2 + 1, value);
     }
   }
 
diff --git a/src/spaces.h b/src/spaces.h
index 770b88a..05254d0 100644
--- a/src/spaces.h
+++ b/src/spaces.h
@@ -468,13 +468,16 @@
   intptr_t GetFlags() { return flags_; }
 
 
-  // PARALLEL_SWEEPING_PENDING - This page is ready for parallel sweeping.
-  // PARALLEL_SWEEPING_IN_PROGRESS - This page is currently swept or was
-  // swept by a sweeper thread.
   // PARALLEL_SWEEPING_DONE - The page state when sweeping is complete or
   // sweeping must not be performed on that page.
+  // PARALLEL_SWEEPING_FINALIZE - A sweeper thread is done sweeping this
+  // page and will not touch the page memory anymore.
+  // PARALLEL_SWEEPING_IN_PROGRESS - This page is currently swept by a
+  // sweeper thread.
+  // PARALLEL_SWEEPING_PENDING - This page is ready for parallel sweeping.
   enum ParallelSweepingState {
     PARALLEL_SWEEPING_DONE,
+    PARALLEL_SWEEPING_FINALIZE,
     PARALLEL_SWEEPING_IN_PROGRESS,
     PARALLEL_SWEEPING_PENDING
   };
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 092eaa3..ff641dd 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -664,10 +664,14 @@
 
 
 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
-  JSObject* receiver = JSObject::cast(args[0]);
+  HandleScope scope(isolate);
+  Handle<JSObject> receiver = args.at<JSObject>(0);
   ASSERT(args.smi_at(1) >= 0);
   uint32_t index = args.smi_at(1);
-  return receiver->GetElementWithInterceptor(receiver, index);
+  Handle<Object> result =
+      JSObject::GetElementWithInterceptor(receiver, receiver, index);
+  RETURN_IF_EMPTY_HANDLE(isolate, result);
+  return *result;
 }
 
 
diff --git a/src/uri.h b/src/uri.h
index 81ec0c5..1e73ddd 100644
--- a/src/uri.h
+++ b/src/uri.h
@@ -127,9 +127,11 @@
 
   int dest_position = 0;
   Handle<String> second_part;
+  ASSERT(unescaped_length <= String::kMaxLength);
   if (one_byte) {
     Handle<SeqOneByteString> dest =
         isolate->factory()->NewRawOneByteString(unescaped_length);
+    ASSERT(!dest.is_null());
     DisallowHeapAllocation no_allocation;
     Vector<const Char> vector = GetCharVector<Char>(string);
     for (int i = start_index; i < length; dest_position++) {
@@ -142,6 +144,7 @@
   } else {
     Handle<SeqTwoByteString> dest =
         isolate->factory()->NewRawTwoByteString(unescaped_length);
+    ASSERT(!dest.is_null());
     DisallowHeapAllocation no_allocation;
     Vector<const Char> vector = GetCharVector<Char>(string);
     for (int i = start_index; i < length; dest_position++) {
@@ -263,11 +266,7 @@
 
       // We don't allow strings that are longer than a maximal length.
       ASSERT(String::kMaxLength < 0x7fffffff - 6);  // Cannot overflow.
-      if (escaped_length > String::kMaxLength) {
-        AllowHeapAllocation allocate_error_and_return;
-        isolate->ThrowInvalidStringLength();
-        return Handle<String>::null();
-      }
+      if (escaped_length > String::kMaxLength) break;  // Provoke exception.
     }
   }
 
@@ -276,6 +275,7 @@
 
   Handle<SeqOneByteString> dest =
       isolate->factory()->NewRawOneByteString(escaped_length);
+  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, dest, Handle<String>());
   int dest_position = 0;
 
   { DisallowHeapAllocation no_allocation;
diff --git a/src/version.cc b/src/version.cc
index 0374476..e606e70 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     25
-#define BUILD_NUMBER      24
-#define PATCH_LEVEL       1
+#define BUILD_NUMBER      25
+#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/test/cctest/cctest.status b/test/cctest/cctest.status
index 182a35b..2f09743 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -74,6 +74,7 @@
   'test-api/Threading2': [PASS, ['mode == debug', SLOW]],
   'test-api/Threading3': [PASS, ['mode == debug', SLOW]],
   'test-api/Threading4': [PASS, ['mode == debug', SLOW]],
+  'test-strings/StringOOM*': [PASS, ['mode == debug', SKIP]],
 }],  # ALWAYS
 
 ##############################################################################
diff --git a/test/cctest/test-strings.cc b/test/cctest/test-strings.cc
index 0f37c3e..6ff5200 100644
--- a/test/cctest/test-strings.cc
+++ b/test/cctest/test-strings.cc
@@ -1352,3 +1352,62 @@
     CHECK_EQ(Min(upper, lower), test);
   }
 }
+
+
+class DummyResource: public v8::String::ExternalStringResource {
+ public:
+  virtual const uint16_t* data() const { return NULL; }
+  virtual size_t length() const { return 1 << 30; }
+};
+
+
+class DummyOneByteResource: public v8::String::ExternalOneByteStringResource {
+ public:
+  virtual const char* data() const { return NULL; }
+  virtual size_t length() const { return 1 << 30; }
+};
+
+
+TEST(InvalidExternalString) {
+  CcTest::InitializeVM();
+  LocalContext context;
+  Isolate* isolate = CcTest::i_isolate();
+  { HandleScope scope(isolate);
+    DummyOneByteResource r;
+    CHECK(isolate->factory()->NewExternalStringFromAscii(&r).is_null());
+    CHECK(isolate->has_pending_exception());
+    isolate->clear_pending_exception();
+  }
+
+  { HandleScope scope(isolate);
+    DummyResource r;
+    CHECK(isolate->factory()->NewExternalStringFromTwoByte(&r).is_null());
+    CHECK(isolate->has_pending_exception());
+    isolate->clear_pending_exception();
+  }
+}
+
+
+#define INVALID_STRING_TEST(FUN, TYPE)                                         \
+  TEST(StringOOM##FUN) {                                                       \
+    CcTest::InitializeVM();                                                    \
+    LocalContext context;                                                      \
+    Isolate* isolate = CcTest::i_isolate();                                    \
+    STATIC_ASSERT(String::kMaxLength < kMaxInt);                               \
+    static const int invalid = String::kMaxLength + 1;                         \
+    HandleScope scope(isolate);                                                \
+    Vector<TYPE> dummy = Vector<TYPE>::New(invalid);                           \
+    CHECK(isolate->factory()->FUN(Vector<const TYPE>::cast(dummy)).is_null()); \
+    memset(dummy.start(), 0x20, dummy.length() * sizeof(TYPE));                \
+    CHECK(isolate->has_pending_exception());                                   \
+    isolate->clear_pending_exception();                                        \
+    dummy.Dispose();                                                           \
+  }
+
+INVALID_STRING_TEST(NewStringFromAscii, char)
+INVALID_STRING_TEST(NewStringFromUtf8, char)
+INVALID_STRING_TEST(NewStringFromOneByte, uint8_t)
+INVALID_STRING_TEST(InternalizeOneByteString, uint8_t)
+INVALID_STRING_TEST(InternalizeUtf8String, char)
+
+#undef INVALID_STRING_TEST
diff --git a/test/mjsunit/compiler/store-elimination.js b/test/mjsunit/compiler/store-elimination.js
new file mode 100644
index 0000000..1806ed9
--- /dev/null
+++ b/test/mjsunit/compiler/store-elimination.js
@@ -0,0 +1,94 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax --store-elimination
+
+// Test local elimination of unobservable stores.
+
+function B(x, y) {
+  this.x = x;
+  this.y = y;
+  return this;
+}
+
+function test_store_store() {
+  var a = new B(1, 2);
+  a.x = 3;  // eliminatable.
+  a.x = 4;
+  return a.x;
+}
+
+function test_store_load_store1() {
+  var a = new B(6, 7);
+  a.x = 3;  // eliminatable.
+  var r = a.y;
+  a.x = 4;
+  return r;
+}
+
+function test_store_load_store2() {
+  var a = new B(6, 8);
+  a.x = 3;  // not eliminatable, unless next load is eliminated.
+  var r = a.x;
+  a.x = 4;
+  return r;
+}
+
+function test_store_call_store() {
+  var a = new B(2, 9);
+  a.x = 3;  // not eliminatable.
+  killall();
+  a.x = 4;
+  return a.y;
+}
+
+function test_store_deopt_store() {
+  var a = new B(2, 1);
+  a.x = 3;  // not eliminatable (implicit ValueOf following)
+  var c = a + 2;
+  a.x = 4;
+  return a.y;
+}
+
+function killall() {
+  try { } catch(e) { }
+}
+
+%NeverOptimizeFunction(killall);
+
+function test(x, f) {
+  assertEquals(x, f());
+  assertEquals(x, f());
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(x, f());
+}
+
+test(4, test_store_store);
+test(7, test_store_load_store1);
+test(3, test_store_load_store2);
+test(9, test_store_call_store);
+test(1, test_store_deopt_store);
diff --git a/test/mjsunit/regress/regress-356053.js b/test/mjsunit/regress/regress-356053.js
new file mode 100644
index 0000000..8f0dbdd
--- /dev/null
+++ b/test/mjsunit/regress/regress-356053.js
@@ -0,0 +1,9 @@
+// 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.
+
+// Flags: --noconcurrent-recompilation --expose-gc --allow-natives-syntax
+
+%SetFlags("--concurrent-recompilation --block-concurrent-recompilation");
+gc();
+try { %UnblockConcurrentRecompilation(); } catch (e) { }
diff --git a/test/mjsunit/string-oom-replace-global-regexp-with-string.js b/test/mjsunit/string-oom-replace-global-regexp-with-string.js
index a527ae6..2de0110 100644
--- a/test/mjsunit/string-oom-replace-global-regexp-with-string.js
+++ b/test/mjsunit/string-oom-replace-global-regexp-with-string.js
@@ -2,13 +2,25 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+
+
 var a = 'a';
 for (var i = 0; i < 5; i++) a += a;
 var b = 'b';
 for (var i = 0; i < 23; i++) b += b;
 
-function replace() {
+function replace1() {
   a.replace(/./g, b);
 }
 
-assertThrows(replace, RangeError);
+assertThrows(replace1, RangeError);
+
+
+var a = 'a';
+for (var i = 0; i < 16; i++) a += a;
+
+function replace2() {
+  a.replace(/a/g, a);
+}
+
+assertThrows(replace2, RangeError);
diff --git a/tools/gcmole/gcmole.lua b/tools/gcmole/gcmole.lua
index aa93247..cd91a91 100644
--- a/tools/gcmole/gcmole.lua
+++ b/tools/gcmole/gcmole.lua
@@ -66,7 +66,7 @@
    end
 end
 
-local ARCHS = ARGS[1] and { ARGS[1] } or { 'ia32', 'arm', 'x64' }
+local ARCHS = ARGS[1] and { ARGS[1] } or { 'ia32', 'arm', 'x64', 'arm64' }
 
 local io = require "io"
 local os = require "os"
@@ -196,7 +196,9 @@
    arm = config { triple = "i586-unknown-linux",
                   arch_define = "V8_TARGET_ARCH_ARM" },
    x64 = config { triple = "x86_64-unknown-linux",
-                  arch_define = "V8_TARGET_ARCH_X64" }
+                  arch_define = "V8_TARGET_ARCH_X64" },
+   arm64 = config { triple = "x86_64-unknown-linux",
+                    arch_define = "V8_TARGET_ARCH_ARM64" },
 }
 
 -------------------------------------------------------------------------------
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 6f97def..52143e9 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -27,6 +27,7 @@
 
 {
   'variables': {
+    'icu_use_data_file_flag%': 0,
     'v8_code': 1,
     'v8_random_seed%': 314159265,
   },
@@ -420,6 +421,8 @@
         '../../src/hydrogen-representation-changes.h',
         '../../src/hydrogen-sce.cc',
         '../../src/hydrogen-sce.h',
+        '../../src/hydrogen-store-elimination.cc',
+        '../../src/hydrogen-store-elimination.h',
         '../../src/hydrogen-uint32-analysis.cc',
         '../../src/hydrogen-uint32-analysis.h',
         '../../src/i18n.cc',
@@ -1018,6 +1021,17 @@
             '../../src/default-platform.h',
           ],
         }],
+        ['icu_use_data_file_flag==1', {
+          'defines': ['ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE'],
+        }, { # else icu_use_data_file_flag !=1
+          'conditions': [
+            ['OS=="win"', {
+              'defines': ['ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_SHARED'],
+            }, {
+              'defines': ['ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC'],
+            }],
+          ],
+        }],
       ],
     },
     {
diff --git a/tools/lexer-shell.cc b/tools/lexer-shell.cc
index 8c7debc..e2e4a9c 100644
--- a/tools/lexer-shell.cc
+++ b/tools/lexer-shell.cc
@@ -68,6 +68,7 @@
             Vector<const uint16_t>(
                 reinterpret_cast<const uint16_t*>(source_),
                 length / 2));
+        CHECK_NOT_EMPTY_HANDLE(isolate, result);
         stream_ =
             new GenericStringUtf16CharacterStream(result, 0, result->length());
         break;
@@ -75,6 +76,7 @@
       case LATIN1: {
         Handle<String> result = isolate->factory()->NewStringFromOneByte(
             Vector<const uint8_t>(source_, length));
+        CHECK_NOT_EMPTY_HANDLE(isolate, result);
         stream_ =
             new GenericStringUtf16CharacterStream(result, 0, result->length());
         break;