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
R=ulan@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23863 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
jkummerow@chromium.org 2014-09-11 10:04:13 +00:00
parent bf7b4c12c3
commit 11f7584d0a
2 changed files with 62 additions and 19 deletions

View File

@ -10280,8 +10280,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: {
@ -10301,25 +10312,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
@ -10332,6 +10333,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);

View File

@ -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);