[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:
parent
a02b7aaa6d
commit
3088979d5c
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
95
test/mjsunit/regress/regress-4825.js
Normal file
95
test/mjsunit/regress/regress-4825.js
Normal 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)));
|
||||
})();
|
Loading…
Reference in New Issue
Block a user