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