Index: src/mksnapshot.cc |
diff --git a/src/mksnapshot.cc b/src/mksnapshot.cc |
index 07b057549237f14ab2f75ecebf858b7345620bd3..2074a9d498edb39b2249c9d77540da1599c18e53 100644 |
--- a/src/mksnapshot.cc |
+++ b/src/mksnapshot.cc |
@@ -52,148 +52,173 @@ class Compressor { |
}; |
-class PartialSnapshotSink : public i::SnapshotByteSink { |
+class ListSnapshotSink : public i::SnapshotByteSink { |
public: |
- PartialSnapshotSink() : data_(), raw_size_(-1) { } |
- virtual ~PartialSnapshotSink() { data_.Free(); } |
- virtual void Put(int byte, const char* description) { |
- data_.Add(byte); |
+ explicit ListSnapshotSink(i::List<char>* data) : data_(data) { } |
+ virtual ~ListSnapshotSink() {} |
+ virtual void Put(int byte, const char* description) { data_->Add(byte); } |
+ virtual int Position() { return data_->length(); } |
+ private: |
+ i::List<char>* data_; |
+}; |
+ |
+ |
+class SnapshotWriter { |
+ public: |
+ explicit SnapshotWriter(const char* snapshot_file) |
+ : fp_(GetFileDescriptorOrDie(snapshot_file)) |
+ , raw_file_(NULL) |
+ , raw_context_file_(NULL) |
+ , compressor_(NULL) |
+ , omit_(false) { |
} |
- virtual int Position() { return data_.length(); } |
- void Print(FILE* fp) { |
- int length = Position(); |
- for (int j = 0; j < length; j++) { |
- if ((j & 0x1f) == 0x1f) { |
- fprintf(fp, "\n"); |
- } |
- if (j != 0) { |
- fprintf(fp, ","); |
- } |
- fprintf(fp, "%u", static_cast<unsigned char>(at(j))); |
- } |
+ |
+ ~SnapshotWriter() { |
+ fclose(fp_); |
+ if (raw_file_) fclose(raw_file_); |
+ if (raw_context_file_) fclose(raw_context_file_); |
} |
- char at(int i) { return data_[i]; } |
- bool Compress(Compressor* compressor) { |
- ASSERT_EQ(-1, raw_size_); |
- raw_size_ = data_.length(); |
- if (!compressor->Compress(data_.ToVector())) return false; |
- data_.Clear(); |
- data_.AddAll(*compressor->output()); |
- return true; |
+ |
+ void SetCompressor(Compressor* compressor) { |
+ compressor_ = compressor; |
} |
- int raw_size() { return raw_size_; } |
- private: |
- i::List<char> data_; |
- int raw_size_; |
-}; |
+ void SetOmit(bool omit) { |
+ omit_ = omit; |
+ } |
+ void SetRawFiles(const char* raw_file, const char* raw_context_file) { |
+ raw_file_ = GetFileDescriptorOrDie(raw_file); |
+ raw_context_file_ = GetFileDescriptorOrDie(raw_context_file); |
+ } |
-class CppByteSink : public PartialSnapshotSink { |
- public: |
- explicit CppByteSink(const char* snapshot_file) { |
- fp_ = i::OS::FOpen(snapshot_file, "wb"); |
- if (fp_ == NULL) { |
- i::PrintF("Unable to write to snapshot file \"%s\"\n", snapshot_file); |
- exit(1); |
- } |
+ void WriteSnapshot(const i::List<char>& snapshot_data, |
+ const i::Serializer& serializer, |
+ const i::List<char>& context_snapshot_data, |
+ const i::Serializer& context_serializer) const { |
+ WriteFilePrefix(); |
+ WriteData("", snapshot_data, raw_file_); |
+ WriteData("context_", context_snapshot_data, raw_context_file_); |
+ WriteMeta("context_", context_serializer); |
+ WriteMeta("", serializer); |
+ WriteFileSuffix(); |
+ } |
+ |
+ private: |
+ void WriteFilePrefix() const { |
fprintf(fp_, "// Autogenerated snapshot file. Do not edit.\n\n"); |
fprintf(fp_, "#include \"v8.h\"\n"); |
fprintf(fp_, "#include \"platform.h\"\n\n"); |
fprintf(fp_, "#include \"snapshot.h\"\n\n"); |
- fprintf(fp_, "namespace v8 {\nnamespace internal {\n\n"); |
- fprintf(fp_, "const byte Snapshot::data_[] = {"); |
+ fprintf(fp_, "namespace v8 {\n"); |
+ fprintf(fp_, "namespace internal {\n\n"); |
} |
- virtual ~CppByteSink() { |
- fprintf(fp_, "const int Snapshot::size_ = %d;\n", Position()); |
-#ifdef COMPRESS_STARTUP_DATA_BZ2 |
- fprintf(fp_, "const byte* Snapshot::raw_data_ = NULL;\n"); |
- fprintf(fp_, |
- "const int Snapshot::raw_size_ = %d;\n\n", |
- raw_size()); |
-#else |
- fprintf(fp_, |
- "const byte* Snapshot::raw_data_ = Snapshot::data_;\n"); |
- fprintf(fp_, |
- "const int Snapshot::raw_size_ = Snapshot::size_;\n\n"); |
-#endif |
- fprintf(fp_, "} } // namespace v8::internal\n"); |
- fclose(fp_); |
+ void WriteFileSuffix() const { |
+ fprintf(fp_, "} // namespace internal\n"); |
+ fprintf(fp_, "} // namespace v8\n"); |
+ } |
+ |
+ void WriteData(const char* prefix, |
+ const i::List<char>& source_data, |
+ FILE* raw_file) const { |
+ const i::List <char>* data_to_be_written = NULL; |
+ i::List<char> compressed_data; |
+ if (!compressor_) { |
+ data_to_be_written = &source_data; |
+ } else if (compressor_->Compress(source_data.ToVector())) { |
+ compressed_data.AddAll(*compressor_->output()); |
+ data_to_be_written = &compressed_data; |
+ } else { |
+ i::PrintF("Compression failed. Aborting.\n"); |
+ exit(1); |
+ } |
+ |
+ ASSERT(data_to_be_written); |
+ MaybeWriteRawFile(data_to_be_written, raw_file); |
+ WriteData(prefix, source_data, data_to_be_written); |
} |
- 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, |
- int property_cell_space_used) { |
- fprintf(fp_, |
- "const int Snapshot::%snew_space_used_ = %d;\n", |
- prefix, |
- new_space_used); |
- fprintf(fp_, |
- "const int Snapshot::%spointer_space_used_ = %d;\n", |
- prefix, |
- pointer_space_used); |
- fprintf(fp_, |
- "const int Snapshot::%sdata_space_used_ = %d;\n", |
- prefix, |
- data_space_used); |
- fprintf(fp_, |
- "const int Snapshot::%scode_space_used_ = %d;\n", |
- prefix, |
- code_space_used); |
- fprintf(fp_, |
- "const int Snapshot::%smap_space_used_ = %d;\n", |
- prefix, |
- map_space_used); |
- fprintf(fp_, |
- "const int Snapshot::%scell_space_used_ = %d;\n", |
- prefix, |
- cell_space_used); |
- fprintf(fp_, |
- "const int Snapshot::%sproperty_cell_space_used_ = %d;\n", |
- prefix, |
- property_cell_space_used); |
+ void MaybeWriteRawFile(const i::List<char>* data, FILE* raw_file) const { |
+ if (!data || !raw_file) |
+ return; |
+ |
+ // Sanity check, whether i::List iterators truly return pointers to an |
+ // internal array. |
+ ASSERT(data->end() - data->begin() == data->length()); |
+ |
+ size_t written = fwrite(data->begin(), 1, data->length(), raw_file); |
+ if (written != (size_t)data->length()) { |
+ i::PrintF("Writing raw file failed.. Aborting.\n"); |
+ exit(1); |
+ } |
} |
- void WritePartialSnapshot() { |
- int length = partial_sink_.Position(); |
- fprintf(fp_, "};\n\n"); |
- fprintf(fp_, "const int Snapshot::context_size_ = %d;\n", length); |
-#ifdef COMPRESS_STARTUP_DATA_BZ2 |
- fprintf(fp_, |
- "const int Snapshot::context_raw_size_ = %d;\n", |
- partial_sink_.raw_size()); |
-#else |
- fprintf(fp_, |
- "const int Snapshot::context_raw_size_ = " |
- "Snapshot::context_size_;\n"); |
-#endif |
- fprintf(fp_, "const byte Snapshot::context_data_[] = {\n"); |
- partial_sink_.Print(fp_); |
- fprintf(fp_, "};\n\n"); |
-#ifdef COMPRESS_STARTUP_DATA_BZ2 |
- fprintf(fp_, "const byte* Snapshot::context_raw_data_ = NULL;\n"); |
-#else |
- fprintf(fp_, "const byte* Snapshot::context_raw_data_ =" |
- " Snapshot::context_data_;\n"); |
-#endif |
+ void WriteData(const char* prefix, |
+ const i::List<char>& source_data, |
+ const i::List<char>* data_to_be_written) const { |
+ fprintf(fp_, "const byte Snapshot::%sdata_[] = {\n", prefix); |
+ if (!omit_) |
+ WriteSnapshotData(data_to_be_written); |
+ fprintf(fp_, "};\n"); |
+ fprintf(fp_, "const int Snapshot::%ssize_ = %d;\n", prefix, |
+ data_to_be_written->length()); |
+ |
+ if (data_to_be_written == &source_data && !omit_) { |
+ fprintf(fp_, "const byte* Snapshot::%sraw_data_ = Snapshot::%sdata_;\n", |
+ prefix, prefix); |
+ fprintf(fp_, "const int Snapshot::%sraw_size_ = Snapshot::%ssize_;\n", |
+ prefix, prefix); |
+ } else { |
+ fprintf(fp_, "const byte* Snapshot::%sraw_data_ = NULL;\n", prefix); |
+ fprintf(fp_, "const int Snapshot::%sraw_size_ = %d;\n", |
+ prefix, source_data.length()); |
+ } |
+ fprintf(fp_, "\n"); |
} |
- void WriteSnapshot() { |
- Print(fp_); |
+ void WriteMeta(const char* prefix, const i::Serializer& ser) const { |
+ WriteSizeVar(ser, prefix, "new", i::NEW_SPACE); |
+ WriteSizeVar(ser, prefix, "pointer", i::OLD_POINTER_SPACE); |
+ WriteSizeVar(ser, prefix, "data", i::OLD_DATA_SPACE); |
+ WriteSizeVar(ser, prefix, "code", i::CODE_SPACE); |
+ WriteSizeVar(ser, prefix, "map", i::MAP_SPACE); |
+ WriteSizeVar(ser, prefix, "cell", i::CELL_SPACE); |
+ WriteSizeVar(ser, prefix, "property_cell", i::PROPERTY_CELL_SPACE); |
+ fprintf(fp_, "\n"); |
} |
- PartialSnapshotSink* partial_sink() { return &partial_sink_; } |
+ void WriteSizeVar(const i::Serializer& ser, const char* prefix, |
+ const char* name, int space) const { |
+ fprintf(fp_, "const int Snapshot::%s%s_space_used_ = %d;\n", |
+ prefix, name, ser.CurrentAllocationAddress(space)); |
+ } |
+ |
+ void WriteSnapshotData(const i::List<char>* data) const { |
+ for (int i = 0; i < data->length(); i++) { |
+ if ((i & 0x1f) == 0x1f) |
+ fprintf(fp_, "\n"); |
+ if (i > 0) |
+ fprintf(fp_, ","); |
+ fprintf(fp_, "%u", static_cast<unsigned char>(data->at(i))); |
+ } |
+ fprintf(fp_, "\n"); |
+ } |
+ |
+ FILE* GetFileDescriptorOrDie(const char* filename) { |
+ FILE* fp = i::OS::FOpen(filename, "wb"); |
+ if (fp == NULL) { |
+ i::PrintF("Unable to open file \"%s\" for writing.\n", filename); |
+ exit(1); |
+ } |
+ return fp; |
+ } |
- private: |
FILE* fp_; |
- PartialSnapshotSink partial_sink_; |
+ FILE* raw_file_; |
+ FILE* raw_context_file_; |
+ Compressor* compressor_; |
+ bool omit_; |
}; |
@@ -359,46 +384,32 @@ int main(int argc, char** argv) { |
i::Heap::kNoGCFlags, "mksnapshot"); |
i::Object* raw_context = *v8::Utils::OpenPersistent(context); |
context.Reset(); |
- CppByteSink sink(argv[1]); |
+ |
// This results in a somewhat smaller snapshot, probably because it gets rid |
// of some things that are cached between garbage collections. |
- i::StartupSerializer ser(internal_isolate, &sink); |
+ i::List<char> snapshot_data; |
+ ListSnapshotSink snapshot_sink(&snapshot_data); |
+ i::StartupSerializer ser(internal_isolate, &snapshot_sink); |
ser.SerializeStrongReferences(); |
- i::PartialSerializer partial_ser( |
- internal_isolate, &ser, sink.partial_sink()); |
- partial_ser.Serialize(&raw_context); |
- |
+ i::List<char> context_data; |
+ ListSnapshotSink contex_sink(&context_data); |
+ i::PartialSerializer context_ser(internal_isolate, &ser, &contex_sink); |
+ context_ser.Serialize(&raw_context); |
ser.SerializeWeakReferences(); |
+ { |
+ SnapshotWriter writer(argv[1]); |
+ writer.SetOmit(i::FLAG_omit); |
+ if (i::FLAG_raw_file && i::FLAG_raw_context_file) |
+ writer.SetRawFiles(i::FLAG_raw_file, i::FLAG_raw_context_file); |
#ifdef COMPRESS_STARTUP_DATA_BZ2 |
- BZip2Compressor compressor; |
- if (!sink.Compress(&compressor)) |
- return 1; |
- if (!sink.partial_sink()->Compress(&compressor)) |
- return 1; |
+ BZip2Compressor bzip2; |
+ writer.SetCompressor(&bzip2); |
#endif |
- sink.WriteSnapshot(); |
- sink.WritePartialSnapshot(); |
- |
- sink.WriteSpaceUsed( |
- "context_", |
- partial_ser.CurrentAllocationAddress(i::NEW_SPACE), |
- partial_ser.CurrentAllocationAddress(i::OLD_POINTER_SPACE), |
- partial_ser.CurrentAllocationAddress(i::OLD_DATA_SPACE), |
- partial_ser.CurrentAllocationAddress(i::CODE_SPACE), |
- partial_ser.CurrentAllocationAddress(i::MAP_SPACE), |
- partial_ser.CurrentAllocationAddress(i::CELL_SPACE), |
- partial_ser.CurrentAllocationAddress(i::PROPERTY_CELL_SPACE)); |
- sink.WriteSpaceUsed( |
- "", |
- ser.CurrentAllocationAddress(i::NEW_SPACE), |
- ser.CurrentAllocationAddress(i::OLD_POINTER_SPACE), |
- ser.CurrentAllocationAddress(i::OLD_DATA_SPACE), |
- ser.CurrentAllocationAddress(i::CODE_SPACE), |
- ser.CurrentAllocationAddress(i::MAP_SPACE), |
- ser.CurrentAllocationAddress(i::CELL_SPACE), |
- ser.CurrentAllocationAddress(i::PROPERTY_CELL_SPACE)); |
+ writer.WriteSnapshot(snapshot_data, ser, context_data, context_ser); |
+ } |
+ |
isolate->Exit(); |
isolate->Dispose(); |
V8::Dispose(); |