Revision: 24826
Author:   [email protected]
Date:     Thu Oct 23 08:43:17 2014 UTC
Log: Use hash map to look for objects in the root array when serializing.

[email protected]

Review URL: https://codereview.chromium.org/645533003
https://code.google.com/p/v8/source/detail?r=24826

Modified:
 /branches/bleeding_edge/src/compiler.cc
 /branches/bleeding_edge/src/heap/heap-inl.h
 /branches/bleeding_edge/src/heap/heap.cc
 /branches/bleeding_edge/src/isolate.cc
 /branches/bleeding_edge/src/serialize.cc
 /branches/bleeding_edge/src/serialize.h

=======================================
--- /branches/bleeding_edge/src/compiler.cc     Tue Oct 21 12:16:37 2014 UTC
+++ /branches/bleeding_edge/src/compiler.cc     Thu Oct 23 08:43:17 2014 UTC
@@ -1238,8 +1238,8 @@
             isolate->counters()->compile_serialize());
         *cached_data = CodeSerializer::Serialize(isolate, result, source);
         if (FLAG_profile_deserialization) {
-          PrintF("[Compiling and serializing %d bytes took %0.3f ms]\n",
- (*cached_data)->length(), timer.Elapsed().InMillisecondsF());
+          PrintF("[Compiling and serializing took %0.3f ms]\n",
+                 timer.Elapsed().InMillisecondsF());
         }
       }
     }
=======================================
--- /branches/bleeding_edge/src/heap/heap-inl.h Fri Sep 19 11:32:17 2014 UTC
+++ /branches/bleeding_edge/src/heap/heap-inl.h Thu Oct 23 08:43:17 2014 UTC
@@ -699,7 +699,7 @@


 void Heap::ClearInstanceofCache() {
-  set_instanceof_cache_function(the_hole_value());
+  set_instanceof_cache_function(Smi::FromInt(0));
 }


@@ -709,8 +709,8 @@


 void Heap::CompletelyClearInstanceofCache() {
-  set_instanceof_cache_map(the_hole_value());
-  set_instanceof_cache_function(the_hole_value());
+  set_instanceof_cache_map(Smi::FromInt(0));
+  set_instanceof_cache_function(Smi::FromInt(0));
 }


=======================================
--- /branches/bleeding_edge/src/heap/heap.cc    Wed Oct 22 06:58:38 2014 UTC
+++ /branches/bleeding_edge/src/heap/heap.cc    Thu Oct 23 08:43:17 2014 UTC
@@ -2906,7 +2906,7 @@
   set_undefined_cell(*factory->NewCell(factory->undefined_value()));

   // The symbol registry is initialized lazily.
-  set_symbol_registry(undefined_value());
+  set_symbol_registry(Smi::FromInt(0));

   // Allocate object to hold object observation state.
   set_observation_state(*factory->NewJSObjectFromMap(
=======================================
--- /branches/bleeding_edge/src/isolate.cc      Thu Oct 23 07:36:39 2014 UTC
+++ /branches/bleeding_edge/src/isolate.cc      Thu Oct 23 08:43:17 2014 UTC
@@ -2206,7 +2206,7 @@


 Handle<JSObject> Isolate::GetSymbolRegistry() {
-  if (heap()->symbol_registry()->IsUndefined()) {
+  if (heap()->symbol_registry()->IsSmi()) {
Handle<Map> map = factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
     Handle<JSObject> registry = factory()->NewJSObjectFromMap(map);
     heap()->set_symbol_registry(*registry);
=======================================
--- /branches/bleeding_edge/src/serialize.cc    Thu Oct 23 08:25:42 2014 UTC
+++ /branches/bleeding_edge/src/serialize.cc    Thu Oct 23 08:43:17 2014 UTC
@@ -479,6 +479,25 @@
   }
   DeleteArray(encodings_);
 }
+
+
+RootIndexMap::RootIndexMap(Isolate* isolate) {
+  map_ = new HashMap(HashMap::PointersMatch);
+  Object** root_array = isolate->heap()->roots_array_start();
+  for (int i = 0; i < Heap::kStrongRootListLength; i++) {
+    Object* root = root_array[i];
+    if (root->IsHeapObject() && !isolate->heap()->InNewSpace(root)) {
+      HeapObject* heap_object = HeapObject::cast(root);
+      if (LookupEntry(map_, heap_object, false) != NULL) {
+        // Some root values are initialized to the empty FixedArray();
+        // Do not add them to the map.
+        DCHECK_EQ(isolate->heap()->empty_fixed_array(), heap_object);
+      } else {
+        SetValue(LookupEntry(map_, heap_object, true), i);
+      }
+    }
+  }
+}


 class CodeAddressMap: public CodeEventLogger {
@@ -1237,7 +1256,7 @@
     : isolate_(isolate),
       sink_(sink),
       external_reference_encoder_(new ExternalReferenceEncoder(isolate)),
-      root_index_wave_front_(0),
+      root_index_map_(isolate),
       code_address_map_(NULL),
       seen_large_objects_index_(0) {
// The serializer is meant to be used only to generate initial heap images
@@ -1265,6 +1284,27 @@
   isolate->heap()->IterateSmiRoots(this);
   isolate->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG);
 }
+
+
+void StartupSerializer::VisitPointers(Object** start, Object** end) {
+  for (Object** current = start; current < end; current++) {
+    if (start == isolate()->heap()->roots_array_start()) {
+      root_index_wave_front_ =
+ Max(root_index_wave_front_, static_cast<intptr_t>(current - start));
+    }
+    if (ShouldBeSkipped(current)) {
+      sink_->Put(kSkip, "Skip");
+      sink_->PutInt(kPointerSize, "SkipOneWord");
+    } else if ((*current)->IsSmi()) {
+      sink_->Put(kRawData + 1, "Smi");
+      for (int i = 0; i < kPointerSize; i++) {
+        sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte");
+      }
+    } else {
+ SerializeObject(HeapObject::cast(*current), kPlain, kStartOfObject, 0);
+    }
+  }
+}


 void PartialSerializer::Serialize(Object** object) {
@@ -1282,23 +1322,14 @@


 void Serializer::VisitPointers(Object** start, Object** end) {
-  Isolate* isolate = this->isolate();;
-
   for (Object** current = start; current < end; current++) {
-    if (start == isolate->heap()->roots_array_start()) {
-      root_index_wave_front_ =
- Max(root_index_wave_front_, static_cast<intptr_t>(current - start));
-    }
-    if (ShouldBeSkipped(current)) {
-      sink_->Put(kSkip, "Skip");
-      sink_->PutInt(kPointerSize, "SkipOneWord");
-    } else if ((*current)->IsSmi()) {
+    if ((*current)->IsSmi()) {
       sink_->Put(kRawData + 1, "Smi");
       for (int i = 0; i < kPointerSize; i++) {
         sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte");
       }
     } else {
-      SerializeObject(*current, kPlain, kStartOfObject, 0);
+ SerializeObject(HeapObject::cast(*current), kPlain, kStartOfObject, 0);
     }
   }
 }
@@ -1366,31 +1397,16 @@
   DCHECK(length == isolate->serialize_partial_snapshot_cache_length() - 1);
   return length;
 }
-
-
-int Serializer::RootIndex(HeapObject* heap_object, HowToCode from) {
-  Heap* heap = isolate()->heap();
-  if (heap->InNewSpace(heap_object)) return kInvalidRootIndex;
-  for (int i = 0; i < root_index_wave_front_; i++) {
-    Object* root = heap->roots_array_start()[i];
-    if (!root->IsSmi() && root == heap_object) {
-      return i;
-    }
-  }
-  return kInvalidRootIndex;
-}


// Encode the location of an already deserialized object in order to write its // location into a later object. We can encode the location as an offset from
 // the start of the deserialized objects or as an offset backwards from the
 // current allocation pointer.
-void Serializer::SerializeReferenceToPreviousObject(HeapObject* heap_object,
-                                                    HowToCode how_to_code,
- WhereToPoint where_to_point,
-                                                    int skip) {
-  int space = SpaceOfObject(heap_object);
-
+void Serializer::SerializeBackReference(BackReference back_reference,
+                                        HowToCode how_to_code,
+ WhereToPoint where_to_point, int skip) {
+  AllocationSpace space = back_reference.space();
   if (skip == 0) {
sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRefSer");
   } else {
@@ -1399,50 +1415,39 @@
     sink_->PutInt(skip, "BackRefSkipDistance");
   }

-  if (space == LO_SPACE) {
-    int index = address_mapper_.MappedTo(heap_object);
-    sink_->PutInt(index, "large object index");
-  } else {
-    uint32_t existing_allocation = address_mapper_.MappedTo(heap_object);
-    // Shift out the bits that are always 0.
-    existing_allocation >>= kObjectAlignmentBits;
-    sink_->PutInt(existing_allocation, "allocation");
-  }
+  sink_->PutInt(back_reference.reference(),
+                (space == LO_SPACE) ? "large object index" : "allocation");
 }


-void StartupSerializer::SerializeObject(
-    Object* o,
-    HowToCode how_to_code,
-    WhereToPoint where_to_point,
-    int skip) {
-  CHECK(o->IsHeapObject());
-  HeapObject* heap_object = HeapObject::cast(o);
-  DCHECK(!heap_object->IsJSFunction());
+void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, + WhereToPoint where_to_point, int skip) {
+  DCHECK(!obj->IsJSFunction());

-  int root_index;
- if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) {
-    PutRoot(root_index, heap_object, how_to_code, where_to_point, skip);
+  int root_index = root_index_map_.Lookup(obj);
+  // We can only encode roots as such if it has already been serialized.
+  // That applies to root indices below the wave front.
+  if (root_index != RootIndexMap::kInvalidRootIndex &&
+      root_index < root_index_wave_front_) {
+    PutRoot(root_index, obj, how_to_code, where_to_point, skip);
     return;
   }

-  if (address_mapper_.IsMapped(heap_object)) {
- SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point,
-                                       skip);
-  } else {
-    if (skip != 0) {
-      sink_->Put(kSkip, "FlushPendingSkip");
-      sink_->PutInt(skip, "SkipDistance");
-    }
+  BackReference back_reference = back_reference_map_.Lookup(obj);
+  if (back_reference.is_valid()) {
+ SerializeBackReference(back_reference, how_to_code, where_to_point, skip);
+    return;
+  }

-    // Object has not yet been serialized.  Serialize it here.
-    ObjectSerializer object_serializer(this,
-                                       heap_object,
-                                       sink_,
-                                       how_to_code,
-                                       where_to_point);
-    object_serializer.Serialize();
+  if (skip != 0) {
+    sink_->Put(kSkip, "FlushPendingSkip");
+    sink_->PutInt(skip, "SkipDistance");
   }
+
+  // Object has not yet been serialized.  Serialize it here.
+  ObjectSerializer object_serializer(this, obj, sink_, how_to_code,
+                                     where_to_point);
+  object_serializer.Serialize();
 }


@@ -1487,34 +1492,27 @@
 }


-void PartialSerializer::SerializeObject(
-    Object* o,
-    HowToCode how_to_code,
-    WhereToPoint where_to_point,
-    int skip) {
-  CHECK(o->IsHeapObject());
-  HeapObject* heap_object = HeapObject::cast(o);
-
-  if (heap_object->IsMap()) {
+void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, + WhereToPoint where_to_point, int skip) {
+  if (obj->IsMap()) {
     // The code-caches link to context-specific code objects, which
     // the startup and context serializes cannot currently handle.
-    DCHECK(Map::cast(heap_object)->code_cache() ==
-           heap_object->GetHeap()->empty_fixed_array());
+ DCHECK(Map::cast(obj)->code_cache() == obj->GetHeap()->empty_fixed_array());
   }

-  int root_index;
- if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) {
-    PutRoot(root_index, heap_object, how_to_code, where_to_point, skip);
+  int root_index = root_index_map_.Lookup(obj);
+  if (root_index != RootIndexMap::kInvalidRootIndex) {
+    PutRoot(root_index, obj, how_to_code, where_to_point, skip);
     return;
   }

-  if (ShouldBeInThePartialSnapshotCache(heap_object)) {
+  if (ShouldBeInThePartialSnapshotCache(obj)) {
     if (skip != 0) {
       sink_->Put(kSkip, "SkipFromSerializeObject");
       sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
     }

-    int cache_index = PartialSnapshotCacheIndex(heap_object);
+    int cache_index = PartialSnapshotCacheIndex(obj);
     sink_->Put(kPartialSnapshotCache + how_to_code + where_to_point,
                "PartialSnapshotCache");
     sink_->PutInt(cache_index, "partial_snapshot_cache_index");
@@ -1524,32 +1522,29 @@
// Pointers from the partial snapshot to the objects in the startup snapshot // should go through the root array or through the partial snapshot cache. // If this is not the case you may have to add something to the root array.
-  DCHECK(!startup_serializer_->address_mapper()->IsMapped(heap_object));
+ DCHECK(!startup_serializer_->back_reference_map()->Lookup(obj).is_valid());
   // All the internalized strings that the partial snapshot needs should be
   // either in the root table or in the partial snapshot cache.
-  DCHECK(!heap_object->IsInternalizedString());
+  DCHECK(!obj->IsInternalizedString());

-  if (address_mapper_.IsMapped(heap_object)) {
- SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point,
-                                       skip);
-  } else {
-    if (skip != 0) {
-      sink_->Put(kSkip, "SkipFromSerializeObject");
-      sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
-    }
-    // Object has not yet been serialized.  Serialize it here.
-    ObjectSerializer serializer(this,
-                                heap_object,
-                                sink_,
-                                how_to_code,
-                                where_to_point);
-    serializer.Serialize();
+  BackReference back_reference = back_reference_map_.Lookup(obj);
+  if (back_reference.is_valid()) {
+ SerializeBackReference(back_reference, how_to_code, where_to_point, skip);
+    return;
+  }
+
+  if (skip != 0) {
+    sink_->Put(kSkip, "SkipFromSerializeObject");
+    sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
   }
+  // Object has not yet been serialized.  Serialize it here.
+ ObjectSerializer serializer(this, obj, sink_, how_to_code, where_to_point);
+  serializer.Serialize();
 }


-void Serializer::ObjectSerializer::SerializePrologue(int space, int size,
-                                                     Map* map) {
+void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space,
+                                                     int size, Map* map) {
   sink_->Put(kNewObject + reference_representation_ + space,
              "ObjectSerialization");
   sink_->PutInt(size >> kObjectAlignmentBits, "Size in words");
@@ -1564,18 +1559,18 @@
   }

   // Mark this object as already serialized.
+  BackReference back_reference;
   if (space == LO_SPACE) {
     if (object_->IsCode()) {
       sink_->Put(EXECUTABLE, "executable large object");
     } else {
       sink_->Put(NOT_EXECUTABLE, "not executable large object");
     }
-    int index = serializer_->AllocateLargeObject(size);
-    serializer_->address_mapper()->AddMapping(object_, index);
+    back_reference = serializer_->AllocateLargeObject(size);
   } else {
-    int allocation = serializer_->Allocate(space, size);
-    serializer_->address_mapper()->AddMapping(object_, allocation);
+    back_reference = serializer_->Allocate(space, size);
   }
+  serializer_->back_reference_map()->Add(object_, back_reference);

   // Serialize the map (first word of the object).
   serializer_->SerializeObject(map, kPlain, kStartOfObject, 0);
@@ -1608,7 +1603,7 @@
         ExternalTwoByteString::cast(string)->resource()->data());
   }

-  int space =
+  AllocationSpace space =
       (size > Page::kMaxRegularHeapObjectSize) ? LO_SPACE : OLD_DATA_SPACE;
   SerializePrologue(space, size, map);

@@ -1673,12 +1668,11 @@

     while (current < end && !(*current)->IsSmi()) {
       HeapObject* current_contents = HeapObject::cast(*current);
-      int root_index = serializer_->RootIndex(current_contents, kPlain);
+ int root_index = serializer_->root_index_map()->Lookup(current_contents); // Repeats are not subject to the write barrier so there are only some // objects that can be used in a repeat encoding. These are the early
       // ones in the root array that are never in new space.
-      if (current != start &&
-          root_index != kInvalidRootIndex &&
+ if (current != start && root_index != RootIndexMap::kInvalidRootIndex &&
           root_index < kRootArrayNumberOfConstantEncodings &&
           current_contents == current[-1]) {
DCHECK(!serializer_->isolate()->heap()->InNewSpace(current_contents));
@@ -1714,7 +1708,8 @@
                            kCanReturnSkipInsteadOfSkipping);
   HowToCode how_to_code = rinfo->IsCodedSpecially() ? kFromCode : kPlain;
   Object* object = rinfo->target_object();
-  serializer_->SerializeObject(object, how_to_code, kStartOfObject, skip);
+  serializer_->SerializeObject(HeapObject::cast(object), how_to_code,
+                               kStartOfObject, skip);
   bytes_processed_so_far_ += rinfo->target_address_size();
 }

@@ -1890,32 +1885,31 @@
 }


-int Serializer::SpaceOfObject(HeapObject* object) {
+AllocationSpace Serializer::SpaceOfObject(HeapObject* object) {
   for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) {
     AllocationSpace s = static_cast<AllocationSpace>(i);
     if (object->GetHeap()->InSpace(object, s)) {
       DCHECK(i < kNumberOfSpaces);
-      return i;
+      return s;
     }
   }
   UNREACHABLE();
-  return 0;
+  return INVALID_SPACE;
 }


-uint32_t Serializer::AllocateLargeObject(int size) {
+BackReference Serializer::AllocateLargeObject(int size) {
   // Large objects are allocated one-by-one when deserializing. We do not
   // have to keep track of multiple chunks.
   pending_chunk_[LO_SPACE] += size;
-  return seen_large_objects_index_++;
+  return BackReference(LO_SPACE, 0, seen_large_objects_index_++);
 }


-uint32_t Serializer::Allocate(int space, int size) {
+BackReference Serializer::Allocate(AllocationSpace space, int size) {
   CHECK(space >= 0 && space < kNumberOfPreallocatedSpaces);
   DCHECK(size > 0 && size <= Page::kMaxRegularHeapObjectSize);
   uint32_t new_chunk_size = pending_chunk_[space] + size;
-  uint32_t allocation;
if (new_chunk_size > static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize)) {
     // The new chunk size would not fit onto a single page. Complete the
     // current chunk and start a new one.
@@ -1923,12 +1917,9 @@
     pending_chunk_[space] = 0;
     new_chunk_size = size;
   }
-  // For back-referencing, each allocation is encoded as a combination
-  // of chunk index and offset inside the chunk.
-  allocation = ChunkIndexBits::encode(completed_chunks_[space].length()) |
-               OffsetBits::encode(pending_chunk_[space]);
+  uint32_t offset = pending_chunk_[space];
   pending_chunk_[space] = new_chunk_size;
-  return allocation;
+  return BackReference(space, completed_chunks_[space].length(), offset);
 }


@@ -1982,6 +1973,13 @@
   cs.Pad();
   cs.FinalizeAllocation();

+  for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
+    // Fail if any chunk index exceeds the limit.
+ if (cs.FinalAllocationChunks(i).length() > BackReference::kMaxChunkIndex) {
+      return NULL;
+    }
+  }
+
   SerializedCodeData data(&payload, &cs);
   ScriptData* script_data = data.GetScriptData();

@@ -1995,27 +1993,25 @@
 }


-void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
+void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, WhereToPoint where_to_point, int skip) {
-  HeapObject* heap_object = HeapObject::cast(o);
-
-  int root_index;
- if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) {
+  int root_index = root_index_map_.Lookup(obj);
+  if (root_index != RootIndexMap::kInvalidRootIndex) {
     if (FLAG_serializer_trace_level > 0) {
       PrintF(" Encoding root: %d\n", root_index);
     }
-    PutRoot(root_index, heap_object, how_to_code, where_to_point, skip);
+    PutRoot(root_index, obj, how_to_code, where_to_point, skip);
     return;
   }

-  if (address_mapper_.IsMapped(heap_object)) {
+  BackReference back_reference = back_reference_map_.Lookup(obj);
+  if (back_reference.is_valid()) {
     if (FLAG_serializer_trace_level > 0) {
       PrintF(" Encoding back reference to: ");
-      heap_object->ShortPrint();
+      obj->ShortPrint();
       PrintF("\n");
     }
- SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point,
-                                       skip);
+ SerializeBackReference(back_reference, how_to_code, where_to_point, skip);
     return;
   }

@@ -2024,8 +2020,8 @@
     sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
   }

-  if (heap_object->IsCode()) {
-    Code* code_object = Code::cast(heap_object);
+  if (obj->IsCode()) {
+    Code* code_object = Code::cast(obj);
     switch (code_object->kind()) {
       case Code::OPTIMIZED_FUNCTION:  // No optimized code compiled yet.
       case Code::HANDLER:             // No handlers patched in yet.
@@ -2052,32 +2048,32 @@
SerializeBuiltin(Builtins::kCompileLazy, how_to_code, where_to_point);
         } else {
           code_object->MakeYoung();
-          SerializeHeapObject(code_object, how_to_code, where_to_point);
+          SerializeGeneric(code_object, how_to_code, where_to_point);
         }
         return;
     }
     UNREACHABLE();
   }

-  if (heap_object == source_) {
+  if (obj == source_) {
     SerializeSourceObject(how_to_code, where_to_point);
     return;
   }

   // Past this point we should not see any (context-specific) maps anymore.
-  CHECK(!heap_object->IsMap());
+  CHECK(!obj->IsMap());
   // There should be no references to the global object embedded.
-  CHECK(!heap_object->IsJSGlobalProxy() && !heap_object->IsGlobalObject());
+  CHECK(!obj->IsJSGlobalProxy() && !obj->IsGlobalObject());
   // There should be no hash table embedded. They would require rehashing.
-  CHECK(!heap_object->IsHashTable());
+  CHECK(!obj->IsHashTable());

-  SerializeHeapObject(heap_object, how_to_code, where_to_point);
+  SerializeGeneric(obj, how_to_code, where_to_point);
 }


-void CodeSerializer::SerializeHeapObject(HeapObject* heap_object,
-                                         HowToCode how_to_code,
-                                         WhereToPoint where_to_point) {
+void CodeSerializer::SerializeGeneric(HeapObject* heap_object,
+                                      HowToCode how_to_code,
+                                      WhereToPoint where_to_point) {
   if (FLAG_serializer_trace_level > 0) {
     PrintF(" Encoding heap object: ");
     heap_object->ShortPrint();
@@ -2166,7 +2162,7 @@
     PrintF(" %s has no special handling\n", Code::Kind2String(ic->kind()));
   }
   DCHECK(ic->kind() == Code::LOAD_IC || ic->kind() == Code::STORE_IC);
-  SerializeHeapObject(ic, how_to_code, where_to_point);
+  SerializeGeneric(ic, how_to_code, where_to_point);
 }


@@ -2253,7 +2249,7 @@


SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
-    : owns_script_data_(true) {
+    : script_data_(NULL), owns_script_data_(true) {
   DisallowHeapAllocation no_gc;
   List<uint32_t>* stub_keys = cs->stub_keys();

=======================================
--- /branches/bleeding_edge/src/serialize.h     Thu Oct 23 08:25:42 2014 UTC
+++ /branches/bleeding_edge/src/serialize.h     Thu Oct 23 08:43:17 2014 UTC
@@ -139,6 +139,135 @@
 };


+class AddressMapBase {
+ protected:
+  static void SetValue(HashMap::Entry* entry, uint32_t v) {
+    entry->value = reinterpret_cast<void*>(v);
+  }
+
+  static uint32_t GetValue(HashMap::Entry* entry) {
+    return reinterpret_cast<uint32_t>(entry->value);
+  }
+
+  static HashMap::Entry* LookupEntry(HashMap* map, HeapObject* obj,
+                                     bool insert) {
+    return map->Lookup(Key(obj), Hash(obj), insert);
+  }
+
+ private:
+  static uint32_t Hash(HeapObject* obj) {
+ return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address()));
+  }
+
+  static void* Key(HeapObject* obj) {
+    return reinterpret_cast<void*>(obj->address());
+  }
+};
+
+
+class RootIndexMap : public AddressMapBase {
+ public:
+  explicit RootIndexMap(Isolate* isolate);
+
+  static const int kInvalidRootIndex = -1;
+  int Lookup(HeapObject* obj) {
+    HashMap::Entry* entry = LookupEntry(map_, obj, false);
+    if (entry) return GetValue(entry);
+    return kInvalidRootIndex;
+  }
+
+ private:
+  HashMap* map_;
+
+  DISALLOW_COPY_AND_ASSIGN(RootIndexMap);
+};
+
+
+class BackReference {
+ public:
+  explicit BackReference(uint32_t bitfield) : bitfield_(bitfield) {}
+
+  BackReference(AllocationSpace space, uint32_t chunk_index,
+                uint32_t chunk_offset) {
+    DCHECK(IsAligned(chunk_offset, kObjectAlignment));
+ bitfield_ = SpaceBits::encode(space) | ChunkIndexBits::encode(chunk_index) | + ChunkOffsetBits::encode(chunk_offset >> kObjectAlignmentBits);
+  }
+
+  BackReference() : bitfield_(kInvalidValue) {}
+
+  bool is_valid() const { return bitfield_ != kInvalidValue; }
+
+  AllocationSpace space() const {
+    DCHECK(is_valid());
+    return SpaceBits::decode(bitfield_);
+  }
+
+  uint32_t chunk_offset() const {
+    DCHECK(is_valid());
+    return ChunkOffsetBits::decode(bitfield_) << kObjectAlignmentBits;
+  }
+
+  uint32_t chunk_index() const {
+    DCHECK(is_valid());
+    return ChunkIndexBits::decode(bitfield_);
+  }
+
+  uint32_t reference() const {
+    DCHECK(is_valid());
+    return bitfield_ & (ChunkOffsetBits::kMask | ChunkIndexBits::kMask);
+  }
+
+  uint32_t bitfield() const { return bitfield_; }
+
+ private:
+  static const uint32_t kInvalidValue = 0xFFFFFFFF;
+  static const int kChunkOffsetSize = kPageSizeBits - kObjectAlignmentBits;
+  static const int kChunkIndexSize = 32 - kChunkOffsetSize - kSpaceTagSize;
+
+ public:
+  static const int kMaxChunkIndex = (1 << kChunkIndexSize) - 1;
+
+ private:
+ class ChunkOffsetBits : public BitField<uint32_t, 0, kChunkOffsetSize> {};
+  class ChunkIndexBits
+ : public BitField<uint32_t, ChunkOffsetBits::kNext, kChunkIndexSize> {};
+  class SpaceBits
+ : public BitField<AllocationSpace, ChunkIndexBits::kNext, kSpaceTagSize> {
+  };
+
+  uint32_t bitfield_;
+};
+
+
+// Mapping objects to their location after deserialization.
+// This is used during building, but not at runtime by V8.
+class BackReferenceMap : public AddressMapBase {
+ public:
+  BackReferenceMap()
+      : no_allocation_(), map_(new HashMap(HashMap::PointersMatch)) {}
+
+  ~BackReferenceMap() { delete map_; }
+
+  BackReference Lookup(HeapObject* obj) {
+    HashMap::Entry* entry = LookupEntry(map_, obj, false);
+    return entry ? BackReference(GetValue(entry)) : BackReference();
+  }
+
+  void Add(HeapObject* obj, BackReference b) {
+    DCHECK(b.is_valid());
+    DCHECK_EQ(NULL, LookupEntry(map_, obj, false));
+    HashMap::Entry* entry = LookupEntry(map_, obj, true);
+    SetValue(entry, b.bitfield());
+  }
+
+ private:
+  DisallowHeapAllocation no_allocation_;
+  HashMap* map_;
+  DISALLOW_COPY_AND_ASSIGN(BackReferenceMap);
+};
+
+
// The Serializer/Deserializer class is a common superclass for Serializer and
 // Deserializer which is used to store common constants and methods used by
 // both.
@@ -152,11 +281,6 @@
   static const int kNumberOfPreallocatedSpaces = LO_SPACE;
   static const int kNumberOfSpaces = INVALID_SPACE;

-  // To encode object for back-references.
-  class OffsetBits : public BitField<uint32_t, 0, kPageSizeBits> {};
-  class ChunkIndexBits
-      : public BitField<uint32_t, kPageSizeBits, 32 - kPageSizeBits> {};
-
  protected:
   // Where the pointed-to object can be found:
   enum Where {
@@ -312,13 +436,13 @@
       uint32_t index = source_->GetInt();
       return deserialized_large_objects_[index];
     } else {
-      uint32_t allocation = source_->GetInt() << kObjectAlignmentBits;
+      BackReference back_reference(source_->GetInt());
       DCHECK(space < kNumberOfPreallocatedSpaces);
-      uint32_t chunk_index = ChunkIndexBits::decode(allocation);
-      uint32_t offset = OffsetBits::decode(allocation);
+      uint32_t chunk_index = back_reference.chunk_index();
       DCHECK_LE(chunk_index, current_chunk_[space]);
+      uint32_t chunk_offset = back_reference.chunk_offset();
return HeapObject::FromAddress(reservations_[space][chunk_index].start +
-                                     offset);
+                                     chunk_offset);
     }
   }

@@ -345,54 +469,6 @@
 };


-// Mapping objects to their location after deserialization.
-// This is used during building, but not at runtime by V8.
-class SerializationAddressMapper {
- public:
-  SerializationAddressMapper()
-      : no_allocation_(),
-        serialization_map_(new HashMap(HashMap::PointersMatch)) { }
-
-  ~SerializationAddressMapper() {
-    delete serialization_map_;
-  }
-
-  bool IsMapped(HeapObject* obj) {
-    return serialization_map_->Lookup(Key(obj), Hash(obj), false) != NULL;
-  }
-
-  int MappedTo(HeapObject* obj) {
-    DCHECK(IsMapped(obj));
-    return static_cast<int>(reinterpret_cast<intptr_t>(
-        serialization_map_->Lookup(Key(obj), Hash(obj), false)->value));
-  }
-
-  void AddMapping(HeapObject* obj, int to) {
-    DCHECK(!IsMapped(obj));
-    HashMap::Entry* entry =
-        serialization_map_->Lookup(Key(obj), Hash(obj), true);
-    entry->value = Value(to);
-  }
-
- private:
-  static uint32_t Hash(HeapObject* obj) {
- return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address()));
-  }
-
-  static void* Key(HeapObject* obj) {
-    return reinterpret_cast<void*>(obj->address());
-  }
-
-  static void* Value(int v) {
-    return reinterpret_cast<void*>(v);
-  }
-
-  DisallowHeapAllocation no_allocation_;
-  HashMap* serialization_map_;
-  DISALLOW_COPY_AND_ASSIGN(SerializationAddressMapper);
-};
-
-
 class CodeAddressMap;

 // There can be only one serializer per V8 process.
@@ -400,7 +476,7 @@
  public:
   Serializer(Isolate* isolate, SnapshotByteSink* sink);
   ~Serializer();
-  void VisitPointers(Object** start, Object** end);
+  virtual void VisitPointers(Object** start, Object** end) OVERRIDE;

   void FinalizeAllocation();

@@ -412,23 +488,10 @@

   Isolate* isolate() const { return isolate_; }

-  SerializationAddressMapper* address_mapper() { return &address_mapper_; }
-  void PutRoot(int index,
-               HeapObject* object,
-               HowToCode how,
-               WhereToPoint where,
-               int skip);
+  BackReferenceMap* back_reference_map() { return &back_reference_map_; }
+  RootIndexMap* root_index_map() { return &root_index_map_; }

  protected:
-  static const int kInvalidRootIndex = -1;
-
-  int RootIndex(HeapObject* heap_object, HowToCode from);
-  intptr_t root_index_wave_front() { return root_index_wave_front_; }
-  void set_root_index_wave_front(intptr_t value) {
-    DCHECK(value >= root_index_wave_front_);
-    root_index_wave_front_ = value;
-  }
-
   class ObjectSerializer : public ObjectVisitor {
    public:
     ObjectSerializer(Serializer* serializer,
@@ -462,7 +525,7 @@
     }

    private:
-    void SerializePrologue(int space, int size, Map* map);
+    void SerializePrologue(AllocationSpace space, int size, Map* map);

     enum ReturnSkip { kCanReturnSkipInsteadOfSkipping, kIgnoringReturn };
// This function outputs or skips the raw data between the last pointer and
@@ -482,19 +545,20 @@
     bool code_has_been_output_;
   };

-  virtual void SerializeObject(Object* o,
-                               HowToCode how_to_code,
-                               WhereToPoint where_to_point,
-                               int skip) = 0;
-  void SerializeReferenceToPreviousObject(HeapObject* heap_object,
-                                          HowToCode how_to_code,
-                                          WhereToPoint where_to_point,
-                                          int skip);
+  virtual void SerializeObject(HeapObject* o, HowToCode how_to_code,
+                               WhereToPoint where_to_point, int skip) = 0;
+
+ void PutRoot(int index, HeapObject* object, HowToCode how, WhereToPoint where,
+               int skip);
+
+  void SerializeBackReference(BackReference back_reference,
+                              HowToCode how_to_code,
+                              WhereToPoint where_to_point, int skip);
   void InitializeAllocators();
   // This will return the space for an object.
-  static int SpaceOfObject(HeapObject* object);
-  uint32_t AllocateLargeObject(int size);
-  uint32_t Allocate(int space, int size);
+  static AllocationSpace SpaceOfObject(HeapObject* object);
+  BackReference AllocateLargeObject(int size);
+  BackReference Allocate(AllocationSpace space, int size);
   int EncodeExternalReference(Address addr) {
     return external_reference_encoder_->Encode(addr);
   }
@@ -517,8 +581,8 @@
   SnapshotByteSink* sink_;
   ExternalReferenceEncoder* external_reference_encoder_;

-  SerializationAddressMapper address_mapper_;
-  intptr_t root_index_wave_front_;
+  BackReferenceMap back_reference_map_;
+  RootIndexMap root_index_map_;
   void Pad();

   friend class ObjectSerializer;
@@ -543,16 +607,13 @@
                     SnapshotByteSink* sink)
     : Serializer(isolate, sink),
       startup_serializer_(startup_snapshot_serializer) {
-    set_root_index_wave_front(Heap::kStrongRootListLength);
     InitializeCodeAddressMap();
   }

   // Serialize the objects reachable from a single object pointer.
   void Serialize(Object** o);
-  virtual void SerializeObject(Object* o,
-                               HowToCode how_to_code,
-                               WhereToPoint where_to_point,
-                               int skip);
+  virtual void SerializeObject(HeapObject* o, HowToCode how_to_code,
+                               WhereToPoint where_to_point, int skip);

  private:
   int PartialSnapshotCacheIndex(HeapObject* o);
@@ -578,7 +639,7 @@
 class StartupSerializer : public Serializer {
  public:
   StartupSerializer(Isolate* isolate, SnapshotByteSink* sink)
-    : Serializer(isolate, sink) {
+      : Serializer(isolate, sink), root_index_wave_front_(0) {
     // Clear the cache of objects used by the partial snapshot.  After the
     // strong roots have been serialized we can create a partial snapshot
     // which will repopulate the cache with objects needed by that partial
@@ -586,15 +647,18 @@
     isolate->set_serialize_partial_snapshot_cache_length(0);
     InitializeCodeAddressMap();
   }
+
+ // The StartupSerializer has to serialize the root array, which is slightly
+  // different.
+  virtual void VisitPointers(Object** start, Object** end) OVERRIDE;
+
   // Serialize the current state of the heap.  The order is:
   // 1) Strong references.
   // 2) Partial snapshot cache.
   // 3) Weak references (e.g. the string table).
   virtual void SerializeStrongReferences();
-  virtual void SerializeObject(Object* o,
-                               HowToCode how_to_code,
-                               WhereToPoint where_to_point,
-                               int skip);
+  virtual void SerializeObject(HeapObject* o, HowToCode how_to_code,
+                               WhereToPoint where_to_point, int skip);
   void SerializeWeakReferences();
   void Serialize() {
     SerializeStrongReferences();
@@ -603,6 +667,7 @@
   }

  private:
+  int root_index_wave_front_;
   DISALLOW_COPY_AND_ASSIGN(StartupSerializer);
 };

@@ -634,11 +699,10 @@
         source_(source),
         main_code_(main_code),
         num_internalized_strings_(0) {
-    set_root_index_wave_front(Heap::kStrongRootListLength);
     InitializeCodeAddressMap();
   }

-  virtual void SerializeObject(Object* o, HowToCode how_to_code,
+  virtual void SerializeObject(HeapObject* o, HowToCode how_to_code,
                                WhereToPoint where_to_point, int skip);

   void SerializeBuiltin(int builtin_index, HowToCode how_to_code,
@@ -649,8 +713,8 @@
                          WhereToPoint where_to_point);
   void SerializeSourceObject(HowToCode how_to_code,
                              WhereToPoint where_to_point);
-  void SerializeHeapObject(HeapObject* heap_object, HowToCode how_to_code,
-                           WhereToPoint where_to_point);
+  void SerializeGeneric(HeapObject* heap_object, HowToCode how_to_code,
+                        WhereToPoint where_to_point);
   int AddCodeStubKey(uint32_t stub_key);

   DisallowHeapAllocation no_gc_;

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to