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