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 #ifndef SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHOLDHEURISTICS_HPP 26 #define SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHOLDHEURISTICS_HPP 27 28 29 #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" 30 #include "gc/shenandoah/shenandoahGenerationalHeap.hpp" 31 32 class ShenandoahCollectionSet; 33 class ShenandoahHeapRegion; 34 class ShenandoahOldGeneration; 35 36 /* 37 * This heuristic is responsible for choosing a set of candidates for inclusion 38 * in mixed collections. These candidates are chosen when marking of the old 39 * generation is complete. Note that this list of candidates may live through 40 * several mixed collections. 41 * 42 * This heuristic is also responsible for triggering old collections. It has its 43 * own collection of triggers to decide whether to start an old collection. It does 44 * _not_ use any of the functionality from the adaptive heuristics for triggers. 45 * It also does not use any of the functionality from the heuristics base classes 46 * to choose the collection set. For these reasons, it does not extend from 47 * ShenandoahGenerationalHeuristics. 48 */ 49 class ShenandoahOldHeuristics : public ShenandoahHeuristics { 50 51 private: 52 53 static uint NOT_FOUND; 54 55 ShenandoahGenerationalHeap* _heap; 56 ShenandoahOldGeneration* _old_gen; 57 58 // After final marking of the old generation, this heuristic will select 59 // a set of candidate regions to be included in subsequent mixed collections. 60 // The regions are sorted into a `_region_data` array (declared in base 61 // class) in decreasing order of garbage. The heuristic will give priority 62 // to regions containing more garbage. 63 64 // The following members are used to keep track of which candidate regions 65 // have yet to be added to a mixed collection. There is also some special 66 // handling for pinned regions, described further below. 67 68 // Pinned regions may not be included in the collection set. Any old regions 69 // which were pinned at the time when old regions were added to the mixed 70 // collection will have been skipped. These regions are still contain garbage, 71 // so we want to include them at the start of the list of candidates for the 72 // _next_ mixed collection cycle. This variable is the index of the _first_ 73 // old region which is pinned when the mixed collection set is formed. 74 uint _first_pinned_candidate; 75 76 // This is the index of the last region which is above the garbage threshold. 77 // No regions after this will be considered for inclusion in a mixed collection 78 // set. 79 uint _last_old_collection_candidate; 80 81 // This index points to the first candidate in line to be added to the mixed 82 // collection set. It is updated as regions are added to the collection set. 83 uint _next_old_collection_candidate; 84 85 // This is the last index in the array of old regions which were active at 86 // the end of old final mark. 87 uint _last_old_region; 88 89 // How much live data must be evacuated from within the unprocessed mixed evacuation candidates? 90 size_t _live_bytes_in_unprocessed_candidates; 91 92 // Keep a pointer to our generation that we can use without down casting a protected member from the base class. 93 ShenandoahOldGeneration* _old_generation; 94 95 // Flags are set when promotion failure is detected (by gc thread), and cleared when 96 // old generation collection begins (by control thread). Flags are set and cleared at safepoints. 97 bool _cannot_expand_trigger; 98 bool _fragmentation_trigger; 99 bool _growth_trigger; 100 101 // Motivation for a fragmentation_trigger 102 double _fragmentation_density; 103 size_t _fragmentation_first_old_region; 104 size_t _fragmentation_last_old_region; 105 106 // Compare by live is used to prioritize compaction of old-gen regions. With old-gen compaction, the goal is 107 // to tightly pack long-lived objects into available regions. In most cases, there has not been an accumulation 108 // of garbage within old-gen regions. The more likely opportunity will be to combine multiple sparsely populated 109 // old-gen regions which may have been promoted in place into a smaller number of densely packed old-gen regions. 110 // This improves subsequent allocation efficiency and reduces the likelihood of allocation failure (including 111 // humongous allocation failure) due to fragmentation of the available old-gen allocation pool 112 static int compare_by_live(RegionData a, RegionData b); 113 114 static int compare_by_index(RegionData a, RegionData b); 115 116 inline void trigger_old_is_fragmented(double density, size_t first_old_index, size_t last_old_index) { 117 _fragmentation_trigger = true; 118 _fragmentation_density = density; 119 _fragmentation_first_old_region = first_old_index; 120 _fragmentation_last_old_region = last_old_index; 121 } 122 inline void trigger_old_has_grown() { _growth_trigger = true; } 123 124 void trigger_collection_if_fragmented(size_t first_old_region, size_t last_old_region, size_t old_region_count, size_t num_regions); 125 void trigger_collection_if_overgrown(); 126 127 protected: 128 void choose_collection_set_from_regiondata(ShenandoahCollectionSet* set, RegionData* data, size_t data_size, size_t free) override; 129 130 public: 131 explicit ShenandoahOldHeuristics(ShenandoahOldGeneration* generation, ShenandoahGenerationalHeap* gen_heap); 132 133 // Prepare for evacuation of old-gen regions by capturing the mark results of a recently completed concurrent mark pass. 134 void prepare_for_old_collections(); 135 136 // Return true iff the collection set is primed with at least one old-gen region. 137 bool prime_collection_set(ShenandoahCollectionSet* set); 138 139 // How many old-collection candidates have not yet been processed? 140 uint unprocessed_old_collection_candidates() const; 141 142 // How much live memory must be evacuated from within old-collection candidates that have not yet been processed? 143 size_t unprocessed_old_collection_candidates_live_memory() const; 144 145 void set_unprocessed_old_collection_candidates_live_memory(size_t initial_live); 146 147 void decrease_unprocessed_old_collection_candidates_live_memory(size_t evacuated_live); 148 149 // How many old or hidden collection candidates have not yet been processed? 150 uint last_old_collection_candidate_index() const; 151 152 // Return the next old-collection candidate in order of decreasing amounts of garbage. (We process most-garbage regions 153 // first.) This does not consume the candidate. If the candidate is selected for inclusion in a collection set, then 154 // the candidate is consumed by invoking consume_old_collection_candidate(). 155 ShenandoahHeapRegion* next_old_collection_candidate(); 156 157 // Adjust internal state to reflect that one fewer old-collection candidate remains to be processed. 158 void consume_old_collection_candidate(); 159 160 // Fill in buffer with all the old-collection regions that were identified at the end of the most recent old-gen 161 // mark to require their unmarked objects to be coalesced and filled. The buffer array must have at least 162 // last_old_region_index() entries, or memory may be corrupted when this function overwrites the 163 // end of the array. 164 unsigned int get_coalesce_and_fill_candidates(ShenandoahHeapRegion** buffer); 165 166 // True if there are old regions that need to be filled. 167 bool has_coalesce_and_fill_candidates() const { return coalesce_and_fill_candidates_count() > 0; } 168 169 // Return the number of old regions that need to be filled. 170 size_t coalesce_and_fill_candidates_count() const { return _last_old_region - _next_old_collection_candidate; } 171 172 // If a GLOBAL gc occurs, it will collect the entire heap which invalidates any collection candidates being 173 // held by this heuristic for supplying mixed collections. 174 void abandon_collection_candidates(); 175 176 void trigger_cannot_expand() { _cannot_expand_trigger = true; }; 177 178 inline void get_fragmentation_trigger_reason_for_log_message(double &density, size_t &first_index, size_t &last_index) { 179 density = _fragmentation_density; 180 first_index = _fragmentation_first_old_region; 181 last_index = _fragmentation_last_old_region; 182 } 183 184 void clear_triggers(); 185 186 void trigger_maybe(size_t first_old_region, size_t last_old_region, size_t old_region_count, size_t num_regions); 187 188 void record_cycle_end() override; 189 190 bool should_start_gc() override; 191 192 void record_success_concurrent() override; 193 194 void record_success_degenerated() override; 195 196 void record_success_full() override; 197 198 const char* name() override; 199 200 bool is_diagnostic() override; 201 202 bool is_experimental() override; 203 204 private: 205 void slide_pinned_regions_to_front(); 206 bool all_candidates_are_pinned(); 207 }; 208 209 #endif // SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHOLDHEURISTICS_HPP