[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(
|
static Handle<FixedArray> DirectCollectElementIndicesImpl(
|
||||||
Isolate* isolate, Handle<JSObject> object,
|
Isolate* isolate, Handle<JSObject> object,
|
||||||
Handle<FixedArrayBase> backing_store, GetKeysConversion convert,
|
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 =
|
uint32_t length =
|
||||||
ElementsAccessorSubclass::GetIterationLength(*object, *backing_store);
|
ElementsAccessorSubclass::GetIterationLength(*object, *backing_store);
|
||||||
uint32_t insertion_index = 0;
|
|
||||||
for (uint32_t i = 0; i < length; i++) {
|
for (uint32_t i = 0; i < length; i++) {
|
||||||
if (ElementsAccessorSubclass::HasElementImpl(object, i, backing_store,
|
if (ElementsAccessorSubclass::HasElementImpl(object, i, backing_store,
|
||||||
filter)) {
|
filter)) {
|
||||||
@ -914,7 +914,7 @@ class ElementsAccessorBase : public ElementsAccessor {
|
|||||||
&nof_indices);
|
&nof_indices);
|
||||||
|
|
||||||
// Sort the indices list if necessary.
|
// Sort the indices list if necessary.
|
||||||
if (IsDictionaryElementsKind(kind())) {
|
if (IsDictionaryElementsKind(kind()) || IsSloppyArgumentsElements(kind())) {
|
||||||
struct {
|
struct {
|
||||||
bool operator()(Object* a, Object* b) {
|
bool operator()(Object* a, Object* b) {
|
||||||
if (!a->IsUndefined()) {
|
if (!a->IsUndefined()) {
|
||||||
@ -1227,11 +1227,11 @@ class DictionaryElementsAccessor
|
|||||||
static Handle<FixedArray> DirectCollectElementIndicesImpl(
|
static Handle<FixedArray> DirectCollectElementIndicesImpl(
|
||||||
Isolate* isolate, Handle<JSObject> object,
|
Isolate* isolate, Handle<JSObject> object,
|
||||||
Handle<FixedArrayBase> backing_store, GetKeysConversion convert,
|
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> dictionary =
|
||||||
Handle<SeededNumberDictionary>::cast(backing_store);
|
Handle<SeededNumberDictionary>::cast(backing_store);
|
||||||
uint32_t capacity = dictionary->Capacity();
|
uint32_t capacity = dictionary->Capacity();
|
||||||
uint32_t insertion_index = 0;
|
|
||||||
for (uint32_t i = 0; i < capacity; i++) {
|
for (uint32_t i = 0; i < capacity; i++) {
|
||||||
uint32_t key = GetKeyForEntryImpl(dictionary, i, filter);
|
uint32_t key = GetKeyForEntryImpl(dictionary, i, filter);
|
||||||
if (key == kMaxUInt32) continue;
|
if (key == kMaxUInt32) continue;
|
||||||
@ -2223,6 +2223,55 @@ class SloppyArgumentsElementsAccessor
|
|||||||
obj, entry - length);
|
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