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