Revision: 3360
Author: [email protected]
Date: Wed Nov 25 04:55:33 2009
Log: Make heap serialization nondestructive.
Review URL: http://codereview.chromium.org/441017
http://code.google.com/p/v8/source/detail?r=3360

Modified:
  /branches/bleeding_edge/src/objects-inl.h
  /branches/bleeding_edge/src/objects.h
  /branches/bleeding_edge/src/serialize.cc
  /branches/bleeding_edge/test/cctest/test-serialize.cc

=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Tue Nov 24 06:10:06 2009
+++ /branches/bleeding_edge/src/objects-inl.h   Wed Nov 25 04:55:33 2009
@@ -914,25 +914,6 @@
    ASSERT(IsForwardingAddress());
    return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
  }
-
-
-bool MapWord::IsSerializationAddress() {
-  return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
-}
-
-
-MapWord MapWord::FromSerializationAddress(int raw) {
-  // When the map word is being used as a serialization address we  
Smi-encode
-  // the serialization address (which is always a smallish positive  
integer).
-  return MapWord(reinterpret_cast<uintptr_t>(Smi::FromInt(raw)));
-}
-
-
-int MapWord::ToSerializationAddress() {
-  // When the map word is being used as a serialization address we treat  
the
-  // map word as a Smi and get the small integer that it encodes.
-  return reinterpret_cast<Smi*>(value_)->value();
-}


  bool MapWord::IsMarked() {
=======================================
--- /branches/bleeding_edge/src/objects.h       Tue Nov 24 06:10:06 2009
+++ /branches/bleeding_edge/src/objects.h       Wed Nov 25 04:55:33 2009
@@ -830,16 +830,6 @@
    // View this map word as a forwarding address.
    inline HeapObject* ToForwardingAddress();

-  // True if this map word is a serialization address.  This will only be  
the
-  // case during a destructive serialization of the heap.
-  inline bool IsSerializationAddress();
-
-  // Create a map word from a serialization address.
-  static inline MapWord FromSerializationAddress(int raw);
-
-  // View this map word as a serialization address.
-  inline int ToSerializationAddress();
-
    // Marking phase of full collection: the map word of live objects is
    // marked, and may be marked as overflowed (eg, the object is live, its
    // children have not been visited, and it does not fit in the marking
=======================================
--- /branches/bleeding_edge/src/serialize.cc    Fri Nov 20 04:38:59 2009
+++ /branches/bleeding_edge/src/serialize.cc    Wed Nov 25 04:55:33 2009
@@ -44,6 +44,69 @@
  namespace v8 {
  namespace internal {

+// Mapping objects to their location after deserialization.
+// This is used during building, but not at runtime by V8.
+class SerializationAddressMapper {
+ public:
+  static bool IsMapped(HeapObject* obj) {
+    EnsureMapExists();
+    return serialization_map_->Lookup(Key(obj), Hash(obj), false) != NULL;
+  }
+
+  static int MappedTo(HeapObject* obj) {
+    ASSERT(IsMapped(obj));
+    return reinterpret_cast<int>(serialization_map_->Lookup(Key(obj),
+                                 Hash(obj),
+                                 false)->value);
+  }
+
+  static void Map(HeapObject* obj, int to) {
+    EnsureMapExists();
+    ASSERT(!IsMapped(obj));
+    HashMap::Entry* entry =
+        serialization_map_->Lookup(Key(obj), Hash(obj), true);
+    entry->value = Value(to);
+  }
+
+  static void Zap() {
+    if (serialization_map_ != NULL) {
+      delete serialization_map_;
+    }
+    serialization_map_ = NULL;
+  }
+
+ private:
+  static bool SerializationMatchFun(void* key1, void* key2) {
+    return key1 == key2;
+  }
+
+  static uint32_t Hash(HeapObject* obj) {
+    return reinterpret_cast<uint32_t>(obj->address());
+  }
+
+  static void* Key(HeapObject* obj) {
+    return reinterpret_cast<void*>(obj->address());
+  }
+
+  static void* Value(int v) {
+    return reinterpret_cast<void*>(v);
+  }
+
+  static void EnsureMapExists() {
+    if (serialization_map_ == NULL) {
+      serialization_map_ = new HashMap(&SerializationMatchFun);
+    }
+  }
+
+  static HashMap* serialization_map_;
+};
+
+
+HashMap* SerializationAddressMapper::serialization_map_ = NULL;
+
+
+
+
  //  
-----------------------------------------------------------------------------
  // Coding of external references.

@@ -871,6 +934,7 @@
    Heap::IterateRoots(this, VISIT_ONLY_STRONG);
    delete external_reference_encoder_;
    external_reference_encoder_ = NULL;
+  SerializationAddressMapper::Zap();
  }


@@ -894,10 +958,9 @@
      ReferenceRepresentation reference_representation) {
    CHECK(o->IsHeapObject());
    HeapObject* heap_object = HeapObject::cast(o);
-  MapWord map_word = heap_object->map_word();
-  if (map_word.IsSerializationAddress()) {
+  if (SerializationAddressMapper::IsMapped(heap_object)) {
      int space = SpaceOfAlreadySerializedObject(heap_object);
-    int address = map_word.ToSerializationAddress();
+    int address = SerializationAddressMapper::MappedTo(heap_object);
      int offset = CurrentAllocationAddress(space) - address;
      bool from_start = true;
      if (SpaceIsPaged(space)) {
@@ -965,24 +1028,23 @@
    }
    sink_->PutInt(size >> kObjectAlignmentBits, "Size in words");

-  // Get the map before overwriting it.
-  Map* map = object_->map();
    // Mark this object as already serialized.
    bool start_new_page;
-  object_->set_map_word(MapWord::FromSerializationAddress(
-      serializer_->Allocate(space, size, &start_new_page)));
+  SerializationAddressMapper::Map(
+    object_,
+    serializer_->Allocate(space, size, &start_new_page));
    if (start_new_page) {
      sink_->Put(START_NEW_PAGE_SERIALIZATION, "NewPage");
      sink_->PutSection(space, "NewPageSpace");
    }

    // Serialize the map (first word of the object).
-  serializer_->SerializeObject(map, TAGGED_REPRESENTATION);
+  serializer_->SerializeObject(object_->map(), TAGGED_REPRESENTATION);

    // Serialize the rest of the object.
    CHECK_EQ(0, bytes_processed_so_far_);
    bytes_processed_so_far_ = kPointerSize;
-  object_->IterateBody(map->instance_type(), size, this);
+  object_->IterateBody(object_->map()->instance_type(), size, this);
    OutputRawData(object_->address() + size);
  }

@@ -1044,12 +1106,9 @@
    Address references_start = reinterpret_cast<Address>(resource_pointer);
    OutputRawData(references_start);
    for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
-    // Use raw_unchecked when maps are munged.
-    Object* source = Heap::raw_unchecked_natives_source_cache()->get(i);
+    Object* source = Heap::natives_source_cache()->get(i);
      if (!source->IsUndefined()) {
-      // Don't use cast when maps are munged.
-      ExternalAsciiString* string =
-          reinterpret_cast<ExternalAsciiString*>(source);
+      ExternalAsciiString* string = ExternalAsciiString::cast(source);
        typedef v8::String::ExternalAsciiStringResource Resource;
        Resource* resource = string->resource();
        if (resource == *resource_pointer) {
=======================================
--- /branches/bleeding_edge/test/cctest/test-serialize.cc       Mon Nov 16  
04:08:40 2009
+++ /branches/bleeding_edge/test/cctest/test-serialize.cc       Wed Nov 25  
04:55:33 2009
@@ -190,6 +190,15 @@
    v8::V8::Initialize();
    Serialize();
  }
+
+
+// Test that heap serialization is non-destructive.
+TEST(SerializeTwice) {
+  Serializer::Enable();
+  v8::V8::Initialize();
+  Serialize();
+  Serialize();
+}


   
//----------------------------------------------------------------------------
@@ -218,7 +227,17 @@

    Deserialize();

-  fflush(stdout);
+  v8::Persistent<v8::Context> env = v8::Context::New();
+  env->Enter();
+
+  SanityCheck();
+}
+
+
+DEPENDENT_TEST(DeserializeFromSecondSerialization, SerializeTwice) {
+  v8::HandleScope scope;
+
+  Deserialize();

    v8::Persistent<v8::Context> env = v8::Context::New();
    env->Enter();
@@ -240,6 +259,22 @@
    v8::Local<v8::Script> script = v8::Script::Compile(source);
    CHECK_EQ(4, script->Run()->Int32Value());
  }
+
+
+DEPENDENT_TEST(DeserializeFromSecondSerializationAndRunScript2,
+               SerializeTwice) {
+  v8::HandleScope scope;
+
+  Deserialize();
+
+  v8::Persistent<v8::Context> env = v8::Context::New();
+  env->Enter();
+
+  const char* c_source = "\"1234\".length";
+  v8::Local<v8::String> source = v8::String::New(c_source);
+  v8::Local<v8::Script> script = v8::Script::Compile(source);
+  CHECK_EQ(4, script->Run()->Int32Value());
+}


  TEST(TestThatAlwaysSucceeds) {

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to