Mercurial > hg > graal-jvmci-8
comparison src/share/vm/memory/referenceProcessor.cpp @ 1974:fd1d227ef1b9
6983204: G1: Nightly test nsk/regression/b4958615 failing with +ExplicitGCInvokesConcurrent
Summary: Enable reference discovery during concurrent marking by setting the reference processor field of the concurrent marking closure. Keep reference objects on the discovered reference lists alive during incremental evacuation pauses until they are processed at the end of concurrent marking.
Reviewed-by: ysr, tonyp
author | johnc |
---|---|
date | Wed, 01 Dec 2010 17:34:02 -0800 |
parents | f95d63e2154a |
children | 8df09fb45352 |
comparison
equal
deleted
inserted
replaced
1973:631f79e71e90 | 1974:fd1d227ef1b9 |
---|---|
768 | 768 |
769 void ReferenceProcessor::abandon_partial_discovery() { | 769 void ReferenceProcessor::abandon_partial_discovery() { |
770 // loop over the lists | 770 // loop over the lists |
771 for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { | 771 for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { |
772 if (TraceReferenceGC && PrintGCDetails && ((i % _max_num_q) == 0)) { | 772 if (TraceReferenceGC && PrintGCDetails && ((i % _max_num_q) == 0)) { |
773 gclog_or_tty->print_cr( | 773 gclog_or_tty->print_cr("\nAbandoning %s discovered list", |
774 "\nAbandoning %s discovered list", | 774 list_name(i)); |
775 list_name(i)); | |
776 } | 775 } |
777 abandon_partial_discovered_list(_discoveredSoftRefs[i]); | 776 abandon_partial_discovered_list(_discoveredSoftRefs[i]); |
778 } | 777 } |
779 } | 778 } |
780 | 779 |
1057 // Determine the queue index to use for this object. | 1056 // Determine the queue index to use for this object. |
1058 if (_discovery_is_mt) { | 1057 if (_discovery_is_mt) { |
1059 // During a multi-threaded discovery phase, | 1058 // During a multi-threaded discovery phase, |
1060 // each thread saves to its "own" list. | 1059 // each thread saves to its "own" list. |
1061 Thread* thr = Thread::current(); | 1060 Thread* thr = Thread::current(); |
1062 assert(thr->is_GC_task_thread(), | 1061 id = thr->as_Worker_thread()->id(); |
1063 "Dubious cast from Thread* to WorkerThread*?"); | |
1064 id = ((WorkerThread*)thr)->id(); | |
1065 } else { | 1062 } else { |
1066 // single-threaded discovery, we save in round-robin | 1063 // single-threaded discovery, we save in round-robin |
1067 // fashion to each of the lists. | 1064 // fashion to each of the lists. |
1068 if (_processing_is_mt) { | 1065 if (_processing_is_mt) { |
1069 id = next_id(); | 1066 id = next_id(); |
1093 // we should not reach here if we are an instanceRefKlass | 1090 // we should not reach here if we are an instanceRefKlass |
1094 default: | 1091 default: |
1095 ShouldNotReachHere(); | 1092 ShouldNotReachHere(); |
1096 } | 1093 } |
1097 if (TraceReferenceGC && PrintGCDetails) { | 1094 if (TraceReferenceGC && PrintGCDetails) { |
1098 gclog_or_tty->print_cr("Thread %d gets list " INTPTR_FORMAT, | 1095 gclog_or_tty->print_cr("Thread %d gets list " INTPTR_FORMAT, id, list); |
1099 id, list); | |
1100 } | 1096 } |
1101 return list; | 1097 return list; |
1102 } | 1098 } |
1103 | 1099 |
1104 inline void | 1100 inline void |
1132 // is necessary. | 1128 // is necessary. |
1133 refs_list.set_head(obj); | 1129 refs_list.set_head(obj); |
1134 refs_list.inc_length(1); | 1130 refs_list.inc_length(1); |
1135 if (_discovered_list_needs_barrier) { | 1131 if (_discovered_list_needs_barrier) { |
1136 _bs->write_ref_field((void*)discovered_addr, current_head); | 1132 _bs->write_ref_field((void*)discovered_addr, current_head); |
1133 } | |
1134 | |
1135 if (TraceReferenceGC) { | |
1136 gclog_or_tty->print_cr("Enqueued reference (mt) (" INTPTR_FORMAT ": %s)", | |
1137 obj, obj->blueprint()->internal_name()); | |
1137 } | 1138 } |
1138 } else { | 1139 } else { |
1139 // If retest was non NULL, another thread beat us to it: | 1140 // If retest was non NULL, another thread beat us to it: |
1140 // The reference has already been discovered... | 1141 // The reference has already been discovered... |
1141 if (TraceReferenceGC) { | 1142 if (TraceReferenceGC) { |
1237 assert(RefDiscoveryPolicy == ReferenceBasedDiscovery, | 1238 assert(RefDiscoveryPolicy == ReferenceBasedDiscovery, |
1238 "Unrecognized policy"); | 1239 "Unrecognized policy"); |
1239 // Check assumption that an object is not potentially | 1240 // Check assumption that an object is not potentially |
1240 // discovered twice except by concurrent collectors that potentially | 1241 // discovered twice except by concurrent collectors that potentially |
1241 // trace the same Reference object twice. | 1242 // trace the same Reference object twice. |
1242 assert(UseConcMarkSweepGC, | 1243 assert(UseConcMarkSweepGC || UseG1GC, |
1243 "Only possible with an incremental-update concurrent collector"); | 1244 "Only possible with a concurrent marking collector"); |
1244 return true; | 1245 return true; |
1245 } | 1246 } |
1246 } | 1247 } |
1247 | 1248 |
1248 if (RefDiscoveryPolicy == ReferentBasedDiscovery) { | 1249 if (RefDiscoveryPolicy == ReferentBasedDiscovery) { |
1291 if (_discovered_list_needs_barrier) { | 1292 if (_discovered_list_needs_barrier) { |
1292 _bs->write_ref_field((void*)discovered_addr, current_head); | 1293 _bs->write_ref_field((void*)discovered_addr, current_head); |
1293 } | 1294 } |
1294 list->set_head(obj); | 1295 list->set_head(obj); |
1295 list->inc_length(1); | 1296 list->inc_length(1); |
1296 } | 1297 |
1297 | 1298 if (TraceReferenceGC) { |
1298 // In the MT discovery case, it is currently possible to see | |
1299 // the following message multiple times if several threads | |
1300 // discover a reference about the same time. Only one will | |
1301 // however have actually added it to the disocvered queue. | |
1302 // One could let add_to_discovered_list_mt() return an | |
1303 // indication for success in queueing (by 1 thread) or | |
1304 // failure (by all other threads), but I decided the extra | |
1305 // code was not worth the effort for something that is | |
1306 // only used for debugging support. | |
1307 if (TraceReferenceGC) { | |
1308 oop referent = java_lang_ref_Reference::referent(obj); | |
1309 if (PrintGCDetails) { | |
1310 gclog_or_tty->print_cr("Enqueued reference (" INTPTR_FORMAT ": %s)", | 1299 gclog_or_tty->print_cr("Enqueued reference (" INTPTR_FORMAT ": %s)", |
1311 obj, obj->blueprint()->internal_name()); | 1300 obj, obj->blueprint()->internal_name()); |
1312 } | 1301 } |
1313 assert(referent->is_oop(), "Enqueued a bad referent"); | |
1314 } | 1302 } |
1315 assert(obj->is_oop(), "Enqueued a bad reference"); | 1303 assert(obj->is_oop(), "Enqueued a bad reference"); |
1304 assert(java_lang_ref_Reference::referent(obj)->is_oop(), "Enqueued a bad referent"); | |
1316 return true; | 1305 return true; |
1317 } | 1306 } |
1318 | 1307 |
1319 // Preclean the discovered references by removing those | 1308 // Preclean the discovered references by removing those |
1320 // whose referents are alive, and by marking from those that | 1309 // whose referents are alive, and by marking from those that |