src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp

Sun, 25 Sep 2011 16:03:29 -0700

author
never
date
Sun, 25 Sep 2011 16:03:29 -0700
changeset 3156
f08d439fab8c
parent 2314
f95d63e2154a
child 5255
a837fa3d3f86
permissions
-rw-r--r--

7089790: integrate bsd-port changes
Reviewed-by: kvn, twisti, jrose
Contributed-by: Kurt Miller <kurt@intricatesoftware.com>, Greg Lewis <glewis@eyesbeyond.com>, Jung-uk Kim <jkim@freebsd.org>, Christos Zoulas <christos@zoulas.com>, Landon Fuller <landonf@plausible.coop>, The FreeBSD Foundation <board@freebsdfoundation.org>, Michael Franz <mvfranz@gmail.com>, Roger Hoover <rhoover@apple.com>, Alexander Strange <astrange@apple.com>

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

mercurial