1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2008 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <errno.h> 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <signal.h> 7958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include <stdio.h> 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "include/libplatform/libplatform.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/assembler.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/platform/platform.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/flags.h" 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/list.h" 14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/snapshot/natives.h" 153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#include "src/snapshot/partial-serializer.h" 163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#include "src/snapshot/startup-serializer.h" 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing namespace v8; 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass SnapshotWriter { 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SnapshotWriter() : fp_(NULL), startup_blob_file_(NULL) {} 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ~SnapshotWriter() { 25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (fp_) fclose(fp_); 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (startup_blob_file_) fclose(startup_blob_file_); 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void SetSnapshotFile(const char* snapshot_file) { 30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (snapshot_file != NULL) fp_ = GetFileDescriptorOrDie(snapshot_file); 31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SetStartupBlobFile(const char* startup_blob_file) { 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (startup_blob_file != NULL) 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch startup_blob_file_ = GetFileDescriptorOrDie(startup_blob_file); 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 37257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier void WriteSnapshot(v8::StartupData blob) const { 39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier i::Vector<const i::byte> blob_vector( 40958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reinterpret_cast<const i::byte*>(blob.data), blob.raw_size); 41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MaybeWriteSnapshotFile(blob_vector); 42958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MaybeWriteStartupBlob(blob_vector); 43257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 46958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier void MaybeWriteStartupBlob(const i::Vector<const i::byte>& blob) const { 47958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!startup_blob_file_) return; 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 49958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier size_t written = fwrite(blob.begin(), 1, blob.length(), startup_blob_file_); 50958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (written != static_cast<size_t>(blob.length())) { 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch i::PrintF("Writing snapshot file failed.. Aborting.\n"); 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch exit(1); 53257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 54257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void MaybeWriteSnapshotFile(const i::Vector<const i::byte>& blob) const { 57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!fp_) return; 58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WriteFilePrefix(); 60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier WriteData(blob); 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WriteFileSuffix(); 62257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void WriteFilePrefix() const { 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fprintf(fp_, "// Autogenerated snapshot file. Do not edit.\n\n"); 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fprintf(fp_, "#include \"src/v8.h\"\n"); 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fprintf(fp_, "#include \"src/base/platform/platform.h\"\n\n"); 68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch fprintf(fp_, "#include \"src/snapshot/snapshot.h\"\n\n"); 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fprintf(fp_, "namespace v8 {\n"); 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fprintf(fp_, "namespace internal {\n\n"); 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 72257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void WriteFileSuffix() const { 74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch fprintf(fp_, "const v8::StartupData* Snapshot::DefaultSnapshotBlob() {\n"); 75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch fprintf(fp_, " return &blob;\n"); 76958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier fprintf(fp_, "}\n\n"); 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fprintf(fp_, "} // namespace internal\n"); 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fprintf(fp_, "} // namespace v8\n"); 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 80257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 81958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier void WriteData(const i::Vector<const i::byte>& blob) const { 8213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch fprintf(fp_, "static const byte blob_data[] = {\n"); 83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier WriteSnapshotData(blob); 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fprintf(fp_, "};\n"); 85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier fprintf(fp_, "static const int blob_size = %d;\n", blob.length()); 86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch fprintf(fp_, "static const v8::StartupData blob =\n"); 87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch fprintf(fp_, "{ (const char*) blob_data, blob_size };\n"); 883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 90958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier void WriteSnapshotData(const i::Vector<const i::byte>& blob) const { 91958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for (int i = 0; i < blob.length(); i++) { 92958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if ((i & 0x1f) == 0x1f) fprintf(fp_, "\n"); 93958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (i > 0) fprintf(fp_, ","); 94958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier fprintf(fp_, "%u", static_cast<unsigned char>(blob.at(i))); 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fprintf(fp_, "\n"); 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FILE* GetFileDescriptorOrDie(const char* filename) { 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FILE* fp = base::OS::FOpen(filename, "wb"); 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (fp == NULL) { 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch i::PrintF("Unable to open file \"%s\" for writing.\n", filename); 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch exit(1); 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return fp; 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FILE* fp_; 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FILE* startup_blob_file_; 110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}; 111e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochchar* GetExtraCode(char* filename, const char* description) { 113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (filename == NULL || strlen(filename) == 0) return NULL; 1143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch ::printf("Loading script for %s: %s\n", description, filename); 115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FILE* file = base::OS::FOpen(filename, "rb"); 116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (file == NULL) { 117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch fprintf(stderr, "Failed to open '%s': errno %d\n", filename, errno); 118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch exit(1); 119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch fseek(file, 0, SEEK_END); 121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch size_t size = ftell(file); 122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch rewind(file); 123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch char* chars = new char[size + 1]; 124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch chars[size] = '\0'; 125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (size_t i = 0; i < size;) { 126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch size_t read = fread(&chars[i], 1, size - i, file); 127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (ferror(file)) { 128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch fprintf(stderr, "Failed to read '%s': errno %d\n", filename, errno); 129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch exit(1); 130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch i += read; 132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch fclose(file); 134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return chars; 135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint main(int argc, char** argv) { 1393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Make mksnapshot runs predictable to create reproducible snapshots. 1403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch i::FLAG_predictable = true; 141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print the usage if an error occurs when parsing the command line 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // flags or if the help flag is set. 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = i::FlagList::SetFlagsFromCommandLine(&argc, argv, true); 1453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (result > 0 || (argc > 3) || i::FLAG_help) { 146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ::printf("Usage: %s --startup_src=... --startup_blob=... [extras]\n", 147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch argv[0]); 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::FlagList::PrintHelp(); 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return !i::FLAG_help; 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch i::CpuFeatures::Probe(true); 15313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch V8::InitializeICUDefaultLocation(argv[0]); 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Platform* platform = v8::platform::CreateDefaultPlatform(); 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::V8::InitializePlatform(platform); 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::V8::Initialize(); 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier { 159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SnapshotWriter writer; 160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (i::FLAG_startup_src) writer.SetSnapshotFile(i::FLAG_startup_src); 161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (i::FLAG_startup_blob) writer.SetStartupBlobFile(i::FLAG_startup_blob); 1623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 1633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch char* embed_script = GetExtraCode(argc >= 2 ? argv[1] : NULL, "embedding"); 1643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch StartupData blob = v8::V8::CreateSnapshotDataBlob(embed_script); 1653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch delete[] embed_script; 1663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 1673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch char* warmup_script = GetExtraCode(argc >= 3 ? argv[2] : NULL, "warm up"); 1683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (warmup_script) { 1693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch StartupData cold = blob; 1703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch blob = v8::V8::WarmUpSnapshotDataBlob(cold, warmup_script); 1713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch delete[] cold.data; 1723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch delete[] warmup_script; 1733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 1743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CHECK(blob.data); 176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier writer.WriteSnapshot(blob); 177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier delete[] blob.data; 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V8::Dispose(); 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V8::ShutdownPlatform(); 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch delete platform; 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 0; 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 185