| 1 | /* | 
|---|
| 2 | * Copyright (c) 2003, 2015, Oracle and/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/parallel/asPSOldGen.hpp" | 
|---|
| 27 | #include "gc/parallel/parallelScavengeHeap.hpp" | 
|---|
| 28 | #include "gc/parallel/psAdaptiveSizePolicy.hpp" | 
|---|
| 29 | #include "gc/parallel/psMarkSweepDecorator.hpp" | 
|---|
| 30 | #include "gc/shared/cardTableBarrierSet.hpp" | 
|---|
| 31 | #include "gc/shared/genArguments.hpp" | 
|---|
| 32 | #include "oops/oop.inline.hpp" | 
|---|
| 33 | #include "runtime/java.hpp" | 
|---|
| 34 | #include "utilities/align.hpp" | 
|---|
| 35 |  | 
|---|
| 36 | // Whereas PSOldGen takes the maximum size of the generation | 
|---|
| 37 | // (which doesn't change in the case of PSOldGen) as a parameter, | 
|---|
| 38 | // ASPSOldGen takes the upper limit on the size of | 
|---|
| 39 | // the generation as a parameter.  In ASPSOldGen the | 
|---|
| 40 | // maximum size of the generation can change as the boundary | 
|---|
| 41 | // moves.  The "maximum size of the generation" is still a valid | 
|---|
| 42 | // concept since the generation can grow and shrink within that | 
|---|
| 43 | // maximum.  There are lots of useful checks that use that | 
|---|
| 44 | // maximum.  In PSOldGen the method max_gen_size() returns | 
|---|
| 45 | // _max_gen_size (as set by the PSOldGen constructor).  This | 
|---|
| 46 | // is how it always worked.  In ASPSOldGen max_gen_size() | 
|---|
| 47 | // returned the size of the reserved space for the generation. | 
|---|
| 48 | // That can change as the boundary moves.  Below the limit of | 
|---|
| 49 | // the size of the generation is passed to the PSOldGen constructor | 
|---|
| 50 | // for "_max_gen_size" (have to pass something) but it is not used later. | 
|---|
| 51 | // | 
|---|
| 52 | ASPSOldGen::ASPSOldGen(size_t initial_size, | 
|---|
| 53 | size_t min_size, | 
|---|
| 54 | size_t size_limit, | 
|---|
| 55 | const char* gen_name, | 
|---|
| 56 | int level) : | 
|---|
| 57 | PSOldGen(initial_size, min_size, size_limit, gen_name, level), | 
|---|
| 58 | _gen_size_limit(size_limit) | 
|---|
| 59 | {} | 
|---|
| 60 |  | 
|---|
| 61 | ASPSOldGen::ASPSOldGen(PSVirtualSpace* vs, | 
|---|
| 62 | size_t initial_size, | 
|---|
| 63 | size_t min_size, | 
|---|
| 64 | size_t size_limit, | 
|---|
| 65 | const char* gen_name, | 
|---|
| 66 | int level) : | 
|---|
| 67 | PSOldGen(initial_size, min_size, size_limit, gen_name, level), | 
|---|
| 68 | _gen_size_limit(size_limit) | 
|---|
| 69 | { | 
|---|
| 70 | _virtual_space = vs; | 
|---|
| 71 | } | 
|---|
| 72 |  | 
|---|
| 73 | void ASPSOldGen::initialize_work(const char* perf_data_name, int level) { | 
|---|
| 74 | PSOldGen::initialize_work(perf_data_name, level); | 
|---|
| 75 |  | 
|---|
| 76 | // The old gen can grow to gen_size_limit().  _reserve reflects only | 
|---|
| 77 | // the current maximum that can be committed. | 
|---|
| 78 | assert(_reserved.byte_size() <= gen_size_limit(), "Consistency check"); | 
|---|
| 79 |  | 
|---|
| 80 | initialize_performance_counters(perf_data_name, level); | 
|---|
| 81 | } | 
|---|
| 82 |  | 
|---|
| 83 | void ASPSOldGen::reset_after_change() { | 
|---|
| 84 | _reserved = MemRegion((HeapWord*)virtual_space()->low_boundary(), | 
|---|
| 85 | (HeapWord*)virtual_space()->high_boundary()); | 
|---|
| 86 | post_resize(); | 
|---|
| 87 | } | 
|---|
| 88 |  | 
|---|
| 89 |  | 
|---|
| 90 | size_t ASPSOldGen::available_for_expansion() { | 
|---|
| 91 | assert(virtual_space()->is_aligned(gen_size_limit()), "not aligned"); | 
|---|
| 92 | assert(gen_size_limit() >= virtual_space()->committed_size(), "bad gen size"); | 
|---|
| 93 |  | 
|---|
| 94 | size_t result =  gen_size_limit() - virtual_space()->committed_size(); | 
|---|
| 95 | size_t result_aligned = align_down(result, GenAlignment); | 
|---|
| 96 | return result_aligned; | 
|---|
| 97 | } | 
|---|
| 98 |  | 
|---|
| 99 | size_t ASPSOldGen::available_for_contraction() { | 
|---|
| 100 | size_t uncommitted_bytes = virtual_space()->uncommitted_size(); | 
|---|
| 101 | if (uncommitted_bytes != 0) { | 
|---|
| 102 | return uncommitted_bytes; | 
|---|
| 103 | } | 
|---|
| 104 |  | 
|---|
| 105 | ParallelScavengeHeap* heap = ParallelScavengeHeap::heap(); | 
|---|
| 106 | PSAdaptiveSizePolicy* policy = heap->size_policy(); | 
|---|
| 107 | const size_t working_size = | 
|---|
| 108 | used_in_bytes() + (size_t) policy->avg_promoted()->padded_average(); | 
|---|
| 109 | const size_t working_aligned = align_up(working_size, GenAlignment); | 
|---|
| 110 | const size_t working_or_min = MAX2(working_aligned, min_gen_size()); | 
|---|
| 111 | if (working_or_min > reserved().byte_size()) { | 
|---|
| 112 | // If the used or minimum gen size (aligned up) is greater | 
|---|
| 113 | // than the total reserved size, then the space available | 
|---|
| 114 | // for contraction should (after proper alignment) be 0 | 
|---|
| 115 | return 0; | 
|---|
| 116 | } | 
|---|
| 117 | const size_t max_contraction = | 
|---|
| 118 | reserved().byte_size() - working_or_min; | 
|---|
| 119 |  | 
|---|
| 120 | // Use the "increment" fraction instead of the "decrement" fraction | 
|---|
| 121 | // to allow the other gen to expand more aggressively.  The | 
|---|
| 122 | // "decrement" fraction is conservative because its intent is to | 
|---|
| 123 | // only reduce the footprint. | 
|---|
| 124 |  | 
|---|
| 125 | size_t result = policy->promo_increment_aligned_down(max_contraction); | 
|---|
| 126 | // Also adjust for inter-generational alignment | 
|---|
| 127 | size_t result_aligned = align_down(result, GenAlignment); | 
|---|
| 128 |  | 
|---|
| 129 | Log(gc, ergo) log; | 
|---|
| 130 | if (log.is_trace()) { | 
|---|
| 131 | size_t working_promoted = (size_t) policy->avg_promoted()->padded_average(); | 
|---|
| 132 | size_t promo_increment = policy->promo_increment(max_contraction); | 
|---|
| 133 | log.trace( "ASPSOldGen::available_for_contraction: "SIZE_FORMAT " K / "SIZE_FORMAT_HEX, result_aligned/K, result_aligned); | 
|---|
| 134 | log.trace( " reserved().byte_size() "SIZE_FORMAT " K / "SIZE_FORMAT_HEX, reserved().byte_size()/K, reserved().byte_size()); | 
|---|
| 135 | log.trace( " padded promoted "SIZE_FORMAT " K / "SIZE_FORMAT_HEX, working_promoted/K, working_promoted); | 
|---|
| 136 | log.trace( " used "SIZE_FORMAT " K / "SIZE_FORMAT_HEX, used_in_bytes()/K, used_in_bytes()); | 
|---|
| 137 | log.trace( " min_gen_size() "SIZE_FORMAT " K / "SIZE_FORMAT_HEX, min_gen_size()/K, min_gen_size()); | 
|---|
| 138 | log.trace( " max_contraction "SIZE_FORMAT " K / "SIZE_FORMAT_HEX, max_contraction/K, max_contraction); | 
|---|
| 139 | log.trace( "    without alignment "SIZE_FORMAT " K / "SIZE_FORMAT_HEX, promo_increment/K, promo_increment); | 
|---|
| 140 | log.trace( " alignment "SIZE_FORMAT_HEX, GenAlignment); | 
|---|
| 141 | } | 
|---|
| 142 |  | 
|---|
| 143 | assert(result_aligned <= max_contraction, "arithmetic is wrong"); | 
|---|
| 144 | return result_aligned; | 
|---|
| 145 | } | 
|---|
| 146 |  | 
|---|