Fix missing write barrier in deserialization. Issue 1783.
authorerik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 21 Oct 2011 15:20:53 +0000 (15:20 +0000)
committererik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 21 Oct 2011 15:20:53 +0000 (15:20 +0000)
Review URL: http://codereview.chromium.org/8352045

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

src/heap.h
src/serialize.cc

index e9b5ffa..7c0b0ea 100644 (file)
@@ -68,6 +68,7 @@ inline Heap* _inline_get_heap_();
   V(Map, shared_function_info_map, SharedFunctionInfoMap)                      \
   V(Map, meta_map, MetaMap)                                                    \
   V(Map, ascii_symbol_map, AsciiSymbolMap)                                     \
+  V(Map, ascii_string_map, AsciiStringMap)                                     \
   V(Map, heap_number_map, HeapNumberMap)                                       \
   V(Map, global_context_map, GlobalContextMap)                                 \
   V(Map, fixed_array_map, FixedArrayMap)                                       \
@@ -85,6 +86,9 @@ inline Heap* _inline_get_heap_();
   V(Smi, stack_limit, StackLimit)                                              \
   V(Oddball, frame_alignment_marker, FrameAlignmentMarker)                     \
   V(Oddball, arguments_marker, ArgumentsMarker)                                \
+  /* The first 32 roots above this line should be boring from a GC point of */ \
+  /* view.  This means they are never in new space and never on a page that */ \
+  /* is being compacted.                                                    */ \
   V(FixedArray, number_string_cache, NumberStringCache)                        \
   V(Object, instanceof_cache_function, InstanceofCacheFunction)                \
   V(Object, instanceof_cache_map, InstanceofCacheMap)                          \
@@ -93,7 +97,6 @@ inline Heap* _inline_get_heap_();
   V(FixedArray, string_split_cache, StringSplitCache)                          \
   V(Object, termination_exception, TerminationException)                       \
   V(Map, string_map, StringMap)                                                \
-  V(Map, ascii_string_map, AsciiStringMap)                                     \
   V(Map, symbol_map, SymbolMap)                                                \
   V(Map, cons_string_map, ConsStringMap)                                       \
   V(Map, cons_ascii_string_map, ConsAsciiStringMap)                            \
@@ -1419,6 +1422,9 @@ class Heap {
   // around a GC).
   inline void CompletelyClearInstanceofCache();
 
+  // The roots that have an index less than this are always in old space.
+  static const int kOldSpaceRoots = 0x20;
+
  private:
   Heap();
 
@@ -1475,6 +1481,9 @@ class Heap {
 
 #define ROOT_ACCESSOR(type, name, camel_name)                                  \
   inline void set_##name(type* value) {                                        \
+    /* The deserializer makes use of the fact that these common roots are */   \
+    /* never in new space and never on a page that is being compacted.    */   \
+    ASSERT(k##camel_name##RootIndex >= kOldSpaceRoots || !InNewSpace(value));  \
     roots_[k##camel_name##RootIndex] = value;                                  \
   }
   ROOT_LIST(ROOT_ACCESSOR)
index 09f54c6..a48e119 100644 (file)
@@ -787,9 +787,19 @@ void Deserializer::ReadChunk(Object** current,
             ASSIGN_DEST_SPACE(space_number)                                    \
             ReadObject(space_number, dest_space, &new_object);                 \
           } else if (where == kRootArray) {                                    \
+            if (source_space != CELL_SPACE &&                                  \
+                source_space != CODE_SPACE &&                                  \
+                source_space != OLD_DATA_SPACE) {                              \
+              emit_write_barrier = true;                                       \
+            }                                                                  \
             int root_id = source_->GetInt();                                   \
             new_object = isolate->heap()->roots_array_start()[root_id];        \
           } else if (where == kPartialSnapshotCache) {                         \
+            if (source_space != CELL_SPACE &&                                  \
+                source_space != CODE_SPACE &&                                  \
+                source_space != OLD_DATA_SPACE) {                              \
+              emit_write_barrier = true;                                       \
+            }                                                                  \
             int cache_index = source_->GetInt();                               \
             new_object = isolate->serialize_partial_snapshot_cache()           \
                 [cache_index];                                                 \
@@ -924,24 +934,30 @@ void Deserializer::ReadChunk(Object** current,
       SIXTEEN_CASES(kRootArrayLowConstants)
       SIXTEEN_CASES(kRootArrayHighConstants) {
         int root_id = RootArrayConstantFromByteCode(data);
-        *current++ = isolate->heap()->roots_array_start()[root_id];
+        Object* object = isolate->heap()->roots_array_start()[root_id];
+        ASSERT(!isolate->heap()->InNewSpace(object));
+        *current++ = object;
         break;
       }
 
       case kRepeat: {
         int repeats = source_->GetInt();
         Object* object = current[-1];
+        ASSERT(!isolate->heap()->InNewSpace(object));
         for (int i = 0; i < repeats; i++) current[i] = object;
         current += repeats;
         break;
       }
 
+      STATIC_ASSERT(kRootArrayNumberOfConstantEncodings ==
+                    Heap::kOldSpaceRoots);
       STATIC_ASSERT(kMaxRepeats == 12);
       FOUR_CASES(kConstantRepeat)
       FOUR_CASES(kConstantRepeat + 4)
       FOUR_CASES(kConstantRepeat + 8) {
         int repeats = RepeatsForCode(data);
         Object* object = current[-1];
+        ASSERT(!isolate->heap()->InNewSpace(object));
         for (int i = 0; i < repeats; i++) current[i] = object;
         current += repeats;
         break;
@@ -1430,11 +1446,18 @@ void Serializer::ObjectSerializer::VisitPointers(Object** start,
     if (current < end) OutputRawData(reinterpret_cast<Address>(current));
 
     while (current < end && !(*current)->IsSmi()) {
+      HeapObject* current_contents = HeapObject::cast(*current);
+      int root_index = serializer_->RootIndex(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 &&
-          current[0] == current[-1] &&
-          !HEAP->InNewSpace(*current)) {
+          root_index != kInvalidRootIndex &&
+          root_index < kRootArrayNumberOfConstantEncodings &&
+          current_contents == current[-1]) {
+        ASSERT(!HEAP->InNewSpace(current_contents));
         int repeat_count = 1;
-        while (current < end - 1 && current[repeat_count] == current[0]) {
+        while (current < end - 1 && current[repeat_count] == current_contents) {
           repeat_count++;
         }
         current += repeat_count;
@@ -1446,7 +1469,7 @@ void Serializer::ObjectSerializer::VisitPointers(Object** start,
           sink_->Put(CodeForRepeats(repeat_count), "SerializeRepeats");
         }
       } else {
-        serializer_->SerializeObject(*current, kPlain, kStartOfObject);
+        serializer_->SerializeObject(current_contents, kPlain, kStartOfObject);
         bytes_processed_so_far_ += kPointerSize;
         current++;
       }