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 )