src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp
changeset 47885 5caa1d5f74c1
child 48889 216c2aabbf1f
equal deleted inserted replaced
47884:3cfab71d6c81 47885:5caa1d5f74c1
       
     1 /*
       
     2  * Copyright (c) 2017, 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 "utilities/ticks.inline.hpp"
       
    39 
       
    40 bool G1FullGCPrepareTask::G1CalculatePointersClosure::doHeapRegion(HeapRegion* hr) {
       
    41   if (hr->is_humongous()) {
       
    42     oop obj = oop(hr->humongous_start_region()->bottom());
       
    43     if (_bitmap->is_marked(obj)) {
       
    44       if (hr->is_starts_humongous()) {
       
    45         obj->forward_to(obj);
       
    46       }
       
    47     } else {
       
    48       free_humongous_region(hr);
       
    49     }
       
    50   } else if (!hr->is_pinned()) {
       
    51     prepare_for_compaction(hr);
       
    52   }
       
    53 
       
    54   // Reset data structures not valid after Full GC.
       
    55   reset_region_metadata(hr);
       
    56 
       
    57   return false;
       
    58 }
       
    59 
       
    60 G1FullGCPrepareTask::G1FullGCPrepareTask(G1FullCollector* collector) :
       
    61     G1FullGCTask("G1 Prepare Compact Task", collector),
       
    62     _hrclaimer(collector->workers()),
       
    63     _freed_regions(false) {
       
    64 }
       
    65 
       
    66 void G1FullGCPrepareTask::set_freed_regions() {
       
    67   if (!_freed_regions) {
       
    68     _freed_regions = true;
       
    69   }
       
    70 }
       
    71 
       
    72 bool G1FullGCPrepareTask::has_freed_regions() {
       
    73   return _freed_regions;
       
    74 }
       
    75 
       
    76 void G1FullGCPrepareTask::work(uint worker_id) {
       
    77   Ticks start = Ticks::now();
       
    78   G1FullGCCompactionPoint* compaction_point = collector()->compaction_point(worker_id);
       
    79   G1CalculatePointersClosure closure(collector()->mark_bitmap(), compaction_point);
       
    80   G1CollectedHeap::heap()->heap_region_par_iterate_from_start(&closure, &_hrclaimer);
       
    81 
       
    82   // Update humongous region sets
       
    83   closure.update_sets();
       
    84   compaction_point->update();
       
    85 
       
    86   // Check if any regions was freed by this worker and store in task.
       
    87   if (closure.freed_regions()) {
       
    88     set_freed_regions();
       
    89   }
       
    90   log_task("Prepare compaction task", worker_id, start);
       
    91 }
       
    92 
       
    93 G1FullGCPrepareTask::G1CalculatePointersClosure::G1CalculatePointersClosure(G1CMBitMap* bitmap,
       
    94                                                                             G1FullGCCompactionPoint* cp) :
       
    95     _g1h(G1CollectedHeap::heap()),
       
    96     _bitmap(bitmap),
       
    97     _cp(cp),
       
    98     _humongous_regions_removed(0) { }
       
    99 
       
   100 void G1FullGCPrepareTask::G1CalculatePointersClosure::free_humongous_region(HeapRegion* hr) {
       
   101   FreeRegionList dummy_free_list("Dummy Free List for G1MarkSweep");
       
   102 
       
   103   hr->set_containing_set(NULL);
       
   104   _humongous_regions_removed++;
       
   105 
       
   106   _g1h->free_humongous_region(hr, &dummy_free_list, false /* skip_remset */);
       
   107   prepare_for_compaction(hr);
       
   108   dummy_free_list.remove_all();
       
   109 }
       
   110 
       
   111 void G1FullGCPrepareTask::G1CalculatePointersClosure::reset_region_metadata(HeapRegion* hr) {
       
   112   hr->reset_gc_time_stamp();
       
   113   hr->rem_set()->clear();
       
   114 
       
   115   _g1h->g1_barrier_set()->clear(MemRegion(hr->bottom(), hr->end()));
       
   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 }