Commit f6e3c9cd authored by Camillo Bruni's avatar Camillo Bruni Committed by Commit Bot

[runtime] Do not handle shadowing keys in CollectKeysTo

Make it explicit that AddShadowingKeys might allocate.

Bug: chromium:1049013
Change-Id: I938531a0324fa581422b74813518f3e85c9b3fbb
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2046888
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66288}
parent fb7f0519
...@@ -1549,11 +1549,13 @@ class DictionaryElementsAccessor ...@@ -1549,11 +1549,13 @@ class DictionaryElementsAccessor
PropertyFilter filter = keys->filter(); PropertyFilter filter = keys->filter();
ReadOnlyRoots roots(isolate); ReadOnlyRoots roots(isolate);
for (InternalIndex i : dictionary->IterateEntries()) { for (InternalIndex i : dictionary->IterateEntries()) {
AllowHeapAllocation allow_gc;
Object raw_key = dictionary->KeyAt(i); Object raw_key = dictionary->KeyAt(i);
if (!dictionary->IsKey(roots, raw_key)) continue; if (!dictionary->IsKey(roots, raw_key)) continue;
uint32_t key = FilterKey(dictionary, i, raw_key, filter); uint32_t key = FilterKey(dictionary, i, raw_key, filter);
if (key == kMaxUInt32) { if (key == kMaxUInt32) {
keys->AddShadowingKey(raw_key); // This might allocate, but {raw_key} is not used afterwards.
keys->AddShadowingKey(raw_key, &allow_gc);
continue; continue;
} }
elements->set(insertion_index, raw_key); elements->set(insertion_index, raw_key);
......
...@@ -281,7 +281,8 @@ bool KeyAccumulator::IsShadowed(Handle<Object> key) { ...@@ -281,7 +281,8 @@ bool KeyAccumulator::IsShadowed(Handle<Object> key) {
return shadowing_keys_->Has(isolate_, key); return shadowing_keys_->Has(isolate_, key);
} }
void KeyAccumulator::AddShadowingKey(Object key) { void KeyAccumulator::AddShadowingKey(Object key,
AllowHeapAllocation* allow_gc) {
if (mode_ == KeyCollectionMode::kOwnOnly) return; if (mode_ == KeyCollectionMode::kOwnOnly) return;
AddShadowingKey(handle(key, isolate_)); AddShadowingKey(handle(key, isolate_));
} }
...@@ -737,6 +738,7 @@ template <bool skip_symbols> ...@@ -737,6 +738,7 @@ template <bool skip_symbols>
base::Optional<int> CollectOwnPropertyNamesInternal( base::Optional<int> CollectOwnPropertyNamesInternal(
Handle<JSObject> object, KeyAccumulator* keys, Handle<JSObject> object, KeyAccumulator* keys,
Handle<DescriptorArray> descs, int start_index, int limit) { Handle<DescriptorArray> descs, int start_index, int limit) {
AllowHeapAllocation allow_gc;
int first_skipped = -1; int first_skipped = -1;
PropertyFilter filter = keys->filter(); PropertyFilter filter = keys->filter();
KeyCollectionMode mode = keys->mode(); KeyCollectionMode mode = keys->mode();
...@@ -767,7 +769,9 @@ base::Optional<int> CollectOwnPropertyNamesInternal( ...@@ -767,7 +769,9 @@ base::Optional<int> CollectOwnPropertyNamesInternal(
if (key.FilterKey(keys->filter())) continue; if (key.FilterKey(keys->filter())) continue;
if (is_shadowing_key) { if (is_shadowing_key) {
keys->AddShadowingKey(key); // This might allocate, but {key} is not used afterwards.
keys->AddShadowingKey(key, &allow_gc);
continue;
} else { } else {
if (keys->AddKey(key, DO_NOT_CONVERT) != ExceptionStatus::kSuccess) { if (keys->AddKey(key, DO_NOT_CONVERT) != ExceptionStatus::kSuccess) {
return base::Optional<int>(); return base::Optional<int>();
...@@ -806,13 +810,13 @@ Maybe<bool> KeyAccumulator::CollectOwnPropertyNames(Handle<JSReceiver> receiver, ...@@ -806,13 +810,13 @@ Maybe<bool> KeyAccumulator::CollectOwnPropertyNames(Handle<JSReceiver> receiver,
int nof_descriptors = map.NumberOfOwnDescriptors(); int nof_descriptors = map.NumberOfOwnDescriptors();
if (enum_keys->length() != nof_descriptors) { if (enum_keys->length() != nof_descriptors) {
if (map.prototype(isolate_) != ReadOnlyRoots(isolate_).null_value()) { if (map.prototype(isolate_) != ReadOnlyRoots(isolate_).null_value()) {
AllowHeapAllocation allow_gc;
Handle<DescriptorArray> descs = Handle<DescriptorArray> descs =
Handle<DescriptorArray>(map.instance_descriptors(), isolate_); Handle<DescriptorArray>(map.instance_descriptors(), isolate_);
for (InternalIndex i : InternalIndex::Range(nof_descriptors)) { for (InternalIndex i : InternalIndex::Range(nof_descriptors)) {
PropertyDetails details = descs->GetDetails(i); PropertyDetails details = descs->GetDetails(i);
if (!details.IsDontEnum()) continue; if (!details.IsDontEnum()) continue;
Object key = descs->GetKey(i); this->AddShadowingKey(descs->GetKey(i), &allow_gc);
this->AddShadowingKey(key);
} }
} }
} }
...@@ -866,6 +870,7 @@ Maybe<bool> KeyAccumulator::CollectOwnPropertyNames(Handle<JSReceiver> receiver, ...@@ -866,6 +870,7 @@ Maybe<bool> KeyAccumulator::CollectOwnPropertyNames(Handle<JSReceiver> receiver,
ExceptionStatus KeyAccumulator::CollectPrivateNames(Handle<JSReceiver> receiver, ExceptionStatus KeyAccumulator::CollectPrivateNames(Handle<JSReceiver> receiver,
Handle<JSObject> object) { Handle<JSObject> object) {
DCHECK_EQ(mode_, KeyCollectionMode::kOwnOnly);
if (object->HasFastProperties()) { if (object->HasFastProperties()) {
int limit = object->map().NumberOfOwnDescriptors(); int limit = object->map().NumberOfOwnDescriptors();
Handle<DescriptorArray> descs(object->map().instance_descriptors(), Handle<DescriptorArray> descs(object->map().instance_descriptors(),
......
...@@ -103,7 +103,7 @@ class KeyAccumulator final { ...@@ -103,7 +103,7 @@ class KeyAccumulator final {
void set_may_have_elements(bool value) { may_have_elements_ = value; } void set_may_have_elements(bool value) { may_have_elements_ = value; }
// Shadowing keys are used to filter keys. This happens when non-enumerable // Shadowing keys are used to filter keys. This happens when non-enumerable
// keys appear again on the prototype chain. // keys appear again on the prototype chain.
void AddShadowingKey(Object key); void AddShadowingKey(Object key, AllowHeapAllocation* allow_gc);
void AddShadowingKey(Handle<Object> key); void AddShadowingKey(Handle<Object> key);
private: private:
......
...@@ -7443,41 +7443,47 @@ void BaseNameDictionary<Derived, Shape>::CopyEnumKeysTo( ...@@ -7443,41 +7443,47 @@ void BaseNameDictionary<Derived, Shape>::CopyEnumKeysTo(
int length = storage->length(); int length = storage->length();
int properties = 0; int properties = 0;
ReadOnlyRoots roots(isolate); ReadOnlyRoots roots(isolate);
for (InternalIndex i : dictionary->IterateEntries()) { {
Object key; AllowHeapAllocation allow_gc;
if (!dictionary->ToKey(roots, i, &key)) continue; for (InternalIndex i : dictionary->IterateEntries()) {
bool is_shadowing_key = false; Object key;
if (key.IsSymbol()) continue; if (!dictionary->ToKey(roots, i, &key)) continue;
PropertyDetails details = dictionary->DetailsAt(i); bool is_shadowing_key = false;
if (details.IsDontEnum()) { if (key.IsSymbol()) continue;
if (mode == KeyCollectionMode::kIncludePrototypes) { PropertyDetails details = dictionary->DetailsAt(i);
is_shadowing_key = true; if (details.IsDontEnum()) {
} else { if (mode == KeyCollectionMode::kIncludePrototypes) {
is_shadowing_key = true;
} else {
continue;
}
}
if (is_shadowing_key) {
// This might allocate, but {key} is not used afterwards.
accumulator->AddShadowingKey(key, &allow_gc);
continue; continue;
} else {
storage->set(properties, Smi::FromInt(i.as_int()));
} }
properties++;
if (mode == KeyCollectionMode::kOwnOnly && properties == length) break;
} }
if (is_shadowing_key) {
accumulator->AddShadowingKey(key);
continue;
} else {
storage->set(properties, Smi::FromInt(i.as_int()));
}
properties++;
if (mode == KeyCollectionMode::kOwnOnly && properties == length) break;
} }
CHECK_EQ(length, properties); CHECK_EQ(length, properties);
DisallowHeapAllocation no_gc; {
Derived raw_dictionary = *dictionary; DisallowHeapAllocation no_gc;
FixedArray raw_storage = *storage; Derived raw_dictionary = *dictionary;
EnumIndexComparator<Derived> cmp(raw_dictionary); FixedArray raw_storage = *storage;
// Use AtomicSlot wrapper to ensure that std::sort uses atomic load and EnumIndexComparator<Derived> cmp(raw_dictionary);
// store operations that are safe for concurrent marking. // Use AtomicSlot wrapper to ensure that std::sort uses atomic load and
AtomicSlot start(storage->GetFirstElementAddress()); // store operations that are safe for concurrent marking.
std::sort(start, start + length, cmp); AtomicSlot start(storage->GetFirstElementAddress());
for (int i = 0; i < length; i++) { std::sort(start, start + length, cmp);
InternalIndex index(Smi::ToInt(raw_storage.get(i))); for (int i = 0; i < length; i++) {
raw_storage.set(i, raw_dictionary.NameAt(index)); InternalIndex index(Smi::ToInt(raw_storage.get(i)));
raw_storage.set(i, raw_dictionary.NameAt(index));
}
} }
} }
...@@ -7518,16 +7524,20 @@ ExceptionStatus BaseNameDictionary<Derived, Shape>::CollectKeysTo( ...@@ -7518,16 +7524,20 @@ ExceptionStatus BaseNameDictionary<Derived, Shape>::CollectKeysTo(
isolate->factory()->NewFixedArray(dictionary->NumberOfElements()); isolate->factory()->NewFixedArray(dictionary->NumberOfElements());
int array_size = 0; int array_size = 0;
PropertyFilter filter = keys->filter(); PropertyFilter filter = keys->filter();
// Handle enumerable strings in CopyEnumKeysTo.
DCHECK_NE(keys->filter(), ENUMERABLE_STRINGS);
{ {
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
Derived raw_dictionary = *dictionary;
for (InternalIndex i : dictionary->IterateEntries()) { for (InternalIndex i : dictionary->IterateEntries()) {
Object k; Object key;
if (!raw_dictionary.ToKey(roots, i, &k)) continue; Derived raw_dictionary = *dictionary;
if (k.FilterKey(filter)) continue; if (!raw_dictionary.ToKey(roots, i, &key)) continue;
if (key.FilterKey(filter)) continue;
PropertyDetails details = raw_dictionary.DetailsAt(i); PropertyDetails details = raw_dictionary.DetailsAt(i);
if ((details.attributes() & filter) != 0) { if ((details.attributes() & filter) != 0) {
keys->AddShadowingKey(k); AllowHeapAllocation gc;
// This might allocate, but {key} is not used afterwards.
keys->AddShadowingKey(key, &gc);
continue; continue;
} }
if (filter & ONLY_ALL_CAN_READ) { if (filter & ONLY_ALL_CAN_READ) {
...@@ -7539,7 +7549,7 @@ ExceptionStatus BaseNameDictionary<Derived, Shape>::CollectKeysTo( ...@@ -7539,7 +7549,7 @@ ExceptionStatus BaseNameDictionary<Derived, Shape>::CollectKeysTo(
array->set(array_size++, Smi::FromInt(i.as_int())); array->set(array_size++, Smi::FromInt(i.as_int()));
} }
EnumIndexComparator<Derived> cmp(raw_dictionary); EnumIndexComparator<Derived> cmp(*dictionary);
// Use AtomicSlot wrapper to ensure that std::sort uses atomic load and // Use AtomicSlot wrapper to ensure that std::sort uses atomic load and
// store operations that are safe for concurrent marking. // store operations that are safe for concurrent marking.
AtomicSlot start(array->GetFirstElementAddress()); AtomicSlot start(array->GetFirstElementAddress());
......
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