| Index: src/mark-compact.cc
|
| diff --git a/src/mark-compact.cc b/src/mark-compact.cc
|
| index bd36459d12b18d63a63a79b638bd1cd12412bc74..68a506226de6afd89dab87dc9dc671d1a7989410 100644
|
| --- a/src/mark-compact.cc
|
| +++ b/src/mark-compact.cc
|
| @@ -1077,6 +1077,12 @@ void MarkCompactCollector::MarkUnmarkedObject(HeapObject* object) {
|
|
|
|
|
| void MarkCompactCollector::MarkMapContents(Map* map) {
|
| + // Mark prototype transitions array but don't push it into marking stack.
|
| + // This will make references from it weak. We will clean dead prototype
|
| + // transitions in ClearNonLiveTransitions.
|
| + FixedArray* prototype_transitions = map->unchecked_prototype_transitions();
|
| + if (!prototype_transitions->IsMarked()) SetMark(prototype_transitions);
|
| +
|
| MarkDescriptorArray(reinterpret_cast<DescriptorArray*>(
|
| *HeapObject::RawField(map, Map::kInstanceDescriptorsOffset)));
|
|
|
| @@ -1494,7 +1500,7 @@ bool MarkCompactCollector::SafeIsMap(HeapObject* object) {
|
|
|
|
|
| void MarkCompactCollector::ClearNonLiveTransitions() {
|
| - HeapObjectIterator map_iterator(heap() ->map_space(), &SizeOfMarkedObject);
|
| + HeapObjectIterator map_iterator(heap()->map_space(), &SizeOfMarkedObject);
|
| // Iterate over the map space, setting map transitions that go from
|
| // a marked map to an unmarked map to null transitions. At the same time,
|
| // set all the prototype fields of maps back to their original value,
|
| @@ -1522,6 +1528,41 @@ void MarkCompactCollector::ClearNonLiveTransitions() {
|
| map->unchecked_constructor()->unchecked_shared()->AttachInitialMap(map);
|
| }
|
|
|
| + // Clear dead prototype transitions.
|
| + FixedArray* prototype_transitions = map->unchecked_prototype_transitions();
|
| + if (prototype_transitions->length() > 0) {
|
| + int finger = Smi::cast(prototype_transitions->get(0))->value();
|
| + int new_finger = 1;
|
| + for (int i = 1; i < finger; i += 2) {
|
| + Object* prototype = prototype_transitions->get(i);
|
| + Object* cached_map = prototype_transitions->get(i + 1);
|
| + if (HeapObject::cast(prototype)->IsMarked() &&
|
| + HeapObject::cast(cached_map)->IsMarked()) {
|
| + if (new_finger != i) {
|
| + prototype_transitions->set_unchecked(heap_,
|
| + new_finger,
|
| + prototype,
|
| + UPDATE_WRITE_BARRIER);
|
| + prototype_transitions->set_unchecked(heap_,
|
| + new_finger + 1,
|
| + cached_map,
|
| + SKIP_WRITE_BARRIER);
|
| + }
|
| + new_finger += 2;
|
| + }
|
| + }
|
| +
|
| + // Fill slots that became free with undefined value.
|
| + Object* undefined = heap()->raw_unchecked_undefined_value();
|
| + for (int i = new_finger; i < finger; i++) {
|
| + prototype_transitions->set_unchecked(heap_,
|
| + i,
|
| + undefined,
|
| + SKIP_WRITE_BARRIER);
|
| + }
|
| + prototype_transitions->set_unchecked(0, Smi::FromInt(new_finger));
|
| + }
|
| +
|
| // Follow the chain of back pointers to find the prototype.
|
| Map* current = map;
|
| while (SafeIsMap(current)) {
|
|
|