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 #endif // #ifndef PRODUCT
 217 
 218 void PSVirtualSpace::print_space_boundaries_on(outputStream* st) const {
 219   st->print_cr(" [" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT ")",
 220                p2i(low_boundary()), p2i(high()), p2i(high_boundary()));
 221 }
 222 
 223 PSVirtualSpaceHighToLow::PSVirtualSpaceHighToLow(ReservedSpace rs,
 224                                                  size_t alignment) :
 225   PSVirtualSpace(alignment)
 226 {
 227   set_reserved(rs);
 228   set_committed(reserved_high_addr(), reserved_high_addr());
 229   DEBUG_ONLY(verify());
 230 }
 231 
 232 PSVirtualSpaceHighToLow::PSVirtualSpaceHighToLow(ReservedSpace rs) {
 233   set_reserved(rs);
 234   set_committed(reserved_high_addr(), reserved_high_addr());
 235   DEBUG_ONLY(verify());
 236 }
 237 
 238 bool PSVirtualSpaceHighToLow::expand_by(size_t bytes) {
 239   assert(is_aligned(bytes), "arg not aligned");
 240   DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
 241 
 242   if (uncommitted_size() < bytes) {
 243     return false;
 244   }
 245 
 246   char* const base_addr = committed_low_addr() - bytes;
 247   bool result = special() ||
 248          os::commit_memory(base_addr, bytes, alignment(), !ExecMem);
 249   if (result) {
 250     _committed_low_addr -= bytes;
 251   }
 252 
 253   return result;
 254 }
 255 
 256 bool PSVirtualSpaceHighToLow::shrink_by(size_t bytes) {
 257   assert(is_aligned(bytes), "arg not aligned");
 258   DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
 259 
 260   if (committed_size() < bytes) {
 261     return false;
 262   }
 263 
 264   char* const base_addr = committed_low_addr();
 265   bool result = special() || os::uncommit_memory(base_addr, bytes);
 266   if (result) {
 267     _committed_low_addr += bytes;
 268   }
 269 
 270   return result;
 271 }
 272 
 273 size_t PSVirtualSpaceHighToLow::expand_into(PSVirtualSpace* other_space,
 274                                             size_t bytes) {
 275   assert(is_aligned(bytes), "arg not aligned");
 276   assert(grows_down(), "this space must grow down");
 277   assert(other_space->grows_up(), "other space must grow up");
 278   assert(reserved_low_addr() == other_space->reserved_high_addr(),
 279          "spaces not contiguous");
 280   assert(special() == other_space->special(), "one space is special in memory, the other is not");
 281   DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
 282   DEBUG_ONLY(PSVirtualSpaceVerifier other_verifier(other_space));
 283 
 284   size_t bytes_needed = bytes;
 285 
 286   // First use the uncommitted region in this space.
 287   size_t tmp_bytes = MIN2(uncommitted_size(), bytes_needed);
 288   if (tmp_bytes > 0) {
 289     if (expand_by(tmp_bytes)) {
 290       bytes_needed -= tmp_bytes;
 291     } else {
 292       return 0;
 293     }
 294   }
 295 
 296   // Next take from the uncommitted region in the other space, and commit it.
 297   tmp_bytes = MIN2(other_space->uncommitted_size(), bytes_needed);
 298   if (tmp_bytes > 0) {
 299     char* const commit_base = committed_low_addr() - tmp_bytes;
 300     if (other_space->special() ||
 301         os::commit_memory(commit_base, tmp_bytes, alignment(), !ExecMem)) {
 302       // Reduce the reserved region in the other space.
 303       other_space->set_reserved(other_space->reserved_low_addr(),
 304                                 other_space->reserved_high_addr() - tmp_bytes,
 305                                 other_space->special());
 306 
 307       // Grow both reserved and committed in this space.
 308       _reserved_low_addr -= tmp_bytes;
 309       _committed_low_addr -= tmp_bytes;
 310       bytes_needed -= tmp_bytes;
 311     } else {
 312       return bytes - bytes_needed;
 313     }
 314   }
 315 
 316   // Finally take from the already committed region in the other space.
 317   tmp_bytes = bytes_needed;
 318   if (tmp_bytes > 0) {
 319     // Reduce both committed and reserved in the other space.
 320     other_space->set_committed(other_space->committed_low_addr(),
 321                                other_space->committed_high_addr() - tmp_bytes);
 322     other_space->set_reserved(other_space->reserved_low_addr(),
 323                               other_space->reserved_high_addr() - tmp_bytes,
 324                               other_space->special());
 325 
 326     // Grow both reserved and committed in this space.
 327     _reserved_low_addr -= tmp_bytes;
 328     _committed_low_addr -= tmp_bytes;
 329   }
 330 
 331   return bytes;
 332 }
 333 
 334 void
 335 PSVirtualSpaceHighToLow::print_space_boundaries_on(outputStream* st) const {
 336   st->print_cr(" (" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT "]",
 337                p2i(high_boundary()), p2i(low()), p2i(low_boundary()));
 338 }
--- EOF ---