Commit b4b69fd9 authored by jkummerow's avatar jkummerow Committed by Commit bot

Teach JSReceiver::GetKeys() how to include symbols

No users of that functionality yet, those will come separately.

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

Cr-Commit-Position: refs/heads/master@{#31024}
parent e3833fdc
...@@ -870,7 +870,7 @@ class ElementsAccessorBase : public ElementsAccessor { ...@@ -870,7 +870,7 @@ class ElementsAccessorBase : public ElementsAccessor {
virtual void AddElementsToKeyAccumulator(Handle<JSObject> receiver, virtual void AddElementsToKeyAccumulator(Handle<JSObject> receiver,
KeyAccumulator* accumulator, KeyAccumulator* accumulator,
FixedArray::KeyFilter filter) final { KeyFilter filter) final {
Handle<FixedArrayBase> from(receiver->elements()); Handle<FixedArrayBase> from(receiver->elements());
uint32_t add_length = uint32_t add_length =
ElementsAccessorSubclass::GetCapacityImpl(*receiver, *from); ElementsAccessorSubclass::GetCapacityImpl(*receiver, *from);
...@@ -883,7 +883,7 @@ class ElementsAccessorBase : public ElementsAccessor { ...@@ -883,7 +883,7 @@ class ElementsAccessorBase : public ElementsAccessor {
DCHECK(!value->IsTheHole()); DCHECK(!value->IsTheHole());
DCHECK(!value->IsAccessorPair()); DCHECK(!value->IsAccessorPair());
DCHECK(!value->IsExecutableAccessorInfo()); DCHECK(!value->IsExecutableAccessorInfo());
if (filter == FixedArray::NON_SYMBOL_KEYS && value->IsSymbol()) { if (filter == SKIP_SYMBOLS && value->IsSymbol()) {
continue; continue;
} }
accumulator->AddKey(value, prev_key_count); accumulator->AddKey(value, prev_key_count);
......
...@@ -102,7 +102,7 @@ class ElementsAccessor { ...@@ -102,7 +102,7 @@ class ElementsAccessor {
virtual void AddElementsToKeyAccumulator(Handle<JSObject> receiver, virtual void AddElementsToKeyAccumulator(Handle<JSObject> receiver,
KeyAccumulator* accumulator, KeyAccumulator* accumulator,
FixedArray::KeyFilter filter) = 0; KeyFilter filter) = 0;
// 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) {
......
...@@ -6759,11 +6759,10 @@ void KeyAccumulator::AddKey(Handle<Object> key, int check_limit) { ...@@ -6759,11 +6759,10 @@ void KeyAccumulator::AddKey(Handle<Object> key, int check_limit) {
} }
void KeyAccumulator::AddKeys(Handle<FixedArray> array, void KeyAccumulator::AddKeys(Handle<FixedArray> array, KeyFilter filter) {
FixedArray::KeyFilter filter) {
int add_length = array->length(); int add_length = array->length();
if (add_length == 0) return; if (add_length == 0) return;
if (keys_.is_null() && filter == FixedArray::ALL_KEYS) { if (keys_.is_null() && filter == INCLUDE_SYMBOLS) {
keys_ = array; keys_ = array;
length_ = keys_->length(); length_ = keys_->length();
return; return;
...@@ -6772,14 +6771,13 @@ void KeyAccumulator::AddKeys(Handle<FixedArray> array, ...@@ -6772,14 +6771,13 @@ void KeyAccumulator::AddKeys(Handle<FixedArray> array,
int previous_key_count = length_; int previous_key_count = length_;
for (int i = 0; i < add_length; i++) { for (int i = 0; i < add_length; i++) {
Handle<Object> current(array->get(i), isolate_); Handle<Object> current(array->get(i), isolate_);
if (filter == FixedArray::NON_SYMBOL_KEYS && current->IsSymbol()) continue; if (filter == SKIP_SYMBOLS && current->IsSymbol()) continue;
AddKey(current, previous_key_count); AddKey(current, previous_key_count);
} }
} }
void KeyAccumulator::AddKeys(Handle<JSObject> array_like, void KeyAccumulator::AddKeys(Handle<JSObject> array_like, KeyFilter filter) {
FixedArray::KeyFilter filter) {
DCHECK(array_like->IsJSArray() || array_like->HasSloppyArgumentsElements()); DCHECK(array_like->IsJSArray() || array_like->HasSloppyArgumentsElements());
ElementsAccessor* accessor = array_like->GetElementsAccessor(); ElementsAccessor* accessor = array_like->GetElementsAccessor();
accessor->AddElementsToKeyAccumulator(array_like, this, filter); accessor->AddElementsToKeyAccumulator(array_like, this, filter);
...@@ -6831,7 +6829,8 @@ void KeyAccumulator::Grow() { ...@@ -6831,7 +6829,8 @@ void KeyAccumulator::Grow() {
MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
KeyCollectionType type) { KeyCollectionType type,
KeyFilter filter) {
USE(ContainsOnlyValidKeys); USE(ContainsOnlyValidKeys);
Isolate* isolate = object->GetIsolate(); Isolate* isolate = object->GetIsolate();
KeyAccumulator accumulator(isolate); KeyAccumulator accumulator(isolate);
...@@ -6857,7 +6856,7 @@ MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, ...@@ -6857,7 +6856,7 @@ MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
arraysize(args), arraysize(args),
args), args),
FixedArray); FixedArray);
accumulator.AddKeys(Handle<JSObject>::cast(names), FixedArray::ALL_KEYS); accumulator.AddKeys(Handle<JSObject>::cast(names), filter);
break; break;
} }
...@@ -6876,7 +6875,7 @@ MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, ...@@ -6876,7 +6875,7 @@ MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
Handle<FixedArray> element_keys = Handle<FixedArray> element_keys =
isolate->factory()->NewFixedArray(current->NumberOfEnumElements()); isolate->factory()->NewFixedArray(current->NumberOfEnumElements());
current->GetEnumElementKeys(*element_keys); current->GetEnumElementKeys(*element_keys);
accumulator.AddKeys(element_keys, FixedArray::ALL_KEYS); accumulator.AddKeys(element_keys, filter);
DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
// Add the element keys from the interceptor. // Add the element keys from the interceptor.
...@@ -6884,38 +6883,49 @@ MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, ...@@ -6884,38 +6883,49 @@ MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
Handle<JSObject> result; Handle<JSObject> result;
if (JSObject::GetKeysForIndexedInterceptor( if (JSObject::GetKeysForIndexedInterceptor(
current, object).ToHandle(&result)) { current, object).ToHandle(&result)) {
accumulator.AddKeys(result, FixedArray::ALL_KEYS); accumulator.AddKeys(result, filter);
} }
DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
} }
// We can cache the computed property keys if access checks are if (filter == SKIP_SYMBOLS) {
// not needed and no interceptors are involved. // We can cache the computed property keys if access checks are
// // not needed and no interceptors are involved.
// We do not use the cache if the object has elements and //
// therefore it does not make sense to cache the property names // We do not use the cache if the object has elements and
// for arguments objects. Arguments objects will always have // therefore it does not make sense to cache the property names
// elements. // for arguments objects. Arguments objects will always have
// Wrapped strings have elements, but don't have an elements // elements.
// array or dictionary. So the fast inline test for whether to // Wrapped strings have elements, but don't have an elements
// use the cache says yes, so we should not create a cache. // array or dictionary. So the fast inline test for whether to
bool cache_enum_length = // use the cache says yes, so we should not create a cache.
((current->map()->GetConstructor() != *arguments_function) && bool cache_enum_length =
!current->IsJSValue() && !current->IsAccessCheckNeeded() && ((current->map()->GetConstructor() != *arguments_function) &&
!current->HasNamedInterceptor() && !current->HasIndexedInterceptor()); !current->IsJSValue() && !current->IsAccessCheckNeeded() &&
// Compute the property keys and cache them if possible. !current->HasNamedInterceptor() &&
!current->HasIndexedInterceptor());
Handle<FixedArray> enum_keys = // Compute the property keys and cache them if possible.
JSObject::GetEnumPropertyKeys(current, cache_enum_length);
accumulator.AddKeys(enum_keys, FixedArray::ALL_KEYS); Handle<FixedArray> enum_keys =
JSObject::GetEnumPropertyKeys(current, cache_enum_length);
accumulator.AddKeys(enum_keys, filter);
} else {
DCHECK(filter == INCLUDE_SYMBOLS);
PropertyAttributes attr_filter =
static_cast<PropertyAttributes>(DONT_ENUM | PRIVATE_SYMBOL);
Handle<FixedArray> property_keys = isolate->factory()->NewFixedArray(
current->NumberOfOwnProperties(attr_filter));
current->GetOwnPropertyNames(*property_keys, 0, attr_filter);
accumulator.AddKeys(property_keys, filter);
}
DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
// Add the non-symbol property keys from the interceptor. // Add the property keys from the interceptor.
if (current->HasNamedInterceptor()) { if (current->HasNamedInterceptor()) {
Handle<JSObject> result; Handle<JSObject> result;
if (JSObject::GetKeysForNamedInterceptor( if (JSObject::GetKeysForNamedInterceptor(
current, object).ToHandle(&result)) { current, object).ToHandle(&result)) {
accumulator.AddKeys(result, FixedArray::NON_SYMBOL_KEYS); accumulator.AddKeys(result, filter);
} }
DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
} }
...@@ -13833,13 +13843,8 @@ int JSObject::GetOwnPropertyNames(FixedArray* storage, int index, ...@@ -13833,13 +13843,8 @@ int JSObject::GetOwnPropertyNames(FixedArray* storage, int index,
int JSObject::NumberOfOwnElements(PropertyAttributes filter) { int JSObject::NumberOfOwnElements(PropertyAttributes filter) {
return GetOwnElementKeys(NULL, filter);
}
int JSObject::NumberOfEnumElements() {
// Fast case for objects with no elements. // Fast case for objects with no elements.
if (!IsJSValue() && HasFastObjectElements()) { if (!IsJSValue() && HasFastElements()) {
uint32_t length = IsJSArray() ? uint32_t length = IsJSArray() ?
static_cast<uint32_t>( static_cast<uint32_t>(
Smi::cast(JSArray::cast(this)->length())->value()) : Smi::cast(JSArray::cast(this)->length())->value()) :
...@@ -13847,6 +13852,11 @@ int JSObject::NumberOfEnumElements() { ...@@ -13847,6 +13852,11 @@ int JSObject::NumberOfEnumElements() {
if (length == 0) return 0; if (length == 0) return 0;
} }
// Compute the number of enumerable elements. // Compute the number of enumerable elements.
return GetOwnElementKeys(NULL, filter);
}
int JSObject::NumberOfEnumElements() {
return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM)); return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM));
} }
......
...@@ -1775,6 +1775,9 @@ enum AccessorComponent { ...@@ -1775,6 +1775,9 @@ enum AccessorComponent {
}; };
enum KeyFilter { SKIP_SYMBOLS, INCLUDE_SYMBOLS };
// JSReceiver includes types on which properties can be defined, i.e., // JSReceiver includes types on which properties can be defined, i.e.,
// JSObject and JSProxy. // JSObject and JSProxy.
class JSReceiver: public HeapObject { class JSReceiver: public HeapObject {
...@@ -1854,8 +1857,8 @@ class JSReceiver: public HeapObject { ...@@ -1854,8 +1857,8 @@ class JSReceiver: public HeapObject {
// Computes the enumerable keys for a JSObject. Used for implementing // Computes the enumerable keys for a JSObject. Used for implementing
// "for (n in object) { }". // "for (n in object) { }".
MUST_USE_RESULT static MaybeHandle<FixedArray> GetKeys( MUST_USE_RESULT static MaybeHandle<FixedArray> GetKeys(
Handle<JSReceiver> object, Handle<JSReceiver> object, KeyCollectionType type,
KeyCollectionType type); KeyFilter filter = SKIP_SYMBOLS);
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSReceiver); DISALLOW_IMPLICIT_CONSTRUCTORS(JSReceiver);
...@@ -2519,8 +2522,6 @@ class FixedArray: public FixedArrayBase { ...@@ -2519,8 +2522,6 @@ class FixedArray: public FixedArrayBase {
// Shrink length and insert filler objects. // Shrink length and insert filler objects.
void Shrink(int length); void Shrink(int length);
enum KeyFilter { ALL_KEYS, NON_SYMBOL_KEYS };
// Copy a sub array from the receiver to dest. // Copy a sub array from the receiver to dest.
void CopyTo(int pos, FixedArray* dest, int dest_pos, int len); void CopyTo(int pos, FixedArray* dest, int dest_pos, int len);
...@@ -10607,8 +10608,8 @@ class KeyAccumulator final BASE_EMBEDDED { ...@@ -10607,8 +10608,8 @@ class KeyAccumulator final BASE_EMBEDDED {
explicit KeyAccumulator(Isolate* isolate) : isolate_(isolate), length_(0) {} explicit KeyAccumulator(Isolate* isolate) : isolate_(isolate), length_(0) {}
void AddKey(Handle<Object> key, int check_limit); void AddKey(Handle<Object> key, int check_limit);
void AddKeys(Handle<FixedArray> array, FixedArray::KeyFilter filter); void AddKeys(Handle<FixedArray> array, KeyFilter filter);
void AddKeys(Handle<JSObject> array, FixedArray::KeyFilter filter); void AddKeys(Handle<JSObject> array, KeyFilter filter);
void PrepareForComparisons(int count); void PrepareForComparisons(int count);
Handle<FixedArray> GetKeys(); Handle<FixedArray> GetKeys();
......
...@@ -220,7 +220,7 @@ RUNTIME_FUNCTION(Runtime_GetArrayKeys) { ...@@ -220,7 +220,7 @@ RUNTIME_FUNCTION(Runtime_GetArrayKeys) {
Handle<FixedArray> current_keys = Handle<FixedArray> current_keys =
isolate->factory()->NewFixedArray(current->NumberOfOwnElements(NONE)); isolate->factory()->NewFixedArray(current->NumberOfOwnElements(NONE));
current->GetOwnElementKeys(*current_keys, NONE); current->GetOwnElementKeys(*current_keys, NONE);
accumulator.AddKeys(current_keys, FixedArray::ALL_KEYS); accumulator.AddKeys(current_keys, INCLUDE_SYMBOLS);
} }
// Erase any keys >= length. // Erase any keys >= length.
// TODO(adamk): Remove this step when the contract of %GetArrayKeys // TODO(adamk): Remove this step when the contract of %GetArrayKeys
......
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