Index: src/serialize.cc |
=================================================================== |
--- src/serialize.cc (revision 9713) |
+++ src/serialize.cc (working copy) |
@@ -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,12 +883,18 @@ |
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. |
#define RAW_CASE(index, size) \ |
@@ -911,6 +917,32 @@ |
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. |
ONE_PER_SPACE(kNewObject, kPlain, kStartOfObject) |
@@ -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"); |
@@ -1256,6 +1280,12 @@ |
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); |
int address = address_mapper_.MappedTo(heap_object); |
@@ -1286,6 +1316,28 @@ |
} |
+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( |
Object* o, |
HowToCode how_to_code, |
@@ -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++; |
+ } |
} |
} |
} |