Mercurial > hg > truffle
comparison src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp @ 1261:0414c1049f15
6923991: G1: improve scalability of RSet scanning
Summary: Implemented block-based work stealing. Moved copying during the rset scanning phase to the main copying phase. Made the size of rset table depend on the region size.
Reviewed-by: apetrusenko, tonyp
author | iveresov |
---|---|
date | Thu, 11 Feb 2010 15:52:19 -0800 |
parents | 9eee977dd1a9 |
children | f9ec1e4bbb44 |
comparison
equal
deleted
inserted
replaced
1260:8859772195c6 | 1261:0414c1049f15 |
---|---|
503 _sparse_table(hr) | 503 _sparse_table(hr) |
504 { | 504 { |
505 typedef PosParPRT* PosParPRTPtr; | 505 typedef PosParPRT* PosParPRTPtr; |
506 if (_max_fine_entries == 0) { | 506 if (_max_fine_entries == 0) { |
507 assert(_mod_max_fine_entries_mask == 0, "Both or none."); | 507 assert(_mod_max_fine_entries_mask == 0, "Both or none."); |
508 _max_fine_entries = (size_t)(1 << G1LogRSRegionEntries); | 508 size_t max_entries_log = (size_t)log2_long((jlong)G1RSetRegionEntries); |
509 _max_fine_entries = (size_t)(1 << max_entries_log); | |
509 _mod_max_fine_entries_mask = _max_fine_entries - 1; | 510 _mod_max_fine_entries_mask = _max_fine_entries - 1; |
510 #if SAMPLE_FOR_EVICTION | 511 #if SAMPLE_FOR_EVICTION |
511 assert(_fine_eviction_sample_size == 0 | 512 assert(_fine_eviction_sample_size == 0 |
512 && _fine_eviction_stride == 0, "All init at same time."); | 513 && _fine_eviction_stride == 0, "All init at same time."); |
513 _fine_eviction_sample_size = MAX2((size_t)4, (size_t)G1LogRSRegionEntries); | 514 _fine_eviction_sample_size = MAX2((size_t)4, max_entries_log); |
514 _fine_eviction_stride = _max_fine_entries / _fine_eviction_sample_size; | 515 _fine_eviction_stride = _max_fine_entries / _fine_eviction_sample_size; |
515 #endif | 516 #endif |
516 } | 517 } |
517 _fine_grain_regions = new PosParPRTPtr[_max_fine_entries]; | 518 _fine_grain_regions = new PosParPRTPtr[_max_fine_entries]; |
518 if (_fine_grain_regions == NULL) | 519 if (_fine_grain_regions == NULL) |
653 "overflow(f: %d, t: %d)", | 654 "overflow(f: %d, t: %d)", |
654 tid, from_hrs_ind, cur_hrs_ind); | 655 tid, from_hrs_ind, cur_hrs_ind); |
655 #endif | 656 #endif |
656 } | 657 } |
657 | 658 |
658 // Otherwise, transfer from sparse to fine-grain. | |
659 CardIdx_t cards[SparsePRTEntry::CardsPerEntry]; | |
660 if (G1HRRSUseSparseTable) { | |
661 bool res = _sparse_table.get_cards(from_hrs_ind, &cards[0]); | |
662 assert(res, "There should have been an entry"); | |
663 } | |
664 | |
665 if (_n_fine_entries == _max_fine_entries) { | 659 if (_n_fine_entries == _max_fine_entries) { |
666 prt = delete_region_table(); | 660 prt = delete_region_table(); |
667 } else { | 661 } else { |
668 prt = PosParPRT::alloc(from_hr); | 662 prt = PosParPRT::alloc(from_hr); |
669 } | 663 } |
674 PosParPRT* first_prt = _fine_grain_regions[ind]; | 668 PosParPRT* first_prt = _fine_grain_regions[ind]; |
675 prt->set_next(first_prt); // XXX Maybe move to init? | 669 prt->set_next(first_prt); // XXX Maybe move to init? |
676 _fine_grain_regions[ind] = prt; | 670 _fine_grain_regions[ind] = prt; |
677 _n_fine_entries++; | 671 _n_fine_entries++; |
678 | 672 |
679 // Add in the cards from the sparse table. | |
680 if (G1HRRSUseSparseTable) { | 673 if (G1HRRSUseSparseTable) { |
681 for (int i = 0; i < SparsePRTEntry::CardsPerEntry; i++) { | 674 // Transfer from sparse to fine-grain. |
682 CardIdx_t c = cards[i]; | 675 SparsePRTEntry *sprt_entry = _sparse_table.get_entry(from_hrs_ind); |
676 assert(sprt_entry != NULL, "There should have been an entry"); | |
677 for (int i = 0; i < SparsePRTEntry::cards_num(); i++) { | |
678 CardIdx_t c = sprt_entry->card(i); | |
683 if (c != SparsePRTEntry::NullEntry) { | 679 if (c != SparsePRTEntry::NullEntry) { |
684 prt->add_card(c); | 680 prt->add_card(c); |
685 } | 681 } |
686 } | 682 } |
687 // Now we can delete the sparse entry. | 683 // Now we can delete the sparse entry. |
1082 false /* in-resource-area */), | 1078 false /* in-resource-area */), |
1083 _iter_state(Unclaimed) | 1079 _iter_state(Unclaimed) |
1084 {} | 1080 {} |
1085 | 1081 |
1086 | 1082 |
1083 void HeapRegionRemSet::setup_remset_size() { | |
1084 // Setup sparse and fine-grain tables sizes. | |
1085 // table_size = base * (log(region_size / 1M) + 1) | |
1086 int region_size_log_mb = MAX2((int)HeapRegion::LogOfHRGrainBytes - (int)LOG_M, 0); | |
1087 if (FLAG_IS_DEFAULT(G1RSetSparseRegionEntries)) { | |
1088 G1RSetSparseRegionEntries = G1RSetSparseRegionEntriesBase * (region_size_log_mb + 1); | |
1089 } | |
1090 if (FLAG_IS_DEFAULT(G1RSetRegionEntries)) { | |
1091 G1RSetRegionEntries = G1RSetRegionEntriesBase * (region_size_log_mb + 1); | |
1092 } | |
1093 guarantee(G1RSetSparseRegionEntries > 0 && G1RSetRegionEntries > 0 , "Sanity"); | |
1094 } | |
1095 | |
1087 void HeapRegionRemSet::init_for_par_iteration() { | 1096 void HeapRegionRemSet::init_for_par_iteration() { |
1088 _iter_state = Unclaimed; | 1097 _iter_state = Unclaimed; |
1089 } | 1098 } |
1090 | 1099 |
1091 bool HeapRegionRemSet::claim_iter() { | 1100 bool HeapRegionRemSet::claim_iter() { |
1397 #ifndef PRODUCT | 1406 #ifndef PRODUCT |
1398 void HeapRegionRemSet::test() { | 1407 void HeapRegionRemSet::test() { |
1399 os::sleep(Thread::current(), (jlong)5000, false); | 1408 os::sleep(Thread::current(), (jlong)5000, false); |
1400 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | 1409 G1CollectedHeap* g1h = G1CollectedHeap::heap(); |
1401 | 1410 |
1402 // Run with "-XX:G1LogRSRegionEntries=2", so that 1 and 5 end up in same | 1411 // Run with "-XX:G1LogRSetRegionEntries=2", so that 1 and 5 end up in same |
1403 // hash bucket. | 1412 // hash bucket. |
1404 HeapRegion* hr0 = g1h->region_at(0); | 1413 HeapRegion* hr0 = g1h->region_at(0); |
1405 HeapRegion* hr1 = g1h->region_at(1); | 1414 HeapRegion* hr1 = g1h->region_at(1); |
1406 HeapRegion* hr2 = g1h->region_at(5); | 1415 HeapRegion* hr2 = g1h->region_at(5); |
1407 HeapRegion* hr3 = g1h->region_at(6); | 1416 HeapRegion* hr3 = g1h->region_at(6); |