1 /*
   2  * Copyright (c) 2003, 2013, 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() ||
 105          os::commit_memory(base_addr, bytes, alignment(), !ExecMem);
 106   if (result) {
 107     _committed_high_addr += bytes;
 108   }
 109 
 110   return result;
 111 }
 112 
 113 bool PSVirtualSpace::shrink_by(size_t bytes) {
 114   assert(is_aligned(bytes), "arg not aligned");
 115   DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
 116 
 117   if (committed_size() < bytes) {
 118     return false;
 119   }
 120 
 121   char* const base_addr = committed_high_addr() - bytes;
 122   bool result = special() || os::uncommit_memory(base_addr, bytes);
 123   if (result) {
 124     _committed_high_addr -= bytes;
 125   }
 126 
 127   return result;
 128 }
 129 
 130 size_t
 131 PSVirtualSpace::expand_into(PSVirtualSpace* other_space, size_t bytes) {
 132   assert(is_aligned(bytes), "arg not aligned");
 133   assert(grows_up(), "this space must grow up");
 134   assert(other_space->grows_down(), "other space must grow down");
 135   assert(reserved_high_addr() == other_space->reserved_low_addr(),
 136          "spaces not contiguous");
 137   assert(special() == other_space->special(), "one space is special, the other is not");
 138   DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
 139   DEBUG_ONLY(PSVirtualSpaceVerifier other_verifier(other_space));
 140 
 141   size_t bytes_needed = bytes;
 142 
 143   // First use the uncommitted region in this space.
 144   size_t tmp_bytes = MIN2(uncommitted_size(), bytes_needed);
 145   if (tmp_bytes > 0) {
 146     if (expand_by(tmp_bytes)) {
 147       bytes_needed -= tmp_bytes;
 148     } else {
 149       return 0;
 150     }
 151   }
 152 
 153   // Next take from the uncommitted region in the other space, and commit it.
 154   tmp_bytes = MIN2(other_space->uncommitted_size(), bytes_needed);
 155   if (tmp_bytes > 0) {
 156     char* const commit_base = committed_high_addr();
 157     if (other_space->special() ||
 158         os::commit_memory(commit_base, tmp_bytes, alignment(), !ExecMem)) {
 159       // Reduce the reserved region in the other space.
 160       other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes,
 161                                 other_space->reserved_high_addr(),
 162                                 other_space->special());
 163 
 164       // Grow both reserved and committed in this space.
 165       _reserved_high_addr += tmp_bytes;
 166       _committed_high_addr += tmp_bytes;
 167       bytes_needed -= tmp_bytes;
 168     } else {
 169       return bytes - bytes_needed;
 170     }
 171   }
 172 
 173   // Finally take from the already committed region in the other space.
 174   tmp_bytes = bytes_needed;
 175   if (tmp_bytes > 0) {
 176     // Reduce both committed and reserved in the other space.
 177     other_space->set_committed(other_space->committed_low_addr() + tmp_bytes,
 178                                other_space->committed_high_addr());
 179     other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes,
 180                               other_space->reserved_high_addr(),
 181                               other_space->special());
 182 
 183     // Grow both reserved and committed in this space.
 184     _reserved_high_addr += tmp_bytes;
 185     _committed_high_addr += tmp_bytes;
 186   }
 187 
 188   return bytes;
 189 }
 190 
 191 #ifndef PRODUCT
 192 bool PSVirtualSpace::is_aligned(size_t value, size_t align) {
 193   const size_t tmp_value = value + align - 1;
 194   const size_t mask = ~(align - 1);
 195   return (tmp_value & mask) == value;
 196 }
 197 
 198 bool PSVirtualSpace::is_aligned(size_t value) const {
 199   return is_aligned(value, alignment());
 200 }
 201 
 202 bool PSVirtualSpace::is_aligned(char* value) const {
 203   return is_aligned((size_t)value);
 204 }
 205 
 206 void PSVirtualSpace::verify() const {
 207   assert(is_aligned(alignment(), os::vm_page_size()), "bad alignment");
 208   assert(is_aligned(reserved_low_addr()), "bad reserved_low_addr");
 209   assert(is_aligned(reserved_high_addr()), "bad reserved_high_addr");
 210   assert(is_aligned(committed_low_addr()), "bad committed_low_addr");
 211   assert(is_aligned(committed_high_addr()), "bad committed_high_addr");
 212 
 213   // Reserved region must be non-empty or both addrs must be 0.
 214   assert(reserved_low_addr() < reserved_high_addr() ||
 215          reserved_low_addr() == NULL && reserved_high_addr() == NULL,
 216          "bad reserved addrs");
 217   assert(committed_low_addr() <= committed_high_addr(), "bad committed addrs");
 218 
 219   if (grows_up()) {
 220     assert(reserved_low_addr() == committed_low_addr(), "bad low addrs");
 221     assert(reserved_high_addr() >= committed_high_addr(), "bad high addrs");
 222   } else {
 223     assert(reserved_high_addr() == committed_high_addr(), "bad high addrs");
 224     assert(reserved_low_addr() <= committed_low_addr(), "bad low addrs");
 225   }
 226 }
 227 
 228 void PSVirtualSpace::print() const {
 229   gclog_or_tty->print_cr("virtual space [" PTR_FORMAT "]:  alignment="
 230                          SIZE_FORMAT "K grows %s%s",
 231                          this, alignment() / K, grows_up() ? "up" : "down",
 232                          special() ? " (pinned in memory)" : "");
 233   gclog_or_tty->print_cr("    reserved=" SIZE_FORMAT "K"
 234                          " [" PTR_FORMAT "," PTR_FORMAT "]"
 235                          " committed=" SIZE_FORMAT "K"
 236                          " [" PTR_FORMAT "," PTR_FORMAT "]",
 237                          reserved_size() / K,
 238                          reserved_low_addr(), reserved_high_addr(),
 239                          committed_size() / K,
 240                          committed_low_addr(), committed_high_addr());
 241 }
 242 #endif // #ifndef PRODUCT
 243 
 244 void PSVirtualSpace::print_space_boundaries_on(outputStream* st) const {
 245   st->print_cr(" [" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT ")",
 246                low_boundary(), high(), high_boundary());
 247 }
 248 
 249 PSVirtualSpaceHighToLow::PSVirtualSpaceHighToLow(ReservedSpace rs,
 250                                                  size_t alignment) :
 251   PSVirtualSpace(alignment)
 252 {
 253   set_reserved(rs);
 254   set_committed(reserved_high_addr(), reserved_high_addr());
 255   DEBUG_ONLY(verify());
 256 }
 257 
 258 PSVirtualSpaceHighToLow::PSVirtualSpaceHighToLow(ReservedSpace rs) {
 259   set_reserved(rs);
 260   set_committed(reserved_high_addr(), reserved_high_addr());
 261   DEBUG_ONLY(verify());
 262 }
 263 
 264 bool PSVirtualSpaceHighToLow::expand_by(size_t bytes) {
 265   assert(is_aligned(bytes), "arg not aligned");
 266   DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
 267 
 268   if (uncommitted_size() < bytes) {
 269     return false;
 270   }
 271 
 272   char* const base_addr = committed_low_addr() - bytes;
 273   bool result = special() ||
 274          os::commit_memory(base_addr, bytes, alignment(), !ExecMem);
 275   if (result) {
 276     _committed_low_addr -= bytes;
 277   }
 278 
 279   return result;
 280 }
 281 
 282 bool PSVirtualSpaceHighToLow::shrink_by(size_t bytes) {
 283   assert(is_aligned(bytes), "arg not aligned");
 284   DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
 285 
 286   if (committed_size() < bytes) {
 287     return false;
 288   }
 289 
 290   char* const base_addr = committed_low_addr();
 291   bool result = special() || os::uncommit_memory(base_addr, bytes);
 292   if (result) {
 293     _committed_low_addr += bytes;
 294   }
 295 
 296   return result;
 297 }
 298 
 299 size_t PSVirtualSpaceHighToLow::expand_into(PSVirtualSpace* other_space,
 300                                             size_t bytes) {
 301   assert(is_aligned(bytes), "arg not aligned");
 302   assert(grows_down(), "this space must grow down");
 303   assert(other_space->grows_up(), "other space must grow up");
 304   assert(reserved_low_addr() == other_space->reserved_high_addr(),
 305          "spaces not contiguous");
 306   assert(special() == other_space->special(), "one space is special in memory, the other is not");
 307   DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
 308   DEBUG_ONLY(PSVirtualSpaceVerifier other_verifier(other_space));
 309 
 310   size_t bytes_needed = bytes;
 311 
 312   // First use the uncommitted region in this space.
 313   size_t tmp_bytes = MIN2(uncommitted_size(), bytes_needed);
 314   if (tmp_bytes > 0) {
 315     if (expand_by(tmp_bytes)) {
 316       bytes_needed -= tmp_bytes;
 317     } else {
 318       return 0;
 319     }
 320   }
 321 
 322   // Next take from the uncommitted region in the other space, and commit it.
 323   tmp_bytes = MIN2(other_space->uncommitted_size(), bytes_needed);
 324   if (tmp_bytes > 0) {
 325     char* const commit_base = committed_low_addr() - tmp_bytes;
 326     if (other_space->special() ||
 327         os::commit_memory(commit_base, tmp_bytes, alignment(), !ExecMem)) {
 328       // Reduce the reserved region in the other space.
 329       other_space->set_reserved(other_space->reserved_low_addr(),
 330                                 other_space->reserved_high_addr() - tmp_bytes,
 331                                 other_space->special());
 332 
 333       // Grow both reserved and committed in this space.
 334       _reserved_low_addr -= tmp_bytes;
 335       _committed_low_addr -= tmp_bytes;
 336       bytes_needed -= tmp_bytes;
 337     } else {
 338       return bytes - bytes_needed;
 339     }
 340   }
 341 
 342   // Finally take from the already committed region in the other space.
 343   tmp_bytes = bytes_needed;
 344   if (tmp_bytes > 0) {
 345     // Reduce both committed and reserved in the other space.
 346     other_space->set_committed(other_space->committed_low_addr(),
 347                                other_space->committed_high_addr() - tmp_bytes);
 348     other_space->set_reserved(other_space->reserved_low_addr(),
 349                               other_space->reserved_high_addr() - tmp_bytes,
 350                               other_space->special());
 351 
 352     // Grow both reserved and committed in this space.
 353     _reserved_low_addr -= tmp_bytes;
 354     _committed_low_addr -= tmp_bytes;
 355   }
 356 
 357   return bytes;
 358 }
 359 
 360 void
 361 PSVirtualSpaceHighToLow::print_space_boundaries_on(outputStream* st) const {
 362   st->print_cr(" (" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT "]",
 363                high_boundary(), low(), low_boundary());
 364 }