Commit 1e53bb96 authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

Deduplicate various snapshot blob helper functions

Helper functions to create and warm-up the snapshot blob were
duplicated in various spots (mksnapshot, inspector tests, serializer
cctests). This merges all of these into a single helper function
family declared in snapshot.h.

Bug: v8:9189, chromium:957029
Change-Id: I2d8d6fd8e955ffffd7d805c199d4a858500af588
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1598695
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61576}
parent d2061b34
...@@ -144,100 +144,37 @@ char* GetExtraCode(char* filename, const char* description) { ...@@ -144,100 +144,37 @@ char* GetExtraCode(char* filename, const char* description) {
return chars; return chars;
} }
bool RunExtraCode(v8::Isolate* isolate, v8::Local<v8::Context> context, v8::StartupData CreateSnapshotDataBlob(v8::Isolate* isolate,
const char* utf8_source, const char* name) { const char* embedded_source) {
v8::base::ElapsedTimer timer; v8::base::ElapsedTimer timer;
timer.Start(); timer.Start();
v8::Context::Scope context_scope(context);
v8::TryCatch try_catch(isolate);
v8::Local<v8::String> source_string;
if (!v8::String::NewFromUtf8(isolate, utf8_source, v8::NewStringType::kNormal)
.ToLocal(&source_string)) {
return false;
}
v8::Local<v8::String> resource_name =
v8::String::NewFromUtf8(isolate, name, v8::NewStringType::kNormal)
.ToLocalChecked();
v8::ScriptOrigin origin(resource_name);
v8::ScriptCompiler::Source source(source_string, origin);
v8::Local<v8::Script> script;
if (!v8::ScriptCompiler::Compile(context, &source).ToLocal(&script))
return false;
if (script->Run(context).IsEmpty()) return false;
if (i::FLAG_profile_deserialization) {
i::PrintF("Executing custom snapshot script %s took %0.3f ms\n", name,
timer.Elapsed().InMillisecondsF());
}
timer.Stop();
CHECK(!try_catch.HasCaught());
return true;
}
v8::StartupData CreateSnapshotDataBlob(v8::SnapshotCreator* snapshot_creator, v8::StartupData result = i::CreateSnapshotDataBlobInternal(
const char* script_source = nullptr) { v8::SnapshotCreator::FunctionCodeHandling::kClear, embedded_source,
// Create a new isolate and a new context from scratch, optionally run isolate);
// a script to embed, and serialize to create a snapshot blob.
v8::StartupData result = {nullptr, 0};
v8::base::ElapsedTimer timer;
timer.Start();
{
v8::Isolate* isolate = snapshot_creator->GetIsolate();
{
v8::HandleScope scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);
if (script_source != nullptr &&
!RunExtraCode(isolate, context, script_source, "<embedded>")) {
return result;
}
snapshot_creator->SetDefaultContext(context);
}
result = snapshot_creator->CreateBlob(
v8::SnapshotCreator::FunctionCodeHandling::kClear);
}
if (i::FLAG_profile_deserialization) { if (i::FLAG_profile_deserialization) {
i::PrintF("Creating snapshot took %0.3f ms\n", i::PrintF("Creating snapshot took %0.3f ms\n",
timer.Elapsed().InMillisecondsF()); timer.Elapsed().InMillisecondsF());
} }
timer.Stop(); timer.Stop();
return result; return result;
} }
v8::StartupData WarmUpSnapshotDataBlob(v8::SnapshotCreator* snapshot_creator, v8::StartupData WarmUpSnapshotDataBlob(v8::StartupData cold_snapshot_blob,
const char* warmup_source) { const char* warmup_source) {
CHECK_NOT_NULL(warmup_source);
// Use following steps to create a warmed up snapshot blob from a cold one:
// - Create a new isolate from the cold snapshot.
// - Create a new context to run the warmup script. This will trigger
// compilation of executed functions.
// - Create a new context. This context will be unpolluted.
// - Serialize the isolate and the second context into a new snapshot blob.
v8::StartupData result = {nullptr, 0};
v8::base::ElapsedTimer timer; v8::base::ElapsedTimer timer;
timer.Start(); timer.Start();
{
v8::Isolate* isolate = snapshot_creator->GetIsolate(); v8::StartupData result =
{ i::WarmUpSnapshotDataBlobInternal(cold_snapshot_blob, warmup_source);
v8::HandleScope scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);
if (!RunExtraCode(isolate, context, warmup_source, "<warm-up>")) {
return result;
}
}
{
v8::HandleScope handle_scope(isolate);
isolate->ContextDisposedNotification(false);
v8::Local<v8::Context> context = v8::Context::New(isolate);
snapshot_creator->SetDefaultContext(context);
}
result = snapshot_creator->CreateBlob(
v8::SnapshotCreator::FunctionCodeHandling::kKeep);
}
if (i::FLAG_profile_deserialization) { if (i::FLAG_profile_deserialization) {
i::PrintF("Warming up snapshot took %0.3f ms\n", i::PrintF("Warming up snapshot took %0.3f ms\n",
timer.Elapsed().InMillisecondsF()); timer.Elapsed().InMillisecondsF());
} }
timer.Stop(); timer.Stop();
return result; return result;
} }
...@@ -332,18 +269,18 @@ int main(int argc, char** argv) { ...@@ -332,18 +269,18 @@ int main(int argc, char** argv) {
// to be written out if builtins are embedded. // to be written out if builtins are embedded.
i_isolate->RegisterEmbeddedFileWriter(&embedded_writer); i_isolate->RegisterEmbeddedFileWriter(&embedded_writer);
} }
v8::SnapshotCreator snapshot_creator(isolate); blob = CreateSnapshotDataBlob(isolate, embed_script.get());
if (i::FLAG_embedded_builtins) { if (i::FLAG_embedded_builtins) {
// At this point, the Isolate has been torn down but the embedded blob
// is still alive (we called DisableEmbeddedBlobRefcounting above).
// That's fine as far as the embedded file writer is concerned.
WriteEmbeddedFile(&embedded_writer); WriteEmbeddedFile(&embedded_writer);
} }
blob = CreateSnapshotDataBlob(&snapshot_creator, embed_script.get());
} }
if (warmup_script) { if (warmup_script) {
CHECK(blob.raw_size > 0 && blob.data != nullptr);
v8::StartupData cold = blob; v8::StartupData cold = blob;
v8::SnapshotCreator snapshot_creator(nullptr, &cold); blob = WarmUpSnapshotDataBlob(cold, warmup_script.get());
blob = WarmUpSnapshotDataBlob(&snapshot_creator, warmup_script.get());
delete[] cold.data; delete[] cold.data;
} }
......
...@@ -380,29 +380,55 @@ bool RunExtraCode(v8::Isolate* isolate, v8::Local<v8::Context> context, ...@@ -380,29 +380,55 @@ bool RunExtraCode(v8::Isolate* isolate, v8::Local<v8::Context> context,
} // namespace } // namespace
// TODO(jgruber): Merge with related code in mksnapshot.cc and
// inspector-test.cc.
v8::StartupData CreateSnapshotDataBlobInternal( v8::StartupData CreateSnapshotDataBlobInternal(
v8::SnapshotCreator::FunctionCodeHandling function_code_handling, v8::SnapshotCreator::FunctionCodeHandling function_code_handling,
const char* embedded_source) { const char* embedded_source, v8::Isolate* isolate) {
// Create a new isolate and a new context from scratch, optionally run // If no isolate is passed in, create it (and a new context) from scratch.
// a script to embed, and serialize to create a snapshot blob. if (isolate == nullptr) isolate = v8::Isolate::Allocate();
v8::StartupData result = {nullptr, 0};
// Optionally run a script to embed, and serialize to create a snapshot blob.
v8::SnapshotCreator snapshot_creator(isolate);
{ {
v8::SnapshotCreator snapshot_creator; v8::HandleScope scope(isolate);
v8::Isolate* isolate = snapshot_creator.GetIsolate(); v8::Local<v8::Context> context = v8::Context::New(isolate);
{ if (embedded_source != nullptr &&
v8::HandleScope scope(isolate); !RunExtraCode(isolate, context, embedded_source, "<embedded>")) {
v8::Local<v8::Context> context = v8::Context::New(isolate); return {};
if (embedded_source != nullptr &&
!RunExtraCode(isolate, context, embedded_source, "<embedded>")) {
return result;
}
snapshot_creator.SetDefaultContext(context);
} }
result = snapshot_creator.CreateBlob(function_code_handling); snapshot_creator.SetDefaultContext(context);
} }
return result; return snapshot_creator.CreateBlob(function_code_handling);
}
v8::StartupData WarmUpSnapshotDataBlobInternal(
v8::StartupData cold_snapshot_blob, const char* warmup_source) {
CHECK(cold_snapshot_blob.raw_size > 0 && cold_snapshot_blob.data != nullptr);
CHECK_NOT_NULL(warmup_source);
// Use following steps to create a warmed up snapshot blob from a cold one:
// - Create a new isolate from the cold snapshot.
// - Create a new context to run the warmup script. This will trigger
// compilation of executed functions.
// - Create a new context. This context will be unpolluted.
// - Serialize the isolate and the second context into a new snapshot blob.
v8::SnapshotCreator snapshot_creator(nullptr, &cold_snapshot_blob);
v8::Isolate* isolate = snapshot_creator.GetIsolate();
{
v8::HandleScope scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);
if (!RunExtraCode(isolate, context, warmup_source, "<warm-up>")) {
return {};
}
}
{
v8::HandleScope handle_scope(isolate);
isolate->ContextDisposedNotification(false);
v8::Local<v8::Context> context = v8::Context::New(isolate);
snapshot_creator.SetDefaultContext(context);
}
return snapshot_creator.CreateBlob(
v8::SnapshotCreator::FunctionCodeHandling::kKeep);
} }
} // namespace internal } // namespace internal
......
...@@ -162,7 +162,12 @@ class Snapshot : public AllStatic { ...@@ -162,7 +162,12 @@ class Snapshot : public AllStatic {
// mksnapshot. // mksnapshot.
V8_EXPORT_PRIVATE v8::StartupData CreateSnapshotDataBlobInternal( V8_EXPORT_PRIVATE v8::StartupData CreateSnapshotDataBlobInternal(
v8::SnapshotCreator::FunctionCodeHandling function_code_handling, v8::SnapshotCreator::FunctionCodeHandling function_code_handling,
const char* embedded_source); const char* embedded_source, v8::Isolate* isolate = nullptr);
// Convenience wrapper around snapshot data blob warmup used e.g. by tests and
// mksnapshot.
V8_EXPORT_PRIVATE v8::StartupData WarmUpSnapshotDataBlobInternal(
v8::StartupData cold_snapshot_blob, const char* warmup_source);
#ifdef V8_USE_EXTERNAL_STARTUP_DATA #ifdef V8_USE_EXTERNAL_STARTUP_DATA
void SetSnapshotFromFile(StartupData* snapshot_blob); void SetSnapshotFromFile(StartupData* snapshot_blob);
......
...@@ -146,67 +146,12 @@ static Vector<const byte> WritePayload(const Vector<const byte>& payload) { ...@@ -146,67 +146,12 @@ static Vector<const byte> WritePayload(const Vector<const byte>& payload) {
namespace { namespace {
bool RunExtraCode(v8::Isolate* isolate, v8::Local<v8::Context> context, // Convenience wrapper around the convenience wrapper.
const char* utf8_source, const char* name) { v8::StartupData CreateSnapshotDataBlob(const char* embedded_source) {
v8::Context::Scope context_scope(context);
v8::TryCatch try_catch(isolate);
v8::Local<v8::String> source_string;
if (!v8::String::NewFromUtf8(isolate, utf8_source, v8::NewStringType::kNormal)
.ToLocal(&source_string)) {
return false;
}
v8::Local<v8::String> resource_name =
v8::String::NewFromUtf8(isolate, name, v8::NewStringType::kNormal)
.ToLocalChecked();
v8::ScriptOrigin origin(resource_name);
v8::ScriptCompiler::Source source(source_string, origin);
v8::Local<v8::Script> script;
if (!v8::ScriptCompiler::Compile(context, &source).ToLocal(&script))
return false;
if (script->Run(context).IsEmpty()) return false;
CHECK(!try_catch.HasCaught());
return true;
}
v8::StartupData CreateSnapshotDataBlob(const char* embedded_source = nullptr) {
return CreateSnapshotDataBlobInternal( return CreateSnapshotDataBlobInternal(
v8::SnapshotCreator::FunctionCodeHandling::kClear, embedded_source); v8::SnapshotCreator::FunctionCodeHandling::kClear, embedded_source);
} }
v8::StartupData WarmUpSnapshotDataBlob(v8::StartupData cold_snapshot_blob,
const char* warmup_source) {
CHECK(cold_snapshot_blob.raw_size > 0 && cold_snapshot_blob.data != nullptr);
CHECK_NOT_NULL(warmup_source);
// Use following steps to create a warmed up snapshot blob from a cold one:
// - Create a new isolate from the cold snapshot.
// - Create a new context to run the warmup script. This will trigger
// compilation of executed functions.
// - Create a new context. This context will be unpolluted.
// - Serialize the isolate and the second context into a new snapshot blob.
v8::StartupData result = {nullptr, 0};
{
v8::SnapshotCreator snapshot_creator(nullptr, &cold_snapshot_blob);
v8::Isolate* isolate = snapshot_creator.GetIsolate();
{
v8::HandleScope scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);
if (!RunExtraCode(isolate, context, warmup_source, "<warm-up>")) {
return result;
}
}
{
v8::HandleScope handle_scope(isolate);
isolate->ContextDisposedNotification(false);
v8::Local<v8::Context> context = v8::Context::New(isolate);
snapshot_creator.SetDefaultContext(context);
}
result = snapshot_creator.CreateBlob(
v8::SnapshotCreator::FunctionCodeHandling::kKeep);
}
ReadOnlyHeap::ClearSharedHeapForTest();
return result;
}
} // namespace } // namespace
static StartupBlobs Serialize(v8::Isolate* isolate) { static StartupBlobs Serialize(v8::Isolate* isolate) {
...@@ -1463,8 +1408,9 @@ UNINITIALIZED_TEST(SnapshotDataBlobWithWarmup) { ...@@ -1463,8 +1408,9 @@ UNINITIALIZED_TEST(SnapshotDataBlobWithWarmup) {
const char* warmup = "Math.abs(1); Math.random = 1;"; const char* warmup = "Math.abs(1); Math.random = 1;";
DisableEmbeddedBlobRefcounting(); DisableEmbeddedBlobRefcounting();
v8::StartupData cold = CreateSnapshotDataBlob(); v8::StartupData cold = CreateSnapshotDataBlob(nullptr);
v8::StartupData warm = WarmUpSnapshotDataBlob(cold, warmup); v8::StartupData warm = WarmUpSnapshotDataBlobInternal(cold, warmup);
ReadOnlyHeap::ClearSharedHeapForTest();
delete[] cold.data; delete[] cold.data;
v8::Isolate::CreateParams params; v8::Isolate::CreateParams params;
...@@ -1500,7 +1446,8 @@ UNINITIALIZED_TEST(CustomSnapshotDataBlobWithWarmup) { ...@@ -1500,7 +1446,8 @@ UNINITIALIZED_TEST(CustomSnapshotDataBlobWithWarmup) {
DisableEmbeddedBlobRefcounting(); DisableEmbeddedBlobRefcounting();
v8::StartupData cold = CreateSnapshotDataBlob(source); v8::StartupData cold = CreateSnapshotDataBlob(source);
v8::StartupData warm = WarmUpSnapshotDataBlob(cold, warmup); v8::StartupData warm = WarmUpSnapshotDataBlobInternal(cold, warmup);
ReadOnlyHeap::ClearSharedHeapForTest();
delete[] cold.data; delete[] cold.data;
v8::Isolate::CreateParams params; v8::Isolate::CreateParams params;
......
...@@ -8,4 +8,4 @@ include_rules = [ ...@@ -8,4 +8,4 @@ include_rules = [
"+src/locked-queue-inl.h", "+src/locked-queue-inl.h",
"+src/utils.h", "+src/utils.h",
"+src/vector.h", "+src/vector.h",
] ]
\ No newline at end of file
...@@ -27,6 +27,12 @@ namespace internal { ...@@ -27,6 +27,12 @@ namespace internal {
extern void DisableEmbeddedBlobRefcounting(); extern void DisableEmbeddedBlobRefcounting();
extern void FreeCurrentEmbeddedBlob(); extern void FreeCurrentEmbeddedBlob();
extern v8::StartupData CreateSnapshotDataBlobInternal(
v8::SnapshotCreator::FunctionCodeHandling function_code_handling,
const char* embedded_source, v8::Isolate* isolate);
extern v8::StartupData WarmUpSnapshotDataBlobInternal(
v8::StartupData cold_snapshot_blob, const char* warmup_source);
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -1044,50 +1050,6 @@ class InspectorExtension : public IsolateData::SetupGlobalTask { ...@@ -1044,50 +1050,6 @@ class InspectorExtension : public IsolateData::SetupGlobalTask {
} }
}; };
bool RunExtraCode(v8::Isolate* isolate, v8::Local<v8::Context> context,
const char* utf8_source, const char* name) {
v8::Context::Scope context_scope(context);
v8::TryCatch try_catch(isolate);
v8::Local<v8::String> source_string;
if (!v8::String::NewFromUtf8(isolate, utf8_source, v8::NewStringType::kNormal)
.ToLocal(&source_string)) {
return false;
}
v8::Local<v8::String> resource_name =
v8::String::NewFromUtf8(isolate, name, v8::NewStringType::kNormal)
.ToLocalChecked();
v8::ScriptOrigin origin(resource_name);
v8::ScriptCompiler::Source source(source_string, origin);
v8::Local<v8::Script> script;
if (!v8::ScriptCompiler::Compile(context, &source).ToLocal(&script))
return false;
if (script->Run(context).IsEmpty()) return false;
CHECK(!try_catch.HasCaught());
return true;
}
v8::StartupData CreateSnapshotDataBlob(const char* embedded_source = nullptr) {
// Create a new isolate and a new context from scratch, optionally run
// a script to embed, and serialize to create a snapshot blob.
v8::StartupData result = {nullptr, 0};
{
v8::SnapshotCreator snapshot_creator;
v8::Isolate* isolate = snapshot_creator.GetIsolate();
{
v8::HandleScope scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);
if (embedded_source != nullptr &&
!RunExtraCode(isolate, context, embedded_source, "<embedded>")) {
return result;
}
snapshot_creator.SetDefaultContext(context);
}
result = snapshot_creator.CreateBlob(
v8::SnapshotCreator::FunctionCodeHandling::kClear);
}
return result;
}
} // namespace } // namespace
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
...@@ -1106,7 +1068,8 @@ int main(int argc, char* argv[]) { ...@@ -1106,7 +1068,8 @@ int main(int argc, char* argv[]) {
if (strcmp(argv[i], "--embed") == 0) { if (strcmp(argv[i], "--embed") == 0) {
argv[i++] = nullptr; argv[i++] = nullptr;
printf("Embedding script '%s'\n", argv[i]); printf("Embedding script '%s'\n", argv[i]);
startup_data = CreateSnapshotDataBlob(argv[i]); startup_data = i::CreateSnapshotDataBlobInternal(
v8::SnapshotCreator::FunctionCodeHandling::kClear, argv[i], nullptr);
argv[i] = nullptr; argv[i] = nullptr;
} }
} }
......
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