Mercurial > hg > graal-jvmci-8
comparison src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp @ 1259:9eee977dd1a9
6802453: G1: hr()->is_in_reserved(from),"Precondition."
Summary: The operations of re-using a RSet component and expanding the same RSet component were not mutually exlusive, and this could lead to RSets getting corrupted and entries being dropped.
Reviewed-by: iveresov, johnc
author | tonyp |
---|---|
date | Mon, 08 Feb 2010 14:23:01 -0500 |
parents | 2c79770d1f6e |
children | 0414c1049f15 |
comparison
equal
deleted
inserted
replaced
1258:38836cf1d8d2 | 1259:9eee977dd1a9 |
---|---|
256 | 256 |
257 enum SomePrivateConstants { | 257 enum SomePrivateConstants { |
258 ReserveParTableExpansion = 1 | 258 ReserveParTableExpansion = 1 |
259 }; | 259 }; |
260 | 260 |
261 void par_expand() { | |
262 int n = HeapRegionRemSet::num_par_rem_sets()-1; | |
263 if (n <= 0) return; | |
264 if (_par_tables == NULL) { | |
265 PerRegionTable* res = | |
266 (PerRegionTable*) | |
267 Atomic::cmpxchg_ptr((PerRegionTable*)ReserveParTableExpansion, | |
268 &_par_tables, NULL); | |
269 if (res != NULL) return; | |
270 // Otherwise, we reserved the right to do the expansion. | |
271 | |
272 PerRegionTable** ptables = NEW_C_HEAP_ARRAY(PerRegionTable*, n); | |
273 for (int i = 0; i < n; i++) { | |
274 PerRegionTable* ptable = PerRegionTable::alloc(hr()); | |
275 ptables[i] = ptable; | |
276 } | |
277 // Here we do not need an atomic. | |
278 _par_tables = ptables; | |
279 #if COUNT_PAR_EXPANDS | |
280 print_par_expand(); | |
281 #endif | |
282 // We must put this table on the expanded list. | |
283 PosParPRT* exp_head = _par_expanded_list; | |
284 while (true) { | |
285 set_next_par_expanded(exp_head); | |
286 PosParPRT* res = | |
287 (PosParPRT*) | |
288 Atomic::cmpxchg_ptr(this, &_par_expanded_list, exp_head); | |
289 if (res == exp_head) return; | |
290 // Otherwise. | |
291 exp_head = res; | |
292 } | |
293 ShouldNotReachHere(); | |
294 } | |
295 } | |
296 | |
297 void par_contract() { | 261 void par_contract() { |
298 assert(_par_tables != NULL, "Precondition."); | 262 assert(_par_tables != NULL, "Precondition."); |
299 int n = HeapRegionRemSet::num_par_rem_sets()-1; | 263 int n = HeapRegionRemSet::num_par_rem_sets()-1; |
300 for (int i = 0; i < n; i++) { | 264 for (int i = 0; i < n; i++) { |
301 _par_tables[i]->union_bitmap_into(bm()); | 265 _par_tables[i]->union_bitmap_into(bm()); |
389 | 353 |
390 PosParPRT* next() const { return _next; } | 354 PosParPRT* next() const { return _next; } |
391 void set_next(PosParPRT* nxt) { _next = nxt; } | 355 void set_next(PosParPRT* nxt) { _next = nxt; } |
392 PosParPRT** next_addr() { return &_next; } | 356 PosParPRT** next_addr() { return &_next; } |
393 | 357 |
358 bool should_expand(int tid) { | |
359 return par_tables() == NULL && tid > 0 && hr()->is_gc_alloc_region(); | |
360 } | |
361 | |
362 void par_expand() { | |
363 int n = HeapRegionRemSet::num_par_rem_sets()-1; | |
364 if (n <= 0) return; | |
365 if (_par_tables == NULL) { | |
366 PerRegionTable* res = | |
367 (PerRegionTable*) | |
368 Atomic::cmpxchg_ptr((PerRegionTable*)ReserveParTableExpansion, | |
369 &_par_tables, NULL); | |
370 if (res != NULL) return; | |
371 // Otherwise, we reserved the right to do the expansion. | |
372 | |
373 PerRegionTable** ptables = NEW_C_HEAP_ARRAY(PerRegionTable*, n); | |
374 for (int i = 0; i < n; i++) { | |
375 PerRegionTable* ptable = PerRegionTable::alloc(hr()); | |
376 ptables[i] = ptable; | |
377 } | |
378 // Here we do not need an atomic. | |
379 _par_tables = ptables; | |
380 #if COUNT_PAR_EXPANDS | |
381 print_par_expand(); | |
382 #endif | |
383 // We must put this table on the expanded list. | |
384 PosParPRT* exp_head = _par_expanded_list; | |
385 while (true) { | |
386 set_next_par_expanded(exp_head); | |
387 PosParPRT* res = | |
388 (PosParPRT*) | |
389 Atomic::cmpxchg_ptr(this, &_par_expanded_list, exp_head); | |
390 if (res == exp_head) return; | |
391 // Otherwise. | |
392 exp_head = res; | |
393 } | |
394 ShouldNotReachHere(); | |
395 } | |
396 } | |
397 | |
394 void add_reference(OopOrNarrowOopStar from, int tid) { | 398 void add_reference(OopOrNarrowOopStar from, int tid) { |
395 // Expand if necessary. | 399 // Expand if necessary. |
396 PerRegionTable** pt = par_tables(); | 400 PerRegionTable** pt = par_tables(); |
397 if (par_tables() == NULL && tid > 0 && hr()->is_gc_alloc_region()) { | |
398 par_expand(); | |
399 pt = par_tables(); | |
400 } | |
401 if (pt != NULL) { | 401 if (pt != NULL) { |
402 // We always have to assume that mods to table 0 are in parallel, | 402 // We always have to assume that mods to table 0 are in parallel, |
403 // because of the claiming scheme in parallel expansion. A thread | 403 // because of the claiming scheme in parallel expansion. A thread |
404 // with tid != 0 that finds the table to be NULL, but doesn't succeed | 404 // with tid != 0 that finds the table to be NULL, but doesn't succeed |
405 // in claiming the right of expanding it, will end up in the else | 405 // in claiming the right of expanding it, will end up in the else |
694 // Note that we can't assert "prt->hr() == from_hr", because of the | 694 // Note that we can't assert "prt->hr() == from_hr", because of the |
695 // possibility of concurrent reuse. But see head comment of | 695 // possibility of concurrent reuse. But see head comment of |
696 // OtherRegionsTable for why this is OK. | 696 // OtherRegionsTable for why this is OK. |
697 assert(prt != NULL, "Inv"); | 697 assert(prt != NULL, "Inv"); |
698 | 698 |
699 prt->add_reference(from, tid); | 699 if (prt->should_expand(tid)) { |
700 MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag); | |
701 HeapRegion* prt_hr = prt->hr(); | |
702 if (prt_hr == from_hr) { | |
703 // Make sure the table still corresponds to the same region | |
704 prt->par_expand(); | |
705 prt->add_reference(from, tid); | |
706 } | |
707 // else: The table has been concurrently coarsened, evicted, and | |
708 // the table data structure re-used for another table. So, we | |
709 // don't need to add the reference any more given that the table | |
710 // has been coarsened and the whole region will be scanned anyway. | |
711 } else { | |
712 prt->add_reference(from, tid); | |
713 } | |
700 if (G1RecordHRRSOops) { | 714 if (G1RecordHRRSOops) { |
701 HeapRegionRemSet::record(hr(), from); | 715 HeapRegionRemSet::record(hr(), from); |
702 #if HRRS_VERBOSE | 716 #if HRRS_VERBOSE |
703 gclog_or_tty->print("Added card " PTR_FORMAT " to region " | 717 gclog_or_tty->print("Added card " PTR_FORMAT " to region " |
704 "[" PTR_FORMAT "...) for ref " PTR_FORMAT ".\n", | 718 "[" PTR_FORMAT "...) for ref " PTR_FORMAT ".\n", |