445 return; 446 } 447 448 // Otherwise find a per-region table to add it to. 449 size_t ind = from_hrm_ind & _mod_max_fine_entries_mask; 450 PerRegionTable* prt = find_region_table(ind, from_hr); 451 if (prt == NULL) { 452 MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); 453 // Confirm that it's really not there... 454 prt = find_region_table(ind, from_hr); 455 if (prt == NULL) { 456 457 uintptr_t from_hr_bot_card_index = 458 uintptr_t(from_hr->bottom()) 459 >> CardTableModRefBS::card_shift; 460 CardIdx_t card_index = from_card - from_hr_bot_card_index; 461 assert(0 <= card_index && (size_t)card_index < HeapRegion::CardsPerRegion, 462 "Must be in range."); 463 if (G1HRRSUseSparseTable && 464 _sparse_table.add_card(from_hrm_ind, card_index)) { 465 if (G1RecordHRRSOops) { 466 HeapRegionRemSet::record(_hr, from); 467 if (G1TraceHeapRegionRememberedSet) { 468 gclog_or_tty->print(" Added card " PTR_FORMAT " to region " 469 "[" PTR_FORMAT "...) for ref " PTR_FORMAT ".\n", 470 align_size_down(uintptr_t(from), 471 CardTableModRefBS::card_size), 472 p2i(_hr->bottom()), p2i(from)); 473 } 474 } 475 if (G1TraceHeapRegionRememberedSet) { 476 gclog_or_tty->print_cr(" added card to sparse table."); 477 } 478 assert(contains_reference_locked(from), "We just added it!"); 479 return; 480 } else { 481 if (G1TraceHeapRegionRememberedSet) { 482 gclog_or_tty->print_cr(" [tid %u] sparse table entry " 483 "overflow(f: %d, t: %u)", 484 tid, from_hrm_ind, cur_hrm_ind); 485 } 486 } 487 488 if (_n_fine_entries == _max_fine_entries) { 489 prt = delete_region_table(); 490 // There is no need to clear the links to the 'all' list here: 491 // prt will be reused immediately, i.e. remain in the 'all' list. 492 prt->init(from_hr, false /* clear_links_to_all_list */); 493 } else { 494 prt = PerRegionTable::alloc(from_hr); 514 assert(sprt_entry != NULL, "There should have been an entry"); 515 for (int i = 0; i < SparsePRTEntry::cards_num(); i++) { 516 CardIdx_t c = sprt_entry->card(i); 517 if (c != SparsePRTEntry::NullEntry) { 518 prt->add_card(c); 519 } 520 } 521 // Now we can delete the sparse entry. 522 bool res = _sparse_table.delete_entry(from_hrm_ind); 523 assert(res, "It should have been there."); 524 } 525 } 526 assert(prt != NULL && prt->hr() == from_hr, "consequence"); 527 } 528 // Note that we can't assert "prt->hr() == from_hr", because of the 529 // possibility of concurrent reuse. But see head comment of 530 // OtherRegionsTable for why this is OK. 531 assert(prt != NULL, "Inv"); 532 533 prt->add_reference(from); 534 535 if (G1RecordHRRSOops) { 536 HeapRegionRemSet::record(_hr, from); 537 if (G1TraceHeapRegionRememberedSet) { 538 gclog_or_tty->print("Added card " PTR_FORMAT " to region " 539 "[" PTR_FORMAT "...) for ref " PTR_FORMAT ".\n", 540 align_size_down(uintptr_t(from), 541 CardTableModRefBS::card_size), 542 p2i(_hr->bottom()), p2i(from)); 543 } 544 } 545 assert(contains_reference(from), "We just added it!"); 546 } 547 548 PerRegionTable* 549 OtherRegionsTable::find_region_table(size_t ind, HeapRegion* hr) const { 550 assert(ind < _max_fine_entries, "Preconditions."); 551 PerRegionTable* prt = _fine_grain_regions[ind]; 552 while (prt != NULL && prt->hr() != hr) { 553 prt = prt->collision_list_next(); 554 } 555 // Loop postcondition is the method postcondition. 556 return prt; 557 } 558 559 jint OtherRegionsTable::_n_coarsenings = 0; 560 561 PerRegionTable* OtherRegionsTable::delete_region_table() { 562 assert(_m->owned_by_self(), "Precondition"); 563 assert(_n_fine_entries == _max_fine_entries, "Precondition"); 564 PerRegionTable* max = NULL; 1052 case Fine: 1053 if (fine_has_next(card_index)) { 1054 _n_yielded_fine++; 1055 return true; 1056 } 1057 // Otherwise, deliberate fall-through 1058 _is = Coarse; 1059 case Coarse: 1060 if (coarse_has_next(card_index)) { 1061 _n_yielded_coarse++; 1062 return true; 1063 } 1064 // Otherwise... 1065 break; 1066 } 1067 assert(ParallelGCThreads > 1 || 1068 n_yielded() == _hrrs->occupied(), 1069 "Should have yielded all the cards in the rem set " 1070 "(in the non-par case)."); 1071 return false; 1072 } 1073 1074 1075 1076 OopOrNarrowOopStar* HeapRegionRemSet::_recorded_oops = NULL; 1077 HeapWord** HeapRegionRemSet::_recorded_cards = NULL; 1078 HeapRegion** HeapRegionRemSet::_recorded_regions = NULL; 1079 int HeapRegionRemSet::_n_recorded = 0; 1080 1081 HeapRegionRemSet::Event* HeapRegionRemSet::_recorded_events = NULL; 1082 int* HeapRegionRemSet::_recorded_event_index = NULL; 1083 int HeapRegionRemSet::_n_recorded_events = 0; 1084 1085 void HeapRegionRemSet::record(HeapRegion* hr, OopOrNarrowOopStar f) { 1086 if (_recorded_oops == NULL) { 1087 assert(_n_recorded == 0 1088 && _recorded_cards == NULL 1089 && _recorded_regions == NULL, 1090 "Inv"); 1091 _recorded_oops = NEW_C_HEAP_ARRAY(OopOrNarrowOopStar, MaxRecorded, mtGC); 1092 _recorded_cards = NEW_C_HEAP_ARRAY(HeapWord*, MaxRecorded, mtGC); 1093 _recorded_regions = NEW_C_HEAP_ARRAY(HeapRegion*, MaxRecorded, mtGC); 1094 } 1095 if (_n_recorded == MaxRecorded) { 1096 gclog_or_tty->print_cr("Filled up 'recorded' (%d).", MaxRecorded); 1097 } else { 1098 _recorded_cards[_n_recorded] = 1099 (HeapWord*)align_size_down(uintptr_t(f), 1100 CardTableModRefBS::card_size); 1101 _recorded_oops[_n_recorded] = f; 1102 _recorded_regions[_n_recorded] = hr; 1103 _n_recorded++; 1104 } 1105 } 1106 1107 void HeapRegionRemSet::record_event(Event evnt) { 1108 if (!G1RecordHRRSEvents) return; 1109 1110 if (_recorded_events == NULL) { 1111 assert(_n_recorded_events == 0 1112 && _recorded_event_index == NULL, 1113 "Inv"); 1114 _recorded_events = NEW_C_HEAP_ARRAY(Event, MaxRecordedEvents, mtGC); 1115 _recorded_event_index = NEW_C_HEAP_ARRAY(int, MaxRecordedEvents, mtGC); 1116 } 1117 if (_n_recorded_events == MaxRecordedEvents) { 1118 gclog_or_tty->print_cr("Filled up 'recorded_events' (%d).", MaxRecordedEvents); 1119 } else { 1120 _recorded_events[_n_recorded_events] = evnt; 1121 _recorded_event_index[_n_recorded_events] = _n_recorded; 1122 _n_recorded_events++; 1123 } 1124 } 1125 1126 void HeapRegionRemSet::print_event(outputStream* str, Event evnt) { 1127 switch (evnt) { 1128 case Event_EvacStart: 1129 str->print("Evac Start"); 1130 break; 1131 case Event_EvacEnd: 1132 str->print("Evac End"); 1133 break; 1134 case Event_RSUpdateEnd: 1135 str->print("RS Update End"); 1136 break; 1137 } 1138 } 1139 1140 void HeapRegionRemSet::print_recorded() { 1141 int cur_evnt = 0; 1142 Event cur_evnt_kind = Event_illegal; 1143 int cur_evnt_ind = 0; 1144 if (_n_recorded_events > 0) { 1145 cur_evnt_kind = _recorded_events[cur_evnt]; 1146 cur_evnt_ind = _recorded_event_index[cur_evnt]; 1147 } 1148 1149 for (int i = 0; i < _n_recorded; i++) { 1150 while (cur_evnt < _n_recorded_events && i == cur_evnt_ind) { 1151 gclog_or_tty->print("Event: "); 1152 print_event(gclog_or_tty, cur_evnt_kind); 1153 gclog_or_tty->cr(); 1154 cur_evnt++; 1155 if (cur_evnt < MaxRecordedEvents) { 1156 cur_evnt_kind = _recorded_events[cur_evnt]; 1157 cur_evnt_ind = _recorded_event_index[cur_evnt]; 1158 } 1159 } 1160 gclog_or_tty->print("Added card " PTR_FORMAT " to region [" PTR_FORMAT "...]" 1161 " for ref " PTR_FORMAT ".\n", 1162 p2i(_recorded_cards[i]), p2i(_recorded_regions[i]->bottom()), 1163 p2i(_recorded_oops[i])); 1164 } 1165 } 1166 1167 void HeapRegionRemSet::reset_for_cleanup_tasks() { 1168 SparsePRT::reset_for_cleanup_tasks(); 1169 } 1170 1171 void HeapRegionRemSet::do_cleanup_work(HRRSCleanupTask* hrrs_cleanup_task) { 1172 _other_regions.do_cleanup_work(hrrs_cleanup_task); 1173 } 1174 1175 void 1176 HeapRegionRemSet::finish_cleanup_task(HRRSCleanupTask* hrrs_cleanup_task) { 1177 SparsePRT::finish_cleanup_task(hrrs_cleanup_task); 1178 } 1179 1180 #ifndef PRODUCT 1181 void PerRegionTable::test_fl_mem_size() { 1182 PerRegionTable* dummy = alloc(NULL); 1183 1184 size_t min_prt_size = sizeof(void*) + dummy->bm()->size_in_words() * HeapWordSize; | 445 return; 446 } 447 448 // Otherwise find a per-region table to add it to. 449 size_t ind = from_hrm_ind & _mod_max_fine_entries_mask; 450 PerRegionTable* prt = find_region_table(ind, from_hr); 451 if (prt == NULL) { 452 MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); 453 // Confirm that it's really not there... 454 prt = find_region_table(ind, from_hr); 455 if (prt == NULL) { 456 457 uintptr_t from_hr_bot_card_index = 458 uintptr_t(from_hr->bottom()) 459 >> CardTableModRefBS::card_shift; 460 CardIdx_t card_index = from_card - from_hr_bot_card_index; 461 assert(0 <= card_index && (size_t)card_index < HeapRegion::CardsPerRegion, 462 "Must be in range."); 463 if (G1HRRSUseSparseTable && 464 _sparse_table.add_card(from_hrm_ind, card_index)) { 465 if (G1TraceHeapRegionRememberedSet) { 466 gclog_or_tty->print_cr(" added card to sparse table."); 467 } 468 assert(contains_reference_locked(from), "We just added it!"); 469 return; 470 } else { 471 if (G1TraceHeapRegionRememberedSet) { 472 gclog_or_tty->print_cr(" [tid %u] sparse table entry " 473 "overflow(f: %d, t: %u)", 474 tid, from_hrm_ind, cur_hrm_ind); 475 } 476 } 477 478 if (_n_fine_entries == _max_fine_entries) { 479 prt = delete_region_table(); 480 // There is no need to clear the links to the 'all' list here: 481 // prt will be reused immediately, i.e. remain in the 'all' list. 482 prt->init(from_hr, false /* clear_links_to_all_list */); 483 } else { 484 prt = PerRegionTable::alloc(from_hr); 504 assert(sprt_entry != NULL, "There should have been an entry"); 505 for (int i = 0; i < SparsePRTEntry::cards_num(); i++) { 506 CardIdx_t c = sprt_entry->card(i); 507 if (c != SparsePRTEntry::NullEntry) { 508 prt->add_card(c); 509 } 510 } 511 // Now we can delete the sparse entry. 512 bool res = _sparse_table.delete_entry(from_hrm_ind); 513 assert(res, "It should have been there."); 514 } 515 } 516 assert(prt != NULL && prt->hr() == from_hr, "consequence"); 517 } 518 // Note that we can't assert "prt->hr() == from_hr", because of the 519 // possibility of concurrent reuse. But see head comment of 520 // OtherRegionsTable for why this is OK. 521 assert(prt != NULL, "Inv"); 522 523 prt->add_reference(from); 524 assert(contains_reference(from), "We just added it!"); 525 } 526 527 PerRegionTable* 528 OtherRegionsTable::find_region_table(size_t ind, HeapRegion* hr) const { 529 assert(ind < _max_fine_entries, "Preconditions."); 530 PerRegionTable* prt = _fine_grain_regions[ind]; 531 while (prt != NULL && prt->hr() != hr) { 532 prt = prt->collision_list_next(); 533 } 534 // Loop postcondition is the method postcondition. 535 return prt; 536 } 537 538 jint OtherRegionsTable::_n_coarsenings = 0; 539 540 PerRegionTable* OtherRegionsTable::delete_region_table() { 541 assert(_m->owned_by_self(), "Precondition"); 542 assert(_n_fine_entries == _max_fine_entries, "Precondition"); 543 PerRegionTable* max = NULL; 1031 case Fine: 1032 if (fine_has_next(card_index)) { 1033 _n_yielded_fine++; 1034 return true; 1035 } 1036 // Otherwise, deliberate fall-through 1037 _is = Coarse; 1038 case Coarse: 1039 if (coarse_has_next(card_index)) { 1040 _n_yielded_coarse++; 1041 return true; 1042 } 1043 // Otherwise... 1044 break; 1045 } 1046 assert(ParallelGCThreads > 1 || 1047 n_yielded() == _hrrs->occupied(), 1048 "Should have yielded all the cards in the rem set " 1049 "(in the non-par case)."); 1050 return false; 1051 } 1052 1053 void HeapRegionRemSet::reset_for_cleanup_tasks() { 1054 SparsePRT::reset_for_cleanup_tasks(); 1055 } 1056 1057 void HeapRegionRemSet::do_cleanup_work(HRRSCleanupTask* hrrs_cleanup_task) { 1058 _other_regions.do_cleanup_work(hrrs_cleanup_task); 1059 } 1060 1061 void 1062 HeapRegionRemSet::finish_cleanup_task(HRRSCleanupTask* hrrs_cleanup_task) { 1063 SparsePRT::finish_cleanup_task(hrrs_cleanup_task); 1064 } 1065 1066 #ifndef PRODUCT 1067 void PerRegionTable::test_fl_mem_size() { 1068 PerRegionTable* dummy = alloc(NULL); 1069 1070 size_t min_prt_size = sizeof(void*) + dummy->bm()->size_in_words() * HeapWordSize; |