Version 4.6.85.32 (cherry-pick)

Merged 6df9a1db8c85ab63dee63879456b6027df53fabc
Merged a7e50a5e06b2c7edd7915df774769c9add42be27
Merged ee9020ddd90900ecb29abc4f5e9e78151f630906

[JSON stringifier] Correctly load array elements.

[JSON stringifier] Reintroduce fast path with bail out to slow path.

Serializer: attach alignment to deferred objects.

BUG=chromium:523919,chromium:554946,chromium:554946
LOG=N
TBR=hablich@chromium.org

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

Cr-Commit-Position: refs/branch-heads/4.6@{#39}
Cr-Branched-From: 24d34a8ae3cad186792fb1e44e2d7c00d49cd181-refs/heads/4.6.85@{#1}
Cr-Branched-From: 8f441181a570c44ef5c949e8dfd9fd326ac10345-refs/heads/master@{#30256}
diff --git a/include/v8-version.h b/include/v8-version.h
index 7744c08..bd7afa5 100644
--- a/include/v8-version.h
+++ b/include/v8-version.h
@@ -11,7 +11,7 @@
 #define V8_MAJOR_VERSION 4
 #define V8_MINOR_VERSION 6
 #define V8_BUILD_NUMBER 85
-#define V8_PATCH_LEVEL 31
+#define V8_PATCH_LEVEL 32
 
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/json-stringifier.h b/src/json-stringifier.h
index fb6b80d..3bbfb63 100644
--- a/src/json-stringifier.h
+++ b/src/json-stringifier.h
@@ -82,7 +82,8 @@
   INLINE(Result SerializeJSArray(Handle<JSArray> object));
   INLINE(Result SerializeJSObject(Handle<JSObject> object));
 
-  Result SerializeJSArraySlow(Handle<JSArray> object, uint32_t length);
+  Result SerializeJSArraySlow(Handle<JSArray> object, uint32_t start,
+                              uint32_t length);
 
   void SerializeString(Handle<String> object);
 
@@ -436,8 +437,8 @@
   builder_.AppendCharacter('[');
   switch (object->GetElementsKind()) {
     case FAST_SMI_ELEMENTS: {
-      Handle<FixedArray> elements(
-          FixedArray::cast(object->elements()), isolate_);
+      Handle<FixedArray> elements(FixedArray::cast(object->elements()),
+                                  isolate_);
       for (uint32_t i = 0; i < length; i++) {
         if (i > 0) builder_.AppendCharacter(',');
         SerializeSmi(Smi::cast(elements->get(i)));
@@ -456,14 +457,20 @@
       break;
     }
     case FAST_ELEMENTS: {
-      Handle<FixedArray> elements(
-          FixedArray::cast(object->elements()), isolate_);
+      Handle<Object> old_length(object->length(), isolate_);
       for (uint32_t i = 0; i < length; i++) {
+        if (object->length() != *old_length ||
+            object->GetElementsKind() != FAST_ELEMENTS) {
+          Result result = SerializeJSArraySlow(object, i, length);
+          if (result != SUCCESS) return result;
+          break;
+        }
         if (i > 0) builder_.AppendCharacter(',');
-        Result result =
-            SerializeElement(isolate_,
-                             Handle<Object>(elements->get(i), isolate_),
-                             i);
+        Result result = SerializeElement(
+            isolate_,
+            Handle<Object>(FixedArray::cast(object->elements())->get(i),
+                           isolate_),
+            i);
         if (result == SUCCESS) continue;
         if (result == UNCHANGED) {
           builder_.AppendCString("null");
@@ -473,11 +480,10 @@
       }
       break;
     }
-    // TODO(yangguo):  The FAST_HOLEY_* cases could be handled in a faster way.
-    // They resemble the non-holey cases except that a prototype chain lookup
-    // is necessary for holes.
+    // The FAST_HOLEY_* cases could be handled in a faster way. They resemble
+    // the non-holey cases except that a lookup is necessary for holes.
     default: {
-      Result result = SerializeJSArraySlow(object, length);
+      Result result = SerializeJSArraySlow(object, 0, length);
       if (result != SUCCESS) return result;
       break;
     }
@@ -489,8 +495,8 @@
 
 
 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArraySlow(
-    Handle<JSArray> object, uint32_t length) {
-  for (uint32_t i = 0; i < length; i++) {
+    Handle<JSArray> object, uint32_t start, uint32_t length) {
+  for (uint32_t i = start; i < length; i++) {
     if (i > 0) builder_.AppendCharacter(',');
     Handle<Object> element;
     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
diff --git a/src/snapshot/serialize.cc b/src/snapshot/serialize.cc
index 9f2b4e9..36b153c 100644
--- a/src/snapshot/serialize.cc
+++ b/src/snapshot/serialize.cc
@@ -660,18 +660,27 @@
 
 void Deserializer::DeserializeDeferredObjects() {
   for (int code = source_.Get(); code != kSynchronize; code = source_.Get()) {
-    int space = code & kSpaceMask;
-    DCHECK(space <= kNumberOfSpaces);
-    DCHECK(code - space == kNewObject);
-    HeapObject* object = GetBackReferencedObject(space);
-    int size = source_.GetInt() << kPointerSizeLog2;
-    Address obj_address = object->address();
-    Object** start = reinterpret_cast<Object**>(obj_address + kPointerSize);
-    Object** end = reinterpret_cast<Object**>(obj_address + size);
-    bool filled = ReadData(start, end, space, obj_address);
-    CHECK(filled);
-    DCHECK(CanBeDeferred(object));
-    PostProcessNewObject(object, space);
+    switch (code) {
+      case kAlignmentPrefix:
+      case kAlignmentPrefix + 1:
+      case kAlignmentPrefix + 2:
+        SetAlignment(code);
+        break;
+      default: {
+        int space = code & kSpaceMask;
+        DCHECK(space <= kNumberOfSpaces);
+        DCHECK(code - space == kNewObject);
+        HeapObject* object = GetBackReferencedObject(space);
+        int size = source_.GetInt() << kPointerSizeLog2;
+        Address obj_address = object->address();
+        Object** start = reinterpret_cast<Object**>(obj_address + kPointerSize);
+        Object** end = reinterpret_cast<Object**>(obj_address + size);
+        bool filled = ReadData(start, end, space, obj_address);
+        CHECK(filled);
+        DCHECK(CanBeDeferred(object));
+        PostProcessNewObject(object, space);
+      }
+    }
   }
 }
 
@@ -1202,12 +1211,9 @@
 
       case kAlignmentPrefix:
       case kAlignmentPrefix + 1:
-      case kAlignmentPrefix + 2: {
-        DCHECK_EQ(kWordAligned, next_alignment_);
-        next_alignment_ =
-            static_cast<AllocationAlignment>(data - (kAlignmentPrefix - 1));
+      case kAlignmentPrefix + 2:
+        SetAlignment(data);
         break;
-      }
 
       STATIC_ASSERT(kNumberOfRootArrayConstants == Heap::kOldSpaceRoots);
       STATIC_ASSERT(kNumberOfRootArrayConstants == 32);
@@ -1982,6 +1988,7 @@
   CHECK_EQ(0, bytes_processed_so_far_);
   bytes_processed_so_far_ = kPointerSize;
 
+  serializer_->PutAlignmentPrefix(object_);
   sink_->Put(kNewObject + reference.space(), "deferred object");
   serializer_->PutBackReference(object_, reference);
   sink_->PutInt(size >> kPointerSizeLog2, "deferred object size");
diff --git a/src/snapshot/serialize.h b/src/snapshot/serialize.h
index e790062..a769bc8 100644
--- a/src/snapshot/serialize.h
+++ b/src/snapshot/serialize.h
@@ -572,6 +572,14 @@
     memcpy(dest, src, sizeof(*src));
   }
 
+  void SetAlignment(byte data) {
+    DCHECK_EQ(kWordAligned, next_alignment_);
+    int alignment = data - (kAlignmentPrefix - 1);
+    DCHECK_LE(kWordAligned, alignment);
+    DCHECK_LE(alignment, kSimd128Unaligned);
+    next_alignment_ = static_cast<AllocationAlignment>(alignment);
+  }
+
   void DeserializeDeferredObjects();
 
   void FlushICacheForNewIsolate();
diff --git a/test/mjsunit/regress/regress-crbug-523919.js b/test/mjsunit/regress/regress-crbug-523919.js
new file mode 100644
index 0000000..4b2a8fe
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-523919.js
@@ -0,0 +1,31 @@
+// Copyright 2015 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: --cache=code
+
+[1.5,
+[2.5,
+[3.5,
+[4.5,
+[5.5,
+[6.5,
+[7.5,
+[8.5,
+[9.5,
+[10.5,
+[11.5,
+[12.5,
+[13.5,
+[14.5,
+[15.5,
+[16.5,
+[17.5,
+[18.5,
+[19.5,
+[20.5,
+[21.5,
+[22.5,
+[23.5,
+[24.5,
+[25.5]]]]]]]]]]]]]]]]]]]]]]]]];
diff --git a/test/mjsunit/regress/regress-crbug-554946.js b/test/mjsunit/regress/regress-crbug-554946.js
new file mode 100644
index 0000000..fbb79f6
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-554946.js
@@ -0,0 +1,61 @@
+// Copyright 2015 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.
+
+var array = [];
+var funky = {
+  toJSON: function() { array.length = 1; return "funky"; }
+};
+for (var i = 0; i < 10; i++) array[i] = i;
+array[0] = funky;
+assertEquals('["funky",null,null,null,null,null,null,null,null,null]',
+             JSON.stringify(array));
+
+array = [];
+funky = {
+  get value() { array.length = 1; return "funky"; }
+};
+for (var i = 0; i < 10; i++) array[i] = i;
+array[3] = funky;
+assertEquals('[0,1,2,{"value":"funky"},null,null,null,null,null,null]',
+             JSON.stringify(array));
+
+array = [];
+funky = {
+  get value() { array.pop(); return "funky"; }
+};
+for (var i = 0; i < 10; i++) array[i] = i;
+array[3] = funky;
+assertEquals('[0,1,2,{"value":"funky"},4,5,6,7,8,null]', JSON.stringify(array));
+
+array = [];
+funky = {
+  get value() { delete array[9]; return "funky"; }
+};
+for (var i = 0; i < 10; i++) array[i] = i;
+array[3] = funky;
+assertEquals('[0,1,2,{"value":"funky"},4,5,6,7,8,null]', JSON.stringify(array));
+
+array = [];
+funky = {
+  get value() { delete array[6]; return "funky"; }
+};
+for (var i = 0; i < 10; i++) array[i] = i;
+array[3] = funky;
+assertEquals('[0,1,2,{"value":"funky"},4,5,null,7,8,9]', JSON.stringify(array));
+
+array = [];
+funky = {
+  get value() { array[12] = 12; return "funky"; }
+};
+for (var i = 0; i < 10; i++) array[i] = i;
+array[3] = funky;
+assertEquals('[0,1,2,{"value":"funky"},4,5,6,7,8,9]', JSON.stringify(array));
+
+array = [];
+funky = {
+  get value() { array[10000000] = 12; return "funky"; }
+};
+for (var i = 0; i < 10; i++) array[i] = i;
+array[3] = funky;
+assertEquals('[0,1,2,{"value":"funky"},4,5,6,7,8,9]', JSON.stringify(array));