| 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++;
|
| + }
|
| }
|
| }
|
| }
|
|
|