Skip to content

Commit 4bc3d2c

Browse files
joyeecheungaddaleax
authored andcommitted
deps: V8: cherry-pick 9baf2865671c
Original commit message: rehash JSMap and JSSet during deserialization To rehash JSMap and JSSet, we simply replace the backing store with a new one created with the new hash. Bug: v8:9187 Refs: joyeecheung/v8@9baf286
1 parent 52b7102 commit 4bc3d2c

File tree

10 files changed

+96
-14
lines changed

10 files changed

+96
-14
lines changed

deps/v8/src/objects/heap-object.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ class HeapObject : public Object {
190190
bool CanBeRehashed() const;
191191

192192
// Rehash the object based on the layout inferred from its map.
193-
void RehashBasedOnMap(ReadOnlyRoots root);
193+
void RehashBasedOnMap(Isolate* isolate);
194194

195195
// Layout description.
196196
#define HEAP_OBJECT_FIELDS(V) \

deps/v8/src/objects/js-collection.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class JSSet : public TorqueGeneratedJSSet<JSSet, JSCollection> {
3030
public:
3131
static void Initialize(Handle<JSSet> set, Isolate* isolate);
3232
static void Clear(Isolate* isolate, Handle<JSSet> set);
33+
void Rehash(Isolate* isolate);
3334

3435
// Dispatched behavior.
3536
DECL_PRINTER(JSSet)
@@ -56,6 +57,7 @@ class JSMap : public TorqueGeneratedJSMap<JSMap, JSCollection> {
5657
public:
5758
static void Initialize(Handle<JSMap> map, Isolate* isolate);
5859
static void Clear(Isolate* isolate, Handle<JSMap> map);
60+
void Rehash(Isolate* isolate);
5961

6062
// Dispatched behavior.
6163
DECL_PRINTER(JSMap)

deps/v8/src/objects/objects.cc

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2285,9 +2285,8 @@ bool HeapObject::NeedsRehashing() const {
22852285
case TRANSITION_ARRAY_TYPE:
22862286
return TransitionArray::cast(*this).number_of_entries() > 1;
22872287
case ORDERED_HASH_MAP_TYPE:
2288-
return OrderedHashMap::cast(*this).NumberOfElements() > 0;
22892288
case ORDERED_HASH_SET_TYPE:
2290-
return OrderedHashSet::cast(*this).NumberOfElements() > 0;
2289+
return false; // We'll rehash from the JSMap or JSSet referencing them.
22912290
case NAME_DICTIONARY_TYPE:
22922291
case GLOBAL_DICTIONARY_TYPE:
22932292
case NUMBER_DICTIONARY_TYPE:
@@ -2297,6 +2296,8 @@ bool HeapObject::NeedsRehashing() const {
22972296
case SMALL_ORDERED_HASH_MAP_TYPE:
22982297
case SMALL_ORDERED_HASH_SET_TYPE:
22992298
case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
2299+
case JS_MAP_TYPE:
2300+
case JS_SET_TYPE:
23002301
return true;
23012302
default:
23022303
return false;
@@ -2306,10 +2307,13 @@ bool HeapObject::NeedsRehashing() const {
23062307
bool HeapObject::CanBeRehashed() const {
23072308
DCHECK(NeedsRehashing());
23082309
switch (map().instance_type()) {
2310+
case JS_MAP_TYPE:
2311+
case JS_SET_TYPE:
2312+
return true;
23092313
case ORDERED_HASH_MAP_TYPE:
23102314
case ORDERED_HASH_SET_TYPE:
2315+
UNREACHABLE(); // We'll rehash from the JSMap or JSSet referencing them.
23112316
case ORDERED_NAME_DICTIONARY_TYPE:
2312-
// TODO(yangguo): actually support rehashing OrderedHash{Map,Set}.
23132317
return false;
23142318
case NAME_DICTIONARY_TYPE:
23152319
case GLOBAL_DICTIONARY_TYPE:
@@ -2333,7 +2337,8 @@ bool HeapObject::CanBeRehashed() const {
23332337
return false;
23342338
}
23352339

2336-
void HeapObject::RehashBasedOnMap(ReadOnlyRoots roots) {
2340+
void HeapObject::RehashBasedOnMap(Isolate* isolate) {
2341+
ReadOnlyRoots roots = ReadOnlyRoots(isolate);
23372342
switch (map().instance_type()) {
23382343
case HASH_TABLE_TYPE:
23392344
UNREACHABLE();
@@ -2365,6 +2370,17 @@ void HeapObject::RehashBasedOnMap(ReadOnlyRoots roots) {
23652370
case SMALL_ORDERED_HASH_SET_TYPE:
23662371
DCHECK_EQ(0, SmallOrderedHashSet::cast(*this).NumberOfElements());
23672372
break;
2373+
case ORDERED_HASH_MAP_TYPE:
2374+
case ORDERED_HASH_SET_TYPE:
2375+
UNREACHABLE(); // We'll rehash from the JSMap or JSSet referencing them.
2376+
case JS_MAP_TYPE: {
2377+
JSMap::cast(*this).Rehash(isolate);
2378+
break;
2379+
}
2380+
case JS_SET_TYPE: {
2381+
JSSet::cast(*this).Rehash(isolate);
2382+
break;
2383+
}
23682384
case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
23692385
DCHECK_EQ(0, SmallOrderedNameDictionary::cast(*this).NumberOfElements());
23702386
break;
@@ -7740,6 +7756,13 @@ void JSSet::Clear(Isolate* isolate, Handle<JSSet> set) {
77407756
set->set_table(*table);
77417757
}
77427758

7759+
void JSSet::Rehash(Isolate* isolate) {
7760+
Handle<OrderedHashSet> table_handle(OrderedHashSet::cast(table()), isolate);
7761+
Handle<OrderedHashSet> new_table =
7762+
OrderedHashSet::Rehash(isolate, table_handle).ToHandleChecked();
7763+
set_table(*new_table);
7764+
}
7765+
77437766
void JSMap::Initialize(Handle<JSMap> map, Isolate* isolate) {
77447767
Handle<OrderedHashMap> table = isolate->factory()->NewOrderedHashMap();
77457768
map->set_table(*table);
@@ -7751,6 +7774,13 @@ void JSMap::Clear(Isolate* isolate, Handle<JSMap> map) {
77517774
map->set_table(*table);
77527775
}
77537776

7777+
void JSMap::Rehash(Isolate* isolate) {
7778+
Handle<OrderedHashMap> table_handle(OrderedHashMap::cast(table()), isolate);
7779+
Handle<OrderedHashMap> new_table =
7780+
OrderedHashMap::Rehash(isolate, table_handle).ToHandleChecked();
7781+
set_table(*new_table);
7782+
}
7783+
77547784
void JSWeakCollection::Initialize(Handle<JSWeakCollection> weak_collection,
77557785
Isolate* isolate) {
77567786
Handle<EphemeronHashTable> table = EphemeronHashTable::New(isolate, 0);

deps/v8/src/objects/ordered-hash-table.cc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,13 @@ HeapObject OrderedHashMap::GetEmpty(ReadOnlyRoots ro_roots) {
193193
return ro_roots.empty_ordered_hash_map();
194194
}
195195

196+
template <class Derived, int entrysize>
197+
MaybeHandle<Derived> OrderedHashTable<Derived, entrysize>::Rehash(
198+
Isolate* isolate, Handle<Derived> table) {
199+
return OrderedHashTable<Derived, entrysize>::Rehash(isolate, table,
200+
table->Capacity());
201+
}
202+
196203
template <class Derived, int entrysize>
197204
MaybeHandle<Derived> OrderedHashTable<Derived, entrysize>::Rehash(
198205
Isolate* isolate, Handle<Derived> table, int new_capacity) {
@@ -249,6 +256,20 @@ MaybeHandle<OrderedHashSet> OrderedHashSet::Rehash(Isolate* isolate,
249256
new_capacity);
250257
}
251258

259+
MaybeHandle<OrderedHashSet> OrderedHashSet::Rehash(
260+
Isolate* isolate, Handle<OrderedHashSet> table) {
261+
return OrderedHashTable<
262+
OrderedHashSet, OrderedHashSet::kEntrySizeWithoutChain>::Rehash(isolate,
263+
table);
264+
}
265+
266+
MaybeHandle<OrderedHashMap> OrderedHashMap::Rehash(
267+
Isolate* isolate, Handle<OrderedHashMap> table) {
268+
return OrderedHashTable<
269+
OrderedHashMap, OrderedHashMap::kEntrySizeWithoutChain>::Rehash(isolate,
270+
table);
271+
}
272+
252273
MaybeHandle<OrderedHashMap> OrderedHashMap::Rehash(Isolate* isolate,
253274
Handle<OrderedHashMap> table,
254275
int new_capacity) {

deps/v8/src/objects/ordered-hash-table.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ class OrderedHashTable : public FixedArray {
138138

139139
// The extra +1 is for linking the bucket chains together.
140140
static const int kEntrySize = entrysize + 1;
141+
static const int kEntrySizeWithoutChain = entrysize;
141142
static const int kChainOffset = entrysize;
142143

143144
static const int kNotFound = -1;
@@ -200,6 +201,8 @@ class OrderedHashTable : public FixedArray {
200201
static MaybeHandle<Derived> Allocate(
201202
Isolate* isolate, int capacity,
202203
AllocationType allocation = AllocationType::kYoung);
204+
205+
static MaybeHandle<Derived> Rehash(Isolate* isolate, Handle<Derived> table);
203206
static MaybeHandle<Derived> Rehash(Isolate* isolate, Handle<Derived> table,
204207
int new_capacity);
205208

@@ -244,6 +247,8 @@ class V8_EXPORT_PRIVATE OrderedHashSet
244247
static MaybeHandle<OrderedHashSet> Rehash(Isolate* isolate,
245248
Handle<OrderedHashSet> table,
246249
int new_capacity);
250+
static MaybeHandle<OrderedHashSet> Rehash(Isolate* isolate,
251+
Handle<OrderedHashSet> table);
247252
static MaybeHandle<OrderedHashSet> Allocate(
248253
Isolate* isolate, int capacity,
249254
AllocationType allocation = AllocationType::kYoung);
@@ -273,6 +278,8 @@ class V8_EXPORT_PRIVATE OrderedHashMap
273278
static MaybeHandle<OrderedHashMap> Rehash(Isolate* isolate,
274279
Handle<OrderedHashMap> table,
275280
int new_capacity);
281+
static MaybeHandle<OrderedHashMap> Rehash(Isolate* isolate,
282+
Handle<OrderedHashMap> table);
276283
Object ValueAt(int entry);
277284

278285
// This takes and returns raw Address values containing tagged Object

deps/v8/src/snapshot/deserializer.cc

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ void Deserializer::Initialize(Isolate* isolate) {
7070
void Deserializer::Rehash() {
7171
DCHECK(can_rehash() || deserializing_user_code());
7272
for (HeapObject item : to_rehash_) {
73-
item.RehashBasedOnMap(ReadOnlyRoots(isolate_));
73+
item.RehashBasedOnMap(isolate_);
7474
}
7575
}
7676

@@ -130,6 +130,14 @@ void Deserializer::DeserializeDeferredObjects() {
130130
}
131131
}
132132
}
133+
134+
// When the deserialization of maps are deferred, they will be created
135+
// as filler maps, and we postpone the post processing until the maps
136+
// are also deserialized.
137+
for (const auto& pair : fillers_to_post_process_) {
138+
DCHECK(!pair.first.IsFiller());
139+
PostProcessNewObject(pair.first, pair.second);
140+
}
133141
}
134142

135143
void Deserializer::LogNewObjectEvents() {
@@ -201,7 +209,11 @@ HeapObject Deserializer::PostProcessNewObject(HeapObject obj,
201209
DisallowHeapAllocation no_gc;
202210

203211
if ((FLAG_rehash_snapshot && can_rehash_) || deserializing_user_code()) {
204-
if (obj.IsString()) {
212+
if (obj.IsFiller()) {
213+
DCHECK_EQ(fillers_to_post_process_.find(obj),
214+
fillers_to_post_process_.end());
215+
fillers_to_post_process_.insert({obj, space});
216+
} else if (obj.IsString()) {
205217
// Uninitialize hash field as we need to recompute the hash.
206218
String string = String::cast(obj);
207219
string.set_hash_field(String::kEmptyHashField);

deps/v8/src/snapshot/deserializer.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,11 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer {
194194
// TODO(6593): generalize rehashing, and remove this flag.
195195
bool can_rehash_;
196196
std::vector<HeapObject> to_rehash_;
197+
// Store the objects whose maps are deferred and thus initialized as filler
198+
// maps during deserialization, so that they can be processed later when the
199+
// maps become available.
200+
std::unordered_map<HeapObject, SnapshotSpace, Object::Hasher>
201+
fillers_to_post_process_;
197202

198203
#ifdef DEBUG
199204
uint32_t num_api_references_;

deps/v8/src/snapshot/object-deserializer.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,10 @@ MaybeHandle<HeapObject> ObjectDeserializer::Deserialize(Isolate* isolate) {
4949
LinkAllocationSites();
5050
LogNewMapEvents();
5151
result = handle(HeapObject::cast(root), isolate);
52-
Rehash();
5352
allocator()->RegisterDeserializedObjectsForBlackAllocation();
5453
}
54+
55+
Rehash();
5556
CommitPostProcessedObjects();
5657
return scope.CloseAndEscape(result);
5758
}

deps/v8/src/snapshot/partial-deserializer.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@ MaybeHandle<Object> PartialDeserializer::Deserialize(
5757
// new code, which also has to be flushed from instruction cache.
5858
CHECK_EQ(start_address, code_space->top());
5959

60-
if (FLAG_rehash_snapshot && can_rehash()) Rehash();
6160
LogNewMapEvents();
6261

6362
result = handle(root, isolate);
6463
}
6564

65+
if (FLAG_rehash_snapshot && can_rehash()) Rehash();
6666
SetupOffHeapArrayBufferBackingStores();
6767

6868
return result;

deps/v8/test/cctest/test-serialize.cc

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3715,7 +3715,7 @@ UNINITIALIZED_TEST(SnapshotCreatorIncludeGlobalProxy) {
37153715
FreeCurrentEmbeddedBlob();
37163716
}
37173717

3718-
UNINITIALIZED_TEST(ReinitializeHashSeedNotRehashable) {
3718+
UNINITIALIZED_TEST(ReinitializeHashSeedJSCollectionRehashable) {
37193719
DisableAlwaysOpt();
37203720
i::FLAG_rehash_snapshot = true;
37213721
i::FLAG_hash_seed = 42;
@@ -3733,13 +3733,16 @@ UNINITIALIZED_TEST(ReinitializeHashSeedNotRehashable) {
37333733
CompileRun(
37343734
"var m = new Map();"
37353735
"m.set('a', 1);"
3736-
"m.set('b', 2);");
3736+
"m.set('b', 2);"
3737+
"var s = new Set();"
3738+
"s.add(1)");
37373739
ExpectInt32("m.get('b')", 2);
3740+
ExpectTrue("s.has(1)");
37383741
creator.SetDefaultContext(context);
37393742
}
37403743
blob =
37413744
creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
3742-
CHECK(!blob.CanBeRehashed());
3745+
CHECK(blob.CanBeRehashed());
37433746
}
37443747

37453748
ReadOnlyHeap::ClearSharedHeapForTest();
@@ -3749,15 +3752,16 @@ UNINITIALIZED_TEST(ReinitializeHashSeedNotRehashable) {
37493752
create_params.snapshot_blob = &blob;
37503753
v8::Isolate* isolate = v8::Isolate::New(create_params);
37513754
{
3752-
// Check that no rehashing has been performed.
3753-
CHECK_EQ(static_cast<uint64_t>(42),
3755+
// Check that rehashing has been performed.
3756+
CHECK_EQ(static_cast<uint64_t>(1337),
37543757
HashSeed(reinterpret_cast<i::Isolate*>(isolate)));
37553758
v8::Isolate::Scope isolate_scope(isolate);
37563759
v8::HandleScope handle_scope(isolate);
37573760
v8::Local<v8::Context> context = v8::Context::New(isolate);
37583761
CHECK(!context.IsEmpty());
37593762
v8::Context::Scope context_scope(context);
37603763
ExpectInt32("m.get('b')", 2);
3764+
ExpectTrue("s.has(1)");
37613765
}
37623766
isolate->Dispose();
37633767
delete[] blob.data;

0 commit comments

Comments
 (0)