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

Tue, 20 Sep 2011 09:59:59 -0400

author
tonyp
date
Tue, 20 Sep 2011 09:59:59 -0400
changeset 3168
4f93f0d00802
parent 2714
455328d90876
child 3268
8aae2050e83e
permissions
-rw-r--r--

7059019: G1: add G1 support to the SA
Summary: Extend the SA to recognize the G1CollectedHeap and implement any code that's needed by our serviceability tools (jmap, jinfo, jstack, etc.) that depend on the SA.
Reviewed-by: never, poonam, johnc

     1 /*
     2  * Copyright (c) 2011, 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/heapRegionSet.inline.hpp"
    28 size_t HeapRegionSetBase::_unrealistically_long_length = 0;
    30 //////////////////// HeapRegionSetBase ////////////////////
    32 void HeapRegionSetBase::set_unrealistically_long_length(size_t len) {
    33   guarantee(_unrealistically_long_length == 0, "should only be set once");
    34   _unrealistically_long_length = len;
    35 }
    37 size_t HeapRegionSetBase::calculate_region_num(HeapRegion* hr) {
    38   assert(hr->startsHumongous(), "pre-condition");
    39   assert(hr->capacity() % HeapRegion::GrainBytes == 0, "invariant");
    40   size_t region_num = hr->capacity() >> HeapRegion::LogOfHRGrainBytes;
    41   assert(region_num > 0, "sanity");
    42   return region_num;
    43 }
    45 void HeapRegionSetBase::fill_in_ext_msg(hrs_ext_msg* msg, const char* message) {
    46   msg->append("[%s] %s "
    47               "ln: "SIZE_FORMAT" rn: "SIZE_FORMAT" "
    48               "cy: "SIZE_FORMAT" ud: "SIZE_FORMAT,
    49               name(), message, length(), region_num(),
    50               total_capacity_bytes(), total_used_bytes());
    51   fill_in_ext_msg_extra(msg);
    52 }
    54 bool HeapRegionSetBase::verify_region(HeapRegion* hr,
    55                                   HeapRegionSetBase* expected_containing_set) {
    56   const char* error_message = NULL;
    58   if (!regions_humongous()) {
    59     if (hr->isHumongous()) {
    60       error_message = "the region should not be humongous";
    61     }
    62   } else {
    63     if (!hr->isHumongous() || !hr->startsHumongous()) {
    64       error_message = "the region should be 'starts humongous'";
    65     }
    66   }
    68   if (!regions_empty()) {
    69     if (hr->is_empty()) {
    70       error_message = "the region should not be empty";
    71     }
    72   } else {
    73     if (!hr->is_empty()) {
    74       error_message = "the region should be empty";
    75     }
    76   }
    78 #ifdef ASSERT
    79   // The _containing_set field is only available when ASSERT is defined.
    80   if (hr->containing_set() != expected_containing_set) {
    81     error_message = "inconsistent containing set found";
    82   }
    83 #endif // ASSERT
    85   const char* extra_error_message = verify_region_extra(hr);
    86   if (extra_error_message != NULL) {
    87     error_message = extra_error_message;
    88   }
    90   if (error_message != NULL) {
    91     outputStream* out = tty;
    92     out->cr();
    93     out->print_cr("## [%s] %s", name(), error_message);
    94     out->print_cr("## Offending Region: "PTR_FORMAT, hr);
    95     out->print_cr("   "HR_FORMAT, HR_FORMAT_PARAMS(hr));
    96 #ifdef ASSERT
    97     out->print_cr("   containing set: "PTR_FORMAT, hr->containing_set());
    98 #endif // ASSERT
    99     out->print_cr("## Offending Region Set: "PTR_FORMAT, this);
   100     print_on(out);
   101     return false;
   102   } else {
   103     return true;
   104   }
   105 }
   107 void HeapRegionSetBase::verify() {
   108   // It's important that we also observe the MT safety protocol even
   109   // for the verification calls. If we do verification without the
   110   // appropriate locks and the set changes underneath our feet
   111   // verification might fail and send us on a wild goose chase.
   112   hrs_assert_mt_safety_ok(this);
   114   guarantee(( is_empty() && length() == 0 && region_num() == 0 &&
   115               total_used_bytes() == 0 && total_capacity_bytes() == 0) ||
   116             (!is_empty() && length() >= 0 && region_num() >= 0 &&
   117               total_used_bytes() >= 0 && total_capacity_bytes() >= 0),
   118             hrs_ext_msg(this, "invariant"));
   120   guarantee((!regions_humongous() && region_num() == length()) ||
   121             ( regions_humongous() && region_num() >= length()),
   122             hrs_ext_msg(this, "invariant"));
   124   guarantee(!regions_empty() || total_used_bytes() == 0,
   125             hrs_ext_msg(this, "invariant"));
   127   guarantee(total_used_bytes() <= total_capacity_bytes(),
   128             hrs_ext_msg(this, "invariant"));
   129 }
   131 void HeapRegionSetBase::verify_start() {
   132   // See comment in verify() about MT safety and verification.
   133   hrs_assert_mt_safety_ok(this);
   134   assert(!_verify_in_progress,
   135          hrs_ext_msg(this, "verification should not be in progress"));
   137   // Do the basic verification first before we do the checks over the regions.
   138   HeapRegionSetBase::verify();
   140   _calc_length               = 0;
   141   _calc_region_num           = 0;
   142   _calc_total_capacity_bytes = 0;
   143   _calc_total_used_bytes     = 0;
   144   _verify_in_progress        = true;
   145 }
   147 void HeapRegionSetBase::verify_next_region(HeapRegion* hr) {
   148   // See comment in verify() about MT safety and verification.
   149   hrs_assert_mt_safety_ok(this);
   150   assert(_verify_in_progress,
   151          hrs_ext_msg(this, "verification should be in progress"));
   153   guarantee(verify_region(hr, this), hrs_ext_msg(this, "region verification"));
   155   _calc_length               += 1;
   156   if (!hr->isHumongous()) {
   157     _calc_region_num         += 1;
   158   } else {
   159     _calc_region_num         += calculate_region_num(hr);
   160   }
   161   _calc_total_capacity_bytes += hr->capacity();
   162   _calc_total_used_bytes     += hr->used();
   163 }
   165 void HeapRegionSetBase::verify_end() {
   166   // See comment in verify() about MT safety and verification.
   167   hrs_assert_mt_safety_ok(this);
   168   assert(_verify_in_progress,
   169          hrs_ext_msg(this, "verification should be in progress"));
   171   guarantee(length() == _calc_length,
   172             hrs_err_msg("[%s] length: "SIZE_FORMAT" should be == "
   173                         "calc length: "SIZE_FORMAT,
   174                         name(), length(), _calc_length));
   176   guarantee(region_num() == _calc_region_num,
   177             hrs_err_msg("[%s] region num: "SIZE_FORMAT" should be == "
   178                         "calc region num: "SIZE_FORMAT,
   179                         name(), region_num(), _calc_region_num));
   181   guarantee(total_capacity_bytes() == _calc_total_capacity_bytes,
   182             hrs_err_msg("[%s] capacity bytes: "SIZE_FORMAT" should be == "
   183                         "calc capacity bytes: "SIZE_FORMAT,
   184                         name(),
   185                         total_capacity_bytes(), _calc_total_capacity_bytes));
   187   guarantee(total_used_bytes() == _calc_total_used_bytes,
   188             hrs_err_msg("[%s] used bytes: "SIZE_FORMAT" should be == "
   189                         "calc used bytes: "SIZE_FORMAT,
   190                         name(), total_used_bytes(), _calc_total_used_bytes));
   192   _verify_in_progress = false;
   193 }
   195 void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) {
   196   out->cr();
   197   out->print_cr("Set: %s ("PTR_FORMAT")", name(), this);
   198   out->print_cr("  Region Assumptions");
   199   out->print_cr("    humongous         : %s", BOOL_TO_STR(regions_humongous()));
   200   out->print_cr("    empty             : %s", BOOL_TO_STR(regions_empty()));
   201   out->print_cr("  Attributes");
   202   out->print_cr("    length            : "SIZE_FORMAT_W(14), length());
   203   out->print_cr("    region num        : "SIZE_FORMAT_W(14), region_num());
   204   out->print_cr("    total capacity    : "SIZE_FORMAT_W(14)" bytes",
   205                 total_capacity_bytes());
   206   out->print_cr("    total used        : "SIZE_FORMAT_W(14)" bytes",
   207                 total_used_bytes());
   208 }
   210 void HeapRegionSetBase::clear() {
   211   _length           = 0;
   212   _region_num       = 0;
   213   _total_used_bytes = 0;
   214 }
   216 HeapRegionSetBase::HeapRegionSetBase(const char* name)
   217   : _name(name), _verify_in_progress(false),
   218     _calc_length(0), _calc_region_num(0),
   219     _calc_total_capacity_bytes(0), _calc_total_used_bytes(0) { }
   221 //////////////////// HeapRegionSet ////////////////////
   223 void HeapRegionSet::update_from_proxy(HeapRegionSet* proxy_set) {
   224   hrs_assert_mt_safety_ok(this);
   225   hrs_assert_mt_safety_ok(proxy_set);
   226   hrs_assert_sets_match(this, proxy_set);
   228   verify_optional();
   229   proxy_set->verify_optional();
   231   if (proxy_set->is_empty()) return;
   233   assert(proxy_set->length() <= _length,
   234          hrs_err_msg("[%s] proxy set length: "SIZE_FORMAT" "
   235                      "should be <= length: "SIZE_FORMAT,
   236                      name(), proxy_set->length(), _length));
   237   _length -= proxy_set->length();
   239   assert(proxy_set->region_num() <= _region_num,
   240          hrs_err_msg("[%s] proxy set region num: "SIZE_FORMAT" "
   241                      "should be <= region num: "SIZE_FORMAT,
   242                      name(), proxy_set->region_num(), _region_num));
   243   _region_num -= proxy_set->region_num();
   245   assert(proxy_set->total_used_bytes() <= _total_used_bytes,
   246          hrs_err_msg("[%s] proxy set used bytes: "SIZE_FORMAT" "
   247                      "should be <= used bytes: "SIZE_FORMAT,
   248                      name(), proxy_set->total_used_bytes(),
   249                      _total_used_bytes));
   250   _total_used_bytes -= proxy_set->total_used_bytes();
   252   proxy_set->clear();
   254   verify_optional();
   255   proxy_set->verify_optional();
   256 }
   258 //////////////////// HeapRegionLinkedList ////////////////////
   260 void HeapRegionLinkedList::fill_in_ext_msg_extra(hrs_ext_msg* msg) {
   261   msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, head(), tail());
   262 }
   264 void HeapRegionLinkedList::add_as_head(HeapRegionLinkedList* from_list) {
   265   hrs_assert_mt_safety_ok(this);
   266   hrs_assert_mt_safety_ok(from_list);
   268   verify_optional();
   269   from_list->verify_optional();
   271   if (from_list->is_empty()) return;
   273 #ifdef ASSERT
   274   HeapRegionLinkedListIterator iter(from_list);
   275   while (iter.more_available()) {
   276     HeapRegion* hr = iter.get_next();
   277     // In set_containing_set() we check that we either set the value
   278     // from NULL to non-NULL or vice versa to catch bugs. So, we have
   279     // to NULL it first before setting it to the value.
   280     hr->set_containing_set(NULL);
   281     hr->set_containing_set(this);
   282   }
   283 #endif // ASSERT
   285   if (_head != NULL) {
   286     assert(length() >  0 && _tail != NULL, hrs_ext_msg(this, "invariant"));
   287     from_list->_tail->set_next(_head);
   288   } else {
   289     assert(length() == 0 && _head == NULL, hrs_ext_msg(this, "invariant"));
   290     _tail = from_list->_tail;
   291   }
   292   _head = from_list->_head;
   294   _length           += from_list->length();
   295   _region_num       += from_list->region_num();
   296   _total_used_bytes += from_list->total_used_bytes();
   297   from_list->clear();
   299   verify_optional();
   300   from_list->verify_optional();
   301 }
   303 void HeapRegionLinkedList::add_as_tail(HeapRegionLinkedList* from_list) {
   304   hrs_assert_mt_safety_ok(this);
   305   hrs_assert_mt_safety_ok(from_list);
   307   verify_optional();
   308   from_list->verify_optional();
   310   if (from_list->is_empty()) return;
   312 #ifdef ASSERT
   313   HeapRegionLinkedListIterator iter(from_list);
   314   while (iter.more_available()) {
   315     HeapRegion* hr = iter.get_next();
   316     // In set_containing_set() we check that we either set the value
   317     // from NULL to non-NULL or vice versa to catch bugs. So, we have
   318     // to NULL it first before setting it to the value.
   319     hr->set_containing_set(NULL);
   320     hr->set_containing_set(this);
   321   }
   322 #endif // ASSERT
   324   if (_tail != NULL) {
   325     assert(length() >  0 && _head != NULL, hrs_ext_msg(this, "invariant"));
   326     _tail->set_next(from_list->_head);
   327   } else {
   328     assert(length() == 0 && _head == NULL, hrs_ext_msg(this, "invariant"));
   329     _head = from_list->_head;
   330   }
   331   _tail = from_list->_tail;
   333   _length           += from_list->length();
   334   _region_num       += from_list->region_num();
   335   _total_used_bytes += from_list->total_used_bytes();
   336   from_list->clear();
   338   verify_optional();
   339   from_list->verify_optional();
   340 }
   342 void HeapRegionLinkedList::remove_all() {
   343   hrs_assert_mt_safety_ok(this);
   344   verify_optional();
   346   HeapRegion* curr = _head;
   347   while (curr != NULL) {
   348     hrs_assert_region_ok(this, curr, this);
   350     HeapRegion* next = curr->next();
   351     curr->set_next(NULL);
   352     curr->set_containing_set(NULL);
   353     curr = next;
   354   }
   355   clear();
   357   verify_optional();
   358 }
   360 void HeapRegionLinkedList::remove_all_pending(size_t target_count) {
   361   hrs_assert_mt_safety_ok(this);
   362   assert(target_count > 1, hrs_ext_msg(this, "pre-condition"));
   363   assert(!is_empty(), hrs_ext_msg(this, "pre-condition"));
   365   verify_optional();
   366   DEBUG_ONLY(size_t old_length = length();)
   368   HeapRegion* curr = _head;
   369   HeapRegion* prev = NULL;
   370   size_t count = 0;
   371   while (curr != NULL) {
   372     hrs_assert_region_ok(this, curr, this);
   373     HeapRegion* next = curr->next();
   375     if (curr->pending_removal()) {
   376       assert(count < target_count,
   377              hrs_err_msg("[%s] should not come across more regions "
   378                          "pending for removal than target_count: "SIZE_FORMAT,
   379                          name(), target_count));
   381       if (prev == NULL) {
   382         assert(_head == curr, hrs_ext_msg(this, "invariant"));
   383         _head = next;
   384       } else {
   385         assert(_head != curr, hrs_ext_msg(this, "invariant"));
   386         prev->set_next(next);
   387       }
   388       if (next == NULL) {
   389         assert(_tail == curr, hrs_ext_msg(this, "invariant"));
   390         _tail = prev;
   391       } else {
   392         assert(_tail != curr, hrs_ext_msg(this, "invariant"));
   393       }
   395       curr->set_next(NULL);
   396       remove_internal(curr);
   397       curr->set_pending_removal(false);
   399       count += 1;
   401       // If we have come across the target number of regions we can
   402       // just bail out. However, for debugging purposes, we can just
   403       // carry on iterating to make sure there are not more regions
   404       // tagged with pending removal.
   405       DEBUG_ONLY(if (count == target_count) break;)
   406     } else {
   407       prev = curr;
   408     }
   409     curr = next;
   410   }
   412   assert(count == target_count,
   413          hrs_err_msg("[%s] count: "SIZE_FORMAT" should be == "
   414                      "target_count: "SIZE_FORMAT, name(), count, target_count));
   415   assert(length() + target_count == old_length,
   416          hrs_err_msg("[%s] new length should be consistent "
   417                      "new length: "SIZE_FORMAT" old length: "SIZE_FORMAT" "
   418                      "target_count: "SIZE_FORMAT,
   419                      name(), length(), old_length, target_count));
   421   verify_optional();
   422 }
   424 void HeapRegionLinkedList::verify() {
   425   // See comment in HeapRegionSetBase::verify() about MT safety and
   426   // verification.
   427   hrs_assert_mt_safety_ok(this);
   429   // This will also do the basic verification too.
   430   verify_start();
   432   HeapRegion* curr  = _head;
   433   HeapRegion* prev1 = NULL;
   434   HeapRegion* prev0 = NULL;
   435   size_t      count = 0;
   436   while (curr != NULL) {
   437     verify_next_region(curr);
   439     count += 1;
   440     guarantee(count < _unrealistically_long_length,
   441               hrs_err_msg("[%s] the calculated length: "SIZE_FORMAT" "
   442                           "seems very long, is there maybe a cycle? "
   443                           "curr: "PTR_FORMAT" prev0: "PTR_FORMAT" "
   444                           "prev1: "PTR_FORMAT" length: "SIZE_FORMAT,
   445                           name(), count, curr, prev0, prev1, length()));
   447     prev1 = prev0;
   448     prev0 = curr;
   449     curr  = curr->next();
   450   }
   452   guarantee(_tail == prev0, hrs_ext_msg(this, "post-condition"));
   454   verify_end();
   455 }
   457 void HeapRegionLinkedList::clear() {
   458   HeapRegionSetBase::clear();
   459   _head = NULL;
   460   _tail = NULL;
   461 }
   463 void HeapRegionLinkedList::print_on(outputStream* out, bool print_contents) {
   464   HeapRegionSetBase::print_on(out, print_contents);
   465   out->print_cr("  Linking");
   466   out->print_cr("    head              : "PTR_FORMAT, _head);
   467   out->print_cr("    tail              : "PTR_FORMAT, _tail);
   469   if (print_contents) {
   470     out->print_cr("  Contents");
   471     HeapRegionLinkedListIterator iter(this);
   472     while (iter.more_available()) {
   473       HeapRegion* hr = iter.get_next();
   474       hr->print_on(out);
   475     }
   476   }
   477 }

mercurial