blob: b019091ee9cca1cb83b5b78e1db569d6cfd7a2da [file] [log] [blame]
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/snapshot/startup-deserializer.h"
#include "src/api/api.h"
#include "src/codegen/assembler-inl.h"
#include "src/execution/v8threads.h"
#include "src/heap/heap-inl.h"
#include "src/logging/log.h"
#include "src/snapshot/snapshot.h"
namespace v8 {
namespace internal {
void StartupDeserializer::DeserializeIntoIsolate() {
HandleScope scope(isolate());
// No active threads.
DCHECK_NULL(isolate()->thread_manager()->FirstThreadStateInUse());
// No active handles.
DCHECK(isolate()->handle_scope_implementer()->blocks()->empty());
// Startup object cache is not yet populated.
DCHECK(isolate()->startup_object_cache()->empty());
// Builtins are not yet created.
DCHECK(!isolate()->builtins()->is_initialized());
{
isolate()->heap()->IterateSmiRoots(this);
isolate()->heap()->IterateRoots(
this,
base::EnumSet<SkipRoot>{SkipRoot::kUnserializable, SkipRoot::kWeak});
Iterate(isolate(), this);
DeserializeStringTable();
isolate()->heap()->IterateWeakRoots(
this, base::EnumSet<SkipRoot>{SkipRoot::kUnserializable});
DeserializeDeferredObjects();
for (Handle<AccessorInfo> info : accessor_infos()) {
RestoreExternalReferenceRedirector(isolate(), info);
}
for (Handle<CallHandlerInfo> info : call_handler_infos()) {
RestoreExternalReferenceRedirector(isolate(), info);
}
// Flush the instruction cache for the entire code-space. Must happen after
// builtins deserialization.
FlushICache();
}
CheckNoArrayBufferBackingStores();
isolate()->heap()->set_native_contexts_list(
ReadOnlyRoots(isolate()).undefined_value());
// The allocation site list is build during root iteration, but if no sites
// were encountered then it needs to be initialized to undefined.
if (isolate()->heap()->allocation_sites_list() == Smi::zero()) {
isolate()->heap()->set_allocation_sites_list(
ReadOnlyRoots(isolate()).undefined_value());
}
isolate()->heap()->set_dirty_js_finalization_registries_list(
ReadOnlyRoots(isolate()).undefined_value());
isolate()->heap()->set_dirty_js_finalization_registries_list_tail(
ReadOnlyRoots(isolate()).undefined_value());
isolate()->builtins()->MarkInitialized();
LogNewMapEvents();
WeakenDescriptorArrays();
if (FLAG_rehash_snapshot && can_rehash()) {
// Hash seed was initalized in ReadOnlyDeserializer.
Rehash();
}
}
void StartupDeserializer::DeserializeStringTable() {
// See StartupSerializer::SerializeStringTable.
// Get the string table size.
int string_table_size = source()->GetInt();
// Add each string to the Isolate's string table.
// TODO(leszeks): Consider pre-sizing the string table.
for (int i = 0; i < string_table_size; ++i) {
Handle<String> string = Handle<String>::cast(ReadObject());
StringTableInsertionKey key(string);
Handle<String> result =
isolate()->string_table()->LookupKey(isolate(), &key);
USE(result);
// This is startup, so there should be no duplicate entries in the string
// table, and the lookup should unconditionally add the given string.
DCHECK_EQ(*result, *string);
}
DCHECK_EQ(string_table_size, isolate()->string_table()->NumberOfElements());
}
void StartupDeserializer::LogNewMapEvents() {
if (FLAG_trace_maps) LOG(isolate(), LogAllMaps());
}
void StartupDeserializer::FlushICache() {
DCHECK(!deserializing_user_code());
// The entire isolate is newly deserialized. Simply flush all code pages.
for (Page* p : *isolate()->heap()->code_space()) {
FlushInstructionCache(p->area_start(), p->area_end() - p->area_start());
}
}
} // namespace internal
} // namespace v8