v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
mksnapshot.cc
Go to the documentation of this file.
1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include <errno.h>
29 #include <stdio.h>
30 #ifdef COMPRESS_STARTUP_DATA_BZ2
31 #include <bzlib.h>
32 #endif
33 #include <signal.h>
34 
35 #include "v8.h"
36 
37 #include "bootstrapper.h"
38 #include "flags.h"
39 #include "natives.h"
40 #include "platform.h"
41 #include "serialize.h"
42 #include "list.h"
43 
44 using namespace v8;
45 
46 static const unsigned int kMaxCounters = 256;
47 
48 // A single counter in a counter collection.
49 class Counter {
50  public:
51  static const int kMaxNameSize = 64;
52  int32_t* Bind(const char* name) {
53  int i;
54  for (i = 0; i < kMaxNameSize - 1 && name[i]; i++) {
55  name_[i] = name[i];
56  }
57  name_[i] = '\0';
58  return &counter_;
59  }
60  private:
61  int32_t counter_;
62  uint8_t name_[kMaxNameSize];
63 };
64 
65 
66 // A set of counters and associated information. An instance of this
67 // class is stored directly in the memory-mapped counters file if
68 // the --save-counters options is used
70  public:
72  magic_number_ = 0xDEADFACE;
73  max_counters_ = kMaxCounters;
74  max_name_size_ = Counter::kMaxNameSize;
75  counters_in_use_ = 0;
76  }
78  if (counters_in_use_ == kMaxCounters) return NULL;
79  return &counters_[counters_in_use_++];
80  }
81  private:
82  uint32_t magic_number_;
83  uint32_t max_counters_;
84  uint32_t max_name_size_;
85  uint32_t counters_in_use_;
86  Counter counters_[kMaxCounters];
87 };
88 
89 
90 class Compressor {
91  public:
92  virtual ~Compressor() {}
93  virtual bool Compress(i::Vector<char> input) = 0;
94  virtual i::Vector<char>* output() = 0;
95 };
96 
97 
99  public:
100  PartialSnapshotSink() : data_(), raw_size_(-1) { }
101  virtual ~PartialSnapshotSink() { data_.Free(); }
102  virtual void Put(int byte, const char* description) {
103  data_.Add(byte);
104  }
105  virtual int Position() { return data_.length(); }
106  void Print(FILE* fp) {
107  int length = Position();
108  for (int j = 0; j < length; j++) {
109  if ((j & 0x1f) == 0x1f) {
110  fprintf(fp, "\n");
111  }
112  if (j != 0) {
113  fprintf(fp, ",");
114  }
115  fprintf(fp, "%u", static_cast<unsigned char>(at(j)));
116  }
117  }
118  char at(int i) { return data_[i]; }
119  bool Compress(Compressor* compressor) {
120  ASSERT_EQ(-1, raw_size_);
121  raw_size_ = data_.length();
122  if (!compressor->Compress(data_.ToVector())) return false;
123  data_.Clear();
124  data_.AddAll(*compressor->output());
125  return true;
126  }
127  int raw_size() { return raw_size_; }
128 
129  private:
130  i::List<char> data_;
131  int raw_size_;
132 };
133 
134 
136  public:
137  explicit CppByteSink(const char* snapshot_file) {
138  fp_ = i::OS::FOpen(snapshot_file, "wb");
139  if (fp_ == NULL) {
140  i::PrintF("Unable to write to snapshot file \"%s\"\n", snapshot_file);
141  exit(1);
142  }
143  fprintf(fp_, "// Autogenerated snapshot file. Do not edit.\n\n");
144  fprintf(fp_, "#include \"v8.h\"\n");
145  fprintf(fp_, "#include \"platform.h\"\n\n");
146  fprintf(fp_, "#include \"snapshot.h\"\n\n");
147  fprintf(fp_, "namespace v8 {\nnamespace internal {\n\n");
148  fprintf(fp_, "const byte Snapshot::data_[] = {");
149  }
150 
151  virtual ~CppByteSink() {
152  fprintf(fp_, "const int Snapshot::size_ = %d;\n", Position());
153 #ifdef COMPRESS_STARTUP_DATA_BZ2
154  fprintf(fp_, "const byte* Snapshot::raw_data_ = NULL;\n");
155  fprintf(fp_,
156  "const int Snapshot::raw_size_ = %d;\n\n",
157  raw_size());
158 #else
159  fprintf(fp_,
160  "const byte* Snapshot::raw_data_ = Snapshot::data_;\n");
161  fprintf(fp_,
162  "const int Snapshot::raw_size_ = Snapshot::size_;\n\n");
163 #endif
164  fprintf(fp_, "} } // namespace v8::internal\n");
165  fclose(fp_);
166  }
167 
169  const char* prefix,
170  int new_space_used,
171  int pointer_space_used,
172  int data_space_used,
173  int code_space_used,
174  int map_space_used,
175  int cell_space_used) {
176  fprintf(fp_,
177  "const int Snapshot::%snew_space_used_ = %d;\n",
178  prefix,
179  new_space_used);
180  fprintf(fp_,
181  "const int Snapshot::%spointer_space_used_ = %d;\n",
182  prefix,
183  pointer_space_used);
184  fprintf(fp_,
185  "const int Snapshot::%sdata_space_used_ = %d;\n",
186  prefix,
187  data_space_used);
188  fprintf(fp_,
189  "const int Snapshot::%scode_space_used_ = %d;\n",
190  prefix,
191  code_space_used);
192  fprintf(fp_,
193  "const int Snapshot::%smap_space_used_ = %d;\n",
194  prefix,
195  map_space_used);
196  fprintf(fp_,
197  "const int Snapshot::%scell_space_used_ = %d;\n",
198  prefix,
199  cell_space_used);
200  }
201 
203  int length = partial_sink_.Position();
204  fprintf(fp_, "};\n\n");
205  fprintf(fp_, "const int Snapshot::context_size_ = %d;\n", length);
206 #ifdef COMPRESS_STARTUP_DATA_BZ2
207  fprintf(fp_,
208  "const int Snapshot::context_raw_size_ = %d;\n",
209  partial_sink_.raw_size());
210 #else
211  fprintf(fp_,
212  "const int Snapshot::context_raw_size_ = "
213  "Snapshot::context_size_;\n");
214 #endif
215  fprintf(fp_, "const byte Snapshot::context_data_[] = {\n");
216  partial_sink_.Print(fp_);
217  fprintf(fp_, "};\n\n");
218 #ifdef COMPRESS_STARTUP_DATA_BZ2
219  fprintf(fp_, "const byte* Snapshot::context_raw_data_ = NULL;\n");
220 #else
221  fprintf(fp_, "const byte* Snapshot::context_raw_data_ ="
222  " Snapshot::context_data_;\n");
223 #endif
224  }
225 
226  void WriteSnapshot() {
227  Print(fp_);
228  }
229 
230  PartialSnapshotSink* partial_sink() { return &partial_sink_; }
231 
232  private:
233  FILE* fp_;
234  PartialSnapshotSink partial_sink_;
235 };
236 
237 
238 #ifdef COMPRESS_STARTUP_DATA_BZ2
239 class BZip2Compressor : public Compressor {
240  public:
241  BZip2Compressor() : output_(NULL) {}
242  virtual ~BZip2Compressor() {
243  delete output_;
244  }
245  virtual bool Compress(i::Vector<char> input) {
246  delete output_;
247  output_ = new i::ScopedVector<char>((input.length() * 101) / 100 + 1000);
248  unsigned int output_length_ = output_->length();
249  int result = BZ2_bzBuffToBuffCompress(output_->start(), &output_length_,
250  input.start(), input.length(),
251  9, 1, 0);
252  if (result == BZ_OK) {
253  output_->Truncate(output_length_);
254  return true;
255  } else {
256  fprintf(stderr, "bzlib error code: %d\n", result);
257  return false;
258  }
259  }
260  virtual i::Vector<char>* output() { return output_; }
261 
262  private:
263  i::ScopedVector<char>* output_;
264 };
265 
266 
267 class BZip2Decompressor : public StartupDataDecompressor {
268  public:
269  virtual ~BZip2Decompressor() { }
270 
271  protected:
272  virtual int DecompressData(char* raw_data,
273  int* raw_data_size,
274  const char* compressed_data,
275  int compressed_data_size) {
278  unsigned int decompressed_size = *raw_data_size;
279  int result =
280  BZ2_bzBuffToBuffDecompress(raw_data,
281  &decompressed_size,
282  const_cast<char*>(compressed_data),
283  compressed_data_size,
284  0, 1);
285  if (result == BZ_OK) {
286  *raw_data_size = decompressed_size;
287  }
288  return result;
289  }
290 };
291 #endif
292 
293 
294 int main(int argc, char** argv) {
295  // By default, log code create information in the snapshot.
296  i::FLAG_log_code = true;
297 
298  // Print the usage if an error occurs when parsing the command line
299  // flags or if the help flag is set.
300  int result = i::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
301  if (result > 0 || argc != 2 || i::FLAG_help) {
302  ::printf("Usage: %s [flag] ... outfile\n", argv[0]);
304  return !i::FLAG_help;
305  }
306 #ifdef COMPRESS_STARTUP_DATA_BZ2
307  BZip2Decompressor natives_decompressor;
308  int bz2_result = natives_decompressor.Decompress();
309  if (bz2_result != BZ_OK) {
310  fprintf(stderr, "bzip error code: %d\n", bz2_result);
311  exit(1);
312  }
313 #endif
316  if (context.IsEmpty()) {
317  fprintf(stderr,
318  "\nException thrown while compiling natives - see above.\n\n");
319  exit(1);
320  }
321  if (i::FLAG_extra_code != NULL) {
322  context->Enter();
323  // Capture 100 frames if anything happens.
325  HandleScope scope;
326  const char* name = i::FLAG_extra_code;
327  FILE* file = i::OS::FOpen(name, "rb");
328  if (file == NULL) {
329  fprintf(stderr, "Failed to open '%s': errno %d\n", name, errno);
330  exit(1);
331  }
332 
333  fseek(file, 0, SEEK_END);
334  int size = ftell(file);
335  rewind(file);
336 
337  char* chars = new char[size + 1];
338  chars[size] = '\0';
339  for (int i = 0; i < size;) {
340  int read = static_cast<int>(fread(&chars[i], 1, size - i, file));
341  if (read < 0) {
342  fprintf(stderr, "Failed to read '%s': errno %d\n", name, errno);
343  exit(1);
344  }
345  i += read;
346  }
347  fclose(file);
348  Local<String> source = String::New(chars);
349  TryCatch try_catch;
350  Local<Script> script = Script::Compile(source);
351  if (try_catch.HasCaught()) {
352  fprintf(stderr, "Failure compiling '%s' (see above)\n", name);
353  exit(1);
354  }
355  script->Run();
356  if (try_catch.HasCaught()) {
357  fprintf(stderr, "Failure running '%s'\n", name);
358  Local<Message> message = try_catch.Message();
359  Local<String> message_string = message->Get();
360  Local<String> message_line = message->GetSourceLine();
361  int len = 2 + message_string->Utf8Length() + message_line->Utf8Length();
362  char* buf = new char(len);
363  message_string->WriteUtf8(buf);
364  fprintf(stderr, "%s at line %d\n", buf, message->GetLineNumber());
365  message_line->WriteUtf8(buf);
366  fprintf(stderr, "%s\n", buf);
367  int from = message->GetStartColumn();
368  int to = message->GetEndColumn();
369  int i;
370  for (i = 0; i < from; i++) fprintf(stderr, " ");
371  for ( ; i <= to; i++) fprintf(stderr, "^");
372  fprintf(stderr, "\n");
373  exit(1);
374  }
375  context->Exit();
376  }
377  // Make sure all builtin scripts are cached.
378  { HandleScope scope;
379  for (int i = 0; i < i::Natives::GetBuiltinsCount(); i++) {
380  i::Isolate::Current()->bootstrapper()->NativesSourceLookup(i);
381  }
382  }
383  // If we don't do this then we end up with a stray root pointing at the
384  // context even after we have disposed of the context.
385  HEAP->CollectAllGarbage(i::Heap::kNoGCFlags, "mksnapshot");
386  i::Object* raw_context = *(v8::Utils::OpenHandle(*context));
387  context.Dispose();
388  CppByteSink sink(argv[1]);
389  // This results in a somewhat smaller snapshot, probably because it gets rid
390  // of some things that are cached between garbage collections.
391  i::StartupSerializer ser(&sink);
393 
394  i::PartialSerializer partial_ser(&ser, sink.partial_sink());
395  partial_ser.Serialize(&raw_context);
396 
398 
399 #ifdef COMPRESS_STARTUP_DATA_BZ2
400  BZip2Compressor compressor;
401  if (!sink.Compress(&compressor))
402  return 1;
403  if (!sink.partial_sink()->Compress(&compressor))
404  return 1;
405 #endif
406  sink.WriteSnapshot();
407  sink.WritePartialSnapshot();
408 
409  sink.WriteSpaceUsed(
410  "context_",
411  partial_ser.CurrentAllocationAddress(i::NEW_SPACE),
412  partial_ser.CurrentAllocationAddress(i::OLD_POINTER_SPACE),
413  partial_ser.CurrentAllocationAddress(i::OLD_DATA_SPACE),
414  partial_ser.CurrentAllocationAddress(i::CODE_SPACE),
415  partial_ser.CurrentAllocationAddress(i::MAP_SPACE),
416  partial_ser.CurrentAllocationAddress(i::CELL_SPACE));
417  sink.WriteSpaceUsed(
418  "",
425  return 0;
426 }
int CurrentAllocationAddress(int space)
Definition: serialize.h:465
static Local< Script > Compile(Handle< String > source, ScriptOrigin *origin=NULL, ScriptData *pre_data=NULL, Handle< String > script_data=Handle< String >())
Definition: api.cc:1568
V8EXPORT int WriteUtf8(char *buffer, int length=-1, int *nchars_ref=NULL, int options=NO_OPTIONS) const
Definition: api.cc:3852
unsigned char byte
Definition: disasm.h:33
void Dispose()
Definition: v8.h:4235
void PrintF(const char *format,...)
Definition: v8utils.cc:40
void WriteSnapshot()
Definition: mksnapshot.cc:226
virtual void Serialize(Object **o)
Definition: serialize.cc:1080
bool HasCaught() const
Definition: api.cc:1703
virtual bool Compress(i::Vector< char > input)=0
Local< String > Get() const
Definition: api.cc:1781
static void SetCaptureStackTraceForUncaughtExceptions(bool capture, int frame_limit=10, StackTrace::StackTraceOptions options=StackTrace::kOverview)
Definition: api.cc:5303
static V8EXPORT Local< String > New(const char *data, int length=-1)
Definition: api.cc:4779
static void PrintHelp()
Definition: flags.cc:519
virtual void SerializeStrongReferences()
Definition: serialize.cc:1066
void WritePartialSnapshot()
Definition: mksnapshot.cc:202
int int32_t
Definition: unicode.cc:47
v8::Handle< v8::Value > Print(const v8::Arguments &args)
bool Compress(Compressor *compressor)
Definition: mksnapshot.cc:119
static const int kMaxNameSize
Definition: d8.h:47
int32_t * Bind(const char *name)
Definition: mksnapshot.cc:52
int GetEndColumn() const
Definition: api.cc:1928
T * start() const
Definition: utils.h:390
PartialSnapshotSink * partial_sink()
Definition: mksnapshot.cc:230
static const int kNoGCFlags
Definition: heap.h:1081
V8EXPORT int Utf8Length() const
Definition: api.cc:3748
virtual ~CppByteSink()
Definition: mksnapshot.cc:151
static FILE * FOpen(const char *path, const char *mode)
int main(int argc, char **argv)
Definition: mksnapshot.cc:294
static void Enable()
Definition: serialize.h:470
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random allows verbose printing trace parsing and preparsing Check icache flushes in ARM and MIPS simulator Stack alingment in bytes in print stack trace when throwing exceptions randomize hashes to avoid predictable hash Fixed seed to use to hash property activate a timer that switches between V8 threads testing_bool_flag float flag Seed used for threading test randomness A filename with extra code to be included in the Print usage message
int length() const
Definition: utils.h:384
int GetLineNumber() const
Definition: api.cc:1873
Counter * GetNextCounter()
Definition: mksnapshot.cc:77
virtual ~Compressor()
Definition: mksnapshot.cc:92
virtual ~PartialSnapshotSink()
Definition: mksnapshot.cc:101
#define HEAP
Definition: isolate.h:1433
#define ASSERT_EQ(v1, v2)
Definition: checks.h:271
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
virtual void Put(int byte, const char *description)
Definition: mksnapshot.cc:102
bool IsEmpty() const
Definition: v8.h:209
Local< Value > Run()
Definition: api.cc:1598
CppByteSink(const char *snapshot_file)
Definition: mksnapshot.cc:137
static Persistent< Context > New(ExtensionConfiguration *extensions=NULL, Handle< ObjectTemplate > global_template=Handle< ObjectTemplate >(), Handle< Value > global_object=Handle< Value >())
Definition: api.cc:4411
const Register fp
void Print(FILE *fp)
Definition: mksnapshot.cc:106
virtual i::Vector< char > * output()=0
int GetStartColumn() const
Definition: api.cc:1910
static StartupData::CompressionAlgorithm GetCompressedStartupDataAlgorithm()
Definition: api.cc:369
virtual int Position()
Definition: mksnapshot.cc:105
Definition: v8.h:106
Local< v8::Message > Message() const
Definition: api.cc:1750
static int SetFlagsFromCommandLine(int *argc, char **argv, bool remove_flags)
Definition: flags.cc:343
Definition: d8.h:45
Local< String > GetSourceLine() const
Definition: api.cc:1948
void WriteSpaceUsed(const char *prefix, int new_space_used, int pointer_space_used, int data_space_used, int code_space_used, int map_space_used, int cell_space_used)
Definition: mksnapshot.cc:168