From d47ad3ef7d19cc11f6306176329e8ff049f63e4f Mon Sep 17 00:00:00 2001 From: Matheus Marchini Date: Tue, 25 Feb 2020 16:00:48 -0800 Subject: [PATCH] deps: V8: backport f7771e5b0cc4 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 Reviewed-by: Jakob Kummerow Reviewed-by: Victor Gomes Cr-Commit-Position: refs/heads/master@{#65690} Refs: https://github.com/v8/v8/commit/f7771e5b0cc46ab75fe5291482a727b3f115dcba --- common.gypi | 2 +- deps/v8/src/objects/dictionary-inl.h | 6 ++-- deps/v8/src/objects/dictionary.h | 15 ++++----- deps/v8/src/objects/hash-table.h | 2 +- deps/v8/src/objects/js-objects.cc | 2 +- deps/v8/src/objects/literal-objects.cc | 2 +- deps/v8/src/objects/lookup.cc | 4 +-- deps/v8/src/objects/objects.cc | 46 ++++++++++++++------------ 8 files changed, 40 insertions(+), 39 deletions(-) diff --git a/common.gypi b/common.gypi index 0f52e138ca2fe0..a867e925945ce4 100644 --- a/common.gypi +++ b/common.gypi @@ -39,7 +39,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.29', + 'v8_embedder_string': '-node.30', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/objects/dictionary-inl.h b/deps/v8/src/objects/dictionary-inl.h index 18b2ee67a4db59..3a5b8cb3c7e201 100644 --- a/deps/v8/src/objects/dictionary-inl.h +++ b/deps/v8/src/objects/dictionary-inl.h @@ -61,13 +61,13 @@ BaseNameDictionary::BaseNameDictionary(Address ptr) : Dictionary(ptr) {} template -void BaseNameDictionary::SetNextEnumerationIndex(int index) { - DCHECK_NE(0, index); +void BaseNameDictionary::set_next_enumeration_index(int index) { + DCHECK_LT(0, index); this->set(kNextEnumerationIndexIndex, Smi::FromInt(index)); } template -int BaseNameDictionary::NextEnumerationIndex() { +int BaseNameDictionary::next_enumeration_index() { return Smi::ToInt(this->get(kNextEnumerationIndexIndex)); } diff --git a/deps/v8/src/objects/dictionary.h b/deps/v8/src/objects/dictionary.h index 35137c7d945430..eb15a77e33e63b 100644 --- a/deps/v8/src/objects/dictionary.h +++ b/deps/v8/src/objects/dictionary.h @@ -120,10 +120,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. - inline void SetNextEnumerationIndex(int index); - inline int NextEnumerationIndex(); - inline void SetHash(int hash); inline int Hash() const; @@ -138,6 +134,13 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) BaseNameDictionary V8_WARN_UNUSED_RESULT static ExceptionStatus CollectKeysTo( Handle dictionary, KeyAccumulator* keys); + // Allocate the next enumeration index. Possibly updates all enumeration + // indices in the table. + static int NextEnumerationIndex(Isolate* isolate, Handle 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 IterationIndices(Isolate* isolate, Handle dictionary); @@ -149,10 +152,6 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) BaseNameDictionary Handle storage, KeyCollectionMode mode, KeyAccumulator* accumulator); - // Ensure enough space for n additional elements. - static Handle EnsureCapacity(Isolate* isolate, - Handle dictionary, int n); - V8_WARN_UNUSED_RESULT static Handle AddNoUpdateNextEnumerationIndex( Isolate* isolate, Handle dictionary, Key key, Handle value, PropertyDetails details, int* entry_out = nullptr); diff --git a/deps/v8/src/objects/hash-table.h b/deps/v8/src/objects/hash-table.h index 5cdeb0c0ec4f9d..32013e58e56a6d 100644 --- a/deps/v8/src/objects/hash-table.h +++ b/deps/v8/src/objects/hash-table.h @@ -201,7 +201,7 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) HashTable // Ensure enough space for n additional elements. V8_WARN_UNUSED_RESULT static Handle EnsureCapacity( - Isolate* isolate, Handle table, int n, + Isolate* isolate, Handle table, int n = 1, AllocationType allocation = AllocationType::kYoung); // Returns true if this table has sufficient capacity for adding n elements. diff --git a/deps/v8/src/objects/js-objects.cc b/deps/v8/src/objects/js-objects.cc index ea0917f18feb10..4b1d9a4c862246 100644 --- a/deps/v8/src/objects/js-objects.cc +++ b/deps/v8/src/objects/js-objects.cc @@ -2908,7 +2908,7 @@ void MigrateFastToSlow(Isolate* isolate, Handle 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; diff --git a/deps/v8/src/objects/literal-objects.cc b/deps/v8/src/objects/literal-objects.cc index 98c41cbfb5f49f..827a8b10219290 100644 --- a/deps/v8/src/objects/literal-objects.cc +++ b/deps/v8/src/objects/literal-objects.cc @@ -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_); diff --git a/deps/v8/src/objects/lookup.cc b/deps/v8/src/objects/lookup.cc index 7f626cc22332e2..0700a6fc921b73 100644 --- a/deps/v8/src/objects/lookup.cc +++ b/deps/v8/src/objects/lookup.cc @@ -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 = diff --git a/deps/v8/src/objects/objects.cc b/deps/v8/src/objects/objects.cc index 723023b707947f..1328b517e8ba01 100644 --- a/deps/v8/src/objects/objects.cc +++ b/deps/v8/src/objects/objects.cc @@ -6677,7 +6677,7 @@ void StringTable::EnsureCapacityForDeserialization(Isolate* isolate, int expected) { Handle 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); } @@ -6729,7 +6729,7 @@ Handle 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); @@ -6870,7 +6870,7 @@ Handle StringSet::New(Isolate* isolate) { Handle StringSet::Add(Isolate* isolate, Handle stringset, Handle 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); @@ -6888,7 +6888,7 @@ Handle ObjectHashSet::Add(Isolate* isolate, Handle 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(); @@ -7084,7 +7084,7 @@ Handle CompilationCacheTable::PutScript( src = String::Flatten(isolate, src); StringSharedKey key(src, shared, language_mode, kNoSourcePosition); Handle 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); @@ -7116,7 +7116,7 @@ Handle CompilationCacheTable::PutEval( } } - cache = EnsureCapacity(isolate, cache, 1); + cache = EnsureCapacity(isolate, cache); int entry = cache->FindInsertionEntry(key.Hash()); Handle k = isolate->factory()->NewNumber(static_cast(key.Hash())); @@ -7130,7 +7130,7 @@ Handle CompilationCacheTable::PutRegExp( Isolate* isolate, Handle cache, Handle src, JSRegExp::Flags flags, Handle 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. @@ -7192,15 +7192,16 @@ Handle BaseNameDictionary::New( Handle dict = Dictionary::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 -Handle BaseNameDictionary::EnsureCapacity( - Isolate* isolate, Handle dictionary, int n) { - // Check whether there are enough enumeration indices to add n elements. - if (!PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) { +int BaseNameDictionary::NextEnumerationIndex( + Isolate* isolate, Handle 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(); @@ -7221,11 +7222,12 @@ Handle BaseNameDictionary::EnsureCapacity( dictionary->DetailsAtPut(isolate, index, new_details); } - // Set the next enumeration index. - dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex + - length); + index = PropertyDetails::kInitialIndex + length; } - return HashTable::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 @@ -7274,13 +7276,13 @@ Handle BaseNameDictionary::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; } @@ -7294,7 +7296,7 @@ Handle Dictionary::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 k = Shape::AsHandle(isolate, key); @@ -7644,7 +7646,7 @@ Handle ObjectHashTableBase::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; } @@ -7892,8 +7894,8 @@ Handle 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(); }