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

Fri, 28 Mar 2008 23:35:42 -0700

author
jcoomes
date
Fri, 28 Mar 2008 23:35:42 -0700
changeset 514
82db0859acbe
parent 435
a61af66fc99e
child 672
1fdb98a17101
permissions
-rw-r--r--

6642862: Code cache allocation fails with large pages after 6588638
Reviewed-by: apetrusenko

     1 /*
     2  * Copyright 2003-2005 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   if (reserved_low_addr() != NULL) {
    75     if (special()) {
    76       os::release_memory_special(reserved_low_addr(), reserved_size());
    77     } else {
    78       (void)os::release_memory(reserved_low_addr(), reserved_size());
    79     }
    80   }
    81   _reserved_low_addr = _reserved_high_addr = NULL;
    82   _committed_low_addr = _committed_high_addr = NULL;
    83   _special = false;
    84 }
    86 bool PSVirtualSpace::expand_by(size_t bytes, bool pre_touch) {
    87   assert(is_aligned(bytes), "arg not aligned");
    88   DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
    90   if (uncommitted_size() < bytes) {
    91     return false;
    92   }
    94   char* const base_addr = committed_high_addr();
    95   bool result = special() || os::commit_memory(base_addr, bytes, alignment());
    96   if (result) {
    97     _committed_high_addr += bytes;
    98   }
   100   if (pre_touch || AlwaysPreTouch) {
   101     for (char* curr = base_addr;
   102          curr < _committed_high_addr;
   103          curr += os::vm_page_size()) {
   104       char tmp = *curr;
   105       *curr = 0;
   106     }
   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, bool pre_touch) {
   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   if (pre_touch || AlwaysPreTouch) {
   278     for (char* curr = base_addr;
   279          curr < _committed_high_addr;
   280          curr += os::vm_page_size()) {
   281       char tmp = *curr;
   282       *curr = 0;
   283     }
   284   }
   286   return result;
   287 }
   289 bool PSVirtualSpaceHighToLow::shrink_by(size_t bytes) {
   290   assert(is_aligned(bytes), "arg not aligned");
   291   DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
   293   if (committed_size() < bytes) {
   294     return false;
   295   }
   297   char* const base_addr = committed_low_addr();
   298   bool result = special() || os::uncommit_memory(base_addr, bytes);
   299   if (result) {
   300     _committed_low_addr += bytes;
   301   }
   303   return result;
   304 }
   306 size_t PSVirtualSpaceHighToLow::expand_into(PSVirtualSpace* other_space,
   307                                             size_t bytes) {
   308   assert(is_aligned(bytes), "arg not aligned");
   309   assert(grows_down(), "this space must grow down");
   310   assert(other_space->grows_up(), "other space must grow up");
   311   assert(reserved_low_addr() == other_space->reserved_high_addr(),
   312          "spaces not contiguous");
   313   assert(special() == other_space->special(), "one space is special in memory, the other is not");
   314   DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
   315   DEBUG_ONLY(PSVirtualSpaceVerifier other_verifier(other_space));
   317   size_t bytes_needed = bytes;
   319   // First use the uncommitted region in this space.
   320   size_t tmp_bytes = MIN2(uncommitted_size(), bytes_needed);
   321   if (tmp_bytes > 0) {
   322     if (expand_by(tmp_bytes)) {
   323       bytes_needed -= tmp_bytes;
   324     } else {
   325       return 0;
   326     }
   327   }
   329   // Next take from the uncommitted region in the other space, and commit it.
   330   tmp_bytes = MIN2(other_space->uncommitted_size(), bytes_needed);
   331   if (tmp_bytes > 0) {
   332     char* const commit_base = committed_low_addr() - tmp_bytes;
   333     if (other_space->special() ||
   334         os::commit_memory(commit_base, tmp_bytes, alignment())) {
   335       // Reduce the reserved region in the other space.
   336       other_space->set_reserved(other_space->reserved_low_addr(),
   337                                 other_space->reserved_high_addr() - tmp_bytes,
   338                                 other_space->special());
   340       // Grow both reserved and committed in this space.
   341       _reserved_low_addr -= tmp_bytes;
   342       _committed_low_addr -= tmp_bytes;
   343       bytes_needed -= tmp_bytes;
   344     } else {
   345       return bytes - bytes_needed;
   346     }
   347   }
   349   // Finally take from the already committed region in the other space.
   350   tmp_bytes = bytes_needed;
   351   if (tmp_bytes > 0) {
   352     // Reduce both committed and reserved in the other space.
   353     other_space->set_committed(other_space->committed_low_addr(),
   354                                other_space->committed_high_addr() - tmp_bytes);
   355     other_space->set_reserved(other_space->reserved_low_addr(),
   356                               other_space->reserved_high_addr() - tmp_bytes,
   357                               other_space->special());
   359     // Grow both reserved and committed in this space.
   360     _reserved_low_addr -= tmp_bytes;
   361     _committed_low_addr -= tmp_bytes;
   362   }
   364   return bytes;
   365 }
   367 void
   368 PSVirtualSpaceHighToLow::print_space_boundaries_on(outputStream* st) const {
   369   st->print_cr(" (" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT "]",
   370                high_boundary(), low(), low_boundary());
   371 }

mercurial