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

Sat, 16 Oct 2010 17:12:19 -0400

author
tonyp
date
Sat, 16 Oct 2010 17:12:19 -0400
changeset 2241
72a161e62cc4
parent 2043
2dfd013a7465
child 2314
f95d63e2154a
permissions
-rw-r--r--

6991377: G1: race between concurrent refinement and humongous object allocation
Summary: There is a race between the concurrent refinement threads and the humongous object allocation that can cause the concurrent refinement threads to corrupt the part of the BOT that it is being initialized by the humongous object allocation operation. The solution is to do the humongous object allocation in careful steps to ensure that the concurrent refinement threads always have a consistent view over the BOT, region contents, and top. The fix includes some very minor tidying up in sparsePRT.
Reviewed-by: jcoomes, johnc, ysr

ysr@777 1 /*
trims@1907 2 * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
ysr@777 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ysr@777 4 *
ysr@777 5 * This code is free software; you can redistribute it and/or modify it
ysr@777 6 * under the terms of the GNU General Public License version 2 only, as
ysr@777 7 * published by the Free Software Foundation.
ysr@777 8 *
ysr@777 9 * This code is distributed in the hope that it will be useful, but WITHOUT
ysr@777 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ysr@777 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ysr@777 12 * version 2 for more details (a copy is included in the LICENSE file that
ysr@777 13 * accompanied this code).
ysr@777 14 *
ysr@777 15 * You should have received a copy of the GNU General Public License version
ysr@777 16 * 2 along with this work; if not, write to the Free Software Foundation,
ysr@777 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ysr@777 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
ysr@777 22 *
ysr@777 23 */
ysr@777 24
ysr@777 25 #include "incls/_precompiled.incl"
ysr@777 26 #include "incls/_heapRegionSeq.cpp.incl"
ysr@777 27
ysr@777 28 // Local to this file.
ysr@777 29
ysr@777 30 static int orderRegions(HeapRegion** hr1p, HeapRegion** hr2p) {
ysr@777 31 if ((*hr1p)->end() <= (*hr2p)->bottom()) return -1;
ysr@777 32 else if ((*hr2p)->end() <= (*hr1p)->bottom()) return 1;
ysr@777 33 else if (*hr1p == *hr2p) return 0;
ysr@777 34 else {
ysr@777 35 assert(false, "We should never compare distinct overlapping regions.");
ysr@777 36 }
ysr@777 37 return 0;
ysr@777 38 }
ysr@777 39
iveresov@828 40 HeapRegionSeq::HeapRegionSeq(const size_t max_size) :
ysr@777 41 _alloc_search_start(0),
ysr@777 42 // The line below is the worst bit of C++ hackery I've ever written
ysr@777 43 // (Detlefs, 11/23). You should think of it as equivalent to
ysr@777 44 // "_regions(100, true)": initialize the growable array and inform it
kvn@2043 45 // that it should allocate its elem array(s) on the C heap.
kvn@2043 46 //
kvn@2043 47 // The first argument, however, is actually a comma expression
kvn@2043 48 // (set_allocation_type(this, C_HEAP), 100). The purpose of the
kvn@2043 49 // set_allocation_type() call is to replace the default allocation
kvn@2043 50 // type for embedded objects STACK_OR_EMBEDDED with C_HEAP. It will
kvn@2043 51 // allow to pass the assert in GenericGrowableArray() which checks
kvn@2043 52 // that a growable array object must be on C heap if elements are.
kvn@2043 53 //
kvn@2043 54 // Note: containing object is allocated on C heap since it is CHeapObj.
kvn@2043 55 //
kvn@2043 56 _regions((ResourceObj::set_allocation_type((address)&_regions,
kvn@2043 57 ResourceObj::C_HEAP),
iveresov@828 58 (int)max_size),
ysr@777 59 true),
ysr@777 60 _next_rr_candidate(0),
ysr@777 61 _seq_bottom(NULL)
ysr@777 62 {}
ysr@777 63
ysr@777 64 // Private methods.
ysr@777 65
ysr@777 66 HeapWord*
ysr@777 67 HeapRegionSeq::alloc_obj_from_region_index(int ind, size_t word_size) {
ysr@777 68 assert(G1CollectedHeap::isHumongous(word_size),
ysr@777 69 "Allocation size should be humongous");
ysr@777 70 int cur = ind;
ysr@777 71 int first = cur;
ysr@777 72 size_t sumSizes = 0;
ysr@777 73 while (cur < _regions.length() && sumSizes < word_size) {
ysr@777 74 // Loop invariant:
ysr@777 75 // For all i in [first, cur):
ysr@777 76 // _regions.at(i)->is_empty()
ysr@777 77 // && _regions.at(i) is contiguous with its predecessor, if any
ysr@777 78 // && sumSizes is the sum of the sizes of the regions in the interval
ysr@777 79 // [first, cur)
ysr@777 80 HeapRegion* curhr = _regions.at(cur);
ysr@777 81 if (curhr->is_empty()
ysr@777 82 && (first == cur
ysr@777 83 || (_regions.at(cur-1)->end() ==
ysr@777 84 curhr->bottom()))) {
ysr@777 85 sumSizes += curhr->capacity() / HeapWordSize;
ysr@777 86 } else {
ysr@777 87 first = cur + 1;
ysr@777 88 sumSizes = 0;
ysr@777 89 }
ysr@777 90 cur++;
ysr@777 91 }
ysr@777 92 if (sumSizes >= word_size) {
ysr@777 93 _alloc_search_start = cur;
tonyp@2241 94
tonyp@2241 95 // We need to initialize the region(s) we just discovered. This is
tonyp@2241 96 // a bit tricky given that it can happen concurrently with
tonyp@2241 97 // refinement threads refining cards on these regions and
tonyp@2241 98 // potentially wanting to refine the BOT as they are scanning
tonyp@2241 99 // those cards (this can happen shortly after a cleanup; see CR
tonyp@2241 100 // 6991377). So we have to set up the region(s) carefully and in
tonyp@2241 101 // a specific order.
tonyp@2241 102
tonyp@2241 103 // Currently, allocs_are_zero_filled() returns false. The zero
tonyp@2241 104 // filling infrastructure will be going away soon (see CR 6977804).
tonyp@2241 105 // So no need to do anything else here.
ysr@777 106 bool zf = G1CollectedHeap::heap()->allocs_are_zero_filled();
tonyp@2241 107 assert(!zf, "not supported");
tonyp@2241 108
tonyp@2241 109 // This will be the "starts humongous" region.
ysr@777 110 HeapRegion* first_hr = _regions.at(first);
tonyp@2241 111 {
tonyp@2241 112 MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
tonyp@2241 113 first_hr->set_zero_fill_allocated();
tonyp@2241 114 }
tonyp@2241 115 // The header of the new object will be placed at the bottom of
tonyp@2241 116 // the first region.
tonyp@2241 117 HeapWord* new_obj = first_hr->bottom();
tonyp@2241 118 // This will be the new end of the first region in the series that
tonyp@2241 119 // should also match the end of the last region in the seriers.
tonyp@2241 120 // (Note: sumSizes = "region size" x "number of regions we found").
tonyp@2241 121 HeapWord* new_end = new_obj + sumSizes;
tonyp@2241 122 // This will be the new top of the first region that will reflect
tonyp@2241 123 // this allocation.
tonyp@2241 124 HeapWord* new_top = new_obj + word_size;
tonyp@2241 125
tonyp@2241 126 // First, we need to zero the header of the space that we will be
tonyp@2241 127 // allocating. When we update top further down, some refinement
tonyp@2241 128 // threads might try to scan the region. By zeroing the header we
tonyp@2241 129 // ensure that any thread that will try to scan the region will
tonyp@2241 130 // come across the zero klass word and bail out.
tonyp@2241 131 //
tonyp@2241 132 // NOTE: It would not have been correct to have used
tonyp@2241 133 // CollectedHeap::fill_with_object() and make the space look like
tonyp@2241 134 // an int array. The thread that is doing the allocation will
tonyp@2241 135 // later update the object header to a potentially different array
tonyp@2241 136 // type and, for a very short period of time, the klass and length
tonyp@2241 137 // fields will be inconsistent. This could cause a refinement
tonyp@2241 138 // thread to calculate the object size incorrectly.
tonyp@2241 139 Copy::fill_to_words(new_obj, oopDesc::header_size(), 0);
tonyp@2241 140
tonyp@2241 141 // We will set up the first region as "starts humongous". This
tonyp@2241 142 // will also update the BOT covering all the regions to reflect
tonyp@2241 143 // that there is a single object that starts at the bottom of the
tonyp@2241 144 // first region.
tonyp@2241 145 first_hr->set_startsHumongous(new_end);
tonyp@2241 146
tonyp@2241 147 // Then, if there are any, we will set up the "continues
tonyp@2241 148 // humongous" regions.
tonyp@2241 149 HeapRegion* hr = NULL;
tonyp@2241 150 for (int i = first + 1; i < cur; ++i) {
tonyp@2241 151 hr = _regions.at(i);
ysr@777 152 {
ysr@777 153 MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
ysr@777 154 hr->set_zero_fill_allocated();
ysr@777 155 }
tonyp@2241 156 hr->set_continuesHumongous(first_hr);
tonyp@2241 157 }
tonyp@2241 158 // If we have "continues humongous" regions (hr != NULL), then the
tonyp@2241 159 // end of the last one should match new_end.
tonyp@2241 160 assert(hr == NULL || hr->end() == new_end, "sanity");
tonyp@2241 161
tonyp@2241 162 // Up to this point no concurrent thread would have been able to
tonyp@2241 163 // do any scanning on any region in this series. All the top
tonyp@2241 164 // fields still point to bottom, so the intersection between
tonyp@2241 165 // [bottom,top] and [card_start,card_end] will be empty. Before we
tonyp@2241 166 // update the top fields, we'll do a storestore to make sure that
tonyp@2241 167 // no thread sees the update to top before the zeroing of the
tonyp@2241 168 // object header and the BOT initialization.
tonyp@2241 169 OrderAccess::storestore();
tonyp@2241 170
tonyp@2241 171 // Now that the BOT and the object header have been initialized,
tonyp@2241 172 // we can update top of the "starts humongous" region.
tonyp@2241 173 assert(first_hr->bottom() < new_top && new_top <= first_hr->end(),
tonyp@2241 174 "new_top should be in this region");
tonyp@2241 175 first_hr->set_top(new_top);
tonyp@2241 176
tonyp@2241 177 // Now, we will update the top fields of the "continues humongous"
tonyp@2241 178 // regions. The reason we need to do this is that, otherwise,
tonyp@2241 179 // these regions would look empty and this will confuse parts of
tonyp@2241 180 // G1. For example, the code that looks for a consecutive number
tonyp@2241 181 // of empty regions will consider them empty and try to
tonyp@2241 182 // re-allocate them. We can extend is_empty() to also include
tonyp@2241 183 // !continuesHumongous(), but it is easier to just update the top
tonyp@2241 184 // fields here.
tonyp@2241 185 hr = NULL;
tonyp@2241 186 for (int i = first + 1; i < cur; ++i) {
tonyp@2241 187 hr = _regions.at(i);
tonyp@2241 188 if ((i + 1) == cur) {
tonyp@2241 189 // last continues humongous region
tonyp@2241 190 assert(hr->bottom() < new_top && new_top <= hr->end(),
tonyp@2241 191 "new_top should fall on this region");
tonyp@2241 192 hr->set_top(new_top);
ysr@777 193 } else {
tonyp@2241 194 // not last one
tonyp@2241 195 assert(new_top > hr->end(), "new_top should be above this region");
tonyp@2241 196 hr->set_top(hr->end());
ysr@777 197 }
ysr@777 198 }
tonyp@2241 199 // If we have continues humongous regions (hr != NULL), then the
tonyp@2241 200 // end of the last one should match new_end and its top should
tonyp@2241 201 // match new_top.
tonyp@2241 202 assert(hr == NULL ||
tonyp@2241 203 (hr->end() == new_end && hr->top() == new_top), "sanity");
tonyp@2241 204
tonyp@2241 205 return new_obj;
ysr@777 206 } else {
ysr@777 207 // If we started from the beginning, we want to know why we can't alloc.
ysr@777 208 return NULL;
ysr@777 209 }
ysr@777 210 }
ysr@777 211
apetrusenko@1112 212 void HeapRegionSeq::print_empty_runs() {
ysr@777 213 int empty_run = 0;
ysr@777 214 int n_empty = 0;
ysr@777 215 int empty_run_start;
ysr@777 216 for (int i = 0; i < _regions.length(); i++) {
ysr@777 217 HeapRegion* r = _regions.at(i);
ysr@777 218 if (r->continuesHumongous()) continue;
apetrusenko@1112 219 if (r->is_empty()) {
ysr@777 220 assert(!r->isHumongous(), "H regions should not be empty.");
ysr@777 221 if (empty_run == 0) empty_run_start = i;
ysr@777 222 empty_run++;
ysr@777 223 n_empty++;
ysr@777 224 } else {
ysr@777 225 if (empty_run > 0) {
ysr@777 226 gclog_or_tty->print(" %d:%d", empty_run_start, empty_run);
ysr@777 227 empty_run = 0;
ysr@777 228 }
ysr@777 229 }
ysr@777 230 }
ysr@777 231 if (empty_run > 0) {
ysr@777 232 gclog_or_tty->print(" %d:%d", empty_run_start, empty_run);
ysr@777 233 }
ysr@777 234 gclog_or_tty->print_cr(" [tot = %d]", n_empty);
ysr@777 235 }
ysr@777 236
ysr@777 237 int HeapRegionSeq::find(HeapRegion* hr) {
ysr@777 238 // FIXME: optimized for adjacent regions of fixed size.
ysr@777 239 int ind = hr->hrs_index();
ysr@777 240 if (ind != -1) {
ysr@777 241 assert(_regions.at(ind) == hr, "Mismatch");
ysr@777 242 }
ysr@777 243 return ind;
ysr@777 244 }
ysr@777 245
ysr@777 246
ysr@777 247 // Public methods.
ysr@777 248
ysr@777 249 void HeapRegionSeq::insert(HeapRegion* hr) {
iveresov@828 250 assert(!_regions.is_full(), "Too many elements in HeapRegionSeq");
ysr@777 251 if (_regions.length() == 0
ysr@777 252 || _regions.top()->end() <= hr->bottom()) {
ysr@777 253 hr->set_hrs_index(_regions.length());
ysr@777 254 _regions.append(hr);
ysr@777 255 } else {
ysr@777 256 _regions.append(hr);
ysr@777 257 _regions.sort(orderRegions);
ysr@777 258 for (int i = 0; i < _regions.length(); i++) {
ysr@777 259 _regions.at(i)->set_hrs_index(i);
ysr@777 260 }
ysr@777 261 }
ysr@777 262 char* bot = (char*)_regions.at(0)->bottom();
ysr@777 263 if (_seq_bottom == NULL || bot < _seq_bottom) _seq_bottom = bot;
ysr@777 264 }
ysr@777 265
ysr@777 266 size_t HeapRegionSeq::length() {
ysr@777 267 return _regions.length();
ysr@777 268 }
ysr@777 269
ysr@777 270 size_t HeapRegionSeq::free_suffix() {
ysr@777 271 size_t res = 0;
ysr@777 272 int first = _regions.length() - 1;
ysr@777 273 int cur = first;
ysr@777 274 while (cur >= 0 &&
ysr@777 275 (_regions.at(cur)->is_empty()
ysr@777 276 && (first == cur
ysr@777 277 || (_regions.at(cur+1)->bottom() ==
ysr@777 278 _regions.at(cur)->end())))) {
ysr@777 279 res++;
ysr@777 280 cur--;
ysr@777 281 }
ysr@777 282 return res;
ysr@777 283 }
ysr@777 284
ysr@777 285 HeapWord* HeapRegionSeq::obj_allocate(size_t word_size) {
ysr@777 286 int cur = _alloc_search_start;
ysr@777 287 // Make sure "cur" is a valid index.
ysr@777 288 assert(cur >= 0, "Invariant.");
ysr@777 289 HeapWord* res = alloc_obj_from_region_index(cur, word_size);
ysr@777 290 if (res == NULL)
ysr@777 291 res = alloc_obj_from_region_index(0, word_size);
ysr@777 292 return res;
ysr@777 293 }
ysr@777 294
ysr@777 295 void HeapRegionSeq::iterate(HeapRegionClosure* blk) {
ysr@777 296 iterate_from((HeapRegion*)NULL, blk);
ysr@777 297 }
ysr@777 298
ysr@777 299 // The first argument r is the heap region at which iteration begins.
ysr@777 300 // This operation runs fastest when r is NULL, or the heap region for
ysr@777 301 // which a HeapRegionClosure most recently returned true, or the
ysr@777 302 // heap region immediately to its right in the sequence. In all
ysr@777 303 // other cases a linear search is required to find the index of r.
ysr@777 304
ysr@777 305 void HeapRegionSeq::iterate_from(HeapRegion* r, HeapRegionClosure* blk) {
ysr@777 306
ysr@777 307 // :::: FIXME ::::
ysr@777 308 // Static cache value is bad, especially when we start doing parallel
ysr@777 309 // remembered set update. For now just don't cache anything (the
ysr@777 310 // code in the def'd out blocks).
ysr@777 311
ysr@777 312 #if 0
ysr@777 313 static int cached_j = 0;
ysr@777 314 #endif
ysr@777 315 int len = _regions.length();
ysr@777 316 int j = 0;
ysr@777 317 // Find the index of r.
ysr@777 318 if (r != NULL) {
ysr@777 319 #if 0
ysr@777 320 assert(cached_j >= 0, "Invariant.");
ysr@777 321 if ((cached_j < len) && (r == _regions.at(cached_j))) {
ysr@777 322 j = cached_j;
ysr@777 323 } else if ((cached_j + 1 < len) && (r == _regions.at(cached_j + 1))) {
ysr@777 324 j = cached_j + 1;
ysr@777 325 } else {
ysr@777 326 j = find(r);
ysr@777 327 #endif
ysr@777 328 if (j < 0) {
ysr@777 329 j = 0;
ysr@777 330 }
ysr@777 331 #if 0
ysr@777 332 }
ysr@777 333 #endif
ysr@777 334 }
ysr@777 335 int i;
ysr@777 336 for (i = j; i < len; i += 1) {
ysr@777 337 int res = blk->doHeapRegion(_regions.at(i));
ysr@777 338 if (res) {
ysr@777 339 #if 0
ysr@777 340 cached_j = i;
ysr@777 341 #endif
ysr@777 342 blk->incomplete();
ysr@777 343 return;
ysr@777 344 }
ysr@777 345 }
ysr@777 346 for (i = 0; i < j; i += 1) {
ysr@777 347 int res = blk->doHeapRegion(_regions.at(i));
ysr@777 348 if (res) {
ysr@777 349 #if 0
ysr@777 350 cached_j = i;
ysr@777 351 #endif
ysr@777 352 blk->incomplete();
ysr@777 353 return;
ysr@777 354 }
ysr@777 355 }
ysr@777 356 }
ysr@777 357
ysr@777 358 void HeapRegionSeq::iterate_from(int idx, HeapRegionClosure* blk) {
ysr@777 359 int len = _regions.length();
ysr@777 360 int i;
ysr@777 361 for (i = idx; i < len; i++) {
ysr@777 362 if (blk->doHeapRegion(_regions.at(i))) {
ysr@777 363 blk->incomplete();
ysr@777 364 return;
ysr@777 365 }
ysr@777 366 }
ysr@777 367 for (i = 0; i < idx; i++) {
ysr@777 368 if (blk->doHeapRegion(_regions.at(i))) {
ysr@777 369 blk->incomplete();
ysr@777 370 return;
ysr@777 371 }
ysr@777 372 }
ysr@777 373 }
ysr@777 374
ysr@777 375 MemRegion HeapRegionSeq::shrink_by(size_t shrink_bytes,
ysr@777 376 size_t& num_regions_deleted) {
ysr@777 377 assert(shrink_bytes % os::vm_page_size() == 0, "unaligned");
ysr@777 378 assert(shrink_bytes % HeapRegion::GrainBytes == 0, "unaligned");
ysr@777 379
ysr@777 380 if (_regions.length() == 0) {
ysr@777 381 num_regions_deleted = 0;
ysr@777 382 return MemRegion();
ysr@777 383 }
ysr@777 384 int j = _regions.length() - 1;
ysr@777 385 HeapWord* end = _regions.at(j)->end();
ysr@777 386 HeapWord* last_start = end;
ysr@777 387 while (j >= 0 && shrink_bytes > 0) {
ysr@777 388 HeapRegion* cur = _regions.at(j);
ysr@777 389 // We have to leave humongous regions where they are,
ysr@777 390 // and work around them.
ysr@777 391 if (cur->isHumongous()) {
ysr@777 392 return MemRegion(last_start, end);
ysr@777 393 }
ysr@777 394 assert(cur == _regions.top(), "Should be top");
ysr@777 395 if (!cur->is_empty()) break;
ysr@1395 396 cur->reset_zero_fill();
ysr@777 397 shrink_bytes -= cur->capacity();
ysr@777 398 num_regions_deleted++;
ysr@777 399 _regions.pop();
ysr@777 400 last_start = cur->bottom();
ysr@777 401 // We need to delete these somehow, but can't currently do so here: if
ysr@777 402 // we do, the ZF thread may still access the deleted region. We'll
ysr@777 403 // leave this here as a reminder that we have to do something about
ysr@777 404 // this.
ysr@777 405 // delete cur;
ysr@777 406 j--;
ysr@777 407 }
ysr@777 408 return MemRegion(last_start, end);
ysr@777 409 }
ysr@777 410
ysr@777 411
ysr@777 412 class PrintHeapRegionClosure : public HeapRegionClosure {
ysr@777 413 public:
ysr@777 414 bool doHeapRegion(HeapRegion* r) {
ysr@777 415 gclog_or_tty->print(PTR_FORMAT ":", r);
ysr@777 416 r->print();
ysr@777 417 return false;
ysr@777 418 }
ysr@777 419 };
ysr@777 420
ysr@777 421 void HeapRegionSeq::print() {
ysr@777 422 PrintHeapRegionClosure cl;
ysr@777 423 iterate(&cl);
ysr@777 424 }

mercurial