Mercurial > hg > truffle
comparison src/share/vm/memory/referenceProcessor.cpp @ 2369:92da084fefc9
6668573: CMS: reference processing crash if ParallelCMSThreads > ParallelGCThreads
Summary: Use _max_num_q = max(discovery_degree, processing_degree), and let balance_queues() redistribute from discovery_degree to processing_degree of queues. This should also allow a more dynamic and flexible parallelism policy in the future.
Reviewed-by: jmasa, johnc
author | ysr |
---|---|
date | Thu, 17 Mar 2011 10:32:46 -0700 |
parents | 8df09fb45352 |
children | c2bf0120ee5d |
comparison
equal
deleted
inserted
replaced
2368:dde920245681 | 2369:92da084fefc9 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
100 guarantee(RefDiscoveryPolicy == ReferenceBasedDiscovery || | 100 guarantee(RefDiscoveryPolicy == ReferenceBasedDiscovery || |
101 RefDiscoveryPolicy == ReferentBasedDiscovery, | 101 RefDiscoveryPolicy == ReferentBasedDiscovery, |
102 "Unrecongnized RefDiscoveryPolicy"); | 102 "Unrecongnized RefDiscoveryPolicy"); |
103 } | 103 } |
104 | 104 |
105 ReferenceProcessor* | |
106 ReferenceProcessor::create_ref_processor(MemRegion span, | |
107 bool atomic_discovery, | |
108 bool mt_discovery, | |
109 BoolObjectClosure* is_alive_non_header, | |
110 int parallel_gc_threads, | |
111 bool mt_processing, | |
112 bool dl_needs_barrier) { | |
113 int mt_degree = 1; | |
114 if (parallel_gc_threads > 1) { | |
115 mt_degree = parallel_gc_threads; | |
116 } | |
117 ReferenceProcessor* rp = | |
118 new ReferenceProcessor(span, atomic_discovery, | |
119 mt_discovery, mt_degree, | |
120 mt_processing && (parallel_gc_threads > 0), | |
121 dl_needs_barrier); | |
122 if (rp == NULL) { | |
123 vm_exit_during_initialization("Could not allocate ReferenceProcessor object"); | |
124 } | |
125 rp->set_is_alive_non_header(is_alive_non_header); | |
126 rp->setup_policy(false /* default soft ref policy */); | |
127 return rp; | |
128 } | |
129 | |
130 ReferenceProcessor::ReferenceProcessor(MemRegion span, | 105 ReferenceProcessor::ReferenceProcessor(MemRegion span, |
106 bool mt_processing, | |
107 int mt_processing_degree, | |
108 bool mt_discovery, | |
109 int mt_discovery_degree, | |
131 bool atomic_discovery, | 110 bool atomic_discovery, |
132 bool mt_discovery, | 111 BoolObjectClosure* is_alive_non_header, |
133 int mt_degree, | |
134 bool mt_processing, | |
135 bool discovered_list_needs_barrier) : | 112 bool discovered_list_needs_barrier) : |
136 _discovering_refs(false), | 113 _discovering_refs(false), |
137 _enqueuing_is_done(false), | 114 _enqueuing_is_done(false), |
138 _is_alive_non_header(NULL), | 115 _is_alive_non_header(is_alive_non_header), |
139 _discovered_list_needs_barrier(discovered_list_needs_barrier), | 116 _discovered_list_needs_barrier(discovered_list_needs_barrier), |
140 _bs(NULL), | 117 _bs(NULL), |
141 _processing_is_mt(mt_processing), | 118 _processing_is_mt(mt_processing), |
142 _next_id(0) | 119 _next_id(0) |
143 { | 120 { |
144 _span = span; | 121 _span = span; |
145 _discovery_is_atomic = atomic_discovery; | 122 _discovery_is_atomic = atomic_discovery; |
146 _discovery_is_mt = mt_discovery; | 123 _discovery_is_mt = mt_discovery; |
147 _num_q = mt_degree; | 124 _num_q = MAX2(1, mt_processing_degree); |
148 _max_num_q = mt_degree; | 125 _max_num_q = MAX2(_num_q, mt_discovery_degree); |
149 _discoveredSoftRefs = NEW_C_HEAP_ARRAY(DiscoveredList, _max_num_q * subclasses_of_ref); | 126 _discoveredSoftRefs = NEW_C_HEAP_ARRAY(DiscoveredList, _max_num_q * subclasses_of_ref); |
150 if (_discoveredSoftRefs == NULL) { | 127 if (_discoveredSoftRefs == NULL) { |
151 vm_exit_during_initialization("Could not allocated RefProc Array"); | 128 vm_exit_during_initialization("Could not allocated RefProc Array"); |
152 } | 129 } |
153 _discoveredWeakRefs = &_discoveredSoftRefs[_max_num_q]; | 130 _discoveredWeakRefs = &_discoveredSoftRefs[_max_num_q]; |
161 } | 138 } |
162 // If we do barreirs, cache a copy of the barrier set. | 139 // If we do barreirs, cache a copy of the barrier set. |
163 if (discovered_list_needs_barrier) { | 140 if (discovered_list_needs_barrier) { |
164 _bs = Universe::heap()->barrier_set(); | 141 _bs = Universe::heap()->barrier_set(); |
165 } | 142 } |
143 setup_policy(false /* default soft ref policy */); | |
166 } | 144 } |
167 | 145 |
168 #ifndef PRODUCT | 146 #ifndef PRODUCT |
169 void ReferenceProcessor::verify_no_references_recorded() { | 147 void ReferenceProcessor::verify_no_references_recorded() { |
170 guarantee(!_discovering_refs, "Discovering refs?"); | 148 guarantee(!_discovering_refs, "Discovering refs?"); |
403 : EnqueueTask(ref_processor, discovered_refs, | 381 : EnqueueTask(ref_processor, discovered_refs, |
404 pending_list_addr, sentinel_ref, n_queues) | 382 pending_list_addr, sentinel_ref, n_queues) |
405 { } | 383 { } |
406 | 384 |
407 virtual void work(unsigned int work_id) { | 385 virtual void work(unsigned int work_id) { |
408 assert(work_id < (unsigned int)_ref_processor.num_q(), "Index out-of-bounds"); | 386 assert(work_id < (unsigned int)_ref_processor.max_num_q(), "Index out-of-bounds"); |
409 // Simplest first cut: static partitioning. | 387 // Simplest first cut: static partitioning. |
410 int index = work_id; | 388 int index = work_id; |
411 // The increment on "index" must correspond to the maximum number of queues | 389 // The increment on "index" must correspond to the maximum number of queues |
412 // (n_queues) with which that ReferenceProcessor was created. That | 390 // (n_queues) with which that ReferenceProcessor was created. That |
413 // is because of the "clever" way the discovered references lists were | 391 // is because of the "clever" way the discovered references lists were |
414 // allocated and are indexed into. That number is ParallelGCThreads | 392 // allocated and are indexed into. |
415 // currently. Assert that. | 393 assert(_n_queues == (int) _ref_processor.max_num_q(), "Different number not expected"); |
416 assert(_n_queues == (int) ParallelGCThreads, "Different number not expected"); | |
417 for (int j = 0; | 394 for (int j = 0; |
418 j < subclasses_of_ref; | 395 j < subclasses_of_ref; |
419 j++, index += _n_queues) { | 396 j++, index += _n_queues) { |
420 _ref_processor.enqueue_discovered_reflist( | 397 _ref_processor.enqueue_discovered_reflist( |
421 _refs_lists[index], _pending_list_addr); | 398 _refs_lists[index], _pending_list_addr); |
670 } else { | 647 } else { |
671 iter.next(); | 648 iter.next(); |
672 } | 649 } |
673 } | 650 } |
674 NOT_PRODUCT( | 651 NOT_PRODUCT( |
675 if (PrintGCDetails && TraceReferenceGC) { | 652 if (PrintGCDetails && TraceReferenceGC && (iter.processed() > 0)) { |
676 gclog_or_tty->print_cr(" Dropped %d active Refs out of %d " | 653 gclog_or_tty->print_cr(" Dropped %d active Refs out of %d " |
677 "Refs in discovered list " INTPTR_FORMAT, | 654 "Refs in discovered list " INTPTR_FORMAT, |
678 iter.removed(), iter.processed(), (address)refs_list.head()); | 655 iter.removed(), iter.processed(), (address)refs_list.head()); |
679 } | 656 } |
680 ) | 657 ) |
709 } | 686 } |
710 } | 687 } |
711 // Now close the newly reachable set | 688 // Now close the newly reachable set |
712 complete_gc->do_void(); | 689 complete_gc->do_void(); |
713 NOT_PRODUCT( | 690 NOT_PRODUCT( |
714 if (PrintGCDetails && TraceReferenceGC) { | 691 if (PrintGCDetails && TraceReferenceGC && (iter.processed() > 0)) { |
715 gclog_or_tty->print_cr(" Dropped %d active Refs out of %d " | 692 gclog_or_tty->print_cr(" Dropped %d active Refs out of %d " |
716 "Refs in discovered list " INTPTR_FORMAT, | 693 "Refs in discovered list " INTPTR_FORMAT, |
717 iter.removed(), iter.processed(), (address)refs_list.head()); | 694 iter.removed(), iter.processed(), (address)refs_list.head()); |
718 } | 695 } |
719 ) | 696 ) |
949 must_balance) { | 926 must_balance) { |
950 balance_queues(refs_lists); | 927 balance_queues(refs_lists); |
951 } | 928 } |
952 if (PrintReferenceGC && PrintGCDetails) { | 929 if (PrintReferenceGC && PrintGCDetails) { |
953 size_t total = 0; | 930 size_t total = 0; |
954 for (int i = 0; i < _num_q; ++i) { | 931 for (int i = 0; i < _max_num_q; ++i) { |
955 total += refs_lists[i].length(); | 932 total += refs_lists[i].length(); |
956 } | 933 } |
957 gclog_or_tty->print(", %u refs", total); | 934 gclog_or_tty->print(", %u refs", total); |
958 } | 935 } |
959 | 936 |
965 if (policy != NULL) { | 942 if (policy != NULL) { |
966 if (mt_processing) { | 943 if (mt_processing) { |
967 RefProcPhase1Task phase1(*this, refs_lists, policy, true /*marks_oops_alive*/); | 944 RefProcPhase1Task phase1(*this, refs_lists, policy, true /*marks_oops_alive*/); |
968 task_executor->execute(phase1); | 945 task_executor->execute(phase1); |
969 } else { | 946 } else { |
970 for (int i = 0; i < _num_q; i++) { | 947 for (int i = 0; i < _max_num_q; i++) { |
971 process_phase1(refs_lists[i], policy, | 948 process_phase1(refs_lists[i], policy, |
972 is_alive, keep_alive, complete_gc); | 949 is_alive, keep_alive, complete_gc); |
973 } | 950 } |
974 } | 951 } |
975 } else { // policy == NULL | 952 } else { // policy == NULL |
981 // . Traverse the list and remove any refs whose referents are alive. | 958 // . Traverse the list and remove any refs whose referents are alive. |
982 if (mt_processing) { | 959 if (mt_processing) { |
983 RefProcPhase2Task phase2(*this, refs_lists, !discovery_is_atomic() /*marks_oops_alive*/); | 960 RefProcPhase2Task phase2(*this, refs_lists, !discovery_is_atomic() /*marks_oops_alive*/); |
984 task_executor->execute(phase2); | 961 task_executor->execute(phase2); |
985 } else { | 962 } else { |
986 for (int i = 0; i < _num_q; i++) { | 963 for (int i = 0; i < _max_num_q; i++) { |
987 process_phase2(refs_lists[i], is_alive, keep_alive, complete_gc); | 964 process_phase2(refs_lists[i], is_alive, keep_alive, complete_gc); |
988 } | 965 } |
989 } | 966 } |
990 | 967 |
991 // Phase 3: | 968 // Phase 3: |
992 // . Traverse the list and process referents as appropriate. | 969 // . Traverse the list and process referents as appropriate. |
993 if (mt_processing) { | 970 if (mt_processing) { |
994 RefProcPhase3Task phase3(*this, refs_lists, clear_referent, true /*marks_oops_alive*/); | 971 RefProcPhase3Task phase3(*this, refs_lists, clear_referent, true /*marks_oops_alive*/); |
995 task_executor->execute(phase3); | 972 task_executor->execute(phase3); |
996 } else { | 973 } else { |
997 for (int i = 0; i < _num_q; i++) { | 974 for (int i = 0; i < _max_num_q; i++) { |
998 process_phase3(refs_lists[i], clear_referent, | 975 process_phase3(refs_lists[i], clear_referent, |
999 is_alive, keep_alive, complete_gc); | 976 is_alive, keep_alive, complete_gc); |
1000 } | 977 } |
1001 } | 978 } |
1002 } | 979 } |
1006 // Should this instead be | 983 // Should this instead be |
1007 // for (int i = 0; i < subclasses_of_ref; i++_ { | 984 // for (int i = 0; i < subclasses_of_ref; i++_ { |
1008 // for (int j = 0; j < _num_q; j++) { | 985 // for (int j = 0; j < _num_q; j++) { |
1009 // int index = i * _max_num_q + j; | 986 // int index = i * _max_num_q + j; |
1010 for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { | 987 for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { |
1011 if (TraceReferenceGC && PrintGCDetails && ((i % _num_q) == 0)) { | 988 if (TraceReferenceGC && PrintGCDetails && ((i % _max_num_q) == 0)) { |
1012 gclog_or_tty->print_cr( | 989 gclog_or_tty->print_cr( |
1013 "\nScrubbing %s discovered list of Null referents", | 990 "\nScrubbing %s discovered list of Null referents", |
1014 list_name(i)); | 991 list_name(i)); |
1015 } | 992 } |
1016 clean_up_discovered_reflist(_discoveredSoftRefs[i]); | 993 clean_up_discovered_reflist(_discoveredSoftRefs[i]); |
1348 | 1325 |
1349 // Weak references | 1326 // Weak references |
1350 { | 1327 { |
1351 TraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC, | 1328 TraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC, |
1352 false, gclog_or_tty); | 1329 false, gclog_or_tty); |
1353 for (int i = 0; i < _num_q; i++) { | 1330 for (int i = 0; i < _max_num_q; i++) { |
1354 if (yield->should_return()) { | 1331 if (yield->should_return()) { |
1355 return; | 1332 return; |
1356 } | 1333 } |
1357 preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive, | 1334 preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive, |
1358 keep_alive, complete_gc, yield); | 1335 keep_alive, complete_gc, yield); |
1361 | 1338 |
1362 // Final references | 1339 // Final references |
1363 { | 1340 { |
1364 TraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC, | 1341 TraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC, |
1365 false, gclog_or_tty); | 1342 false, gclog_or_tty); |
1366 for (int i = 0; i < _num_q; i++) { | 1343 for (int i = 0; i < _max_num_q; i++) { |
1367 if (yield->should_return()) { | 1344 if (yield->should_return()) { |
1368 return; | 1345 return; |
1369 } | 1346 } |
1370 preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive, | 1347 preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive, |
1371 keep_alive, complete_gc, yield); | 1348 keep_alive, complete_gc, yield); |
1374 | 1351 |
1375 // Phantom references | 1352 // Phantom references |
1376 { | 1353 { |
1377 TraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC, | 1354 TraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC, |
1378 false, gclog_or_tty); | 1355 false, gclog_or_tty); |
1379 for (int i = 0; i < _num_q; i++) { | 1356 for (int i = 0; i < _max_num_q; i++) { |
1380 if (yield->should_return()) { | 1357 if (yield->should_return()) { |
1381 return; | 1358 return; |
1382 } | 1359 } |
1383 preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive, | 1360 preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive, |
1384 keep_alive, complete_gc, yield); | 1361 keep_alive, complete_gc, yield); |
1431 } | 1408 } |
1432 // Close the reachable set | 1409 // Close the reachable set |
1433 complete_gc->do_void(); | 1410 complete_gc->do_void(); |
1434 | 1411 |
1435 NOT_PRODUCT( | 1412 NOT_PRODUCT( |
1436 if (PrintGCDetails && PrintReferenceGC) { | 1413 if (PrintGCDetails && PrintReferenceGC && (iter.processed() > 0)) { |
1437 gclog_or_tty->print_cr(" Dropped %d Refs out of %d " | 1414 gclog_or_tty->print_cr(" Dropped %d Refs out of %d " |
1438 "Refs in discovered list " INTPTR_FORMAT, | 1415 "Refs in discovered list " INTPTR_FORMAT, |
1439 iter.removed(), iter.processed(), (address)refs_list.head()); | 1416 iter.removed(), iter.processed(), (address)refs_list.head()); |
1440 } | 1417 } |
1441 ) | 1418 ) |