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