[runtime] fix getting element keys from SLOW_SLOPPY_ARGUMENTS_ELEMENTS

BUG=v8:4825
LOG=N
R=jkummerow@chromium.org, cbruni@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#34754}
This commit is contained in:
caitpotter88 2016-03-14 10:09:19 -07:00 committed by Commit bot
parent a02b7aaa6d
commit 3088979d5c
2 changed files with 149 additions and 5 deletions

View File

@ -866,10 +866,10 @@ class ElementsAccessorBase : public ElementsAccessor {
static Handle<FixedArray> DirectCollectElementIndicesImpl(
Isolate* isolate, Handle<JSObject> object,
Handle<FixedArrayBase> backing_store, GetKeysConversion convert,
PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices) {
PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices,
uint32_t insertion_index = 0) {
uint32_t length =
ElementsAccessorSubclass::GetIterationLength(*object, *backing_store);
uint32_t insertion_index = 0;
for (uint32_t i = 0; i < length; i++) {
if (ElementsAccessorSubclass::HasElementImpl(object, i, backing_store,
filter)) {
@ -914,7 +914,7 @@ class ElementsAccessorBase : public ElementsAccessor {
&nof_indices);
// Sort the indices list if necessary.
if (IsDictionaryElementsKind(kind())) {
if (IsDictionaryElementsKind(kind()) || IsSloppyArgumentsElements(kind())) {
struct {
bool operator()(Object* a, Object* b) {
if (!a->IsUndefined()) {
@ -1227,11 +1227,11 @@ class DictionaryElementsAccessor
static Handle<FixedArray> DirectCollectElementIndicesImpl(
Isolate* isolate, Handle<JSObject> object,
Handle<FixedArrayBase> backing_store, GetKeysConversion convert,
PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices) {
PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices,
uint32_t insertion_index = 0) {
Handle<SeededNumberDictionary> dictionary =
Handle<SeededNumberDictionary>::cast(backing_store);
uint32_t capacity = dictionary->Capacity();
uint32_t insertion_index = 0;
for (uint32_t i = 0; i < capacity; i++) {
uint32_t key = GetKeyForEntryImpl(dictionary, i, filter);
if (key == kMaxUInt32) continue;
@ -2223,6 +2223,55 @@ class SloppyArgumentsElementsAccessor
obj, entry - length);
}
}
static void CollectElementIndicesImpl(Handle<JSObject> object,
Handle<FixedArrayBase> backing_store,
KeyAccumulator* keys, uint32_t range,
PropertyFilter filter,
uint32_t offset) {
FixedArray* parameter_map = FixedArray::cast(*backing_store);
uint32_t length = parameter_map->length() - 2;
if (range < length) length = range;
for (uint32_t i = offset; i < length; ++i) {
if (!parameter_map->get(i + 2)->IsTheHole()) {
keys->AddKey(i);
}
}
Handle<FixedArrayBase> store(FixedArrayBase::cast(parameter_map->get(1)));
ArgumentsAccessor::CollectElementIndicesImpl(object, store, keys, range,
filter, offset);
if (SloppyArgumentsElementsAccessorSubclass::kind() ==
FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
keys->SortCurrentElementsList();
}
}
static Handle<FixedArray> DirectCollectElementIndicesImpl(
Isolate* isolate, Handle<JSObject> object,
Handle<FixedArrayBase> backing_store, GetKeysConversion convert,
PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices,
uint32_t insertion_index = 0) {
FixedArray* parameter_map = FixedArray::cast(*backing_store);
uint32_t length = parameter_map->length() - 2;
for (uint32_t i = 0; i < length; ++i) {
if (parameter_map->get(i + 2)->IsTheHole()) continue;
if (convert == CONVERT_TO_STRING) {
Handle<String> index_string = isolate->factory()->Uint32ToString(i);
list->set(insertion_index, *index_string);
} else {
list->set(insertion_index, Smi::FromInt(i), SKIP_WRITE_BARRIER);
}
insertion_index++;
}
Handle<FixedArrayBase> store(FixedArrayBase::cast(parameter_map->get(1)));
return ArgumentsAccessor::DirectCollectElementIndicesImpl(
isolate, object, store, convert, filter, list, nof_indices,
insertion_index);
}
};

View File

@ -0,0 +1,95 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function enumerate(o) {
var keys = [];
for (var key in o) keys.push(key);
return keys;
}
(function testSlowSloppyArgumentsElements() {
function slowSloppyArguments(a, b, c) {
arguments[10000] = "last";
arguments[4000] = "first";
arguments[6000] = "second";
arguments[5999] = "x";
arguments[3999] = "y";
return arguments;
}
assertEquals(["0", "1", "2", "3999", "4000", "5999", "6000", "10000"],
Object.keys(slowSloppyArguments(1, 2, 3)));
assertEquals(["0", "1", "2", "3999", "4000", "5999", "6000", "10000"],
enumerate(slowSloppyArguments(1,2,3)));
})();
(function testSlowSloppyArgumentsElementsNotEnumerable() {
function slowSloppyArguments(a, b, c) {
Object.defineProperty(arguments, 10000, {
enumerable: false, configurable: false, value: "NOPE"
});
arguments[4000] = "first";
arguments[6000] = "second";
arguments[5999] = "x";
arguments[3999] = "y";
return arguments;
}
assertEquals(["0", "1", "2", "3999", "4000", "5999", "6000"],
Object.keys(slowSloppyArguments(1, 2, 3)));
assertEquals(["0", "1", "2", "3999", "4000", "5999", "6000"],
enumerate(slowSloppyArguments(1,2,3)));
})();
(function testFastSloppyArgumentsElements() {
function fastSloppyArguments(a, b, c) {
arguments[5] = 1;
arguments[7] = 0;
arguments[3] = 2;
return arguments;
}
assertEquals(["0", "1", "2", "3", "5", "7"],
Object.keys(fastSloppyArguments(1, 2, 3)));
assertEquals(
["0", "1", "2", "3", "5", "7"], enumerate(fastSloppyArguments(1, 2, 3)));
function fastSloppyArguments2(a, b, c) {
delete arguments[0];
arguments[0] = "test";
return arguments;
}
assertEquals(["0", "1", "2"], Object.keys(fastSloppyArguments2(1, 2, 3)));
assertEquals(["0", "1", "2"], enumerate(fastSloppyArguments2(1, 2, 3)));
})();
(function testFastSloppyArgumentsElementsNotEnumerable() {
function fastSloppyArguments(a, b, c) {
Object.defineProperty(arguments, 5, {
enumerable: false, configurable: false, value: "NOPE"
});
arguments[7] = 0;
arguments[3] = 2;
return arguments;
}
assertEquals(
["0", "1", "2", "3", "7"], Object.keys(fastSloppyArguments(1, 2, 3)));
assertEquals(
["0", "1", "2", "3", "7"], enumerate(fastSloppyArguments(1,2,3)));
function fastSloppyArguments2(a, b, c) {
delete arguments[0];
Object.defineProperty(arguments, 1, {
enumerable: false, configurable: false, value: "NOPE"
});
arguments[0] = "test";
return arguments;
}
assertEquals(["0", "2"], Object.keys(fastSloppyArguments2(1, 2, 3)));
assertEquals(["0", "2"], enumerate(fastSloppyArguments2(1, 2, 3)));
})();