Commit eaa07445 authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[snapshot] Pull more snapshot creation details into src/

The call sequence for snapshot creation is quite involved. Details
should not be exposed outside src/snapshot. This CL pulls more details
of snapshot creation into Snapshot::Create, which is intended to be the
single chokepoint for API, tests, and other internal use.

Bug: v8:10416,chromium:1043058
Change-Id: I610293b5f70fec12e5513e5f803b5dd9118fd3b2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2150589
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarDan Elphick <delphick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67384}
parent 6f69ae49
......@@ -96,10 +96,8 @@
#include "src/regexp/regexp-utils.h"
#include "src/runtime/runtime.h"
#include "src/snapshot/code-serializer.h"
#include "src/snapshot/context-serializer.h"
#include "src/snapshot/read-only-serializer.h"
#include "src/snapshot/snapshot.h"
#include "src/snapshot/startup-serializer.h"
#include "src/snapshot/startup-serializer.h" // For SerializedHandleChecker.
#include "src/strings/char-predicates-inl.h"
#include "src/strings/string-hasher.h"
#include "src/strings/unicode-inl.h"
......@@ -599,7 +597,6 @@ SnapshotCreator::SnapshotCreator(Isolate* isolate,
const intptr_t* external_references,
StartupData* existing_snapshot) {
SnapshotCreatorData* data = new SnapshotCreatorData(isolate);
data->isolate_ = isolate;
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
internal_isolate->set_array_buffer_allocator(&data->allocator_);
internal_isolate->set_api_external_references(external_references);
......@@ -734,8 +731,11 @@ StartupData SnapshotCreator::CreateBlob(
DCHECK(!data->created_);
DCHECK(!data->default_context_.IsEmpty());
int num_additional_contexts = static_cast<int>(data->contexts_.Size());
const int num_additional_contexts = static_cast<int>(data->contexts_.Size());
const int num_contexts = num_additional_contexts + 1; // The default context.
// Create and store lists of embedder-provided data needed during
// serialization.
{
i::HandleScope scope(isolate);
// Convert list of context-independent data to FixedArray.
......@@ -815,26 +815,6 @@ StartupData SnapshotCreator::CreateBlob(
i::DisallowHeapAllocation no_gc_from_here_on;
int num_contexts = num_additional_contexts + 1;
std::vector<i::Context> contexts;
contexts.reserve(num_contexts);
{
i::HandleScope scope(isolate);
contexts.push_back(
*v8::Utils::OpenHandle(*data->default_context_.Get(data->isolate_)));
data->default_context_.Reset();
for (int i = 0; i < num_additional_contexts; i++) {
i::Handle<i::Context> context =
v8::Utils::OpenHandle(*data->contexts_.Get(i));
contexts.push_back(*context);
}
data->contexts_.Clear();
}
// Check that values referenced by global/eternal handles are accounted for.
i::SerializedHandleChecker handle_checker(isolate, &contexts);
CHECK(handle_checker.CheckGlobalAndEternalHandles());
i::HeapObjectIterator heap_iterator(isolate->heap());
for (i::HeapObject current_obj = heap_iterator.Next(); !current_obj.is_null();
current_obj = heap_iterator.Next()) {
......@@ -857,60 +837,52 @@ StartupData SnapshotCreator::CreateBlob(
i::ReadOnlyRoots(isolate).undefined_value());
fun.set_code(isolate->builtins()->builtin(i::Builtins::kCompileLazy));
}
#ifdef DEBUG
if (function_code_handling == FunctionCodeHandling::kClear) {
DCHECK(fun.shared().HasWasmExportedFunctionData() ||
fun.shared().HasBuiltinId() || fun.shared().IsApiFunction() ||
fun.shared().HasUncompiledDataWithoutPreparseData());
}
#endif // DEBUG
}
}
i::ReadOnlySerializer read_only_serializer(isolate);
read_only_serializer.SerializeReadOnlyRoots();
i::StartupSerializer startup_serializer(isolate, &read_only_serializer);
startup_serializer.SerializeStrongReferences();
// Serialize each context with a new context serializer.
std::vector<i::SnapshotData*> context_snapshots;
context_snapshots.reserve(num_contexts);
// TODO(6593): generalize rehashing, and remove this flag.
bool can_be_rehashed = true;
for (int i = 0; i < num_contexts; i++) {
bool is_default_context = i == 0;
i::ContextSerializer context_serializer(
isolate, &startup_serializer,
is_default_context ? data->default_embedder_fields_serializer_
: data->embedder_fields_serializers_[i - 1]);
context_serializer.Serialize(&contexts[i], !is_default_context);
can_be_rehashed = can_be_rehashed && context_serializer.can_be_rehashed();
context_snapshots.push_back(new i::SnapshotData(&context_serializer));
// Create a vector with all contexts and clear associated Persistent fields.
// Note these contexts may be dead after calling Clear(), but will not be
// collected until serialization completes and the DisallowHeapAllocation
// scope above goes out of scope.
std::vector<i::Context> contexts;
contexts.reserve(num_contexts);
{
i::HandleScope scope(isolate);
contexts.push_back(
*v8::Utils::OpenHandle(*data->default_context_.Get(data->isolate_)));
data->default_context_.Reset();
for (int i = 0; i < num_additional_contexts; i++) {
i::Handle<i::Context> context =
v8::Utils::OpenHandle(*data->contexts_.Get(i));
contexts.push_back(*context);
}
data->contexts_.Clear();
}
startup_serializer.SerializeWeakReferencesAndDeferred();
can_be_rehashed = can_be_rehashed && startup_serializer.can_be_rehashed();
startup_serializer.CheckNoDirtyFinalizationRegistries();
read_only_serializer.FinalizeSerialization();
can_be_rehashed = can_be_rehashed && read_only_serializer.can_be_rehashed();
i::SnapshotData read_only_snapshot(&read_only_serializer);
i::SnapshotData startup_snapshot(&startup_serializer);
StartupData result =
i::Snapshot::CreateSnapshotBlob(&startup_snapshot, &read_only_snapshot,
context_snapshots, can_be_rehashed);
// Check that values referenced by global/eternal handles are accounted for.
i::SerializedHandleChecker handle_checker(isolate, &contexts);
CHECK(handle_checker.CheckGlobalAndEternalHandles());
// Delete heap-allocated context snapshot instances.
for (const auto context_snapshot : context_snapshots) {
delete context_snapshot;
// Create a vector with all embedder fields serializers.
std::vector<SerializeInternalFieldsCallback> embedder_fields_serializers;
embedder_fields_serializers.reserve(num_contexts);
embedder_fields_serializers.push_back(
data->default_embedder_fields_serializer_);
for (int i = 0; i < num_additional_contexts; i++) {
embedder_fields_serializers.push_back(
data->embedder_fields_serializers_[i]);
}
data->created_ = true;
DCHECK(i::Snapshot::VerifyChecksum(&result));
return result;
data->created_ = true;
return i::Snapshot::Create(isolate, &contexts, embedder_fields_serializers,
&no_gc_from_here_on);
}
bool StartupData::CanBeRehashed() const {
......
......@@ -9,9 +9,12 @@
#include "src/base/platform/platform.h"
#include "src/logging/counters.h"
#include "src/snapshot/context-deserializer.h"
#include "src/snapshot/context-serializer.h"
#include "src/snapshot/read-only-deserializer.h"
#include "src/snapshot/read-only-serializer.h"
#include "src/snapshot/snapshot-utils.h"
#include "src/snapshot/startup-deserializer.h"
#include "src/snapshot/startup-serializer.h"
#include "src/utils/memcopy.h"
#include "src/utils/version.h"
......@@ -26,6 +29,12 @@ namespace {
class SnapshotImpl : public AllStatic {
public:
static v8::StartupData CreateSnapshotBlob(
const SnapshotData* startup_snapshot_in,
const SnapshotData* read_only_snapshot_in,
const std::vector<SnapshotData*>& context_snapshots_in,
bool can_be_rehashed);
static uint32_t ExtractNumContexts(const v8::StartupData* data);
static uint32_t ExtractContextOffset(const v8::StartupData* data,
uint32_t index);
......@@ -201,7 +210,68 @@ void ProfileDeserialization(
}
}
v8::StartupData Snapshot::CreateSnapshotBlob(
// static
v8::StartupData Snapshot::Create(
Isolate* isolate, std::vector<Context>* contexts,
const std::vector<SerializeInternalFieldsCallback>&
embedder_fields_serializers,
const DisallowHeapAllocation* no_gc) {
DCHECK_EQ(contexts->size(), embedder_fields_serializers.size());
DCHECK_GT(contexts->size(), 0);
ReadOnlySerializer read_only_serializer(isolate);
read_only_serializer.SerializeReadOnlyRoots();
StartupSerializer startup_serializer(isolate, &read_only_serializer);
startup_serializer.SerializeStrongReferences();
// Serialize each context with a new serializer.
const int num_contexts = static_cast<int>(contexts->size());
std::vector<SnapshotData*> context_snapshots;
context_snapshots.reserve(num_contexts);
// TODO(v8:6593): generalize rehashing, and remove this flag.
bool can_be_rehashed = true;
for (int i = 0; i < num_contexts; i++) {
const bool is_default_context = (i == 0);
const bool include_global_proxy = !is_default_context;
ContextSerializer context_serializer(isolate, &startup_serializer,
embedder_fields_serializers[i]);
context_serializer.Serialize(&contexts->at(i), include_global_proxy);
can_be_rehashed = can_be_rehashed && context_serializer.can_be_rehashed();
context_snapshots.push_back(new SnapshotData(&context_serializer));
}
startup_serializer.SerializeWeakReferencesAndDeferred();
can_be_rehashed = can_be_rehashed && startup_serializer.can_be_rehashed();
startup_serializer.CheckNoDirtyFinalizationRegistries();
read_only_serializer.FinalizeSerialization();
can_be_rehashed = can_be_rehashed && read_only_serializer.can_be_rehashed();
SnapshotData read_only_snapshot(&read_only_serializer);
SnapshotData startup_snapshot(&startup_serializer);
v8::StartupData result =
SnapshotImpl::CreateSnapshotBlob(&startup_snapshot, &read_only_snapshot,
context_snapshots, can_be_rehashed);
for (const SnapshotData* ptr : context_snapshots) delete ptr;
CHECK(Snapshot::VerifyChecksum(&result));
return result;
}
// static
v8::StartupData Snapshot::Create(Isolate* isolate, Context default_context,
const DisallowHeapAllocation* no_gc) {
std::vector<Context> contexts{default_context};
std::vector<SerializeInternalFieldsCallback> callbacks{{}};
return Snapshot::Create(isolate, &contexts, callbacks, no_gc);
}
v8::StartupData SnapshotImpl::CreateSnapshotBlob(
const SnapshotData* startup_snapshot_in,
const SnapshotData* read_only_snapshot_in,
const std::vector<SnapshotData*>& context_snapshots_in,
......
......@@ -6,11 +6,13 @@
#define V8_SNAPSHOT_SNAPSHOT_H_
#include "include/v8.h" // For StartupData.
#include "src/common/assert-scope.h"
#include "src/common/globals.h"
namespace v8 {
namespace internal {
class Context;
class Isolate;
class SnapshotData;
class JSGlobalProxy;
......@@ -19,11 +21,18 @@ class Snapshot : public AllStatic {
public:
// ---------------- Serialization -------------------------------------------
static v8::StartupData CreateSnapshotBlob(
const SnapshotData* startup_snapshot_in,
const SnapshotData* read_only_snapshot_in,
const std::vector<SnapshotData*>& context_snapshots_in,
bool can_be_rehashed);
// Serializes the given isolate and contexts. Each context may have an
// associated callback to serialize internal fields. The default context must
// be passed at index 0.
static v8::StartupData Create(
Isolate* isolate, std::vector<Context>* contexts,
const std::vector<SerializeInternalFieldsCallback>&
embedder_fields_serializers,
const DisallowHeapAllocation* no_gc);
// Convenience helper for the above when only serializing a single context.
static v8::StartupData Create(Isolate* isolate, Context default_context,
const DisallowHeapAllocation* no_gc);
// ---------------- Deserialization -----------------------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment