Skip to content

Commit

Permalink
deps: V8: backport f7771e5b0cc4
Browse files Browse the repository at this point in the history
Original commit message:

    [runtime] Recompute enumeration indices of dictionaries upon bitfield overflow

    Otherwise we'll get weird semantics when enumerating objects after many
    deletes/reinserts.

    Bug: chromium:1033771
    Change-Id: If0a459169c3794a30d9632d09e80da3cfcd4302c
    Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1993966
    Commit-Queue: Toon Verwaest <verwaest@chromium.org>
    Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
    Reviewed-by: Victor Gomes <victorgomes@chromium.org>
    Cr-Commit-Position: refs/heads/master@{#65690}

Refs: v8/v8@f7771e5

PR-URL: #31957
Backport-PR-URL: #32053
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
  • Loading branch information
mmarchini authored and codebytere committed Mar 23, 2020
1 parent baf99da commit e6d08f9
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 42 deletions.
2 changes: 1 addition & 1 deletion common.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

# Reset this number to 0 on major V8 upgrades.
# Increment by one for each non-official patch applied to deps/v8.
'v8_embedder_string': '-node.31',
'v8_embedder_string': '-node.32',

##### V8 defaults for Node.js #####

Expand Down
11 changes: 11 additions & 0 deletions deps/v8/src/objects/dictionary-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ template <typename Derived, typename Shape>
BaseNameDictionary<Derived, Shape>::BaseNameDictionary(Address ptr)
: Dictionary<Derived, Shape>(ptr) {}

template <typename Derived, typename Shape>
void BaseNameDictionary<Derived, Shape>::set_next_enumeration_index(int index) {
DCHECK_LT(0, index);
this->set(kNextEnumerationIndexIndex, Smi::FromInt(index));
}

template <typename Derived, typename Shape>
int BaseNameDictionary<Derived, Shape>::next_enumeration_index() {
return Smi::ToInt(this->get(kNextEnumerationIndexIndex));
}

GlobalDictionary::GlobalDictionary(Address ptr)
: BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>(ptr) {
SLOW_DCHECK(IsGlobalDictionary());
Expand Down
21 changes: 7 additions & 14 deletions deps/v8/src/objects/dictionary.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,16 +140,6 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) BaseNameDictionary
static const int kObjectHashIndex = kNextEnumerationIndexIndex + 1;
static const int kEntryValueIndex = 1;

// Accessors for next enumeration index.
void SetNextEnumerationIndex(int index) {
DCHECK_NE(0, index);
this->set(kNextEnumerationIndexIndex, Smi::FromInt(index));
}

int NextEnumerationIndex() {
return Smi::ToInt(this->get(kNextEnumerationIndexIndex));
}

void SetHash(int hash) {
DCHECK(PropertyArray::HashField::is_valid(hash));
this->set(kObjectHashIndex, Smi::FromInt(hash));
Expand All @@ -173,6 +163,13 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) BaseNameDictionary
V8_WARN_UNUSED_RESULT static ExceptionStatus CollectKeysTo(
Handle<Derived> dictionary, KeyAccumulator* keys);

// Allocate the next enumeration index. Possibly updates all enumeration
// indices in the table.
static int NextEnumerationIndex(Isolate* isolate, Handle<Derived> dictionary);
// Accessors for next enumeration index.
inline int next_enumeration_index();
inline void set_next_enumeration_index(int index);

// Return the key indices sorted by its enumeration index.
static Handle<FixedArray> IterationIndices(Isolate* isolate,
Handle<Derived> dictionary);
Expand All @@ -184,10 +181,6 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) BaseNameDictionary
Handle<FixedArray> storage, KeyCollectionMode mode,
KeyAccumulator* accumulator);

// Ensure enough space for n additional elements.
static Handle<Derived> EnsureCapacity(Isolate* isolate,
Handle<Derived> dictionary, int n);

V8_WARN_UNUSED_RESULT static Handle<Derived> AddNoUpdateNextEnumerationIndex(
Isolate* isolate, Handle<Derived> dictionary, Key key,
Handle<Object> value, PropertyDetails details, int* entry_out = nullptr);
Expand Down
2 changes: 1 addition & 1 deletion deps/v8/src/objects/hash-table.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) HashTable

// Ensure enough space for n additional elements.
V8_WARN_UNUSED_RESULT static Handle<Derived> EnsureCapacity(
Isolate* isolate, Handle<Derived> table, int n,
Isolate* isolate, Handle<Derived> table, int n = 1,
AllocationType allocation = AllocationType::kYoung);

// Returns true if this table has sufficient capacity for adding n elements.
Expand Down
2 changes: 1 addition & 1 deletion deps/v8/src/objects/js-objects.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2885,7 +2885,7 @@ void MigrateFastToSlow(Isolate* isolate, Handle<JSObject> object,
}

// Copy the next enumeration index from instance descriptor.
dictionary->SetNextEnumerationIndex(real_size + 1);
dictionary->set_next_enumeration_index(real_size + 1);

// From here on we cannot fail and we shouldn't GC anymore.
DisallowHeapAllocation no_allocation;
Expand Down
2 changes: 1 addition & 1 deletion deps/v8/src/objects/literal-objects.cc
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ class ObjectDescriptor {

void Finalize(Isolate* isolate) {
if (HasDictionaryProperties()) {
properties_dictionary_template_->SetNextEnumerationIndex(
properties_dictionary_template_->set_next_enumeration_index(
next_enumeration_index_);
computed_properties_ = FixedArray::ShrinkOrEmpty(
isolate, computed_properties_, current_computed_index_);
Expand Down
4 changes: 2 additions & 2 deletions deps/v8/src/objects/lookup.cc
Original file line number Diff line number Diff line change
Expand Up @@ -634,8 +634,8 @@ void LookupIterator::PrepareTransitionToDataProperty(
transition_ = cell;
// Assign an enumeration index to the property and update
// SetNextEnumerationIndex.
int index = dictionary->NextEnumerationIndex();
dictionary->SetNextEnumerationIndex(index + 1);
int index = GlobalDictionary::NextEnumerationIndex(isolate_, dictionary);
dictionary->set_next_enumeration_index(index + 1);
property_details_ = PropertyDetails(
kData, attributes, PropertyCellType::kUninitialized, index);
PropertyCellType new_type =
Expand Down
46 changes: 24 additions & 22 deletions deps/v8/src/objects/objects.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6663,7 +6663,7 @@ void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
int expected) {
Handle<StringTable> table = isolate->factory()->string_table();
// We need a key instance for the virtual hash function.
table = StringTable::EnsureCapacity(isolate, table, expected);
table = EnsureCapacity(isolate, table, expected);
isolate->heap()->SetRootStringTable(*table);
}

Expand Down Expand Up @@ -6715,7 +6715,7 @@ Handle<String> StringTable::LookupKey(Isolate* isolate, StringTableKey* key) {

table = StringTable::CautiousShrink(isolate, table);
// Adding new string. Grow table if needed.
table = StringTable::EnsureCapacity(isolate, table, 1);
table = EnsureCapacity(isolate, table);
isolate->heap()->SetRootStringTable(*table);

return AddKeyNoResize(isolate, key);
Expand Down Expand Up @@ -6856,7 +6856,7 @@ Handle<StringSet> StringSet::New(Isolate* isolate) {
Handle<StringSet> StringSet::Add(Isolate* isolate, Handle<StringSet> stringset,
Handle<String> name) {
if (!stringset->Has(isolate, name)) {
stringset = EnsureCapacity(isolate, stringset, 1);
stringset = EnsureCapacity(isolate, stringset);
uint32_t hash = ShapeT::Hash(isolate, *name);
int entry = stringset->FindInsertionEntry(hash);
stringset->set(EntryToIndex(entry), *name);
Expand All @@ -6874,7 +6874,7 @@ Handle<ObjectHashSet> ObjectHashSet::Add(Isolate* isolate,
Handle<Object> key) {
int32_t hash = key->GetOrCreateHash(isolate).value();
if (!set->Has(isolate, key, hash)) {
set = EnsureCapacity(isolate, set, 1);
set = EnsureCapacity(isolate, set);
int entry = set->FindInsertionEntry(hash);
set->set(EntryToIndex(entry), *key);
set->ElementAdded();
Expand Down Expand Up @@ -7070,7 +7070,7 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutScript(
src = String::Flatten(isolate, src);
StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
Handle<Object> k = key.AsHandle(isolate);
cache = EnsureCapacity(isolate, cache, 1);
cache = EnsureCapacity(isolate, cache);
int entry = cache->FindInsertionEntry(key.Hash());
cache->set(EntryToIndex(entry), *k);
cache->set(EntryToIndex(entry) + 1, *value);
Expand Down Expand Up @@ -7102,7 +7102,7 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
}
}

cache = EnsureCapacity(isolate, cache, 1);
cache = EnsureCapacity(isolate, cache);
int entry = cache->FindInsertionEntry(key.Hash());
Handle<Object> k =
isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
Expand All @@ -7116,7 +7116,7 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
Isolate* isolate, Handle<CompilationCacheTable> cache, Handle<String> src,
JSRegExp::Flags flags, Handle<FixedArray> value) {
RegExpKey key(src, flags);
cache = EnsureCapacity(isolate, cache, 1);
cache = EnsureCapacity(isolate, cache);
int entry = cache->FindInsertionEntry(key.Hash());
// We store the value in the key slot, and compare the search key
// to the stored value with a custon IsMatch function during lookups.
Expand Down Expand Up @@ -7178,15 +7178,16 @@ Handle<Derived> BaseNameDictionary<Derived, Shape>::New(
Handle<Derived> dict = Dictionary<Derived, Shape>::New(
isolate, at_least_space_for, allocation, capacity_option);
dict->SetHash(PropertyArray::kNoHashSentinel);
dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
dict->set_next_enumeration_index(PropertyDetails::kInitialIndex);
return dict;
}

template <typename Derived, typename Shape>
Handle<Derived> BaseNameDictionary<Derived, Shape>::EnsureCapacity(
Isolate* isolate, Handle<Derived> dictionary, int n) {
// Check whether there are enough enumeration indices to add n elements.
if (!PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) {
int BaseNameDictionary<Derived, Shape>::NextEnumerationIndex(
Isolate* isolate, Handle<Derived> dictionary) {
int index = dictionary->next_enumeration_index();
// Check whether the next enumeration index is valid.
if (!PropertyDetails::IsValidIndex(index)) {
// If not, we generate new indices for the properties.
int length = dictionary->NumberOfElements();

Expand All @@ -7207,11 +7208,12 @@ Handle<Derived> BaseNameDictionary<Derived, Shape>::EnsureCapacity(
dictionary->DetailsAtPut(isolate, index, new_details);
}

// Set the next enumeration index.
dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex +
length);
index = PropertyDetails::kInitialIndex + length;
}
return HashTable<Derived, Shape>::EnsureCapacity(isolate, dictionary, n);

// Don't update the next enumeration index here, since we might be looking at
// an immutable empty dictionary.
return index;
}

template <typename Derived, typename Shape>
Expand Down Expand Up @@ -7260,13 +7262,13 @@ Handle<Derived> BaseNameDictionary<Derived, Shape>::Add(
DCHECK_EQ(0, details.dictionary_index());
// Assign an enumeration index to the property and update
// SetNextEnumerationIndex.
int index = dictionary->NextEnumerationIndex();
int index = Derived::NextEnumerationIndex(isolate, dictionary);
details = details.set_index(index);
dictionary = AddNoUpdateNextEnumerationIndex(isolate, dictionary, key, value,
details, entry_out);
// Update enumeration index here in order to avoid potential modification of
// the canonical empty dictionary which lives in read only space.
dictionary->SetNextEnumerationIndex(index + 1);
dictionary->set_next_enumeration_index(index + 1);
return dictionary;
}

Expand All @@ -7280,7 +7282,7 @@ Handle<Derived> Dictionary<Derived, Shape>::Add(Isolate* isolate,
// Valdate key is absent.
SLOW_DCHECK((dictionary->FindEntry(isolate, key) == Dictionary::kNotFound));
// Check whether the dictionary should be extended.
dictionary = Derived::EnsureCapacity(isolate, dictionary, 1);
dictionary = Derived::EnsureCapacity(isolate, dictionary);

// Compute the key object.
Handle<Object> k = Shape::AsHandle(isolate, key);
Expand Down Expand Up @@ -7625,7 +7627,7 @@ Handle<Derived> ObjectHashTableBase<Derived, Shape>::Put(Isolate* isolate,
}

// Check whether the hash table should be extended.
table = Derived::EnsureCapacity(isolate, table, 1);
table = Derived::EnsureCapacity(isolate, table);
table->AddEntry(table->FindInsertionEntry(hash), *key, *value);
return table;
}
Expand Down Expand Up @@ -7873,8 +7875,8 @@ Handle<PropertyCell> PropertyCell::PrepareForValue(
// Preserve the enumeration index unless the property was deleted or never
// initialized.
if (cell->value().IsTheHole(isolate)) {
index = dictionary->NextEnumerationIndex();
dictionary->SetNextEnumerationIndex(index + 1);
index = GlobalDictionary::NextEnumerationIndex(isolate, dictionary);
dictionary->set_next_enumeration_index(index + 1);
} else {
index = original_details.dictionary_index();
}
Expand Down

0 comments on commit e6d08f9

Please sign in to comment.