Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(440)

Unified Diff: src/keys.cc

Issue 2081733002: [keys] support shadowing keys in the KeyAccumulator (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebasing Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/keys.h ('k') | src/messages.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/keys.cc
diff --git a/src/keys.cc b/src/keys.cc
index 793460c6455c24b7d27462d56c6189a02c510477..6d882663d78c18892376193616b6d22fcab51591 100644
--- a/src/keys.cc
+++ b/src/keys.cc
@@ -69,6 +69,7 @@ void KeyAccumulator::AddKey(Handle<Object> key, AddKeyConversion convert) {
} else if (filter_ & SKIP_STRINGS) {
return;
}
+ if (IsShadowed(key)) return;
if (keys_.is_null()) {
keys_ = OrderedHashSet::Allocate(isolate_, 16);
}
@@ -96,13 +97,15 @@ void KeyAccumulator::AddKeys(Handle<JSObject> array_like,
accessor->AddElementsToKeyAccumulator(array_like, this, convert);
}
-MaybeHandle<FixedArray> FilterProxyKeys(Isolate* isolate, Handle<JSProxy> owner,
+MaybeHandle<FixedArray> FilterProxyKeys(KeyAccumulator* accumulator,
+ Handle<JSProxy> owner,
Handle<FixedArray> keys,
PropertyFilter filter) {
if (filter == ALL_PROPERTIES) {
// Nothing to do.
return keys;
}
+ Isolate* isolate = accumulator->isolate();
int store_position = 0;
for (int i = 0; i < keys->length(); ++i) {
Handle<Name> key(Name::cast(keys->get(i)), isolate);
@@ -112,7 +115,11 @@ MaybeHandle<FixedArray> FilterProxyKeys(Isolate* isolate, Handle<JSProxy> owner,
Maybe<bool> found =
JSProxy::GetOwnPropertyDescriptor(isolate, owner, key, &desc);
MAYBE_RETURN(found, MaybeHandle<FixedArray>());
- if (!found.FromJust() || !desc.enumerable()) continue; // Skip this key.
+ if (!found.FromJust()) continue;
+ if (!desc.enumerable()) {
+ accumulator->AddShadowKey(key);
+ continue;
+ }
}
// Keep this key.
if (store_position != i) {
@@ -131,7 +138,7 @@ Maybe<bool> KeyAccumulator::AddKeysFromJSProxy(Handle<JSProxy> proxy,
if (filter_proxy_keys_) {
DCHECK(!is_for_in_);
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate_, keys, FilterProxyKeys(isolate_, proxy, keys, filter_),
+ isolate_, keys, FilterProxyKeys(this, proxy, keys, filter_),
Nothing<bool>());
}
if (mode_ == KeyCollectionMode::kOwnOnly && !is_for_in_) {
@@ -183,6 +190,23 @@ Maybe<bool> KeyAccumulator::CollectKeys(Handle<JSReceiver> receiver,
return Just(true);
}
+bool KeyAccumulator::IsShadowed(Handle<Object> key) {
+ if (shadowed_keys_.is_null()) return false;
+ return shadowed_keys_->Has(isolate_, key);
+}
+
+void KeyAccumulator::AddShadowKey(Object* key) {
+ if (mode_ == KeyCollectionMode::kOwnOnly) return;
+ AddShadowKey(handle(key, isolate_));
+}
+void KeyAccumulator::AddShadowKey(Handle<Object> key) {
+ if (mode_ == KeyCollectionMode::kOwnOnly) return;
+ if (shadowed_keys_.is_null()) {
+ shadowed_keys_ = ObjectHashSet::New(isolate_, 16);
+ }
+ shadowed_keys_ = ObjectHashSet::Add(shadowed_keys_, key);
+}
+
namespace {
void TrySettingEmptyEnumCache(JSReceiver* object) {
@@ -329,7 +353,7 @@ Handle<FixedArray> GetOwnKeysWithElements(Isolate* isolate,
keys = GetFastEnumPropertyKeys(isolate, object);
} else {
// TODO(cbruni): preallocate big enough array to also hold elements.
- keys = KeyAccumulator::GetEnumPropertyKeys(isolate, object);
+ keys = KeyAccumulator::GetOwnEnumPropertyKeys(isolate, object);
}
Handle<FixedArray> result =
accessor->PrependElementIndices(object, keys, convert, ONLY_ENUMERABLE);
@@ -495,33 +519,87 @@ int CollectOwnPropertyNamesInternal(Handle<JSObject> object,
Handle<DescriptorArray> descs,
int start_index, int limit) {
int first_skipped = -1;
+ PropertyFilter filter = keys->filter();
+ KeyCollectionMode mode = keys->mode();
for (int i = start_index; i < limit; i++) {
+ bool is_shadowing_key = false;
PropertyDetails details = descs->GetDetails(i);
- if ((details.attributes() & keys->filter()) != 0) continue;
- if (keys->filter() & ONLY_ALL_CAN_READ) {
+
+ if ((details.attributes() & filter) != 0) {
+ if (mode == KeyCollectionMode::kIncludePrototypes) {
+ is_shadowing_key = true;
+ } else {
+ continue;
+ }
+ }
+
+ if (filter & ONLY_ALL_CAN_READ) {
if (details.kind() != kAccessor) continue;
Object* accessors = descs->GetValue(i);
if (!accessors->IsAccessorInfo()) continue;
if (!AccessorInfo::cast(accessors)->all_can_read()) continue;
}
+
Name* key = descs->GetKey(i);
if (skip_symbols == key->IsSymbol()) {
if (first_skipped == -1) first_skipped = i;
continue;
}
if (key->FilterKey(keys->filter())) continue;
- keys->AddKey(key, DO_NOT_CONVERT);
+
+ if (is_shadowing_key) {
+ keys->AddShadowKey(key);
+ } else {
+ keys->AddKey(key, DO_NOT_CONVERT);
+ }
}
return first_skipped;
}
+template <class T>
+Handle<FixedArray> GetOwnEnumPropertyDictionaryKeys(Isolate* isolate,
+ KeyCollectionMode mode,
+ KeyAccumulator* accumulator,
+ Handle<JSObject> object,
+ T* raw_dictionary) {
+ Handle<T> dictionary(raw_dictionary, isolate);
+ int length = dictionary->NumberOfEnumElements();
+ if (length == 0) {
+ return isolate->factory()->empty_fixed_array();
+ }
+ Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
+ T::CopyEnumKeysTo(dictionary, storage, mode, accumulator);
+ return storage;
+}
} // namespace
Maybe<bool> KeyAccumulator::CollectOwnPropertyNames(Handle<JSReceiver> receiver,
Handle<JSObject> object) {
if (filter_ == ENUMERABLE_STRINGS) {
- Handle<FixedArray> enum_keys =
- KeyAccumulator::GetEnumPropertyKeys(isolate_, object);
+ Handle<FixedArray> enum_keys;
+ if (object->HasFastProperties()) {
+ enum_keys = KeyAccumulator::GetOwnEnumPropertyKeys(isolate_, object);
+ // If the number of properties equals the length of enumerable properties
+ // we do not have to filter out non-enumerable ones
+ Map* map = object->map();
+ int nof_descriptors = map->NumberOfOwnDescriptors();
+ if (enum_keys->length() != nof_descriptors) {
+ Handle<DescriptorArray> descs =
+ Handle<DescriptorArray>(map->instance_descriptors(), isolate_);
+ for (int i = 0; i < nof_descriptors; i++) {
+ PropertyDetails details = descs->GetDetails(i);
+ if (!details.IsDontEnum()) continue;
+ Object* key = descs->GetKey(i);
+ this->AddShadowKey(key);
+ }
+ }
+ } else if (object->IsJSGlobalObject()) {
+ enum_keys = GetOwnEnumPropertyDictionaryKeys(
+ isolate_, mode_, this, object, object->global_dictionary());
+ } else {
+ enum_keys = GetOwnEnumPropertyDictionaryKeys(
+ isolate_, mode_, this, object, object->property_dictionary());
+ }
AddKeys(enum_keys, DO_NOT_CONVERT);
} else {
if (object->HasFastProperties()) {
@@ -538,10 +616,10 @@ Maybe<bool> KeyAccumulator::CollectOwnPropertyNames(Handle<JSReceiver> receiver,
}
} else if (object->IsJSGlobalObject()) {
GlobalDictionary::CollectKeysTo(
- handle(object->global_dictionary(), isolate_), this, filter_);
+ handle(object->global_dictionary(), isolate_), this);
} else {
NameDictionary::CollectKeysTo(
- handle(object->property_dictionary(), isolate_), this, filter_);
+ handle(object->property_dictionary(), isolate_), this);
}
}
// Add the property keys from the interceptor.
@@ -608,28 +686,18 @@ Maybe<bool> KeyAccumulator::CollectOwnKeys(Handle<JSReceiver> receiver,
}
// static
-Handle<FixedArray> KeyAccumulator::GetEnumPropertyKeys(
+Handle<FixedArray> KeyAccumulator::GetOwnEnumPropertyKeys(
Isolate* isolate, Handle<JSObject> object) {
if (object->HasFastProperties()) {
return GetFastEnumPropertyKeys(isolate, object);
} else if (object->IsJSGlobalObject()) {
- Handle<GlobalDictionary> dictionary(object->global_dictionary(), isolate);
- int length = dictionary->NumberOfEnumElements();
- if (length == 0) {
- return isolate->factory()->empty_fixed_array();
- }
- Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
- dictionary->CopyEnumKeysTo(*storage);
- return storage;
+ return GetOwnEnumPropertyDictionaryKeys(
+ isolate, KeyCollectionMode::kOwnOnly, nullptr, object,
+ object->global_dictionary());
} else {
- Handle<NameDictionary> dictionary(object->property_dictionary(), isolate);
- int length = dictionary->NumberOfEnumElements();
- if (length == 0) {
- return isolate->factory()->empty_fixed_array();
- }
- Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
- dictionary->CopyEnumKeysTo(*storage);
- return storage;
+ return GetOwnEnumPropertyDictionaryKeys(
+ isolate, KeyCollectionMode::kOwnOnly, nullptr, object,
+ object->property_dictionary());
}
}
« no previous file with comments | « src/keys.h ('k') | src/messages.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698