Reviewers: ulan,

Description:
Fix ElementsKind handling of prototypes in Array.concat

Double elements, typed elements, and sloppy arguments elements were all
erroneously marked UNREACHABLE.

BUG=chromium:412203
LOG=n

Please review this at https://codereview.chromium.org/560463002/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files (+62, -19 lines):
  M src/runtime.cc
  A test/mjsunit/regress/regress-crbug-412203.js


Index: src/runtime.cc
diff --git a/src/runtime.cc b/src/runtime.cc
index ce2d51c82a77cc9c2f37bad70764bdadb0aa7b21..e559f94fb8f732b2074e4a5c8bf09c1953ca01c4 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -10282,8 +10282,19 @@ static void CollectElementIndices(Handle<JSObject> object,
     }
     case FAST_HOLEY_DOUBLE_ELEMENTS:
     case FAST_DOUBLE_ELEMENTS: {
-      // TODO(1810): Decide if it's worthwhile to implement this.
-      UNREACHABLE();
+      if (object->elements()->IsFixedArray()) {
+        DCHECK(object->elements()->length() == 0);
+        break;
+      }
+      Handle<FixedDoubleArray> elements(
+          FixedDoubleArray::cast(object->elements()));
+      uint32_t length = static_cast<uint32_t>(elements->length());
+      if (range < length) length = range;
+      for (uint32_t i = 0; i < length; i++) {
+        if (!elements->is_the_hole(i)) {
+          indices->Add(i);
+        }
+      }
       break;
     }
     case DICTIONARY_ELEMENTS: {
@@ -10303,25 +10314,15 @@ static void CollectElementIndices(Handle<JSObject> object,
       }
       break;
     }
-    default: {
-      int dense_elements_length;
-      switch (kind) {
-#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ - case EXTERNAL_##TYPE##_ELEMENTS: { \ - dense_elements_length = \ - External##Type##Array::cast(object->elements())->length(); \ - break; \
-        }
+#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
+    case TYPE##_ELEMENTS:                               \
+    case EXTERNAL_##TYPE##_ELEMENTS:

-        TYPED_ARRAYS(TYPED_ARRAY_CASE)
+      TYPED_ARRAYS(TYPED_ARRAY_CASE)
 #undef TYPED_ARRAY_CASE
-
-        default:
-          UNREACHABLE();
-          dense_elements_length = 0;
-          break;
-      }
-      uint32_t length = static_cast<uint32_t>(dense_elements_length);
+    {
+      uint32_t length = static_cast<uint32_t>(
+          FixedArrayBase::cast(object->elements())->length());
       if (range <= length) {
         length = range;
         // We will add all indices, so we might as well clear it first
@@ -10334,6 +10335,17 @@ static void CollectElementIndices(Handle<JSObject> object,
       if (length == range) return;  // All indices accounted for already.
       break;
     }
+    case SLOPPY_ARGUMENTS_ELEMENTS: {
+      uint32_t length = static_cast<uint32_t>(
+          Handle<JSArray>::cast(object)->length()->Number());
+      ElementsAccessor* accessor = object->GetElementsAccessor();
+      for (uint32_t i = 0; i < length; i++) {
+        if (accessor->HasElement(object, object, i)) {
+          indices->Add(i);
+        }
+      }
+      break;
+    }
   }

   PrototypeIterator iter(isolate, object);
Index: test/mjsunit/regress/regress-crbug-412203.js
diff --git a/test/mjsunit/regress/regress-crbug-412203.js b/test/mjsunit/regress/regress-crbug-412203.js
new file mode 100644
index 0000000000000000000000000000000000000000..6a781308f75b2932ffb606f754f65911228728b9
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-412203.js
@@ -0,0 +1,31 @@
+// 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: --allow-natives-syntax
+
+var b = [];
+b[10000] = 1;
+// Required to reproduce the bug.
+assertTrue(%HasDictionaryElements(b));
+
+var a1 = [1.5];
+b.__proto__ = a1;
+assertEquals(1.5, ([].concat(b))[0]);
+
+var a2 = new Int32Array(2);
+a2[0] = 3;
+b.__proto__ = a2
+assertEquals(3, ([].concat(b))[0]);
+
+function foo(x, y) {
+  var a = [];
+  a[10000] = 1;
+  assertTrue(%HasDictionaryElements(a));
+
+  a.__proto__ = arguments;
+  var c = [].concat(a);
+  assertEquals(2, c[0]);
+  assertEquals(undefined, c[1]);
+}
+foo(2);


--
--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to