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