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

Mon, 01 Dec 2008 23:25:24 -0800

author
ysr
date
Mon, 01 Dec 2008 23:25:24 -0800
changeset 892
27a80744a83b
parent 772
9ee9cf798b59
child 970
4e400c36026f
permissions
-rw-r--r--

6778647: snap(), snap_policy() should be renamed setup(), setup_policy()
Summary: Renamed Reference{Policy,Pocessor} methods from snap{,_policy}() to setup{,_policy}()
Reviewed-by: apetrusenko

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

mercurial