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

Fri, 11 Mar 2011 16:35:18 +0100

author
jwilhelm
date
Fri, 11 Mar 2011 16:35:18 +0100
changeset 2648
1fb790245268
parent 2314
f95d63e2154a
child 3156
f08d439fab8c
permissions
-rw-r--r--

6820066: Check that -XX:ParGCArrayScanChunk has a value larger than zero.
Summary: Check that -XX:ParGCArrayScanChunk has a value larger than zero.
Reviewed-by: johnc, jmasa, ysr

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

mercurial