| Index: src/heap/mark-compact.cc
|
| diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc
|
| index 1c5299fb6021b67fbcfd16e41bf81c6010660faa..741414a1eff5db98378708b496fa0e2793cbb5cc 100644
|
| --- a/src/heap/mark-compact.cc
|
| +++ b/src/heap/mark-compact.cc
|
| @@ -2113,6 +2113,61 @@ void MarkCompactCollector::ProcessTopOptimizedFrame(ObjectVisitor* visitor) {
|
| }
|
|
|
|
|
| +void MarkCompactCollector::RetainMaps() {
|
| + if (reduce_memory_footprint_ || abort_incremental_marking_ ||
|
| + FLAG_retain_maps_for_n_gc == 0) {
|
| + // Do not retain dead maps if flag disables it or there is
|
| + // - memory pressure (reduce_memory_footprint_),
|
| + // - GC is requested by tests or dev-tools (abort_incremental_marking_).
|
| + return;
|
| + }
|
| +
|
| + ArrayList* retained_maps = heap()->retained_maps();
|
| + int length = retained_maps->Length();
|
| + int new_length = 0;
|
| + for (int i = 0; i < length; i += 2) {
|
| + WeakCell* cell = WeakCell::cast(retained_maps->Get(i));
|
| + if (cell->cleared()) continue;
|
| + int age = Smi::cast(retained_maps->Get(i + 1))->value();
|
| + int new_age;
|
| + Map* map = Map::cast(cell->value());
|
| + MarkBit map_mark = Marking::MarkBitFrom(map);
|
| + if (!map_mark.Get()) {
|
| + if (age == 0) {
|
| + // The map has aged. Do not retain this map.
|
| + continue;
|
| + }
|
| + Object* constructor = map->GetConstructor();
|
| + if (!constructor->IsHeapObject() ||
|
| + !Marking::MarkBitFrom(HeapObject::cast(constructor)).Get()) {
|
| + // The constructor is dead, no new objects with this map can
|
| + // be created. Do not retain this map.
|
| + continue;
|
| + }
|
| + new_age = age - 1;
|
| + MarkObject(map, map_mark);
|
| + } else {
|
| + new_age = FLAG_retain_maps_for_n_gc;
|
| + }
|
| + if (i != new_length) {
|
| + retained_maps->Set(new_length, cell);
|
| + Object** slot = retained_maps->Slot(new_length);
|
| + RecordSlot(slot, slot, cell);
|
| + retained_maps->Set(new_length + 1, Smi::FromInt(new_age));
|
| + } else if (new_age != age) {
|
| + retained_maps->Set(new_length + 1, Smi::FromInt(new_age));
|
| + }
|
| + new_length += 2;
|
| + }
|
| + Object* undefined = heap()->undefined_value();
|
| + for (int i = new_length; i < length; i++) {
|
| + retained_maps->Clear(i, undefined);
|
| + }
|
| + if (new_length != length) retained_maps->SetLength(new_length);
|
| + ProcessMarkingDeque();
|
| +}
|
| +
|
| +
|
| void MarkCompactCollector::EnsureMarkingDequeIsCommittedAndInitialize() {
|
| if (marking_deque_memory_ == NULL) {
|
| marking_deque_memory_ = new base::VirtualMemory(4 * MB);
|
| @@ -2228,6 +2283,11 @@ void MarkCompactCollector::MarkLiveObjects() {
|
|
|
| ProcessTopOptimizedFrame(&root_visitor);
|
|
|
| + // Retaining dying maps should happen before or during ephemeral marking
|
| + // because a map could keep the key of an ephemeron alive. Note that map
|
| + // aging is imprecise: maps that are kept alive only by ephemerons will age.
|
| + RetainMaps();
|
| +
|
| {
|
| GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_WEAKCLOSURE);
|
|
|
|
|