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