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 
 32 PSVirtualSpace::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 
 40 PSVirtualSpace::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.
 49 PSVirtualSpace::PSVirtualSpace(): _alignment(os::vm_page_size()) {
 50 }
 51 
 52 // Deprecated.
 53 bool 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 
 65 PSVirtualSpace::~PSVirtualSpace() {
 66   release();
 67 }
 68 
 69 bool PSVirtualSpace::contains(void* p) const {
 70   char* const cp = (char*)p;
 71   return cp >= committed_low_addr() && cp < committed_high_addr();
 72 }
 73 
 74 void 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 
 83 bool 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 
101 bool 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 
118 size_t
119 PSVirtualSpace::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
180 bool 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 
186 bool PSVirtualSpace::is_aligned(size_t value) const {
187   return is_aligned(value, alignment());
188 }
189 
190 bool PSVirtualSpace::is_aligned(char* value) const {
191   return is_aligned((size_t)value);
192 }
193 
194 void 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 
218 void 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 
223 PSVirtualSpaceHighToLow::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 
232 PSVirtualSpaceHighToLow::PSVirtualSpaceHighToLow(ReservedSpace rs) {
233   set_reserved(rs);
234   set_committed(reserved_high_addr(), reserved_high_addr());
235   DEBUG_ONLY(verify());
236 }
237 
238 bool 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 
256 bool 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 
273 size_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 
334 void
335 PSVirtualSpaceHighToLow::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 }