| Index: src/heap/incremental-marking.cc
|
| diff --git a/src/heap/incremental-marking.cc b/src/heap/incremental-marking.cc
|
| index 6c842b1b274c8310551bafa32fece60b6fc5de3f..21152583222cbc5a628eca4f691b2d181c2692b4 100644
|
| --- a/src/heap/incremental-marking.cc
|
| +++ b/src/heap/incremental-marking.cc
|
| @@ -683,6 +683,69 @@ void IncrementalMarking::ProcessWeakCells() {
|
| }
|
|
|
|
|
| +bool ShouldRetainMap(Map* map, int age) {
|
| + if (age == 0) {
|
| + // The map has aged. Do not retain this map.
|
| + return false;
|
| + }
|
| + Object* constructor = map->GetConstructor();
|
| + if (!constructor->IsHeapObject() ||
|
| + Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(constructor)))) {
|
| + // The constructor is dead, no new objects with this map can
|
| + // be created. Do not retain this map.
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +
|
| +void IncrementalMarking::RetainMaps() {
|
| + // 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_).
|
| + bool map_retaining_is_disabled = heap()->ShouldReduceMemory() ||
|
| + heap()->ShouldAbortIncrementalMarking() ||
|
| + FLAG_retain_maps_for_n_gc == 0;
|
| + ArrayList* retained_maps = heap()->retained_maps();
|
| + int length = retained_maps->Length();
|
| + // The number_of_disposed_maps separates maps in the retained_maps
|
| + // array that were created before and after context disposal.
|
| + // We do not age and retain disposed maps to avoid memory leaks.
|
| + int number_of_disposed_maps = heap()->number_of_disposed_maps_;
|
| + for (int i = 0; i < length; i += 2) {
|
| + DCHECK(retained_maps->Get(i)->IsWeakCell());
|
| + 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 (i >= number_of_disposed_maps && !map_retaining_is_disabled &&
|
| + Marking::IsWhite(map_mark)) {
|
| + if (ShouldRetainMap(map, age)) {
|
| + MarkObject(heap(), map);
|
| + }
|
| + Object* prototype = map->prototype();
|
| + if (age > 0 && prototype->IsHeapObject() &&
|
| + Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(prototype)))) {
|
| + // The prototype is not marked, age the map.
|
| + new_age = age - 1;
|
| + } else {
|
| + // The prototype and the constructor are marked, this map keeps only
|
| + // transition tree alive, not JSObjects. Do not age the map.
|
| + new_age = age;
|
| + }
|
| + } else {
|
| + new_age = FLAG_retain_maps_for_n_gc;
|
| + }
|
| + // Compact the array and update the age.
|
| + if (new_age != age) {
|
| + retained_maps->Set(i + 1, Smi::FromInt(new_age));
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| void IncrementalMarking::FinalizeIncrementally() {
|
| DCHECK(!finalize_marking_completed_);
|
| DCHECK(IsMarking());
|
| @@ -696,10 +759,16 @@ void IncrementalMarking::FinalizeIncrementally() {
|
| // objects to reduce the marking load in the final pause.
|
| // 1) We scan and mark the roots again to find all changes to the root set.
|
| // 2) We mark the object groups.
|
| - // 3) Remove weak cell with live values from the list of weak cells, they
|
| + // 3) Age and retain maps embedded in optimized code.
|
| + // 4) Remove weak cell with live values from the list of weak cells, they
|
| // do not need processing during GC.
|
| MarkRoots();
|
| MarkObjectGroups();
|
| + if (incremental_marking_finalization_rounds_ == 0) {
|
| + // Map retaining is needed for perfromance, not correctness,
|
| + // so we can do it only once at the beginning of the finalization.
|
| + RetainMaps();
|
| + }
|
| ProcessWeakCells();
|
|
|
| int marking_progress =
|
|
|