src/share/vm/runtime/virtualspace.cpp

Fri, 04 Oct 2013 13:33:02 +0200

author
mgerdin
date
Fri, 04 Oct 2013 13:33:02 +0200
changeset 5859
04b18a42c2f3
parent 5708
8c5e6482cbfc
child 6472
2b8e28fdf503
permissions
-rw-r--r--

8025526: VirtualSpace should support per-instance disabling of large pages
Summary: Add a new initialization function to VirtualSpace which allows the caller to override the max commit granularity.
Reviewed-by: stefank, ehelin, tschatzl

     1 /*
     2  * Copyright (c) 1997, 2013, 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 "oops/markOop.hpp"
    27 #include "oops/oop.inline.hpp"
    28 #include "runtime/virtualspace.hpp"
    29 #include "services/memTracker.hpp"
    30 #ifdef TARGET_OS_FAMILY_linux
    31 # include "os_linux.inline.hpp"
    32 #endif
    33 #ifdef TARGET_OS_FAMILY_solaris
    34 # include "os_solaris.inline.hpp"
    35 #endif
    36 #ifdef TARGET_OS_FAMILY_windows
    37 # include "os_windows.inline.hpp"
    38 #endif
    39 #ifdef TARGET_OS_FAMILY_bsd
    40 # include "os_bsd.inline.hpp"
    41 #endif
    44 // ReservedSpace
    46 // Dummy constructor
    47 ReservedSpace::ReservedSpace() : _base(NULL), _size(0), _noaccess_prefix(0),
    48     _alignment(0), _special(false), _executable(false) {
    49 }
    51 ReservedSpace::ReservedSpace(size_t size) {
    52   size_t page_size = os::page_size_for_region(size, size, 1);
    53   bool large_pages = page_size != (size_t)os::vm_page_size();
    54   // Don't force the alignment to be large page aligned,
    55   // since that will waste memory.
    56   size_t alignment = os::vm_allocation_granularity();
    57   initialize(size, alignment, large_pages, NULL, 0, false);
    58 }
    60 ReservedSpace::ReservedSpace(size_t size, size_t alignment,
    61                              bool large,
    62                              char* requested_address,
    63                              const size_t noaccess_prefix) {
    64   initialize(size+noaccess_prefix, alignment, large, requested_address,
    65              noaccess_prefix, false);
    66 }
    68 ReservedSpace::ReservedSpace(size_t size, size_t alignment,
    69                              bool large,
    70                              bool executable) {
    71   initialize(size, alignment, large, NULL, 0, executable);
    72 }
    74 // Helper method.
    75 static bool failed_to_reserve_as_requested(char* base, char* requested_address,
    76                                            const size_t size, bool special)
    77 {
    78   if (base == requested_address || requested_address == NULL)
    79     return false; // did not fail
    81   if (base != NULL) {
    82     // Different reserve address may be acceptable in other cases
    83     // but for compressed oops heap should be at requested address.
    84     assert(UseCompressedOops, "currently requested address used only for compressed oops");
    85     if (PrintCompressedOopsMode) {
    86       tty->cr();
    87       tty->print_cr("Reserved memory not at requested address: " PTR_FORMAT " vs " PTR_FORMAT, base, requested_address);
    88     }
    89     // OS ignored requested address. Try different address.
    90     if (special) {
    91       if (!os::release_memory_special(base, size)) {
    92         fatal("os::release_memory_special failed");
    93       }
    94     } else {
    95       if (!os::release_memory(base, size)) {
    96         fatal("os::release_memory failed");
    97       }
    98     }
    99   }
   100   return true;
   101 }
   103 void ReservedSpace::initialize(size_t size, size_t alignment, bool large,
   104                                char* requested_address,
   105                                const size_t noaccess_prefix,
   106                                bool executable) {
   107   const size_t granularity = os::vm_allocation_granularity();
   108   assert((size & (granularity - 1)) == 0,
   109          "size not aligned to os::vm_allocation_granularity()");
   110   assert((alignment & (granularity - 1)) == 0,
   111          "alignment not aligned to os::vm_allocation_granularity()");
   112   assert(alignment == 0 || is_power_of_2((intptr_t)alignment),
   113          "not a power of 2");
   115   alignment = MAX2(alignment, (size_t)os::vm_page_size());
   117   // Assert that if noaccess_prefix is used, it is the same as alignment.
   118   assert(noaccess_prefix == 0 ||
   119          noaccess_prefix == alignment, "noaccess prefix wrong");
   121   _base = NULL;
   122   _size = 0;
   123   _special = false;
   124   _executable = executable;
   125   _alignment = 0;
   126   _noaccess_prefix = 0;
   127   if (size == 0) {
   128     return;
   129   }
   131   // If OS doesn't support demand paging for large page memory, we need
   132   // to use reserve_memory_special() to reserve and pin the entire region.
   133   bool special = large && !os::can_commit_large_page_memory();
   134   char* base = NULL;
   136   if (requested_address != 0) {
   137     requested_address -= noaccess_prefix; // adjust requested address
   138     assert(requested_address != NULL, "huge noaccess prefix?");
   139   }
   141   if (special) {
   143     base = os::reserve_memory_special(size, alignment, requested_address, executable);
   145     if (base != NULL) {
   146       if (failed_to_reserve_as_requested(base, requested_address, size, true)) {
   147         // OS ignored requested address. Try different address.
   148         return;
   149       }
   150       // Check alignment constraints.
   151       assert((uintptr_t) base % alignment == 0,
   152              err_msg("Large pages returned a non-aligned address, base: "
   153                  PTR_FORMAT " alignment: " PTR_FORMAT,
   154                  base, (void*)(uintptr_t)alignment));
   155       _special = true;
   156     } else {
   157       // failed; try to reserve regular memory below
   158       if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) ||
   159                             !FLAG_IS_DEFAULT(LargePageSizeInBytes))) {
   160         if (PrintCompressedOopsMode) {
   161           tty->cr();
   162           tty->print_cr("Reserve regular memory without large pages.");
   163         }
   164       }
   165     }
   166   }
   168   if (base == NULL) {
   169     // Optimistically assume that the OSes returns an aligned base pointer.
   170     // When reserving a large address range, most OSes seem to align to at
   171     // least 64K.
   173     // If the memory was requested at a particular address, use
   174     // os::attempt_reserve_memory_at() to avoid over mapping something
   175     // important.  If available space is not detected, return NULL.
   177     if (requested_address != 0) {
   178       base = os::attempt_reserve_memory_at(size, requested_address);
   179       if (failed_to_reserve_as_requested(base, requested_address, size, false)) {
   180         // OS ignored requested address. Try different address.
   181         base = NULL;
   182       }
   183     } else {
   184       base = os::reserve_memory(size, NULL, alignment);
   185     }
   187     if (base == NULL) return;
   189     // Check alignment constraints
   190     if ((((size_t)base + noaccess_prefix) & (alignment - 1)) != 0) {
   191       // Base not aligned, retry
   192       if (!os::release_memory(base, size)) fatal("os::release_memory failed");
   193       // Make sure that size is aligned
   194       size = align_size_up(size, alignment);
   195       base = os::reserve_memory_aligned(size, alignment);
   197       if (requested_address != 0 &&
   198           failed_to_reserve_as_requested(base, requested_address, size, false)) {
   199         // As a result of the alignment constraints, the allocated base differs
   200         // from the requested address. Return back to the caller who can
   201         // take remedial action (like try again without a requested address).
   202         assert(_base == NULL, "should be");
   203         return;
   204       }
   205     }
   206   }
   207   // Done
   208   _base = base;
   209   _size = size;
   210   _alignment = alignment;
   211   _noaccess_prefix = noaccess_prefix;
   213   // Assert that if noaccess_prefix is used, it is the same as alignment.
   214   assert(noaccess_prefix == 0 ||
   215          noaccess_prefix == _alignment, "noaccess prefix wrong");
   217   assert(markOopDesc::encode_pointer_as_mark(_base)->decode_pointer() == _base,
   218          "area must be distinguisable from marks for mark-sweep");
   219   assert(markOopDesc::encode_pointer_as_mark(&_base[size])->decode_pointer() == &_base[size],
   220          "area must be distinguisable from marks for mark-sweep");
   221 }
   224 ReservedSpace::ReservedSpace(char* base, size_t size, size_t alignment,
   225                              bool special, bool executable) {
   226   assert((size % os::vm_allocation_granularity()) == 0,
   227          "size not allocation aligned");
   228   _base = base;
   229   _size = size;
   230   _alignment = alignment;
   231   _noaccess_prefix = 0;
   232   _special = special;
   233   _executable = executable;
   234 }
   237 ReservedSpace ReservedSpace::first_part(size_t partition_size, size_t alignment,
   238                                         bool split, bool realloc) {
   239   assert(partition_size <= size(), "partition failed");
   240   if (split) {
   241     os::split_reserved_memory(base(), size(), partition_size, realloc);
   242   }
   243   ReservedSpace result(base(), partition_size, alignment, special(),
   244                        executable());
   245   return result;
   246 }
   249 ReservedSpace
   250 ReservedSpace::last_part(size_t partition_size, size_t alignment) {
   251   assert(partition_size <= size(), "partition failed");
   252   ReservedSpace result(base() + partition_size, size() - partition_size,
   253                        alignment, special(), executable());
   254   return result;
   255 }
   258 size_t ReservedSpace::page_align_size_up(size_t size) {
   259   return align_size_up(size, os::vm_page_size());
   260 }
   263 size_t ReservedSpace::page_align_size_down(size_t size) {
   264   return align_size_down(size, os::vm_page_size());
   265 }
   268 size_t ReservedSpace::allocation_align_size_up(size_t size) {
   269   return align_size_up(size, os::vm_allocation_granularity());
   270 }
   273 size_t ReservedSpace::allocation_align_size_down(size_t size) {
   274   return align_size_down(size, os::vm_allocation_granularity());
   275 }
   278 void ReservedSpace::release() {
   279   if (is_reserved()) {
   280     char *real_base = _base - _noaccess_prefix;
   281     const size_t real_size = _size + _noaccess_prefix;
   282     if (special()) {
   283       os::release_memory_special(real_base, real_size);
   284     } else{
   285       os::release_memory(real_base, real_size);
   286     }
   287     _base = NULL;
   288     _size = 0;
   289     _noaccess_prefix = 0;
   290     _special = false;
   291     _executable = false;
   292   }
   293 }
   295 void ReservedSpace::protect_noaccess_prefix(const size_t size) {
   296   assert( (_noaccess_prefix != 0) == (UseCompressedOops && _base != NULL &&
   297                                       (Universe::narrow_oop_base() != NULL) &&
   298                                       Universe::narrow_oop_use_implicit_null_checks()),
   299          "noaccess_prefix should be used only with non zero based compressed oops");
   301   // If there is no noaccess prefix, return.
   302   if (_noaccess_prefix == 0) return;
   304   assert(_noaccess_prefix >= (size_t)os::vm_page_size(),
   305          "must be at least page size big");
   307   // Protect memory at the base of the allocated region.
   308   // If special, the page was committed (only matters on windows)
   309   if (!os::protect_memory(_base, _noaccess_prefix, os::MEM_PROT_NONE,
   310                           _special)) {
   311     fatal("cannot protect protection page");
   312   }
   313   if (PrintCompressedOopsMode) {
   314     tty->cr();
   315     tty->print_cr("Protected page at the reserved heap base: " PTR_FORMAT " / " INTX_FORMAT " bytes", _base, _noaccess_prefix);
   316   }
   318   _base += _noaccess_prefix;
   319   _size -= _noaccess_prefix;
   320   assert((size == _size) && ((uintptr_t)_base % _alignment == 0),
   321          "must be exactly of required size and alignment");
   322 }
   324 ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment,
   325                                      bool large, char* requested_address) :
   326   ReservedSpace(size, alignment, large,
   327                 requested_address,
   328                 (UseCompressedOops && (Universe::narrow_oop_base() != NULL) &&
   329                  Universe::narrow_oop_use_implicit_null_checks()) ?
   330                   lcm(os::vm_page_size(), alignment) : 0) {
   331   if (base() > 0) {
   332     MemTracker::record_virtual_memory_type((address)base(), mtJavaHeap);
   333   }
   335   // Only reserved space for the java heap should have a noaccess_prefix
   336   // if using compressed oops.
   337   protect_noaccess_prefix(size);
   338 }
   340 // Reserve space for code segment.  Same as Java heap only we mark this as
   341 // executable.
   342 ReservedCodeSpace::ReservedCodeSpace(size_t r_size,
   343                                      size_t rs_align,
   344                                      bool large) :
   345   ReservedSpace(r_size, rs_align, large, /*executable*/ true) {
   346   MemTracker::record_virtual_memory_type((address)base(), mtCode);
   347 }
   349 // VirtualSpace
   351 VirtualSpace::VirtualSpace() {
   352   _low_boundary           = NULL;
   353   _high_boundary          = NULL;
   354   _low                    = NULL;
   355   _high                   = NULL;
   356   _lower_high             = NULL;
   357   _middle_high            = NULL;
   358   _upper_high             = NULL;
   359   _lower_high_boundary    = NULL;
   360   _middle_high_boundary   = NULL;
   361   _upper_high_boundary    = NULL;
   362   _lower_alignment        = 0;
   363   _middle_alignment       = 0;
   364   _upper_alignment        = 0;
   365   _special                = false;
   366   _executable             = false;
   367 }
   370 bool VirtualSpace::initialize(ReservedSpace rs, size_t committed_size) {
   371   const size_t max_commit_granularity = os::page_size_for_region(rs.size(), rs.size(), 1);
   372   return initialize_with_granularity(rs, committed_size, max_commit_granularity);
   373 }
   375 bool VirtualSpace::initialize_with_granularity(ReservedSpace rs, size_t committed_size, size_t max_commit_granularity) {
   376   if(!rs.is_reserved()) return false;  // allocation failed.
   377   assert(_low_boundary == NULL, "VirtualSpace already initialized");
   378   assert(max_commit_granularity > 0, "Granularity must be non-zero.");
   380   _low_boundary  = rs.base();
   381   _high_boundary = low_boundary() + rs.size();
   383   _low = low_boundary();
   384   _high = low();
   386   _special = rs.special();
   387   _executable = rs.executable();
   389   // When a VirtualSpace begins life at a large size, make all future expansion
   390   // and shrinking occur aligned to a granularity of large pages.  This avoids
   391   // fragmentation of physical addresses that inhibits the use of large pages
   392   // by the OS virtual memory system.  Empirically,  we see that with a 4MB
   393   // page size, the only spaces that get handled this way are codecache and
   394   // the heap itself, both of which provide a substantial performance
   395   // boost in many benchmarks when covered by large pages.
   396   //
   397   // No attempt is made to force large page alignment at the very top and
   398   // bottom of the space if they are not aligned so already.
   399   _lower_alignment  = os::vm_page_size();
   400   _middle_alignment = max_commit_granularity;
   401   _upper_alignment  = os::vm_page_size();
   403   // End of each region
   404   _lower_high_boundary = (char*) round_to((intptr_t) low_boundary(), middle_alignment());
   405   _middle_high_boundary = (char*) round_down((intptr_t) high_boundary(), middle_alignment());
   406   _upper_high_boundary = high_boundary();
   408   // High address of each region
   409   _lower_high = low_boundary();
   410   _middle_high = lower_high_boundary();
   411   _upper_high = middle_high_boundary();
   413   // commit to initial size
   414   if (committed_size > 0) {
   415     if (!expand_by(committed_size)) {
   416       return false;
   417     }
   418   }
   419   return true;
   420 }
   423 VirtualSpace::~VirtualSpace() {
   424   release();
   425 }
   428 void VirtualSpace::release() {
   429   // This does not release memory it never reserved.
   430   // Caller must release via rs.release();
   431   _low_boundary           = NULL;
   432   _high_boundary          = NULL;
   433   _low                    = NULL;
   434   _high                   = NULL;
   435   _lower_high             = NULL;
   436   _middle_high            = NULL;
   437   _upper_high             = NULL;
   438   _lower_high_boundary    = NULL;
   439   _middle_high_boundary   = NULL;
   440   _upper_high_boundary    = NULL;
   441   _lower_alignment        = 0;
   442   _middle_alignment       = 0;
   443   _upper_alignment        = 0;
   444   _special                = false;
   445   _executable             = false;
   446 }
   449 size_t VirtualSpace::committed_size() const {
   450   return pointer_delta(high(), low(), sizeof(char));
   451 }
   454 size_t VirtualSpace::reserved_size() const {
   455   return pointer_delta(high_boundary(), low_boundary(), sizeof(char));
   456 }
   459 size_t VirtualSpace::uncommitted_size()  const {
   460   return reserved_size() - committed_size();
   461 }
   463 size_t VirtualSpace::actual_committed_size() const {
   464   // Special VirtualSpaces commit all reserved space up front.
   465   if (special()) {
   466     return reserved_size();
   467   }
   469   size_t committed_low    = pointer_delta(_lower_high,  _low_boundary,         sizeof(char));
   470   size_t committed_middle = pointer_delta(_middle_high, _lower_high_boundary,  sizeof(char));
   471   size_t committed_high   = pointer_delta(_upper_high,  _middle_high_boundary, sizeof(char));
   473 #ifdef ASSERT
   474   size_t lower  = pointer_delta(_lower_high_boundary,  _low_boundary,         sizeof(char));
   475   size_t middle = pointer_delta(_middle_high_boundary, _lower_high_boundary,  sizeof(char));
   476   size_t upper  = pointer_delta(_upper_high_boundary,  _middle_high_boundary, sizeof(char));
   478   if (committed_high > 0) {
   479     assert(committed_low == lower, "Must be");
   480     assert(committed_middle == middle, "Must be");
   481   }
   483   if (committed_middle > 0) {
   484     assert(committed_low == lower, "Must be");
   485   }
   486   if (committed_middle < middle) {
   487     assert(committed_high == 0, "Must be");
   488   }
   490   if (committed_low < lower) {
   491     assert(committed_high == 0, "Must be");
   492     assert(committed_middle == 0, "Must be");
   493   }
   494 #endif
   496   return committed_low + committed_middle + committed_high;
   497 }
   500 bool VirtualSpace::contains(const void* p) const {
   501   return low() <= (const char*) p && (const char*) p < high();
   502 }
   504 /*
   505    First we need to determine if a particular virtual space is using large
   506    pages.  This is done at the initialize function and only virtual spaces
   507    that are larger than LargePageSizeInBytes use large pages.  Once we
   508    have determined this, all expand_by and shrink_by calls must grow and
   509    shrink by large page size chunks.  If a particular request
   510    is within the current large page, the call to commit and uncommit memory
   511    can be ignored.  In the case that the low and high boundaries of this
   512    space is not large page aligned, the pages leading to the first large
   513    page address and the pages after the last large page address must be
   514    allocated with default pages.
   515 */
   516 bool VirtualSpace::expand_by(size_t bytes, bool pre_touch) {
   517   if (uncommitted_size() < bytes) return false;
   519   if (special()) {
   520     // don't commit memory if the entire space is pinned in memory
   521     _high += bytes;
   522     return true;
   523   }
   525   char* previous_high = high();
   526   char* unaligned_new_high = high() + bytes;
   527   assert(unaligned_new_high <= high_boundary(),
   528          "cannot expand by more than upper boundary");
   530   // Calculate where the new high for each of the regions should be.  If
   531   // the low_boundary() and high_boundary() are LargePageSizeInBytes aligned
   532   // then the unaligned lower and upper new highs would be the
   533   // lower_high() and upper_high() respectively.
   534   char* unaligned_lower_new_high =
   535     MIN2(unaligned_new_high, lower_high_boundary());
   536   char* unaligned_middle_new_high =
   537     MIN2(unaligned_new_high, middle_high_boundary());
   538   char* unaligned_upper_new_high =
   539     MIN2(unaligned_new_high, upper_high_boundary());
   541   // Align the new highs based on the regions alignment.  lower and upper
   542   // alignment will always be default page size.  middle alignment will be
   543   // LargePageSizeInBytes if the actual size of the virtual space is in
   544   // fact larger than LargePageSizeInBytes.
   545   char* aligned_lower_new_high =
   546     (char*) round_to((intptr_t) unaligned_lower_new_high, lower_alignment());
   547   char* aligned_middle_new_high =
   548     (char*) round_to((intptr_t) unaligned_middle_new_high, middle_alignment());
   549   char* aligned_upper_new_high =
   550     (char*) round_to((intptr_t) unaligned_upper_new_high, upper_alignment());
   552   // Determine which regions need to grow in this expand_by call.
   553   // If you are growing in the lower region, high() must be in that
   554   // region so calcuate the size based on high().  For the middle and
   555   // upper regions, determine the starting point of growth based on the
   556   // location of high().  By getting the MAX of the region's low address
   557   // (or the prevoius region's high address) and high(), we can tell if it
   558   // is an intra or inter region growth.
   559   size_t lower_needs = 0;
   560   if (aligned_lower_new_high > lower_high()) {
   561     lower_needs =
   562       pointer_delta(aligned_lower_new_high, lower_high(), sizeof(char));
   563   }
   564   size_t middle_needs = 0;
   565   if (aligned_middle_new_high > middle_high()) {
   566     middle_needs =
   567       pointer_delta(aligned_middle_new_high, middle_high(), sizeof(char));
   568   }
   569   size_t upper_needs = 0;
   570   if (aligned_upper_new_high > upper_high()) {
   571     upper_needs =
   572       pointer_delta(aligned_upper_new_high, upper_high(), sizeof(char));
   573   }
   575   // Check contiguity.
   576   assert(low_boundary() <= lower_high() &&
   577          lower_high() <= lower_high_boundary(),
   578          "high address must be contained within the region");
   579   assert(lower_high_boundary() <= middle_high() &&
   580          middle_high() <= middle_high_boundary(),
   581          "high address must be contained within the region");
   582   assert(middle_high_boundary() <= upper_high() &&
   583          upper_high() <= upper_high_boundary(),
   584          "high address must be contained within the region");
   586   // Commit regions
   587   if (lower_needs > 0) {
   588     assert(low_boundary() <= lower_high() &&
   589            lower_high() + lower_needs <= lower_high_boundary(),
   590            "must not expand beyond region");
   591     if (!os::commit_memory(lower_high(), lower_needs, _executable)) {
   592       debug_only(warning("INFO: os::commit_memory(" PTR_FORMAT
   593                          ", lower_needs=" SIZE_FORMAT ", %d) failed",
   594                          lower_high(), lower_needs, _executable);)
   595       return false;
   596     } else {
   597       _lower_high += lower_needs;
   598     }
   599   }
   600   if (middle_needs > 0) {
   601     assert(lower_high_boundary() <= middle_high() &&
   602            middle_high() + middle_needs <= middle_high_boundary(),
   603            "must not expand beyond region");
   604     if (!os::commit_memory(middle_high(), middle_needs, middle_alignment(),
   605                            _executable)) {
   606       debug_only(warning("INFO: os::commit_memory(" PTR_FORMAT
   607                          ", middle_needs=" SIZE_FORMAT ", " SIZE_FORMAT
   608                          ", %d) failed", middle_high(), middle_needs,
   609                          middle_alignment(), _executable);)
   610       return false;
   611     }
   612     _middle_high += middle_needs;
   613   }
   614   if (upper_needs > 0) {
   615     assert(middle_high_boundary() <= upper_high() &&
   616            upper_high() + upper_needs <= upper_high_boundary(),
   617            "must not expand beyond region");
   618     if (!os::commit_memory(upper_high(), upper_needs, _executable)) {
   619       debug_only(warning("INFO: os::commit_memory(" PTR_FORMAT
   620                          ", upper_needs=" SIZE_FORMAT ", %d) failed",
   621                          upper_high(), upper_needs, _executable);)
   622       return false;
   623     } else {
   624       _upper_high += upper_needs;
   625     }
   626   }
   628   if (pre_touch || AlwaysPreTouch) {
   629     int vm_ps = os::vm_page_size();
   630     for (char* curr = previous_high;
   631          curr < unaligned_new_high;
   632          curr += vm_ps) {
   633       // Note the use of a write here; originally we tried just a read, but
   634       // since the value read was unused, the optimizer removed the read.
   635       // If we ever have a concurrent touchahead thread, we'll want to use
   636       // a read, to avoid the potential of overwriting data (if a mutator
   637       // thread beats the touchahead thread to a page).  There are various
   638       // ways of making sure this read is not optimized away: for example,
   639       // generating the code for a read procedure at runtime.
   640       *curr = 0;
   641     }
   642   }
   644   _high += bytes;
   645   return true;
   646 }
   648 // A page is uncommitted if the contents of the entire page is deemed unusable.
   649 // Continue to decrement the high() pointer until it reaches a page boundary
   650 // in which case that particular page can now be uncommitted.
   651 void VirtualSpace::shrink_by(size_t size) {
   652   if (committed_size() < size)
   653     fatal("Cannot shrink virtual space to negative size");
   655   if (special()) {
   656     // don't uncommit if the entire space is pinned in memory
   657     _high -= size;
   658     return;
   659   }
   661   char* unaligned_new_high = high() - size;
   662   assert(unaligned_new_high >= low_boundary(), "cannot shrink past lower boundary");
   664   // Calculate new unaligned address
   665   char* unaligned_upper_new_high =
   666     MAX2(unaligned_new_high, middle_high_boundary());
   667   char* unaligned_middle_new_high =
   668     MAX2(unaligned_new_high, lower_high_boundary());
   669   char* unaligned_lower_new_high =
   670     MAX2(unaligned_new_high, low_boundary());
   672   // Align address to region's alignment
   673   char* aligned_upper_new_high =
   674     (char*) round_to((intptr_t) unaligned_upper_new_high, upper_alignment());
   675   char* aligned_middle_new_high =
   676     (char*) round_to((intptr_t) unaligned_middle_new_high, middle_alignment());
   677   char* aligned_lower_new_high =
   678     (char*) round_to((intptr_t) unaligned_lower_new_high, lower_alignment());
   680   // Determine which regions need to shrink
   681   size_t upper_needs = 0;
   682   if (aligned_upper_new_high < upper_high()) {
   683     upper_needs =
   684       pointer_delta(upper_high(), aligned_upper_new_high, sizeof(char));
   685   }
   686   size_t middle_needs = 0;
   687   if (aligned_middle_new_high < middle_high()) {
   688     middle_needs =
   689       pointer_delta(middle_high(), aligned_middle_new_high, sizeof(char));
   690   }
   691   size_t lower_needs = 0;
   692   if (aligned_lower_new_high < lower_high()) {
   693     lower_needs =
   694       pointer_delta(lower_high(), aligned_lower_new_high, sizeof(char));
   695   }
   697   // Check contiguity.
   698   assert(middle_high_boundary() <= upper_high() &&
   699          upper_high() <= upper_high_boundary(),
   700          "high address must be contained within the region");
   701   assert(lower_high_boundary() <= middle_high() &&
   702          middle_high() <= middle_high_boundary(),
   703          "high address must be contained within the region");
   704   assert(low_boundary() <= lower_high() &&
   705          lower_high() <= lower_high_boundary(),
   706          "high address must be contained within the region");
   708   // Uncommit
   709   if (upper_needs > 0) {
   710     assert(middle_high_boundary() <= aligned_upper_new_high &&
   711            aligned_upper_new_high + upper_needs <= upper_high_boundary(),
   712            "must not shrink beyond region");
   713     if (!os::uncommit_memory(aligned_upper_new_high, upper_needs)) {
   714       debug_only(warning("os::uncommit_memory failed"));
   715       return;
   716     } else {
   717       _upper_high -= upper_needs;
   718     }
   719   }
   720   if (middle_needs > 0) {
   721     assert(lower_high_boundary() <= aligned_middle_new_high &&
   722            aligned_middle_new_high + middle_needs <= middle_high_boundary(),
   723            "must not shrink beyond region");
   724     if (!os::uncommit_memory(aligned_middle_new_high, middle_needs)) {
   725       debug_only(warning("os::uncommit_memory failed"));
   726       return;
   727     } else {
   728       _middle_high -= middle_needs;
   729     }
   730   }
   731   if (lower_needs > 0) {
   732     assert(low_boundary() <= aligned_lower_new_high &&
   733            aligned_lower_new_high + lower_needs <= lower_high_boundary(),
   734            "must not shrink beyond region");
   735     if (!os::uncommit_memory(aligned_lower_new_high, lower_needs)) {
   736       debug_only(warning("os::uncommit_memory failed"));
   737       return;
   738     } else {
   739       _lower_high -= lower_needs;
   740     }
   741   }
   743   _high -= size;
   744 }
   746 #ifndef PRODUCT
   747 void VirtualSpace::check_for_contiguity() {
   748   // Check contiguity.
   749   assert(low_boundary() <= lower_high() &&
   750          lower_high() <= lower_high_boundary(),
   751          "high address must be contained within the region");
   752   assert(lower_high_boundary() <= middle_high() &&
   753          middle_high() <= middle_high_boundary(),
   754          "high address must be contained within the region");
   755   assert(middle_high_boundary() <= upper_high() &&
   756          upper_high() <= upper_high_boundary(),
   757          "high address must be contained within the region");
   758   assert(low() >= low_boundary(), "low");
   759   assert(low_boundary() <= lower_high_boundary(), "lower high boundary");
   760   assert(upper_high_boundary() <= high_boundary(), "upper high boundary");
   761   assert(high() <= upper_high(), "upper high");
   762 }
   764 void VirtualSpace::print_on(outputStream* out) {
   765   out->print   ("Virtual space:");
   766   if (special()) out->print(" (pinned in memory)");
   767   out->cr();
   768   out->print_cr(" - committed: " SIZE_FORMAT, committed_size());
   769   out->print_cr(" - reserved:  " SIZE_FORMAT, reserved_size());
   770   out->print_cr(" - [low, high]:     [" INTPTR_FORMAT ", " INTPTR_FORMAT "]",  low(), high());
   771   out->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]",  low_boundary(), high_boundary());
   772 }
   774 void VirtualSpace::print() {
   775   print_on(tty);
   776 }
   778 /////////////// Unit tests ///////////////
   780 #ifndef PRODUCT
   782 #define test_log(...) \
   783   do {\
   784     if (VerboseInternalVMTests) { \
   785       tty->print_cr(__VA_ARGS__); \
   786       tty->flush(); \
   787     }\
   788   } while (false)
   790 class TestReservedSpace : AllStatic {
   791  public:
   792   static void small_page_write(void* addr, size_t size) {
   793     size_t page_size = os::vm_page_size();
   795     char* end = (char*)addr + size;
   796     for (char* p = (char*)addr; p < end; p += page_size) {
   797       *p = 1;
   798     }
   799   }
   801   static void release_memory_for_test(ReservedSpace rs) {
   802     if (rs.special()) {
   803       guarantee(os::release_memory_special(rs.base(), rs.size()), "Shouldn't fail");
   804     } else {
   805       guarantee(os::release_memory(rs.base(), rs.size()), "Shouldn't fail");
   806     }
   807   }
   809   static void test_reserved_space1(size_t size, size_t alignment) {
   810     test_log("test_reserved_space1(%p)", (void*) (uintptr_t) size);
   812     assert(is_size_aligned(size, alignment), "Incorrect input parameters");
   814     ReservedSpace rs(size,          // size
   815                      alignment,     // alignment
   816                      UseLargePages, // large
   817                      NULL,          // requested_address
   818                      0);            // noacces_prefix
   820     test_log(" rs.special() == %d", rs.special());
   822     assert(rs.base() != NULL, "Must be");
   823     assert(rs.size() == size, "Must be");
   825     assert(is_ptr_aligned(rs.base(), alignment), "aligned sizes should always give aligned addresses");
   826     assert(is_size_aligned(rs.size(), alignment), "aligned sizes should always give aligned addresses");
   828     if (rs.special()) {
   829       small_page_write(rs.base(), size);
   830     }
   832     release_memory_for_test(rs);
   833   }
   835   static void test_reserved_space2(size_t size) {
   836     test_log("test_reserved_space2(%p)", (void*)(uintptr_t)size);
   838     assert(is_size_aligned(size, os::vm_allocation_granularity()), "Must be at least AG aligned");
   840     ReservedSpace rs(size);
   842     test_log(" rs.special() == %d", rs.special());
   844     assert(rs.base() != NULL, "Must be");
   845     assert(rs.size() == size, "Must be");
   847     if (rs.special()) {
   848       small_page_write(rs.base(), size);
   849     }
   851     release_memory_for_test(rs);
   852   }
   854   static void test_reserved_space3(size_t size, size_t alignment, bool maybe_large) {
   855     test_log("test_reserved_space3(%p, %p, %d)",
   856         (void*)(uintptr_t)size, (void*)(uintptr_t)alignment, maybe_large);
   858     assert(is_size_aligned(size, os::vm_allocation_granularity()), "Must be at least AG aligned");
   859     assert(is_size_aligned(size, alignment), "Must be at least aligned against alignment");
   861     bool large = maybe_large && UseLargePages && size >= os::large_page_size();
   863     ReservedSpace rs(size, alignment, large, false);
   865     test_log(" rs.special() == %d", rs.special());
   867     assert(rs.base() != NULL, "Must be");
   868     assert(rs.size() == size, "Must be");
   870     if (rs.special()) {
   871       small_page_write(rs.base(), size);
   872     }
   874     release_memory_for_test(rs);
   875   }
   878   static void test_reserved_space1() {
   879     size_t size = 2 * 1024 * 1024;
   880     size_t ag   = os::vm_allocation_granularity();
   882     test_reserved_space1(size,      ag);
   883     test_reserved_space1(size * 2,  ag);
   884     test_reserved_space1(size * 10, ag);
   885   }
   887   static void test_reserved_space2() {
   888     size_t size = 2 * 1024 * 1024;
   889     size_t ag = os::vm_allocation_granularity();
   891     test_reserved_space2(size * 1);
   892     test_reserved_space2(size * 2);
   893     test_reserved_space2(size * 10);
   894     test_reserved_space2(ag);
   895     test_reserved_space2(size - ag);
   896     test_reserved_space2(size);
   897     test_reserved_space2(size + ag);
   898     test_reserved_space2(size * 2);
   899     test_reserved_space2(size * 2 - ag);
   900     test_reserved_space2(size * 2 + ag);
   901     test_reserved_space2(size * 3);
   902     test_reserved_space2(size * 3 - ag);
   903     test_reserved_space2(size * 3 + ag);
   904     test_reserved_space2(size * 10);
   905     test_reserved_space2(size * 10 + size / 2);
   906   }
   908   static void test_reserved_space3() {
   909     size_t ag = os::vm_allocation_granularity();
   911     test_reserved_space3(ag,      ag    , false);
   912     test_reserved_space3(ag * 2,  ag    , false);
   913     test_reserved_space3(ag * 3,  ag    , false);
   914     test_reserved_space3(ag * 2,  ag * 2, false);
   915     test_reserved_space3(ag * 4,  ag * 2, false);
   916     test_reserved_space3(ag * 8,  ag * 2, false);
   917     test_reserved_space3(ag * 4,  ag * 4, false);
   918     test_reserved_space3(ag * 8,  ag * 4, false);
   919     test_reserved_space3(ag * 16, ag * 4, false);
   921     if (UseLargePages) {
   922       size_t lp = os::large_page_size();
   924       // Without large pages
   925       test_reserved_space3(lp,     ag * 4, false);
   926       test_reserved_space3(lp * 2, ag * 4, false);
   927       test_reserved_space3(lp * 4, ag * 4, false);
   928       test_reserved_space3(lp,     lp    , false);
   929       test_reserved_space3(lp * 2, lp    , false);
   930       test_reserved_space3(lp * 3, lp    , false);
   931       test_reserved_space3(lp * 2, lp * 2, false);
   932       test_reserved_space3(lp * 4, lp * 2, false);
   933       test_reserved_space3(lp * 8, lp * 2, false);
   935       // With large pages
   936       test_reserved_space3(lp, ag * 4    , true);
   937       test_reserved_space3(lp * 2, ag * 4, true);
   938       test_reserved_space3(lp * 4, ag * 4, true);
   939       test_reserved_space3(lp, lp        , true);
   940       test_reserved_space3(lp * 2, lp    , true);
   941       test_reserved_space3(lp * 3, lp    , true);
   942       test_reserved_space3(lp * 2, lp * 2, true);
   943       test_reserved_space3(lp * 4, lp * 2, true);
   944       test_reserved_space3(lp * 8, lp * 2, true);
   945     }
   946   }
   948   static void test_reserved_space() {
   949     test_reserved_space1();
   950     test_reserved_space2();
   951     test_reserved_space3();
   952   }
   953 };
   955 void TestReservedSpace_test() {
   956   TestReservedSpace::test_reserved_space();
   957 }
   959 #define assert_equals(actual, expected)     \
   960   assert(actual == expected,                \
   961     err_msg("Got " SIZE_FORMAT " expected " \
   962       SIZE_FORMAT, actual, expected));
   964 #define assert_ge(value1, value2)                  \
   965   assert(value1 >= value2,                         \
   966     err_msg("'" #value1 "': " SIZE_FORMAT " '"     \
   967       #value2 "': " SIZE_FORMAT, value1, value2));
   969 #define assert_lt(value1, value2)                  \
   970   assert(value1 < value2,                          \
   971     err_msg("'" #value1 "': " SIZE_FORMAT " '"     \
   972       #value2 "': " SIZE_FORMAT, value1, value2));
   975 class TestVirtualSpace : AllStatic {
   976   enum TestLargePages {
   977     Default,
   978     Disable,
   979     Reserve,
   980     Commit
   981   };
   983   static ReservedSpace reserve_memory(size_t reserve_size_aligned, TestLargePages mode) {
   984     switch(mode) {
   985     default:
   986     case Default:
   987     case Reserve:
   988       return ReservedSpace(reserve_size_aligned);
   989     case Disable:
   990     case Commit:
   991       return ReservedSpace(reserve_size_aligned,
   992                            os::vm_allocation_granularity(),
   993                            /* large */ false, /* exec */ false);
   994     }
   995   }
   997   static bool initialize_virtual_space(VirtualSpace& vs, ReservedSpace rs, TestLargePages mode) {
   998     switch(mode) {
   999     default:
  1000     case Default:
  1001     case Reserve:
  1002       return vs.initialize(rs, 0);
  1003     case Disable:
  1004       return vs.initialize_with_granularity(rs, 0, os::vm_page_size());
  1005     case Commit:
  1006       return vs.initialize_with_granularity(rs, 0, os::page_size_for_region(rs.size(), rs.size(), 1));
  1010  public:
  1011   static void test_virtual_space_actual_committed_space(size_t reserve_size, size_t commit_size,
  1012                                                         TestLargePages mode = Default) {
  1013     size_t granularity = os::vm_allocation_granularity();
  1014     size_t reserve_size_aligned = align_size_up(reserve_size, granularity);
  1016     ReservedSpace reserved = reserve_memory(reserve_size_aligned, mode);
  1018     assert(reserved.is_reserved(), "Must be");
  1020     VirtualSpace vs;
  1021     bool initialized = initialize_virtual_space(vs, reserved, mode);
  1022     assert(initialized, "Failed to initialize VirtualSpace");
  1024     vs.expand_by(commit_size, false);
  1026     if (vs.special()) {
  1027       assert_equals(vs.actual_committed_size(), reserve_size_aligned);
  1028     } else {
  1029       assert_ge(vs.actual_committed_size(), commit_size);
  1030       // Approximate the commit granularity.
  1031       // Make sure that we don't commit using large pages
  1032       // if large pages has been disabled for this VirtualSpace.
  1033       size_t commit_granularity = (mode == Disable || !UseLargePages) ?
  1034                                    os::vm_page_size() : os::large_page_size();
  1035       assert_lt(vs.actual_committed_size(), commit_size + commit_granularity);
  1038     reserved.release();
  1041   static void test_virtual_space_actual_committed_space_one_large_page() {
  1042     if (!UseLargePages) {
  1043       return;
  1046     size_t large_page_size = os::large_page_size();
  1048     ReservedSpace reserved(large_page_size, large_page_size, true, false);
  1050     assert(reserved.is_reserved(), "Must be");
  1052     VirtualSpace vs;
  1053     bool initialized = vs.initialize(reserved, 0);
  1054     assert(initialized, "Failed to initialize VirtualSpace");
  1056     vs.expand_by(large_page_size, false);
  1058     assert_equals(vs.actual_committed_size(), large_page_size);
  1060     reserved.release();
  1063   static void test_virtual_space_actual_committed_space() {
  1064     test_virtual_space_actual_committed_space(4 * K, 0);
  1065     test_virtual_space_actual_committed_space(4 * K, 4 * K);
  1066     test_virtual_space_actual_committed_space(8 * K, 0);
  1067     test_virtual_space_actual_committed_space(8 * K, 4 * K);
  1068     test_virtual_space_actual_committed_space(8 * K, 8 * K);
  1069     test_virtual_space_actual_committed_space(12 * K, 0);
  1070     test_virtual_space_actual_committed_space(12 * K, 4 * K);
  1071     test_virtual_space_actual_committed_space(12 * K, 8 * K);
  1072     test_virtual_space_actual_committed_space(12 * K, 12 * K);
  1073     test_virtual_space_actual_committed_space(64 * K, 0);
  1074     test_virtual_space_actual_committed_space(64 * K, 32 * K);
  1075     test_virtual_space_actual_committed_space(64 * K, 64 * K);
  1076     test_virtual_space_actual_committed_space(2 * M, 0);
  1077     test_virtual_space_actual_committed_space(2 * M, 4 * K);
  1078     test_virtual_space_actual_committed_space(2 * M, 64 * K);
  1079     test_virtual_space_actual_committed_space(2 * M, 1 * M);
  1080     test_virtual_space_actual_committed_space(2 * M, 2 * M);
  1081     test_virtual_space_actual_committed_space(10 * M, 0);
  1082     test_virtual_space_actual_committed_space(10 * M, 4 * K);
  1083     test_virtual_space_actual_committed_space(10 * M, 8 * K);
  1084     test_virtual_space_actual_committed_space(10 * M, 1 * M);
  1085     test_virtual_space_actual_committed_space(10 * M, 2 * M);
  1086     test_virtual_space_actual_committed_space(10 * M, 5 * M);
  1087     test_virtual_space_actual_committed_space(10 * M, 10 * M);
  1090   static void test_virtual_space_disable_large_pages() {
  1091     if (!UseLargePages) {
  1092       return;
  1094     // These test cases verify that if we force VirtualSpace to disable large pages
  1095     test_virtual_space_actual_committed_space(10 * M, 0, Disable);
  1096     test_virtual_space_actual_committed_space(10 * M, 4 * K, Disable);
  1097     test_virtual_space_actual_committed_space(10 * M, 8 * K, Disable);
  1098     test_virtual_space_actual_committed_space(10 * M, 1 * M, Disable);
  1099     test_virtual_space_actual_committed_space(10 * M, 2 * M, Disable);
  1100     test_virtual_space_actual_committed_space(10 * M, 5 * M, Disable);
  1101     test_virtual_space_actual_committed_space(10 * M, 10 * M, Disable);
  1103     test_virtual_space_actual_committed_space(10 * M, 0, Reserve);
  1104     test_virtual_space_actual_committed_space(10 * M, 4 * K, Reserve);
  1105     test_virtual_space_actual_committed_space(10 * M, 8 * K, Reserve);
  1106     test_virtual_space_actual_committed_space(10 * M, 1 * M, Reserve);
  1107     test_virtual_space_actual_committed_space(10 * M, 2 * M, Reserve);
  1108     test_virtual_space_actual_committed_space(10 * M, 5 * M, Reserve);
  1109     test_virtual_space_actual_committed_space(10 * M, 10 * M, Reserve);
  1111     test_virtual_space_actual_committed_space(10 * M, 0, Commit);
  1112     test_virtual_space_actual_committed_space(10 * M, 4 * K, Commit);
  1113     test_virtual_space_actual_committed_space(10 * M, 8 * K, Commit);
  1114     test_virtual_space_actual_committed_space(10 * M, 1 * M, Commit);
  1115     test_virtual_space_actual_committed_space(10 * M, 2 * M, Commit);
  1116     test_virtual_space_actual_committed_space(10 * M, 5 * M, Commit);
  1117     test_virtual_space_actual_committed_space(10 * M, 10 * M, Commit);
  1120   static void test_virtual_space() {
  1121     test_virtual_space_actual_committed_space();
  1122     test_virtual_space_actual_committed_space_one_large_page();
  1123     test_virtual_space_disable_large_pages();
  1125 };
  1127 void TestVirtualSpace_test() {
  1128   TestVirtualSpace::test_virtual_space();
  1131 #endif // PRODUCT
  1133 #endif

mercurial