1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2008 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef COMPRESS_STARTUP_DATA_BZ2
29257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include <bzlib.h>
30257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <signal.h>
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "bootstrapper.h"
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "natives.h"
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "platform.h"
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "serialize.h"
393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "list.h"
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing namespace v8;
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const unsigned int kMaxCounters = 256;
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A single counter in a counter collection.
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Counter {
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kMaxNameSize = 64;
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int32_t* Bind(const char* name) {
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int i;
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (i = 0; i < kMaxNameSize - 1 && name[i]; i++) {
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      name_[i] = name[i];
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    name_[i] = '\0';
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return &counter_;
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int32_t counter_;
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint8_t name_[kMaxNameSize];
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A set of counters and associated information.  An instance of this
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// class is stored directly in the memory-mapped counters file if
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the --save-counters options is used
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CounterCollection {
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CounterCollection() {
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    magic_number_ = 0xDEADFACE;
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    max_counters_ = kMaxCounters;
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    max_name_size_ = Counter::kMaxNameSize;
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    counters_in_use_ = 0;
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Counter* GetNextCounter() {
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (counters_in_use_ == kMaxCounters) return NULL;
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return &counters_[counters_in_use_++];
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint32_t magic_number_;
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint32_t max_counters_;
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint32_t max_name_size_;
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint32_t counters_in_use_;
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Counter counters_[kMaxCounters];
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
87257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass Compressor {
88257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
89257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual ~Compressor() {}
90257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual bool Compress(i::Vector<char> input) = 0;
91257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual i::Vector<char>* output() = 0;
92257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
93257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
94257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
95257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass PartialSnapshotSink : public i::SnapshotByteSink {
96257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
97257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  PartialSnapshotSink() : data_(), raw_size_(-1) { }
98257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual ~PartialSnapshotSink() { data_.Free(); }
99257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual void Put(int byte, const char* description) {
100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    data_.Add(byte);
101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual int Position() { return data_.length(); }
103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void Print(FILE* fp) {
104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int length = Position();
105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    for (int j = 0; j < length; j++) {
106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if ((j & 0x1f) == 0x1f) {
107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        fprintf(fp, "\n");
108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (j != 0) {
110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        fprintf(fp, ",");
111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      fprintf(fp, "%u", static_cast<unsigned char>(at(j)));
113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  char at(int i) { return data_[i]; }
116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool Compress(Compressor* compressor) {
117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT_EQ(-1, raw_size_);
118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    raw_size_ = data_.length();
119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!compressor->Compress(data_.ToVector())) return false;
120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    data_.Clear();
121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    data_.AddAll(*compressor->output());
122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return true;
123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int raw_size() { return raw_size_; }
1253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  i::List<char> data_;
128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int raw_size_;
129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass CppByteSink : public PartialSnapshotSink {
133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public:
134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  explicit CppByteSink(const char* snapshot_file) {
135d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    fp_ = i::OS::FOpen(snapshot_file, "wb");
136d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (fp_ == NULL) {
137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      i::PrintF("Unable to write to snapshot file \"%s\"\n", snapshot_file);
138d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      exit(1);
139d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    fprintf(fp_, "// Autogenerated snapshot file. Do not edit.\n\n");
141d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    fprintf(fp_, "#include \"v8.h\"\n");
142d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    fprintf(fp_, "#include \"platform.h\"\n\n");
143d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    fprintf(fp_, "#include \"snapshot.h\"\n\n");
144d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    fprintf(fp_, "namespace v8 {\nnamespace internal {\n\n");
145d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    fprintf(fp_, "const byte Snapshot::data_[] = {");
146d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  virtual ~CppByteSink() {
149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    fprintf(fp_, "const int Snapshot::size_ = %d;\n", Position());
150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef COMPRESS_STARTUP_DATA_BZ2
151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    fprintf(fp_, "const byte* Snapshot::raw_data_ = NULL;\n");
152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    fprintf(fp_,
153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            "const int Snapshot::raw_size_ = %d;\n\n",
154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            raw_size());
155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#else
156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    fprintf(fp_,
157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            "const byte* Snapshot::raw_data_ = Snapshot::data_;\n");
158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    fprintf(fp_,
159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            "const int Snapshot::raw_size_ = Snapshot::size_;\n\n");
160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
1613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    fprintf(fp_, "} }  // namespace v8::internal\n");
1623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    fclose(fp_);
1633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
1643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void WriteSpaceUsed(
1663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      int new_space_used,
1673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      int pointer_space_used,
1683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      int data_space_used,
1693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      int code_space_used,
1703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      int map_space_used,
1713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      int cell_space_used,
1723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      int large_space_used) {
1733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    fprintf(fp_, "const int Snapshot::new_space_used_ = %d;\n", new_space_used);
1743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    fprintf(fp_,
1753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu            "const int Snapshot::pointer_space_used_ = %d;\n",
1763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu            pointer_space_used);
1773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    fprintf(fp_,
1783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu            "const int Snapshot::data_space_used_ = %d;\n",
1793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu            data_space_used);
1803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    fprintf(fp_,
1813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu            "const int Snapshot::code_space_used_ = %d;\n",
1823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu            code_space_used);
1833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    fprintf(fp_, "const int Snapshot::map_space_used_ = %d;\n", map_space_used);
1843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    fprintf(fp_,
1853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu            "const int Snapshot::cell_space_used_ = %d;\n",
1863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu            cell_space_used);
1873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    fprintf(fp_,
1883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu            "const int Snapshot::large_space_used_ = %d;\n",
1893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu            large_space_used);
1903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
1913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void WritePartialSnapshot() {
1933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    int length = partial_sink_.Position();
1943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    fprintf(fp_, "};\n\n");
1953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    fprintf(fp_, "const int Snapshot::context_size_ = %d;\n",  length);
196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef COMPRESS_STARTUP_DATA_BZ2
197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    fprintf(fp_,
198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            "const int Snapshot::context_raw_size_ = %d;\n",
199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            partial_sink_.raw_size());
200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#else
201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    fprintf(fp_,
202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            "const int Snapshot::context_raw_size_ = "
203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            "Snapshot::context_size_;\n");
204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
2053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    fprintf(fp_, "const byte Snapshot::context_data_[] = {\n");
206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    partial_sink_.Print(fp_);
207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    fprintf(fp_, "};\n\n");
208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef COMPRESS_STARTUP_DATA_BZ2
209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    fprintf(fp_, "const byte* Snapshot::context_raw_data_ = NULL;\n");
210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#else
211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    fprintf(fp_, "const byte* Snapshot::context_raw_data_ ="
212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            " Snapshot::context_data_;\n");
213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
215d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void WriteSnapshot() {
217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Print(fp_);
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  PartialSnapshotSink* partial_sink() { return &partial_sink_; }
221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  FILE* fp_;
224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  PartialSnapshotSink partial_sink_;
225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
226e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef COMPRESS_STARTUP_DATA_BZ2
229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass BZip2Compressor : public Compressor {
230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BZip2Compressor() : output_(NULL) {}
232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual ~BZip2Compressor() {
233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    delete output_;
234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual bool Compress(i::Vector<char> input) {
236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    delete output_;
237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    output_ = new i::ScopedVector<char>((input.length() * 101) / 100 + 1000);
238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    unsigned int output_length_ = output_->length();
239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int result = BZ2_bzBuffToBuffCompress(output_->start(), &output_length_,
240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          input.start(), input.length(),
241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          9, 1, 0);
242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (result == BZ_OK) {
243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      output_->Truncate(output_length_);
244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return true;
245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      fprintf(stderr, "bzlib error code: %d\n", result);
247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return false;
2483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual i::Vector<char>* output() { return output_; }
2513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block private:
253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  i::ScopedVector<char>* output_;
254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block};
2553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass BZip2Decompressor : public StartupDataDecompressor {
2583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch public:
2593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual ~BZip2Decompressor() { }
2603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch protected:
2623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual int DecompressData(char* raw_data,
2633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             int* raw_data_size,
2643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             const char* compressed_data,
2653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             int compressed_data_size) {
2663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT_EQ(StartupData::kBZip2,
2673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch              V8::GetCompressedStartupDataAlgorithm());
2683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    unsigned int decompressed_size = *raw_data_size;
2693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int result =
2703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        BZ2_bzBuffToBuffDecompress(raw_data,
2713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                   &decompressed_size,
2723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                   const_cast<char*>(compressed_data),
2733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                   compressed_data_size,
2743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                   0, 1);
2753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (result == BZ_OK) {
2763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      *raw_data_size = decompressed_size;
2773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return result;
2793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
2803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch};
281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint main(int argc, char** argv) {
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // By default, log code create information in the snapshot.
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::FLAG_log_code = true;
2873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print the usage if an error occurs when parsing the command line
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // flags or if the help flag is set.
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int result = i::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (result > 0 || argc != 2 || i::FLAG_help) {
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ::printf("Usage: %s [flag] ... outfile\n", argv[0]);
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    i::FlagList::PrintHelp();
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return !i::FLAG_help;
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#ifdef COMPRESS_STARTUP_DATA_BZ2
2973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BZip2Decompressor natives_decompressor;
2983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int bz2_result = natives_decompressor.Decompress();
2993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (bz2_result != BZ_OK) {
3003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    fprintf(stderr, "bzip error code: %d\n", bz2_result);
3013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    exit(1);
3023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
3033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::Serializer::Enable();
305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Persistent<Context> context = v8::Context::New();
306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(!context.IsEmpty());
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure all builtin scripts are cached.
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { HandleScope scope;
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 0; i < i::Natives::GetBuiltinsCount(); i++) {
31044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      i::Isolate::Current()->bootstrapper()->NativesSourceLookup(i);
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // If we don't do this then we end up with a stray root pointing at the
3143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // context even after we have disposed of the context.
3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(i::Heap::kNoGCFlags, "mksnapshot");
3163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  i::Object* raw_context = *(v8::Utils::OpenHandle(*context));
317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  context.Dispose();
318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CppByteSink sink(argv[1]);
319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This results in a somewhat smaller snapshot, probably because it gets rid
320d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // of some things that are cached between garbage collections.
321d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  i::StartupSerializer ser(&sink);
3223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ser.SerializeStrongReferences();
3233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  i::PartialSerializer partial_ser(&ser, sink.partial_sink());
3253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  partial_ser.Serialize(&raw_context);
3263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ser.SerializeWeakReferences();
3283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef COMPRESS_STARTUP_DATA_BZ2
330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BZip2Compressor compressor;
331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!sink.Compress(&compressor))
332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return 1;
333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!sink.partial_sink()->Compress(&compressor))
334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return 1;
335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  sink.WriteSnapshot();
3373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  sink.WritePartialSnapshot();
3383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  sink.WriteSpaceUsed(
3403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      partial_ser.CurrentAllocationAddress(i::NEW_SPACE),
3413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      partial_ser.CurrentAllocationAddress(i::OLD_POINTER_SPACE),
3423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      partial_ser.CurrentAllocationAddress(i::OLD_DATA_SPACE),
3433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      partial_ser.CurrentAllocationAddress(i::CODE_SPACE),
3443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      partial_ser.CurrentAllocationAddress(i::MAP_SPACE),
3453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      partial_ser.CurrentAllocationAddress(i::CELL_SPACE),
3463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      partial_ser.CurrentAllocationAddress(i::LO_SPACE));
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 0;
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
349