1 /*
   2  * Copyright (c) 2013, 2015, Red Hat, Inc. and/or its affiliates.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.
   7  *
   8  * This code is distributed in the hope that it will be useful, but WITHOUT
   9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  11  * version 2 for more details (a copy is included in the LICENSE file that
  12  * accompanied this code).
  13  *
  14  * You should have received a copy of the GNU General Public License version
  15  * 2 along with this work; if not, write to the Free Software Foundation,
  16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17  *
  18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  19  * or visit www.oracle.com if you need additional information or have any
  20  * questions.
  21  *
  22  */
  23 
  24 #include "gc/shenandoah/shenandoahMarkCompact.hpp"
  25 #include "gc/shenandoah/vm_operations_shenandoah.hpp"
  26 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  27 
  28 VM_Operation::VMOp_Type VM_ShenandoahInitMark::type() const {
  29   return VMOp_ShenandoahInitMark;
  30 }
  31 
  32 const char* VM_ShenandoahInitMark::name() const {
  33   return "Shenandoah Initial Marking";
  34 }
  35 
  36 void VM_ShenandoahInitMark::doit() {
  37   ShenandoahHeap *sh = (ShenandoahHeap*) Universe::heap();
  38   sh->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::init_mark);
  39 
  40   assert(sh->is_bitmap_clear(), "need clear marking bitmap");
  41 
  42   if (ShenandoahGCVerbose)
  43     tty->print("vm_ShenandoahInitMark\n");
  44   sh->start_concurrent_marking();
  45   if (UseTLAB) {
  46     sh->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::resize_tlabs);
  47     sh->resize_all_tlabs();
  48     sh->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::resize_tlabs);
  49   }
  50 
  51   sh->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::init_mark);
  52 
  53   if (! ShenandoahConcurrentMarking) {
  54     sh->concurrentMark()->mark_from_roots();
  55     VM_ShenandoahStartEvacuation finishMark;
  56     finishMark.doit();
  57   }
  58 }
  59 
  60 VM_Operation::VMOp_Type VM_ShenandoahFullGC::type() const {
  61   return VMOp_ShenandoahFullGC;
  62 }
  63 
  64 void VM_ShenandoahFullGC::doit() {
  65 
  66   ShenandoahMarkCompact::do_mark_compact();
  67   ShenandoahHeap *sh = ShenandoahHeap::heap();
  68   if (UseTLAB) {
  69     sh->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::resize_tlabs);
  70     sh->resize_all_tlabs();
  71     sh->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::resize_tlabs);
  72   }
  73 }
  74 
  75 const char* VM_ShenandoahFullGC::name() const {
  76   return "Shenandoah Full GC";
  77 }
  78 
  79 
  80 bool VM_ShenandoahReferenceOperation::doit_prologue() {
  81   ShenandoahHeap *sh = (ShenandoahHeap*) Universe::heap();
  82   sh->acquire_pending_refs_lock();
  83   return true;
  84 }
  85 
  86 void VM_ShenandoahReferenceOperation::doit_epilogue() {
  87   ShenandoahHeap *sh = ShenandoahHeap::heap();
  88   sh->release_pending_refs_lock();
  89 }
  90 
  91 void VM_ShenandoahStartEvacuation::doit() {
  92 
  93   // We need to do the finish mark here, so that a JNI critical region
  94   // can't divide it from evacuation start. It is critical that we
  95   // evacuate roots right after finishing marking, so that we don't
  96   // get unmarked objects in the roots.
  97   ShenandoahHeap *sh = ShenandoahHeap::heap();
  98   if (!sh->cancelled_concgc()) {
  99     if (ShenandoahGCVerbose)
 100       tty->print("vm_ShenandoahFinalMark\n");
 101 
 102     sh->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::final_mark);
 103     sh->concurrentMark()->finish_mark_from_roots();
 104     sh->stop_concurrent_marking();
 105     sh->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::final_mark);
 106 
 107     sh->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::prepare_evac);
 108     sh->prepare_for_concurrent_evacuation();
 109     sh->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::prepare_evac);
 110 
 111     if (!sh->cancelled_concgc()){
 112       sh->set_evacuation_in_progress(true);
 113 
 114       // From here on, we need to update references.
 115       sh->set_need_update_refs(true);
 116 
 117       if (! ShenandoahConcurrentEvacuation) {
 118         VM_ShenandoahEvacuation evacuation;
 119         evacuation.doit();
 120       } else {
 121         if (!sh->cancelled_concgc()) {
 122           sh->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::init_evac);
 123           sh->evacuate_and_update_roots();
 124           sh->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::init_evac);
 125         }
 126       }
 127     } else {
 128       sh->free_regions()->set_concurrent_iteration_safe_limits();
 129       //      sh->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::prepare_evac);
 130       //      sh->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::final_mark);
 131     }
 132   } else {
 133     sh->concurrentMark()->cancel();
 134     sh->stop_concurrent_marking();
 135   }
 136 }
 137 
 138 VM_Operation::VMOp_Type VM_ShenandoahStartEvacuation::type() const {
 139   return VMOp_ShenandoahStartEvacuation;
 140 }
 141 
 142 const char* VM_ShenandoahStartEvacuation::name() const {
 143   return "Start shenandoah evacuation";
 144 }
 145 
 146 VM_Operation::VMOp_Type VM_ShenandoahVerifyHeapAfterEvacuation::type() const {
 147   return VMOp_ShenandoahVerifyHeapAfterEvacuation;
 148 }
 149 
 150 const char* VM_ShenandoahVerifyHeapAfterEvacuation::name() const {
 151   return "Shenandoah verify heap after evacuation";
 152 }
 153 
 154 void VM_ShenandoahVerifyHeapAfterEvacuation::doit() {
 155 
 156   ShenandoahHeap *sh = ShenandoahHeap::heap();
 157   sh->verify_heap_after_evacuation();
 158 
 159 }
 160 
 161 VM_Operation::VMOp_Type VM_ShenandoahEvacuation::type() const {
 162   return VMOp_ShenandoahEvacuation;
 163 }
 164 
 165 const char* VM_ShenandoahEvacuation::name() const {
 166   return "Shenandoah evacuation";
 167 }
 168 
 169 void VM_ShenandoahEvacuation::doit() {
 170   if (ShenandoahGCVerbose)
 171     tty->print("vm_ShenandoahEvacuation\n");
 172 
 173   ShenandoahHeap *sh = ShenandoahHeap::heap();
 174   sh->do_evacuation();
 175 
 176   if (! ShenandoahConcurrentUpdateRefs) {
 177     assert(! ShenandoahConcurrentEvacuation, "turn off concurrent evacuation");
 178     sh->prepare_for_update_references();
 179     sh->update_references();
 180   }
 181 }
 182 /*
 183   VM_Operation::VMOp_Type VM_ShenandoahVerifyHeapAfterUpdateRefs::type() const {
 184   return VMOp_ShenandoahVerifyHeapAfterUpdateRefs;
 185   }
 186 
 187   const char* VM_ShenandoahVerifyHeapAfterUpdateRefs::name() const {
 188   return "Shenandoah verify heap after updating references";
 189   }
 190 
 191   void VM_ShenandoahVerifyHeapAfterUpdateRefs::doit() {
 192 
 193   ShenandoahHeap *sh = ShenandoahHeap::heap();
 194   sh->verify_heap_after_update_refs();
 195 
 196   }
 197 */
 198 VM_Operation::VMOp_Type VM_ShenandoahUpdateRootRefs::type() const {
 199   return VMOp_ShenandoahUpdateRootRefs;
 200 }
 201 
 202 const char* VM_ShenandoahUpdateRootRefs::name() const {
 203   return "Shenandoah update root references";
 204 }
 205 
 206 void VM_ShenandoahUpdateRootRefs::doit() {
 207   ShenandoahHeap *sh = ShenandoahHeap::heap();
 208   if (! sh->cancelled_concgc()) {
 209 
 210     if (ShenandoahGCVerbose)
 211       tty->print("vm_ShenandoahUpdateRootRefs\n");
 212 
 213 
 214     sh->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::final_uprefs);
 215 
 216     sh->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::update_roots);
 217 
 218     sh->update_roots();
 219 
 220     sh->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::update_roots);
 221 
 222     sh->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::final_uprefs);
 223   }
 224 
 225   sh->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::recycle_regions);
 226   sh->recycle_dirty_regions();
 227   sh->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::recycle_regions);
 228 
 229   if (ShenandoahVerify && ! sh->cancelled_concgc()) {
 230     sh->verify_heap_after_update_refs();
 231     sh->verify_regions_after_update_refs();
 232   }
 233 #ifdef ASSERT
 234   if (! ShenandoahVerify) {
 235     assert(sh->is_bitmap_clear(), "need cleared bitmap here");
 236   }
 237 #endif
 238 
 239 }
 240 
 241 VM_Operation::VMOp_Type VM_ShenandoahUpdateRefs::type() const {
 242   return VMOp_ShenandoahUpdateRefs;
 243 }
 244 
 245 const char* VM_ShenandoahUpdateRefs::name() const {
 246   return "Shenandoah update references";
 247 }
 248 
 249 void VM_ShenandoahUpdateRefs::doit() {
 250   ShenandoahHeap *sh = ShenandoahHeap::heap();
 251   if (!sh->cancelled_concgc()) {
 252 
 253     if (ShenandoahGCVerbose)
 254       tty->print("vm_ShenandoahUpdateRefs\n");
 255 
 256     sh->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::final_evac);
 257     sh->set_evacuation_in_progress(false);
 258     sh->prepare_for_update_references();
 259     assert(ShenandoahConcurrentUpdateRefs, "only do this when concurrent update references is turned on");
 260     sh->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::final_evac);
 261   }
 262 }