Commit de23dd28 authored by verwaest's avatar verwaest Committed by Commit bot

Fix for-in for large indexes and indexes on proxies

BUG=v8:4130
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#28526}
parent b4feaacc
...@@ -130,11 +130,7 @@ static bool HasKey(Handle<FixedArray> array, Handle<Object> key_handle) { ...@@ -130,11 +130,7 @@ static bool HasKey(Handle<FixedArray> array, Handle<Object> key_handle) {
int len0 = array->length(); int len0 = array->length();
for (int i = 0; i < len0; i++) { for (int i = 0; i < len0; i++) {
Object* element = array->get(i); Object* element = array->get(i);
if (element->IsSmi() && element == key) return true; if (key->KeyEquals(element)) return true;
if (element->IsString() &&
key->IsString() && String::cast(element)->Equals(String::cast(key))) {
return true;
}
} }
return false; return false;
} }
...@@ -738,8 +734,10 @@ class ElementsAccessorBase : public ElementsAccessor { ...@@ -738,8 +734,10 @@ class ElementsAccessorBase : public ElementsAccessor {
} }
virtual MaybeHandle<FixedArray> AddElementsToFixedArray( virtual MaybeHandle<FixedArray> AddElementsToFixedArray(
Handle<Object> receiver, Handle<JSObject> holder, Handle<FixedArray> to, Handle<JSObject> receiver, Handle<FixedArray> to,
Handle<FixedArrayBase> from, FixedArray::KeyFilter filter) final { FixedArray::KeyFilter filter) final {
Handle<FixedArrayBase> from(receiver->elements());
int len0 = to->length(); int len0 = to->length();
#ifdef ENABLE_SLOW_DCHECKS #ifdef ENABLE_SLOW_DCHECKS
if (FLAG_enable_slow_asserts) { if (FLAG_enable_slow_asserts) {
...@@ -751,7 +749,7 @@ class ElementsAccessorBase : public ElementsAccessor { ...@@ -751,7 +749,7 @@ class ElementsAccessorBase : public ElementsAccessor {
// Optimize if 'other' is empty. // Optimize if 'other' is empty.
// We cannot optimize if 'this' is empty, as other may have holes. // We cannot optimize if 'this' is empty, as other may have holes.
uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(holder, from); uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(receiver, from);
if (len1 == 0) return to; if (len1 == 0) return to;
Isolate* isolate = from->GetIsolate(); Isolate* isolate = from->GetIsolate();
...@@ -760,11 +758,11 @@ class ElementsAccessorBase : public ElementsAccessor { ...@@ -760,11 +758,11 @@ class ElementsAccessorBase : public ElementsAccessor {
uint32_t extra = 0; uint32_t extra = 0;
for (uint32_t y = 0; y < len1; y++) { for (uint32_t y = 0; y < len1; y++) {
uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(from, y); uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(from, y);
if (ElementsAccessorSubclass::HasElementImpl(holder, key, from)) { if (ElementsAccessorSubclass::HasElementImpl(receiver, key, from)) {
Handle<Object> value; Handle<Object> value;
ASSIGN_RETURN_ON_EXCEPTION( ASSIGN_RETURN_ON_EXCEPTION(
isolate, value, isolate, value,
ElementsAccessorSubclass::GetImpl(receiver, holder, key, from), ElementsAccessorSubclass::GetImpl(receiver, receiver, key, from),
FixedArray); FixedArray);
DCHECK(!value->IsTheHole()); DCHECK(!value->IsTheHole());
...@@ -797,11 +795,11 @@ class ElementsAccessorBase : public ElementsAccessor { ...@@ -797,11 +795,11 @@ class ElementsAccessorBase : public ElementsAccessor {
for (uint32_t y = 0; y < len1; y++) { for (uint32_t y = 0; y < len1; y++) {
uint32_t key = uint32_t key =
ElementsAccessorSubclass::GetKeyForIndexImpl(from, y); ElementsAccessorSubclass::GetKeyForIndexImpl(from, y);
if (ElementsAccessorSubclass::HasElementImpl(holder, key, from)) { if (ElementsAccessorSubclass::HasElementImpl(receiver, key, from)) {
Handle<Object> value; Handle<Object> value;
ASSIGN_RETURN_ON_EXCEPTION( ASSIGN_RETURN_ON_EXCEPTION(
isolate, value, isolate, value,
ElementsAccessorSubclass::GetImpl(receiver, holder, key, from), ElementsAccessorSubclass::GetImpl(receiver, receiver, key, from),
FixedArray); FixedArray);
if (filter == FixedArray::NON_SYMBOL_KEYS && value->IsSymbol()) { if (filter == FixedArray::NON_SYMBOL_KEYS && value->IsSymbol()) {
continue; continue;
......
...@@ -159,15 +159,8 @@ class ElementsAccessor { ...@@ -159,15 +159,8 @@ class ElementsAccessor {
} }
MUST_USE_RESULT virtual MaybeHandle<FixedArray> AddElementsToFixedArray( MUST_USE_RESULT virtual MaybeHandle<FixedArray> AddElementsToFixedArray(
Handle<Object> receiver, Handle<JSObject> holder, Handle<FixedArray> to, Handle<JSObject> receiver, Handle<FixedArray> to,
Handle<FixedArrayBase> from, FixedArray::KeyFilter filter) = 0; FixedArray::KeyFilter filter) = 0;
MUST_USE_RESULT inline MaybeHandle<FixedArray> AddElementsToFixedArray(
Handle<Object> receiver, Handle<JSObject> holder, Handle<FixedArray> to,
FixedArray::KeyFilter filter) {
return AddElementsToFixedArray(receiver, holder, to,
handle(holder->elements()), filter);
}
// Returns a shared ElementsAccessor for the specified ElementsKind. // Returns a shared ElementsAccessor for the specified ElementsKind.
static ElementsAccessor* ForKind(ElementsKind elements_kind) { static ElementsAccessor* ForKind(ElementsKind elements_kind) {
......
...@@ -275,6 +275,24 @@ bool Object::HasValidElements() { ...@@ -275,6 +275,24 @@ bool Object::HasValidElements() {
} }
bool Object::KeyEquals(Object* second) {
Object* first = this;
if (second->IsNumber()) {
if (first->IsNumber()) return first->Number() == second->Number();
Object* temp = first;
first = second;
second = temp;
}
if (first->IsNumber()) {
DCHECK_LE(0, first->Number());
uint32_t expected = static_cast<uint32_t>(first->Number());
uint32_t index;
return Name::cast(second)->AsArrayIndex(&index) && index == expected;
}
return Name::cast(first)->Equals(Name::cast(second));
}
Handle<Object> Object::NewStorageFor(Isolate* isolate, Handle<Object> Object::NewStorageFor(Isolate* isolate,
Handle<Object> object, Handle<Object> object,
Representation representation) { Representation representation) {
......
...@@ -8203,8 +8203,7 @@ MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike( ...@@ -8203,8 +8203,7 @@ MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike(
Handle<FixedArray> result; Handle<FixedArray> result;
ASSIGN_RETURN_ON_EXCEPTION( ASSIGN_RETURN_ON_EXCEPTION(
array->GetIsolate(), result, array->GetIsolate(), result,
accessor->AddElementsToFixedArray(array, array, content, filter), accessor->AddElementsToFixedArray(array, content, filter), FixedArray);
FixedArray);
#ifdef ENABLE_SLOW_DCHECKS #ifdef ENABLE_SLOW_DCHECKS
if (FLAG_enable_slow_asserts) { if (FLAG_enable_slow_asserts) {
...@@ -8221,25 +8220,27 @@ MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike( ...@@ -8221,25 +8220,27 @@ MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike(
MaybeHandle<FixedArray> FixedArray::UnionOfKeys(Handle<FixedArray> first, MaybeHandle<FixedArray> FixedArray::UnionOfKeys(Handle<FixedArray> first,
Handle<FixedArray> second) { Handle<FixedArray> second) {
ElementsAccessor* accessor = ElementsAccessor::ForArray(second); if (second->length() == 0) return first;
Handle<FixedArray> result; if (first->length() == 0) return second;
ASSIGN_RETURN_ON_EXCEPTION( Isolate* isolate = first->GetIsolate();
first->GetIsolate(), result, Handle<FixedArray> result =
accessor->AddElementsToFixedArray( isolate->factory()->NewFixedArray(first->length() + second->length());
Handle<Object>::null(), // receiver for (int i = 0; i < first->length(); i++) {
Handle<JSObject>::null(), // holder result->set(i, first->get(i));
first, Handle<FixedArrayBase>::cast(second), ALL_KEYS), }
FixedArray); int pos = first->length();
for (int j = 0; j < second->length(); j++) {
#ifdef ENABLE_SLOW_DCHECKS Object* current = second->get(j);
if (FLAG_enable_slow_asserts) { int i;
DisallowHeapAllocation no_allocation; for (i = 0; i < first->length(); i++) {
for (int i = 0; i < result->length(); i++) { if (current->KeyEquals(first->get(i))) break;
Object* current = result->get(i); }
DCHECK(current->IsNumber() || current->IsName()); if (i == first->length()) {
result->set(pos++, current);
} }
} }
#endif
result->Shrink(pos);
return result; return result;
} }
......
...@@ -1107,6 +1107,11 @@ class Object { ...@@ -1107,6 +1107,11 @@ class Object {
return true; return true;
} }
// Checks whether two valid primitive encodings of a property name resolve to
// the same logical property. E.g., the smi 1, the string "1" and the double
// 1 all refer to the same property, so this helper will return true.
inline bool KeyEquals(Object* other);
Handle<HeapType> OptimalType(Isolate* isolate, Representation representation); Handle<HeapType> OptimalType(Isolate* isolate, Representation representation);
inline static Handle<Object> NewStorageFor(Isolate* isolate, inline static Handle<Object> NewStorageFor(Isolate* isolate,
......
...@@ -119,3 +119,15 @@ for (i=0 ; i < 3; ++i) { ...@@ -119,3 +119,15 @@ for (i=0 ; i < 3; ++i) {
assertEquals("undefined", typeof y[2], "y[2]"); assertEquals("undefined", typeof y[2], "y[2]");
assertEquals("undefined", typeof y[0], "y[0]"); assertEquals("undefined", typeof y[0], "y[0]");
} }
(function() {
var large_key = 2147483650;
var o = {__proto__: {}};
o[large_key] = 1;
o.__proto__[large_key] = 1;
var keys = [];
for (var k in o) {
keys.push(k);
}
assertEquals(["2147483650"], keys);
})();
...@@ -165,4 +165,13 @@ TestForInThrow(Proxy.create({ ...@@ -165,4 +165,13 @@ TestForInThrow(Proxy.create({
get: function(pr, pk) { get: function(pr, pk) {
return function() { throw "myexn" } return function() { throw "myexn" }
} }
})) }));
(function() {
var p = Proxy.create({enumerate:function() { return [0]; }});
var o = [0];
o.__proto__ = p;
var keys = [];
for (var k in o) { keys.push(k); };
assertEquals(["0"], keys);
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment