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/workerThread.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 WorkerTask {
 55 private:
 56   ShenandoahRootUpdater*  _root_updater;
 57   bool                    _check_alive;
 58 public:
 59   ShenandoahUpdateRootsTask(ShenandoahRootUpdater* root_updater, bool check_alive) :
 60     WorkerTask("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     ShenandoahUpdateRefsClosure cl;
 70     if (_check_alive) {
 71       ShenandoahForwardedIsAliveClosure is_alive;
 72       _root_updater->roots_do<ShenandoahForwardedIsAliveClosure, ShenandoahUpdateRefsClosure>(worker_id, &is_alive, &cl);
 73     } else {
 74       AlwaysTrueClosure always_true;;
 75       _root_updater->roots_do<AlwaysTrueClosure, ShenandoahUpdateRefsClosure>(worker_id, &always_true, &cl);
 76     }
 77   }
 78 };
 79 
 80 void ShenandoahGC::update_roots(bool full_gc) {
 81   assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint");
 82   assert(ShenandoahHeap::heap()->is_full_gc_in_progress() ||
 83          ShenandoahHeap::heap()->is_degenerated_gc_in_progress(),
 84          "Only for degenerated GC and full GC");
 85 
 86   bool check_alive = !full_gc;
 87   ShenandoahPhaseTimings::Phase p = full_gc ?
 88                                     ShenandoahPhaseTimings::full_gc_update_roots :
 89                                     ShenandoahPhaseTimings::degen_gc_update_roots;
 90 
 91   ShenandoahGCPhase phase(p);
 92 #if COMPILER2_OR_JVMCI
 93   DerivedPointerTable::clear();
 94 #endif
 95 
 96   ShenandoahHeap* const heap = ShenandoahHeap::heap();
 97   WorkerThreads* workers = heap->workers();
 98   uint nworkers = workers->active_workers();
 99 
100   ShenandoahRootUpdater root_updater(nworkers, p);
101   ShenandoahUpdateRootsTask update_roots(&root_updater, check_alive);
102   workers->run_task(&update_roots);
103 
104 #if COMPILER2_OR_JVMCI
105   DerivedPointerTable::update_pointers();
106 #endif
107 }