Skip to content

Commit 67ce52c

Browse files
hashseedMylesBorins
authored andcommitted
deps: backport rehash strings after deserialization
Original commit messages: v8/v8@a2ab135 [snapshot] Rehash strings after deserialization. See https://goo.gl/6aN8xA Bug: v8:6593 Change-Id: Ic8b0b57195d01d41591397d5d45de3f0f3ebc3d9 Reviewed-on: https://chromium-review.googlesource.com/574527 Reviewed-by: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Commit-Queue: Yang Guo <yangguo@chromium.org> Cr-Commit-Position: refs/heads/master@{#46732} v8/v8@182caaf Do not track transitions for built-in objects. Objects created during bootstrapping do not need a transition tree except for elements kind transitions. Bug: v8:6596 Change-Id: I237b8b2792f201336e1c9731c815095dd06bc182 Reviewed-on: https://chromium-review.googlesource.com/571750 Reviewed-by: Igor Sheludko <ishell@chromium.org> Commit-Queue: Yang Guo <yangguo@chromium.org> Cr-Commit-Position: refs/heads/master@{#46693} Fixes: #14171 PR-URL: #14385
1 parent 5900ebe commit 67ce52c

22 files changed

+302
-25
lines changed

configure

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -419,12 +419,12 @@ parser.add_option('--without-perfctr',
419419
# Dummy option for backwards compatibility
420420
parser.add_option('--with-snapshot',
421421
action='store_true',
422-
dest='with_snapshot',
422+
dest='unused_with_snapshot',
423423
help=optparse.SUPPRESS_HELP)
424424

425425
parser.add_option('--without-snapshot',
426426
action='store_true',
427-
dest='unused_without_snapshot',
427+
dest='without_snapshot',
428428
help=optparse.SUPPRESS_HELP)
429429

430430
parser.add_option('--without-ssl',
@@ -802,7 +802,7 @@ def configure_node(o):
802802
cross_compiling = (options.cross_compiling
803803
if options.cross_compiling is not None
804804
else target_arch != host_arch)
805-
want_snapshots = 1 if options.with_snapshot else 0
805+
want_snapshots = not options.without_snapshot
806806
o['variables']['want_separate_host_toolset'] = int(
807807
cross_compiling and want_snapshots)
808808

@@ -946,7 +946,7 @@ def configure_v8(o):
946946
o['variables']['v8_no_strict_aliasing'] = 1 # Work around compiler bugs.
947947
o['variables']['v8_optimized_debug'] = 0 # Compile with -O0 in debug builds.
948948
o['variables']['v8_random_seed'] = 0 # Use a random seed for hash tables.
949-
o['variables']['v8_use_snapshot'] = b(options.with_snapshot)
949+
o['variables']['v8_use_snapshot'] = 'false' if options.without_snapshot else 'true'
950950
o['variables']['node_use_v8_platform'] = b(not options.without_v8_platform)
951951
o['variables']['node_use_bundled_v8'] = b(not options.without_bundled_v8)
952952
o['variables']['force_dynamic_crt'] = 1 if options.shared else 0

deps/v8/include/v8-version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#define V8_MAJOR_VERSION 5
1212
#define V8_MINOR_VERSION 1
1313
#define V8_BUILD_NUMBER 281
14-
#define V8_PATCH_LEVEL 103
14+
#define V8_PATCH_LEVEL 104
1515

1616
// Use 1 for candidates and 0 otherwise.
1717
// (Boolean macro values are not supported by all preprocessors.)

deps/v8/src/api.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,9 @@ StartupData SerializeIsolateAndContext(
391391

392392
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
393393

394+
// We might rehash strings and re-sort descriptors. Clear the lookup cache.
395+
internal_isolate->descriptor_lookup_cache()->Clear();
396+
394397
// If we don't do this then we end up with a stray root pointing at the
395398
// context even after we have disposed of the context.
396399
internal_isolate->heap()->CollectAllAvailableGarbage("mksnapshot");
@@ -428,6 +431,9 @@ StartupData SerializeIsolateAndContext(
428431
context_ser.Serialize(&raw_context);
429432
ser.SerializeWeakReferencesAndDeferred();
430433

434+
metadata.set_can_rehash(ser.can_be_rehashed() &&
435+
context_ser.can_be_rehashed());
436+
431437
return i::Snapshot::CreateSnapshotBlob(ser, context_ser, metadata);
432438
}
433439

deps/v8/src/bootstrapper.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,8 @@ Handle<JSFunction> Genesis::GetThrowTypeErrorIntrinsic(
655655
DCHECK(false);
656656
}
657657

658+
JSObject::MigrateSlowToFast(function, 0, "Bootstrapping");
659+
658660
return function;
659661
}
660662

@@ -1133,6 +1135,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
11331135

11341136
sloppy_function_map_writable_prototype_->SetConstructor(*function_fun);
11351137
strict_function_map_writable_prototype_->SetConstructor(*function_fun);
1138+
1139+
JSObject::MigrateSlowToFast(function_fun, 0, "Bootstrapping");
11361140
}
11371141

11381142
{ // --- A r r a y ---

deps/v8/src/flag-definitions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,8 @@ DEFINE_BOOL(abort_on_uncaught_exception, false,
830830
DEFINE_BOOL(randomize_hashes, true,
831831
"randomize hashes to avoid predictable hash collisions "
832832
"(with snapshots this option cannot override the baked-in seed)")
833+
DEFINE_BOOL(rehash_snapshot, true,
834+
"rehash strings from the snapshot to override the baked-in seed")
833835
DEFINE_INT(hash_seed, 0,
834836
"Fixed seed to use to hash property keys (0 means random)"
835837
"(with snapshots this option cannot override the baked-in seed)")

deps/v8/src/heap/heap.cc

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5348,14 +5348,7 @@ bool Heap::SetUp() {
53485348

53495349
// Set up the seed that is used to randomize the string hash function.
53505350
DCHECK(hash_seed() == 0);
5351-
if (FLAG_randomize_hashes) {
5352-
if (FLAG_hash_seed == 0) {
5353-
int rnd = isolate()->random_number_generator()->NextInt();
5354-
set_hash_seed(Smi::FromInt(rnd & Name::kHashBitMask));
5355-
} else {
5356-
set_hash_seed(Smi::FromInt(FLAG_hash_seed));
5357-
}
5358-
}
5351+
if (FLAG_randomize_hashes) InitializeHashSeed();
53595352

53605353
for (int i = 0; i < static_cast<int>(v8::Isolate::kUseCounterFeatureCount);
53615354
i++) {
@@ -5393,6 +5386,14 @@ bool Heap::SetUp() {
53935386
return true;
53945387
}
53955388

5389+
void Heap::InitializeHashSeed() {
5390+
if (FLAG_hash_seed == 0) {
5391+
int rnd = isolate()->random_number_generator()->NextInt();
5392+
set_hash_seed(Smi::FromInt(rnd & Name::kHashBitMask));
5393+
} else {
5394+
set_hash_seed(Smi::FromInt(FLAG_hash_seed));
5395+
}
5396+
}
53965397

53975398
bool Heap::CreateHeapObjects() {
53985399
// Create initial maps.

deps/v8/src/heap/heap.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,9 @@ class Heap {
864864
// without actually creating any objects.
865865
bool SetUp();
866866

867+
// (Re-)Initialize hash seed from flag or RNG.
868+
void InitializeHashSeed();
869+
867870
// Bootstraps the object heap with the core set of objects required to run.
868871
// Returns whether it succeeded.
869872
bool CreateHeapObjects();

deps/v8/src/js/array.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1831,6 +1831,8 @@ var unscopables = {
18311831
keys: true,
18321832
};
18331833

1834+
%ToFastProperties(unscopables);
1835+
18341836
%AddNamedProperty(GlobalArray.prototype, unscopablesSymbol, unscopables,
18351837
DONT_ENUM | READ_ONLY);
18361838

deps/v8/src/objects.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9469,6 +9469,12 @@ void Map::TraceAllTransitions(Map* map) {
94699469

94709470
void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child,
94719471
Handle<Name> name, SimpleTransitionFlag flag) {
9472+
// Do not track transitions during bootstrap except for element transitions.
9473+
Isolate* isolate = parent->GetIsolate();
9474+
if (isolate->bootstrapper()->IsActive() &&
9475+
!name.is_identical_to(isolate->factory()->elements_transition_symbol())) {
9476+
return;
9477+
}
94729478
if (!parent->GetBackPointer()->IsUndefined()) {
94739479
parent->set_owns_descriptors(false);
94749480
} else {
@@ -17520,6 +17526,12 @@ template class Dictionary<UnseededNumberDictionary,
1752017526
UnseededNumberDictionaryShape,
1752117527
uint32_t>;
1752217528

17529+
template void
17530+
HashTable<GlobalDictionary, GlobalDictionaryShape, Handle<Name> >::Rehash(Handle<Name> key);
17531+
17532+
template void
17533+
HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::Rehash(Handle<Name> key);
17534+
1752317535
template Handle<SeededNumberDictionary>
1752417536
Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
1752517537
New(Isolate*, int at_least_space_for, PretenureFlag pretenure);

deps/v8/src/snapshot/deserializer.cc

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ void Deserializer::Deserialize(Isolate* isolate) {
109109
LOG_CODE_EVENT(isolate_, LogCodeObjects());
110110
LOG_CODE_EVENT(isolate_, LogBytecodeHandlers());
111111
LOG_CODE_EVENT(isolate_, LogCompiledFunctions());
112+
113+
if (FLAG_rehash_snapshot && can_rehash_) Rehash();
112114
}
113115

114116
MaybeHandle<Object> Deserializer::DeserializePartial(
@@ -138,6 +140,9 @@ MaybeHandle<Object> Deserializer::DeserializePartial(
138140
// changed and logging should be added to notify the profiler et al of the
139141
// new code, which also has to be flushed from instruction cache.
140142
CHECK_EQ(start_address, code_space->top());
143+
144+
if (FLAG_rehash_snapshot && can_rehash_) RehashContext(Context::cast(root));
145+
141146
return Handle<Object>(root, isolate);
142147
}
143148

@@ -164,6 +169,64 @@ MaybeHandle<SharedFunctionInfo> Deserializer::DeserializeCode(
164169
}
165170
}
166171

172+
// We only really just need HashForObject here.
173+
class StringRehashKey : public HashTableKey {
174+
public:
175+
uint32_t HashForObject(Object* other) override {
176+
return String::cast(other)->Hash();
177+
}
178+
179+
static uint32_t StringHash(Object* obj) {
180+
UNREACHABLE();
181+
return String::cast(obj)->Hash();
182+
}
183+
184+
bool IsMatch(Object* string) override {
185+
UNREACHABLE();
186+
return false;
187+
}
188+
189+
uint32_t Hash() override {
190+
UNREACHABLE();
191+
return 0;
192+
}
193+
194+
Handle<Object> AsHandle(Isolate* isolate) override {
195+
UNREACHABLE();
196+
return isolate->factory()->empty_string();
197+
}
198+
};
199+
200+
void Deserializer::Rehash() {
201+
DCHECK(can_rehash_);
202+
isolate_->heap()->InitializeHashSeed();
203+
if (FLAG_profile_deserialization) {
204+
PrintF("Re-initializing hash seed to %x\n",
205+
isolate_->heap()->hash_seed()->value());
206+
}
207+
StringRehashKey string_rehash_key;
208+
isolate_->heap()->string_table()->Rehash(&string_rehash_key);
209+
isolate_->heap()->intrinsic_function_names()->Rehash(
210+
isolate_->factory()->empty_string());
211+
SortMapDescriptors();
212+
}
213+
214+
void Deserializer::RehashContext(Context* context) {
215+
DCHECK(can_rehash_);
216+
for (const auto& array : transition_arrays_) array->Sort();
217+
Handle<Name> dummy = isolate_->factory()->empty_string();
218+
context->global_object()->global_dictionary()->Rehash(dummy);
219+
SortMapDescriptors();
220+
}
221+
222+
void Deserializer::SortMapDescriptors() {
223+
for (const auto& map : maps_) {
224+
if (map->instance_descriptors()->number_of_descriptors() > 1) {
225+
map->instance_descriptors()->Sort();
226+
}
227+
}
228+
}
229+
167230
Deserializer::~Deserializer() {
168231
// TODO(svenpanne) Re-enable this assertion when v8 initialization is fixed.
169232
// DCHECK(source_.AtEOF());
@@ -288,6 +351,18 @@ HeapObject* Deserializer::PostProcessNewObject(HeapObject* obj, int space) {
288351
new_code_objects_.Add(Code::cast(obj));
289352
}
290353
}
354+
if (FLAG_rehash_snapshot && can_rehash_ && !deserializing_user_code()) {
355+
if (obj->IsString()) {
356+
// Uninitialize hash field as we are going to reinitialize the hash seed.
357+
String* string = String::cast(obj);
358+
string->set_hash_field(String::kEmptyHashField);
359+
} else if (obj->IsTransitionArray() &&
360+
TransitionArray::cast(obj)->number_of_entries() > 1) {
361+
transition_arrays_.Add(TransitionArray::cast(obj));
362+
} else if (obj->IsMap()) {
363+
maps_.Add(Map::cast(obj));
364+
}
365+
}
291366
// Check alignment.
292367
DCHECK_EQ(0, Heap::GetFillToAlign(obj->address(), obj->RequiredAlignment()));
293368
return obj;

0 commit comments

Comments
 (0)