[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: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Dan Elphick <delphick@chromium.org> Cr-Commit-Position: refs/heads/master@{#67384}
This commit is contained in:
parent
6f69ae49a7
commit
eaa07445e4
104
src/api/api.cc
104
src/api/api.cc
@ -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();
|
||||
// Check that values referenced by global/eternal handles are accounted for.
|
||||
i::SerializedHandleChecker handle_checker(isolate, &contexts);
|
||||
CHECK(handle_checker.CheckGlobalAndEternalHandles());
|
||||
|
||||
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);
|
||||
|
||||
// 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;
|
||||
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 -----------------------------------------
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user