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/snapshot/natives.h" 15 #include "src/snapshot/serialize.h" 16 17 18 using namespace v8; 19 20 class SnapshotWriter { 21 public: 22 SnapshotWriter() : fp_(NULL), startup_blob_file_(NULL) {} 23 24 ~SnapshotWriter() { 25 if (fp_) fclose(fp_); 26 if (startup_blob_file_) fclose(startup_blob_file_); 27 } 28 29 void SetSnapshotFile(const char* snapshot_file) { 30 if (snapshot_file != NULL) fp_ = GetFileDescriptorOrDie(snapshot_file); 31 } 32 33 void SetStartupBlobFile(const char* startup_blob_file) { 34 if (startup_blob_file != NULL) 35 startup_blob_file_ = GetFileDescriptorOrDie(startup_blob_file); 36 } 37 38 void WriteSnapshot(v8::StartupData blob) const { 39 i::Vector<const i::byte> blob_vector( 40 reinterpret_cast<const i::byte*>(blob.data), blob.raw_size); 41 MaybeWriteSnapshotFile(blob_vector); 42 MaybeWriteStartupBlob(blob_vector); 43 } 44 45 private: 46 void MaybeWriteStartupBlob(const i::Vector<const i::byte>& blob) const { 47 if (!startup_blob_file_) return; 48 49 size_t written = fwrite(blob.begin(), 1, blob.length(), startup_blob_file_); 50 if (written != static_cast<size_t>(blob.length())) { 51 i::PrintF("Writing snapshot file failed.. Aborting.\n"); 52 exit(1); 53 } 54 } 55 56 void MaybeWriteSnapshotFile(const i::Vector<const i::byte>& blob) const { 57 if (!fp_) return; 58 59 WriteFilePrefix(); 60 WriteData(blob); 61 WriteFileSuffix(); 62 } 63 64 void WriteFilePrefix() const { 65 fprintf(fp_, "// Autogenerated snapshot file. Do not edit.\n\n"); 66 fprintf(fp_, "#include \"src/v8.h\"\n"); 67 fprintf(fp_, "#include \"src/base/platform/platform.h\"\n\n"); 68 fprintf(fp_, "#include \"src/snapshot/snapshot.h\"\n\n"); 69 fprintf(fp_, "namespace v8 {\n"); 70 fprintf(fp_, "namespace internal {\n\n"); 71 } 72 73 void WriteFileSuffix() const { 74 fprintf(fp_, "const v8::StartupData* Snapshot::DefaultSnapshotBlob() {\n"); 75 fprintf(fp_, " return &blob;\n"); 76 fprintf(fp_, "}\n\n"); 77 fprintf(fp_, "} // namespace internal\n"); 78 fprintf(fp_, "} // namespace v8\n"); 79 } 80 81 void WriteData(const i::Vector<const i::byte>& blob) const { 82 fprintf(fp_, "static const byte blob_data[] __attribute__((aligned(8))) = {\n"); 83 WriteSnapshotData(blob); 84 fprintf(fp_, "};\n"); 85 fprintf(fp_, "static const int blob_size = %d;\n", blob.length()); 86 fprintf(fp_, "static const v8::StartupData blob =\n"); 87 fprintf(fp_, "{ (const char*) blob_data, blob_size };\n"); 88 } 89 90 void WriteSnapshotData(const i::Vector<const i::byte>& blob) const { 91 for (int i = 0; i < blob.length(); i++) { 92 if ((i & 0x1f) == 0x1f) fprintf(fp_, "\n"); 93 if (i > 0) fprintf(fp_, ","); 94 fprintf(fp_, "%u", static_cast<unsigned char>(blob.at(i))); 95 } 96 fprintf(fp_, "\n"); 97 } 98 99 FILE* GetFileDescriptorOrDie(const char* filename) { 100 FILE* fp = base::OS::FOpen(filename, "wb"); 101 if (fp == NULL) { 102 i::PrintF("Unable to open file \"%s\" for writing.\n", filename); 103 exit(1); 104 } 105 return fp; 106 } 107 108 FILE* fp_; 109 FILE* startup_blob_file_; 110 }; 111 112 113 char* GetExtraCode(char* filename) { 114 if (filename == NULL || strlen(filename) == 0) return NULL; 115 ::printf("Embedding extra script: %s\n", filename); 116 FILE* file = base::OS::FOpen(filename, "rb"); 117 if (file == NULL) { 118 fprintf(stderr, "Failed to open '%s': errno %d\n", filename, errno); 119 exit(1); 120 } 121 fseek(file, 0, SEEK_END); 122 size_t size = ftell(file); 123 rewind(file); 124 char* chars = new char[size + 1]; 125 chars[size] = '\0'; 126 for (size_t i = 0; i < size;) { 127 size_t read = fread(&chars[i], 1, size - i, file); 128 if (ferror(file)) { 129 fprintf(stderr, "Failed to read '%s': errno %d\n", filename, errno); 130 exit(1); 131 } 132 i += read; 133 } 134 fclose(file); 135 return chars; 136 } 137 138 139 int main(int argc, char** argv) { 140 // By default, log code create information in the snapshot. 141 i::FLAG_log_code = true; 142 i::FLAG_logfile_per_isolate = false; 143 144 // Print the usage if an error occurs when parsing the command line 145 // flags or if the help flag is set. 146 int result = i::FlagList::SetFlagsFromCommandLine(&argc, argv, true); 147 if (result > 0 || (argc != 1 && argc != 2) || i::FLAG_help) { 148 ::printf("Usage: %s --startup_src=... --startup_blob=... [extras]\n", 149 argv[0]); 150 i::FlagList::PrintHelp(); 151 return !i::FLAG_help; 152 } 153 154 i::CpuFeatures::Probe(true); 155 V8::InitializeICU(); 156 v8::Platform* platform = v8::platform::CreateDefaultPlatform(); 157 v8::V8::InitializePlatform(platform); 158 v8::V8::Initialize(); 159 160 { 161 SnapshotWriter writer; 162 if (i::FLAG_startup_src) writer.SetSnapshotFile(i::FLAG_startup_src); 163 if (i::FLAG_startup_blob) writer.SetStartupBlobFile(i::FLAG_startup_blob); 164 char* extra_code = GetExtraCode(argc == 2 ? argv[1] : NULL); 165 StartupData blob = v8::V8::CreateSnapshotDataBlob(extra_code); 166 CHECK(blob.data); 167 writer.WriteSnapshot(blob); 168 delete[] extra_code; 169 delete[] blob.data; 170 } 171 172 V8::Dispose(); 173 V8::ShutdownPlatform(); 174 delete platform; 175 return 0; 176 } 177