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 #include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
27 #include "gc/shenandoah/shenandoahCollectionSetPreselector.hpp"
28 #include "gc/shenandoah/shenandoahFreeSet.hpp"
29 #include "gc/shenandoah/shenandoahGeneration.hpp"
30 #include "gc/shenandoah/shenandoahGenerationalHeap.inline.hpp"
31 #include "gc/shenandoah/shenandoahHeapRegionClosures.hpp"
32 #include "gc/shenandoah/shenandoahOldGeneration.hpp"
33 #include "gc/shenandoah/shenandoahReferenceProcessor.hpp"
34 #include "gc/shenandoah/shenandoahScanRemembered.inline.hpp"
35 #include "gc/shenandoah/shenandoahTaskqueue.inline.hpp"
36 #include "gc/shenandoah/shenandoahUtils.hpp"
37 #include "gc/shenandoah/shenandoahVerifier.hpp"
38 #include "gc/shenandoah/shenandoahYoungGeneration.hpp"
39 #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
40
41 #include "utilities/quickSort.hpp"
42
43 template <bool PREPARE_FOR_CURRENT_CYCLE, bool FULL_GC = false>
44 class ShenandoahResetBitmapClosure final : public ShenandoahHeapRegionClosure {
45 private:
46 ShenandoahHeap* _heap;
47 ShenandoahMarkingContext* _ctx;
48
49 public:
50 explicit ShenandoahResetBitmapClosure() :
51 ShenandoahHeapRegionClosure(), _heap(ShenandoahHeap::heap()), _ctx(_heap->marking_context()) {}
52
53 void heap_region_do(ShenandoahHeapRegion* region) override {
54 assert(!_heap->is_uncommit_in_progress(), "Cannot uncommit bitmaps while resetting them.");
55 if (PREPARE_FOR_CURRENT_CYCLE) {
56 if (region->need_bitmap_reset() && _heap->is_bitmap_slice_committed(region)) {
57 _ctx->clear_bitmap(region);
58 } else {
59 region->set_needs_bitmap_reset();
60 }
61 // Capture Top At Mark Start for this generation.
62 if (FULL_GC || region->is_active()) {
63 // Reset live data and set TAMS optimistically. We would recheck these under the pause
64 // anyway to capture any updates that happened since now.
65 _ctx->capture_top_at_mark_start(region);
66 region->clear_live_data();
67 }
68 } else {
69 if (_heap->is_bitmap_slice_committed(region)) {
70 _ctx->clear_bitmap(region);
71 region->unset_needs_bitmap_reset();
72 } else {
73 region->set_needs_bitmap_reset();
74 }
75 }
76 }
77
78 bool is_thread_safe() override { return true; }
79 };
80
81 // Copy the write-version of the card-table into the read-version, clearing the
82 // write-copy.
83 class ShenandoahMergeWriteTable: public ShenandoahHeapRegionClosure {
84 private:
85 ShenandoahScanRemembered* _scanner;
86 public:
87 ShenandoahMergeWriteTable(ShenandoahScanRemembered* scanner) : _scanner(scanner) {}
88
89 void heap_region_do(ShenandoahHeapRegion* r) override {
90 assert(r->is_old(), "Don't waste time doing this for non-old regions");
91 _scanner->merge_write_table(r->bottom(), ShenandoahHeapRegion::region_size_words());
92 }
93
94 bool is_thread_safe() override {
95 return true;
96 }
97 };
98
99 // Add [TAMS, top) volume over young regions. Used to correct age 0 cohort census
100 // for adaptive tenuring when census is taken during marking.
101 // In non-product builds, for the purposes of verification, we also collect the total
102 // live objects in young regions as well.
103 class ShenandoahUpdateCensusZeroCohortClosure : public ShenandoahHeapRegionClosure {
104 private:
105 ShenandoahMarkingContext* const _ctx;
106 // Population size units are words (not bytes)
107 size_t _age0_pop; // running tally of age0 population size
108 size_t _total_pop; // total live population size
109 public:
110 explicit ShenandoahUpdateCensusZeroCohortClosure(ShenandoahMarkingContext* ctx)
111 : _ctx(ctx), _age0_pop(0), _total_pop(0) {}
112
113 void heap_region_do(ShenandoahHeapRegion* r) override {
114 if (_ctx != nullptr && r->is_active()) {
115 assert(r->is_young(), "Young regions only");
116 HeapWord* tams = _ctx->top_at_mark_start(r);
117 HeapWord* top = r->top();
118 if (top > tams) {
119 _age0_pop += pointer_delta(top, tams);
120 }
121 // TODO: check significance of _ctx != nullptr above, can that
122 // spoof _total_pop in some corner cases?
123 NOT_PRODUCT(_total_pop += r->get_live_data_words();)
124 }
125 }
126
127 size_t get_age0_population() const { return _age0_pop; }
128 size_t get_total_population() const { return _total_pop; }
129 };
130
131 void ShenandoahGeneration::confirm_heuristics_mode() {
132 if (_heuristics->is_diagnostic() && !UnlockDiagnosticVMOptions) {
133 vm_exit_during_initialization(
134 err_msg("Heuristics \"%s\" is diagnostic, and must be enabled via -XX:+UnlockDiagnosticVMOptions.",
135 _heuristics->name()));
136 }
137 if (_heuristics->is_experimental() && !UnlockExperimentalVMOptions) {
138 vm_exit_during_initialization(
139 err_msg("Heuristics \"%s\" is experimental, and must be enabled via -XX:+UnlockExperimentalVMOptions.",
140 _heuristics->name()));
141 }
142 }
143
144 ShenandoahHeuristics* ShenandoahGeneration::initialize_heuristics(ShenandoahMode* gc_mode) {
145 _heuristics = gc_mode->initialize_heuristics(this);
146 _heuristics->set_guaranteed_gc_interval(ShenandoahGuaranteedGCInterval);
147 confirm_heuristics_mode();
148 return _heuristics;
149 }
150
151 size_t ShenandoahGeneration::bytes_allocated_since_gc_start() const {
152 return Atomic::load(&_bytes_allocated_since_gc_start);
153 }
154
155 void ShenandoahGeneration::reset_bytes_allocated_since_gc_start() {
156 Atomic::store(&_bytes_allocated_since_gc_start, (size_t)0);
157 }
158
159 void ShenandoahGeneration::increase_allocated(size_t bytes) {
160 Atomic::add(&_bytes_allocated_since_gc_start, bytes, memory_order_relaxed);
161 }
162
163 void ShenandoahGeneration::set_evacuation_reserve(size_t new_val) {
164 _evacuation_reserve = new_val;
165 }
166
167 size_t ShenandoahGeneration::get_evacuation_reserve() const {
168 return _evacuation_reserve;
169 }
170
171 void ShenandoahGeneration::augment_evacuation_reserve(size_t increment) {
172 _evacuation_reserve += increment;
173 }
174
175 void ShenandoahGeneration::log_status(const char *msg) const {
176 typedef LogTarget(Info, gc, ergo) LogGcInfo;
177
178 if (!LogGcInfo::is_enabled()) {
179 return;
180 }
181
182 // Not under a lock here, so read each of these once to make sure
183 // byte size in proper unit and proper unit for byte size are consistent.
184 const size_t v_used = used();
185 const size_t v_used_regions = used_regions_size();
186 const size_t v_soft_max_capacity = ShenandoahHeap::heap()->soft_max_capacity();
187 const size_t v_max_capacity = max_capacity();
188 const size_t v_available = available();
189 const size_t v_humongous_waste = get_humongous_waste();
190
191 const LogGcInfo target;
192 LogStream ls(target);
193 ls.print("%s: ", msg);
194 if (_type != NON_GEN) {
195 ls.print("%s generation ", name());
196 }
197
198 ls.print_cr("used: " PROPERFMT ", used regions: " PROPERFMT ", humongous waste: " PROPERFMT
199 ", soft capacity: " PROPERFMT ", max capacity: " PROPERFMT ", available: " PROPERFMT,
200 PROPERFMTARGS(v_used), PROPERFMTARGS(v_used_regions), PROPERFMTARGS(v_humongous_waste),
201 PROPERFMTARGS(v_soft_max_capacity), PROPERFMTARGS(v_max_capacity), PROPERFMTARGS(v_available));
202 }
203
204 template <bool PREPARE_FOR_CURRENT_CYCLE, bool FULL_GC>
205 void ShenandoahGeneration::reset_mark_bitmap() {
206 ShenandoahHeap* heap = ShenandoahHeap::heap();
207 heap->assert_gc_workers(heap->workers()->active_workers());
208
209 set_mark_incomplete();
210
211 ShenandoahResetBitmapClosure<PREPARE_FOR_CURRENT_CYCLE, FULL_GC> closure;
212 parallel_heap_region_iterate_free(&closure);
213 }
214 // Explicit specializations
215 template void ShenandoahGeneration::reset_mark_bitmap<true, false>();
216 template void ShenandoahGeneration::reset_mark_bitmap<true, true>();
217 template void ShenandoahGeneration::reset_mark_bitmap<false, false>();
218
219 // Swap the read and write card table pointers prior to the next remset scan.
220 // This avoids the need to synchronize reads of the table by the GC workers
221 // doing remset scanning, on the one hand, with the dirtying of the table by
222 // mutators on the other.
223 void ShenandoahGeneration::swap_card_tables() {
224 // Must be sure that marking is complete before we swap remembered set.
225 ShenandoahGenerationalHeap* heap = ShenandoahGenerationalHeap::heap();
226 heap->assert_gc_workers(heap->workers()->active_workers());
227 shenandoah_assert_safepoint();
228
229 ShenandoahOldGeneration* old_generation = heap->old_generation();
230 old_generation->card_scan()->swap_card_tables();
231 }
232
233 // Copy the write-version of the card-table into the read-version, clearing the
234 // write-version. The work is done at a safepoint and in parallel by the GC
235 // worker threads.
236 void ShenandoahGeneration::merge_write_table() {
237 // This should only happen for degenerated cycles
238 ShenandoahGenerationalHeap* heap = ShenandoahGenerationalHeap::heap();
239 heap->assert_gc_workers(heap->workers()->active_workers());
240 shenandoah_assert_safepoint();
241
242 ShenandoahOldGeneration* old_generation = heap->old_generation();
243 ShenandoahMergeWriteTable task(old_generation->card_scan());
244 old_generation->parallel_heap_region_iterate(&task);
245 }
246
247 void ShenandoahGeneration::prepare_gc() {
248 reset_mark_bitmap<true>();
249 }
250
251 void ShenandoahGeneration::parallel_heap_region_iterate_free(ShenandoahHeapRegionClosure* cl) {
252 ShenandoahHeap::heap()->parallel_heap_region_iterate(cl);
253 }
254
255 void ShenandoahGeneration::compute_evacuation_budgets(ShenandoahHeap* const heap) {
256 shenandoah_assert_generational();
257
258 ShenandoahOldGeneration* const old_generation = heap->old_generation();
259 ShenandoahYoungGeneration* const young_generation = heap->young_generation();
260
261 // During initialization and phase changes, it is more likely that fewer objects die young and old-gen
262 // memory is not yet full (or is in the process of being replaced). During these times especially, it
263 // is beneficial to loan memory from old-gen to young-gen during the evacuation and update-refs phases
264 // of execution.
265
266 // Calculate EvacuationReserve before PromotionReserve. Evacuation is more critical than promotion.
267 // If we cannot evacuate old-gen, we will not be able to reclaim old-gen memory. Promotions are less
268 // critical. If we cannot promote, there may be degradation of young-gen memory because old objects
269 // accumulate there until they can be promoted. This increases the young-gen marking and evacuation work.
270
271 // First priority is to reclaim the easy garbage out of young-gen.
272
273 // maximum_young_evacuation_reserve is upper bound on memory to be evacuated out of young
274 const size_t maximum_young_evacuation_reserve = (young_generation->max_capacity() * ShenandoahEvacReserve) / 100;
275 const size_t young_evacuation_reserve = MIN2(maximum_young_evacuation_reserve, young_generation->available_with_reserve());
276
277 // maximum_old_evacuation_reserve is an upper bound on memory evacuated from old and evacuated to old (promoted),
278 // clamped by the old generation space available.
279 //
280 // Here's the algebra.
281 // Let SOEP = ShenandoahOldEvacRatioPercent,
282 // OE = old evac,
283 // YE = young evac, and
284 // TE = total evac = OE + YE
285 // By definition:
286 // SOEP/100 = OE/TE
287 // = OE/(OE+YE)
288 // => SOEP/(100-SOEP) = OE/((OE+YE)-OE) // componendo-dividendo: If a/b = c/d, then a/(b-a) = c/(d-c)
289 // = OE/YE
290 // => OE = YE*SOEP/(100-SOEP)
291
292 // We have to be careful in the event that SOEP is set to 100 by the user.
293 assert(ShenandoahOldEvacRatioPercent <= 100, "Error");
294 const size_t old_available = old_generation->available();
295 const size_t maximum_old_evacuation_reserve = (ShenandoahOldEvacRatioPercent == 100) ?
296 old_available : MIN2((maximum_young_evacuation_reserve * ShenandoahOldEvacRatioPercent) / (100 - ShenandoahOldEvacRatioPercent),
297 old_available);
298
299
300 // Second priority is to reclaim garbage out of old-gen if there are old-gen collection candidates. Third priority
301 // is to promote as much as we have room to promote. However, if old-gen memory is in short supply, this means young
302 // GC is operating under "duress" and was unable to transfer the memory that we would normally expect. In this case,
303 // old-gen will refrain from compacting itself in order to allow a quicker young-gen cycle (by avoiding the update-refs
304 // through ALL of old-gen). If there is some memory available in old-gen, we will use this for promotions as promotions
305 // do not add to the update-refs burden of GC.
306
307 size_t old_evacuation_reserve, old_promo_reserve;
308 if (is_global()) {
309 // Global GC is typically triggered by user invocation of System.gc(), and typically indicates that there is lots
310 // of garbage to be reclaimed because we are starting a new phase of execution. Marking for global GC may take
311 // significantly longer than typical young marking because we must mark through all old objects. To expedite
312 // evacuation and update-refs, we give emphasis to reclaiming garbage first, wherever that garbage is found.
313 // Global GC will adjust generation sizes to accommodate the collection set it chooses.
314
315 // Set old_promo_reserve to enforce that no regions are preselected for promotion. Such regions typically
316 // have relatively high memory utilization. We still call select_aged_regions() because this will prepare for
317 // promotions in place, if relevant.
318 old_promo_reserve = 0;
319
320 // Dedicate all available old memory to old_evacuation reserve. This may be small, because old-gen is only
321 // expanded based on an existing mixed evacuation workload at the end of the previous GC cycle. We'll expand
322 // the budget for evacuation of old during GLOBAL cset selection.
323 old_evacuation_reserve = maximum_old_evacuation_reserve;
324 } else if (old_generation->has_unprocessed_collection_candidates()) {
325 // We reserved all old-gen memory at end of previous GC to hold anticipated evacuations to old-gen. If this is
326 // mixed evacuation, reserve all of this memory for compaction of old-gen and do not promote. Prioritize compaction
327 // over promotion in order to defragment OLD so that it will be better prepared to efficiently receive promoted memory.
328 old_evacuation_reserve = maximum_old_evacuation_reserve;
329 old_promo_reserve = 0;
330 } else {
331 // Make all old-evacuation memory for promotion, but if we can't use it all for promotion, we'll allow some evacuation.
332 old_evacuation_reserve = 0;
333 old_promo_reserve = maximum_old_evacuation_reserve;
334 }
335 assert(old_evacuation_reserve <= old_available, "Error");
336
337 // We see too many old-evacuation failures if we force ourselves to evacuate into regions that are not initially empty.
338 // So we limit the old-evacuation reserve to unfragmented memory. Even so, old-evacuation is free to fill in nooks and
339 // crannies within existing partially used regions and it generally tries to do so.
340 const size_t old_free_unfragmented = old_generation->free_unaffiliated_regions() * ShenandoahHeapRegion::region_size_bytes();
341 if (old_evacuation_reserve > old_free_unfragmented) {
342 const size_t delta = old_evacuation_reserve - old_free_unfragmented;
343 old_evacuation_reserve -= delta;
344 // Let promo consume fragments of old-gen memory if not global
345 if (!is_global()) {
346 old_promo_reserve += delta;
347 }
348 }
349
350 // Preselect regions for promotion by evacuation (obtaining the live data to seed promoted_reserve),
351 // and identify regions that will promote in place. These use the tenuring threshold.
352 const size_t consumed_by_advance_promotion = select_aged_regions(old_promo_reserve);
353 assert(consumed_by_advance_promotion <= maximum_old_evacuation_reserve, "Cannot promote more than available old-gen memory");
354
355 // Note that unused old_promo_reserve might not be entirely consumed_by_advance_promotion. Do not transfer this
356 // to old_evacuation_reserve because this memory is likely very fragmented, and we do not want to increase the likelihood
357 // of old evacuation failure.
358 young_generation->set_evacuation_reserve(young_evacuation_reserve);
359 old_generation->set_evacuation_reserve(old_evacuation_reserve);
360 old_generation->set_promoted_reserve(consumed_by_advance_promotion);
361
362 // There is no need to expand OLD because all memory used here was set aside at end of previous GC, except in the
363 // case of a GLOBAL gc. During choose_collection_set() of GLOBAL, old will be expanded on demand.
364 }
365
366 // Having chosen the collection set, adjust the budgets for generational mode based on its composition. Note
367 // that young_generation->available() now knows about recently discovered immediate garbage.
368 //
369 void ShenandoahGeneration::adjust_evacuation_budgets(ShenandoahHeap* const heap, ShenandoahCollectionSet* const collection_set) {
370 shenandoah_assert_generational();
371 // We may find that old_evacuation_reserve and/or loaned_for_young_evacuation are not fully consumed, in which case we may
372 // be able to increase regions_available_to_loan
373
374 // The role of adjust_evacuation_budgets() is to compute the correct value of regions_available_to_loan and to make
375 // effective use of this memory, including the remnant memory within these regions that may result from rounding loan to
376 // integral number of regions. Excess memory that is available to be loaned is applied to an allocation supplement,
377 // which allows mutators to allocate memory beyond the current capacity of young-gen on the promise that the loan
378 // will be repaid as soon as we finish updating references for the recently evacuated collection set.
379
380 // We cannot recalculate regions_available_to_loan by simply dividing old_generation->available() by region_size_bytes
381 // because the available memory may be distributed between many partially occupied regions that are already holding old-gen
382 // objects. Memory in partially occupied regions is not "available" to be loaned. Note that an increase in old-gen
383 // available that results from a decrease in memory consumed by old evacuation is not necessarily available to be loaned
384 // to young-gen.
385
386 size_t region_size_bytes = ShenandoahHeapRegion::region_size_bytes();
387 ShenandoahOldGeneration* const old_generation = heap->old_generation();
388 ShenandoahYoungGeneration* const young_generation = heap->young_generation();
389
390 size_t old_evacuated = collection_set->get_old_bytes_reserved_for_evacuation();
391 size_t old_evacuated_committed = (size_t) (ShenandoahOldEvacWaste * double(old_evacuated));
392 size_t old_evacuation_reserve = old_generation->get_evacuation_reserve();
393
394 if (old_evacuated_committed > old_evacuation_reserve) {
395 // This should only happen due to round-off errors when enforcing ShenandoahOldEvacWaste
396 assert(old_evacuated_committed <= (33 * old_evacuation_reserve) / 32,
397 "Round-off errors should be less than 3.125%%, committed: " SIZE_FORMAT ", reserved: " SIZE_FORMAT,
398 old_evacuated_committed, old_evacuation_reserve);
399 old_evacuated_committed = old_evacuation_reserve;
400 // Leave old_evac_reserve as previously configured
401 } else if (old_evacuated_committed < old_evacuation_reserve) {
402 // This happens if the old-gen collection consumes less than full budget.
403 old_evacuation_reserve = old_evacuated_committed;
404 old_generation->set_evacuation_reserve(old_evacuation_reserve);
405 }
406
407 size_t young_advance_promoted = collection_set->get_young_bytes_to_be_promoted();
408 size_t young_advance_promoted_reserve_used = (size_t) (ShenandoahPromoEvacWaste * double(young_advance_promoted));
409
410 size_t young_evacuated = collection_set->get_young_bytes_reserved_for_evacuation();
411 size_t young_evacuated_reserve_used = (size_t) (ShenandoahEvacWaste * double(young_evacuated));
412
413 size_t total_young_available = young_generation->available_with_reserve();
414 assert(young_evacuated_reserve_used <= total_young_available, "Cannot evacuate more than is available in young");
415 young_generation->set_evacuation_reserve(young_evacuated_reserve_used);
416
417 size_t old_available = old_generation->available();
418 // Now that we've established the collection set, we know how much memory is really required by old-gen for evacuation
419 // and promotion reserves. Try shrinking OLD now in case that gives us a bit more runway for mutator allocations during
420 // evac and update phases.
421 size_t old_consumed = old_evacuated_committed + young_advance_promoted_reserve_used;
422
423 if (old_available < old_consumed) {
424 // This can happen due to round-off errors when adding the results of truncated integer arithmetic.
425 // We've already truncated old_evacuated_committed. Truncate young_advance_promoted_reserve_used here.
426 assert(young_advance_promoted_reserve_used <= (33 * (old_available - old_evacuated_committed)) / 32,
427 "Round-off errors should be less than 3.125%%, committed: " SIZE_FORMAT ", reserved: " SIZE_FORMAT,
428 young_advance_promoted_reserve_used, old_available - old_evacuated_committed);
429 young_advance_promoted_reserve_used = old_available - old_evacuated_committed;
430 old_consumed = old_evacuated_committed + young_advance_promoted_reserve_used;
431 }
432
433 assert(old_available >= old_consumed, "Cannot consume (" SIZE_FORMAT ") more than is available (" SIZE_FORMAT ")",
434 old_consumed, old_available);
435 size_t excess_old = old_available - old_consumed;
436 size_t unaffiliated_old_regions = old_generation->free_unaffiliated_regions();
437 size_t unaffiliated_old = unaffiliated_old_regions * region_size_bytes;
438 assert(old_available >= unaffiliated_old, "Unaffiliated old is a subset of old available");
439
440 // Make sure old_evac_committed is unaffiliated
441 if (old_evacuated_committed > 0) {
442 if (unaffiliated_old > old_evacuated_committed) {
443 size_t giveaway = unaffiliated_old - old_evacuated_committed;
444 size_t giveaway_regions = giveaway / region_size_bytes; // round down
445 if (giveaway_regions > 0) {
446 excess_old = MIN2(excess_old, giveaway_regions * region_size_bytes);
447 } else {
448 excess_old = 0;
449 }
450 } else {
451 excess_old = 0;
452 }
453 }
454
455 // If we find that OLD has excess regions, give them back to YOUNG now to reduce likelihood we run out of allocation
456 // runway during evacuation and update-refs.
457 size_t regions_to_xfer = 0;
458 if (excess_old > unaffiliated_old) {
459 // we can give back unaffiliated_old (all of unaffiliated is excess)
460 if (unaffiliated_old_regions > 0) {
461 regions_to_xfer = unaffiliated_old_regions;
462 }
463 } else if (unaffiliated_old_regions > 0) {
464 // excess_old < unaffiliated old: we can give back MIN(excess_old/region_size_bytes, unaffiliated_old_regions)
465 size_t excess_regions = excess_old / region_size_bytes;
466 regions_to_xfer = MIN2(excess_regions, unaffiliated_old_regions);
467 }
468
469 if (regions_to_xfer > 0) {
470 bool result = ShenandoahGenerationalHeap::cast(heap)->generation_sizer()->transfer_to_young(regions_to_xfer);
471 assert(excess_old >= regions_to_xfer * region_size_bytes,
472 "Cannot transfer (" SIZE_FORMAT ", " SIZE_FORMAT ") more than excess old (" SIZE_FORMAT ")",
473 regions_to_xfer, region_size_bytes, excess_old);
474 excess_old -= regions_to_xfer * region_size_bytes;
475 log_debug(gc, ergo)("%s transferred " SIZE_FORMAT " excess regions to young before start of evacuation",
476 result? "Successfully": "Unsuccessfully", regions_to_xfer);
477 }
478
479 // Add in the excess_old memory to hold unanticipated promotions, if any. If there are more unanticipated
480 // promotions than fit in reserved memory, they will be deferred until a future GC pass.
481 size_t total_promotion_reserve = young_advance_promoted_reserve_used + excess_old;
482 old_generation->set_promoted_reserve(total_promotion_reserve);
483 old_generation->reset_promoted_expended();
484 }
485
486 typedef struct {
487 ShenandoahHeapRegion* _region;
488 size_t _live_data;
489 } AgedRegionData;
490
491 static int compare_by_aged_live(AgedRegionData a, AgedRegionData b) {
492 if (a._live_data < b._live_data)
493 return -1;
494 else if (a._live_data > b._live_data)
495 return 1;
496 else return 0;
497 }
498
499 inline void assert_no_in_place_promotions() {
500 #ifdef ASSERT
501 class ShenandoahNoInPlacePromotions : public ShenandoahHeapRegionClosure {
502 public:
503 void heap_region_do(ShenandoahHeapRegion *r) override {
504 assert(r->get_top_before_promote() == nullptr,
505 "Region " SIZE_FORMAT " should not be ready for in-place promotion", r->index());
506 }
507 } cl;
508 ShenandoahHeap::heap()->heap_region_iterate(&cl);
509 #endif
510 }
511
512 // Preselect for inclusion into the collection set regions whose age is at or above tenure age which contain more than
513 // ShenandoahOldGarbageThreshold amounts of garbage. We identify these regions by setting the appropriate entry of
514 // the collection set's preselected regions array to true. All entries are initialized to false before calling this
515 // function.
516 //
517 // During the subsequent selection of the collection set, we give priority to these promotion set candidates.
518 // Without this prioritization, we found that the aged regions tend to be ignored because they typically have
519 // much less garbage and much more live data than the recently allocated "eden" regions. When aged regions are
520 // repeatedly excluded from the collection set, the amount of live memory within the young generation tends to
521 // accumulate and this has the undesirable side effect of causing young-generation collections to require much more
522 // CPU and wall-clock time.
523 //
524 // A second benefit of treating aged regions differently than other regions during collection set selection is
525 // that this allows us to more accurately budget memory to hold the results of evacuation. Memory for evacuation
526 // of aged regions must be reserved in the old generation. Memory for evacuation of all other regions must be
527 // reserved in the young generation.
528 size_t ShenandoahGeneration::select_aged_regions(size_t old_available) {
529
530 // There should be no regions configured for subsequent in-place-promotions carried over from the previous cycle.
531 assert_no_in_place_promotions();
532
533 auto const heap = ShenandoahGenerationalHeap::heap();
534 bool* const candidate_regions_for_promotion_by_copy = heap->collection_set()->preselected_regions();
535 ShenandoahMarkingContext* const ctx = heap->marking_context();
536
537 const size_t old_garbage_threshold = (ShenandoahHeapRegion::region_size_bytes() * ShenandoahOldGarbageThreshold) / 100;
538
539 size_t old_consumed = 0;
540 size_t promo_potential = 0;
541 size_t candidates = 0;
542
543 // Tracks the padding of space above top in regions eligible for promotion in place
544 size_t promote_in_place_pad = 0;
545
546 // Sort the promotion-eligible regions in order of increasing live-data-bytes so that we can first reclaim regions that require
547 // less evacuation effort. This prioritizes garbage first, expanding the allocation pool early before we reclaim regions that
548 // have more live data.
549 const size_t num_regions = heap->num_regions();
550
551 ResourceMark rm;
552 AgedRegionData* sorted_regions = NEW_RESOURCE_ARRAY(AgedRegionData, num_regions);
553
554 for (size_t i = 0; i < num_regions; i++) {
555 ShenandoahHeapRegion* const r = heap->get_region(i);
556 if (r->is_empty() || !r->has_live() || !r->is_young() || !r->is_regular()) {
557 // skip over regions that aren't regular young with some live data
558 continue;
559 }
560 if (heap->is_tenurable(r)) {
561 if ((r->garbage() < old_garbage_threshold)) {
562 // This tenure-worthy region has too little garbage, so we do not want to expend the copying effort to
563 // reclaim the garbage; instead this region may be eligible for promotion-in-place to the
564 // old generation.
565 HeapWord* tams = ctx->top_at_mark_start(r);
566 HeapWord* original_top = r->top();
567 if (!heap->is_concurrent_old_mark_in_progress() && tams == original_top) {
568 // No allocations from this region have been made during concurrent mark. It meets all the criteria
569 // for in-place-promotion. Though we only need the value of top when we fill the end of the region,
570 // we use this field to indicate that this region should be promoted in place during the evacuation
571 // phase.
572 r->save_top_before_promote();
573
574 size_t remnant_size = r->free() / HeapWordSize;
575 if (remnant_size > ShenandoahHeap::min_fill_size()) {
576 ShenandoahHeap::fill_with_object(original_top, remnant_size);
577 // Fill the remnant memory within this region to assure no allocations prior to promote in place. Otherwise,
578 // newly allocated objects will not be parsable when promote in place tries to register them. Furthermore, any
579 // new allocations would not necessarily be eligible for promotion. This addresses both issues.
580 r->set_top(r->end());
581 promote_in_place_pad += remnant_size * HeapWordSize;
582 } else {
583 // Since the remnant is so small that it cannot be filled, we don't have to worry about any accidental
584 // allocations occurring within this region before the region is promoted in place.
585 }
586 }
587 // Else, we do not promote this region (either in place or by copy) because it has received new allocations.
588
589 // During evacuation, we exclude from promotion regions for which age > tenure threshold, garbage < garbage-threshold,
590 // and get_top_before_promote() != tams
591 } else {
592 // Record this promotion-eligible candidate region. After sorting and selecting the best candidates below,
593 // we may still decide to exclude this promotion-eligible region from the current collection set. If this
594 // happens, we will consider this region as part of the anticipated promotion potential for the next GC
595 // pass; see further below.
596 sorted_regions[candidates]._region = r;
597 sorted_regions[candidates++]._live_data = r->get_live_data_bytes();
598 }
599 } else {
600 // We only evacuate & promote objects from regular regions whose garbage() is above old-garbage-threshold.
601 // Objects in tenure-worthy regions with less garbage are promoted in place. These take a different path to
602 // old-gen. Regions excluded from promotion because their garbage content is too low (causing us to anticipate that
603 // the region would be promoted in place) may be eligible for evacuation promotion by the time promotion takes
604 // place during a subsequent GC pass because more garbage is found within the region between now and then. This
605 // should not happen if we are properly adapting the tenure age. The theory behind adaptive tenuring threshold
606 // is to choose the youngest age that demonstrates no "significant" further loss of population since the previous
607 // age. If not this, we expect the tenure age to demonstrate linear population decay for at least two population
608 // samples, whereas we expect to observe exponential population decay for ages younger than the tenure age.
609 //
610 // In the case that certain regions which were anticipated to be promoted in place need to be promoted by
611 // evacuation, it may be the case that there is not sufficient reserve within old-gen to hold evacuation of
612 // these regions. The likely outcome is that these regions will not be selected for evacuation or promotion
613 // in the current cycle and we will anticipate that they will be promoted in the next cycle. This will cause
614 // us to reserve more old-gen memory so that these objects can be promoted in the subsequent cycle.
615 if (heap->is_aging_cycle() && heap->age_census()->is_tenurable(r->age() + 1)) {
616 if (r->garbage() >= old_garbage_threshold) {
617 promo_potential += r->get_live_data_bytes();
618 }
619 }
620 }
621 // Note that we keep going even if one region is excluded from selection.
622 // Subsequent regions may be selected if they have smaller live data.
623 }
624 // Sort in increasing order according to live data bytes. Note that candidates represents the number of regions
625 // that qualify to be promoted by evacuation.
626 if (candidates > 0) {
627 size_t selected_regions = 0;
628 size_t selected_live = 0;
629 QuickSort::sort<AgedRegionData>(sorted_regions, candidates, compare_by_aged_live, false);
630 for (size_t i = 0; i < candidates; i++) {
631 ShenandoahHeapRegion* const region = sorted_regions[i]._region;
632 size_t region_live_data = sorted_regions[i]._live_data;
633 size_t promotion_need = (size_t) (region_live_data * ShenandoahPromoEvacWaste);
634 if (old_consumed + promotion_need <= old_available) {
635 old_consumed += promotion_need;
636 candidate_regions_for_promotion_by_copy[region->index()] = true;
637 selected_regions++;
638 selected_live += region_live_data;
639 } else {
640 // We rejected this promotable region from the collection set because we had no room to hold its copy.
641 // Add this region to promo potential for next GC.
642 promo_potential += region_live_data;
643 assert(!candidate_regions_for_promotion_by_copy[region->index()], "Shouldn't be selected");
644 }
645 // We keep going even if one region is excluded from selection because we need to accumulate all eligible
646 // regions that are not preselected into promo_potential
647 }
648 log_debug(gc)("Preselected " SIZE_FORMAT " regions containing " SIZE_FORMAT " live bytes,"
649 " consuming: " SIZE_FORMAT " of budgeted: " SIZE_FORMAT,
650 selected_regions, selected_live, old_consumed, old_available);
651 }
652
653 heap->old_generation()->set_pad_for_promote_in_place(promote_in_place_pad);
654 heap->old_generation()->set_promotion_potential(promo_potential);
655 return old_consumed;
656 }
657
658 void ShenandoahGeneration::prepare_regions_and_collection_set(bool concurrent) {
659 ShenandoahHeap* heap = ShenandoahHeap::heap();
660 ShenandoahCollectionSet* collection_set = heap->collection_set();
661 bool is_generational = heap->mode()->is_generational();
662
663 assert(!heap->is_full_gc_in_progress(), "Only for concurrent and degenerated GC");
664 assert(!is_old(), "Only YOUNG and GLOBAL GC perform evacuations");
665 {
666 ShenandoahGCPhase phase(concurrent ? ShenandoahPhaseTimings::final_update_region_states :
667 ShenandoahPhaseTimings::degen_gc_final_update_region_states);
668 ShenandoahFinalMarkUpdateRegionStateClosure cl(complete_marking_context());
669 parallel_heap_region_iterate(&cl);
670
671 if (is_young()) {
672 // We always need to update the watermark for old regions. If there
673 // are mixed collections pending, we also need to synchronize the
674 // pinned status for old regions. Since we are already visiting every
675 // old region here, go ahead and sync the pin status too.
676 ShenandoahFinalMarkUpdateRegionStateClosure old_cl(nullptr);
677 heap->old_generation()->parallel_heap_region_iterate(&old_cl);
678 }
679 }
680
681 // Tally the census counts and compute the adaptive tenuring threshold
682 if (is_generational && ShenandoahGenerationalAdaptiveTenuring && !ShenandoahGenerationalCensusAtEvac) {
683 // Objects above TAMS weren't included in the age census. Since they were all
684 // allocated in this cycle they belong in the age 0 cohort. We walk over all
685 // young regions and sum the volume of objects between TAMS and top.
686 ShenandoahUpdateCensusZeroCohortClosure age0_cl(complete_marking_context());
687 heap->young_generation()->heap_region_iterate(&age0_cl);
688 size_t age0_pop = age0_cl.get_age0_population();
689
690 // Update the global census, including the missed age 0 cohort above,
691 // along with the census done during marking, and compute the tenuring threshold.
692 ShenandoahAgeCensus* census = ShenandoahGenerationalHeap::heap()->age_census();
693 census->update_census(age0_pop);
694 #ifndef PRODUCT
695 size_t total_pop = age0_cl.get_total_population();
696 size_t total_census = census->get_total();
697 // Usually total_pop > total_census, but not by too much.
698 // We use integer division so anything up to just less than 2 is considered
699 // reasonable, and the "+1" is to avoid divide-by-zero.
700 assert((total_pop+1)/(total_census+1) == 1, "Extreme divergence: "
701 SIZE_FORMAT "/" SIZE_FORMAT, total_pop, total_census);
702 #endif
703 }
704
705 {
706 ShenandoahGCPhase phase(concurrent ? ShenandoahPhaseTimings::choose_cset :
707 ShenandoahPhaseTimings::degen_gc_choose_cset);
708
709 collection_set->clear();
710 ShenandoahHeapLocker locker(heap->lock());
711 if (is_generational) {
712 // Seed the collection set with resource area-allocated
713 // preselected regions, which are removed when we exit this scope.
714 ShenandoahCollectionSetPreselector preselector(collection_set, heap->num_regions());
715
716 // Find the amount that will be promoted, regions that will be promoted in
717 // place, and preselect older regions that will be promoted by evacuation.
718 compute_evacuation_budgets(heap);
719
720 // Choose the collection set, including the regions preselected above for
721 // promotion into the old generation.
722 _heuristics->choose_collection_set(collection_set);
723 if (!collection_set->is_empty()) {
724 // only make use of evacuation budgets when we are evacuating
725 adjust_evacuation_budgets(heap, collection_set);
726 }
727
728 if (is_global()) {
729 // We have just chosen a collection set for a global cycle. The mark bitmap covering old regions is complete, so
730 // the remembered set scan can use that to avoid walking into garbage. When the next old mark begins, we will
731 // use the mark bitmap to make the old regions parsable by coalescing and filling any unmarked objects. Thus,
732 // we prepare for old collections by remembering which regions are old at this time. Note that any objects
733 // promoted into old regions will be above TAMS, and so will be considered marked. However, free regions that
734 // become old after this point will not be covered correctly by the mark bitmap, so we must be careful not to
735 // coalesce those regions. Only the old regions which are not part of the collection set at this point are
736 // eligible for coalescing. As implemented now, this has the side effect of possibly initiating mixed-evacuations
737 // after a global cycle for old regions that were not included in this collection set.
738 heap->old_generation()->prepare_for_mixed_collections_after_global_gc();
739 }
740 } else {
741 _heuristics->choose_collection_set(collection_set);
742 }
743 }
744
745
746 {
747 ShenandoahGCPhase phase(concurrent ? ShenandoahPhaseTimings::final_rebuild_freeset :
748 ShenandoahPhaseTimings::degen_gc_final_rebuild_freeset);
749 ShenandoahHeapLocker locker(heap->lock());
750 size_t young_cset_regions, old_cset_regions;
751
752 // We are preparing for evacuation. At this time, we ignore cset region tallies.
753 size_t first_old, last_old, num_old;
754 heap->free_set()->prepare_to_rebuild(young_cset_regions, old_cset_regions, first_old, last_old, num_old);
755 // Free set construction uses reserve quantities, because they are known to be valid here
756 heap->free_set()->finish_rebuild(young_cset_regions, old_cset_regions, num_old, true);
757 }
758 }
759
760 bool ShenandoahGeneration::is_bitmap_clear() {
761 ShenandoahHeap* heap = ShenandoahHeap::heap();
762 ShenandoahMarkingContext* context = heap->marking_context();
763 const size_t num_regions = heap->num_regions();
764 for (size_t idx = 0; idx < num_regions; idx++) {
765 ShenandoahHeapRegion* r = heap->get_region(idx);
766 if (contains(r) && r->is_affiliated()) {
767 if (heap->is_bitmap_slice_committed(r) && (context->top_at_mark_start(r) > r->bottom()) &&
768 !context->is_bitmap_range_within_region_clear(r->bottom(), r->end())) {
769 return false;
770 }
771 }
772 }
773 return true;
774 }
775
776 void ShenandoahGeneration::set_mark_complete() {
777 _is_marking_complete.set();
778 }
779
780 void ShenandoahGeneration::set_mark_incomplete() {
781 _is_marking_complete.unset();
782 }
783
784 ShenandoahMarkingContext* ShenandoahGeneration::complete_marking_context() {
785 assert(is_mark_complete(), "Marking must be completed.");
786 return ShenandoahHeap::heap()->marking_context();
787 }
788
789 void ShenandoahGeneration::cancel_marking() {
790 log_info(gc)("Cancel marking: %s", name());
791 if (is_concurrent_mark_in_progress()) {
792 set_mark_incomplete();
793 }
794 _task_queues->clear();
795 ref_processor()->abandon_partial_discovery();
796 set_concurrent_mark_in_progress(false);
797 }
798
799 ShenandoahGeneration::ShenandoahGeneration(ShenandoahGenerationType type,
800 uint max_workers,
801 size_t max_capacity) :
802 _type(type),
803 _task_queues(new ShenandoahObjToScanQueueSet(max_workers)),
804 _ref_processor(new ShenandoahReferenceProcessor(MAX2(max_workers, 1U))),
805 _affiliated_region_count(0), _humongous_waste(0), _evacuation_reserve(0),
806 _used(0), _bytes_allocated_since_gc_start(0),
807 _max_capacity(max_capacity),
808 _heuristics(nullptr)
809 {
810 _is_marking_complete.set();
811 assert(max_workers > 0, "At least one queue");
812 for (uint i = 0; i < max_workers; ++i) {
813 ShenandoahObjToScanQueue* task_queue = new ShenandoahObjToScanQueue();
814 _task_queues->register_queue(i, task_queue);
815 }
816 }
817
818 ShenandoahGeneration::~ShenandoahGeneration() {
819 for (uint i = 0; i < _task_queues->size(); ++i) {
820 ShenandoahObjToScanQueue* q = _task_queues->queue(i);
821 delete q;
822 }
823 delete _task_queues;
824 }
825
826 void ShenandoahGeneration::reserve_task_queues(uint workers) {
827 _task_queues->reserve(workers);
828 }
829
830 ShenandoahObjToScanQueueSet* ShenandoahGeneration::old_gen_task_queues() const {
831 return nullptr;
832 }
833
834 void ShenandoahGeneration::scan_remembered_set(bool is_concurrent) {
835 assert(is_young(), "Should only scan remembered set for young generation.");
836
837 ShenandoahGenerationalHeap* const heap = ShenandoahGenerationalHeap::heap();
838 uint nworkers = heap->workers()->active_workers();
839 reserve_task_queues(nworkers);
840
841 ShenandoahReferenceProcessor* rp = ref_processor();
842 ShenandoahRegionChunkIterator work_list(nworkers);
843 ShenandoahScanRememberedTask task(task_queues(), old_gen_task_queues(), rp, &work_list, is_concurrent);
844 heap->assert_gc_workers(nworkers);
845 heap->workers()->run_task(&task);
846 if (ShenandoahEnableCardStats) {
847 ShenandoahScanRemembered* scanner = heap->old_generation()->card_scan();
848 assert(scanner != nullptr, "Not generational");
849 scanner->log_card_stats(nworkers, CARD_STAT_SCAN_RS);
850 }
851 }
852
853 size_t ShenandoahGeneration::increment_affiliated_region_count() {
854 shenandoah_assert_heaplocked_or_safepoint();
855 // During full gc, multiple GC worker threads may change region affiliations without a lock. No lock is enforced
856 // on read and write of _affiliated_region_count. At the end of full gc, a single thread overwrites the count with
857 // a coherent value.
858 return Atomic::add(&_affiliated_region_count, (size_t) 1);
859 }
860
861 size_t ShenandoahGeneration::decrement_affiliated_region_count() {
862 shenandoah_assert_heaplocked_or_safepoint();
863 // During full gc, multiple GC worker threads may change region affiliations without a lock. No lock is enforced
864 // on read and write of _affiliated_region_count. At the end of full gc, a single thread overwrites the count with
865 // a coherent value.
866 auto affiliated_region_count = Atomic::sub(&_affiliated_region_count, (size_t) 1);
867 assert(ShenandoahHeap::heap()->is_full_gc_in_progress() ||
868 (used() + _humongous_waste <= affiliated_region_count * ShenandoahHeapRegion::region_size_bytes()),
869 "used + humongous cannot exceed regions");
870 return affiliated_region_count;
871 }
872
873 size_t ShenandoahGeneration::decrement_affiliated_region_count_without_lock() {
874 return Atomic::sub(&_affiliated_region_count, (size_t) 1);
875 }
876
877 size_t ShenandoahGeneration::increase_affiliated_region_count(size_t delta) {
878 shenandoah_assert_heaplocked_or_safepoint();
879 return Atomic::add(&_affiliated_region_count, delta);
880 }
881
882 size_t ShenandoahGeneration::decrease_affiliated_region_count(size_t delta) {
883 shenandoah_assert_heaplocked_or_safepoint();
884 assert(Atomic::load(&_affiliated_region_count) >= delta, "Affiliated region count cannot be negative");
885
886 auto const affiliated_region_count = Atomic::sub(&_affiliated_region_count, delta);
887 assert(ShenandoahHeap::heap()->is_full_gc_in_progress() ||
888 (_used + _humongous_waste <= affiliated_region_count * ShenandoahHeapRegion::region_size_bytes()),
889 "used + humongous cannot exceed regions");
890 return affiliated_region_count;
891 }
892
893 void ShenandoahGeneration::establish_usage(size_t num_regions, size_t num_bytes, size_t humongous_waste) {
894 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "must be at a safepoint");
895 Atomic::store(&_affiliated_region_count, num_regions);
896 Atomic::store(&_used, num_bytes);
897 _humongous_waste = humongous_waste;
898 }
899
900 void ShenandoahGeneration::increase_used(size_t bytes) {
901 Atomic::add(&_used, bytes);
902 }
903
904 void ShenandoahGeneration::increase_humongous_waste(size_t bytes) {
905 if (bytes > 0) {
906 Atomic::add(&_humongous_waste, bytes);
907 }
908 }
909
910 void ShenandoahGeneration::decrease_humongous_waste(size_t bytes) {
911 if (bytes > 0) {
912 assert(ShenandoahHeap::heap()->is_full_gc_in_progress() || (_humongous_waste >= bytes),
913 "Waste (" SIZE_FORMAT ") cannot be negative (after subtracting " SIZE_FORMAT ")", _humongous_waste, bytes);
914 Atomic::sub(&_humongous_waste, bytes);
915 }
916 }
917
918 void ShenandoahGeneration::decrease_used(size_t bytes) {
919 assert(ShenandoahHeap::heap()->is_full_gc_in_progress() ||
920 (_used >= bytes), "cannot reduce bytes used by generation below zero");
921 Atomic::sub(&_used, bytes);
922 }
923
924 size_t ShenandoahGeneration::used_regions() const {
925 return Atomic::load(&_affiliated_region_count);
926 }
927
928 size_t ShenandoahGeneration::free_unaffiliated_regions() const {
929 size_t result = max_capacity() / ShenandoahHeapRegion::region_size_bytes();
930 auto const used_regions = this->used_regions();
931 if (used_regions > result) {
932 result = 0;
933 } else {
934 result -= used_regions;
935 }
936 return result;
937 }
938
939 size_t ShenandoahGeneration::used_regions_size() const {
940 return used_regions() * ShenandoahHeapRegion::region_size_bytes();
941 }
942
943 size_t ShenandoahGeneration::available() const {
944 return available(max_capacity());
945 }
946
947 // For ShenandoahYoungGeneration, Include the young available that may have been reserved for the Collector.
948 size_t ShenandoahGeneration::available_with_reserve() const {
949 return available(max_capacity());
950 }
951
952 size_t ShenandoahGeneration::soft_available() const {
953 return available(ShenandoahHeap::heap()->soft_max_capacity());
954 }
955
956 size_t ShenandoahGeneration::available(size_t capacity) const {
957 size_t in_use = used() + get_humongous_waste();
958 return in_use > capacity ? 0 : capacity - in_use;
959 }
960
961 size_t ShenandoahGeneration::increase_capacity(size_t increment) {
962 shenandoah_assert_heaplocked_or_safepoint();
963
964 // We do not enforce that new capacity >= heap->max_size_for(this). The maximum generation size is treated as a rule of thumb
965 // which may be violated during certain transitions, such as when we are forcing transfers for the purpose of promoting regions
966 // in place.
967 assert(ShenandoahHeap::heap()->is_full_gc_in_progress() ||
968 (_max_capacity + increment <= ShenandoahHeap::heap()->max_capacity()), "Generation cannot be larger than heap size");
969 assert(increment % ShenandoahHeapRegion::region_size_bytes() == 0, "Generation capacity must be multiple of region size");
970 _max_capacity += increment;
971
972 // This detects arithmetic wraparound on _used
973 assert(ShenandoahHeap::heap()->is_full_gc_in_progress() ||
974 (used_regions_size() >= used()),
975 "Affiliated regions must hold more than what is currently used");
976 return _max_capacity;
977 }
978
979 size_t ShenandoahGeneration::set_capacity(size_t byte_size) {
980 shenandoah_assert_heaplocked_or_safepoint();
981 _max_capacity = byte_size;
982 return _max_capacity;
983 }
984
985 size_t ShenandoahGeneration::decrease_capacity(size_t decrement) {
986 shenandoah_assert_heaplocked_or_safepoint();
987
988 // We do not enforce that new capacity >= heap->min_size_for(this). The minimum generation size is treated as a rule of thumb
989 // which may be violated during certain transitions, such as when we are forcing transfers for the purpose of promoting regions
990 // in place.
991 assert(decrement % ShenandoahHeapRegion::region_size_bytes() == 0, "Generation capacity must be multiple of region size");
992 assert(_max_capacity >= decrement, "Generation capacity cannot be negative");
993
994 _max_capacity -= decrement;
995
996 // This detects arithmetic wraparound on _used
997 assert(ShenandoahHeap::heap()->is_full_gc_in_progress() ||
998 (used_regions_size() >= used()),
999 "Affiliated regions must hold more than what is currently used");
1000 assert(ShenandoahHeap::heap()->is_full_gc_in_progress() ||
1001 (_used <= _max_capacity), "Cannot use more than capacity");
1002 assert(ShenandoahHeap::heap()->is_full_gc_in_progress() ||
1003 (used_regions_size() <= _max_capacity),
1004 "Cannot use more than capacity");
1005 return _max_capacity;
1006 }
1007
1008 void ShenandoahGeneration::record_success_concurrent(bool abbreviated) {
1009 heuristics()->record_success_concurrent();
1010 ShenandoahHeap::heap()->shenandoah_policy()->record_success_concurrent(is_young(), abbreviated);
1011 }