annotate src/share/vm/memory/tenuredGeneration.cpp @ 453:c96030fff130

6684579: SoftReference processing can be made more efficient Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not. Reviewed-by: jmasa
author ysr
date Thu, 20 Nov 2008 16:56:09 -0800
parents d1605aabd0a1
children 7d7a7c599c17
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
196
d1605aabd0a1 6719955: Update copyright year
xdono
parents: 6
diff changeset
2 * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
a61af66fc99e Initial load
duke
parents:
diff changeset
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
a61af66fc99e Initial load
duke
parents:
diff changeset
20 * CA 95054 USA or visit www.sun.com if you need additional information or
a61af66fc99e Initial load
duke
parents:
diff changeset
21 * have any questions.
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 # include "incls/_precompiled.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
26 # include "incls/_tenuredGeneration.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
27
a61af66fc99e Initial load
duke
parents:
diff changeset
28 TenuredGeneration::TenuredGeneration(ReservedSpace rs,
a61af66fc99e Initial load
duke
parents:
diff changeset
29 size_t initial_byte_size, int level,
a61af66fc99e Initial load
duke
parents:
diff changeset
30 GenRemSet* remset) :
a61af66fc99e Initial load
duke
parents:
diff changeset
31 OneContigSpaceCardGeneration(rs, initial_byte_size,
a61af66fc99e Initial load
duke
parents:
diff changeset
32 MinHeapDeltaBytes, level, remset, NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
33 {
a61af66fc99e Initial load
duke
parents:
diff changeset
34 HeapWord* bottom = (HeapWord*) _virtual_space.low();
a61af66fc99e Initial load
duke
parents:
diff changeset
35 HeapWord* end = (HeapWord*) _virtual_space.high();
a61af66fc99e Initial load
duke
parents:
diff changeset
36 _the_space = new TenuredSpace(_bts, MemRegion(bottom, end));
a61af66fc99e Initial load
duke
parents:
diff changeset
37 _the_space->reset_saved_mark();
a61af66fc99e Initial load
duke
parents:
diff changeset
38 _shrink_factor = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
39 _capacity_at_prologue = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
40
a61af66fc99e Initial load
duke
parents:
diff changeset
41 _gc_stats = new GCStats();
a61af66fc99e Initial load
duke
parents:
diff changeset
42
a61af66fc99e Initial load
duke
parents:
diff changeset
43 // initialize performance counters
a61af66fc99e Initial load
duke
parents:
diff changeset
44
a61af66fc99e Initial load
duke
parents:
diff changeset
45 const char* gen_name = "old";
a61af66fc99e Initial load
duke
parents:
diff changeset
46
a61af66fc99e Initial load
duke
parents:
diff changeset
47 // Generation Counters -- generation 1, 1 subspace
a61af66fc99e Initial load
duke
parents:
diff changeset
48 _gen_counters = new GenerationCounters(gen_name, 1, 1, &_virtual_space);
a61af66fc99e Initial load
duke
parents:
diff changeset
49
a61af66fc99e Initial load
duke
parents:
diff changeset
50 _gc_counters = new CollectorCounters("MSC", 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
51
a61af66fc99e Initial load
duke
parents:
diff changeset
52 _space_counters = new CSpaceCounters(gen_name, 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
53 _virtual_space.reserved_size(),
a61af66fc99e Initial load
duke
parents:
diff changeset
54 _the_space, _gen_counters);
a61af66fc99e Initial load
duke
parents:
diff changeset
55 #ifndef SERIALGC
a61af66fc99e Initial load
duke
parents:
diff changeset
56 if (UseParNewGC && ParallelGCThreads > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
57 typedef ParGCAllocBufferWithBOT* ParGCAllocBufferWithBOTPtr;
a61af66fc99e Initial load
duke
parents:
diff changeset
58 _alloc_buffers = NEW_C_HEAP_ARRAY(ParGCAllocBufferWithBOTPtr,
a61af66fc99e Initial load
duke
parents:
diff changeset
59 ParallelGCThreads);
a61af66fc99e Initial load
duke
parents:
diff changeset
60 if (_alloc_buffers == NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
61 vm_exit_during_initialization("Could not allocate alloc_buffers");
a61af66fc99e Initial load
duke
parents:
diff changeset
62 for (uint i = 0; i < ParallelGCThreads; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
63 _alloc_buffers[i] =
a61af66fc99e Initial load
duke
parents:
diff changeset
64 new ParGCAllocBufferWithBOT(OldPLABSize, _bts);
a61af66fc99e Initial load
duke
parents:
diff changeset
65 if (_alloc_buffers[i] == NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
66 vm_exit_during_initialization("Could not allocate alloc_buffers");
a61af66fc99e Initial load
duke
parents:
diff changeset
67 }
a61af66fc99e Initial load
duke
parents:
diff changeset
68 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
69 _alloc_buffers = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
70 }
a61af66fc99e Initial load
duke
parents:
diff changeset
71 #endif // SERIALGC
a61af66fc99e Initial load
duke
parents:
diff changeset
72 }
a61af66fc99e Initial load
duke
parents:
diff changeset
73
a61af66fc99e Initial load
duke
parents:
diff changeset
74
a61af66fc99e Initial load
duke
parents:
diff changeset
75 const char* TenuredGeneration::name() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
76 return "tenured generation";
a61af66fc99e Initial load
duke
parents:
diff changeset
77 }
a61af66fc99e Initial load
duke
parents:
diff changeset
78
a61af66fc99e Initial load
duke
parents:
diff changeset
79 void TenuredGeneration::compute_new_size() {
a61af66fc99e Initial load
duke
parents:
diff changeset
80 assert(_shrink_factor <= 100, "invalid shrink factor");
a61af66fc99e Initial load
duke
parents:
diff changeset
81 size_t current_shrink_factor = _shrink_factor;
a61af66fc99e Initial load
duke
parents:
diff changeset
82 _shrink_factor = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
83
a61af66fc99e Initial load
duke
parents:
diff changeset
84 // We don't have floating point command-line arguments
a61af66fc99e Initial load
duke
parents:
diff changeset
85 // Note: argument processing ensures that MinHeapFreeRatio < 100.
a61af66fc99e Initial load
duke
parents:
diff changeset
86 const double minimum_free_percentage = MinHeapFreeRatio / 100.0;
a61af66fc99e Initial load
duke
parents:
diff changeset
87 const double maximum_used_percentage = 1.0 - minimum_free_percentage;
a61af66fc99e Initial load
duke
parents:
diff changeset
88
a61af66fc99e Initial load
duke
parents:
diff changeset
89 // Compute some numbers about the state of the heap.
a61af66fc99e Initial load
duke
parents:
diff changeset
90 const size_t used_after_gc = used();
a61af66fc99e Initial load
duke
parents:
diff changeset
91 const size_t capacity_after_gc = capacity();
a61af66fc99e Initial load
duke
parents:
diff changeset
92
a61af66fc99e Initial load
duke
parents:
diff changeset
93 const double min_tmp = used_after_gc / maximum_used_percentage;
a61af66fc99e Initial load
duke
parents:
diff changeset
94 size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx));
a61af66fc99e Initial load
duke
parents:
diff changeset
95 // Don't shrink less than the initial generation size
a61af66fc99e Initial load
duke
parents:
diff changeset
96 minimum_desired_capacity = MAX2(minimum_desired_capacity,
a61af66fc99e Initial load
duke
parents:
diff changeset
97 spec()->init_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
98 assert(used_after_gc <= minimum_desired_capacity, "sanity check");
a61af66fc99e Initial load
duke
parents:
diff changeset
99
a61af66fc99e Initial load
duke
parents:
diff changeset
100 if (PrintGC && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
101 const size_t free_after_gc = free();
a61af66fc99e Initial load
duke
parents:
diff changeset
102 const double free_percentage = ((double)free_after_gc) / capacity_after_gc;
a61af66fc99e Initial load
duke
parents:
diff changeset
103 gclog_or_tty->print_cr("TenuredGeneration::compute_new_size: ");
a61af66fc99e Initial load
duke
parents:
diff changeset
104 gclog_or_tty->print_cr(" "
a61af66fc99e Initial load
duke
parents:
diff changeset
105 " minimum_free_percentage: %6.2f"
a61af66fc99e Initial load
duke
parents:
diff changeset
106 " maximum_used_percentage: %6.2f",
a61af66fc99e Initial load
duke
parents:
diff changeset
107 minimum_free_percentage,
a61af66fc99e Initial load
duke
parents:
diff changeset
108 maximum_used_percentage);
a61af66fc99e Initial load
duke
parents:
diff changeset
109 gclog_or_tty->print_cr(" "
a61af66fc99e Initial load
duke
parents:
diff changeset
110 " free_after_gc : %6.1fK"
a61af66fc99e Initial load
duke
parents:
diff changeset
111 " used_after_gc : %6.1fK"
a61af66fc99e Initial load
duke
parents:
diff changeset
112 " capacity_after_gc : %6.1fK",
a61af66fc99e Initial load
duke
parents:
diff changeset
113 free_after_gc / (double) K,
a61af66fc99e Initial load
duke
parents:
diff changeset
114 used_after_gc / (double) K,
a61af66fc99e Initial load
duke
parents:
diff changeset
115 capacity_after_gc / (double) K);
a61af66fc99e Initial load
duke
parents:
diff changeset
116 gclog_or_tty->print_cr(" "
a61af66fc99e Initial load
duke
parents:
diff changeset
117 " free_percentage: %6.2f",
a61af66fc99e Initial load
duke
parents:
diff changeset
118 free_percentage);
a61af66fc99e Initial load
duke
parents:
diff changeset
119 }
a61af66fc99e Initial load
duke
parents:
diff changeset
120
a61af66fc99e Initial load
duke
parents:
diff changeset
121 if (capacity_after_gc < minimum_desired_capacity) {
a61af66fc99e Initial load
duke
parents:
diff changeset
122 // If we have less free space than we want then expand
a61af66fc99e Initial load
duke
parents:
diff changeset
123 size_t expand_bytes = minimum_desired_capacity - capacity_after_gc;
a61af66fc99e Initial load
duke
parents:
diff changeset
124 // Don't expand unless it's significant
a61af66fc99e Initial load
duke
parents:
diff changeset
125 if (expand_bytes >= _min_heap_delta_bytes) {
a61af66fc99e Initial load
duke
parents:
diff changeset
126 expand(expand_bytes, 0); // safe if expansion fails
a61af66fc99e Initial load
duke
parents:
diff changeset
127 }
a61af66fc99e Initial load
duke
parents:
diff changeset
128 if (PrintGC && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
129 gclog_or_tty->print_cr(" expanding:"
a61af66fc99e Initial load
duke
parents:
diff changeset
130 " minimum_desired_capacity: %6.1fK"
a61af66fc99e Initial load
duke
parents:
diff changeset
131 " expand_bytes: %6.1fK"
a61af66fc99e Initial load
duke
parents:
diff changeset
132 " _min_heap_delta_bytes: %6.1fK",
a61af66fc99e Initial load
duke
parents:
diff changeset
133 minimum_desired_capacity / (double) K,
a61af66fc99e Initial load
duke
parents:
diff changeset
134 expand_bytes / (double) K,
a61af66fc99e Initial load
duke
parents:
diff changeset
135 _min_heap_delta_bytes / (double) K);
a61af66fc99e Initial load
duke
parents:
diff changeset
136 }
a61af66fc99e Initial load
duke
parents:
diff changeset
137 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
138 }
a61af66fc99e Initial load
duke
parents:
diff changeset
139
a61af66fc99e Initial load
duke
parents:
diff changeset
140 // No expansion, now see if we want to shrink
a61af66fc99e Initial load
duke
parents:
diff changeset
141 size_t shrink_bytes = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
142 // We would never want to shrink more than this
a61af66fc99e Initial load
duke
parents:
diff changeset
143 size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity;
a61af66fc99e Initial load
duke
parents:
diff changeset
144
a61af66fc99e Initial load
duke
parents:
diff changeset
145 if (MaxHeapFreeRatio < 100) {
a61af66fc99e Initial load
duke
parents:
diff changeset
146 const double maximum_free_percentage = MaxHeapFreeRatio / 100.0;
a61af66fc99e Initial load
duke
parents:
diff changeset
147 const double minimum_used_percentage = 1.0 - maximum_free_percentage;
a61af66fc99e Initial load
duke
parents:
diff changeset
148 const double max_tmp = used_after_gc / minimum_used_percentage;
a61af66fc99e Initial load
duke
parents:
diff changeset
149 size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx));
a61af66fc99e Initial load
duke
parents:
diff changeset
150 maximum_desired_capacity = MAX2(maximum_desired_capacity,
a61af66fc99e Initial load
duke
parents:
diff changeset
151 spec()->init_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
152 if (PrintGC && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
153 gclog_or_tty->print_cr(" "
a61af66fc99e Initial load
duke
parents:
diff changeset
154 " maximum_free_percentage: %6.2f"
a61af66fc99e Initial load
duke
parents:
diff changeset
155 " minimum_used_percentage: %6.2f",
a61af66fc99e Initial load
duke
parents:
diff changeset
156 maximum_free_percentage,
a61af66fc99e Initial load
duke
parents:
diff changeset
157 minimum_used_percentage);
a61af66fc99e Initial load
duke
parents:
diff changeset
158 gclog_or_tty->print_cr(" "
a61af66fc99e Initial load
duke
parents:
diff changeset
159 " _capacity_at_prologue: %6.1fK"
a61af66fc99e Initial load
duke
parents:
diff changeset
160 " minimum_desired_capacity: %6.1fK"
a61af66fc99e Initial load
duke
parents:
diff changeset
161 " maximum_desired_capacity: %6.1fK",
a61af66fc99e Initial load
duke
parents:
diff changeset
162 _capacity_at_prologue / (double) K,
a61af66fc99e Initial load
duke
parents:
diff changeset
163 minimum_desired_capacity / (double) K,
a61af66fc99e Initial load
duke
parents:
diff changeset
164 maximum_desired_capacity / (double) K);
a61af66fc99e Initial load
duke
parents:
diff changeset
165 }
a61af66fc99e Initial load
duke
parents:
diff changeset
166 assert(minimum_desired_capacity <= maximum_desired_capacity,
a61af66fc99e Initial load
duke
parents:
diff changeset
167 "sanity check");
a61af66fc99e Initial load
duke
parents:
diff changeset
168
a61af66fc99e Initial load
duke
parents:
diff changeset
169 if (capacity_after_gc > maximum_desired_capacity) {
a61af66fc99e Initial load
duke
parents:
diff changeset
170 // Capacity too large, compute shrinking size
a61af66fc99e Initial load
duke
parents:
diff changeset
171 shrink_bytes = capacity_after_gc - maximum_desired_capacity;
a61af66fc99e Initial load
duke
parents:
diff changeset
172 // We don't want shrink all the way back to initSize if people call
a61af66fc99e Initial load
duke
parents:
diff changeset
173 // System.gc(), because some programs do that between "phases" and then
a61af66fc99e Initial load
duke
parents:
diff changeset
174 // we'd just have to grow the heap up again for the next phase. So we
a61af66fc99e Initial load
duke
parents:
diff changeset
175 // damp the shrinking: 0% on the first call, 10% on the second call, 40%
a61af66fc99e Initial load
duke
parents:
diff changeset
176 // on the third call, and 100% by the fourth call. But if we recompute
a61af66fc99e Initial load
duke
parents:
diff changeset
177 // size without shrinking, it goes back to 0%.
a61af66fc99e Initial load
duke
parents:
diff changeset
178 shrink_bytes = shrink_bytes / 100 * current_shrink_factor;
a61af66fc99e Initial load
duke
parents:
diff changeset
179 assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
a61af66fc99e Initial load
duke
parents:
diff changeset
180 if (current_shrink_factor == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
181 _shrink_factor = 10;
a61af66fc99e Initial load
duke
parents:
diff changeset
182 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
183 _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100);
a61af66fc99e Initial load
duke
parents:
diff changeset
184 }
a61af66fc99e Initial load
duke
parents:
diff changeset
185 if (PrintGC && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
186 gclog_or_tty->print_cr(" "
a61af66fc99e Initial load
duke
parents:
diff changeset
187 " shrinking:"
a61af66fc99e Initial load
duke
parents:
diff changeset
188 " initSize: %.1fK"
a61af66fc99e Initial load
duke
parents:
diff changeset
189 " maximum_desired_capacity: %.1fK",
a61af66fc99e Initial load
duke
parents:
diff changeset
190 spec()->init_size() / (double) K,
a61af66fc99e Initial load
duke
parents:
diff changeset
191 maximum_desired_capacity / (double) K);
a61af66fc99e Initial load
duke
parents:
diff changeset
192 gclog_or_tty->print_cr(" "
a61af66fc99e Initial load
duke
parents:
diff changeset
193 " shrink_bytes: %.1fK"
a61af66fc99e Initial load
duke
parents:
diff changeset
194 " current_shrink_factor: %d"
a61af66fc99e Initial load
duke
parents:
diff changeset
195 " new shrink factor: %d"
a61af66fc99e Initial load
duke
parents:
diff changeset
196 " _min_heap_delta_bytes: %.1fK",
a61af66fc99e Initial load
duke
parents:
diff changeset
197 shrink_bytes / (double) K,
a61af66fc99e Initial load
duke
parents:
diff changeset
198 current_shrink_factor,
a61af66fc99e Initial load
duke
parents:
diff changeset
199 _shrink_factor,
a61af66fc99e Initial load
duke
parents:
diff changeset
200 _min_heap_delta_bytes / (double) K);
a61af66fc99e Initial load
duke
parents:
diff changeset
201 }
a61af66fc99e Initial load
duke
parents:
diff changeset
202 }
a61af66fc99e Initial load
duke
parents:
diff changeset
203 }
a61af66fc99e Initial load
duke
parents:
diff changeset
204
a61af66fc99e Initial load
duke
parents:
diff changeset
205 if (capacity_after_gc > _capacity_at_prologue) {
a61af66fc99e Initial load
duke
parents:
diff changeset
206 // We might have expanded for promotions, in which case we might want to
a61af66fc99e Initial load
duke
parents:
diff changeset
207 // take back that expansion if there's room after GC. That keeps us from
a61af66fc99e Initial load
duke
parents:
diff changeset
208 // stretching the heap with promotions when there's plenty of room.
a61af66fc99e Initial load
duke
parents:
diff changeset
209 size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue;
a61af66fc99e Initial load
duke
parents:
diff changeset
210 expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
211 // We have two shrinking computations, take the largest
a61af66fc99e Initial load
duke
parents:
diff changeset
212 shrink_bytes = MAX2(shrink_bytes, expansion_for_promotion);
a61af66fc99e Initial load
duke
parents:
diff changeset
213 assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
a61af66fc99e Initial load
duke
parents:
diff changeset
214 if (PrintGC && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
215 gclog_or_tty->print_cr(" "
a61af66fc99e Initial load
duke
parents:
diff changeset
216 " aggressive shrinking:"
a61af66fc99e Initial load
duke
parents:
diff changeset
217 " _capacity_at_prologue: %.1fK"
a61af66fc99e Initial load
duke
parents:
diff changeset
218 " capacity_after_gc: %.1fK"
a61af66fc99e Initial load
duke
parents:
diff changeset
219 " expansion_for_promotion: %.1fK"
a61af66fc99e Initial load
duke
parents:
diff changeset
220 " shrink_bytes: %.1fK",
a61af66fc99e Initial load
duke
parents:
diff changeset
221 capacity_after_gc / (double) K,
a61af66fc99e Initial load
duke
parents:
diff changeset
222 _capacity_at_prologue / (double) K,
a61af66fc99e Initial load
duke
parents:
diff changeset
223 expansion_for_promotion / (double) K,
a61af66fc99e Initial load
duke
parents:
diff changeset
224 shrink_bytes / (double) K);
a61af66fc99e Initial load
duke
parents:
diff changeset
225 }
a61af66fc99e Initial load
duke
parents:
diff changeset
226 }
a61af66fc99e Initial load
duke
parents:
diff changeset
227 // Don't shrink unless it's significant
a61af66fc99e Initial load
duke
parents:
diff changeset
228 if (shrink_bytes >= _min_heap_delta_bytes) {
a61af66fc99e Initial load
duke
parents:
diff changeset
229 shrink(shrink_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
230 }
a61af66fc99e Initial load
duke
parents:
diff changeset
231 assert(used() == used_after_gc && used_after_gc <= capacity(),
a61af66fc99e Initial load
duke
parents:
diff changeset
232 "sanity check");
a61af66fc99e Initial load
duke
parents:
diff changeset
233 }
a61af66fc99e Initial load
duke
parents:
diff changeset
234
a61af66fc99e Initial load
duke
parents:
diff changeset
235 void TenuredGeneration::gc_prologue(bool full) {
a61af66fc99e Initial load
duke
parents:
diff changeset
236 _capacity_at_prologue = capacity();
a61af66fc99e Initial load
duke
parents:
diff changeset
237 _used_at_prologue = used();
a61af66fc99e Initial load
duke
parents:
diff changeset
238 if (VerifyBeforeGC) {
a61af66fc99e Initial load
duke
parents:
diff changeset
239 verify_alloc_buffers_clean();
a61af66fc99e Initial load
duke
parents:
diff changeset
240 }
a61af66fc99e Initial load
duke
parents:
diff changeset
241 }
a61af66fc99e Initial load
duke
parents:
diff changeset
242
a61af66fc99e Initial load
duke
parents:
diff changeset
243 void TenuredGeneration::gc_epilogue(bool full) {
a61af66fc99e Initial load
duke
parents:
diff changeset
244 if (VerifyAfterGC) {
a61af66fc99e Initial load
duke
parents:
diff changeset
245 verify_alloc_buffers_clean();
a61af66fc99e Initial load
duke
parents:
diff changeset
246 }
a61af66fc99e Initial load
duke
parents:
diff changeset
247 OneContigSpaceCardGeneration::gc_epilogue(full);
a61af66fc99e Initial load
duke
parents:
diff changeset
248 }
a61af66fc99e Initial load
duke
parents:
diff changeset
249
a61af66fc99e Initial load
duke
parents:
diff changeset
250
a61af66fc99e Initial load
duke
parents:
diff changeset
251 bool TenuredGeneration::should_collect(bool full,
a61af66fc99e Initial load
duke
parents:
diff changeset
252 size_t size,
a61af66fc99e Initial load
duke
parents:
diff changeset
253 bool is_tlab) {
a61af66fc99e Initial load
duke
parents:
diff changeset
254 // This should be one big conditional or (||), but I want to be able to tell
a61af66fc99e Initial load
duke
parents:
diff changeset
255 // why it returns what it returns (without re-evaluating the conditionals
a61af66fc99e Initial load
duke
parents:
diff changeset
256 // in case they aren't idempotent), so I'm doing it this way.
a61af66fc99e Initial load
duke
parents:
diff changeset
257 // DeMorgan says it's okay.
a61af66fc99e Initial load
duke
parents:
diff changeset
258 bool result = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
259 if (!result && full) {
a61af66fc99e Initial load
duke
parents:
diff changeset
260 result = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
261 if (PrintGC && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
262 gclog_or_tty->print_cr("TenuredGeneration::should_collect: because"
a61af66fc99e Initial load
duke
parents:
diff changeset
263 " full");
a61af66fc99e Initial load
duke
parents:
diff changeset
264 }
a61af66fc99e Initial load
duke
parents:
diff changeset
265 }
a61af66fc99e Initial load
duke
parents:
diff changeset
266 if (!result && should_allocate(size, is_tlab)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
267 result = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
268 if (PrintGC && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
269 gclog_or_tty->print_cr("TenuredGeneration::should_collect: because"
a61af66fc99e Initial load
duke
parents:
diff changeset
270 " should_allocate(" SIZE_FORMAT ")",
a61af66fc99e Initial load
duke
parents:
diff changeset
271 size);
a61af66fc99e Initial load
duke
parents:
diff changeset
272 }
a61af66fc99e Initial load
duke
parents:
diff changeset
273 }
a61af66fc99e Initial load
duke
parents:
diff changeset
274 // If we don't have very much free space.
a61af66fc99e Initial load
duke
parents:
diff changeset
275 // XXX: 10000 should be a percentage of the capacity!!!
a61af66fc99e Initial load
duke
parents:
diff changeset
276 if (!result && free() < 10000) {
a61af66fc99e Initial load
duke
parents:
diff changeset
277 result = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
278 if (PrintGC && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
279 gclog_or_tty->print_cr("TenuredGeneration::should_collect: because"
a61af66fc99e Initial load
duke
parents:
diff changeset
280 " free(): " SIZE_FORMAT,
a61af66fc99e Initial load
duke
parents:
diff changeset
281 free());
a61af66fc99e Initial load
duke
parents:
diff changeset
282 }
a61af66fc99e Initial load
duke
parents:
diff changeset
283 }
a61af66fc99e Initial load
duke
parents:
diff changeset
284 // If we had to expand to accomodate promotions from younger generations
a61af66fc99e Initial load
duke
parents:
diff changeset
285 if (!result && _capacity_at_prologue < capacity()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
286 result = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
287 if (PrintGC && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
288 gclog_or_tty->print_cr("TenuredGeneration::should_collect: because"
a61af66fc99e Initial load
duke
parents:
diff changeset
289 "_capacity_at_prologue: " SIZE_FORMAT " < capacity(): " SIZE_FORMAT,
a61af66fc99e Initial load
duke
parents:
diff changeset
290 _capacity_at_prologue, capacity());
a61af66fc99e Initial load
duke
parents:
diff changeset
291 }
a61af66fc99e Initial load
duke
parents:
diff changeset
292 }
a61af66fc99e Initial load
duke
parents:
diff changeset
293 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
294 }
a61af66fc99e Initial load
duke
parents:
diff changeset
295
a61af66fc99e Initial load
duke
parents:
diff changeset
296 void TenuredGeneration::collect(bool full,
a61af66fc99e Initial load
duke
parents:
diff changeset
297 bool clear_all_soft_refs,
a61af66fc99e Initial load
duke
parents:
diff changeset
298 size_t size,
a61af66fc99e Initial load
duke
parents:
diff changeset
299 bool is_tlab) {
a61af66fc99e Initial load
duke
parents:
diff changeset
300 retire_alloc_buffers_before_full_gc();
a61af66fc99e Initial load
duke
parents:
diff changeset
301 OneContigSpaceCardGeneration::collect(full, clear_all_soft_refs,
a61af66fc99e Initial load
duke
parents:
diff changeset
302 size, is_tlab);
a61af66fc99e Initial load
duke
parents:
diff changeset
303 }
a61af66fc99e Initial load
duke
parents:
diff changeset
304
a61af66fc99e Initial load
duke
parents:
diff changeset
305 void TenuredGeneration::update_gc_stats(int current_level,
a61af66fc99e Initial load
duke
parents:
diff changeset
306 bool full) {
a61af66fc99e Initial load
duke
parents:
diff changeset
307 // If the next lower level(s) has been collected, gather any statistics
a61af66fc99e Initial load
duke
parents:
diff changeset
308 // that are of interest at this point.
a61af66fc99e Initial load
duke
parents:
diff changeset
309 if (!full && (current_level + 1) == level()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
310 // Calculate size of data promoted from the younger generations
a61af66fc99e Initial load
duke
parents:
diff changeset
311 // before doing the collection.
a61af66fc99e Initial load
duke
parents:
diff changeset
312 size_t used_before_gc = used();
a61af66fc99e Initial load
duke
parents:
diff changeset
313
a61af66fc99e Initial load
duke
parents:
diff changeset
314 // If the younger gen collections were skipped, then the
a61af66fc99e Initial load
duke
parents:
diff changeset
315 // number of promoted bytes will be 0 and adding it to the
a61af66fc99e Initial load
duke
parents:
diff changeset
316 // average will incorrectly lessen the average. It is, however,
a61af66fc99e Initial load
duke
parents:
diff changeset
317 // also possible that no promotion was needed.
a61af66fc99e Initial load
duke
parents:
diff changeset
318 if (used_before_gc >= _used_at_prologue) {
a61af66fc99e Initial load
duke
parents:
diff changeset
319 size_t promoted_in_bytes = used_before_gc - _used_at_prologue;
a61af66fc99e Initial load
duke
parents:
diff changeset
320 gc_stats()->avg_promoted()->sample(promoted_in_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
321 }
a61af66fc99e Initial load
duke
parents:
diff changeset
322 }
a61af66fc99e Initial load
duke
parents:
diff changeset
323 }
a61af66fc99e Initial load
duke
parents:
diff changeset
324
a61af66fc99e Initial load
duke
parents:
diff changeset
325 void TenuredGeneration::update_counters() {
a61af66fc99e Initial load
duke
parents:
diff changeset
326 if (UsePerfData) {
a61af66fc99e Initial load
duke
parents:
diff changeset
327 _space_counters->update_all();
a61af66fc99e Initial load
duke
parents:
diff changeset
328 _gen_counters->update_all();
a61af66fc99e Initial load
duke
parents:
diff changeset
329 }
a61af66fc99e Initial load
duke
parents:
diff changeset
330 }
a61af66fc99e Initial load
duke
parents:
diff changeset
331
a61af66fc99e Initial load
duke
parents:
diff changeset
332
a61af66fc99e Initial load
duke
parents:
diff changeset
333 #ifndef SERIALGC
a61af66fc99e Initial load
duke
parents:
diff changeset
334 oop TenuredGeneration::par_promote(int thread_num,
a61af66fc99e Initial load
duke
parents:
diff changeset
335 oop old, markOop m, size_t word_sz) {
a61af66fc99e Initial load
duke
parents:
diff changeset
336
a61af66fc99e Initial load
duke
parents:
diff changeset
337 ParGCAllocBufferWithBOT* buf = _alloc_buffers[thread_num];
a61af66fc99e Initial load
duke
parents:
diff changeset
338 HeapWord* obj_ptr = buf->allocate(word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
339 bool is_lab = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
340 if (obj_ptr == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
341 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
342 if (Universe::heap()->promotion_should_fail()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
343 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
344 }
a61af66fc99e Initial load
duke
parents:
diff changeset
345 #endif // #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
346
a61af66fc99e Initial load
duke
parents:
diff changeset
347 // Slow path:
a61af66fc99e Initial load
duke
parents:
diff changeset
348 if (word_sz * 100 < ParallelGCBufferWastePct * buf->word_sz()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
349 // Is small enough; abandon this buffer and start a new one.
a61af66fc99e Initial load
duke
parents:
diff changeset
350 size_t buf_size = buf->word_sz();
a61af66fc99e Initial load
duke
parents:
diff changeset
351 HeapWord* buf_space =
a61af66fc99e Initial load
duke
parents:
diff changeset
352 TenuredGeneration::par_allocate(buf_size, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
353 if (buf_space == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
354 buf_space = expand_and_allocate(buf_size, false, true /* parallel*/);
a61af66fc99e Initial load
duke
parents:
diff changeset
355 }
a61af66fc99e Initial load
duke
parents:
diff changeset
356 if (buf_space != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
357 buf->retire(false, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
358 buf->set_buf(buf_space);
a61af66fc99e Initial load
duke
parents:
diff changeset
359 obj_ptr = buf->allocate(word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
360 assert(obj_ptr != NULL, "Buffer was definitely big enough...");
a61af66fc99e Initial load
duke
parents:
diff changeset
361 }
a61af66fc99e Initial load
duke
parents:
diff changeset
362 };
a61af66fc99e Initial load
duke
parents:
diff changeset
363 // Otherwise, buffer allocation failed; try allocating object
a61af66fc99e Initial load
duke
parents:
diff changeset
364 // individually.
a61af66fc99e Initial load
duke
parents:
diff changeset
365 if (obj_ptr == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
366 obj_ptr = TenuredGeneration::par_allocate(word_sz, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
367 if (obj_ptr == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
368 obj_ptr = expand_and_allocate(word_sz, false, true /* parallel */);
a61af66fc99e Initial load
duke
parents:
diff changeset
369 }
a61af66fc99e Initial load
duke
parents:
diff changeset
370 }
a61af66fc99e Initial load
duke
parents:
diff changeset
371 if (obj_ptr == NULL) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
372 }
a61af66fc99e Initial load
duke
parents:
diff changeset
373 assert(obj_ptr != NULL, "program logic");
a61af66fc99e Initial load
duke
parents:
diff changeset
374 Copy::aligned_disjoint_words((HeapWord*)old, obj_ptr, word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
375 oop obj = oop(obj_ptr);
a61af66fc99e Initial load
duke
parents:
diff changeset
376 // Restore the mark word copied above.
a61af66fc99e Initial load
duke
parents:
diff changeset
377 obj->set_mark(m);
a61af66fc99e Initial load
duke
parents:
diff changeset
378 return obj;
a61af66fc99e Initial load
duke
parents:
diff changeset
379 }
a61af66fc99e Initial load
duke
parents:
diff changeset
380
a61af66fc99e Initial load
duke
parents:
diff changeset
381 void TenuredGeneration::par_promote_alloc_undo(int thread_num,
a61af66fc99e Initial load
duke
parents:
diff changeset
382 HeapWord* obj,
a61af66fc99e Initial load
duke
parents:
diff changeset
383 size_t word_sz) {
a61af66fc99e Initial load
duke
parents:
diff changeset
384 ParGCAllocBufferWithBOT* buf = _alloc_buffers[thread_num];
a61af66fc99e Initial load
duke
parents:
diff changeset
385 if (buf->contains(obj)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
386 guarantee(buf->contains(obj + word_sz - 1),
a61af66fc99e Initial load
duke
parents:
diff changeset
387 "should contain whole object");
a61af66fc99e Initial load
duke
parents:
diff changeset
388 buf->undo_allocation(obj, word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
389 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
390 SharedHeap::fill_region_with_object(MemRegion(obj, word_sz));
a61af66fc99e Initial load
duke
parents:
diff changeset
391 }
a61af66fc99e Initial load
duke
parents:
diff changeset
392 }
a61af66fc99e Initial load
duke
parents:
diff changeset
393
a61af66fc99e Initial load
duke
parents:
diff changeset
394 void TenuredGeneration::par_promote_alloc_done(int thread_num) {
a61af66fc99e Initial load
duke
parents:
diff changeset
395 ParGCAllocBufferWithBOT* buf = _alloc_buffers[thread_num];
a61af66fc99e Initial load
duke
parents:
diff changeset
396 buf->retire(true, ParallelGCRetainPLAB);
a61af66fc99e Initial load
duke
parents:
diff changeset
397 }
a61af66fc99e Initial load
duke
parents:
diff changeset
398
a61af66fc99e Initial load
duke
parents:
diff changeset
399 void TenuredGeneration::retire_alloc_buffers_before_full_gc() {
a61af66fc99e Initial load
duke
parents:
diff changeset
400 if (UseParNewGC) {
a61af66fc99e Initial load
duke
parents:
diff changeset
401 for (uint i = 0; i < ParallelGCThreads; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
402 _alloc_buffers[i]->retire(true /*end_of_gc*/, false /*retain*/);
a61af66fc99e Initial load
duke
parents:
diff changeset
403 }
a61af66fc99e Initial load
duke
parents:
diff changeset
404 }
a61af66fc99e Initial load
duke
parents:
diff changeset
405 }
a61af66fc99e Initial load
duke
parents:
diff changeset
406
a61af66fc99e Initial load
duke
parents:
diff changeset
407 // Verify that any retained parallel allocation buffers do not
a61af66fc99e Initial load
duke
parents:
diff changeset
408 // intersect with dirty cards.
a61af66fc99e Initial load
duke
parents:
diff changeset
409 void TenuredGeneration::verify_alloc_buffers_clean() {
a61af66fc99e Initial load
duke
parents:
diff changeset
410 if (UseParNewGC) {
a61af66fc99e Initial load
duke
parents:
diff changeset
411 for (uint i = 0; i < ParallelGCThreads; i++) {
6
73e96e5c30df 6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents: 0
diff changeset
412 _rs->verify_aligned_region_empty(_alloc_buffers[i]->range());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
413 }
a61af66fc99e Initial load
duke
parents:
diff changeset
414 }
a61af66fc99e Initial load
duke
parents:
diff changeset
415 }
6
73e96e5c30df 6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents: 0
diff changeset
416
0
a61af66fc99e Initial load
duke
parents:
diff changeset
417 #else // SERIALGC
a61af66fc99e Initial load
duke
parents:
diff changeset
418 void TenuredGeneration::retire_alloc_buffers_before_full_gc() {}
a61af66fc99e Initial load
duke
parents:
diff changeset
419 void TenuredGeneration::verify_alloc_buffers_clean() {}
a61af66fc99e Initial load
duke
parents:
diff changeset
420 #endif // SERIALGC
a61af66fc99e Initial load
duke
parents:
diff changeset
421
a61af66fc99e Initial load
duke
parents:
diff changeset
422 bool TenuredGeneration::promotion_attempt_is_safe(
a61af66fc99e Initial load
duke
parents:
diff changeset
423 size_t max_promotion_in_bytes,
a61af66fc99e Initial load
duke
parents:
diff changeset
424 bool younger_handles_promotion_failure) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
425
a61af66fc99e Initial load
duke
parents:
diff changeset
426 bool result = max_contiguous_available() >= max_promotion_in_bytes;
a61af66fc99e Initial load
duke
parents:
diff changeset
427
a61af66fc99e Initial load
duke
parents:
diff changeset
428 if (younger_handles_promotion_failure && !result) {
a61af66fc99e Initial load
duke
parents:
diff changeset
429 result = max_contiguous_available() >=
a61af66fc99e Initial load
duke
parents:
diff changeset
430 (size_t) gc_stats()->avg_promoted()->padded_average();
a61af66fc99e Initial load
duke
parents:
diff changeset
431 if (PrintGC && Verbose && result) {
a61af66fc99e Initial load
duke
parents:
diff changeset
432 gclog_or_tty->print_cr("TenuredGeneration::promotion_attempt_is_safe"
a61af66fc99e Initial load
duke
parents:
diff changeset
433 " contiguous_available: " SIZE_FORMAT
a61af66fc99e Initial load
duke
parents:
diff changeset
434 " avg_promoted: " SIZE_FORMAT,
a61af66fc99e Initial load
duke
parents:
diff changeset
435 max_contiguous_available(),
a61af66fc99e Initial load
duke
parents:
diff changeset
436 gc_stats()->avg_promoted()->padded_average());
a61af66fc99e Initial load
duke
parents:
diff changeset
437 }
a61af66fc99e Initial load
duke
parents:
diff changeset
438 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
439 if (PrintGC && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
440 gclog_or_tty->print_cr("TenuredGeneration::promotion_attempt_is_safe"
a61af66fc99e Initial load
duke
parents:
diff changeset
441 " contiguous_available: " SIZE_FORMAT
a61af66fc99e Initial load
duke
parents:
diff changeset
442 " promotion_in_bytes: " SIZE_FORMAT,
a61af66fc99e Initial load
duke
parents:
diff changeset
443 max_contiguous_available(), max_promotion_in_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
444 }
a61af66fc99e Initial load
duke
parents:
diff changeset
445 }
a61af66fc99e Initial load
duke
parents:
diff changeset
446 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
447 }