1 /* 2 * Copyright Amazon.com Inc. 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 27 #include "gc/shenandoah/heuristics/shenandoahYoungHeuristics.hpp" 28 #include "gc/shenandoah/shenandoahFreeSet.hpp" 29 #include "gc/shenandoah/shenandoahHeap.inline.hpp" 30 #include "gc/shenandoah/shenandoahMonitoringSupport.hpp" 31 #include "gc/shenandoah/shenandoahOldGC.hpp" 32 #include "gc/shenandoah/shenandoahOopClosures.inline.hpp" 33 #include "gc/shenandoah/shenandoahGeneration.hpp" 34 #include "gc/shenandoah/shenandoahOldGeneration.hpp" 35 #include "gc/shenandoah/shenandoahYoungGeneration.hpp" 36 #include "prims/jvmtiTagMap.hpp" 37 #include "utilities/events.hpp" 38 39 40 41 42 ShenandoahOldGC::ShenandoahOldGC(ShenandoahGeneration* generation, ShenandoahSharedFlag& allow_preemption) : 43 ShenandoahConcurrentGC(generation, false), _allow_preemption(allow_preemption) { 44 } 45 46 // Final mark for old-gen is different than for young or old, so we 47 // override the implementation. 48 void ShenandoahOldGC::op_final_mark() { 49 50 ShenandoahHeap* const heap = ShenandoahHeap::heap(); 51 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Should be at safepoint"); 52 assert(!heap->has_forwarded_objects(), "No forwarded objects on this path"); 53 54 if (ShenandoahVerify) { 55 heap->verifier()->verify_roots_no_forwarded(); 56 } 57 58 if (!heap->cancelled_gc()) { 59 assert(_mark.generation()->is_old(), "Generation of Old-Gen GC should be OLD"); 60 _mark.finish_mark(); 61 assert(!heap->cancelled_gc(), "STW mark cannot OOM"); 62 63 // Old collection is complete, the young generation no longer needs this 64 // reference to the old concurrent mark so clean it up. 65 heap->young_generation()->set_old_gen_task_queues(nullptr); 66 67 // We need to do this because weak root cleaning reports the number of dead handles 68 JvmtiTagMap::set_needs_cleaning(); 69 70 _generation->prepare_regions_and_collection_set(true); 71 72 heap->set_unload_classes(false); 73 heap->prepare_concurrent_roots(); 74 75 // Believe verification following old-gen concurrent mark needs to be different than verification following 76 // young-gen concurrent mark, so am commenting this out for now: 77 // if (ShenandoahVerify) { 78 // heap->verifier()->verify_after_concmark(); 79 // } 80 81 if (VerifyAfterGC) { 82 Universe::verify(); 83 } 84 } 85 } 86 87 bool ShenandoahOldGC::collect(GCCause::Cause cause) { 88 ShenandoahHeap* heap = ShenandoahHeap::heap(); 89 assert(!heap->doing_mixed_evacuations(), "Should not start an old gc with pending mixed evacuations"); 90 assert(!heap->is_prepare_for_old_mark_in_progress(), "Old regions need to be parseable during concurrent mark."); 91 92 // Enable preemption of old generation mark. 93 _allow_preemption.set(); 94 95 // Continue concurrent mark, do not reset regions, do not mark roots, do not collect $200. 96 entry_mark(); 97 98 // If we failed to unset the preemption flag, it means another thread has already unset it. 99 if (!_allow_preemption.try_unset()) { 100 // The regulator thread has unset the preemption guard. That thread will shortly cancel 101 // the gc, but the control thread is now racing it. Wait until this thread sees the 102 // cancellation. 103 while (!heap->cancelled_gc()) { 104 SpinPause(); 105 } 106 } 107 108 if (heap->cancelled_gc()) { 109 return false; 110 } 111 112 // Complete marking under STW 113 vmop_entry_final_mark(); 114 115 // We aren't dealing with old generation evacuation yet. Our heuristic 116 // should not have built a cset in final mark. 117 assert(!heap->is_evacuation_in_progress(), "Old gen evacuations are not supported"); 118 119 // Process weak roots that might still point to regions that would be broken by cleanup 120 if (heap->is_concurrent_weak_root_in_progress()) { 121 entry_weak_refs(); 122 entry_weak_roots(); 123 } 124 125 // Final mark might have reclaimed some immediate garbage, kick cleanup to reclaim 126 // the space. This would be the last action if there is nothing to evacuate. 127 entry_cleanup_early(); 128 129 { 130 ShenandoahHeapLocker locker(heap->lock()); 131 heap->free_set()->log_status(); 132 } 133 134 135 // TODO: Old marking doesn't support class unloading yet 136 // Perform concurrent class unloading 137 // if (heap->unload_classes() && 138 // heap->is_concurrent_weak_root_in_progress()) { 139 // entry_class_unloading(); 140 // } 141 142 143 assert(!heap->is_concurrent_strong_root_in_progress(), "No evacuations during old gc."); 144 145 // We must execute this vm operation if we completed final mark. We cannot 146 // return from here with weak roots in progress. This is not a valid gc state 147 // for any young collections (or allocation failures) that interrupt the old 148 // collection. 149 vmop_entry_final_roots(); 150 151 // We do not rebuild_free following increments of old marking because memory has not been reclaimed.. However, we may 152 // need to transfer memory to OLD in order to efficiently support the mixed evacuations that might immediately follow. 153 size_t allocation_runway = heap->young_heuristics()->bytes_of_allocation_runway_before_gc_trigger(0); 154 heap->adjust_generation_sizes_for_next_cycle(allocation_runway, 0, 0); 155 156 bool success; 157 size_t region_xfer; 158 const char* region_destination; 159 ShenandoahYoungGeneration* young_gen = heap->young_generation(); 160 ShenandoahGeneration* old_gen = heap->old_generation(); 161 { 162 ShenandoahHeapLocker locker(heap->lock()); 163 164 size_t old_region_surplus = heap->get_old_region_surplus(); 165 size_t old_region_deficit = heap->get_old_region_deficit(); 166 if (old_region_surplus) { 167 success = heap->generation_sizer()->transfer_to_young(old_region_surplus); 168 region_destination = "young"; 169 region_xfer = old_region_surplus; 170 } else if (old_region_deficit) { 171 success = heap->generation_sizer()->transfer_to_old(old_region_deficit); 172 region_destination = "old"; 173 region_xfer = old_region_deficit; 174 if (!success) { 175 ((ShenandoahOldHeuristics *) old_gen->heuristics())->trigger_cannot_expand(); 176 } 177 } else { 178 region_destination = "none"; 179 region_xfer = 0; 180 success = true; 181 } 182 heap->set_old_region_surplus(0); 183 heap->set_old_region_deficit(0); 184 } 185 186 // Report outside the heap lock 187 size_t young_available = young_gen->available(); 188 size_t old_available = old_gen->available(); 189 log_info(gc, ergo)("After old marking finished, %s " SIZE_FORMAT " regions to %s to prepare for next gc, old available: " 190 SIZE_FORMAT "%s, young_available: " SIZE_FORMAT "%s", 191 success? "successfully transferred": "failed to transfer", region_xfer, region_destination, 192 byte_size_in_proper_unit(old_available), proper_unit_for_byte_size(old_available), 193 byte_size_in_proper_unit(young_available), proper_unit_for_byte_size(young_available)); 194 return true; 195 }