Implement enough of the partial snapshots that we can deserialize
authorerik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 15 Jan 2010 14:20:31 +0000 (14:20 +0000)
committererik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 15 Jan 2010 14:20:31 +0000 (14:20 +0000)
a single string.
Review URL: http://codereview.chromium.org/536077

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

src/serialize.cc
src/serialize.h
src/v8.cc
test/cctest/test-serialize.cc

index ef263fd..de2fb8e 100644 (file)
@@ -554,11 +554,10 @@ ExternalReferenceDecoder::~ExternalReferenceDecoder() {
 
 bool Serializer::serialization_enabled_ = false;
 bool Serializer::too_late_to_enable_now_ = false;
+ExternalReferenceDecoder* Deserializer::external_reference_decoder_ = NULL;
 
 
-Deserializer::Deserializer(SnapshotByteSource* source)
-    : source_(source),
-      external_reference_decoder_(NULL) {
+Deserializer::Deserializer(SnapshotByteSource* source) : source_(source) {
 }
 
 
@@ -648,8 +647,26 @@ void Deserializer::Deserialize() {
   external_reference_decoder_ = new ExternalReferenceDecoder();
   Heap::IterateRoots(this, VISIT_ONLY_STRONG);
   ASSERT(source_->AtEOF());
-  delete external_reference_decoder_;
-  external_reference_decoder_ = NULL;
+}
+
+
+void Deserializer::DeserializePartial(Object** root) {
+  // Don't GC while deserializing - just expand the heap.
+  AlwaysAllocateScope always_allocate;
+  // Don't use the free lists while deserializing.
+  LinearAllocationScope allocate_linearly;
+  if (external_reference_decoder_ == NULL) {
+    external_reference_decoder_ = new ExternalReferenceDecoder();
+  }
+  VisitPointer(root);
+}
+
+
+void Deserializer::TearDown() {
+  if (external_reference_decoder_ != NULL) {
+    delete external_reference_decoder_;
+    external_reference_decoder_ = NULL;
+  }
 }
 
 
@@ -862,6 +879,11 @@ void Deserializer::ReadChunk(Object** current,
         *current++ = reinterpret_cast<Object*>(resource);
         break;
       }
+      case ROOT_SERIALIZATION: {
+        int root_id = source_->GetInt();
+        *current++ = Heap::roots_address()[root_id];
+        break;
+      }
       default:
         UNREACHABLE();
     }
@@ -915,7 +937,8 @@ Serializer::Serializer(SnapshotByteSink* sink)
     : sink_(sink),
       current_root_index_(0),
       external_reference_encoder_(NULL),
-      partial_(false) {
+      partial_(false),
+      large_object_total_(0) {
   for (int i = 0; i <= LAST_SPACE; i++) {
     fullness_[i] = 0;
   }
@@ -1226,6 +1249,7 @@ int Serializer::Allocate(int space, int size, bool* new_page) {
     // In large object space we merely number the objects instead of trying to
     // determine some sort of address.
     *new_page = true;
+    large_object_total_ += size;
     return fullness_[LO_SPACE]++;
   }
   *new_page = false;
index b32f4e8..fcd3723 100644 (file)
@@ -239,10 +239,16 @@ class Deserializer: public SerDes {
 
   // Deserialize the snapshot into an empty heap.
   void Deserialize();
+
+  // Deserialize a single object and the objects reachable from it.
+  void DeserializePartial(Object** root);
+
 #ifdef DEBUG
   virtual void Synchronize(const char* tag);
 #endif
 
+  static void TearDown();
+
  private:
   virtual void VisitPointers(Object** start, Object** end);
 
@@ -267,7 +273,7 @@ class Deserializer: public SerDes {
   List<Address> pages_[SerDes::kNumberOfSpaces];
 
   SnapshotByteSource* source_;
-  ExternalReferenceDecoder* external_reference_decoder_;
+  static ExternalReferenceDecoder* external_reference_decoder_;
   // This is the address of the next object that will be allocated in each
   // space.  It is used to calculate the addresses of back-references.
   Address high_water_[LAST_SPACE + 1];
@@ -302,7 +308,7 @@ class Serializer : public SerDes {
   // You can call this after serialization to find out how much space was used
   // in each space.
   int CurrentAllocationAddress(int space) {
-    if (SpaceIsLarge(space)) space = LO_SPACE;
+    if (SpaceIsLarge(space)) return large_object_total_;
     return fullness_[space];
   }
 
@@ -392,6 +398,7 @@ class Serializer : public SerDes {
   static bool serialization_enabled_;
   // Did we already make use of the fact that serialization was not enabled?
   static bool too_late_to_enable_now_;
+  int large_object_total_;
 
   friend class ObjectSerializer;
   friend class Deserializer;
index 3bec827..db570a4 100644 (file)
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -146,6 +146,7 @@ void V8::TearDown() {
 
   Heap::TearDown();
   Logger::TearDown();
+  Deserializer::TearDown();
 
   is_running_ = false;
   has_been_disposed_ = true;
index 9961281..94b741c 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2007-2008 the V8 project authors. All rights reserved.
+// Copyright 2007-2010 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -277,6 +277,7 @@ class FileByteSink : public SnapshotByteSink {
  public:
   explicit FileByteSink(const char* snapshot_file) {
     fp_ = 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);
@@ -292,12 +293,44 @@ class FileByteSink : public SnapshotByteSink {
       fputc(byte, fp_);
     }
   }
+  void WriteSpaceUsed(
+      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 large_space_used);
 
  private:
   FILE* fp_;
+  const char* file_name_;
 };
 
 
+void FileByteSink::WriteSpaceUsed(
+      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 large_space_used) {
+  int file_name_length = strlen(file_name_) + 10;
+  Vector<char> name = Vector<char>::New(file_name_length + 1);
+  OS::SNPrintF(name, "%s.size", file_name_);
+  FILE* fp = OS::FOpen(name.start(), "wa");
+  fprintf(fp, "new %d\n", new_space_used);
+  fprintf(fp, "pointer %d\n", pointer_space_used);
+  fprintf(fp, "data %d\n", data_space_used);
+  fprintf(fp, "code %d\n", code_space_used);
+  fprintf(fp, "map %d\n", map_space_used);
+  fprintf(fp, "cell %d\n", cell_space_used);
+  fprintf(fp, "large %d\n", large_space_used);
+  fclose(fp);
+}
+
+
 TEST(PartialSerialization) {
   Serializer::Enable();
   v8::V8::Initialize();
@@ -312,6 +345,47 @@ TEST(PartialSerialization) {
   i::Handle<i::String> internal_foo = v8::Utils::OpenHandle(*foo);
   Object* raw_foo = *internal_foo;
   ser.SerializePartial(&raw_foo);
+  file.WriteSpaceUsed(ser.CurrentAllocationAddress(NEW_SPACE),
+                      ser.CurrentAllocationAddress(OLD_POINTER_SPACE),
+                      ser.CurrentAllocationAddress(OLD_DATA_SPACE),
+                      ser.CurrentAllocationAddress(CODE_SPACE),
+                      ser.CurrentAllocationAddress(MAP_SPACE),
+                      ser.CurrentAllocationAddress(CELL_SPACE),
+                      ser.CurrentAllocationAddress(LO_SPACE));
+}
+
+
+DEPENDENT_TEST(PartialDeserialization, PartialSerialization) {
+  v8::V8::Initialize();
+  const char* file_name = FLAG_testing_serialization_file;
+  int file_name_length = strlen(file_name) + 10;
+  Vector<char> name = Vector<char>::New(file_name_length + 1);
+  OS::SNPrintF(name, "%s.size", file_name);
+  FILE* fp = OS::FOpen(name.start(), "ra");
+  int new_size, pointer_size, data_size, code_size, map_size, cell_size;
+  int large_size;
+  CHECK_EQ(1, fscanf(fp, "new %d\n", &new_size));
+  CHECK_EQ(1, fscanf(fp, "pointer %d\n", &pointer_size));
+  CHECK_EQ(1, fscanf(fp, "data %d\n", &data_size));
+  CHECK_EQ(1, fscanf(fp, "code %d\n", &code_size));
+  CHECK_EQ(1, fscanf(fp, "map %d\n", &map_size));
+  CHECK_EQ(1, fscanf(fp, "cell %d\n", &cell_size));
+  CHECK_EQ(1, fscanf(fp, "large %d\n", &large_size));
+  fclose(fp);
+  Heap::ReserveSpace(new_size,
+                     pointer_size,
+                     data_size,
+                     code_size,
+                     map_size,
+                     cell_size,
+                     large_size);
+  int snapshot_size = 0;
+  byte* snapshot = ReadBytes(file_name, &snapshot_size);
+  SnapshotByteSource source(snapshot, snapshot_size);
+  Deserializer deserializer(&source);
+  Object* root;
+  deserializer.DeserializePartial(&root);
+  CHECK(root->IsString());
 }