src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp

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

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

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

     2 /*
     3  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
     4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5  *
     6  * This code is free software; you can redistribute it and/or modify it
     7  * under the terms of the GNU General Public License version 2 only, as
     8  * published by the Free Software Foundation.
     9  *
    10  * This code is distributed in the hope that it will be useful, but WITHOUT
    11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    13  * version 2 for more details (a copy is included in the LICENSE file that
    14  * accompanied this code).
    15  *
    16  * You should have received a copy of the GNU General Public License version
    17  * 2 along with this work; if not, write to the Free Software Foundation,
    18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    19  *
    20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    21  * or visit www.oracle.com if you need additional information or have any
    22  * questions.
    23  *
    24  */
    26 #include "precompiled.hpp"
    27 #include "gc_implementation/shared/mutableNUMASpace.hpp"
    28 #include "gc_implementation/shared/spaceDecorator.hpp"
    29 #include "memory/sharedHeap.hpp"
    30 #include "oops/oop.inline.hpp"
    31 #ifdef TARGET_OS_FAMILY_linux
    32 # include "thread_linux.inline.hpp"
    33 #endif
    34 #ifdef TARGET_OS_FAMILY_solaris
    35 # include "thread_solaris.inline.hpp"
    36 #endif
    37 #ifdef TARGET_OS_FAMILY_windows
    38 # include "thread_windows.inline.hpp"
    39 #endif
    40 #ifdef TARGET_OS_FAMILY_bsd
    41 # include "thread_bsd.inline.hpp"
    42 #endif
    45 MutableNUMASpace::MutableNUMASpace(size_t alignment) : MutableSpace(alignment) {
    46   _lgrp_spaces = new (ResourceObj::C_HEAP) GrowableArray<LGRPSpace*>(0, true);
    47   _page_size = os::vm_page_size();
    48   _adaptation_cycles = 0;
    49   _samples_count = 0;
    50   update_layout(true);
    51 }
    53 MutableNUMASpace::~MutableNUMASpace() {
    54   for (int i = 0; i < lgrp_spaces()->length(); i++) {
    55     delete lgrp_spaces()->at(i);
    56   }
    57   delete lgrp_spaces();
    58 }
    60 #ifndef PRODUCT
    61 void MutableNUMASpace::mangle_unused_area() {
    62   // This method should do nothing.
    63   // It can be called on a numa space during a full compaction.
    64 }
    65 void MutableNUMASpace::mangle_unused_area_complete() {
    66   // This method should do nothing.
    67   // It can be called on a numa space during a full compaction.
    68 }
    69 void MutableNUMASpace::mangle_region(MemRegion mr) {
    70   // This method should do nothing because numa spaces are not mangled.
    71 }
    72 void MutableNUMASpace::set_top_for_allocations(HeapWord* v) {
    73   assert(false, "Do not mangle MutableNUMASpace's");
    74 }
    75 void MutableNUMASpace::set_top_for_allocations() {
    76   // This method should do nothing.
    77 }
    78 void MutableNUMASpace::check_mangled_unused_area(HeapWord* limit) {
    79   // This method should do nothing.
    80 }
    81 void MutableNUMASpace::check_mangled_unused_area_complete() {
    82   // This method should do nothing.
    83 }
    84 #endif  // NOT_PRODUCT
    86 // There may be unallocated holes in the middle chunks
    87 // that should be filled with dead objects to ensure parseability.
    88 void MutableNUMASpace::ensure_parsability() {
    89   for (int i = 0; i < lgrp_spaces()->length(); i++) {
    90     LGRPSpace *ls = lgrp_spaces()->at(i);
    91     MutableSpace *s = ls->space();
    92     if (s->top() < top()) { // For all spaces preceding the one containing top()
    93       if (s->free_in_words() > 0) {
    94         size_t area_touched_words = pointer_delta(s->end(), s->top());
    95         CollectedHeap::fill_with_object(s->top(), area_touched_words);
    96 #ifndef ASSERT
    97         if (!ZapUnusedHeapArea) {
    98           area_touched_words = MIN2((size_t)align_object_size(typeArrayOopDesc::header_size(T_INT)),
    99                                     area_touched_words);
   100         }
   101 #endif
   102         if (!os::numa_has_static_binding()) {
   103           MemRegion invalid;
   104           HeapWord *crossing_start = (HeapWord*)round_to((intptr_t)s->top(), os::vm_page_size());
   105           HeapWord *crossing_end = (HeapWord*)round_to((intptr_t)(s->top() + area_touched_words),
   106                                                        os::vm_page_size());
   107           if (crossing_start != crossing_end) {
   108             // If object header crossed a small page boundary we mark the area
   109             // as invalid rounding it to a page_size().
   110             HeapWord *start = MAX2((HeapWord*)round_down((intptr_t)s->top(), page_size()), s->bottom());
   111             HeapWord *end = MIN2((HeapWord*)round_to((intptr_t)(s->top() + area_touched_words), page_size()),
   112                                  s->end());
   113             invalid = MemRegion(start, end);
   114           }
   116           ls->add_invalid_region(invalid);
   117         }
   118       }
   119     } else {
   120       if (!os::numa_has_static_binding()) {
   121 #ifdef ASSERT
   122         MemRegion invalid(s->top(), s->end());
   123         ls->add_invalid_region(invalid);
   124 #else
   125         if (ZapUnusedHeapArea) {
   126           MemRegion invalid(s->top(), s->end());
   127           ls->add_invalid_region(invalid);
   128         } else {
   129           return;
   130         }
   131 #endif
   132       } else {
   133           return;
   134       }
   135     }
   136   }
   137 }
   139 size_t MutableNUMASpace::used_in_words() const {
   140   size_t s = 0;
   141   for (int i = 0; i < lgrp_spaces()->length(); i++) {
   142     s += lgrp_spaces()->at(i)->space()->used_in_words();
   143   }
   144   return s;
   145 }
   147 size_t MutableNUMASpace::free_in_words() const {
   148   size_t s = 0;
   149   for (int i = 0; i < lgrp_spaces()->length(); i++) {
   150     s += lgrp_spaces()->at(i)->space()->free_in_words();
   151   }
   152   return s;
   153 }
   156 size_t MutableNUMASpace::tlab_capacity(Thread *thr) const {
   157   guarantee(thr != NULL, "No thread");
   158   int lgrp_id = thr->lgrp_id();
   159   if (lgrp_id == -1) {
   160     // This case can occur after the topology of the system has
   161     // changed. Thread can change their location, the new home
   162     // group will be determined during the first allocation
   163     // attempt. For now we can safely assume that all spaces
   164     // have equal size because the whole space will be reinitialized.
   165     if (lgrp_spaces()->length() > 0) {
   166       return capacity_in_bytes() / lgrp_spaces()->length();
   167     } else {
   168       assert(false, "There should be at least one locality group");
   169       return 0;
   170     }
   171   }
   172   // That's the normal case, where we know the locality group of the thread.
   173   int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals);
   174   if (i == -1) {
   175     return 0;
   176   }
   177   return lgrp_spaces()->at(i)->space()->capacity_in_bytes();
   178 }
   180 size_t MutableNUMASpace::unsafe_max_tlab_alloc(Thread *thr) const {
   181   // Please see the comments for tlab_capacity().
   182   guarantee(thr != NULL, "No thread");
   183   int lgrp_id = thr->lgrp_id();
   184   if (lgrp_id == -1) {
   185     if (lgrp_spaces()->length() > 0) {
   186       return free_in_bytes() / lgrp_spaces()->length();
   187     } else {
   188       assert(false, "There should be at least one locality group");
   189       return 0;
   190     }
   191   }
   192   int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals);
   193   if (i == -1) {
   194     return 0;
   195   }
   196   return lgrp_spaces()->at(i)->space()->free_in_bytes();
   197 }
   200 size_t MutableNUMASpace::capacity_in_words(Thread* thr) const {
   201   guarantee(thr != NULL, "No thread");
   202   int lgrp_id = thr->lgrp_id();
   203   if (lgrp_id == -1) {
   204     if (lgrp_spaces()->length() > 0) {
   205       return capacity_in_words() / lgrp_spaces()->length();
   206     } else {
   207       assert(false, "There should be at least one locality group");
   208       return 0;
   209     }
   210   }
   211   int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals);
   212   if (i == -1) {
   213     return 0;
   214   }
   215   return lgrp_spaces()->at(i)->space()->capacity_in_words();
   216 }
   218 // Check if the NUMA topology has changed. Add and remove spaces if needed.
   219 // The update can be forced by setting the force parameter equal to true.
   220 bool MutableNUMASpace::update_layout(bool force) {
   221   // Check if the topology had changed.
   222   bool changed = os::numa_topology_changed();
   223   if (force || changed) {
   224     // Compute lgrp intersection. Add/remove spaces.
   225     int lgrp_limit = (int)os::numa_get_groups_num();
   226     int *lgrp_ids = NEW_C_HEAP_ARRAY(int, lgrp_limit);
   227     int lgrp_num = (int)os::numa_get_leaf_groups(lgrp_ids, lgrp_limit);
   228     assert(lgrp_num > 0, "There should be at least one locality group");
   229     // Add new spaces for the new nodes
   230     for (int i = 0; i < lgrp_num; i++) {
   231       bool found = false;
   232       for (int j = 0; j < lgrp_spaces()->length(); j++) {
   233         if (lgrp_spaces()->at(j)->lgrp_id() == lgrp_ids[i]) {
   234           found = true;
   235           break;
   236         }
   237       }
   238       if (!found) {
   239         lgrp_spaces()->append(new LGRPSpace(lgrp_ids[i], alignment()));
   240       }
   241     }
   243     // Remove spaces for the removed nodes.
   244     for (int i = 0; i < lgrp_spaces()->length();) {
   245       bool found = false;
   246       for (int j = 0; j < lgrp_num; j++) {
   247         if (lgrp_spaces()->at(i)->lgrp_id() == lgrp_ids[j]) {
   248           found = true;
   249           break;
   250         }
   251       }
   252       if (!found) {
   253         delete lgrp_spaces()->at(i);
   254         lgrp_spaces()->remove_at(i);
   255       } else {
   256         i++;
   257       }
   258     }
   260     FREE_C_HEAP_ARRAY(int, lgrp_ids);
   262     if (changed) {
   263       for (JavaThread *thread = Threads::first(); thread; thread = thread->next()) {
   264         thread->set_lgrp_id(-1);
   265       }
   266     }
   267     return true;
   268   }
   269   return false;
   270 }
   272 // Bias region towards the first-touching lgrp. Set the right page sizes.
   273 void MutableNUMASpace::bias_region(MemRegion mr, int lgrp_id) {
   274   HeapWord *start = (HeapWord*)round_to((intptr_t)mr.start(), page_size());
   275   HeapWord *end = (HeapWord*)round_down((intptr_t)mr.end(), page_size());
   276   if (end > start) {
   277     MemRegion aligned_region(start, end);
   278     assert((intptr_t)aligned_region.start()     % page_size() == 0 &&
   279            (intptr_t)aligned_region.byte_size() % page_size() == 0, "Bad alignment");
   280     assert(region().contains(aligned_region), "Sanity");
   281     // First we tell the OS which page size we want in the given range. The underlying
   282     // large page can be broken down if we require small pages.
   283     os::realign_memory((char*)aligned_region.start(), aligned_region.byte_size(), page_size());
   284     // Then we uncommit the pages in the range.
   285     os::free_memory((char*)aligned_region.start(), aligned_region.byte_size());
   286     // And make them local/first-touch biased.
   287     os::numa_make_local((char*)aligned_region.start(), aligned_region.byte_size(), lgrp_id);
   288   }
   289 }
   291 // Free all pages in the region.
   292 void MutableNUMASpace::free_region(MemRegion mr) {
   293   HeapWord *start = (HeapWord*)round_to((intptr_t)mr.start(), page_size());
   294   HeapWord *end = (HeapWord*)round_down((intptr_t)mr.end(), page_size());
   295   if (end > start) {
   296     MemRegion aligned_region(start, end);
   297     assert((intptr_t)aligned_region.start()     % page_size() == 0 &&
   298            (intptr_t)aligned_region.byte_size() % page_size() == 0, "Bad alignment");
   299     assert(region().contains(aligned_region), "Sanity");
   300     os::free_memory((char*)aligned_region.start(), aligned_region.byte_size());
   301   }
   302 }
   304 // Update space layout. Perform adaptation.
   305 void MutableNUMASpace::update() {
   306   if (update_layout(false)) {
   307     // If the topology has changed, make all chunks zero-sized.
   308     // And clear the alloc-rate statistics.
   309     // In future we may want to handle this more gracefully in order
   310     // to avoid the reallocation of the pages as much as possible.
   311     for (int i = 0; i < lgrp_spaces()->length(); i++) {
   312       LGRPSpace *ls = lgrp_spaces()->at(i);
   313       MutableSpace *s = ls->space();
   314       s->set_end(s->bottom());
   315       s->set_top(s->bottom());
   316       ls->clear_alloc_rate();
   317     }
   318     // A NUMA space is never mangled
   319     initialize(region(),
   320                SpaceDecorator::Clear,
   321                SpaceDecorator::DontMangle);
   322   } else {
   323     bool should_initialize = false;
   324     if (!os::numa_has_static_binding()) {
   325       for (int i = 0; i < lgrp_spaces()->length(); i++) {
   326         if (!lgrp_spaces()->at(i)->invalid_region().is_empty()) {
   327           should_initialize = true;
   328           break;
   329         }
   330       }
   331     }
   333     if (should_initialize ||
   334         (UseAdaptiveNUMAChunkSizing && adaptation_cycles() < samples_count())) {
   335       // A NUMA space is never mangled
   336       initialize(region(),
   337                  SpaceDecorator::Clear,
   338                  SpaceDecorator::DontMangle);
   339     }
   340   }
   342   if (NUMAStats) {
   343     for (int i = 0; i < lgrp_spaces()->length(); i++) {
   344       lgrp_spaces()->at(i)->accumulate_statistics(page_size());
   345     }
   346   }
   348   scan_pages(NUMAPageScanRate);
   349 }
   351 // Scan pages. Free pages that have smaller size or wrong placement.
   352 void MutableNUMASpace::scan_pages(size_t page_count)
   353 {
   354   size_t pages_per_chunk = page_count / lgrp_spaces()->length();
   355   if (pages_per_chunk > 0) {
   356     for (int i = 0; i < lgrp_spaces()->length(); i++) {
   357       LGRPSpace *ls = lgrp_spaces()->at(i);
   358       ls->scan_pages(page_size(), pages_per_chunk);
   359     }
   360   }
   361 }
   363 // Accumulate statistics about the allocation rate of each lgrp.
   364 void MutableNUMASpace::accumulate_statistics() {
   365   if (UseAdaptiveNUMAChunkSizing) {
   366     for (int i = 0; i < lgrp_spaces()->length(); i++) {
   367       lgrp_spaces()->at(i)->sample();
   368     }
   369     increment_samples_count();
   370   }
   372   if (NUMAStats) {
   373     for (int i = 0; i < lgrp_spaces()->length(); i++) {
   374       lgrp_spaces()->at(i)->accumulate_statistics(page_size());
   375     }
   376   }
   377 }
   379 // Get the current size of a chunk.
   380 // This function computes the size of the chunk based on the
   381 // difference between chunk ends. This allows it to work correctly in
   382 // case the whole space is resized and during the process of adaptive
   383 // chunk resizing.
   384 size_t MutableNUMASpace::current_chunk_size(int i) {
   385   HeapWord *cur_end, *prev_end;
   386   if (i == 0) {
   387     prev_end = bottom();
   388   } else {
   389     prev_end = lgrp_spaces()->at(i - 1)->space()->end();
   390   }
   391   if (i == lgrp_spaces()->length() - 1) {
   392     cur_end = end();
   393   } else {
   394     cur_end = lgrp_spaces()->at(i)->space()->end();
   395   }
   396   if (cur_end > prev_end) {
   397     return pointer_delta(cur_end, prev_end, sizeof(char));
   398   }
   399   return 0;
   400 }
   402 // Return the default chunk size by equally diving the space.
   403 // page_size() aligned.
   404 size_t MutableNUMASpace::default_chunk_size() {
   405   return base_space_size() / lgrp_spaces()->length() * page_size();
   406 }
   408 // Produce a new chunk size. page_size() aligned.
   409 // This function is expected to be called on sequence of i's from 0 to
   410 // lgrp_spaces()->length().
   411 size_t MutableNUMASpace::adaptive_chunk_size(int i, size_t limit) {
   412   size_t pages_available = base_space_size();
   413   for (int j = 0; j < i; j++) {
   414     pages_available -= round_down(current_chunk_size(j), page_size()) / page_size();
   415   }
   416   pages_available -= lgrp_spaces()->length() - i - 1;
   417   assert(pages_available > 0, "No pages left");
   418   float alloc_rate = 0;
   419   for (int j = i; j < lgrp_spaces()->length(); j++) {
   420     alloc_rate += lgrp_spaces()->at(j)->alloc_rate()->average();
   421   }
   422   size_t chunk_size = 0;
   423   if (alloc_rate > 0) {
   424     LGRPSpace *ls = lgrp_spaces()->at(i);
   425     chunk_size = (size_t)(ls->alloc_rate()->average() / alloc_rate * pages_available) * page_size();
   426   }
   427   chunk_size = MAX2(chunk_size, page_size());
   429   if (limit > 0) {
   430     limit = round_down(limit, page_size());
   431     if (chunk_size > current_chunk_size(i)) {
   432       size_t upper_bound = pages_available * page_size();
   433       if (upper_bound > limit &&
   434           current_chunk_size(i) < upper_bound - limit) {
   435         // The resulting upper bound should not exceed the available
   436         // amount of memory (pages_available * page_size()).
   437         upper_bound = current_chunk_size(i) + limit;
   438       }
   439       chunk_size = MIN2(chunk_size, upper_bound);
   440     } else {
   441       size_t lower_bound = page_size();
   442       if (current_chunk_size(i) > limit) { // lower_bound shouldn't underflow.
   443         lower_bound = current_chunk_size(i) - limit;
   444       }
   445       chunk_size = MAX2(chunk_size, lower_bound);
   446     }
   447   }
   448   assert(chunk_size <= pages_available * page_size(), "Chunk size out of range");
   449   return chunk_size;
   450 }
   453 // Return the bottom_region and the top_region. Align them to page_size() boundary.
   454 // |------------------new_region---------------------------------|
   455 // |----bottom_region--|---intersection---|------top_region------|
   456 void MutableNUMASpace::select_tails(MemRegion new_region, MemRegion intersection,
   457                                     MemRegion* bottom_region, MemRegion *top_region) {
   458   // Is there bottom?
   459   if (new_region.start() < intersection.start()) { // Yes
   460     // Try to coalesce small pages into a large one.
   461     if (UseLargePages && page_size() >= alignment()) {
   462       HeapWord* p = (HeapWord*)round_to((intptr_t) intersection.start(), alignment());
   463       if (new_region.contains(p)
   464           && pointer_delta(p, new_region.start(), sizeof(char)) >= alignment()) {
   465         if (intersection.contains(p)) {
   466           intersection = MemRegion(p, intersection.end());
   467         } else {
   468           intersection = MemRegion(p, p);
   469         }
   470       }
   471     }
   472     *bottom_region = MemRegion(new_region.start(), intersection.start());
   473   } else {
   474     *bottom_region = MemRegion();
   475   }
   477   // Is there top?
   478   if (intersection.end() < new_region.end()) { // Yes
   479     // Try to coalesce small pages into a large one.
   480     if (UseLargePages && page_size() >= alignment()) {
   481       HeapWord* p = (HeapWord*)round_down((intptr_t) intersection.end(), alignment());
   482       if (new_region.contains(p)
   483           && pointer_delta(new_region.end(), p, sizeof(char)) >= alignment()) {
   484         if (intersection.contains(p)) {
   485           intersection = MemRegion(intersection.start(), p);
   486         } else {
   487           intersection = MemRegion(p, p);
   488         }
   489       }
   490     }
   491     *top_region = MemRegion(intersection.end(), new_region.end());
   492   } else {
   493     *top_region = MemRegion();
   494   }
   495 }
   497 // Try to merge the invalid region with the bottom or top region by decreasing
   498 // the intersection area. Return the invalid_region aligned to the page_size()
   499 // boundary if it's inside the intersection. Return non-empty invalid_region
   500 // if it lies inside the intersection (also page-aligned).
   501 // |------------------new_region---------------------------------|
   502 // |----------------|-------invalid---|--------------------------|
   503 // |----bottom_region--|---intersection---|------top_region------|
   504 void MutableNUMASpace::merge_regions(MemRegion new_region, MemRegion* intersection,
   505                                      MemRegion *invalid_region) {
   506   if (intersection->start() >= invalid_region->start() && intersection->contains(invalid_region->end())) {
   507     *intersection = MemRegion(invalid_region->end(), intersection->end());
   508     *invalid_region = MemRegion();
   509   } else
   510     if (intersection->end() <= invalid_region->end() && intersection->contains(invalid_region->start())) {
   511       *intersection = MemRegion(intersection->start(), invalid_region->start());
   512       *invalid_region = MemRegion();
   513     } else
   514       if (intersection->equals(*invalid_region) || invalid_region->contains(*intersection)) {
   515         *intersection = MemRegion(new_region.start(), new_region.start());
   516         *invalid_region = MemRegion();
   517       } else
   518         if (intersection->contains(invalid_region)) {
   519             // That's the only case we have to make an additional bias_region() call.
   520             HeapWord* start = invalid_region->start();
   521             HeapWord* end = invalid_region->end();
   522             if (UseLargePages && page_size() >= alignment()) {
   523               HeapWord *p = (HeapWord*)round_down((intptr_t) start, alignment());
   524               if (new_region.contains(p)) {
   525                 start = p;
   526               }
   527               p = (HeapWord*)round_to((intptr_t) end, alignment());
   528               if (new_region.contains(end)) {
   529                 end = p;
   530               }
   531             }
   532             if (intersection->start() > start) {
   533               *intersection = MemRegion(start, intersection->end());
   534             }
   535             if (intersection->end() < end) {
   536               *intersection = MemRegion(intersection->start(), end);
   537             }
   538             *invalid_region = MemRegion(start, end);
   539         }
   540 }
   542 void MutableNUMASpace::initialize(MemRegion mr,
   543                                   bool clear_space,
   544                                   bool mangle_space,
   545                                   bool setup_pages) {
   546   assert(clear_space, "Reallocation will destory data!");
   547   assert(lgrp_spaces()->length() > 0, "There should be at least one space");
   549   MemRegion old_region = region(), new_region;
   550   set_bottom(mr.start());
   551   set_end(mr.end());
   552   // Must always clear the space
   553   clear(SpaceDecorator::DontMangle);
   555   // Compute chunk sizes
   556   size_t prev_page_size = page_size();
   557   set_page_size(UseLargePages ? alignment() : os::vm_page_size());
   558   HeapWord* rounded_bottom = (HeapWord*)round_to((intptr_t) bottom(), page_size());
   559   HeapWord* rounded_end = (HeapWord*)round_down((intptr_t) end(), page_size());
   560   size_t base_space_size_pages = pointer_delta(rounded_end, rounded_bottom, sizeof(char)) / page_size();
   562   // Try small pages if the chunk size is too small
   563   if (base_space_size_pages / lgrp_spaces()->length() == 0
   564       && page_size() > (size_t)os::vm_page_size()) {
   565     set_page_size(os::vm_page_size());
   566     rounded_bottom = (HeapWord*)round_to((intptr_t) bottom(), page_size());
   567     rounded_end = (HeapWord*)round_down((intptr_t) end(), page_size());
   568     base_space_size_pages = pointer_delta(rounded_end, rounded_bottom, sizeof(char)) / page_size();
   569   }
   570   guarantee(base_space_size_pages / lgrp_spaces()->length() > 0, "Space too small");
   571   set_base_space_size(base_space_size_pages);
   573   // Handle space resize
   574   MemRegion top_region, bottom_region;
   575   if (!old_region.equals(region())) {
   576     new_region = MemRegion(rounded_bottom, rounded_end);
   577     MemRegion intersection = new_region.intersection(old_region);
   578     if (intersection.start() == NULL ||
   579         intersection.end() == NULL   ||
   580         prev_page_size > page_size()) { // If the page size got smaller we have to change
   581                                         // the page size preference for the whole space.
   582       intersection = MemRegion(new_region.start(), new_region.start());
   583     }
   584     select_tails(new_region, intersection, &bottom_region, &top_region);
   585     bias_region(bottom_region, lgrp_spaces()->at(0)->lgrp_id());
   586     bias_region(top_region, lgrp_spaces()->at(lgrp_spaces()->length() - 1)->lgrp_id());
   587   }
   589   // Check if the space layout has changed significantly?
   590   // This happens when the space has been resized so that either head or tail
   591   // chunk became less than a page.
   592   bool layout_valid = UseAdaptiveNUMAChunkSizing          &&
   593                       current_chunk_size(0) > page_size() &&
   594                       current_chunk_size(lgrp_spaces()->length() - 1) > page_size();
   597   for (int i = 0; i < lgrp_spaces()->length(); i++) {
   598     LGRPSpace *ls = lgrp_spaces()->at(i);
   599     MutableSpace *s = ls->space();
   600     old_region = s->region();
   602     size_t chunk_byte_size = 0, old_chunk_byte_size = 0;
   603     if (i < lgrp_spaces()->length() - 1) {
   604       if (!UseAdaptiveNUMAChunkSizing                                ||
   605           (UseAdaptiveNUMAChunkSizing && NUMAChunkResizeWeight == 0) ||
   606            samples_count() < AdaptiveSizePolicyReadyThreshold) {
   607         // No adaptation. Divide the space equally.
   608         chunk_byte_size = default_chunk_size();
   609       } else
   610         if (!layout_valid || NUMASpaceResizeRate == 0) {
   611           // Fast adaptation. If no space resize rate is set, resize
   612           // the chunks instantly.
   613           chunk_byte_size = adaptive_chunk_size(i, 0);
   614         } else {
   615           // Slow adaptation. Resize the chunks moving no more than
   616           // NUMASpaceResizeRate bytes per collection.
   617           size_t limit = NUMASpaceResizeRate /
   618                          (lgrp_spaces()->length() * (lgrp_spaces()->length() + 1) / 2);
   619           chunk_byte_size = adaptive_chunk_size(i, MAX2(limit * (i + 1), page_size()));
   620         }
   622       assert(chunk_byte_size >= page_size(), "Chunk size too small");
   623       assert(chunk_byte_size <= capacity_in_bytes(), "Sanity check");
   624     }
   626     if (i == 0) { // Bottom chunk
   627       if (i != lgrp_spaces()->length() - 1) {
   628         new_region = MemRegion(bottom(), rounded_bottom + (chunk_byte_size >> LogHeapWordSize));
   629       } else {
   630         new_region = MemRegion(bottom(), end());
   631       }
   632     } else
   633       if (i < lgrp_spaces()->length() - 1) { // Middle chunks
   634         MutableSpace *ps = lgrp_spaces()->at(i - 1)->space();
   635         new_region = MemRegion(ps->end(),
   636                                ps->end() + (chunk_byte_size >> LogHeapWordSize));
   637       } else { // Top chunk
   638         MutableSpace *ps = lgrp_spaces()->at(i - 1)->space();
   639         new_region = MemRegion(ps->end(), end());
   640       }
   641     guarantee(region().contains(new_region), "Region invariant");
   644     // The general case:
   645     // |---------------------|--invalid---|--------------------------|
   646     // |------------------new_region---------------------------------|
   647     // |----bottom_region--|---intersection---|------top_region------|
   648     //                     |----old_region----|
   649     // The intersection part has all pages in place we don't need to migrate them.
   650     // Pages for the top and bottom part should be freed and then reallocated.
   652     MemRegion intersection = old_region.intersection(new_region);
   654     if (intersection.start() == NULL || intersection.end() == NULL) {
   655       intersection = MemRegion(new_region.start(), new_region.start());
   656     }
   658     if (!os::numa_has_static_binding()) {
   659       MemRegion invalid_region = ls->invalid_region().intersection(new_region);
   660       // Invalid region is a range of memory that could've possibly
   661       // been allocated on the other node. That's relevant only on Solaris where
   662       // there is no static memory binding.
   663       if (!invalid_region.is_empty()) {
   664         merge_regions(new_region, &intersection, &invalid_region);
   665         free_region(invalid_region);
   666         ls->set_invalid_region(MemRegion());
   667       }
   668     }
   670     select_tails(new_region, intersection, &bottom_region, &top_region);
   672     if (!os::numa_has_static_binding()) {
   673       // If that's a system with the first-touch policy then it's enough
   674       // to free the pages.
   675       free_region(bottom_region);
   676       free_region(top_region);
   677     } else {
   678       // In a system with static binding we have to change the bias whenever
   679       // we reshape the heap.
   680       bias_region(bottom_region, ls->lgrp_id());
   681       bias_region(top_region, ls->lgrp_id());
   682     }
   684     // Clear space (set top = bottom) but never mangle.
   685     s->initialize(new_region, SpaceDecorator::Clear, SpaceDecorator::DontMangle, MutableSpace::DontSetupPages);
   687     set_adaptation_cycles(samples_count());
   688   }
   689 }
   691 // Set the top of the whole space.
   692 // Mark the the holes in chunks below the top() as invalid.
   693 void MutableNUMASpace::set_top(HeapWord* value) {
   694   bool found_top = false;
   695   for (int i = 0; i < lgrp_spaces()->length();) {
   696     LGRPSpace *ls = lgrp_spaces()->at(i);
   697     MutableSpace *s = ls->space();
   698     HeapWord *top = MAX2((HeapWord*)round_down((intptr_t)s->top(), page_size()), s->bottom());
   700     if (s->contains(value)) {
   701       // Check if setting the chunk's top to a given value would create a hole less than
   702       // a minimal object; assuming that's not the last chunk in which case we don't care.
   703       if (i < lgrp_spaces()->length() - 1) {
   704         size_t remainder = pointer_delta(s->end(), value);
   705         const size_t min_fill_size = CollectedHeap::min_fill_size();
   706         if (remainder < min_fill_size && remainder > 0) {
   707           // Add a minimum size filler object; it will cross the chunk boundary.
   708           CollectedHeap::fill_with_object(value, min_fill_size);
   709           value += min_fill_size;
   710           assert(!s->contains(value), "Should be in the next chunk");
   711           // Restart the loop from the same chunk, since the value has moved
   712           // to the next one.
   713           continue;
   714         }
   715       }
   717       if (!os::numa_has_static_binding() && top < value && top < s->end()) {
   718         ls->add_invalid_region(MemRegion(top, value));
   719       }
   720       s->set_top(value);
   721       found_top = true;
   722     } else {
   723         if (found_top) {
   724             s->set_top(s->bottom());
   725         } else {
   726           if (!os::numa_has_static_binding() && top < s->end()) {
   727             ls->add_invalid_region(MemRegion(top, s->end()));
   728           }
   729           s->set_top(s->end());
   730         }
   731     }
   732     i++;
   733   }
   734   MutableSpace::set_top(value);
   735 }
   737 void MutableNUMASpace::clear(bool mangle_space) {
   738   MutableSpace::set_top(bottom());
   739   for (int i = 0; i < lgrp_spaces()->length(); i++) {
   740     // Never mangle NUMA spaces because the mangling will
   741     // bind the memory to a possibly unwanted lgroup.
   742     lgrp_spaces()->at(i)->space()->clear(SpaceDecorator::DontMangle);
   743   }
   744 }
   746 /*
   747    Linux supports static memory binding, therefore the most part of the
   748    logic dealing with the possible invalid page allocation is effectively
   749    disabled. Besides there is no notion of the home node in Linux. A
   750    thread is allowed to migrate freely. Although the scheduler is rather
   751    reluctant to move threads between the nodes. We check for the current
   752    node every allocation. And with a high probability a thread stays on
   753    the same node for some time allowing local access to recently allocated
   754    objects.
   755  */
   757 HeapWord* MutableNUMASpace::allocate(size_t size) {
   758   Thread* thr = Thread::current();
   759   int lgrp_id = thr->lgrp_id();
   760   if (lgrp_id == -1 || !os::numa_has_group_homing()) {
   761     lgrp_id = os::numa_get_group_id();
   762     thr->set_lgrp_id(lgrp_id);
   763   }
   765   int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals);
   767   // It is possible that a new CPU has been hotplugged and
   768   // we haven't reshaped the space accordingly.
   769   if (i == -1) {
   770     i = os::random() % lgrp_spaces()->length();
   771   }
   773   LGRPSpace* ls = lgrp_spaces()->at(i);
   774   MutableSpace *s = ls->space();
   775   HeapWord *p = s->allocate(size);
   777   if (p != NULL) {
   778     size_t remainder = s->free_in_words();
   779     if (remainder < CollectedHeap::min_fill_size() && remainder > 0) {
   780       s->set_top(s->top() - size);
   781       p = NULL;
   782     }
   783   }
   784   if (p != NULL) {
   785     if (top() < s->top()) { // Keep _top updated.
   786       MutableSpace::set_top(s->top());
   787     }
   788   }
   789   // Make the page allocation happen here if there is no static binding..
   790   if (p != NULL && !os::numa_has_static_binding()) {
   791     for (HeapWord *i = p; i < p + size; i += os::vm_page_size() >> LogHeapWordSize) {
   792       *(int*)i = 0;
   793     }
   794   }
   795   if (p == NULL) {
   796     ls->set_allocation_failed();
   797   }
   798   return p;
   799 }
   801 // This version is lock-free.
   802 HeapWord* MutableNUMASpace::cas_allocate(size_t size) {
   803   Thread* thr = Thread::current();
   804   int lgrp_id = thr->lgrp_id();
   805   if (lgrp_id == -1 || !os::numa_has_group_homing()) {
   806     lgrp_id = os::numa_get_group_id();
   807     thr->set_lgrp_id(lgrp_id);
   808   }
   810   int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals);
   811   // It is possible that a new CPU has been hotplugged and
   812   // we haven't reshaped the space accordingly.
   813   if (i == -1) {
   814     i = os::random() % lgrp_spaces()->length();
   815   }
   816   LGRPSpace *ls = lgrp_spaces()->at(i);
   817   MutableSpace *s = ls->space();
   818   HeapWord *p = s->cas_allocate(size);
   819   if (p != NULL) {
   820     size_t remainder = pointer_delta(s->end(), p + size);
   821     if (remainder < CollectedHeap::min_fill_size() && remainder > 0) {
   822       if (s->cas_deallocate(p, size)) {
   823         // We were the last to allocate and created a fragment less than
   824         // a minimal object.
   825         p = NULL;
   826       } else {
   827         guarantee(false, "Deallocation should always succeed");
   828       }
   829     }
   830   }
   831   if (p != NULL) {
   832     HeapWord* cur_top, *cur_chunk_top = p + size;
   833     while ((cur_top = top()) < cur_chunk_top) { // Keep _top updated.
   834       if (Atomic::cmpxchg_ptr(cur_chunk_top, top_addr(), cur_top) == cur_top) {
   835         break;
   836       }
   837     }
   838   }
   840   // Make the page allocation happen here if there is no static binding.
   841   if (p != NULL && !os::numa_has_static_binding() ) {
   842     for (HeapWord *i = p; i < p + size; i += os::vm_page_size() >> LogHeapWordSize) {
   843       *(int*)i = 0;
   844     }
   845   }
   846   if (p == NULL) {
   847     ls->set_allocation_failed();
   848   }
   849   return p;
   850 }
   852 void MutableNUMASpace::print_short_on(outputStream* st) const {
   853   MutableSpace::print_short_on(st);
   854   st->print(" (");
   855   for (int i = 0; i < lgrp_spaces()->length(); i++) {
   856     st->print("lgrp %d: ", lgrp_spaces()->at(i)->lgrp_id());
   857     lgrp_spaces()->at(i)->space()->print_short_on(st);
   858     if (i < lgrp_spaces()->length() - 1) {
   859       st->print(", ");
   860     }
   861   }
   862   st->print(")");
   863 }
   865 void MutableNUMASpace::print_on(outputStream* st) const {
   866   MutableSpace::print_on(st);
   867   for (int i = 0; i < lgrp_spaces()->length(); i++) {
   868     LGRPSpace *ls = lgrp_spaces()->at(i);
   869     st->print("    lgrp %d", ls->lgrp_id());
   870     ls->space()->print_on(st);
   871     if (NUMAStats) {
   872       for (int i = 0; i < lgrp_spaces()->length(); i++) {
   873         lgrp_spaces()->at(i)->accumulate_statistics(page_size());
   874       }
   875       st->print("    local/remote/unbiased/uncommitted: %dK/%dK/%dK/%dK, large/small pages: %d/%d\n",
   876                 ls->space_stats()->_local_space / K,
   877                 ls->space_stats()->_remote_space / K,
   878                 ls->space_stats()->_unbiased_space / K,
   879                 ls->space_stats()->_uncommited_space / K,
   880                 ls->space_stats()->_large_pages,
   881                 ls->space_stats()->_small_pages);
   882     }
   883   }
   884 }
   886 void MutableNUMASpace::verify(bool allow_dirty) {
   887   // This can be called after setting an arbitary value to the space's top,
   888   // so an object can cross the chunk boundary. We ensure the parsablity
   889   // of the space and just walk the objects in linear fashion.
   890   ensure_parsability();
   891   MutableSpace::verify(allow_dirty);
   892 }
   894 // Scan pages and gather stats about page placement and size.
   895 void MutableNUMASpace::LGRPSpace::accumulate_statistics(size_t page_size) {
   896   clear_space_stats();
   897   char *start = (char*)round_to((intptr_t) space()->bottom(), page_size);
   898   char* end = (char*)round_down((intptr_t) space()->end(), page_size);
   899   if (start < end) {
   900     for (char *p = start; p < end;) {
   901       os::page_info info;
   902       if (os::get_page_info(p, &info)) {
   903         if (info.size > 0) {
   904           if (info.size > (size_t)os::vm_page_size()) {
   905             space_stats()->_large_pages++;
   906           } else {
   907             space_stats()->_small_pages++;
   908           }
   909           if (info.lgrp_id == lgrp_id()) {
   910             space_stats()->_local_space += info.size;
   911           } else {
   912             space_stats()->_remote_space += info.size;
   913           }
   914           p += info.size;
   915         } else {
   916           p += os::vm_page_size();
   917           space_stats()->_uncommited_space += os::vm_page_size();
   918         }
   919       } else {
   920         return;
   921       }
   922     }
   923   }
   924   space_stats()->_unbiased_space = pointer_delta(start, space()->bottom(), sizeof(char)) +
   925                                    pointer_delta(space()->end(), end, sizeof(char));
   927 }
   929 // Scan page_count pages and verify if they have the right size and right placement.
   930 // If invalid pages are found they are freed in hope that subsequent reallocation
   931 // will be more successful.
   932 void MutableNUMASpace::LGRPSpace::scan_pages(size_t page_size, size_t page_count)
   933 {
   934   char* range_start = (char*)round_to((intptr_t) space()->bottom(), page_size);
   935   char* range_end = (char*)round_down((intptr_t) space()->end(), page_size);
   937   if (range_start > last_page_scanned() || last_page_scanned() >= range_end) {
   938     set_last_page_scanned(range_start);
   939   }
   941   char *scan_start = last_page_scanned();
   942   char* scan_end = MIN2(scan_start + page_size * page_count, range_end);
   944   os::page_info page_expected, page_found;
   945   page_expected.size = page_size;
   946   page_expected.lgrp_id = lgrp_id();
   948   char *s = scan_start;
   949   while (s < scan_end) {
   950     char *e = os::scan_pages(s, (char*)scan_end, &page_expected, &page_found);
   951     if (e == NULL) {
   952       break;
   953     }
   954     if (e != scan_end) {
   955       if ((page_expected.size != page_size || page_expected.lgrp_id != lgrp_id())
   956           && page_expected.size != 0) {
   957         os::free_memory(s, pointer_delta(e, s, sizeof(char)));
   958       }
   959       page_expected = page_found;
   960     }
   961     s = e;
   962   }
   964   set_last_page_scanned(scan_end);
   965 }

mercurial