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

Fri, 14 Mar 2014 10:15:46 +0100

author
brutisso
date
Fri, 14 Mar 2014 10:15:46 +0100
changeset 6385
58fc1b1523dc
parent 3957
a2f7274eb6ef
child 6386
0d2ce7411240
permissions
-rw-r--r--

8034079: G1: Refactor the HeapRegionSet hierarchy
Reviewed-by: tschatzl, pliden

tonyp@2472 1 /*
tonyp@3713 2 * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
tonyp@2472 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
tonyp@2472 4 *
tonyp@2472 5 * This code is free software; you can redistribute it and/or modify it
tonyp@2472 6 * under the terms of the GNU General Public License version 2 only, as
tonyp@2472 7 * published by the Free Software Foundation.
tonyp@2472 8 *
tonyp@2472 9 * This code is distributed in the hope that it will be useful, but WITHOUT
tonyp@2472 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
tonyp@2472 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
tonyp@2472 12 * version 2 for more details (a copy is included in the LICENSE file that
tonyp@2472 13 * accompanied this code).
tonyp@2472 14 *
tonyp@2472 15 * You should have received a copy of the GNU General Public License version
tonyp@2472 16 * 2 along with this work; if not, write to the Free Software Foundation,
tonyp@2472 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
tonyp@2472 18 *
tonyp@2472 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
tonyp@2472 20 * or visit www.oracle.com if you need additional information or have any
tonyp@2472 21 * questions.
tonyp@2472 22 *
tonyp@2472 23 */
tonyp@2472 24
tonyp@2472 25 #include "precompiled.hpp"
brutisso@6385 26 #include "gc_implementation/g1/heapRegionRemSet.hpp"
tonyp@2472 27 #include "gc_implementation/g1/heapRegionSet.inline.hpp"
tonyp@2472 28
brutisso@6385 29 uint FreeRegionList::_unrealistically_long_length = 0;
tonyp@2472 30
tonyp@2643 31 void HeapRegionSetBase::fill_in_ext_msg(hrs_ext_msg* msg, const char* message) {
brutisso@6385 32 msg->append("[%s] %s ln: %u cy: "SIZE_FORMAT,
brutisso@6385 33 name(), message, length(), total_capacity_bytes());
tonyp@2472 34 fill_in_ext_msg_extra(msg);
tonyp@2472 35 }
tonyp@2472 36
brutisso@6385 37 #ifndef PRODUCT
brutisso@6385 38 void HeapRegionSetBase::verify_region(HeapRegion* hr) {
brutisso@6385 39 assert(hr->containing_set() == this, err_msg("Inconsistent containing set for %u", hr->hrs_index()));
brutisso@6385 40 assert(!hr->is_young(), err_msg("Adding young region %u", hr->hrs_index())); // currently we don't use these sets for young regions
brutisso@6385 41 assert(hr->isHumongous() == regions_humongous(), err_msg("Wrong humongous state for region %u and set %s", hr->hrs_index(), name()));
brutisso@6385 42 assert(hr->is_empty() == regions_empty(), err_msg("Wrong empty state for region %u and set %s", hr->hrs_index(), name()));
brutisso@6385 43 assert(hr->rem_set()->verify_ready_for_par_iteration(), err_msg("Wrong iteration state %u", hr->hrs_index()));
tonyp@2472 44 }
brutisso@6385 45 #endif
tonyp@2472 46
tonyp@2472 47 void HeapRegionSetBase::verify() {
tonyp@2472 48 // It's important that we also observe the MT safety protocol even
tonyp@2472 49 // for the verification calls. If we do verification without the
tonyp@2472 50 // appropriate locks and the set changes underneath our feet
tonyp@2472 51 // verification might fail and send us on a wild goose chase.
brutisso@6385 52 check_mt_safety();
tonyp@2472 53
brutisso@6385 54 guarantee(( is_empty() && length() == 0 && total_capacity_bytes() == 0) ||
brutisso@6385 55 (!is_empty() && length() >= 0 && total_capacity_bytes() >= 0),
tonyp@2643 56 hrs_ext_msg(this, "invariant"));
tonyp@2472 57 }
tonyp@2472 58
tonyp@2472 59 void HeapRegionSetBase::verify_start() {
tonyp@2472 60 // See comment in verify() about MT safety and verification.
brutisso@6385 61 check_mt_safety();
tonyp@2472 62 assert(!_verify_in_progress,
tonyp@2643 63 hrs_ext_msg(this, "verification should not be in progress"));
tonyp@2472 64
tonyp@2472 65 // Do the basic verification first before we do the checks over the regions.
tonyp@2472 66 HeapRegionSetBase::verify();
tonyp@2472 67
tonyp@2472 68 _verify_in_progress = true;
tonyp@2472 69 }
tonyp@2472 70
tonyp@2472 71 void HeapRegionSetBase::verify_end() {
tonyp@2472 72 // See comment in verify() about MT safety and verification.
brutisso@6385 73 check_mt_safety();
tonyp@2472 74 assert(_verify_in_progress,
tonyp@2643 75 hrs_ext_msg(this, "verification should be in progress"));
tonyp@2472 76
tonyp@2472 77 _verify_in_progress = false;
tonyp@2472 78 }
tonyp@2472 79
tonyp@2472 80 void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) {
tonyp@2472 81 out->cr();
tonyp@2472 82 out->print_cr("Set: %s ("PTR_FORMAT")", name(), this);
tonyp@2472 83 out->print_cr(" Region Assumptions");
tonyp@2472 84 out->print_cr(" humongous : %s", BOOL_TO_STR(regions_humongous()));
tonyp@2472 85 out->print_cr(" empty : %s", BOOL_TO_STR(regions_empty()));
tonyp@2472 86 out->print_cr(" Attributes");
tonyp@3713 87 out->print_cr(" length : %14u", length());
tonyp@2472 88 out->print_cr(" total capacity : "SIZE_FORMAT_W(14)" bytes",
tonyp@2472 89 total_capacity_bytes());
tonyp@2472 90 }
tonyp@2472 91
brutisso@6385 92 HeapRegionSetBase::HeapRegionSetBase(const char* name, bool humongous, bool empty, HRSMtSafeChecker* mt_safety_checker)
brutisso@6385 93 : _name(name), _verify_in_progress(false),
brutisso@6385 94 _is_humongous(humongous), _is_empty(empty), _mt_safety_checker(mt_safety_checker),
brutisso@6385 95 _count()
brutisso@6385 96 { }
brutisso@6385 97
brutisso@6385 98 void FreeRegionList::set_unrealistically_long_length(uint len) {
brutisso@6385 99 guarantee(_unrealistically_long_length == 0, "should only be set once");
brutisso@6385 100 _unrealistically_long_length = len;
tonyp@2472 101 }
tonyp@2472 102
brutisso@6385 103 void FreeRegionList::fill_in_ext_msg_extra(hrs_ext_msg* msg) {
tonyp@2472 104 msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, head(), tail());
tonyp@2472 105 }
tonyp@2472 106
brutisso@6385 107 void FreeRegionList::add_as_head_or_tail(FreeRegionList* from_list, bool as_head) {
brutisso@6385 108 check_mt_safety();
brutisso@6385 109 from_list->check_mt_safety();
tonyp@2714 110
tonyp@2714 111 verify_optional();
tonyp@2714 112 from_list->verify_optional();
tonyp@2714 113
brutisso@6385 114 if (from_list->is_empty()) {
brutisso@6385 115 return;
brutisso@6385 116 }
tonyp@2714 117
tonyp@2714 118 #ifdef ASSERT
brutisso@6385 119 FreeRegionListIterator iter(from_list);
tonyp@2714 120 while (iter.more_available()) {
tonyp@2714 121 HeapRegion* hr = iter.get_next();
tonyp@2714 122 // In set_containing_set() we check that we either set the value
tonyp@2714 123 // from NULL to non-NULL or vice versa to catch bugs. So, we have
tonyp@2714 124 // to NULL it first before setting it to the value.
tonyp@2714 125 hr->set_containing_set(NULL);
tonyp@2714 126 hr->set_containing_set(this);
tonyp@2714 127 }
tonyp@2714 128 #endif // ASSERT
tonyp@2714 129
brutisso@6385 130 if (_head == NULL) {
brutisso@6385 131 assert(length() == 0 && _tail == NULL, hrs_ext_msg(this, "invariant"));
brutisso@6385 132 _head = from_list->_head;
brutisso@6385 133 _tail = from_list->_tail;
tonyp@2714 134 } else {
brutisso@6385 135 assert(length() > 0 && _tail != NULL, hrs_ext_msg(this, "invariant"));
brutisso@6385 136 if (as_head) {
brutisso@6385 137 from_list->_tail->set_next(_head);
brutisso@6385 138 _head = from_list->_head;
brutisso@6385 139 } else {
brutisso@6385 140 _tail->set_next(from_list->_head);
brutisso@6385 141 _tail = from_list->_tail;
brutisso@6385 142 }
tonyp@2714 143 }
tonyp@2714 144
brutisso@6385 145 _count.increment(from_list->length(), from_list->total_capacity_bytes());
tonyp@2714 146 from_list->clear();
tonyp@2714 147
tonyp@2714 148 verify_optional();
tonyp@2714 149 from_list->verify_optional();
tonyp@2714 150 }
tonyp@2714 151
brutisso@6385 152 void FreeRegionList::add_as_head(FreeRegionList* from_list) {
brutisso@6385 153 add_as_head_or_tail(from_list, true /* as_head */);
tonyp@2472 154 }
tonyp@2472 155
brutisso@6385 156 void FreeRegionList::add_as_tail(FreeRegionList* from_list) {
brutisso@6385 157 add_as_head_or_tail(from_list, false /* as_head */);
brutisso@6385 158 }
brutisso@6385 159
brutisso@6385 160 void FreeRegionList::remove_all() {
brutisso@6385 161 check_mt_safety();
tonyp@2472 162 verify_optional();
tonyp@2472 163
tonyp@2472 164 HeapRegion* curr = _head;
tonyp@2472 165 while (curr != NULL) {
brutisso@6385 166 verify_region(curr);
tonyp@2472 167
tonyp@2472 168 HeapRegion* next = curr->next();
tonyp@2472 169 curr->set_next(NULL);
tonyp@2472 170 curr->set_containing_set(NULL);
tonyp@2472 171 curr = next;
tonyp@2472 172 }
tonyp@2472 173 clear();
tonyp@2472 174
tonyp@2472 175 verify_optional();
tonyp@2472 176 }
tonyp@2472 177
brutisso@6385 178 void FreeRegionList::remove_all_pending(uint target_count) {
brutisso@6385 179 check_mt_safety();
tonyp@2643 180 assert(target_count > 1, hrs_ext_msg(this, "pre-condition"));
tonyp@2643 181 assert(!is_empty(), hrs_ext_msg(this, "pre-condition"));
tonyp@2472 182
tonyp@2472 183 verify_optional();
tonyp@3713 184 DEBUG_ONLY(uint old_length = length();)
tonyp@2472 185
tonyp@2472 186 HeapRegion* curr = _head;
tonyp@2472 187 HeapRegion* prev = NULL;
tonyp@3713 188 uint count = 0;
tonyp@2472 189 while (curr != NULL) {
brutisso@6385 190 verify_region(curr);
tonyp@2472 191 HeapRegion* next = curr->next();
tonyp@2472 192
tonyp@2472 193 if (curr->pending_removal()) {
tonyp@2472 194 assert(count < target_count,
tonyp@2643 195 hrs_err_msg("[%s] should not come across more regions "
tonyp@3713 196 "pending for removal than target_count: %u",
tonyp@2472 197 name(), target_count));
tonyp@2472 198
tonyp@2472 199 if (prev == NULL) {
tonyp@2643 200 assert(_head == curr, hrs_ext_msg(this, "invariant"));
tonyp@2472 201 _head = next;
tonyp@2472 202 } else {
tonyp@2643 203 assert(_head != curr, hrs_ext_msg(this, "invariant"));
tonyp@2472 204 prev->set_next(next);
tonyp@2472 205 }
tonyp@2472 206 if (next == NULL) {
tonyp@2643 207 assert(_tail == curr, hrs_ext_msg(this, "invariant"));
tonyp@2472 208 _tail = prev;
tonyp@2472 209 } else {
tonyp@2643 210 assert(_tail != curr, hrs_ext_msg(this, "invariant"));
tonyp@2472 211 }
tonyp@2472 212
tonyp@2472 213 curr->set_next(NULL);
brutisso@6385 214 remove(curr);
tonyp@2472 215 curr->set_pending_removal(false);
tonyp@2472 216
tonyp@2472 217 count += 1;
tonyp@2472 218
tonyp@2472 219 // If we have come across the target number of regions we can
tonyp@2472 220 // just bail out. However, for debugging purposes, we can just
tonyp@2472 221 // carry on iterating to make sure there are not more regions
tonyp@2472 222 // tagged with pending removal.
tonyp@2472 223 DEBUG_ONLY(if (count == target_count) break;)
tonyp@2472 224 } else {
tonyp@2472 225 prev = curr;
tonyp@2472 226 }
tonyp@2472 227 curr = next;
tonyp@2472 228 }
tonyp@2472 229
tonyp@2472 230 assert(count == target_count,
tonyp@3713 231 hrs_err_msg("[%s] count: %u should be == target_count: %u",
tonyp@3713 232 name(), count, target_count));
tonyp@2472 233 assert(length() + target_count == old_length,
tonyp@2643 234 hrs_err_msg("[%s] new length should be consistent "
tonyp@3713 235 "new length: %u old length: %u target_count: %u",
tonyp@2472 236 name(), length(), old_length, target_count));
tonyp@2472 237
tonyp@2472 238 verify_optional();
tonyp@2472 239 }
tonyp@2472 240
brutisso@6385 241 void FreeRegionList::verify() {
tonyp@2472 242 // See comment in HeapRegionSetBase::verify() about MT safety and
tonyp@2472 243 // verification.
brutisso@6385 244 check_mt_safety();
tonyp@2472 245
tonyp@2472 246 // This will also do the basic verification too.
tonyp@2472 247 verify_start();
tonyp@2472 248
brutisso@6385 249 verify_list();
tonyp@2472 250
tonyp@2472 251 verify_end();
tonyp@2472 252 }
tonyp@2472 253
brutisso@6385 254 void FreeRegionList::clear() {
brutisso@6385 255 _count = HeapRegionSetCount();
tonyp@2472 256 _head = NULL;
tonyp@2472 257 _tail = NULL;
tonyp@2472 258 }
tonyp@2472 259
brutisso@6385 260 void FreeRegionList::print_on(outputStream* out, bool print_contents) {
tonyp@2472 261 HeapRegionSetBase::print_on(out, print_contents);
tonyp@2472 262 out->print_cr(" Linking");
tonyp@2472 263 out->print_cr(" head : "PTR_FORMAT, _head);
tonyp@2472 264 out->print_cr(" tail : "PTR_FORMAT, _tail);
tonyp@2472 265
tonyp@2472 266 if (print_contents) {
tonyp@2472 267 out->print_cr(" Contents");
brutisso@6385 268 FreeRegionListIterator iter(this);
tonyp@2472 269 while (iter.more_available()) {
tonyp@2472 270 HeapRegion* hr = iter.get_next();
tonyp@2472 271 hr->print_on(out);
tonyp@2472 272 }
tonyp@2472 273 }
tonyp@2472 274 }

mercurial