1 /*
  2  * Copyright (c) 2021, Red Hat, Inc. 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 
 27 #include "compiler/oopMap.hpp"
 28 #include "gc/shared/workgroup.hpp"
 29 #include "gc/shenandoah/shenandoahClosures.inline.hpp"
 30 #include "gc/shenandoah/shenandoahGC.hpp"
 31 #include "gc/shenandoah/shenandoahHeap.hpp"
 32 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
 33 #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
 34 #include "gc/shenandoah/shenandoahUtils.hpp"
 35 
 36 const char* ShenandoahGC::degen_point_to_string(ShenandoahDegenPoint point) {
 37   switch(point) {
 38     case _degenerated_unset:
 39       return "<UNSET>";
 40     case _degenerated_outside_cycle:
 41       return "Outside of Cycle";
 42     case _degenerated_roots:
 43       return "Roots";
 44     case _degenerated_mark:
 45       return "Mark";
 46     case _degenerated_evac:
 47       return "Evacuation";
 48     case _degenerated_updaterefs:
 49       return "Update References";
 50     default:
 51       ShouldNotReachHere();
 52       return "ERROR";
 53    }
 54 }
 55 
 56 class ShenandoahUpdateRootsTask : public AbstractGangTask {
 57 private:
 58   ShenandoahRootUpdater*  _root_updater;
 59   bool                    _check_alive;
 60 public:
 61   ShenandoahUpdateRootsTask(ShenandoahRootUpdater* root_updater, bool check_alive) :
 62     AbstractGangTask("Shenandoah Update Roots"),
 63     _root_updater(root_updater),
 64     _check_alive(check_alive){
 65   }
 66 
 67   void work(uint worker_id) {
 68     assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint");
 69     ShenandoahParallelWorkerSession worker_session(worker_id);
 70 
 71     ShenandoahHeap* heap = ShenandoahHeap::heap();
 72     ShenandoahUpdateRefsClosure cl;
 73     if (_check_alive) {
 74       ShenandoahForwardedIsAliveClosure is_alive;
 75       _root_updater->roots_do<ShenandoahForwardedIsAliveClosure, ShenandoahUpdateRefsClosure>(worker_id, &is_alive, &cl);
 76     } else {
 77       AlwaysTrueClosure always_true;;
 78       _root_updater->roots_do<AlwaysTrueClosure, ShenandoahUpdateRefsClosure>(worker_id, &always_true, &cl);
 79     }
 80   }
 81 };
 82 
 83 void ShenandoahGC::update_roots(bool full_gc) {
 84   assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint");
 85   assert(ShenandoahHeap::heap()->is_full_gc_in_progress() ||
 86          ShenandoahHeap::heap()->is_degenerated_gc_in_progress(),
 87          "Only for degenerated GC and full GC");
 88 
 89   bool check_alive = !full_gc;
 90   ShenandoahPhaseTimings::Phase p = full_gc ?
 91                                     ShenandoahPhaseTimings::full_gc_update_roots :
 92                                     ShenandoahPhaseTimings::degen_gc_update_roots;
 93 
 94   ShenandoahGCPhase phase(p);
 95 #if COMPILER2_OR_JVMCI
 96   DerivedPointerTable::clear();
 97 #endif
 98 
 99   ShenandoahHeap* const heap = ShenandoahHeap::heap();
100   WorkGang* workers = heap->workers();
101   uint nworkers = workers->active_workers();
102 
103   ShenandoahRootUpdater root_updater(nworkers, p);
104   ShenandoahUpdateRootsTask update_roots(&root_updater, check_alive);
105   workers->run_task(&update_roots);
106 
107 #if COMPILER2_OR_JVMCI
108   DerivedPointerTable::update_pointers();
109 #endif
110 }