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