LCOV - code coverage report
Current view: top level - src/snapshot - mksnapshot.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 42 91 46.2 %
Date: 2017-04-26 Functions: 6 10 60.0 %

          Line data    Source code
       1             : // Copyright 2006-2008 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include <errno.h>
       6             : #include <signal.h>
       7             : #include <stdio.h>
       8             : 
       9             : #include "include/libplatform/libplatform.h"
      10             : #include "src/assembler.h"
      11             : #include "src/base/platform/platform.h"
      12             : #include "src/flags.h"
      13             : #include "src/list.h"
      14             : #include "src/msan.h"
      15             : #include "src/snapshot/natives.h"
      16             : #include "src/snapshot/partial-serializer.h"
      17             : #include "src/snapshot/startup-serializer.h"
      18             : 
      19             : using namespace v8;
      20             : 
      21             : class SnapshotWriter {
      22             :  public:
      23           1 :   SnapshotWriter() : snapshot_cpp_path_(NULL), snapshot_blob_path_(NULL) {}
      24             : 
      25             :   void SetSnapshotFile(const char* snapshot_cpp_file) {
      26           0 :     snapshot_cpp_path_ = snapshot_cpp_file;
      27             :   }
      28             : 
      29             :   void SetStartupBlobFile(const char* snapshot_blob_file) {
      30           1 :     snapshot_blob_path_ = snapshot_blob_file;
      31             :   }
      32             : 
      33           2 :   void WriteSnapshot(v8::StartupData blob) const {
      34             :     // TODO(crbug/633159): if we crash before the files have been fully created,
      35             :     // we end up with a corrupted snapshot file. The build step would succeed,
      36             :     // but the build target is unusable. Ideally we would write out temporary
      37             :     // files and only move them to the final destination as last step.
      38             : 
      39             :     // Tell MSan to ignore uninitialized padding in the blob.
      40             :     MSAN_MEMORY_IS_INITIALIZED(blob.data, blob.raw_size);
      41             : 
      42             :     i::Vector<const i::byte> blob_vector(
      43           1 :         reinterpret_cast<const i::byte*>(blob.data), blob.raw_size);
      44           1 :     MaybeWriteSnapshotFile(blob_vector);
      45           1 :     MaybeWriteStartupBlob(blob_vector);
      46           1 :   }
      47             : 
      48             :  private:
      49           4 :   void MaybeWriteStartupBlob(const i::Vector<const i::byte>& blob) const {
      50           2 :     if (!snapshot_blob_path_) return;
      51             : 
      52           1 :     FILE* fp = GetFileDescriptorOrDie(snapshot_blob_path_);
      53           2 :     size_t written = fwrite(blob.begin(), 1, blob.length(), fp);
      54           1 :     fclose(fp);
      55           1 :     if (written != static_cast<size_t>(blob.length())) {
      56           0 :       i::PrintF("Writing snapshot file failed.. Aborting.\n");
      57           0 :       remove(snapshot_blob_path_);
      58           0 :       exit(1);
      59             :     }
      60             :   }
      61             : 
      62           1 :   void MaybeWriteSnapshotFile(const i::Vector<const i::byte>& blob) const {
      63           2 :     if (!snapshot_cpp_path_) return;
      64             : 
      65           0 :     FILE* fp = GetFileDescriptorOrDie(snapshot_cpp_path_);
      66             : 
      67           0 :     WriteFilePrefix(fp);
      68           0 :     WriteData(fp, blob);
      69           0 :     WriteFileSuffix(fp);
      70             : 
      71           0 :     fclose(fp);
      72             :   }
      73             : 
      74           0 :   static void WriteFilePrefix(FILE* fp) {
      75             :     fprintf(fp, "// Autogenerated snapshot file. Do not edit.\n\n");
      76             :     fprintf(fp, "#include \"src/v8.h\"\n");
      77             :     fprintf(fp, "#include \"src/base/platform/platform.h\"\n\n");
      78             :     fprintf(fp, "#include \"src/snapshot/snapshot.h\"\n\n");
      79             :     fprintf(fp, "namespace v8 {\n");
      80             :     fprintf(fp, "namespace internal {\n\n");
      81           0 :   }
      82             : 
      83           0 :   static void WriteFileSuffix(FILE* fp) {
      84             :     fprintf(fp, "const v8::StartupData* Snapshot::DefaultSnapshotBlob() {\n");
      85             :     fprintf(fp, "  return &blob;\n");
      86             :     fprintf(fp, "}\n\n");
      87             :     fprintf(fp, "}  // namespace internal\n");
      88             :     fprintf(fp, "}  // namespace v8\n");
      89           0 :   }
      90             : 
      91           0 :   static void WriteData(FILE* fp, const i::Vector<const i::byte>& blob) {
      92             :     fprintf(fp, "static const byte blob_data[] = {\n");
      93           0 :     WriteSnapshotData(fp, blob);
      94             :     fprintf(fp, "};\n");
      95             :     fprintf(fp, "static const int blob_size = %d;\n", blob.length());
      96             :     fprintf(fp, "static const v8::StartupData blob =\n");
      97             :     fprintf(fp, "{ (const char*) blob_data, blob_size };\n");
      98           0 :   }
      99             : 
     100           0 :   static void WriteSnapshotData(FILE* fp,
     101           0 :                                 const i::Vector<const i::byte>& blob) {
     102           0 :     for (int i = 0; i < blob.length(); i++) {
     103           0 :       if ((i & 0x1f) == 0x1f) fprintf(fp, "\n");
     104           0 :       if (i > 0) fprintf(fp, ",");
     105           0 :       fprintf(fp, "%u", static_cast<unsigned char>(blob.at(i)));
     106             :     }
     107             :     fprintf(fp, "\n");
     108           0 :   }
     109             : 
     110           1 :   static FILE* GetFileDescriptorOrDie(const char* filename) {
     111           1 :     FILE* fp = base::OS::FOpen(filename, "wb");
     112           1 :     if (fp == NULL) {
     113           0 :       i::PrintF("Unable to open file \"%s\" for writing.\n", filename);
     114           0 :       exit(1);
     115             :     }
     116           1 :     return fp;
     117             :   }
     118             : 
     119             :   const char* snapshot_cpp_path_;
     120             :   const char* snapshot_blob_path_;
     121             : };
     122             : 
     123           2 : char* GetExtraCode(char* filename, const char* description) {
     124           2 :   if (filename == NULL || strlen(filename) == 0) return NULL;
     125             :   ::printf("Loading script for %s: %s\n", description, filename);
     126           0 :   FILE* file = base::OS::FOpen(filename, "rb");
     127           0 :   if (file == NULL) {
     128           0 :     fprintf(stderr, "Failed to open '%s': errno %d\n", filename, errno);
     129           0 :     exit(1);
     130             :   }
     131           0 :   fseek(file, 0, SEEK_END);
     132           0 :   size_t size = ftell(file);
     133           0 :   rewind(file);
     134           0 :   char* chars = new char[size + 1];
     135           0 :   chars[size] = '\0';
     136           0 :   for (size_t i = 0; i < size;) {
     137           0 :     size_t read = fread(&chars[i], 1, size - i, file);
     138           0 :     if (ferror(file)) {
     139           0 :       fprintf(stderr, "Failed to read '%s': errno %d\n", filename, errno);
     140           0 :       exit(1);
     141             :     }
     142           0 :     i += read;
     143             :   }
     144           0 :   fclose(file);
     145           0 :   return chars;
     146             : }
     147             : 
     148             : 
     149           1 : int main(int argc, char** argv) {
     150             :   // Make mksnapshot runs predictable to create reproducible snapshots.
     151           1 :   i::FLAG_predictable = true;
     152             : 
     153             :   // Print the usage if an error occurs when parsing the command line
     154             :   // flags or if the help flag is set.
     155           1 :   int result = i::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
     156           1 :   if (result > 0 || (argc > 3) || i::FLAG_help) {
     157             :     ::printf("Usage: %s --startup_src=... --startup_blob=... [extras]\n",
     158           0 :              argv[0]);
     159           0 :     i::FlagList::PrintHelp();
     160           0 :     return !i::FLAG_help;
     161             :   }
     162             : 
     163             :   i::CpuFeatures::Probe(true);
     164           1 :   V8::InitializeICUDefaultLocation(argv[0]);
     165           1 :   v8::Platform* platform = v8::platform::CreateDefaultPlatform();
     166           1 :   v8::V8::InitializePlatform(platform);
     167           1 :   v8::V8::Initialize();
     168             : 
     169             :   {
     170             :     SnapshotWriter writer;
     171           1 :     if (i::FLAG_startup_src) writer.SetSnapshotFile(i::FLAG_startup_src);
     172           1 :     if (i::FLAG_startup_blob) writer.SetStartupBlobFile(i::FLAG_startup_blob);
     173             : 
     174           1 :     char* embed_script = GetExtraCode(argc >= 2 ? argv[1] : NULL, "embedding");
     175           1 :     StartupData blob = v8::V8::CreateSnapshotDataBlob(embed_script);
     176           1 :     delete[] embed_script;
     177             : 
     178           1 :     char* warmup_script = GetExtraCode(argc >= 3 ? argv[2] : NULL, "warm up");
     179           1 :     if (warmup_script) {
     180           0 :       StartupData cold = blob;
     181           0 :       blob = v8::V8::WarmUpSnapshotDataBlob(cold, warmup_script);
     182           0 :       delete[] cold.data;
     183           0 :       delete[] warmup_script;
     184             :     }
     185             : 
     186           1 :     CHECK(blob.data);
     187           1 :     writer.WriteSnapshot(blob);
     188           1 :     delete[] blob.data;
     189             :   }
     190             : 
     191           1 :   V8::Dispose();
     192           1 :   V8::ShutdownPlatform();
     193           1 :   delete platform;
     194             :   return 0;
     195             : }

Generated by: LCOV version 1.10