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 // Set the fragmentation trigger if old-gen memory has become fragmented. 117 void set_trigger_if_old_is_fragmented(size_t first_old_region, size_t last_old_region, 118 size_t old_region_count, size_t num_regions); 119 120 // Set the overgrowth trigger if old-gen memory has grown beyond a particular threshold. 121 void set_trigger_if_old_is_overgrown(); 122 123 protected: 124 void choose_collection_set_from_regiondata(ShenandoahCollectionSet* set, RegionData* data, size_t data_size, size_t free) override; 125 126 public: 127 explicit ShenandoahOldHeuristics(ShenandoahOldGeneration* generation, ShenandoahGenerationalHeap* gen_heap); 128 129 // Prepare for evacuation of old-gen regions by capturing the mark results of a recently completed concurrent mark pass. 130 void prepare_for_old_collections(); 131 132 // Return true iff the collection set is primed with at least one old-gen region. 133 bool prime_collection_set(ShenandoahCollectionSet* set); 134 135 // How many old-collection candidates have not yet been processed? 136 uint unprocessed_old_collection_candidates() const; 137 138 // How much live memory must be evacuated from within old-collection candidates that have not yet been processed? 139 size_t unprocessed_old_collection_candidates_live_memory() const; 140 141 void set_unprocessed_old_collection_candidates_live_memory(size_t initial_live); 142 143 void decrease_unprocessed_old_collection_candidates_live_memory(size_t evacuated_live); 144 145 // How many old or hidden collection candidates have not yet been processed? 146 uint last_old_collection_candidate_index() const; 147 148 // Return the next old-collection candidate in order of decreasing amounts of garbage. (We process most-garbage regions 149 // first.) This does not consume the candidate. If the candidate is selected for inclusion in a collection set, then 150 // the candidate is consumed by invoking consume_old_collection_candidate(). 151 ShenandoahHeapRegion* next_old_collection_candidate(); 152 153 // Adjust internal state to reflect that one fewer old-collection candidate remains to be processed. 154 void consume_old_collection_candidate(); 155 156 // Fill in buffer with all the old-collection regions that were identified at the end of the most recent old-gen 157 // mark to require their unmarked objects to be coalesced and filled. The buffer array must have at least 158 // last_old_region_index() entries, or memory may be corrupted when this function overwrites the 159 // end of the array. 160 unsigned int get_coalesce_and_fill_candidates(ShenandoahHeapRegion** buffer); 161 162 // True if there are old regions that need to be filled. 163 bool has_coalesce_and_fill_candidates() const { return coalesce_and_fill_candidates_count() > 0; } 164 165 // Return the number of old regions that need to be filled. 166 size_t coalesce_and_fill_candidates_count() const { return _last_old_region - _next_old_collection_candidate; } 167 168 // If a GLOBAL gc occurs, it will collect the entire heap which invalidates any collection candidates being 169 // held by this heuristic for supplying mixed collections. 170 void abandon_collection_candidates(); 171 172 void trigger_cannot_expand() { _cannot_expand_trigger = true; }; 173 174 inline void get_fragmentation_trigger_reason_for_log_message(double &density, size_t &first_index, size_t &last_index) { 175 density = _fragmentation_density; 176 first_index = _fragmentation_first_old_region; 177 last_index = _fragmentation_last_old_region; 178 } 179 180 void clear_triggers(); 181 182 // Check whether conditions merit the start of old GC. Set appropriate trigger if so. 183 void evaluate_triggers(size_t first_old_region, size_t last_old_region, size_t old_region_count, size_t num_regions); 184 185 void record_cycle_end() override; 186 187 bool should_start_gc() override; 188 189 void record_success_concurrent() override; 190 191 void record_success_degenerated() override; 192 193 void record_success_full() override; 194 195 const char* name() override; 196 197 bool is_diagnostic() override; 198 199 bool is_experimental() override; 200 201 private: 202 void slide_pinned_regions_to_front(); 203 bool all_candidates_are_pinned(); 204 }; 205 206 #endif // SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHOLDHEURISTICS_HPP