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_mark:
 43       return "Mark";
 44     case _degenerated_evac:
 45       return "Evacuation";
 46     case _degenerated_updaterefs:
 47       return "Update References";
 48     default:
 49       ShouldNotReachHere();
 50       return "ERROR";
 51    }
 52 }
 53 
 54 class ShenandoahUpdateRootsTask : public AbstractGangTask {
 55 private:
 56   ShenandoahRootUpdater*  _root_updater;
 57   bool                    _check_alive;
 58 public:
 59   ShenandoahUpdateRootsTask(ShenandoahRootUpdater* root_updater, bool check_alive) :
 60     AbstractGangTask("Shenandoah Update Roots"),
 61     _root_updater(root_updater),
 62     _check_alive(check_alive){
 63   }
 64 
 65   void work(uint worker_id) {
 66     assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint");
 67     ShenandoahParallelWorkerSession worker_session(worker_id);
 68 
 69     ShenandoahHeap* heap = ShenandoahHeap::heap();
 70     ShenandoahUpdateRefsClosure cl;
 71     if (_check_alive) {
 72       ShenandoahForwardedIsAliveClosure is_alive;
 73       _root_updater->roots_do<ShenandoahForwardedIsAliveClosure, ShenandoahUpdateRefsClosure>(worker_id, &is_alive, &cl);
 74     } else {
 75       AlwaysTrueClosure always_true;;
 76       _root_updater->roots_do<AlwaysTrueClosure, ShenandoahUpdateRefsClosure>(worker_id, &always_true, &cl);
 77     }
 78   }
 79 };
 80 
 81 void ShenandoahGC::update_roots(bool full_gc) {
 82   assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint");
 83   assert(ShenandoahHeap::heap()->is_full_gc_in_progress() ||
 84          ShenandoahHeap::heap()->is_degenerated_gc_in_progress(),
 85          "Only for degenerated GC and full GC");
 86 
 87   bool check_alive = !full_gc;
 88   ShenandoahPhaseTimings::Phase p = full_gc ?
 89                                     ShenandoahPhaseTimings::full_gc_update_roots :
 90                                     ShenandoahPhaseTimings::degen_gc_update_roots;
 91 
 92   ShenandoahGCPhase phase(p);
 93 #if COMPILER2_OR_JVMCI
 94   DerivedPointerTable::clear();
 95 #endif
 96 
 97   ShenandoahHeap* const heap = ShenandoahHeap::heap();
 98   WorkGang* workers = heap->workers();
 99   uint nworkers = workers->active_workers();
100 
101   ShenandoahRootUpdater root_updater(nworkers, p);
102   ShenandoahUpdateRootsTask update_roots(&root_updater, check_alive);
103   workers->run_task(&update_roots);
104 
105 #if COMPILER2_OR_JVMCI
106   DerivedPointerTable::update_pointers();
107 #endif
108 }