Revision: 9722
Author:   [email protected]
Date:     Thu Oct 20 05:27:10 2011
Log:      Shave 39% from snapshot size.
Review URL: http://codereview.chromium.org/8344079
http://code.google.com/p/v8/source/detail?r=9722

Modified:
 /branches/bleeding_edge/src/arm/builtins-arm.cc
 /branches/bleeding_edge/src/arm/deoptimizer-arm.cc
 /branches/bleeding_edge/src/assembler.cc
 /branches/bleeding_edge/src/assembler.h
 /branches/bleeding_edge/src/heap.h
 /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
 /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc
 /branches/bleeding_edge/src/mips/builtins-mips.cc
 /branches/bleeding_edge/src/mksnapshot.cc
 /branches/bleeding_edge/src/serialize.cc
 /branches/bleeding_edge/src/serialize.h
 /branches/bleeding_edge/src/x64/macro-assembler-x64.cc
 /branches/bleeding_edge/src/x64/macro-assembler-x64.h
 /branches/bleeding_edge/test/cctest/test-serialize.cc

=======================================
--- /branches/bleeding_edge/src/arm/builtins-arm.cc     Tue Sep 20 03:06:23 2011
+++ /branches/bleeding_edge/src/arm/builtins-arm.cc     Thu Oct 20 05:27:10 2011
@@ -1027,9 +1027,9 @@
     __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));

     // Set up the roots register.
-    ExternalReference roots_address =
-        ExternalReference::roots_address(masm->isolate());
-    __ mov(r10, Operand(roots_address));
+    ExternalReference roots_array_start =
+        ExternalReference::roots_array_start(masm->isolate());
+    __ mov(r10, Operand(roots_array_start));

     // Push the function and the receiver onto the stack.
     __ push(r1);
=======================================
--- /branches/bleeding_edge/src/arm/deoptimizer-arm.cc Tue Oct 18 08:07:42 2011 +++ /branches/bleeding_edge/src/arm/deoptimizer-arm.cc Thu Oct 20 05:27:10 2011
@@ -756,8 +756,9 @@
   __ pop(ip);  // remove lr

   // Set up the roots register.
- ExternalReference roots_address = ExternalReference::roots_address(isolate);
-  __ mov(r10, Operand(roots_address));
+  ExternalReference roots_array_start =
+      ExternalReference::roots_array_start(isolate);
+  __ mov(r10, Operand(roots_array_start));

   __ pop(ip);  // remove pc
   __ pop(r7);  // get continuation, leave pc on stack
=======================================
--- /branches/bleeding_edge/src/assembler.cc    Thu Oct 20 03:26:45 2011
+++ /branches/bleeding_edge/src/assembler.cc    Thu Oct 20 05:27:10 2011
@@ -834,8 +834,8 @@
 }


-ExternalReference ExternalReference::roots_address(Isolate* isolate) {
-  return ExternalReference(isolate->heap()->roots_address());
+ExternalReference ExternalReference::roots_array_start(Isolate* isolate) {
+  return ExternalReference(isolate->heap()->roots_array_start());
 }


=======================================
--- /branches/bleeding_edge/src/assembler.h     Thu Oct 20 03:26:45 2011
+++ /branches/bleeding_edge/src/assembler.h     Thu Oct 20 05:27:10 2011
@@ -593,8 +593,8 @@
   static ExternalReference keyed_lookup_cache_keys(Isolate* isolate);
static ExternalReference keyed_lookup_cache_field_offsets(Isolate* isolate);

-  // Static variable Heap::roots_address()
-  static ExternalReference roots_address(Isolate* isolate);
+  // Static variable Heap::roots_array_start()
+  static ExternalReference roots_array_start(Isolate* isolate);

   // Static variable StackGuard::address_of_jslimit()
   static ExternalReference address_of_stack_limit(Isolate* isolate);
=======================================
--- /branches/bleeding_edge/src/heap.h  Thu Oct 20 04:40:16 2011
+++ /branches/bleeding_edge/src/heap.h  Thu Oct 20 05:27:10 2011
@@ -64,18 +64,27 @@
V(Oddball, null_value, NullValue) \ V(Oddball, true_value, TrueValue) \ V(Oddball, false_value, FalseValue) \ - V(Oddball, arguments_marker, ArgumentsMarker) \ - V(Oddball, frame_alignment_marker, FrameAlignmentMarker) \ + V(Map, global_property_cell_map, GlobalPropertyCellMap) \ + V(Map, shared_function_info_map, SharedFunctionInfoMap) \ + V(Map, meta_map, MetaMap) \ + V(Map, ascii_symbol_map, AsciiSymbolMap) \ V(Map, heap_number_map, HeapNumberMap) \ V(Map, global_context_map, GlobalContextMap) \ V(Map, fixed_array_map, FixedArrayMap) \ + V(Map, code_map, CodeMap) \ V(Map, serialized_scope_info_map, SerializedScopeInfoMap) \ V(Map, fixed_cow_array_map, FixedCOWArrayMap) \ V(Map, fixed_double_array_map, FixedDoubleArrayMap) \ V(Object, no_interceptor_result_sentinel, NoInterceptorResultSentinel) \ - V(Map, meta_map, MetaMap) \ V(Map, hash_table_map, HashTableMap) \ + V(FixedArray, empty_fixed_array, EmptyFixedArray) \ + V(ByteArray, empty_byte_array, EmptyByteArray) \ + V(FixedDoubleArray, empty_fixed_double_array, EmptyFixedDoubleArray) \ + V(String, empty_string, EmptyString) \ + V(DescriptorArray, empty_descriptor_array, EmptyDescriptorArray) \ V(Smi, stack_limit, StackLimit) \ + V(Oddball, frame_alignment_marker, FrameAlignmentMarker) \ + V(Oddball, arguments_marker, ArgumentsMarker) \ V(FixedArray, number_string_cache, NumberStringCache) \ V(Object, instanceof_cache_function, InstanceofCacheFunction) \ V(Object, instanceof_cache_map, InstanceofCacheMap) \
@@ -83,11 +92,6 @@
V(FixedArray, single_character_string_cache, SingleCharacterStringCache) \ V(FixedArray, string_split_cache, StringSplitCache) \ V(Object, termination_exception, TerminationException) \ - V(FixedArray, empty_fixed_array, EmptyFixedArray) \ - V(ByteArray, empty_byte_array, EmptyByteArray) \ - V(FixedDoubleArray, empty_fixed_double_array, EmptyFixedDoubleArray) \ - V(String, empty_string, EmptyString) \ - V(DescriptorArray, empty_descriptor_array, EmptyDescriptorArray) \ V(Map, string_map, StringMap) \ V(Map, ascii_string_map, AsciiStringMap) \ V(Map, symbol_map, SymbolMap) \
@@ -95,7 +99,6 @@
V(Map, cons_ascii_string_map, ConsAsciiStringMap) \ V(Map, sliced_string_map, SlicedStringMap) \ V(Map, sliced_ascii_string_map, SlicedAsciiStringMap) \ - V(Map, ascii_symbol_map, AsciiSymbolMap) \ V(Map, cons_symbol_map, ConsSymbolMap) \ V(Map, cons_ascii_symbol_map, ConsAsciiSymbolMap) \ V(Map, external_symbol_map, ExternalSymbolMap) \
@@ -120,10 +123,7 @@
V(Map, catch_context_map, CatchContextMap) \ V(Map, with_context_map, WithContextMap) \ V(Map, block_context_map, BlockContextMap) \ - V(Map, code_map, CodeMap) \ V(Map, oddball_map, OddballMap) \ - V(Map, global_property_cell_map, GlobalPropertyCellMap) \ - V(Map, shared_function_info_map, SharedFunctionInfoMap) \ V(Map, message_object_map, JSMessageObjectMap) \ V(Map, foreign_map, ForeignMap) \ V(HeapNumber, nan_value, NanValue) \
@@ -1097,7 +1097,7 @@
   inline void SetLastScriptId(Object* last_script_id);

   // Generated code can embed this address to get access to the roots.
-  Object** roots_address() { return roots_; }
+  Object** roots_array_start() { return roots_; }

   Address* store_buffer_top_address() {
     return reinterpret_cast<Address*>(&roots_[kStoreBufferTopRootIndex]);
@@ -1474,7 +1474,7 @@
   int unflattened_strings_length_;

#define ROOT_ACCESSOR(type, name, camel_name) \
-  inline void set_##name(type* value) {                                 \
+ inline void set_##name(type* value) { \ roots_[k##camel_name##RootIndex] = value; \
   }
   ROOT_LIST(ROOT_ACCESSOR)
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Thu Oct 20 02:38:24 2011 +++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Thu Oct 20 05:27:10 2011
@@ -3882,11 +3882,11 @@
   Register scratch = scratch2;

   // Load the number string cache.
-  ExternalReference roots_address =
-      ExternalReference::roots_address(masm->isolate());
+  ExternalReference roots_array_start =
+      ExternalReference::roots_array_start(masm->isolate());
   __ mov(scratch, Immediate(Heap::kNumberStringCacheRootIndex));
   __ mov(number_string_cache,
-         Operand::StaticArray(scratch, times_pointer_size, roots_address));
+ Operand::StaticArray(scratch, times_pointer_size, roots_array_start));
   // Make the hash mask from the length of the number string cache. It
   // contains two elements (number and string) for each cache entry.
__ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset));
@@ -4854,8 +4854,8 @@
static const int8_t kCmpEdiImmediateByte2 = BitCast<int8_t, uint8_t>(0xff); static const int8_t kMovEaxImmediateByte = BitCast<int8_t, uint8_t>(0xb8);

-  ExternalReference roots_address =
-      ExternalReference::roots_address(masm->isolate());
+  ExternalReference roots_array_start =
+      ExternalReference::roots_array_start(masm->isolate());

   ASSERT_EQ(object.code(), InstanceofStub::left().code());
   ASSERT_EQ(function.code(), InstanceofStub::right().code());
@@ -4877,16 +4877,17 @@
     // Look up the function and the map in the instanceof cache.
     Label miss;
     __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex));
-    __ cmp(function,
- Operand::StaticArray(scratch, times_pointer_size, roots_address));
+    __ cmp(function, Operand::StaticArray(scratch,
+                                          times_pointer_size,
+                                          roots_array_start));
     __ j(not_equal, &miss, Label::kNear);
     __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex));
     __ cmp(map, Operand::StaticArray(
-        scratch, times_pointer_size, roots_address));
+        scratch, times_pointer_size, roots_array_start));
     __ j(not_equal, &miss, Label::kNear);
     __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
     __ mov(eax, Operand::StaticArray(
-        scratch, times_pointer_size, roots_address));
+        scratch, times_pointer_size, roots_array_start));
     __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
     __ bind(&miss);
   }
@@ -4902,9 +4903,10 @@
// map and function. The cached answer will be set when it is known below.
   if (!HasCallSiteInlineCheck()) {
   __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex));
- __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address), map); + __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start),
+         map);
   __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex));
-  __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address),
+ __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start),
          function);
   } else {
// The constants for the code patching are based on no push instructions
@@ -4941,7 +4943,7 @@
     __ Set(eax, Immediate(0));
     __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
     __ mov(Operand::StaticArray(scratch,
-                                times_pointer_size, roots_address), eax);
+ times_pointer_size, roots_array_start), eax);
   } else {
     // Get return address and delta to inlined map check.
     __ mov(eax, factory->true_value());
@@ -4963,7 +4965,7 @@
     __ Set(eax, Immediate(Smi::FromInt(1)));
     __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
     __ mov(Operand::StaticArray(
-        scratch, times_pointer_size, roots_address), eax);
+        scratch, times_pointer_size, roots_array_start), eax);
   } else {
     // Get return address and delta to inlined map check.
     __ mov(eax, factory->false_value());
@@ -5752,11 +5754,11 @@

   // Load the symbol table.
   Register symbol_table = c2;
-  ExternalReference roots_address =
-      ExternalReference::roots_address(masm->isolate());
+  ExternalReference roots_array_start =
+      ExternalReference::roots_array_start(masm->isolate());
   __ mov(scratch, Immediate(Heap::kSymbolTableRootIndex));
   __ mov(symbol_table,
-         Operand::StaticArray(scratch, times_pointer_size, roots_address));
+ Operand::StaticArray(scratch, times_pointer_size, roots_array_start));

   // Calculate capacity mask from the symbol table capacity.
   Register mask = scratch2;
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Mon Oct 17 05:44:16 2011 +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Thu Oct 20 05:27:10 2011
@@ -352,7 +352,7 @@

void MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) {
   // see ROOT_ACCESSOR macro in factory.h
-  Handle<Object> value(&isolate()->heap()->roots_address()[index]);
+  Handle<Object> value(&isolate()->heap()->roots_array_start()[index]);
   cmp(with, value);
 }

=======================================
--- /branches/bleeding_edge/src/mips/builtins-mips.cc Thu Oct 13 01:00:10 2011 +++ /branches/bleeding_edge/src/mips/builtins-mips.cc Thu Oct 20 05:27:10 2011
@@ -1053,9 +1053,9 @@
     __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));

     // Set up the roots register.
-    ExternalReference roots_address =
-        ExternalReference::roots_address(masm->isolate());
-    __ li(s6, Operand(roots_address));
+    ExternalReference roots_array_start =
+        ExternalReference::roots_array_start(masm->isolate());
+    __ li(s6, Operand(roots_array_start));

     // Push the function and the receiver onto the stack.
     __ Push(a1, a2);
=======================================
--- /branches/bleeding_edge/src/mksnapshot.cc   Mon Sep 19 11:36:47 2011
+++ /branches/bleeding_edge/src/mksnapshot.cc   Thu Oct 20 05:27:10 2011
@@ -312,7 +312,6 @@
   }
   // If we don't do this then we end up with a stray root pointing at the
   // context even after we have disposed of the context.
-  // TODO(gc): request full compaction?
   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
   i::Object* raw_context = *(v8::Utils::OpenHandle(*context));
   context.Dispose();
=======================================
--- /branches/bleeding_edge/src/serialize.cc    Tue Oct  4 02:07:50 2011
+++ /branches/bleeding_edge/src/serialize.cc    Thu Oct 20 05:27:10 2011
@@ -318,10 +318,10 @@


   // Miscellaneous
-  Add(ExternalReference::roots_address(isolate).address(),
+  Add(ExternalReference::roots_array_start(isolate).address(),
       UNCLASSIFIED,
       3,
-      "Heap::roots_address()");
+      "Heap::roots_array_start()");
   Add(ExternalReference::address_of_stack_limit(isolate).address(),
       UNCLASSIFIED,
       4,
@@ -784,7 +784,7 @@
ReadObject(space_number, dest_space, &new_object); \ } else if (where == kRootArray) { \ int root_id = source_->GetInt(); \ - new_object = isolate->heap()->roots_address()[root_id]; \ + new_object = isolate->heap()->roots_array_start()[root_id]; \ } else if (where == kPartialSnapshotCache) { \ int cache_index = source_->GetInt(); \ new_object = isolate->serialize_partial_snapshot_cache() \
@@ -883,11 +883,17 @@
CASE_STATEMENT(where, how, within, kLargeCode) \
   CASE_BODY(where, how, within, kLargeCode, kUnknownOffsetFromStart)

-#define EMIT_COMMON_REFERENCE_PATTERNS(pseudo_space_number, \ - space_number, \ - offset_from_start) \ - CASE_STATEMENT(kFromStart, kPlain, kStartOfObject, pseudo_space_number) \ - CASE_BODY(kFromStart, kPlain, kStartOfObject, space_number, offset_from_start)
+#define FOUR_CASES(byte_code)             \
+  case byte_code:                         \
+  case byte_code + 1:                     \
+  case byte_code + 2:                     \
+  case byte_code + 3:
+
+#define SIXTEEN_CASES(byte_code)          \
+  FOUR_CASES(byte_code)                   \
+  FOUR_CASES(byte_code + 4)               \
+  FOUR_CASES(byte_code + 8)               \
+  FOUR_CASES(byte_code + 12)

// We generate 15 cases and bodies that process special tags that combine
       // the raw data tag and the length into one byte.
@@ -910,6 +916,32 @@
         current = reinterpret_cast<Object**>(raw_data_out + size);
         break;
       }
+
+      SIXTEEN_CASES(kRootArrayLowConstants)
+      SIXTEEN_CASES(kRootArrayHighConstants) {
+        int root_id = RootArrayConstantFromByteCode(data);
+        *current++ = isolate->heap()->roots_array_start()[root_id];
+        break;
+      }
+
+      case kRepeat: {
+        int repeats = source_->GetInt();
+        Object* object = current[-1];
+        for (int i = 0; i < repeats; i++) current[i] = object;
+        current += repeats;
+        break;
+      }
+
+      STATIC_ASSERT(kMaxRepeats == 12);
+      FOUR_CASES(kConstantRepeat)
+      FOUR_CASES(kConstantRepeat + 4)
+      FOUR_CASES(kConstantRepeat + 8) {
+        int repeats = RepeatsForCode(data);
+        Object* object = current[-1];
+        for (int i = 0; i < repeats; i++) current[i] = object;
+        current += repeats;
+        break;
+      }

       // Deserialize a new object and write a pointer to it to the current
       // object.
@@ -936,9 +968,6 @@
// start and write a pointer to its first instruction to the current code
       // object.
       ALL_SPACES(kFromStart, kFromCode, kFirstInstruction)
- // Find an already deserialized object at one of the predetermined popular - // offsets from the start and write a pointer to it in the current object.
-      COMMON_REFERENCE_PATTERNS(EMIT_COMMON_REFERENCE_PATTERNS)
       // Find an object in the roots array and write a pointer to it to the
       // current object.
       CASE_STATEMENT(kRootArray, kPlain, kStartOfObject, 0)
@@ -980,7 +1009,6 @@
 #undef CASE_BODY
 #undef ONE_PER_SPACE
 #undef ALL_SPACES
-#undef EMIT_COMMON_REFERENCE_PATTERNS
 #undef ASSIGN_DEST_SPACE

       case kNewPage: {
@@ -1067,7 +1095,8 @@
     : sink_(sink),
       current_root_index_(0),
       external_reference_encoder_(new ExternalReferenceEncoder),
-      large_object_total_(0) {
+      large_object_total_(0),
+      root_index_wave_front_(0) {
// The serializer is meant to be used only to generate initial heap images
   // from a context in which there is only one isolate.
   ASSERT(Isolate::Current()->IsDefaultIsolate());
@@ -1124,6 +1153,9 @@
   Isolate* isolate = Isolate::Current();

   for (Object** current = start; current < end; current++) {
+    if (start == isolate->heap()->roots_array_start()) {
+ root_index_wave_front_ = Max(root_index_wave_front_, current - start);
+    }
     if (reinterpret_cast<Address>(current) ==
         isolate->heap()->store_buffer()->TopAddress()) {
       sink_->Put(kSkip, "Skip");
@@ -1191,10 +1223,12 @@
 }


-int PartialSerializer::RootIndex(HeapObject* heap_object) {
-  for (int i = 0; i < Heap::kRootListLength; i++) {
-    Object* root = HEAP->roots_address()[i];
-    if (root == heap_object) return i;
+int Serializer::RootIndex(HeapObject* heap_object) {
+  Heap* heap = 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;
 }
@@ -1230,18 +1264,8 @@
   // all objects) then we should shift out the bits that are always 0.
   if (!SpaceIsLarge(space)) address >>= kObjectAlignmentBits;
   if (from_start) {
-#define COMMON_REFS_CASE(pseudo_space, actual_space, offset) \ - if (space == actual_space && address == offset && \ - how_to_code == kPlain && where_to_point == kStartOfObject) { \ - sink_->Put(kFromStart + how_to_code + where_to_point + \ - pseudo_space, "RefSer"); \
-    } else  /* NOLINT */
-    COMMON_REFERENCE_PATTERNS(COMMON_REFS_CASE)
-#undef COMMON_REFS_CASE
-    {  /* NOLINT */
- sink_->Put(kFromStart + how_to_code + where_to_point + space, "RefSer");
-      sink_->PutInt(address, "address");
-    }
+ sink_->Put(kFromStart + how_to_code + where_to_point + space, "RefSer");
+    sink_->PutInt(address, "address");
   } else {
sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRefSer");
     sink_->PutInt(address, "address");
@@ -1255,6 +1279,12 @@
     WhereToPoint where_to_point) {
   CHECK(o->IsHeapObject());
   HeapObject* heap_object = HeapObject::cast(o);
+
+  int root_index;
+  if ((root_index = RootIndex(heap_object)) != kInvalidRootIndex) {
+    PutRoot(root_index, heap_object, how_to_code, where_to_point);
+    return;
+  }

   if (address_mapper_.IsMapped(heap_object)) {
     int space = SpaceOfAlreadySerializedObject(heap_object);
@@ -1284,6 +1314,28 @@
   }
   HEAP->IterateWeakRoots(this, VISIT_ALL);
 }
+
+
+void Serializer::PutRoot(int root_index,
+                         HeapObject* object,
+                         SerializerDeserializer::HowToCode how_to_code,
+ SerializerDeserializer::WhereToPoint where_to_point) {
+  if (how_to_code == kPlain &&
+      where_to_point == kStartOfObject &&
+      root_index < kRootArrayNumberOfConstantEncodings &&
+      !HEAP->InNewSpace(object)) {
+    if (root_index < kRootArrayNumberOfLowConstantEncodings) {
+      sink_->Put(kRootArrayLowConstants + root_index, "RootLoConstant");
+    } else {
+      sink_->Put(kRootArrayHighConstants + root_index -
+                     kRootArrayNumberOfLowConstantEncodings,
+                 "RootHiConstant");
+    }
+  } else {
+ sink_->Put(kRootArray + how_to_code + where_to_point, "RootSerialization");
+    sink_->PutInt(root_index, "root_index");
+  }
+}


 void PartialSerializer::SerializeObject(
@@ -1295,8 +1347,7 @@

   int root_index;
   if ((root_index = RootIndex(heap_object)) != kInvalidRootIndex) {
- sink_->Put(kRootArray + how_to_code + where_to_point, "RootSerialization");
-    sink_->PutInt(root_index, "root_index");
+    PutRoot(root_index, heap_object, how_to_code, where_to_point);
     return;
   }

@@ -1374,9 +1425,26 @@
     if (current < end) OutputRawData(reinterpret_cast<Address>(current));

     while (current < end && !(*current)->IsSmi()) {
-      serializer_->SerializeObject(*current, kPlain, kStartOfObject);
-      bytes_processed_so_far_ += kPointerSize;
-      current++;
+      if (current != start &&
+          current[0] == current[-1] &&
+          !HEAP->InNewSpace(*current)) {
+        int repeat_count = 1;
+        while (current < end - 1 && current[repeat_count] == current[0]) {
+          repeat_count++;
+        }
+        current += repeat_count;
+        bytes_processed_so_far_ += repeat_count * kPointerSize;
+        if (repeat_count > kMaxRepeats) {
+          sink_->Put(kRepeat, "SerializeRepeats");
+          sink_->PutInt(repeat_count, "SerializeRepeats");
+        } else {
+          sink_->Put(CodeForRepeats(repeat_count), "SerializeRepeats");
+        }
+      } else {
+        serializer_->SerializeObject(*current, kPlain, kStartOfObject);
+        bytes_processed_so_far_ += kPointerSize;
+        current++;
+      }
     }
   }
 }
=======================================
--- /branches/bleeding_edge/src/serialize.h     Mon Sep 19 11:36:47 2011
+++ /branches/bleeding_edge/src/serialize.h     Thu Oct 20 05:27:10 2011
@@ -187,24 +187,6 @@
 };


-// It is very common to have a reference to objects at certain offsets in the
-// heap.  These offsets have been determined experimentally.  We code
-// references to such objects in a single byte that encodes the way the pointer -// is written (only plain pointers allowed), the space number and the offset. -// This only works for objects in the first page of a space. Don't use this for
-// things in newspace since it bypasses the write barrier.
-
-static const int k64 = (sizeof(uintptr_t) - 4) / 4;
-
-#define COMMON_REFERENCE_PATTERNS(f)                               \
-  f(kNumberOfSpaces, 2, (11 - k64))                                \
-  f((kNumberOfSpaces + 1), 2, 0)                                   \
-  f((kNumberOfSpaces + 2), 2, (142 - 16 * k64))                    \
-  f((kNumberOfSpaces + 3), 2, (74 - 15 * k64))                     \
-  f((kNumberOfSpaces + 4), 2, 5)                                   \
-  f((kNumberOfSpaces + 5), 1, 135)                                 \
-  f((kNumberOfSpaces + 6), 2, (228 - 39 * k64))
-
 #define COMMON_RAW_LENGTHS(f)        \
   f(1, 1)  \
   f(2, 2)  \
@@ -242,7 +224,7 @@
     // 0xd-0xf                         Free.
kBackref = 0x10, // Object is described relative to end.
     // 0x11-0x18                       One per space.
-    // 0x19-0x1f                       Common backref offsets.
+    // 0x19-0x1f                       Free.
kFromStart = 0x20, // Object is described relative to start.
     // 0x21-0x28                       One per space.
     // 0x29-0x2f                       Free.
@@ -279,9 +261,29 @@
   // is referred to from external strings in the snapshot.
   static const int kNativesStringResource = 0x71;
   static const int kNewPage = 0x72;
-  // 0x73-0x7f                            Free.
-  // 0xb0-0xbf                            Free.
-  // 0xf0-0xff                            Free.
+  static const int kRepeat = 0x73;
+  static const int kConstantRepeat = 0x74;
+ // 0x74-0x7f Repeat last word (subtract 0x73 to get the count).
+  static const int kMaxRepeats = 0x7f - 0x73;
+  static int CodeForRepeats(int repeats) {
+    ASSERT(repeats >= 1 && repeats <= kMaxRepeats);
+    return 0x73 + repeats;
+  }
+  static int RepeatsForCode(int byte_code) {
+    ASSERT(byte_code >= kConstantRepeat && byte_code <= 0x7f);
+    return byte_code - 0x73;
+  }
+  static const int kRootArrayLowConstants = 0xb0;
+ // 0xb0-0xbf Things from the first 16 elements of the root array.
+  static const int kRootArrayHighConstants = 0xf0;
+ // 0xf0-0xff Things from the next 16 elements of the root array.
+  static const int kRootArrayNumberOfConstantEncodings = 0x20;
+  static const int kRootArrayNumberOfLowConstantEncodings = 0x10;
+  static int RootArrayConstantFromByteCode(int byte_code) {
+    int constant = (byte_code & 0xf) | ((byte_code & 0x40) >> 2);
+ ASSERT(constant >= 0 && constant < kRootArrayNumberOfConstantEncodings);
+    return constant;
+  }


   static const int kLargeData = LAST_SPACE;
@@ -475,14 +477,22 @@
   static void TooLateToEnableNow() { too_late_to_enable_now_ = true; }
   static bool enabled() { return serialization_enabled_; }
   SerializationAddressMapper* address_mapper() { return &address_mapper_; }
+  void PutRoot(
+      int index, HeapObject* object, HowToCode how, WhereToPoint where);
 #ifdef DEBUG
   virtual void Synchronize(const char* tag);
 #endif

  protected:
   static const int kInvalidRootIndex = -1;
-  virtual int RootIndex(HeapObject* heap_object) = 0;
+
+  int RootIndex(HeapObject* heap_object);
   virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) = 0;
+  intptr_t root_index_wave_front() { return root_index_wave_front_; }
+  void set_root_index_wave_front(intptr_t value) {
+    ASSERT(value >= root_index_wave_front_);
+    root_index_wave_front_ = value;
+  }

   class ObjectSerializer : public ObjectVisitor {
    public:
@@ -558,6 +568,7 @@
   static bool too_late_to_enable_now_;
   int large_object_total_;
   SerializationAddressMapper address_mapper_;
+  intptr_t root_index_wave_front_;

   friend class ObjectSerializer;
   friend class Deserializer;
@@ -572,6 +583,7 @@
                     SnapshotByteSink* sink)
     : Serializer(sink),
       startup_serializer_(startup_snapshot_serializer) {
+    set_root_index_wave_front(Heap::kStrongRootListLength);
   }

   // Serialize the objects reachable from a single object pointer.
@@ -581,7 +593,6 @@
                                WhereToPoint where_to_point);

  protected:
-  virtual int RootIndex(HeapObject* o);
   virtual int PartialSnapshotCacheIndex(HeapObject* o);
   virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) {
// Scripts should be referred only through shared function infos. We can't
@@ -606,7 +617,7 @@
   explicit StartupSerializer(SnapshotByteSink* sink) : Serializer(sink) {
     // 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 neede by that partial
+    // which will repopulate the cache with objects needed by that partial
     // snapshot.
     Isolate::Current()->set_serialize_partial_snapshot_cache_length(0);
   }
@@ -625,7 +636,6 @@
   }

  private:
-  virtual int RootIndex(HeapObject* o) { return kInvalidRootIndex; }
   virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) {
     return false;
   }
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Wed Oct 19 04:36:55 2011 +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Thu Oct 20 05:27:10 2011
@@ -55,7 +55,7 @@

static intptr_t RootRegisterDelta(ExternalReference other, Isolate* isolate) {
   Address roots_register_value = kRootRegisterBias +
-      reinterpret_cast<Address>(isolate->heap()->roots_address());
+      reinterpret_cast<Address>(isolate->heap()->roots_array_start());
   intptr_t delta = other.address() - roots_register_value;
   return delta;
 }
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.h Wed Oct 19 04:36:55 2011 +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.h Thu Oct 20 05:27:10 2011
@@ -319,9 +319,9 @@
   void LoadFromSafepointRegisterSlot(Register dst, Register src);

   void InitializeRootRegister() {
-    ExternalReference roots_address =
-        ExternalReference::roots_address(isolate());
-    movq(kRootRegister, roots_address);
+    ExternalReference roots_array_start =
+        ExternalReference::roots_array_start(isolate());
+    movq(kRootRegister, roots_array_start);
     addq(kRootRegister, Immediate(kRootRegisterBias));
   }

=======================================
--- /branches/bleeding_edge/test/cctest/test-serialize.cc Tue Oct 4 02:07:50 2011 +++ /branches/bleeding_edge/test/cctest/test-serialize.cc Thu Oct 20 05:27:10 2011
@@ -130,7 +130,8 @@
            encoder.Encode(
                ExternalReference::new_space_start(isolate).address()));
   CHECK_EQ(make_code(UNCLASSIFIED, 3),
- encoder.Encode(ExternalReference::roots_address(isolate).address()));
+           encoder.Encode(
+               ExternalReference::roots_array_start(isolate).address()));
 }


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

Reply via email to