1/*
2 * Copyright (c) 2003, 2019, 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/psVirtualspace.hpp"
27#include "memory/virtualspace.hpp"
28#include "runtime/os.hpp"
29
30// PSVirtualSpace
31
32PSVirtualSpace::PSVirtualSpace(ReservedSpace rs, size_t alignment) :
33 _alignment(alignment)
34{
35 set_reserved(rs);
36 set_committed(reserved_low_addr(), reserved_low_addr());
37 DEBUG_ONLY(verify());
38}
39
40PSVirtualSpace::PSVirtualSpace(ReservedSpace rs) :
41 _alignment(os::vm_page_size())
42{
43 set_reserved(rs);
44 set_committed(reserved_low_addr(), reserved_low_addr());
45 DEBUG_ONLY(verify());
46}
47
48// Deprecated.
49PSVirtualSpace::PSVirtualSpace():
50 _alignment(os::vm_page_size()),
51 _reserved_low_addr(NULL),
52 _reserved_high_addr(NULL),
53 _committed_low_addr(NULL),
54 _committed_high_addr(NULL),
55 _special(false) {
56}
57
58// Deprecated.
59bool PSVirtualSpace::initialize(ReservedSpace rs,
60 size_t commit_size) {
61 set_reserved(rs);
62 set_committed(reserved_low_addr(), reserved_low_addr());
63
64 // Commit to initial size.
65 assert(commit_size <= rs.size(), "commit_size too big");
66 bool result = commit_size > 0 ? expand_by(commit_size) : true;
67 DEBUG_ONLY(verify());
68 return result;
69}
70
71PSVirtualSpace::~PSVirtualSpace() {
72 release();
73}
74
75bool PSVirtualSpace::contains(void* p) const {
76 char* const cp = (char*)p;
77 return cp >= committed_low_addr() && cp < committed_high_addr();
78}
79
80void PSVirtualSpace::release() {
81 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
82 // This may not release memory it didn't reserve.
83 // Use rs.release() to release the underlying memory instead.
84 _reserved_low_addr = _reserved_high_addr = NULL;
85 _committed_low_addr = _committed_high_addr = NULL;
86 _special = false;
87}
88
89bool PSVirtualSpace::expand_by(size_t bytes) {
90 assert(is_aligned(bytes), "arg not aligned");
91 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
92
93 if (uncommitted_size() < bytes) {
94 return false;
95 }
96
97 char* const base_addr = committed_high_addr();
98 bool result = special() ||
99 os::commit_memory(base_addr, bytes, alignment(), !ExecMem);
100 if (result) {
101 _committed_high_addr += bytes;
102 }
103
104 return result;
105}
106
107bool PSVirtualSpace::shrink_by(size_t bytes) {
108 assert(is_aligned(bytes), "arg not aligned");
109 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
110
111 if (committed_size() < bytes) {
112 return false;
113 }
114
115 char* const base_addr = committed_high_addr() - bytes;
116 bool result = special() || os::uncommit_memory(base_addr, bytes);
117 if (result) {
118 _committed_high_addr -= bytes;
119 }
120
121 return result;
122}
123
124size_t
125PSVirtualSpace::expand_into(PSVirtualSpace* other_space, size_t bytes) {
126 assert(is_aligned(bytes), "arg not aligned");
127 assert(grows_up(), "this space must grow up");
128 assert(other_space->grows_down(), "other space must grow down");
129 assert(reserved_high_addr() == other_space->reserved_low_addr(),
130 "spaces not contiguous");
131 assert(special() == other_space->special(), "one space is special, the other is not");
132 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
133 DEBUG_ONLY(PSVirtualSpaceVerifier other_verifier(other_space));
134
135 size_t bytes_needed = bytes;
136
137 // First use the uncommitted region in this space.
138 size_t tmp_bytes = MIN2(uncommitted_size(), bytes_needed);
139 if (tmp_bytes > 0) {
140 if (expand_by(tmp_bytes)) {
141 bytes_needed -= tmp_bytes;
142 } else {
143 return 0;
144 }
145 }
146
147 // Next take from the uncommitted region in the other space, and commit it.
148 tmp_bytes = MIN2(other_space->uncommitted_size(), bytes_needed);
149 if (tmp_bytes > 0) {
150 char* const commit_base = committed_high_addr();
151 if (other_space->special() ||
152 os::commit_memory(commit_base, tmp_bytes, alignment(), !ExecMem)) {
153 // Reduce the reserved region in the other space.
154 other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes,
155 other_space->reserved_high_addr(),
156 other_space->special());
157
158 // Grow both reserved and committed in this space.
159 _reserved_high_addr += tmp_bytes;
160 _committed_high_addr += tmp_bytes;
161 bytes_needed -= tmp_bytes;
162 } else {
163 return bytes - bytes_needed;
164 }
165 }
166
167 // Finally take from the already committed region in the other space.
168 tmp_bytes = bytes_needed;
169 if (tmp_bytes > 0) {
170 // Reduce both committed and reserved in the other space.
171 other_space->set_committed(other_space->committed_low_addr() + tmp_bytes,
172 other_space->committed_high_addr());
173 other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes,
174 other_space->reserved_high_addr(),
175 other_space->special());
176
177 // Grow both reserved and committed in this space.
178 _reserved_high_addr += tmp_bytes;
179 _committed_high_addr += tmp_bytes;
180 }
181
182 return bytes;
183}
184
185#ifndef PRODUCT
186bool PSVirtualSpace::is_aligned(size_t value, size_t align) {
187 const size_t tmp_value = value + align - 1;
188 const size_t mask = ~(align - 1);
189 return (tmp_value & mask) == value;
190}
191
192bool PSVirtualSpace::is_aligned(size_t value) const {
193 return is_aligned(value, alignment());
194}
195
196bool PSVirtualSpace::is_aligned(char* value) const {
197 return is_aligned((size_t)value);
198}
199
200void PSVirtualSpace::verify() const {
201 assert(is_aligned(alignment(), os::vm_page_size()), "bad alignment");
202 assert(is_aligned(reserved_low_addr()), "bad reserved_low_addr");
203 assert(is_aligned(reserved_high_addr()), "bad reserved_high_addr");
204 assert(is_aligned(committed_low_addr()), "bad committed_low_addr");
205 assert(is_aligned(committed_high_addr()), "bad committed_high_addr");
206
207 // Reserved region must be non-empty or both addrs must be 0.
208 assert(reserved_low_addr() < reserved_high_addr() ||
209 reserved_low_addr() == NULL && reserved_high_addr() == NULL,
210 "bad reserved addrs");
211 assert(committed_low_addr() <= committed_high_addr(), "bad committed addrs");
212
213 if (grows_up()) {
214 assert(reserved_low_addr() == committed_low_addr(), "bad low addrs");
215 assert(reserved_high_addr() >= committed_high_addr(), "bad high addrs");
216 } else {
217 assert(reserved_high_addr() == committed_high_addr(), "bad high addrs");
218 assert(reserved_low_addr() <= committed_low_addr(), "bad low addrs");
219 }
220}
221
222#endif // #ifndef PRODUCT
223
224void PSVirtualSpace::print_space_boundaries_on(outputStream* st) const {
225 st->print_cr(" [" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT ")",
226 p2i(low_boundary()), p2i(high()), p2i(high_boundary()));
227}
228
229PSVirtualSpaceHighToLow::PSVirtualSpaceHighToLow(ReservedSpace rs,
230 size_t alignment) :
231 PSVirtualSpace(alignment)
232{
233 set_reserved(rs);
234 set_committed(reserved_high_addr(), reserved_high_addr());
235 DEBUG_ONLY(verify());
236}
237
238PSVirtualSpaceHighToLow::PSVirtualSpaceHighToLow(ReservedSpace rs) {
239 set_reserved(rs);
240 set_committed(reserved_high_addr(), reserved_high_addr());
241 DEBUG_ONLY(verify());
242}
243
244bool PSVirtualSpaceHighToLow::expand_by(size_t bytes) {
245 assert(is_aligned(bytes), "arg not aligned");
246 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
247
248 if (uncommitted_size() < bytes) {
249 return false;
250 }
251
252 char* const base_addr = committed_low_addr() - bytes;
253 bool result = special() ||
254 os::commit_memory(base_addr, bytes, alignment(), !ExecMem);
255 if (result) {
256 _committed_low_addr -= bytes;
257 }
258
259 return result;
260}
261
262bool PSVirtualSpaceHighToLow::shrink_by(size_t bytes) {
263 assert(is_aligned(bytes), "arg not aligned");
264 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
265
266 if (committed_size() < bytes) {
267 return false;
268 }
269
270 char* const base_addr = committed_low_addr();
271 bool result = special() || os::uncommit_memory(base_addr, bytes);
272 if (result) {
273 _committed_low_addr += bytes;
274 }
275
276 return result;
277}
278
279size_t PSVirtualSpaceHighToLow::expand_into(PSVirtualSpace* other_space,
280 size_t bytes) {
281 assert(is_aligned(bytes), "arg not aligned");
282 assert(grows_down(), "this space must grow down");
283 assert(other_space->grows_up(), "other space must grow up");
284 assert(reserved_low_addr() == other_space->reserved_high_addr(),
285 "spaces not contiguous");
286 assert(special() == other_space->special(), "one space is special in memory, the other is not");
287 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
288 DEBUG_ONLY(PSVirtualSpaceVerifier other_verifier(other_space));
289
290 size_t bytes_needed = bytes;
291
292 // First use the uncommitted region in this space.
293 size_t tmp_bytes = MIN2(uncommitted_size(), bytes_needed);
294 if (tmp_bytes > 0) {
295 if (expand_by(tmp_bytes)) {
296 bytes_needed -= tmp_bytes;
297 } else {
298 return 0;
299 }
300 }
301
302 // Next take from the uncommitted region in the other space, and commit it.
303 tmp_bytes = MIN2(other_space->uncommitted_size(), bytes_needed);
304 if (tmp_bytes > 0) {
305 char* const commit_base = committed_low_addr() - tmp_bytes;
306 if (other_space->special() ||
307 os::commit_memory(commit_base, tmp_bytes, alignment(), !ExecMem)) {
308 // Reduce the reserved region in the other space.
309 other_space->set_reserved(other_space->reserved_low_addr(),
310 other_space->reserved_high_addr() - tmp_bytes,
311 other_space->special());
312
313 // Grow both reserved and committed in this space.
314 _reserved_low_addr -= tmp_bytes;
315 _committed_low_addr -= tmp_bytes;
316 bytes_needed -= tmp_bytes;
317 } else {
318 return bytes - bytes_needed;
319 }
320 }
321
322 // Finally take from the already committed region in the other space.
323 tmp_bytes = bytes_needed;
324 if (tmp_bytes > 0) {
325 // Reduce both committed and reserved in the other space.
326 other_space->set_committed(other_space->committed_low_addr(),
327 other_space->committed_high_addr() - tmp_bytes);
328 other_space->set_reserved(other_space->reserved_low_addr(),
329 other_space->reserved_high_addr() - tmp_bytes,
330 other_space->special());
331
332 // Grow both reserved and committed in this space.
333 _reserved_low_addr -= tmp_bytes;
334 _committed_low_addr -= tmp_bytes;
335 }
336
337 return bytes;
338}
339
340void
341PSVirtualSpaceHighToLow::print_space_boundaries_on(outputStream* st) const {
342 st->print_cr(" (" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT "]",
343 p2i(high_boundary()), p2i(low()), p2i(low_boundary()));
344}
345