Chromium Code Reviews| Index: src/serialize.cc |
| =================================================================== |
| --- src/serialize.cc (revision 9713) |
| +++ src/serialize.cc (working copy) |
| @@ -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_address()[root_id]; |
|
Lasse Reichstein
2011/10/20 10:06:54
The name roots_address suggests that it returns an
Erik Corry
2011/10/20 11:01:42
Done.
|
| + 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_address()) { |
| + 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_address()[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,26 @@ |
| } |
| +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 < 0x20 && |
|
Lasse Reichstein
2011/10/20 10:06:54
Name the constants.
Erik Corry
2011/10/20 11:01:42
Done.
|
| + !HEAP->InNewSpace(object)) { |
| + if (root_index < 0x10) { |
| + sink_->Put(kRootArrayLowConstants + root_index, "RootLoConstant"); |
| + } else { |
| + sink_->Put(kRootArrayHighConstants + root_index - 0x10, "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 +1345,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 +1423,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) { |
|
Lasse Reichstein
2011/10/20 10:06:54
A generic repeat takes five bytes. Up to 4*kMaxRep
Erik Corry
2011/10/20 11:01:42
No, a generic repeat takes 2 bytes if the repeat c
|
| + 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++; |
| + } |
| } |
| } |
| } |