src/share/vm/gc_implementation/g1/heapRegionSet.cpp

Fri, 10 Oct 2014 15:51:58 +0200

author
tschatzl
date
Fri, 10 Oct 2014 15:51:58 +0200
changeset 7257
e7d0505c8a30
parent 7195
c02ec279b062
child 7535
7ae4e26cb1e0
child 7781
33e421924c67
permissions
-rw-r--r--

8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso

     1 /*
     2  * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #include "precompiled.hpp"
    26 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
    27 #include "gc_implementation/g1/heapRegionRemSet.hpp"
    28 #include "gc_implementation/g1/heapRegionSet.inline.hpp"
    30 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
    32 uint FreeRegionList::_unrealistically_long_length = 0;
    34 void HeapRegionSetBase::fill_in_ext_msg(hrs_ext_msg* msg, const char* message) {
    35   msg->append("[%s] %s ln: %u cy: "SIZE_FORMAT,
    36               name(), message, length(), total_capacity_bytes());
    37   fill_in_ext_msg_extra(msg);
    38 }
    40 #ifndef PRODUCT
    41 void HeapRegionSetBase::verify_region(HeapRegion* hr) {
    42   assert(hr->containing_set() == this, err_msg("Inconsistent containing set for %u", hr->hrm_index()));
    43   assert(!hr->is_young(), err_msg("Adding young region %u", hr->hrm_index())); // currently we don't use these sets for young regions
    44   assert(hr->isHumongous() == regions_humongous(), err_msg("Wrong humongous state for region %u and set %s", hr->hrm_index(), name()));
    45   assert(hr->is_free() == regions_free(), err_msg("Wrong free state for region %u and set %s", hr->hrm_index(), name()));
    46   assert(!hr->is_free() || hr->is_empty(), err_msg("Free region %u is not empty for set %s", hr->hrm_index(), name()));
    47   assert(!hr->is_empty() || hr->is_free(), err_msg("Empty region %u is not free for set %s", hr->hrm_index(), name()));
    48   assert(hr->rem_set()->verify_ready_for_par_iteration(), err_msg("Wrong iteration state %u", hr->hrm_index()));
    49 }
    50 #endif
    52 void HeapRegionSetBase::verify() {
    53   // It's important that we also observe the MT safety protocol even
    54   // for the verification calls. If we do verification without the
    55   // appropriate locks and the set changes underneath our feet
    56   // verification might fail and send us on a wild goose chase.
    57   check_mt_safety();
    59   guarantee(( is_empty() && length() == 0 && total_capacity_bytes() == 0) ||
    60             (!is_empty() && length() >= 0 && total_capacity_bytes() >= 0),
    61             hrs_ext_msg(this, "invariant"));
    62 }
    64 void HeapRegionSetBase::verify_start() {
    65   // See comment in verify() about MT safety and verification.
    66   check_mt_safety();
    67   assert(!_verify_in_progress,
    68          hrs_ext_msg(this, "verification should not be in progress"));
    70   // Do the basic verification first before we do the checks over the regions.
    71   HeapRegionSetBase::verify();
    73   _verify_in_progress = true;
    74 }
    76 void HeapRegionSetBase::verify_end() {
    77   // See comment in verify() about MT safety and verification.
    78   check_mt_safety();
    79   assert(_verify_in_progress,
    80          hrs_ext_msg(this, "verification should be in progress"));
    82   _verify_in_progress = false;
    83 }
    85 void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) {
    86   out->cr();
    87   out->print_cr("Set: %s ("PTR_FORMAT")", name(), this);
    88   out->print_cr("  Region Assumptions");
    89   out->print_cr("    humongous         : %s", BOOL_TO_STR(regions_humongous()));
    90   out->print_cr("    free              : %s", BOOL_TO_STR(regions_free()));
    91   out->print_cr("  Attributes");
    92   out->print_cr("    length            : %14u", length());
    93   out->print_cr("    total capacity    : "SIZE_FORMAT_W(14)" bytes",
    94                 total_capacity_bytes());
    95 }
    97 HeapRegionSetBase::HeapRegionSetBase(const char* name, bool humongous, bool free, HRSMtSafeChecker* mt_safety_checker)
    98   : _name(name), _verify_in_progress(false),
    99     _is_humongous(humongous), _is_free(free), _mt_safety_checker(mt_safety_checker),
   100     _count()
   101 { }
   103 void FreeRegionList::set_unrealistically_long_length(uint len) {
   104   guarantee(_unrealistically_long_length == 0, "should only be set once");
   105   _unrealistically_long_length = len;
   106 }
   108 void FreeRegionList::fill_in_ext_msg_extra(hrs_ext_msg* msg) {
   109   msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, _head, _tail);
   110 }
   112 void FreeRegionList::remove_all() {
   113   check_mt_safety();
   114   verify_optional();
   116   HeapRegion* curr = _head;
   117   while (curr != NULL) {
   118     verify_region(curr);
   120     HeapRegion* next = curr->next();
   121     curr->set_next(NULL);
   122     curr->set_prev(NULL);
   123     curr->set_containing_set(NULL);
   124     curr = next;
   125   }
   126   clear();
   128   verify_optional();
   129 }
   131 void FreeRegionList::add_ordered(FreeRegionList* from_list) {
   132   check_mt_safety();
   133   from_list->check_mt_safety();
   135   verify_optional();
   136   from_list->verify_optional();
   138   if (from_list->is_empty()) {
   139     return;
   140   }
   142   #ifdef ASSERT
   143   FreeRegionListIterator iter(from_list);
   144   while (iter.more_available()) {
   145     HeapRegion* hr = iter.get_next();
   146     // In set_containing_set() we check that we either set the value
   147     // from NULL to non-NULL or vice versa to catch bugs. So, we have
   148     // to NULL it first before setting it to the value.
   149     hr->set_containing_set(NULL);
   150     hr->set_containing_set(this);
   151   }
   152   #endif // ASSERT
   154   if (is_empty()) {
   155     assert(length() == 0 && _tail == NULL, hrs_ext_msg(this, "invariant"));
   156     _head = from_list->_head;
   157     _tail = from_list->_tail;
   158   } else {
   159     HeapRegion* curr_to = _head;
   160     HeapRegion* curr_from = from_list->_head;
   162     while (curr_from != NULL) {
   163       while (curr_to != NULL && curr_to->hrm_index() < curr_from->hrm_index()) {
   164         curr_to = curr_to->next();
   165       }
   167       if (curr_to == NULL) {
   168         // The rest of the from list should be added as tail
   169         _tail->set_next(curr_from);
   170         curr_from->set_prev(_tail);
   171         curr_from = NULL;
   172       } else {
   173         HeapRegion* next_from = curr_from->next();
   175         curr_from->set_next(curr_to);
   176         curr_from->set_prev(curr_to->prev());
   177         if (curr_to->prev() == NULL) {
   178           _head = curr_from;
   179         } else {
   180           curr_to->prev()->set_next(curr_from);
   181         }
   182         curr_to->set_prev(curr_from);
   184         curr_from = next_from;
   185       }
   186     }
   188     if (_tail->hrm_index() < from_list->_tail->hrm_index()) {
   189       _tail = from_list->_tail;
   190     }
   191   }
   193   _count.increment(from_list->length(), from_list->total_capacity_bytes());
   194   from_list->clear();
   196   verify_optional();
   197   from_list->verify_optional();
   198 }
   200 void FreeRegionList::remove_starting_at(HeapRegion* first, uint num_regions) {
   201   check_mt_safety();
   202   assert(num_regions >= 1, hrs_ext_msg(this, "pre-condition"));
   203   assert(!is_empty(), hrs_ext_msg(this, "pre-condition"));
   205   verify_optional();
   206   DEBUG_ONLY(uint old_length = length();)
   208   HeapRegion* curr = first;
   209   uint count = 0;
   210   while (count < num_regions) {
   211     verify_region(curr);
   212     HeapRegion* next = curr->next();
   213     HeapRegion* prev = curr->prev();
   215     assert(count < num_regions,
   216            hrs_err_msg("[%s] should not come across more regions "
   217                        "pending for removal than num_regions: %u",
   218                        name(), num_regions));
   220     if (prev == NULL) {
   221       assert(_head == curr, hrs_ext_msg(this, "invariant"));
   222       _head = next;
   223     } else {
   224       assert(_head != curr, hrs_ext_msg(this, "invariant"));
   225       prev->set_next(next);
   226     }
   227     if (next == NULL) {
   228       assert(_tail == curr, hrs_ext_msg(this, "invariant"));
   229       _tail = prev;
   230     } else {
   231       assert(_tail != curr, hrs_ext_msg(this, "invariant"));
   232       next->set_prev(prev);
   233     }
   234     if (_last = curr) {
   235       _last = NULL;
   236     }
   238     curr->set_next(NULL);
   239     curr->set_prev(NULL);
   240     remove(curr);
   242     count++;
   243     curr = next;
   244   }
   246   assert(count == num_regions,
   247          hrs_err_msg("[%s] count: %u should be == num_regions: %u",
   248                      name(), count, num_regions));
   249   assert(length() + num_regions == old_length,
   250          hrs_err_msg("[%s] new length should be consistent "
   251                      "new length: %u old length: %u num_regions: %u",
   252                      name(), length(), old_length, num_regions));
   254   verify_optional();
   255 }
   257 void FreeRegionList::verify() {
   258   // See comment in HeapRegionSetBase::verify() about MT safety and
   259   // verification.
   260   check_mt_safety();
   262   // This will also do the basic verification too.
   263   verify_start();
   265   verify_list();
   267   verify_end();
   268 }
   270 void FreeRegionList::clear() {
   271   _count = HeapRegionSetCount();
   272   _head = NULL;
   273   _tail = NULL;
   274   _last = NULL;
   275 }
   277 void FreeRegionList::print_on(outputStream* out, bool print_contents) {
   278   HeapRegionSetBase::print_on(out, print_contents);
   279   out->print_cr("  Linking");
   280   out->print_cr("    head              : "PTR_FORMAT, _head);
   281   out->print_cr("    tail              : "PTR_FORMAT, _tail);
   283   if (print_contents) {
   284     out->print_cr("  Contents");
   285     FreeRegionListIterator iter(this);
   286     while (iter.more_available()) {
   287       HeapRegion* hr = iter.get_next();
   288       hr->print_on(out);
   289     }
   290   }
   292   out->cr();
   293 }
   295 void FreeRegionList::verify_list() {
   296   HeapRegion* curr = _head;
   297   HeapRegion* prev1 = NULL;
   298   HeapRegion* prev0 = NULL;
   299   uint count = 0;
   300   size_t capacity = 0;
   301   uint last_index = 0;
   303   guarantee(_head == NULL || _head->prev() == NULL, "_head should not have a prev");
   304   while (curr != NULL) {
   305     verify_region(curr);
   307     count++;
   308     guarantee(count < _unrealistically_long_length,
   309         hrs_err_msg("[%s] the calculated length: %u seems very long, is there maybe a cycle? curr: "PTR_FORMAT" prev0: "PTR_FORMAT" " "prev1: "PTR_FORMAT" length: %u", name(), count, curr, prev0, prev1, length()));
   311     if (curr->next() != NULL) {
   312       guarantee(curr->next()->prev() == curr, "Next or prev pointers messed up");
   313     }
   314     guarantee(curr->hrm_index() == 0 || curr->hrm_index() > last_index, "List should be sorted");
   315     last_index = curr->hrm_index();
   317     capacity += curr->capacity();
   319     prev1 = prev0;
   320     prev0 = curr;
   321     curr = curr->next();
   322   }
   324   guarantee(_tail == prev0, err_msg("Expected %s to end with %u but it ended with %u.", name(), _tail->hrm_index(), prev0->hrm_index()));
   325   guarantee(_tail == NULL || _tail->next() == NULL, "_tail should not have a next");
   326   guarantee(length() == count, err_msg("%s count mismatch. Expected %u, actual %u.", name(), length(), count));
   327   guarantee(total_capacity_bytes() == capacity, err_msg("%s capacity mismatch. Expected " SIZE_FORMAT ", actual " SIZE_FORMAT,
   328       name(), total_capacity_bytes(), capacity));
   329 }
   331 // Note on the check_mt_safety() methods below:
   332 //
   333 // Verification of the "master" heap region sets / lists that are
   334 // maintained by G1CollectedHeap is always done during a STW pause and
   335 // by the VM thread at the start / end of the pause. The standard
   336 // verification methods all assert check_mt_safety(). This is
   337 // important as it ensures that verification is done without
   338 // concurrent updates taking place at the same time. It follows, that,
   339 // for the "master" heap region sets / lists, the check_mt_safety()
   340 // method should include the VM thread / STW case.
   342 void MasterFreeRegionListMtSafeChecker::check() {
   343   // Master Free List MT safety protocol:
   344   // (a) If we're at a safepoint, operations on the master free list
   345   // should be invoked by either the VM thread (which will serialize
   346   // them) or by the GC workers while holding the
   347   // FreeList_lock.
   348   // (b) If we're not at a safepoint, operations on the master free
   349   // list should be invoked while holding the Heap_lock.
   351   if (SafepointSynchronize::is_at_safepoint()) {
   352     guarantee(Thread::current()->is_VM_thread() ||
   353               FreeList_lock->owned_by_self(), "master free list MT safety protocol at a safepoint");
   354   } else {
   355     guarantee(Heap_lock->owned_by_self(), "master free list MT safety protocol outside a safepoint");
   356   }
   357 }
   359 void SecondaryFreeRegionListMtSafeChecker::check() {
   360   // Secondary Free List MT safety protocol:
   361   // Operations on the secondary free list should always be invoked
   362   // while holding the SecondaryFreeList_lock.
   364   guarantee(SecondaryFreeList_lock->owned_by_self(), "secondary free list MT safety protocol");
   365 }
   367 void OldRegionSetMtSafeChecker::check() {
   368   // Master Old Set MT safety protocol:
   369   // (a) If we're at a safepoint, operations on the master old set
   370   // should be invoked:
   371   // - by the VM thread (which will serialize them), or
   372   // - by the GC workers while holding the FreeList_lock, if we're
   373   //   at a safepoint for an evacuation pause (this lock is taken
   374   //   anyway when an GC alloc region is retired so that a new one
   375   //   is allocated from the free list), or
   376   // - by the GC workers while holding the OldSets_lock, if we're at a
   377   //   safepoint for a cleanup pause.
   378   // (b) If we're not at a safepoint, operations on the master old set
   379   // should be invoked while holding the Heap_lock.
   381   if (SafepointSynchronize::is_at_safepoint()) {
   382     guarantee(Thread::current()->is_VM_thread()
   383         || FreeList_lock->owned_by_self() || OldSets_lock->owned_by_self(),
   384         "master old set MT safety protocol at a safepoint");
   385   } else {
   386     guarantee(Heap_lock->owned_by_self(), "master old set MT safety protocol outside a safepoint");
   387   }
   388 }
   390 void HumongousRegionSetMtSafeChecker::check() {
   391   // Humongous Set MT safety protocol:
   392   // (a) If we're at a safepoint, operations on the master humongous
   393   // set should be invoked by either the VM thread (which will
   394   // serialize them) or by the GC workers while holding the
   395   // OldSets_lock.
   396   // (b) If we're not at a safepoint, operations on the master
   397   // humongous set should be invoked while holding the Heap_lock.
   399   if (SafepointSynchronize::is_at_safepoint()) {
   400     guarantee(Thread::current()->is_VM_thread() ||
   401               OldSets_lock->owned_by_self(),
   402               "master humongous set MT safety protocol at a safepoint");
   403   } else {
   404     guarantee(Heap_lock->owned_by_self(),
   405               "master humongous set MT safety protocol outside a safepoint");
   406   }
   407 }
   409 void FreeRegionList_test() {
   410   FreeRegionList l("test");
   412   const uint num_regions_in_test = 5;
   413   // Create a fake heap. It does not need to be valid, as the HeapRegion constructor
   414   // does not access it.
   415   MemRegion heap(NULL, num_regions_in_test * HeapRegion::GrainWords);
   416   // Allocate a fake BOT because the HeapRegion constructor initializes
   417   // the BOT.
   418   size_t bot_size = G1BlockOffsetSharedArray::compute_size(heap.word_size());
   419   HeapWord* bot_data = NEW_C_HEAP_ARRAY(HeapWord, bot_size, mtGC);
   420   ReservedSpace bot_rs(G1BlockOffsetSharedArray::compute_size(heap.word_size()));
   421   G1RegionToSpaceMapper* bot_storage =
   422     G1RegionToSpaceMapper::create_mapper(bot_rs,
   423                                          os::vm_page_size(),
   424                                          HeapRegion::GrainBytes,
   425                                          G1BlockOffsetSharedArray::N_bytes,
   426                                          mtGC);
   427   G1BlockOffsetSharedArray oa(heap, bot_storage);
   428   bot_storage->commit_regions(0, num_regions_in_test);
   429   HeapRegion hr0(0, &oa, heap);
   430   HeapRegion hr1(1, &oa, heap);
   431   HeapRegion hr2(2, &oa, heap);
   432   HeapRegion hr3(3, &oa, heap);
   433   HeapRegion hr4(4, &oa, heap);
   434   l.add_ordered(&hr1);
   435   l.add_ordered(&hr0);
   436   l.add_ordered(&hr3);
   437   l.add_ordered(&hr4);
   438   l.add_ordered(&hr2);
   439   assert(l.length() == num_regions_in_test, "wrong length");
   440   l.verify_list();
   442   bot_storage->uncommit_regions(0, num_regions_in_test);
   443   delete bot_storage;
   444   FREE_C_HEAP_ARRAY(HeapWord, bot_data, mtGC);
   445 }

mercurial