Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.cpp
38920 views
1
/*
2
* Copyright (c) 2003, 2014, 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_implementation/parallelScavenge/adjoiningGenerations.hpp"
27
#include "gc_implementation/parallelScavenge/adjoiningVirtualSpaces.hpp"
28
#include "gc_implementation/parallelScavenge/generationSizer.hpp"
29
#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
30
31
// If boundary moving is being used, create the young gen and old
32
// gen with ASPSYoungGen and ASPSOldGen, respectively. Revert to
33
// the old behavior otherwise (with PSYoungGen and PSOldGen).
34
35
AdjoiningGenerations::AdjoiningGenerations(ReservedSpace old_young_rs,
36
GenerationSizer* policy,
37
size_t alignment) :
38
_virtual_spaces(old_young_rs, policy->min_gen1_size(),
39
policy->min_gen0_size(), alignment) {
40
size_t init_low_byte_size = policy->initial_gen1_size();
41
size_t min_low_byte_size = policy->min_gen1_size();
42
size_t max_low_byte_size = policy->max_gen1_size();
43
size_t init_high_byte_size = policy->initial_gen0_size();
44
size_t min_high_byte_size = policy->min_gen0_size();
45
size_t max_high_byte_size = policy->max_gen0_size();
46
47
assert(min_low_byte_size <= init_low_byte_size &&
48
init_low_byte_size <= max_low_byte_size, "Parameter check");
49
assert(min_high_byte_size <= init_high_byte_size &&
50
init_high_byte_size <= max_high_byte_size, "Parameter check");
51
// Create the generations differently based on the option to
52
// move the boundary.
53
if (UseAdaptiveGCBoundary) {
54
// Initialize the adjoining virtual spaces. Then pass the
55
// a virtual to each generation for initialization of the
56
// generation.
57
58
// Does the actual creation of the virtual spaces
59
_virtual_spaces.initialize(max_low_byte_size,
60
init_low_byte_size,
61
init_high_byte_size);
62
63
// Place the young gen at the high end. Passes in the virtual space.
64
_young_gen = new ASPSYoungGen(_virtual_spaces.high(),
65
_virtual_spaces.high()->committed_size(),
66
min_high_byte_size,
67
_virtual_spaces.high_byte_size_limit());
68
69
// Place the old gen at the low end. Passes in the virtual space.
70
_old_gen = new ASPSOldGen(_virtual_spaces.low(),
71
_virtual_spaces.low()->committed_size(),
72
min_low_byte_size,
73
_virtual_spaces.low_byte_size_limit(),
74
"old", 1);
75
76
young_gen()->initialize_work();
77
assert(young_gen()->reserved().byte_size() <= young_gen()->gen_size_limit(),
78
"Consistency check");
79
assert(old_young_rs.size() >= young_gen()->gen_size_limit(),
80
"Consistency check");
81
82
old_gen()->initialize_work("old", 1);
83
assert(old_gen()->reserved().byte_size() <= old_gen()->gen_size_limit(),
84
"Consistency check");
85
assert(old_young_rs.size() >= old_gen()->gen_size_limit(),
86
"Consistency check");
87
} else {
88
89
// Layout the reserved space for the generations.
90
ReservedSpace old_rs =
91
virtual_spaces()->reserved_space().first_part(max_low_byte_size);
92
ReservedSpace heap_rs =
93
virtual_spaces()->reserved_space().last_part(max_low_byte_size);
94
ReservedSpace young_rs = heap_rs.first_part(max_high_byte_size);
95
assert(young_rs.size() == heap_rs.size(), "Didn't reserve all of the heap");
96
97
// Create the generations. Virtual spaces are not passed in.
98
_young_gen = new PSYoungGen(init_high_byte_size,
99
min_high_byte_size,
100
max_high_byte_size);
101
_old_gen = new PSOldGen(init_low_byte_size,
102
min_low_byte_size,
103
max_low_byte_size,
104
"old", 1);
105
106
// The virtual spaces are created by the initialization of the gens.
107
_young_gen->initialize(young_rs, alignment);
108
assert(young_gen()->gen_size_limit() == young_rs.size(),
109
"Consistency check");
110
_old_gen->initialize(old_rs, alignment, "old", 1);
111
assert(old_gen()->gen_size_limit() == old_rs.size(), "Consistency check");
112
}
113
}
114
115
size_t AdjoiningGenerations::reserved_byte_size() {
116
return virtual_spaces()->reserved_space().size();
117
}
118
119
120
// Make checks on the current sizes of the generations and
121
// the contraints on the sizes of the generations. Push
122
// up the boundary within the contraints. A partial
123
// push can occur.
124
void AdjoiningGenerations::request_old_gen_expansion(size_t expand_in_bytes) {
125
assert(UseAdaptiveSizePolicy && UseAdaptiveGCBoundary, "runtime check");
126
127
assert_lock_strong(ExpandHeap_lock);
128
assert_locked_or_safepoint(Heap_lock);
129
130
// These sizes limit the amount the boundaries can move. Effectively,
131
// the generation says how much it is willing to yield to the other
132
// generation.
133
const size_t young_gen_available = young_gen()->available_for_contraction();
134
const size_t old_gen_available = old_gen()->available_for_expansion();
135
const size_t alignment = virtual_spaces()->alignment();
136
size_t change_in_bytes = MIN3(young_gen_available,
137
old_gen_available,
138
align_size_up_(expand_in_bytes, alignment));
139
140
if (change_in_bytes == 0) {
141
return;
142
}
143
144
if (TraceAdaptiveGCBoundary) {
145
gclog_or_tty->print_cr("Before expansion of old gen with boundary move");
146
gclog_or_tty->print_cr(" Requested change: " SIZE_FORMAT_HEX " Attempted change: " SIZE_FORMAT_HEX,
147
expand_in_bytes, change_in_bytes);
148
if (!PrintHeapAtGC) {
149
Universe::print_on(gclog_or_tty);
150
}
151
gclog_or_tty->print_cr(" PSOldGen max size: " SIZE_FORMAT "K",
152
old_gen()->max_gen_size()/K);
153
}
154
155
// Move the boundary between the generations up (smaller young gen).
156
if (virtual_spaces()->adjust_boundary_up(change_in_bytes)) {
157
young_gen()->reset_after_change();
158
old_gen()->reset_after_change();
159
}
160
161
// The total reserved for the generations should match the sum
162
// of the two even if the boundary is moving.
163
assert(reserved_byte_size() ==
164
old_gen()->max_gen_size() + young_gen()->max_size(),
165
"Space is missing");
166
young_gen()->space_invariants();
167
old_gen()->space_invariants();
168
169
if (TraceAdaptiveGCBoundary) {
170
gclog_or_tty->print_cr("After expansion of old gen with boundary move");
171
if (!PrintHeapAtGC) {
172
Universe::print_on(gclog_or_tty);
173
}
174
gclog_or_tty->print_cr(" PSOldGen max size: " SIZE_FORMAT "K",
175
old_gen()->max_gen_size()/K);
176
}
177
}
178
179
// See comments on request_old_gen_expansion()
180
bool AdjoiningGenerations::request_young_gen_expansion(size_t expand_in_bytes) {
181
assert(UseAdaptiveSizePolicy && UseAdaptiveGCBoundary, "runtime check");
182
183
// If eden is not empty, the boundary can be moved but no advantage
184
// can be made of the move since eden cannot be moved.
185
if (!young_gen()->eden_space()->is_empty()) {
186
return false;
187
}
188
189
190
bool result = false;
191
const size_t young_gen_available = young_gen()->available_for_expansion();
192
const size_t old_gen_available = old_gen()->available_for_contraction();
193
const size_t alignment = virtual_spaces()->alignment();
194
size_t change_in_bytes = MIN3(young_gen_available,
195
old_gen_available,
196
align_size_up_(expand_in_bytes, alignment));
197
198
if (change_in_bytes == 0) {
199
return false;
200
}
201
202
if (TraceAdaptiveGCBoundary) {
203
gclog_or_tty->print_cr("Before expansion of young gen with boundary move");
204
gclog_or_tty->print_cr(" Requested change: " SIZE_FORMAT_HEX " Attempted change: " SIZE_FORMAT_HEX,
205
expand_in_bytes, change_in_bytes);
206
if (!PrintHeapAtGC) {
207
Universe::print_on(gclog_or_tty);
208
}
209
gclog_or_tty->print_cr(" PSYoungGen max size: " SIZE_FORMAT "K",
210
young_gen()->max_size()/K);
211
}
212
213
// Move the boundary between the generations down (smaller old gen).
214
MutexLocker x(ExpandHeap_lock);
215
if (virtual_spaces()->adjust_boundary_down(change_in_bytes)) {
216
young_gen()->reset_after_change();
217
old_gen()->reset_after_change();
218
result = true;
219
}
220
221
// The total reserved for the generations should match the sum
222
// of the two even if the boundary is moving.
223
assert(reserved_byte_size() ==
224
old_gen()->max_gen_size() + young_gen()->max_size(),
225
"Space is missing");
226
young_gen()->space_invariants();
227
old_gen()->space_invariants();
228
229
if (TraceAdaptiveGCBoundary) {
230
gclog_or_tty->print_cr("After expansion of young gen with boundary move");
231
if (!PrintHeapAtGC) {
232
Universe::print_on(gclog_or_tty);
233
}
234
gclog_or_tty->print_cr(" PSYoungGen max size: " SIZE_FORMAT "K",
235
young_gen()->max_size()/K);
236
}
237
238
return result;
239
}
240
241
// Additional space is needed in the old generation. Try to move the boundary
242
// up to meet the need. Moves boundary up only
243
void AdjoiningGenerations::adjust_boundary_for_old_gen_needs(
244
size_t desired_free_space) {
245
assert(UseAdaptiveSizePolicy && UseAdaptiveGCBoundary, "runtime check");
246
247
// Stress testing.
248
if (PSAdaptiveSizePolicyResizeVirtualSpaceAlot == 1) {
249
MutexLocker x(ExpandHeap_lock);
250
request_old_gen_expansion(virtual_spaces()->alignment() * 3 / 2);
251
}
252
253
// Expand only if the entire generation is already committed.
254
if (old_gen()->virtual_space()->uncommitted_size() == 0) {
255
if (old_gen()->free_in_bytes() < desired_free_space) {
256
MutexLocker x(ExpandHeap_lock);
257
request_old_gen_expansion(desired_free_space);
258
}
259
}
260
}
261
262
// See comment on adjust_boundary_for_old_gen_needss().
263
// Adjust boundary down only.
264
void AdjoiningGenerations::adjust_boundary_for_young_gen_needs(size_t eden_size,
265
size_t survivor_size) {
266
267
assert(UseAdaptiveSizePolicy && UseAdaptiveGCBoundary, "runtime check");
268
269
// Stress testing.
270
if (PSAdaptiveSizePolicyResizeVirtualSpaceAlot == 0) {
271
request_young_gen_expansion(virtual_spaces()->alignment() * 3 / 2);
272
eden_size = young_gen()->eden_space()->capacity_in_bytes();
273
}
274
275
// Expand only if the entire generation is already committed.
276
if (young_gen()->virtual_space()->uncommitted_size() == 0) {
277
size_t desired_size = eden_size + 2 * survivor_size;
278
const size_t committed = young_gen()->virtual_space()->committed_size();
279
if (desired_size > committed) {
280
request_young_gen_expansion(desired_size - committed);
281
}
282
}
283
}
284
285