De-virtualize snapshot sink.
authoryangguo@chromium.org <yangguo@chromium.org>
Thu, 23 Oct 2014 11:23:57 +0000 (11:23 +0000)
committeryangguo@chromium.org <yangguo@chromium.org>
Thu, 23 Oct 2014 11:23:57 +0000 (11:23 +0000)
R=vogelheim@chromium.org

Review URL: https://codereview.chromium.org/669133003

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24836 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/flag-definitions.h
src/mksnapshot.cc
src/serialize.cc
src/serialize.h
src/snapshot-source-sink.cc
src/snapshot-source-sink.h
test/cctest/test-serialize.cc

index 4cf8eb8..ed7eabc 100644 (file)
@@ -463,7 +463,7 @@ DEFINE_BOOL(trace_stub_failures, false,
             "trace deoptimization of generated code stubs")
 
 DEFINE_BOOL(serialize_toplevel, false, "enable caching of toplevel scripts")
-DEFINE_INT(serializer_trace_level, 0, "trace code serializer (0 .. 2)")
+DEFINE_BOOL(trace_code_serializer, false, "print code serializer trace")
 
 // compiler.cc
 DEFINE_INT(min_preparse_length, 1024,
index 0737c9e..740c30c 100644 (file)
@@ -78,11 +78,9 @@ class SnapshotWriter {
                              const i::Serializer& serializer,
                              const i::List<i::byte>& context_snapshot_data,
                              const i::Serializer& context_serializer) const {
-    if (!startup_blob_file_)
-      return;
+    if (!startup_blob_file_) return;
 
-    i::List<i::byte> startup_blob;
-    i::ListSnapshotSink sink(&startup_blob);
+    i::SnapshotByteSink sink;
 
     int spaces[] = {i::NEW_SPACE,           i::OLD_POINTER_SPACE,
                     i::OLD_DATA_SPACE,      i::CODE_SPACE,
@@ -111,9 +109,10 @@ class SnapshotWriter {
       sink.PutInt(chunks[0], "spaces");
     }
 
+    const i::List<i::byte>& startup_blob = sink.data();
     size_t written = fwrite(startup_blob.begin(), 1, startup_blob.length(),
                             startup_blob_file_);
-    if (written != (size_t)startup_blob.length()) {
+    if (written != static_cast<size_t>(startup_blob.length())) {
       i::PrintF("Writing snapshot file failed.. Aborting.\n");
       exit(1);
     }
@@ -420,14 +419,12 @@ int main(int argc, char** argv) {
 
     // This results in a somewhat smaller snapshot, probably because it gets
     // rid of some things that are cached between garbage collections.
-    i::List<i::byte> snapshot_data;
-    i::ListSnapshotSink snapshot_sink(&snapshot_data);
+    i::SnapshotByteSink snapshot_sink;
     i::StartupSerializer ser(internal_isolate, &snapshot_sink);
     ser.SerializeStrongReferences();
 
-    i::List<i::byte> context_data;
-    i::ListSnapshotSink contex_sink(&context_data);
-    i::PartialSerializer context_ser(internal_isolate, &ser, &contex_sink);
+    i::SnapshotByteSink context_sink;
+    i::PartialSerializer context_ser(internal_isolate, &ser, &context_sink);
     context_ser.Serialize(&raw_context);
     ser.SerializeWeakReferences();
 
@@ -444,7 +441,8 @@ int main(int argc, char** argv) {
       BZip2Compressor bzip2;
       writer.SetCompressor(&bzip2);
   #endif
-      writer.WriteSnapshot(snapshot_data, ser, context_data, context_ser);
+      writer.WriteSnapshot(snapshot_sink.data(), ser, context_sink.data(),
+                           context_ser);
     }
   }
 
index ee0a9ec..c11f94a 100644 (file)
@@ -1952,7 +1952,7 @@ ScriptData* CodeSerializer::Serialize(Isolate* isolate,
                                       Handle<String> source) {
   base::ElapsedTimer timer;
   if (FLAG_profile_deserialization) timer.Start();
-  if (FLAG_serializer_trace_level > 0) {
+  if (FLAG_trace_code_serializer) {
     PrintF("[Serializing from");
     Object* script = info->script();
     if (script->IsScript()) Script::cast(script)->name()->ShortPrint();
@@ -1960,13 +1960,8 @@ ScriptData* CodeSerializer::Serialize(Isolate* isolate,
   }
 
   // Serialize code object.
-  List<byte> payload;
-  ListSnapshotSink list_sink(&payload);
-  DebugSnapshotSink debug_sink(&list_sink);
-  SnapshotByteSink* sink = FLAG_serializer_trace_level > 1
-                               ? static_cast<SnapshotByteSink*>(&debug_sink)
-                               : static_cast<SnapshotByteSink*>(&list_sink);
-  CodeSerializer cs(isolate, sink, *source, info->code());
+  SnapshotByteSink sink(info->code()->CodeSize() * 2);
+  CodeSerializer cs(isolate, &sink, *source, info->code());
   DisallowHeapAllocation no_gc;
   Object** location = Handle<Object>::cast(info).location();
   cs.VisitPointer(location);
@@ -1980,7 +1975,7 @@ ScriptData* CodeSerializer::Serialize(Isolate* isolate,
     }
   }
 
-  SerializedCodeData data(&payload, &cs);
+  SerializedCodeData data(sink.data(), &cs);
   ScriptData* script_data = data.GetScriptData();
 
   if (FLAG_profile_deserialization) {
@@ -1997,7 +1992,7 @@ void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
                                      WhereToPoint where_to_point, int skip) {
   int root_index = root_index_map_.Lookup(obj);
   if (root_index != RootIndexMap::kInvalidRootIndex) {
-    if (FLAG_serializer_trace_level > 0) {
+    if (FLAG_trace_code_serializer) {
       PrintF(" Encoding root: %d\n", root_index);
     }
     PutRoot(root_index, obj, how_to_code, where_to_point, skip);
@@ -2006,7 +2001,7 @@ void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
 
   BackReference back_reference = back_reference_map_.Lookup(obj);
   if (back_reference.is_valid()) {
-    if (FLAG_serializer_trace_level > 0) {
+    if (FLAG_trace_code_serializer) {
       PrintF(" Encoding back reference to: ");
       obj->ShortPrint();
       PrintF("\n");
@@ -2074,7 +2069,7 @@ void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
 void CodeSerializer::SerializeGeneric(HeapObject* heap_object,
                                       HowToCode how_to_code,
                                       WhereToPoint where_to_point) {
-  if (FLAG_serializer_trace_level > 0) {
+  if (FLAG_trace_code_serializer) {
     PrintF(" Encoding heap object: ");
     heap_object->ShortPrint();
     PrintF("\n");
@@ -2097,7 +2092,7 @@ void CodeSerializer::SerializeBuiltin(int builtin_index, HowToCode how_to_code,
   DCHECK_LT(builtin_index, Builtins::builtin_count);
   DCHECK_LE(0, builtin_index);
 
-  if (FLAG_serializer_trace_level > 0) {
+  if (FLAG_trace_code_serializer) {
     PrintF(" Encoding builtin: %s\n",
            isolate()->builtins()->name(builtin_index));
   }
@@ -2117,7 +2112,7 @@ void CodeSerializer::SerializeCodeStub(uint32_t stub_key, HowToCode how_to_code,
 
   int index = AddCodeStubKey(stub_key) + kCodeStubsBaseIndex;
 
-  if (FLAG_serializer_trace_level > 0) {
+  if (FLAG_trace_code_serializer) {
     PrintF(" Encoding code stub %s as %d\n",
            CodeStub::MajorName(CodeStub::MajorKeyFromKey(stub_key), false),
            index);
@@ -2133,7 +2128,7 @@ void CodeSerializer::SerializeIC(Code* ic, HowToCode how_to_code,
   // The IC may be implemented as a stub.
   uint32_t stub_key = ic->stub_key();
   if (stub_key != CodeStub::NoCacheKey()) {
-    if (FLAG_serializer_trace_level > 0) {
+    if (FLAG_trace_code_serializer) {
       PrintF(" %s is a code stub\n", Code::Kind2String(ic->kind()));
     }
     SerializeCodeStub(stub_key, how_to_code, where_to_point);
@@ -2147,7 +2142,7 @@ void CodeSerializer::SerializeIC(Code* ic, HowToCode how_to_code,
     Builtins::Name name = static_cast<Builtins::Name>(builtin_index);
     Code* builtin = isolate()->builtins()->builtin(name);
     if (builtin == ic) {
-      if (FLAG_serializer_trace_level > 0) {
+      if (FLAG_trace_code_serializer) {
         PrintF(" %s is a builtin\n", Code::Kind2String(ic->kind()));
       }
       DCHECK(ic->kind() == Code::KEYED_LOAD_IC ||
@@ -2158,7 +2153,7 @@ void CodeSerializer::SerializeIC(Code* ic, HowToCode how_to_code,
   }
   // The IC may also just be a piece of code kept in the non_monomorphic_cache.
   // In that case, just serialize as a normal code object.
-  if (FLAG_serializer_trace_level > 0) {
+  if (FLAG_trace_code_serializer) {
     PrintF(" %s has no special handling\n", Code::Kind2String(ic->kind()));
   }
   DCHECK(ic->kind() == Code::LOAD_IC || ic->kind() == Code::STORE_IC);
@@ -2180,7 +2175,7 @@ int CodeSerializer::AddCodeStubKey(uint32_t stub_key) {
 
 void CodeSerializer::SerializeSourceObject(HowToCode how_to_code,
                                            WhereToPoint where_to_point) {
-  if (FLAG_serializer_trace_level > 0) PrintF(" Encoding source object\n");
+  if (FLAG_trace_code_serializer) PrintF(" Encoding source object\n");
 
   DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject);
   sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source");
@@ -2248,7 +2243,8 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
 }
 
 
-SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
+SerializedCodeData::SerializedCodeData(const List<byte>& payload,
+                                       CodeSerializer* cs)
     : script_data_(NULL), owns_script_data_(true) {
   DisallowHeapAllocation no_gc;
   List<uint32_t>* stub_keys = cs->stub_keys();
@@ -2273,7 +2269,7 @@ SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
   int num_stub_keys = stub_keys->length();
   int stub_keys_size = stub_keys->length() * kInt32Size;
   int data_length =
-      kHeaderSize + reservation_size + stub_keys_size + payload->length();
+      kHeaderSize + reservation_size + stub_keys_size + payload.length();
 
   // Allocate backing store and create result data.
   byte* data = NewArray<byte>(data_length);
@@ -2286,7 +2282,7 @@ SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
   SetHeaderValue(kNumInternalizedStringsOffset, cs->num_internalized_strings());
   SetHeaderValue(kReservationsOffset, reservations.length());
   SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys);
-  SetHeaderValue(kPayloadLengthOffset, payload->length());
+  SetHeaderValue(kPayloadLengthOffset, payload.length());
 
   // Copy reservation chunk sizes.
   CopyBytes(data + kHeaderSize, reinterpret_cast<byte*>(reservations.begin()),
@@ -2298,7 +2294,7 @@ SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
 
   // Copy serialized data.
   CopyBytes(data + kHeaderSize + reservation_size + stub_keys_size,
-            payload->begin(), static_cast<size_t>(payload->length()));
+            payload.begin(), static_cast<size_t>(payload.length()));
 }
 
 
index bc40b8f..d15fb54 100644 (file)
@@ -739,7 +739,7 @@ class SerializedCodeData {
   }
 
   // Used when producing.
-  SerializedCodeData(List<byte>* payload, CodeSerializer* cs);
+  SerializedCodeData(const List<byte>& payload, CodeSerializer* cs);
 
   ~SerializedCodeData() {
     if (owns_script_data_) delete script_data_;
index 29bad33..8e3b8a9 100644 (file)
@@ -89,11 +89,5 @@ bool SnapshotByteSource::GetBlob(const byte** data, int* number_of_bytes) {
   }
 }
 
-
-void DebugSnapshotSink::Put(byte b, const char* description) {
-  PrintF("%24s: %x\n", description, b);
-  sink_->Put(b, description);
-}
-
 }  // namespace v8::internal
 }  // namespace v8
index c1a31b5..68901a1 100644 (file)
@@ -70,53 +70,27 @@ class SnapshotByteSource FINAL {
  */
 class SnapshotByteSink {
  public:
-  virtual ~SnapshotByteSink() { }
-  virtual void Put(byte b, const char* description) = 0;
-  virtual void PutSection(int b, const char* description) {
+  SnapshotByteSink() {}
+  explicit SnapshotByteSink(int initial_size) : data_(initial_size) {}
+
+  ~SnapshotByteSink() {}
+
+  void Put(byte b, const char* description) { data_.Add(b); }
+
+  void PutSection(int b, const char* description) {
     DCHECK_LE(b, kMaxUInt8);
     Put(static_cast<byte>(b), description);
   }
+
   void PutInt(uintptr_t integer, const char* description);
   void PutRaw(byte* data, int number_of_bytes, const char* description);
   void PutBlob(byte* data, int number_of_bytes, const char* description);
-  virtual int Position() = 0;
-};
-
+  int Position() { return data_.length(); }
 
-class DummySnapshotSink : public SnapshotByteSink {
- public:
-  DummySnapshotSink() : length_(0) {}
-  virtual ~DummySnapshotSink() {}
-  virtual void Put(byte b, const char* description) { length_++; }
-  virtual int Position() { return length_; }
-
- private:
-  int length_;
-};
-
-
-// Wrap a SnapshotByteSink into a DebugSnapshotSink to get debugging output.
-class DebugSnapshotSink : public SnapshotByteSink {
- public:
-  explicit DebugSnapshotSink(SnapshotByteSink* chained) : sink_(chained) {}
-  virtual void Put(byte b, const char* description) OVERRIDE;
-  virtual int Position() OVERRIDE { return sink_->Position(); }
-
- private:
-  SnapshotByteSink* sink_;
-};
-
-
-class ListSnapshotSink : public i::SnapshotByteSink {
- public:
-  explicit ListSnapshotSink(i::List<byte>* data) : data_(data) {}
-  virtual void Put(byte b, const char* description) OVERRIDE {
-    data_->Add(b);
-  }
-  virtual int Position() OVERRIDE { return data_->length(); }
+  const List<byte>& data() const { return data_; }
 
  private:
-  i::List<byte>* data_;
+  List<byte> data_;
 };
 
 }  // namespace v8::internal
index e73e426..62c1d82 100644 (file)
@@ -114,41 +114,25 @@ TEST(ExternalReferenceDecoder) {
 }
 
 
-class FileByteSink : public SnapshotByteSink {
- public:
-  explicit FileByteSink(const char* snapshot_file) {
-    fp_ = v8::base::OS::FOpen(snapshot_file, "wb");
-    file_name_ = snapshot_file;
-    if (fp_ == NULL) {
-      PrintF("Unable to write to snapshot file \"%s\"\n", snapshot_file);
-      exit(1);
-    }
-  }
-  virtual ~FileByteSink() {
-    if (fp_ != NULL) {
-      fclose(fp_);
-    }
+void WritePayload(const List<byte>& payload, const char* file_name) {
+  FILE* file = v8::base::OS::FOpen(file_name, "wb");
+  if (file == NULL) {
+    PrintF("Unable to write to snapshot file \"%s\"\n", file_name);
+    exit(1);
   }
-  virtual void Put(byte b, const char* description) {
-    if (fp_ != NULL) {
-      fputc(b, fp_);
-    }
-  }
-  virtual int Position() {
-    return ftell(fp_);
+  size_t written = fwrite(payload.begin(), 1, payload.length(), file);
+  if (written != static_cast<size_t>(payload.length())) {
+    i::PrintF("Writing snapshot file failed.. Aborting.\n");
+    exit(1);
   }
-  void WriteSpaceUsed(Serializer* serializer);
-
- private:
-  FILE* fp_;
-  const char* file_name_;
-};
+  fclose(file);
+}
 
 
-void FileByteSink::WriteSpaceUsed(Serializer* ser) {
-  int file_name_length = StrLength(file_name_) + 10;
+void WriteSpaceUsed(Serializer* ser, const char* file_name) {
+  int file_name_length = StrLength(file_name) + 10;
   Vector<char> name = Vector<char>::New(file_name_length + 1);
-  SNPrintF(name, "%s.size", file_name_);
+  SNPrintF(name, "%s.size", file_name);
   FILE* fp = v8::base::OS::FOpen(name.start(), "w");
   name.Dispose();
 
@@ -181,12 +165,13 @@ void FileByteSink::WriteSpaceUsed(Serializer* ser) {
 
 
 static bool WriteToFile(Isolate* isolate, const char* snapshot_file) {
-  FileByteSink file(snapshot_file);
-  StartupSerializer ser(isolate, &file);
+  SnapshotByteSink sink;
+  StartupSerializer ser(isolate, &sink);
   ser.Serialize();
   ser.FinalizeAllocation();
 
-  file.WriteSpaceUsed(&ser);
+  WritePayload(sink.data(), snapshot_file);
+  WriteSpaceUsed(&ser, snapshot_file);
 
   return true;
 }
@@ -440,21 +425,26 @@ UNINITIALIZED_TEST(PartialSerialization) {
       }
       env.Reset();
 
-      FileByteSink startup_sink(startup_name.start());
+      SnapshotByteSink startup_sink;
       StartupSerializer startup_serializer(isolate, &startup_sink);
       startup_serializer.SerializeStrongReferences();
 
-      FileByteSink partial_sink(FLAG_testing_serialization_file);
-      PartialSerializer p_ser(isolate, &startup_serializer, &partial_sink);
-      p_ser.Serialize(&raw_foo);
+      SnapshotByteSink partial_sink;
+      PartialSerializer partial_serializer(isolate, &startup_serializer,
+                                           &partial_sink);
+      partial_serializer.Serialize(&raw_foo);
+
       startup_serializer.SerializeWeakReferences();
 
-      p_ser.FinalizeAllocation();
+      partial_serializer.FinalizeAllocation();
       startup_serializer.FinalizeAllocation();
 
-      partial_sink.WriteSpaceUsed(&p_ser);
+      WritePayload(partial_sink.data(), FLAG_testing_serialization_file);
+      WritePayload(startup_sink.data(), startup_name.start());
+
+      WriteSpaceUsed(&partial_serializer, FLAG_testing_serialization_file);
+      WriteSpaceUsed(&startup_serializer, startup_name.start());
 
-      startup_sink.WriteSpaceUsed(&startup_serializer);
       startup_name.Dispose();
     }
     v8_isolate->Exit();
@@ -552,21 +542,25 @@ UNINITIALIZED_TEST(ContextSerialization) {
 
       env.Reset();
 
-      FileByteSink startup_sink(startup_name.start());
+      SnapshotByteSink startup_sink;
       StartupSerializer startup_serializer(isolate, &startup_sink);
       startup_serializer.SerializeStrongReferences();
 
-      FileByteSink partial_sink(FLAG_testing_serialization_file);
-      PartialSerializer p_ser(isolate, &startup_serializer, &partial_sink);
-      p_ser.Serialize(&raw_context);
+      SnapshotByteSink partial_sink;
+      PartialSerializer partial_serializer(isolate, &startup_serializer,
+                                           &partial_sink);
+      partial_serializer.Serialize(&raw_context);
       startup_serializer.SerializeWeakReferences();
 
-      p_ser.FinalizeAllocation();
+      partial_serializer.FinalizeAllocation();
       startup_serializer.FinalizeAllocation();
 
-      partial_sink.WriteSpaceUsed(&p_ser);
+      WritePayload(partial_sink.data(), FLAG_testing_serialization_file);
+      WritePayload(startup_sink.data(), startup_name.start());
+
+      WriteSpaceUsed(&partial_serializer, FLAG_testing_serialization_file);
+      WriteSpaceUsed(&startup_serializer, startup_name.start());
 
-      startup_sink.WriteSpaceUsed(&startup_serializer);
       startup_name.Dispose();
     }
     v8_isolate->Dispose();