86 _discovering_refs = true; |
86 _discovering_refs = true; |
87 } |
87 } |
88 |
88 |
89 ReferenceProcessor::ReferenceProcessor(MemRegion span, |
89 ReferenceProcessor::ReferenceProcessor(MemRegion span, |
90 bool mt_processing, |
90 bool mt_processing, |
91 int mt_processing_degree, |
91 uint mt_processing_degree, |
92 bool mt_discovery, |
92 bool mt_discovery, |
93 int mt_discovery_degree, |
93 uint mt_discovery_degree, |
94 bool atomic_discovery, |
94 bool atomic_discovery, |
95 BoolObjectClosure* is_alive_non_header, |
95 BoolObjectClosure* is_alive_non_header, |
96 bool discovered_list_needs_barrier) : |
96 bool discovered_list_needs_barrier) : |
97 _discovering_refs(false), |
97 _discovering_refs(false), |
98 _enqueuing_is_done(false), |
98 _enqueuing_is_done(false), |
103 _next_id(0) |
103 _next_id(0) |
104 { |
104 { |
105 _span = span; |
105 _span = span; |
106 _discovery_is_atomic = atomic_discovery; |
106 _discovery_is_atomic = atomic_discovery; |
107 _discovery_is_mt = mt_discovery; |
107 _discovery_is_mt = mt_discovery; |
108 _num_q = MAX2(1, mt_processing_degree); |
108 _num_q = MAX2(1U, mt_processing_degree); |
109 _max_num_q = MAX2(_num_q, mt_discovery_degree); |
109 _max_num_q = MAX2(_num_q, mt_discovery_degree); |
110 _discovered_refs = NEW_C_HEAP_ARRAY(DiscoveredList, |
110 _discovered_refs = NEW_C_HEAP_ARRAY(DiscoveredList, |
111 _max_num_q * number_of_subclasses_of_ref()); |
111 _max_num_q * number_of_subclasses_of_ref()); |
112 if (_discovered_refs == NULL) { |
112 if (_discovered_refs == NULL) { |
113 vm_exit_during_initialization("Could not allocated RefProc Array"); |
113 vm_exit_during_initialization("Could not allocated RefProc Array"); |
116 _discoveredWeakRefs = &_discoveredSoftRefs[_max_num_q]; |
116 _discoveredWeakRefs = &_discoveredSoftRefs[_max_num_q]; |
117 _discoveredFinalRefs = &_discoveredWeakRefs[_max_num_q]; |
117 _discoveredFinalRefs = &_discoveredWeakRefs[_max_num_q]; |
118 _discoveredPhantomRefs = &_discoveredFinalRefs[_max_num_q]; |
118 _discoveredPhantomRefs = &_discoveredFinalRefs[_max_num_q]; |
119 |
119 |
120 // Initialize all entries to NULL |
120 // Initialize all entries to NULL |
121 for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { |
121 for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { |
122 _discovered_refs[i].set_head(NULL); |
122 _discovered_refs[i].set_head(NULL); |
123 _discovered_refs[i].set_length(0); |
123 _discovered_refs[i].set_length(0); |
124 } |
124 } |
125 |
125 |
126 // If we do barriers, cache a copy of the barrier set. |
126 // If we do barriers, cache a copy of the barrier set. |
131 } |
131 } |
132 |
132 |
133 #ifndef PRODUCT |
133 #ifndef PRODUCT |
134 void ReferenceProcessor::verify_no_references_recorded() { |
134 void ReferenceProcessor::verify_no_references_recorded() { |
135 guarantee(!_discovering_refs, "Discovering refs?"); |
135 guarantee(!_discovering_refs, "Discovering refs?"); |
136 for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { |
136 for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { |
137 guarantee(_discovered_refs[i].is_empty(), |
137 guarantee(_discovered_refs[i].is_empty(), |
138 "Found non-empty discovered list"); |
138 "Found non-empty discovered list"); |
139 } |
139 } |
140 } |
140 } |
141 #endif |
141 #endif |
142 |
142 |
143 void ReferenceProcessor::weak_oops_do(OopClosure* f) { |
143 void ReferenceProcessor::weak_oops_do(OopClosure* f) { |
144 for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { |
144 for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { |
145 if (UseCompressedOops) { |
145 if (UseCompressedOops) { |
146 f->do_oop((narrowOop*)_discovered_refs[i].adr_head()); |
146 f->do_oop((narrowOop*)_discovered_refs[i].adr_head()); |
147 } else { |
147 } else { |
148 f->do_oop((oop*)_discovered_refs[i].adr_head()); |
148 f->do_oop((oop*)_discovered_refs[i].adr_head()); |
149 } |
149 } |
435 RefProcEnqueueTask tsk(*this, _discovered_refs, |
435 RefProcEnqueueTask tsk(*this, _discovered_refs, |
436 pending_list_addr, _max_num_q); |
436 pending_list_addr, _max_num_q); |
437 task_executor->execute(tsk); |
437 task_executor->execute(tsk); |
438 } else { |
438 } else { |
439 // Serial code: call the parent class's implementation |
439 // Serial code: call the parent class's implementation |
440 for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { |
440 for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { |
441 enqueue_discovered_reflist(_discovered_refs[i], pending_list_addr); |
441 enqueue_discovered_reflist(_discovered_refs[i], pending_list_addr); |
442 _discovered_refs[i].set_head(NULL); |
442 _discovered_refs[i].set_head(NULL); |
443 _discovered_refs[i].set_length(0); |
443 _discovered_refs[i].set_length(0); |
444 } |
444 } |
445 } |
445 } |
694 clear_discovered_references(refs_list); |
694 clear_discovered_references(refs_list); |
695 } |
695 } |
696 |
696 |
697 void ReferenceProcessor::abandon_partial_discovery() { |
697 void ReferenceProcessor::abandon_partial_discovery() { |
698 // loop over the lists |
698 // loop over the lists |
699 for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { |
699 for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { |
700 if (TraceReferenceGC && PrintGCDetails && ((i % _max_num_q) == 0)) { |
700 if (TraceReferenceGC && PrintGCDetails && ((i % _max_num_q) == 0)) { |
701 gclog_or_tty->print_cr("\nAbandoning %s discovered list", list_name(i)); |
701 gclog_or_tty->print_cr("\nAbandoning %s discovered list", list_name(i)); |
702 } |
702 } |
703 abandon_partial_discovered_list(_discovered_refs[i]); |
703 abandon_partial_discovered_list(_discovered_refs[i]); |
704 } |
704 } |
785 size_t total_refs = 0; |
785 size_t total_refs = 0; |
786 if (TraceReferenceGC && PrintGCDetails) { |
786 if (TraceReferenceGC && PrintGCDetails) { |
787 gclog_or_tty->print_cr("\nBalance ref_lists "); |
787 gclog_or_tty->print_cr("\nBalance ref_lists "); |
788 } |
788 } |
789 |
789 |
790 for (int i = 0; i < _max_num_q; ++i) { |
790 for (uint i = 0; i < _max_num_q; ++i) { |
791 total_refs += ref_lists[i].length(); |
791 total_refs += ref_lists[i].length(); |
792 if (TraceReferenceGC && PrintGCDetails) { |
792 if (TraceReferenceGC && PrintGCDetails) { |
793 gclog_or_tty->print("%d ", ref_lists[i].length()); |
793 gclog_or_tty->print("%d ", ref_lists[i].length()); |
794 } |
794 } |
795 } |
795 } |
796 if (TraceReferenceGC && PrintGCDetails) { |
796 if (TraceReferenceGC && PrintGCDetails) { |
797 gclog_or_tty->print_cr(" = %d", total_refs); |
797 gclog_or_tty->print_cr(" = %d", total_refs); |
798 } |
798 } |
799 size_t avg_refs = total_refs / _num_q + 1; |
799 size_t avg_refs = total_refs / _num_q + 1; |
800 int to_idx = 0; |
800 uint to_idx = 0; |
801 for (int from_idx = 0; from_idx < _max_num_q; from_idx++) { |
801 for (uint from_idx = 0; from_idx < _max_num_q; from_idx++) { |
802 bool move_all = false; |
802 bool move_all = false; |
803 if (from_idx >= _num_q) { |
803 if (from_idx >= _num_q) { |
804 move_all = ref_lists[from_idx].length() > 0; |
804 move_all = ref_lists[from_idx].length() > 0; |
805 } |
805 } |
806 while ((ref_lists[from_idx].length() > avg_refs) || |
806 while ((ref_lists[from_idx].length() > avg_refs) || |
855 } |
855 } |
856 } |
856 } |
857 } |
857 } |
858 #ifdef ASSERT |
858 #ifdef ASSERT |
859 size_t balanced_total_refs = 0; |
859 size_t balanced_total_refs = 0; |
860 for (int i = 0; i < _max_num_q; ++i) { |
860 for (uint i = 0; i < _max_num_q; ++i) { |
861 balanced_total_refs += ref_lists[i].length(); |
861 balanced_total_refs += ref_lists[i].length(); |
862 if (TraceReferenceGC && PrintGCDetails) { |
862 if (TraceReferenceGC && PrintGCDetails) { |
863 gclog_or_tty->print("%d ", ref_lists[i].length()); |
863 gclog_or_tty->print("%d ", ref_lists[i].length()); |
864 } |
864 } |
865 } |
865 } |
901 must_balance) { |
901 must_balance) { |
902 balance_queues(refs_lists); |
902 balance_queues(refs_lists); |
903 } |
903 } |
904 if (PrintReferenceGC && PrintGCDetails) { |
904 if (PrintReferenceGC && PrintGCDetails) { |
905 size_t total = 0; |
905 size_t total = 0; |
906 for (int i = 0; i < _max_num_q; ++i) { |
906 for (uint i = 0; i < _max_num_q; ++i) { |
907 total += refs_lists[i].length(); |
907 total += refs_lists[i].length(); |
908 } |
908 } |
909 gclog_or_tty->print(", %u refs", total); |
909 gclog_or_tty->print(", %u refs", total); |
910 } |
910 } |
911 |
911 |
917 if (policy != NULL) { |
917 if (policy != NULL) { |
918 if (mt_processing) { |
918 if (mt_processing) { |
919 RefProcPhase1Task phase1(*this, refs_lists, policy, true /*marks_oops_alive*/); |
919 RefProcPhase1Task phase1(*this, refs_lists, policy, true /*marks_oops_alive*/); |
920 task_executor->execute(phase1); |
920 task_executor->execute(phase1); |
921 } else { |
921 } else { |
922 for (int i = 0; i < _max_num_q; i++) { |
922 for (uint i = 0; i < _max_num_q; i++) { |
923 process_phase1(refs_lists[i], policy, |
923 process_phase1(refs_lists[i], policy, |
924 is_alive, keep_alive, complete_gc); |
924 is_alive, keep_alive, complete_gc); |
925 } |
925 } |
926 } |
926 } |
927 } else { // policy == NULL |
927 } else { // policy == NULL |
933 // . Traverse the list and remove any refs whose referents are alive. |
933 // . Traverse the list and remove any refs whose referents are alive. |
934 if (mt_processing) { |
934 if (mt_processing) { |
935 RefProcPhase2Task phase2(*this, refs_lists, !discovery_is_atomic() /*marks_oops_alive*/); |
935 RefProcPhase2Task phase2(*this, refs_lists, !discovery_is_atomic() /*marks_oops_alive*/); |
936 task_executor->execute(phase2); |
936 task_executor->execute(phase2); |
937 } else { |
937 } else { |
938 for (int i = 0; i < _max_num_q; i++) { |
938 for (uint i = 0; i < _max_num_q; i++) { |
939 process_phase2(refs_lists[i], is_alive, keep_alive, complete_gc); |
939 process_phase2(refs_lists[i], is_alive, keep_alive, complete_gc); |
940 } |
940 } |
941 } |
941 } |
942 |
942 |
943 // Phase 3: |
943 // Phase 3: |
944 // . Traverse the list and process referents as appropriate. |
944 // . Traverse the list and process referents as appropriate. |
945 if (mt_processing) { |
945 if (mt_processing) { |
946 RefProcPhase3Task phase3(*this, refs_lists, clear_referent, true /*marks_oops_alive*/); |
946 RefProcPhase3Task phase3(*this, refs_lists, clear_referent, true /*marks_oops_alive*/); |
947 task_executor->execute(phase3); |
947 task_executor->execute(phase3); |
948 } else { |
948 } else { |
949 for (int i = 0; i < _max_num_q; i++) { |
949 for (uint i = 0; i < _max_num_q; i++) { |
950 process_phase3(refs_lists[i], clear_referent, |
950 process_phase3(refs_lists[i], clear_referent, |
951 is_alive, keep_alive, complete_gc); |
951 is_alive, keep_alive, complete_gc); |
952 } |
952 } |
953 } |
953 } |
954 } |
954 } |
955 |
955 |
956 void ReferenceProcessor::clean_up_discovered_references() { |
956 void ReferenceProcessor::clean_up_discovered_references() { |
957 // loop over the lists |
957 // loop over the lists |
958 for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { |
958 for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { |
959 if (TraceReferenceGC && PrintGCDetails && ((i % _max_num_q) == 0)) { |
959 if (TraceReferenceGC && PrintGCDetails && ((i % _max_num_q) == 0)) { |
960 gclog_or_tty->print_cr( |
960 gclog_or_tty->print_cr( |
961 "\nScrubbing %s discovered list of Null referents", |
961 "\nScrubbing %s discovered list of Null referents", |
962 list_name(i)); |
962 list_name(i)); |
963 } |
963 } |
998 } |
998 } |
999 ) |
999 ) |
1000 } |
1000 } |
1001 |
1001 |
1002 inline DiscoveredList* ReferenceProcessor::get_discovered_list(ReferenceType rt) { |
1002 inline DiscoveredList* ReferenceProcessor::get_discovered_list(ReferenceType rt) { |
1003 int id = 0; |
1003 uint id = 0; |
1004 // Determine the queue index to use for this object. |
1004 // Determine the queue index to use for this object. |
1005 if (_discovery_is_mt) { |
1005 if (_discovery_is_mt) { |
1006 // During a multi-threaded discovery phase, |
1006 // During a multi-threaded discovery phase, |
1007 // each thread saves to its "own" list. |
1007 // each thread saves to its "own" list. |
1008 Thread* thr = Thread::current(); |
1008 Thread* thr = Thread::current(); |
1280 #endif |
1280 #endif |
1281 // Soft references |
1281 // Soft references |
1282 { |
1282 { |
1283 TraceTime tt("Preclean SoftReferences", PrintGCDetails && PrintReferenceGC, |
1283 TraceTime tt("Preclean SoftReferences", PrintGCDetails && PrintReferenceGC, |
1284 false, gclog_or_tty); |
1284 false, gclog_or_tty); |
1285 for (int i = 0; i < _max_num_q; i++) { |
1285 for (uint i = 0; i < _max_num_q; i++) { |
1286 if (yield->should_return()) { |
1286 if (yield->should_return()) { |
1287 return; |
1287 return; |
1288 } |
1288 } |
1289 preclean_discovered_reflist(_discoveredSoftRefs[i], is_alive, |
1289 preclean_discovered_reflist(_discoveredSoftRefs[i], is_alive, |
1290 keep_alive, complete_gc, yield); |
1290 keep_alive, complete_gc, yield); |
1293 |
1293 |
1294 // Weak references |
1294 // Weak references |
1295 { |
1295 { |
1296 TraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC, |
1296 TraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC, |
1297 false, gclog_or_tty); |
1297 false, gclog_or_tty); |
1298 for (int i = 0; i < _max_num_q; i++) { |
1298 for (uint i = 0; i < _max_num_q; i++) { |
1299 if (yield->should_return()) { |
1299 if (yield->should_return()) { |
1300 return; |
1300 return; |
1301 } |
1301 } |
1302 preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive, |
1302 preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive, |
1303 keep_alive, complete_gc, yield); |
1303 keep_alive, complete_gc, yield); |
1306 |
1306 |
1307 // Final references |
1307 // Final references |
1308 { |
1308 { |
1309 TraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC, |
1309 TraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC, |
1310 false, gclog_or_tty); |
1310 false, gclog_or_tty); |
1311 for (int i = 0; i < _max_num_q; i++) { |
1311 for (uint i = 0; i < _max_num_q; i++) { |
1312 if (yield->should_return()) { |
1312 if (yield->should_return()) { |
1313 return; |
1313 return; |
1314 } |
1314 } |
1315 preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive, |
1315 preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive, |
1316 keep_alive, complete_gc, yield); |
1316 keep_alive, complete_gc, yield); |
1319 |
1319 |
1320 // Phantom references |
1320 // Phantom references |
1321 { |
1321 { |
1322 TraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC, |
1322 TraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC, |
1323 false, gclog_or_tty); |
1323 false, gclog_or_tty); |
1324 for (int i = 0; i < _max_num_q; i++) { |
1324 for (uint i = 0; i < _max_num_q; i++) { |
1325 if (yield->should_return()) { |
1325 if (yield->should_return()) { |
1326 return; |
1326 return; |
1327 } |
1327 } |
1328 preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive, |
1328 preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive, |
1329 keep_alive, complete_gc, yield); |
1329 keep_alive, complete_gc, yield); |
1384 iter.removed(), iter.processed(), (address)refs_list.head()); |
1384 iter.removed(), iter.processed(), (address)refs_list.head()); |
1385 } |
1385 } |
1386 ) |
1386 ) |
1387 } |
1387 } |
1388 |
1388 |
1389 const char* ReferenceProcessor::list_name(int i) { |
1389 const char* ReferenceProcessor::list_name(uint i) { |
1390 assert(i >= 0 && i <= _max_num_q * number_of_subclasses_of_ref(), |
1390 assert(i >= 0 && i <= _max_num_q * number_of_subclasses_of_ref(), |
1391 "Out of bounds index"); |
1391 "Out of bounds index"); |
1392 |
1392 |
1393 int j = i / _max_num_q; |
1393 int j = i / _max_num_q; |
1394 switch (j) { |
1394 switch (j) { |