Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Unified Diff: src/api.cc

Issue 1805903002: [serializer] Add API to warm up startup snapshot with an additional script. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix comment Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « include/v8.h ('k') | src/globals.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/api.cc
diff --git a/src/api.cc b/src/api.cc
index 647bd6e21bca049e94c62ce8cea89a8605acbe71..f933540ba3b1698528c7fee65b3aaa6941c6057c 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -341,12 +341,23 @@ void V8::SetSnapshotDataBlob(StartupData* snapshot_blob) {
i::V8::SetSnapshotBlob(snapshot_blob);
}
+namespace {
+
+class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
+ public:
+ virtual void* Allocate(size_t length) {
+ void* data = AllocateUninitialized(length);
+ return data == NULL ? data : memset(data, 0, length);
+ }
+ virtual void* AllocateUninitialized(size_t length) { return malloc(length); }
+ virtual void Free(void* data, size_t) { free(data); }
+};
bool RunExtraCode(Isolate* isolate, Local<Context> context,
- const char* utf8_source) {
- // Run custom script if provided.
+ const char* utf8_source, const char* name) {
base::ElapsedTimer timer;
timer.Start();
+ Context::Scope context_scope(context);
TryCatch try_catch(isolate);
Local<String> source_string;
if (!String::NewFromUtf8(isolate, utf8_source, NewStringType::kNormal)
@@ -354,7 +365,7 @@ bool RunExtraCode(Isolate* isolate, Local<Context> context,
return false;
}
Local<String> resource_name =
- String::NewFromUtf8(isolate, "<embedded script>", NewStringType::kNormal)
+ String::NewFromUtf8(isolate, name, NewStringType::kNormal)
.ToLocalChecked();
ScriptOrigin origin(resource_name);
ScriptCompiler::Source source(source_string, origin);
@@ -362,7 +373,7 @@ bool RunExtraCode(Isolate* isolate, Local<Context> context,
if (!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 took %0.3f ms\n",
+ i::PrintF("Executing custom snapshot script %s took %0.3f ms\n", name,
timer.Elapsed().InMillisecondsF());
}
timer.Stop();
@@ -370,92 +381,148 @@ bool RunExtraCode(Isolate* isolate, Local<Context> context,
return true;
}
+StartupData SerializeIsolateAndContext(
+ Isolate* isolate, Persistent<Context>* context,
+ i::Snapshot::Metadata metadata,
+ i::StartupSerializer::FunctionCodeHandling function_code_handling) {
+ if (context->IsEmpty()) return {NULL, 0};
-namespace {
+ i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
-class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
- public:
- virtual void* Allocate(size_t length) {
- void* data = AllocateUninitialized(length);
- return data == NULL ? data : memset(data, 0, length);
+ // If we don't do this then we end up with a stray root pointing at the
+ // context even after we have disposed of the context.
+ internal_isolate->heap()->CollectAllAvailableGarbage("mksnapshot");
+
+ // GC may have cleared weak cells, so compact any WeakFixedArrays
+ // found on the heap.
+ i::HeapIterator iterator(internal_isolate->heap(),
+ i::HeapIterator::kFilterUnreachable);
+ for (i::HeapObject* o = iterator.next(); o != NULL; o = iterator.next()) {
+ if (o->IsPrototypeInfo()) {
+ i::Object* prototype_users = i::PrototypeInfo::cast(o)->prototype_users();
+ if (prototype_users->IsWeakFixedArray()) {
+ i::WeakFixedArray* array = i::WeakFixedArray::cast(prototype_users);
+ array->Compact<i::JSObject::PrototypeRegistryCompactionCallback>();
+ }
+ } else if (o->IsScript()) {
+ i::Object* shared_list = i::Script::cast(o)->shared_function_infos();
+ if (shared_list->IsWeakFixedArray()) {
+ i::WeakFixedArray* array = i::WeakFixedArray::cast(shared_list);
+ array->Compact<i::WeakFixedArray::NullCallback>();
+ }
+ }
}
- virtual void* AllocateUninitialized(size_t length) { return malloc(length); }
- virtual void Free(void* data, size_t) { free(data); }
-};
+
+ i::Object* raw_context = *v8::Utils::OpenPersistent(*context);
+ context->Reset();
+
+ i::SnapshotByteSink snapshot_sink;
+ i::StartupSerializer ser(internal_isolate, &snapshot_sink,
+ function_code_handling);
+ ser.SerializeStrongReferences();
+
+ i::SnapshotByteSink context_sink;
+ i::PartialSerializer context_ser(internal_isolate, &ser, &context_sink);
+ context_ser.Serialize(&raw_context);
+ ser.SerializeWeakReferencesAndDeferred();
+
+ return i::Snapshot::CreateSnapshotBlob(ser, context_ser, metadata);
+}
} // namespace
+StartupData V8::CreateSnapshotDataBlob(const char* embedded_source) {
+ // Create a new isolate and a new context from scratch, optionally run
+ // a script to embed, and serialize to create a snapshot blob.
+ StartupData result = {NULL, 0};
+
+ base::ElapsedTimer timer;
+ timer.Start();
-StartupData V8::CreateSnapshotDataBlob(const char* custom_source) {
- i::Isolate* internal_isolate = new i::Isolate(true);
ArrayBufferAllocator allocator;
+ i::Isolate* internal_isolate = new i::Isolate(true);
internal_isolate->set_array_buffer_allocator(&allocator);
Isolate* isolate = reinterpret_cast<Isolate*>(internal_isolate);
- StartupData result = {NULL, 0};
+
{
- base::ElapsedTimer timer;
- timer.Start();
Isolate::Scope isolate_scope(isolate);
internal_isolate->Init(NULL);
Persistent<Context> context;
- i::Snapshot::Metadata metadata;
{
HandleScope handle_scope(isolate);
Local<Context> new_context = Context::New(isolate);
context.Reset(isolate, new_context);
- if (custom_source != NULL) {
- metadata.set_embeds_script(true);
- Context::Scope context_scope(new_context);
- if (!RunExtraCode(isolate, new_context, custom_source)) context.Reset();
+ if (embedded_source != NULL &&
+ !RunExtraCode(isolate, new_context, embedded_source, "<embedded>")) {
+ context.Reset();
}
}
- if (!context.IsEmpty()) {
- // If we don't do this then we end up with a stray root pointing at the
- // context even after we have disposed of the context.
- internal_isolate->heap()->CollectAllAvailableGarbage("mksnapshot");
-
- // GC may have cleared weak cells, so compact any WeakFixedArrays
- // found on the heap.
- i::HeapIterator iterator(internal_isolate->heap(),
- i::HeapIterator::kFilterUnreachable);
- for (i::HeapObject* o = iterator.next(); o != NULL; o = iterator.next()) {
- if (o->IsPrototypeInfo()) {
- i::Object* prototype_users =
- i::PrototypeInfo::cast(o)->prototype_users();
- if (prototype_users->IsWeakFixedArray()) {
- i::WeakFixedArray* array = i::WeakFixedArray::cast(prototype_users);
- array->Compact<i::JSObject::PrototypeRegistryCompactionCallback>();
- }
- } else if (o->IsScript()) {
- i::Object* shared_list = i::Script::cast(o)->shared_function_infos();
- if (shared_list->IsWeakFixedArray()) {
- i::WeakFixedArray* array = i::WeakFixedArray::cast(shared_list);
- array->Compact<i::WeakFixedArray::NullCallback>();
- }
- }
- }
- i::Object* raw_context = *v8::Utils::OpenPersistent(context);
- context.Reset();
+ i::Snapshot::Metadata metadata;
+ metadata.set_embeds_script(embedded_source != NULL);
- i::SnapshotByteSink snapshot_sink;
- i::StartupSerializer ser(internal_isolate, &snapshot_sink);
- ser.SerializeStrongReferences();
+ result = SerializeIsolateAndContext(
+ isolate, &context, metadata, i::StartupSerializer::CLEAR_FUNCTION_CODE);
+ DCHECK(context.IsEmpty());
+ }
+ isolate->Dispose();
- i::SnapshotByteSink context_sink;
- i::PartialSerializer context_ser(internal_isolate, &ser, &context_sink);
- context_ser.Serialize(&raw_context);
- ser.SerializeWeakReferencesAndDeferred();
+ if (i::FLAG_profile_deserialization) {
+ i::PrintF("Creating snapshot took %0.3f ms\n",
+ timer.Elapsed().InMillisecondsF());
+ }
+ timer.Stop();
+ return result;
+}
- result = i::Snapshot::CreateSnapshotBlob(ser, context_ser, metadata);
- }
- if (i::FLAG_profile_deserialization) {
- i::PrintF("Creating snapshot took %0.3f ms\n",
- timer.Elapsed().InMillisecondsF());
+StartupData V8::WarmUpSnapshotDataBlob(StartupData cold_snapshot_blob,
+ const char* warmup_source) {
+ CHECK(cold_snapshot_blob.raw_size > 0 && cold_snapshot_blob.data != NULL);
+ CHECK(warmup_source != NULL);
+ // 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.
+ StartupData result = {NULL, 0};
+
+ base::ElapsedTimer timer;
+ timer.Start();
+
+ ArrayBufferAllocator allocator;
+ i::Isolate* internal_isolate = new i::Isolate(true);
+ internal_isolate->set_array_buffer_allocator(&allocator);
+ internal_isolate->set_snapshot_blob(&cold_snapshot_blob);
+ Isolate* isolate = reinterpret_cast<Isolate*>(internal_isolate);
+
+ {
+ Isolate::Scope isolate_scope(isolate);
+ i::Snapshot::Initialize(internal_isolate);
+ Persistent<Context> context;
+ {
+ HandleScope handle_scope(isolate);
+ Local<Context> warmup_context = Context::New(isolate);
+ if (RunExtraCode(isolate, warmup_context, warmup_source, "<warm-up>")) {
+ Local<Context> fresh_context = Context::New(isolate);
+ context.Reset(isolate, fresh_context);
+ }
}
- timer.Stop();
+
+ i::Snapshot::Metadata metadata;
+ metadata.set_embeds_script(i::Snapshot::EmbedsScript(internal_isolate));
+
+ result = SerializeIsolateAndContext(
+ isolate, &context, metadata, i::StartupSerializer::KEEP_FUNCTION_CODE);
+ DCHECK(context.IsEmpty());
}
isolate->Dispose();
+
+ if (i::FLAG_profile_deserialization) {
+ i::PrintF("Warming up snapshot took %0.3f ms\n",
+ timer.Elapsed().InMillisecondsF());
+ }
+ timer.Stop();
return result;
}
« no previous file with comments | « include/v8.h ('k') | src/globals.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698