From: vogelheim@chromium.org Date: Thu, 24 Apr 2014 12:31:10 +0000 (+0000) Subject: Implement --omit, --raw_[context_]file=... for mksnapshot tool. X-Git-Tag: upstream/4.7.83~9452 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=331cc8a278128dd04b647f6272258b8be21c4a26;p=platform%2Fupstream%2Fv8.git Implement --omit, --raw_[context_]file=... for mksnapshot tool. These switches are analogous to --omit and --raw for js2c.py. The goal it to allow embedders to externally load all (or generate) the V8 startup data. There's a bit of gratuitous refactoring with the writing logic that helped me understand the code. Let me know if it's not an improvement. BUG=355539 LOG=N R=jochen@chromium.org, svenpanne@chromium.org Review URL: https://codereview.chromium.org/249283002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20941 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/flag-definitions.h b/src/flag-definitions.h index 989e285..4e8791b 100644 --- a/src/flag-definitions.h +++ b/src/flag-definitions.h @@ -653,7 +653,13 @@ DEFINE_string(testing_serialization_file, "/tmp/serdes", // mksnapshot.cc DEFINE_string(extra_code, NULL, "A filename with extra code to be included in" - " the snapshot (mksnapshot only)") + " the snapshot (mksnapshot only)") +DEFINE_string(raw_file, NULL, "A file to write the raw snapshot bytes to. " + "(mksnapshot only)") +DEFINE_string(raw_context_file, NULL, "A file to write the raw context " + "snapshot bytes to. (mksnapshot only)") +DEFINE_bool(omit, false, "Omit raw snapshot bytes in generated code. " + "(mksnapshot only)") // code-stubs-hydrogen.cc DEFINE_bool(profile_hydrogen_code_stub_compilation, false, diff --git a/src/mksnapshot.cc b/src/mksnapshot.cc index 47b5b3c..9f91b83 100644 --- a/src/mksnapshot.cc +++ b/src/mksnapshot.cc @@ -56,148 +56,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* 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* 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(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 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& snapshot_data, + const i::Serializer& serializer, + const i::List& 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& source_data, + FILE* raw_file) const { + const i::List * data_to_be_written = NULL; + i::List 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* 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& source_data, + const i::List* 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* 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(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_; }; @@ -369,46 +394,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 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 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(); diff --git a/src/serialize.h b/src/serialize.h index 9e1d3d5..2d65436 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -464,7 +464,7 @@ class Serializer : public SerializerDeserializer { void VisitPointers(Object** start, Object** end); // You can call this after serialization to find out how much space was used // in each space. - int CurrentAllocationAddress(int space) { + int CurrentAllocationAddress(int space) const { ASSERT(space < kNumberOfSpaces); return fullness_[space]; }