Index: src/serialize.cc |
=================================================================== |
--- src/serialize.cc (revision 9808) |
+++ 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, |
@@ -490,6 +490,10 @@ |
UNCLASSIFIED, |
44, |
"canonical_nan"); |
+ Add(ExternalReference::address_of_the_hole_nan().address(), |
+ UNCLASSIFIED, |
+ 45, |
+ "the_hole_nan"); |
} |
@@ -753,8 +757,13 @@ |
void Deserializer::ReadChunk(Object** current, |
Object** limit, |
int source_space, |
- Address address) { |
+ Address current_object_address) { |
Isolate* const isolate = isolate_; |
+ bool write_barrier_needed = (current_object_address != NULL && |
+ source_space != NEW_SPACE && |
+ source_space != CELL_SPACE && |
+ source_space != CODE_SPACE && |
+ source_space != OLD_DATA_SPACE); |
while (current < limit) { |
int data = source_->Get(); |
switch (data) { |
@@ -774,9 +783,7 @@ |
if (where == kNewObject && how == kPlain && within == kStartOfObject) {\ |
ASSIGN_DEST_SPACE(space_number) \ |
ReadObject(space_number, dest_space, current); \ |
- emit_write_barrier = (space_number == NEW_SPACE && \ |
- source_space != NEW_SPACE && \ |
- source_space != CELL_SPACE); \ |
+ emit_write_barrier = (space_number == NEW_SPACE); \ |
} else { \ |
Object* new_object = NULL; /* May not be a real Object pointer. */ \ |
if (where == kNewObject) { \ |
@@ -784,27 +791,25 @@ |
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]; \ |
+ emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
} else if (where == kPartialSnapshotCache) { \ |
int cache_index = source_->GetInt(); \ |
new_object = isolate->serialize_partial_snapshot_cache() \ |
[cache_index]; \ |
+ emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
} else if (where == kExternalReference) { \ |
int reference_id = source_->GetInt(); \ |
Address address = external_reference_decoder_-> \ |
Decode(reference_id); \ |
new_object = reinterpret_cast<Object*>(address); \ |
} else if (where == kBackref) { \ |
- emit_write_barrier = (space_number == NEW_SPACE && \ |
- source_space != NEW_SPACE && \ |
- source_space != CELL_SPACE); \ |
+ emit_write_barrier = (space_number == NEW_SPACE); \ |
new_object = GetAddressFromEnd(data & kSpaceMask); \ |
} else { \ |
ASSERT(where == kFromStart); \ |
if (offset_from_start == kUnknownOffsetFromStart) { \ |
- emit_write_barrier = (space_number == NEW_SPACE && \ |
- source_space != NEW_SPACE && \ |
- source_space != CELL_SPACE); \ |
+ emit_write_barrier = (space_number == NEW_SPACE); \ |
new_object = GetAddressFromStart(data & kSpaceMask); \ |
} else { \ |
Address object_address = pages_[space_number][0] + \ |
@@ -831,12 +836,14 @@ |
*current = new_object; \ |
} \ |
} \ |
- if (emit_write_barrier) { \ |
- isolate->heap()->RecordWrite(address, static_cast<int>( \ |
- reinterpret_cast<Address>(current) - address)); \ |
+ if (emit_write_barrier && write_barrier_needed) { \ |
+ Address current_address = reinterpret_cast<Address>(current); \ |
+ isolate->heap()->RecordWrite( \ |
+ current_object_address, \ |
+ static_cast<int>(current_address - current_object_address)); \ |
} \ |
if (!current_was_incremented) { \ |
- current++; /* Increment current if it wasn't done above. */ \ |
+ current++; \ |
} \ |
break; \ |
} \ |
@@ -883,12 +890,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 +924,38 @@ |
break; |
} |
+ SIXTEEN_CASES(kRootArrayLowConstants) |
+ SIXTEEN_CASES(kRootArrayHighConstants) { |
+ int root_id = RootArrayConstantFromByteCode(data); |
+ 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; |
+ } |
+ |
// Deserialize a new object and write a pointer to it to the current |
// object. |
ONE_PER_SPACE(kNewObject, kPlain, kStartOfObject) |
@@ -936,9 +981,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 +1022,6 @@ |
#undef CASE_BODY |
#undef ONE_PER_SPACE |
#undef ALL_SPACES |
-#undef EMIT_COMMON_REFERENCE_PATTERNS |
#undef ASSIGN_DEST_SPACE |
case kNewPage: { |
@@ -1067,7 +1108,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 +1166,10 @@ |
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_, static_cast<intptr_t>(current - start)); |
+ } |
if (reinterpret_cast<Address>(current) == |
isolate->heap()->store_buffer()->TopAddress()) { |
sink_->Put(kSkip, "Skip"); |
@@ -1191,10 +1237,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 +1278,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 +1294,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 +1330,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 +1361,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 +1439,33 @@ |
if (current < end) OutputRawData(reinterpret_cast<Address>(current)); |
while (current < end && !(*current)->IsSmi()) { |
- serializer_->SerializeObject(*current, kPlain, kStartOfObject); |
- bytes_processed_so_far_ += kPointerSize; |
- current++; |
+ 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 && |
+ 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_contents) { |
+ 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_contents, kPlain, kStartOfObject); |
+ bytes_processed_so_far_ += kPointerSize; |
+ current++; |
+ } |
} |
} |
} |