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