| Index: src/mark-compact.cc
|
| diff --git a/src/mark-compact.cc b/src/mark-compact.cc
|
| index 16e51468cb81390bcb1aeb8b5c89064e392e2fc2..3b0415f2f7a58f6c12008e60eb8b36493f415a9b 100644
|
| --- a/src/mark-compact.cc
|
| +++ b/src/mark-compact.cc
|
| @@ -2310,88 +2310,92 @@ void MarkCompactCollector::ClearNonLiveTransitions() {
|
| map->unchecked_constructor()->unchecked_shared()->AttachInitialMap(map);
|
| }
|
|
|
| - // Clear dead prototype transitions.
|
| - int number_of_transitions = map->NumberOfProtoTransitions();
|
| - FixedArray* prototype_transitions = map->prototype_transitions();
|
| -
|
| - int new_number_of_transitions = 0;
|
| - const int header = Map::kProtoTransitionHeaderSize;
|
| - const int proto_offset =
|
| - header + Map::kProtoTransitionPrototypeOffset;
|
| - const int map_offset = header + Map::kProtoTransitionMapOffset;
|
| - const int step = Map::kProtoTransitionElementsPerEntry;
|
| - for (int i = 0; i < number_of_transitions; i++) {
|
| - Object* prototype = prototype_transitions->get(proto_offset + i * step);
|
| - Object* cached_map = prototype_transitions->get(map_offset + i * step);
|
| - if (IsMarked(prototype) && IsMarked(cached_map)) {
|
| - int proto_index = proto_offset + new_number_of_transitions * step;
|
| - int map_index = map_offset + new_number_of_transitions * step;
|
| - if (new_number_of_transitions != i) {
|
| - prototype_transitions->set_unchecked(
|
| - heap_,
|
| - proto_index,
|
| - prototype,
|
| - UPDATE_WRITE_BARRIER);
|
| - prototype_transitions->set_unchecked(
|
| - heap_,
|
| - map_index,
|
| - cached_map,
|
| - SKIP_WRITE_BARRIER);
|
| - }
|
| - Object** slot =
|
| - HeapObject::RawField(prototype_transitions,
|
| - FixedArray::OffsetOfElementAt(proto_index));
|
| - RecordSlot(slot, slot, prototype);
|
| - new_number_of_transitions++;
|
| + ClearNonLivePrototypeTransitions(map);
|
| + ClearNonLiveMapTransitions(map, map_mark);
|
| + }
|
| +}
|
| +
|
| +
|
| +void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) {
|
| + int number_of_transitions = map->NumberOfProtoTransitions();
|
| + FixedArray* prototype_transitions = map->prototype_transitions();
|
| +
|
| + int new_number_of_transitions = 0;
|
| + const int header = Map::kProtoTransitionHeaderSize;
|
| + const int proto_offset = header + Map::kProtoTransitionPrototypeOffset;
|
| + const int map_offset = header + Map::kProtoTransitionMapOffset;
|
| + const int step = Map::kProtoTransitionElementsPerEntry;
|
| + for (int i = 0; i < number_of_transitions; i++) {
|
| + Object* prototype = prototype_transitions->get(proto_offset + i * step);
|
| + Object* cached_map = prototype_transitions->get(map_offset + i * step);
|
| + if (IsMarked(prototype) && IsMarked(cached_map)) {
|
| + int proto_index = proto_offset + new_number_of_transitions * step;
|
| + int map_index = map_offset + new_number_of_transitions * step;
|
| + if (new_number_of_transitions != i) {
|
| + prototype_transitions->set_unchecked(
|
| + heap_,
|
| + proto_index,
|
| + prototype,
|
| + UPDATE_WRITE_BARRIER);
|
| + prototype_transitions->set_unchecked(
|
| + heap_,
|
| + map_index,
|
| + cached_map,
|
| + SKIP_WRITE_BARRIER);
|
| }
|
| + Object** slot =
|
| + HeapObject::RawField(prototype_transitions,
|
| + FixedArray::OffsetOfElementAt(proto_index));
|
| + RecordSlot(slot, slot, prototype);
|
| + new_number_of_transitions++;
|
| }
|
| + }
|
|
|
| - if (new_number_of_transitions != number_of_transitions) {
|
| - map->SetNumberOfProtoTransitions(new_number_of_transitions);
|
| - }
|
| + if (new_number_of_transitions != number_of_transitions) {
|
| + map->SetNumberOfProtoTransitions(new_number_of_transitions);
|
| + }
|
|
|
| - // Fill slots that became free with undefined value.
|
| - for (int i = new_number_of_transitions * step;
|
| - i < number_of_transitions * step;
|
| - i++) {
|
| - prototype_transitions->set_undefined(heap_, header + i);
|
| - }
|
| + // Fill slots that became free with undefined value.
|
| + for (int i = new_number_of_transitions * step;
|
| + i < number_of_transitions * step;
|
| + i++) {
|
| + prototype_transitions->set_undefined(heap_, header + i);
|
| + }
|
| +}
|
|
|
| - // Follow the chain of back pointers to find the prototype.
|
| - Map* current = map;
|
| - while (current->IsMap()) {
|
| - current = reinterpret_cast<Map*>(current->prototype());
|
| - ASSERT(current->IsHeapObject());
|
| - }
|
| - Object* real_prototype = current;
|
|
|
| - // Follow back pointers, setting them to prototype,
|
| - // clearing map transitions when necessary.
|
| - current = map;
|
| - bool on_dead_path = !map_mark.Get();
|
| - Object* next;
|
| - while (current->IsMap()) {
|
| - next = current->prototype();
|
| - // There should never be a dead map above a live map.
|
| - MarkBit current_mark = Marking::MarkBitFrom(current);
|
| - bool is_alive = current_mark.Get();
|
| - ASSERT(on_dead_path || is_alive);
|
| +void MarkCompactCollector::ClearNonLiveMapTransitions(Map* map,
|
| + MarkBit map_mark) {
|
| + // Follow the chain of back pointers to find the prototype.
|
| + Map* real_prototype = map;
|
| + while (real_prototype->IsMap()) {
|
| + real_prototype = reinterpret_cast<Map*>(real_prototype->prototype());
|
| + ASSERT(real_prototype->IsHeapObject());
|
| + }
|
|
|
| - // A live map above a dead map indicates a dead transition.
|
| - // This test will always be false on the first iteration.
|
| - if (on_dead_path && is_alive) {
|
| - on_dead_path = false;
|
| - current->ClearNonLiveTransitions(heap(), real_prototype);
|
| - }
|
| - *HeapObject::RawField(current, Map::kPrototypeOffset) =
|
| - real_prototype;
|
| + // Follow back pointers, setting them to prototype, clearing map transitions
|
| + // when necessary.
|
| + Map* current = map;
|
| + bool current_is_alive = map_mark.Get();
|
| + bool on_dead_path = !current_is_alive;
|
| + while (current->IsMap()) {
|
| + Object* next = current->prototype();
|
| + // There should never be a dead map above a live map.
|
| + ASSERT(on_dead_path || current_is_alive);
|
|
|
| - if (is_alive) {
|
| - Object** slot = HeapObject::RawField(current, Map::kPrototypeOffset);
|
| - RecordSlot(slot, slot, real_prototype);
|
| - }
|
| - current = reinterpret_cast<Map*>(next);
|
| + // A live map above a dead map indicates a dead transition. This test will
|
| + // always be false on the first iteration.
|
| + if (on_dead_path && current_is_alive) {
|
| + on_dead_path = false;
|
| + current->ClearNonLiveTransitions(heap(), real_prototype);
|
| }
|
| +
|
| + Object** slot = HeapObject::RawField(current, Map::kPrototypeOffset);
|
| + *slot = real_prototype;
|
| + if (current_is_alive) RecordSlot(slot, slot, real_prototype);
|
| +
|
| + current = reinterpret_cast<Map*>(next);
|
| + current_is_alive = Marking::MarkBitFrom(current).Get();
|
| }
|
| }
|
|
|
|
|