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

Tue, 23 Nov 2010 13:22:55 -0800

author
stefank
date
Tue, 23 Nov 2010 13:22:55 -0800
changeset 2314
f95d63e2154a
parent 1934
e9ff18c4ace7
child 3156
f08d439fab8c
permissions
-rw-r--r--

6989984: Use standard include model for Hospot
Summary: Replaced MakeDeps and the includeDB files with more standardized solutions.
Reviewed-by: coleenp, kvn, kamg

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

mercurial