The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / mksnapshot.cc @ f230a1cf

History | View | Annotate | Download (12.9 KB)

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

    
47
class Compressor {
48
 public:
49
  virtual ~Compressor() {}
50
  virtual bool Compress(i::Vector<char> input) = 0;
51
  virtual i::Vector<char>* output() = 0;
52
};
53

    
54

    
55
class PartialSnapshotSink : public i::SnapshotByteSink {
56
 public:
57
  PartialSnapshotSink() : data_(), raw_size_(-1) { }
58
  virtual ~PartialSnapshotSink() { data_.Free(); }
59
  virtual void Put(int byte, const char* description) {
60
    data_.Add(byte);
61
  }
62
  virtual int Position() { return data_.length(); }
63
  void Print(FILE* fp) {
64
    int length = Position();
65
    for (int j = 0; j < length; j++) {
66
      if ((j & 0x1f) == 0x1f) {
67
        fprintf(fp, "\n");
68
      }
69
      if (j != 0) {
70
        fprintf(fp, ",");
71
      }
72
      fprintf(fp, "%u", static_cast<unsigned char>(at(j)));
73
    }
74
  }
75
  char at(int i) { return data_[i]; }
76
  bool Compress(Compressor* compressor) {
77
    ASSERT_EQ(-1, raw_size_);
78
    raw_size_ = data_.length();
79
    if (!compressor->Compress(data_.ToVector())) return false;
80
    data_.Clear();
81
    data_.AddAll(*compressor->output());
82
    return true;
83
  }
84
  int raw_size() { return raw_size_; }
85

    
86
 private:
87
  i::List<char> data_;
88
  int raw_size_;
89
};
90

    
91

    
92
class CppByteSink : public PartialSnapshotSink {
93
 public:
94
  explicit CppByteSink(const char* snapshot_file) {
95
    fp_ = i::OS::FOpen(snapshot_file, "wb");
96
    if (fp_ == NULL) {
97
      i::PrintF("Unable to write to snapshot file \"%s\"\n", snapshot_file);
98
      exit(1);
99
    }
100
    fprintf(fp_, "// Autogenerated snapshot file. Do not edit.\n\n");
101
    fprintf(fp_, "#include \"v8.h\"\n");
102
    fprintf(fp_, "#include \"platform.h\"\n\n");
103
    fprintf(fp_, "#include \"snapshot.h\"\n\n");
104
    fprintf(fp_, "namespace v8 {\nnamespace internal {\n\n");
105
    fprintf(fp_, "const byte Snapshot::data_[] = {");
106
  }
107

    
108
  virtual ~CppByteSink() {
109
    fprintf(fp_, "const int Snapshot::size_ = %d;\n", Position());
110
#ifdef COMPRESS_STARTUP_DATA_BZ2
111
    fprintf(fp_, "const byte* Snapshot::raw_data_ = NULL;\n");
112
    fprintf(fp_,
113
            "const int Snapshot::raw_size_ = %d;\n\n",
114
            raw_size());
115
#else
116
    fprintf(fp_,
117
            "const byte* Snapshot::raw_data_ = Snapshot::data_;\n");
118
    fprintf(fp_,
119
            "const int Snapshot::raw_size_ = Snapshot::size_;\n\n");
120
#endif
121
    fprintf(fp_, "} }  // namespace v8::internal\n");
122
    fclose(fp_);
123
  }
124

    
125
  void WriteSpaceUsed(
126
      const char* prefix,
127
      int new_space_used,
128
      int pointer_space_used,
129
      int data_space_used,
130
      int code_space_used,
131
      int map_space_used,
132
      int cell_space_used,
133
      int property_cell_space_used) {
134
    fprintf(fp_,
135
            "const int Snapshot::%snew_space_used_ = %d;\n",
136
            prefix,
137
            new_space_used);
138
    fprintf(fp_,
139
            "const int Snapshot::%spointer_space_used_ = %d;\n",
140
            prefix,
141
            pointer_space_used);
142
    fprintf(fp_,
143
            "const int Snapshot::%sdata_space_used_ = %d;\n",
144
            prefix,
145
            data_space_used);
146
    fprintf(fp_,
147
            "const int Snapshot::%scode_space_used_ = %d;\n",
148
            prefix,
149
            code_space_used);
150
    fprintf(fp_,
151
            "const int Snapshot::%smap_space_used_ = %d;\n",
152
            prefix,
153
            map_space_used);
154
    fprintf(fp_,
155
            "const int Snapshot::%scell_space_used_ = %d;\n",
156
            prefix,
157
            cell_space_used);
158
    fprintf(fp_,
159
            "const int Snapshot::%sproperty_cell_space_used_ = %d;\n",
160
            prefix,
161
            property_cell_space_used);
162
  }
163

    
164
  void WritePartialSnapshot() {
165
    int length = partial_sink_.Position();
166
    fprintf(fp_, "};\n\n");
167
    fprintf(fp_, "const int Snapshot::context_size_ = %d;\n",  length);
168
#ifdef COMPRESS_STARTUP_DATA_BZ2
169
    fprintf(fp_,
170
            "const int Snapshot::context_raw_size_ = %d;\n",
171
            partial_sink_.raw_size());
172
#else
173
    fprintf(fp_,
174
            "const int Snapshot::context_raw_size_ = "
175
            "Snapshot::context_size_;\n");
176
#endif
177
    fprintf(fp_, "const byte Snapshot::context_data_[] = {\n");
178
    partial_sink_.Print(fp_);
179
    fprintf(fp_, "};\n\n");
180
#ifdef COMPRESS_STARTUP_DATA_BZ2
181
    fprintf(fp_, "const byte* Snapshot::context_raw_data_ = NULL;\n");
182
#else
183
    fprintf(fp_, "const byte* Snapshot::context_raw_data_ ="
184
            " Snapshot::context_data_;\n");
185
#endif
186
  }
187

    
188
  void WriteSnapshot() {
189
    Print(fp_);
190
  }
191

    
192
  PartialSnapshotSink* partial_sink() { return &partial_sink_; }
193

    
194
 private:
195
  FILE* fp_;
196
  PartialSnapshotSink partial_sink_;
197
};
198

    
199

    
200
#ifdef COMPRESS_STARTUP_DATA_BZ2
201
class BZip2Compressor : public Compressor {
202
 public:
203
  BZip2Compressor() : output_(NULL) {}
204
  virtual ~BZip2Compressor() {
205
    delete output_;
206
  }
207
  virtual bool Compress(i::Vector<char> input) {
208
    delete output_;
209
    output_ = new i::ScopedVector<char>((input.length() * 101) / 100 + 1000);
210
    unsigned int output_length_ = output_->length();
211
    int result = BZ2_bzBuffToBuffCompress(output_->start(), &output_length_,
212
                                          input.start(), input.length(),
213
                                          9, 1, 0);
214
    if (result == BZ_OK) {
215
      output_->Truncate(output_length_);
216
      return true;
217
    } else {
218
      fprintf(stderr, "bzlib error code: %d\n", result);
219
      return false;
220
    }
221
  }
222
  virtual i::Vector<char>* output() { return output_; }
223

    
224
 private:
225
  i::ScopedVector<char>* output_;
226
};
227

    
228

    
229
class BZip2Decompressor : public StartupDataDecompressor {
230
 public:
231
  virtual ~BZip2Decompressor() { }
232

    
233
 protected:
234
  virtual int DecompressData(char* raw_data,
235
                             int* raw_data_size,
236
                             const char* compressed_data,
237
                             int compressed_data_size) {
238
    ASSERT_EQ(StartupData::kBZip2,
239
              V8::GetCompressedStartupDataAlgorithm());
240
    unsigned int decompressed_size = *raw_data_size;
241
    int result =
242
        BZ2_bzBuffToBuffDecompress(raw_data,
243
                                   &decompressed_size,
244
                                   const_cast<char*>(compressed_data),
245
                                   compressed_data_size,
246
                                   0, 1);
247
    if (result == BZ_OK) {
248
      *raw_data_size = decompressed_size;
249
    }
250
    return result;
251
  }
252
};
253
#endif
254

    
255

    
256
void DumpException(Handle<Message> message) {
257
  String::Utf8Value message_string(message->Get());
258
  String::Utf8Value message_line(message->GetSourceLine());
259
  fprintf(stderr, "%s at line %d\n", *message_string, message->GetLineNumber());
260
  fprintf(stderr, "%s\n", *message_line);
261
  for (int i = 0; i <= message->GetEndColumn(); ++i) {
262
    fprintf(stderr, "%c", i < message->GetStartColumn() ? ' ' : '^');
263
  }
264
  fprintf(stderr, "\n");
265
}
266

    
267

    
268
int main(int argc, char** argv) {
269
  V8::InitializeICU();
270
  i::Isolate::SetCrashIfDefaultIsolateInitialized();
271

    
272
  // By default, log code create information in the snapshot.
273
  i::FLAG_log_code = true;
274

    
275
  // Print the usage if an error occurs when parsing the command line
276
  // flags or if the help flag is set.
277
  int result = i::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
278
  if (result > 0 || argc != 2 || i::FLAG_help) {
279
    ::printf("Usage: %s [flag] ... outfile\n", argv[0]);
280
    i::FlagList::PrintHelp();
281
    return !i::FLAG_help;
282
  }
283
#ifdef COMPRESS_STARTUP_DATA_BZ2
284
  BZip2Decompressor natives_decompressor;
285
  int bz2_result = natives_decompressor.Decompress();
286
  if (bz2_result != BZ_OK) {
287
    fprintf(stderr, "bzip error code: %d\n", bz2_result);
288
    exit(1);
289
  }
290
#endif
291
  i::FLAG_logfile_per_isolate = false;
292

    
293
  Isolate* isolate = v8::Isolate::New();
294
  isolate->Enter();
295
  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
296
  i::Serializer::Enable(internal_isolate);
297
  Persistent<Context> context;
298
  {
299
    HandleScope handle_scope(isolate);
300
    context.Reset(isolate, Context::New(isolate));
301
  }
302

    
303
  if (context.IsEmpty()) {
304
    fprintf(stderr,
305
            "\nException thrown while compiling natives - see above.\n\n");
306
    exit(1);
307
  }
308
  if (i::FLAG_extra_code != NULL) {
309
    // Capture 100 frames if anything happens.
310
    V8::SetCaptureStackTraceForUncaughtExceptions(true, 100);
311
    HandleScope scope(isolate);
312
    v8::Context::Scope(v8::Local<v8::Context>::New(isolate, context));
313
    const char* name = i::FLAG_extra_code;
314
    FILE* file = i::OS::FOpen(name, "rb");
315
    if (file == NULL) {
316
      fprintf(stderr, "Failed to open '%s': errno %d\n", name, errno);
317
      exit(1);
318
    }
319

    
320
    fseek(file, 0, SEEK_END);
321
    int size = ftell(file);
322
    rewind(file);
323

    
324
    char* chars = new char[size + 1];
325
    chars[size] = '\0';
326
    for (int i = 0; i < size;) {
327
      int read = static_cast<int>(fread(&chars[i], 1, size - i, file));
328
      if (read < 0) {
329
        fprintf(stderr, "Failed to read '%s': errno %d\n", name, errno);
330
        exit(1);
331
      }
332
      i += read;
333
    }
334
    fclose(file);
335
    Local<String> source = String::New(chars);
336
    TryCatch try_catch;
337
    Local<Script> script = Script::Compile(source);
338
    if (try_catch.HasCaught()) {
339
      fprintf(stderr, "Failure compiling '%s'\n", name);
340
      DumpException(try_catch.Message());
341
      exit(1);
342
    }
343
    script->Run();
344
    if (try_catch.HasCaught()) {
345
      fprintf(stderr, "Failure running '%s'\n", name);
346
      DumpException(try_catch.Message());
347
      exit(1);
348
    }
349
  }
350
  // Make sure all builtin scripts are cached.
351
  { HandleScope scope(isolate);
352
    for (int i = 0; i < i::Natives::GetBuiltinsCount(); i++) {
353
      internal_isolate->bootstrapper()->NativesSourceLookup(i);
354
    }
355
  }
356
  // If we don't do this then we end up with a stray root pointing at the
357
  // context even after we have disposed of the context.
358
  internal_isolate->heap()->CollectAllGarbage(
359
      i::Heap::kNoGCFlags, "mksnapshot");
360
  i::Object* raw_context = *v8::Utils::OpenPersistent(context);
361
  context.Dispose();
362
  CppByteSink sink(argv[1]);
363
  // This results in a somewhat smaller snapshot, probably because it gets rid
364
  // of some things that are cached between garbage collections.
365
  i::StartupSerializer ser(internal_isolate, &sink);
366
  ser.SerializeStrongReferences();
367

    
368
  i::PartialSerializer partial_ser(
369
      internal_isolate, &ser, sink.partial_sink());
370
  partial_ser.Serialize(&raw_context);
371

    
372
  ser.SerializeWeakReferences();
373

    
374
#ifdef COMPRESS_STARTUP_DATA_BZ2
375
  BZip2Compressor compressor;
376
  if (!sink.Compress(&compressor))
377
    return 1;
378
  if (!sink.partial_sink()->Compress(&compressor))
379
    return 1;
380
#endif
381
  sink.WriteSnapshot();
382
  sink.WritePartialSnapshot();
383

    
384
  sink.WriteSpaceUsed(
385
      "context_",
386
      partial_ser.CurrentAllocationAddress(i::NEW_SPACE),
387
      partial_ser.CurrentAllocationAddress(i::OLD_POINTER_SPACE),
388
      partial_ser.CurrentAllocationAddress(i::OLD_DATA_SPACE),
389
      partial_ser.CurrentAllocationAddress(i::CODE_SPACE),
390
      partial_ser.CurrentAllocationAddress(i::MAP_SPACE),
391
      partial_ser.CurrentAllocationAddress(i::CELL_SPACE),
392
      partial_ser.CurrentAllocationAddress(i::PROPERTY_CELL_SPACE));
393
  sink.WriteSpaceUsed(
394
      "",
395
      ser.CurrentAllocationAddress(i::NEW_SPACE),
396
      ser.CurrentAllocationAddress(i::OLD_POINTER_SPACE),
397
      ser.CurrentAllocationAddress(i::OLD_DATA_SPACE),
398
      ser.CurrentAllocationAddress(i::CODE_SPACE),
399
      ser.CurrentAllocationAddress(i::MAP_SPACE),
400
      ser.CurrentAllocationAddress(i::CELL_SPACE),
401
      ser.CurrentAllocationAddress(i::PROPERTY_CELL_SPACE));
402
  return 0;
403
}