1 /*
   2  * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "gc/g1/g1CollectedHeap.hpp"
  27 #include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
  28 #include "gc/g1/g1FullCollector.hpp"
  29 #include "gc/g1/g1FullGCCompactionPoint.hpp"
  30 #include "gc/g1/g1FullGCMarker.hpp"
  31 #include "gc/g1/g1FullGCOopClosures.inline.hpp"
  32 #include "gc/g1/g1FullGCPrepareTask.hpp"
  33 #include "gc/g1/g1HotCardCache.hpp"
  34 #include "gc/g1/heapRegion.inline.hpp"
  35 #include "gc/shared/gcTraceTime.inline.hpp"
  36 #include "gc/shared/referenceProcessor.hpp"
  37 #include "logging/log.hpp"
  38 #include "memory/iterator.inline.hpp"
  39 #include "oops/oop.inline.hpp"
  40 #include "utilities/ticks.hpp"
  41 
  42 bool G1FullGCPrepareTask::G1CalculatePointersClosure::do_heap_region(HeapRegion* hr) {
  43   if (hr->is_humongous()) {
  44     oop obj = oop(hr->humongous_start_region()->bottom());
  45     if (_bitmap->is_marked(obj)) {
  46       if (hr->is_starts_humongous()) {
  47         obj->forward_to(obj);
  48       }
  49     } else {
  50       free_humongous_region(hr);
  51     }
  52   } else if (!hr->is_pinned()) {
  53     prepare_for_compaction(hr);
  54   }
  55 
  56   // Reset data structures not valid after Full GC.
  57   reset_region_metadata(hr);
  58 
  59   return false;
  60 }
  61 
  62 G1FullGCPrepareTask::G1FullGCPrepareTask(G1FullCollector* collector) :
  63     G1FullGCTask("G1 Prepare Compact Task", collector),
  64     _hrclaimer(collector->workers()),
  65     _freed_regions(false) {
  66 }
  67 
  68 void G1FullGCPrepareTask::set_freed_regions() {
  69   if (!_freed_regions) {
  70     _freed_regions = true;
  71   }
  72 }
  73 
  74 bool G1FullGCPrepareTask::has_freed_regions() {
  75   return _freed_regions;
  76 }
  77 
  78 void G1FullGCPrepareTask::work(uint worker_id) {
  79   Ticks start = Ticks::now();
  80   G1FullGCCompactionPoint* compaction_point = collector()->compaction_point(worker_id);
  81   G1CalculatePointersClosure closure(collector()->mark_bitmap(), compaction_point);
  82   G1CollectedHeap::heap()->heap_region_par_iterate_from_start(&closure, &_hrclaimer);
  83 
  84   // Update humongous region sets
  85   closure.update_sets();
  86   compaction_point->update();
  87 
  88   // Check if any regions was freed by this worker and store in task.
  89   if (closure.freed_regions()) {
  90     set_freed_regions();
  91   }
  92   log_task("Prepare compaction task", worker_id, start);
  93 }
  94 
  95 G1FullGCPrepareTask::G1CalculatePointersClosure::G1CalculatePointersClosure(G1CMBitMap* bitmap,
  96                                                                             G1FullGCCompactionPoint* cp) :
  97     _g1h(G1CollectedHeap::heap()),
  98     _bitmap(bitmap),
  99     _cp(cp),
 100     _humongous_regions_removed(0) { }
 101 
 102 void G1FullGCPrepareTask::G1CalculatePointersClosure::free_humongous_region(HeapRegion* hr) {
 103   FreeRegionList dummy_free_list("Dummy Free List for G1MarkSweep");
 104 
 105   hr->set_containing_set(NULL);
 106   _humongous_regions_removed++;
 107 
 108   _g1h->free_humongous_region(hr, &dummy_free_list);
 109   prepare_for_compaction(hr);
 110   dummy_free_list.remove_all();
 111 }
 112 
 113 void G1FullGCPrepareTask::G1CalculatePointersClosure::reset_region_metadata(HeapRegion* hr) {
 114   hr->rem_set()->clear();
 115   hr->clear_cardtable();
 116 
 117   if (_g1h->g1_hot_card_cache()->use_cache()) {
 118     _g1h->g1_hot_card_cache()->reset_card_counts(hr);
 119   }
 120 }
 121 
 122 G1FullGCPrepareTask::G1PrepareCompactLiveClosure::G1PrepareCompactLiveClosure(G1FullGCCompactionPoint* cp) :
 123     _cp(cp) { }
 124 
 125 size_t G1FullGCPrepareTask::G1PrepareCompactLiveClosure::apply(oop object) {
 126   size_t size = object->size();
 127   _cp->forward(object, size);
 128   return size;
 129 }
 130 
 131 size_t G1FullGCPrepareTask::G1RePrepareClosure::apply(oop obj) {
 132   // We only re-prepare objects forwarded within the current region, so
 133   // skip objects that are already forwarded to another region.
 134   oop forwarded_to = obj->forwardee();
 135   if (forwarded_to != NULL && !_current->is_in(forwarded_to)) {
 136     return obj->size();
 137   }
 138 
 139   // Get size and forward.
 140   size_t size = obj->size();
 141   _cp->forward(obj, size);
 142 
 143   return size;
 144 }
 145 
 146 void G1FullGCPrepareTask::G1CalculatePointersClosure::prepare_for_compaction_work(G1FullGCCompactionPoint* cp,
 147                                                                                   HeapRegion* hr) {
 148   G1PrepareCompactLiveClosure prepare_compact(cp);
 149   hr->set_compaction_top(hr->bottom());
 150   hr->apply_to_marked_objects(_bitmap, &prepare_compact);
 151 }
 152 
 153 void G1FullGCPrepareTask::G1CalculatePointersClosure::prepare_for_compaction(HeapRegion* hr) {
 154   if (!_cp->is_initialized()) {
 155     hr->set_compaction_top(hr->bottom());
 156     _cp->initialize(hr, true);
 157   }
 158   // Add region to the compaction queue and prepare it.
 159   _cp->add(hr);
 160   prepare_for_compaction_work(_cp, hr);
 161 }
 162 
 163 void G1FullGCPrepareTask::prepare_serial_compaction() {
 164   GCTraceTime(Debug, gc, phases) debug("Phase 2: Prepare Serial Compaction", collector()->scope()->timer());
 165   // At this point we know that no regions were completely freed by
 166   // the parallel compaction. That means that the last region of
 167   // all compaction queues still have data in them. We try to compact
 168   // these regions in serial to avoid a premature OOM.
 169   for (uint i = 0; i < collector()->workers(); i++) {
 170     G1FullGCCompactionPoint* cp = collector()->compaction_point(i);
 171     if (cp->has_regions()) {
 172       collector()->serial_compaction_point()->add(cp->remove_last());
 173     }
 174   }
 175 
 176   // Update the forwarding information for the regions in the serial
 177   // compaction point.
 178   G1FullGCCompactionPoint* cp = collector()->serial_compaction_point();
 179   for (GrowableArrayIterator<HeapRegion*> it = cp->regions()->begin(); it != cp->regions()->end(); ++it) {
 180     HeapRegion* current = *it;
 181     if (!cp->is_initialized()) {
 182       // Initialize the compaction point. Nothing more is needed for the first heap region
 183       // since it is already prepared for compaction.
 184       cp->initialize(current, false);
 185     } else {
 186       assert(!current->is_humongous(), "Should be no humongous regions in compaction queue");
 187       G1RePrepareClosure re_prepare(cp, current);
 188       current->set_compaction_top(current->bottom());
 189       current->apply_to_marked_objects(collector()->mark_bitmap(), &re_prepare);
 190     }
 191   }
 192   cp->update();
 193 }
 194 
 195 void G1FullGCPrepareTask::G1CalculatePointersClosure::update_sets() {
 196   // We'll recalculate total used bytes and recreate the free list
 197   // at the end of the GC, so no point in updating those values here.
 198   _g1h->remove_from_old_sets(0, _humongous_regions_removed);
 199 }
 200 
 201 bool G1FullGCPrepareTask::G1CalculatePointersClosure::freed_regions() {
 202   if (_humongous_regions_removed > 0) {
 203     // Free regions from dead humongous regions.
 204     return true;
 205   }
 206 
 207   if (!_cp->has_regions()) {
 208     // No regions in queue, so no free ones either.
 209     return false;
 210   }
 211 
 212   if (_cp->current_region() != _cp->regions()->last()) {
 213     // The current region used for compaction is not the last in the
 214     // queue. That means there is at least one free region in the queue.
 215     return true;
 216   }
 217 
 218   // No free regions in the queue.
 219   return false;
 220 }