Embed custom script into the snapshot.
authoryangguo <yangguo@chromium.org>
Mon, 12 Jan 2015 15:26:20 +0000 (07:26 -0800)
committerCommit bot <commit-bot@chromium.org>
Mon, 12 Jan 2015 15:26:31 +0000 (15:26 +0000)
R=vogelheim@chromium.org

Review URL: https://codereview.chromium.org/845973003

Cr-Commit-Position: refs/heads/master@{#26029}

Makefile
include/v8.h
src/api.cc
src/execution.cc
src/mksnapshot.cc
src/snapshot-common.cc
tools/gyp/v8.gyp

index 9b53f86..03d8013 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -153,6 +153,9 @@ ifeq ($(asan), on)
     GYPFLAGS += -Dlsan=1
   endif
 endif
+ifdef embedscript
+  GYPFLAGS += -Dembed_script=$(embedscript)
+endif
 
 # arm specific flags.
 # arm_version=<number | "default">
index a87ad01..e3d5254 100644 (file)
@@ -5336,7 +5336,7 @@ class V8_EXPORT V8 {
    * Returns { NULL, 0 } on failure.
    * The caller owns the data array in the return value.
    */
-  static StartupData CreateSnapshotDataBlob();
+  static StartupData CreateSnapshotDataBlob(char* custom_source = NULL);
 
   /**
    * Adds a message listener.
index 51cd6c8..99b0bb8 100644 (file)
@@ -206,7 +206,21 @@ void V8::SetSnapshotDataBlob(StartupData* snapshot_blob) {
 }
 
 
-StartupData V8::CreateSnapshotDataBlob() {
+bool RunExtraCode(Isolate* isolate, char* utf8_source) {
+  // Run custom script if provided.
+  TryCatch try_catch;
+  Local<String> source_string = String::NewFromUtf8(isolate, utf8_source);
+  if (try_catch.HasCaught()) return false;
+  ScriptOrigin origin(String::NewFromUtf8(isolate, "<embedded script>"));
+  ScriptCompiler::Source source(source_string, origin);
+  Local<Script> script = ScriptCompiler::Compile(isolate, &source);
+  if (try_catch.HasCaught()) return false;
+  script->Run();
+  return !try_catch.HasCaught();
+}
+
+
+StartupData V8::CreateSnapshotDataBlob(char* custom_source) {
   Isolate::CreateParams params;
   params.enable_serializer = true;
   Isolate* isolate = v8::Isolate::New(params);
@@ -217,7 +231,12 @@ StartupData V8::CreateSnapshotDataBlob() {
     Persistent<Context> context;
     {
       HandleScope handle_scope(isolate);
-      context.Reset(isolate, Context::New(isolate));
+      Handle<Context> new_context = Context::New(isolate);
+      context.Reset(isolate, new_context);
+      if (custom_source != NULL) {
+        Context::Scope context_scope(new_context);
+        if (!RunExtraCode(isolate, custom_source)) context.Reset();
+      }
     }
     if (!context.IsEmpty()) {
       // Make sure all builtin scripts are cached.
index a85effd..b09904d 100644 (file)
@@ -37,10 +37,15 @@ void StackGuard::reset_limits(const ExecutionAccess& lock) {
 static void PrintDeserializedCodeInfo(Handle<JSFunction> function) {
   if (function->code() == function->shared()->code() &&
       function->shared()->deserialized()) {
-    PrintF("Running deserialized script ");
+    PrintF("[Running deserialized script");
     Object* script = function->shared()->script();
-    if (script->IsScript()) Script::cast(script)->name()->ShortPrint();
-    PrintF("\n");
+    if (script->IsScript()) {
+      Object* name = Script::cast(script)->name();
+      if (name->IsString()) {
+        PrintF(": %s", String::cast(name)->ToCString().get());
+      }
+    }
+    PrintF("]\n");
   }
 }
 
index 988e7da..bc18aeb 100644 (file)
@@ -111,6 +111,32 @@ class SnapshotWriter {
 };
 
 
+char* GetExtraCode(char* filename) {
+  if (filename == NULL || strlen(filename) == 0) return NULL;
+  ::printf("Embedding extra script: %s\n", filename);
+  FILE* file = base::OS::FOpen(filename, "rb");
+  if (file == NULL) {
+    fprintf(stderr, "Failed to open '%s': errno %d\n", filename, errno);
+    exit(1);
+  }
+  fseek(file, 0, SEEK_END);
+  int size = ftell(file);
+  rewind(file);
+  char* chars = new char[size + 1];
+  chars[size] = '\0';
+  for (int i = 0; i < size;) {
+    int read = static_cast<int>(fread(&chars[i], 1, size - i, file));
+    if (read < 0) {
+      fprintf(stderr, "Failed to read '%s': errno %d\n", filename, errno);
+      exit(1);
+    }
+    i += read;
+  }
+  fclose(file);
+  return chars;
+}
+
+
 int main(int argc, char** argv) {
   // By default, log code create information in the snapshot.
   i::FLAG_log_code = true;
@@ -124,7 +150,7 @@ int main(int argc, char** argv) {
   // Print the usage if an error occurs when parsing the command line
   // flags or if the help flag is set.
   int result = i::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
-  if (result > 0 || argc != 2 || i::FLAG_help) {
+  if (result > 0 || (argc != 2 && argc != 3) || i::FLAG_help) {
     ::printf("Usage: %s [flag] ... outfile\n", argv[0]);
     i::FlagList::PrintHelp();
     return !i::FLAG_help;
@@ -139,9 +165,11 @@ int main(int argc, char** argv) {
   {
     SnapshotWriter writer(argv[1]);
     if (i::FLAG_startup_blob) writer.SetStartupBlobFile(i::FLAG_startup_blob);
-    StartupData blob = v8::V8::CreateSnapshotDataBlob();
+    char* extra_code = GetExtraCode(argc == 3 ? argv[2] : NULL);
+    StartupData blob = v8::V8::CreateSnapshotDataBlob(extra_code);
     CHECK(blob.data);
     writer.WriteSnapshot(blob);
+    delete[] extra_code;
     delete[] blob.data;
   }
 
index dc7f655..e38872d 100644 (file)
@@ -25,12 +25,14 @@ bool Snapshot::Initialize(Isolate* isolate) {
   if (FLAG_profile_deserialization) timer.Start();
 
   const v8::StartupData blob = SnapshotBlob();
-  SnapshotData snapshot_data(ExtractStartupData(&blob));
+  Vector<const byte> startup_data = ExtractStartupData(&blob);
+  SnapshotData snapshot_data(startup_data);
   Deserializer deserializer(&snapshot_data);
   bool success = isolate->Init(&deserializer);
   if (FLAG_profile_deserialization) {
     double ms = timer.Elapsed().InMillisecondsF();
-    PrintF("[Snapshot loading and deserialization took %0.3f ms]\n", ms);
+    int bytes = startup_data.length();
+    PrintF("[Deserializing isolate (%d bytes) took %0.3f ms]\n", bytes, ms);
   }
   return success;
 }
@@ -38,13 +40,21 @@ bool Snapshot::Initialize(Isolate* isolate) {
 
 Handle<Context> Snapshot::NewContextFromSnapshot(Isolate* isolate) {
   if (!HaveASnapshotToStartFrom()) return Handle<Context>();
+  base::ElapsedTimer timer;
+  if (FLAG_profile_deserialization) timer.Start();
 
   const v8::StartupData blob = SnapshotBlob();
-  SnapshotData snapshot_data(ExtractContextData(&blob));
+  Vector<const byte> context_data = ExtractContextData(&blob);
+  SnapshotData snapshot_data(context_data);
   Deserializer deserializer(&snapshot_data);
   Object* root;
   deserializer.DeserializePartial(isolate, &root);
   CHECK(root->IsContext());
+  if (FLAG_profile_deserialization) {
+    double ms = timer.Elapsed().InMillisecondsF();
+    int bytes = context_data.length();
+    PrintF("[Deserializing context (%d bytes) took %0.3f ms]\n", bytes, ms);
+  }
   return Handle<Context>(Context::cast(root));
 }
 
index 83f49f0..2472b33 100644 (file)
@@ -30,6 +30,8 @@
     'icu_use_data_file_flag%': 0,
     'v8_code': 1,
     'v8_random_seed%': 314159265,
+    'embed_script%': "",
+    'mksnapshot_exec': '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)mksnapshot<(EXECUTABLE_SUFFIX)',
   },
   'includes': ['../../build/toolchain.gypi', '../../build/features.gypi'],
   'targets': [
         {
           'action_name': 'run_mksnapshot',
           'inputs': [
-            '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)mksnapshot<(EXECUTABLE_SUFFIX)',
+            '<(mksnapshot_exec)',
+            '<(embed_script)',
           ],
           'outputs': [
             '<(INTERMEDIATE_DIR)/snapshot.cc',
             ],
           },
           'action': [
-            '<@(_inputs)',
+            '<(mksnapshot_exec)',
             '<@(mksnapshot_flags)',
-            '<@(INTERMEDIATE_DIR)/snapshot.cc'
+            '<@(INTERMEDIATE_DIR)/snapshot.cc',
+            '<(embed_script)',
           ],
         },
       ],
             {
               'action_name': 'run_mksnapshot (external)',
               'inputs': [
-                '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)mksnapshot<(EXECUTABLE_SUFFIX)',
+                '<(mksnapshot_exec)',
               ],
               'variables': {
                 'mksnapshot_flags': [
                         '<(PRODUCT_DIR)/snapshot_blob_host.bin',
                       ],
                       'action': [
-                        '<@(_inputs)',
+                        '<(mksnapshot_exec)',
                         '<@(mksnapshot_flags)',
                         '<@(INTERMEDIATE_DIR)/snapshot.cc',
                         '--startup_blob', '<(PRODUCT_DIR)/snapshot_blob_host.bin',
+                        '<(embed_script)',
                       ],
                     }, {
                       'outputs': [
                         '<(PRODUCT_DIR)/snapshot_blob.bin',
                       ],
                       'action': [
-                        '<@(_inputs)',
+                        '<(mksnapshot_exec)',
                         '<@(mksnapshot_flags)',
                         '<@(INTERMEDIATE_DIR)/snapshot.cc',
                         '--startup_blob', '<(PRODUCT_DIR)/snapshot_blob.bin',
+                        '<(embed_script)',
                       ],
                     }],
                   ],
                     '<(PRODUCT_DIR)/snapshot_blob.bin',
                   ],
                   'action': [
-                    '<@(_inputs)',
+                    '<(mksnapshot_exec)',
                     '<@(mksnapshot_flags)',
                     '<@(INTERMEDIATE_DIR)/snapshot.cc',
                     '--startup_blob', '<(PRODUCT_DIR)/snapshot_blob.bin',
+                    '<(embed_script)',
                   ],
                 }],
               ],