595 DiscoveredList refs_lists[],
596 bool clear_referent,
597 bool marks_oops_alive,
598 ReferenceProcessorPhaseTimes* phase_times)
599 : ProcessTask(ref_processor, refs_lists, marks_oops_alive, phase_times),
600 _clear_referent(clear_referent)
601 { }
602 virtual void work(unsigned int i, BoolObjectClosure& is_alive,
603 OopClosure& keep_alive,
604 VoidClosure& complete_gc)
605 {
606 RefProcWorkerTimeTracker tt(ReferenceProcessorPhaseTimes::RefPhase3, _phase_times, i);
607
608 _ref_processor.process_phase3(_refs_lists[i], _clear_referent,
609 &is_alive, &keep_alive, &complete_gc);
610 }
611 private:
612 bool _clear_referent;
613 };
614
615 #ifndef PRODUCT
616 void ReferenceProcessor::log_reflist_counts(DiscoveredList ref_lists[], uint active_length, size_t total_refs) {
617 if (!log_is_enabled(Trace, gc, ref)) {
618 return;
619 }
620
621 stringStream st;
622 for (uint i = 0; i < active_length; ++i) {
623 st.print(SIZE_FORMAT " ", ref_lists[i].length());
624 }
625 log_develop_trace(gc, ref)("%s= " SIZE_FORMAT, st.as_string(), total_refs);
626 #ifdef ASSERT
627 for (uint i = active_length; i < _max_num_queues; i++) {
628 assert(ref_lists[i].length() == 0, SIZE_FORMAT " unexpected References in %u",
629 ref_lists[i].length(), i);
630 }
631 #endif
632 }
633 #endif
634
635 void ReferenceProcessor::set_active_mt_degree(uint v) {
636 _num_queues = v;
637 _next_id = 0;
638 }
639
640 // Balances reference queues.
641 // Move entries from all queues[0, 1, ..., _max_num_q-1] to
642 // queues[0, 1, ..., _num_q-1] because only the first _num_q
643 // corresponding to the active workers will be processed.
644 void ReferenceProcessor::balance_queues(DiscoveredList ref_lists[])
645 {
646 // calculate total length
647 size_t total_refs = 0;
648 log_develop_trace(gc, ref)("Balance ref_lists ");
649
650 for (uint i = 0; i < _max_num_queues; ++i) {
651 total_refs += ref_lists[i].length();
652 }
653 log_reflist_counts(ref_lists, _max_num_queues, total_refs);
654 size_t avg_refs = total_refs / _num_queues + 1;
655 uint to_idx = 0;
656 for (uint from_idx = 0; from_idx < _max_num_queues; from_idx++) {
657 bool move_all = false;
658 if (from_idx >= _num_queues) {
659 move_all = ref_lists[from_idx].length() > 0;
660 }
661 while ((ref_lists[from_idx].length() > avg_refs) ||
662 move_all) {
663 assert(to_idx < _num_queues, "Sanity Check!");
664 if (ref_lists[to_idx].length() < avg_refs) {
665 // move superfluous refs
666 size_t refs_to_move;
667 // Move all the Ref's if the from queue will not be processed.
668 if (move_all) {
669 refs_to_move = MIN2(ref_lists[from_idx].length(),
670 avg_refs - ref_lists[to_idx].length());
671 } else {
672 refs_to_move = MIN2(ref_lists[from_idx].length() - avg_refs,
673 avg_refs - ref_lists[to_idx].length());
694 ref_lists[to_idx].set_head(move_head);
695 ref_lists[to_idx].inc_length(refs_to_move);
696
697 // Remove the chain from the from list.
698 if (move_tail == new_head) {
699 // We found the end of the from list.
700 ref_lists[from_idx].set_head(NULL);
701 } else {
702 ref_lists[from_idx].set_head(new_head);
703 }
704 ref_lists[from_idx].dec_length(refs_to_move);
705 if (ref_lists[from_idx].length() == 0) {
706 break;
707 }
708 } else {
709 to_idx = (to_idx + 1) % _num_queues;
710 }
711 }
712 }
713 #ifdef ASSERT
714 size_t balanced_total_refs = 0;
715 for (uint i = 0; i < _num_queues; ++i) {
716 balanced_total_refs += ref_lists[i].length();
717 }
718 log_reflist_counts(ref_lists, _num_queues, balanced_total_refs);
719 assert(total_refs == balanced_total_refs, "Balancing was incomplete");
720 #endif
721 }
722
723 void ReferenceProcessor::process_discovered_reflist(
724 DiscoveredList refs_lists[],
725 ReferencePolicy* policy,
726 bool clear_referent,
727 BoolObjectClosure* is_alive,
728 OopClosure* keep_alive,
729 VoidClosure* complete_gc,
730 AbstractRefProcTaskExecutor* task_executor,
731 ReferenceProcessorPhaseTimes* phase_times)
732 {
733 bool mt_processing = task_executor != NULL && _processing_is_mt;
734
735 phase_times->set_processing_is_mt(mt_processing);
736
737 if (mt_processing && ParallelRefProcBalancingEnabled) {
738 RefProcBalanceQueuesTimeTracker tt(phase_times);
1013 RawAccess<>::oop_store(discovered_addr, next_discovered);
1014 list->set_head(obj);
1015 list->inc_length(1);
1016
1017 log_develop_trace(gc, ref)("Discovered reference (" INTPTR_FORMAT ": %s)", p2i(obj), obj->klass()->internal_name());
1018 }
1019 assert(oopDesc::is_oop(obj), "Discovered a bad reference");
1020 verify_referent(obj);
1021 return true;
1022 }
1023
1024 bool ReferenceProcessor::has_discovered_references() {
1025 for (uint i = 0; i < _max_num_queues * number_of_subclasses_of_ref(); i++) {
1026 if (!_discovered_refs[i].is_empty()) {
1027 return true;
1028 }
1029 }
1030 return false;
1031 }
1032
1033 // Preclean the discovered references by removing those
1034 // whose referents are alive, and by marking from those that
1035 // are not active. These lists can be handled here
1036 // in any order and, indeed, concurrently.
1037 void ReferenceProcessor::preclean_discovered_references(
1038 BoolObjectClosure* is_alive,
1039 OopClosure* keep_alive,
1040 VoidClosure* complete_gc,
1041 YieldClosure* yield,
1042 GCTimer* gc_timer) {
1043
1044 // Soft references
1045 {
1046 GCTraceTime(Debug, gc, ref) tm("Preclean SoftReferences", gc_timer);
1047 for (uint i = 0; i < _max_num_queues; i++) {
1048 if (yield->should_return()) {
1049 return;
1050 }
1051 preclean_discovered_reflist(_discoveredSoftRefs[i], is_alive,
1052 keep_alive, complete_gc, yield);
1053 }
1054 }
1055
1056 // Weak references
1057 {
1058 GCTraceTime(Debug, gc, ref) tm("Preclean WeakReferences", gc_timer);
1059 for (uint i = 0; i < _max_num_queues; i++) {
1060 if (yield->should_return()) {
1061 return;
1062 }
1063 preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive,
1064 keep_alive, complete_gc, yield);
1065 }
1066 }
1067
1068 // Final references
1069 {
1070 GCTraceTime(Debug, gc, ref) tm("Preclean FinalReferences", gc_timer);
1071 for (uint i = 0; i < _max_num_queues; i++) {
1072 if (yield->should_return()) {
1073 return;
1074 }
1075 preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive,
1076 keep_alive, complete_gc, yield);
1077 }
1078 }
1079
1080 // Phantom references
1081 {
1082 GCTraceTime(Debug, gc, ref) tm("Preclean PhantomReferences", gc_timer);
1083 for (uint i = 0; i < _max_num_queues; i++) {
1084 if (yield->should_return()) {
1085 return;
1086 }
1087 preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive,
1088 keep_alive, complete_gc, yield);
1089 }
1090 }
1091 }
1092
1093 // Walk the given discovered ref list, and remove all reference objects
1094 // whose referents are still alive, whose referents are NULL or which
1095 // are not active (have a non-NULL next field). NOTE: When we are
1096 // thus precleaning the ref lists (which happens single-threaded today),
1097 // we do not disable refs discovery to honor the correct semantics of
1098 // java.lang.Reference. As a result, we need to be careful below
1099 // that ref removal steps interleave safely with ref discovery steps
1100 // (in this thread).
1101 void
1102 ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list,
1103 BoolObjectClosure* is_alive,
1104 OopClosure* keep_alive,
1105 VoidClosure* complete_gc,
1106 YieldClosure* yield) {
1107 DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
1108 while (iter.has_next()) {
1109 iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
1110 oop obj = iter.obj();
1111 oop next = java_lang_ref_Reference::next(obj);
1112 if (iter.referent() == NULL || iter.is_referent_alive() ||
1113 next != NULL) {
1114 // The referent has been cleared, or is alive, or the Reference is not
1115 // active; we need to trace and mark its cohort.
1116 log_develop_trace(gc, ref)("Precleaning Reference (" INTPTR_FORMAT ": %s)",
1117 p2i(iter.obj()), iter.obj()->klass()->internal_name());
1118 // Remove Reference object from list
1119 iter.remove();
1120 // Keep alive its cohort.
1121 iter.make_referent_alive();
1122 if (UseCompressedOops) {
1123 narrowOop* next_addr = (narrowOop*)java_lang_ref_Reference::next_addr_raw(obj);
1124 keep_alive->do_oop(next_addr);
1125 } else {
1126 oop* next_addr = (oop*)java_lang_ref_Reference::next_addr_raw(obj);
1127 keep_alive->do_oop(next_addr);
1128 }
1129 iter.move_to_next();
1130 } else {
1131 iter.next();
1132 }
1133 }
1134 // Close the reachable set
1135 complete_gc->do_void();
1136
1137 NOT_PRODUCT(
1138 if (iter.processed() > 0) {
1139 log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " Refs out of " SIZE_FORMAT " Refs in discovered list " INTPTR_FORMAT,
1140 iter.removed(), iter.processed(), p2i(&refs_list));
1141 }
1142 )
1143 }
1144
1145 const char* ReferenceProcessor::list_name(uint i) {
1146 assert(i <= _max_num_queues * number_of_subclasses_of_ref(),
1147 "Out of bounds index");
1148
1149 int j = i / _max_num_queues;
1150 switch (j) {
1151 case 0: return "SoftRef";
1152 case 1: return "WeakRef";
1153 case 2: return "FinalRef";
1154 case 3: return "PhantomRef";
1155 }
1156 ShouldNotReachHere();
1157 return NULL;
1158 }
|
595 DiscoveredList refs_lists[],
596 bool clear_referent,
597 bool marks_oops_alive,
598 ReferenceProcessorPhaseTimes* phase_times)
599 : ProcessTask(ref_processor, refs_lists, marks_oops_alive, phase_times),
600 _clear_referent(clear_referent)
601 { }
602 virtual void work(unsigned int i, BoolObjectClosure& is_alive,
603 OopClosure& keep_alive,
604 VoidClosure& complete_gc)
605 {
606 RefProcWorkerTimeTracker tt(ReferenceProcessorPhaseTimes::RefPhase3, _phase_times, i);
607
608 _ref_processor.process_phase3(_refs_lists[i], _clear_referent,
609 &is_alive, &keep_alive, &complete_gc);
610 }
611 private:
612 bool _clear_referent;
613 };
614
615 void ReferenceProcessor::log_reflist(const char* prefix, DiscoveredList list[], uint num_active_queues) {
616 LogTarget(Trace, gc, ref) lt;
617
618 if (!lt.is_enabled()) {
619 return;
620 }
621
622 size_t total = 0;
623
624 LogStream ls(lt);
625 ls.print("%s", prefix);
626 for (uint i = 0; i < num_active_queues; i++) {
627 ls.print(SIZE_FORMAT " ", list[i].length());
628 total += list[i].length();
629 }
630 ls.print_cr("(" SIZE_FORMAT ")", total);
631 }
632
633 #ifndef PRODUCT
634 void ReferenceProcessor::log_reflist_counts(DiscoveredList ref_lists[], uint num_active_queues) {
635 if (!log_is_enabled(Trace, gc, ref)) {
636 return;
637 }
638
639 log_reflist("", ref_lists, num_active_queues);
640 #ifdef ASSERT
641 for (uint i = num_active_queues; i < _max_num_queues; i++) {
642 assert(ref_lists[i].length() == 0, SIZE_FORMAT " unexpected References in %u",
643 ref_lists[i].length(), i);
644 }
645 #endif
646 }
647 #endif
648
649 void ReferenceProcessor::set_active_mt_degree(uint v) {
650 _num_queues = v;
651 _next_id = 0;
652 }
653
654 // Balances reference queues.
655 // Move entries from all queues[0, 1, ..., _max_num_q-1] to
656 // queues[0, 1, ..., _num_q-1] because only the first _num_q
657 // corresponding to the active workers will be processed.
658 void ReferenceProcessor::balance_queues(DiscoveredList ref_lists[])
659 {
660 // calculate total length
661 size_t total_refs = 0;
662 log_develop_trace(gc, ref)("Balance ref_lists ");
663
664 log_reflist_counts(ref_lists, _max_num_queues);
665
666 for (uint i = 0; i < _max_num_queues; ++i) {
667 total_refs += ref_lists[i].length();
668 }
669 size_t avg_refs = total_refs / _num_queues + 1;
670 uint to_idx = 0;
671 for (uint from_idx = 0; from_idx < _max_num_queues; from_idx++) {
672 bool move_all = false;
673 if (from_idx >= _num_queues) {
674 move_all = ref_lists[from_idx].length() > 0;
675 }
676 while ((ref_lists[from_idx].length() > avg_refs) ||
677 move_all) {
678 assert(to_idx < _num_queues, "Sanity Check!");
679 if (ref_lists[to_idx].length() < avg_refs) {
680 // move superfluous refs
681 size_t refs_to_move;
682 // Move all the Ref's if the from queue will not be processed.
683 if (move_all) {
684 refs_to_move = MIN2(ref_lists[from_idx].length(),
685 avg_refs - ref_lists[to_idx].length());
686 } else {
687 refs_to_move = MIN2(ref_lists[from_idx].length() - avg_refs,
688 avg_refs - ref_lists[to_idx].length());
709 ref_lists[to_idx].set_head(move_head);
710 ref_lists[to_idx].inc_length(refs_to_move);
711
712 // Remove the chain from the from list.
713 if (move_tail == new_head) {
714 // We found the end of the from list.
715 ref_lists[from_idx].set_head(NULL);
716 } else {
717 ref_lists[from_idx].set_head(new_head);
718 }
719 ref_lists[from_idx].dec_length(refs_to_move);
720 if (ref_lists[from_idx].length() == 0) {
721 break;
722 }
723 } else {
724 to_idx = (to_idx + 1) % _num_queues;
725 }
726 }
727 }
728 #ifdef ASSERT
729 log_reflist_counts(ref_lists, _num_queues);
730 size_t balanced_total_refs = 0;
731 for (uint i = 0; i < _num_queues; ++i) {
732 balanced_total_refs += ref_lists[i].length();
733 }
734 assert(total_refs == balanced_total_refs, "Balancing was incomplete");
735 #endif
736 }
737
738 void ReferenceProcessor::process_discovered_reflist(
739 DiscoveredList refs_lists[],
740 ReferencePolicy* policy,
741 bool clear_referent,
742 BoolObjectClosure* is_alive,
743 OopClosure* keep_alive,
744 VoidClosure* complete_gc,
745 AbstractRefProcTaskExecutor* task_executor,
746 ReferenceProcessorPhaseTimes* phase_times)
747 {
748 bool mt_processing = task_executor != NULL && _processing_is_mt;
749
750 phase_times->set_processing_is_mt(mt_processing);
751
752 if (mt_processing && ParallelRefProcBalancingEnabled) {
753 RefProcBalanceQueuesTimeTracker tt(phase_times);
1028 RawAccess<>::oop_store(discovered_addr, next_discovered);
1029 list->set_head(obj);
1030 list->inc_length(1);
1031
1032 log_develop_trace(gc, ref)("Discovered reference (" INTPTR_FORMAT ": %s)", p2i(obj), obj->klass()->internal_name());
1033 }
1034 assert(oopDesc::is_oop(obj), "Discovered a bad reference");
1035 verify_referent(obj);
1036 return true;
1037 }
1038
1039 bool ReferenceProcessor::has_discovered_references() {
1040 for (uint i = 0; i < _max_num_queues * number_of_subclasses_of_ref(); i++) {
1041 if (!_discovered_refs[i].is_empty()) {
1042 return true;
1043 }
1044 }
1045 return false;
1046 }
1047
1048 void ReferenceProcessor::preclean_discovered_references(BoolObjectClosure* is_alive,
1049 OopClosure* keep_alive,
1050 VoidClosure* complete_gc,
1051 YieldClosure* yield,
1052 GCTimer* gc_timer) {
1053 // These lists can be handled here in any order and, indeed, concurrently.
1054
1055 // Soft references
1056 {
1057 GCTraceTime(Debug, gc, ref) tm("Preclean SoftReferences", gc_timer);
1058 log_reflist("SoftRef before: ", _discoveredSoftRefs, _max_num_queues);
1059 for (uint i = 0; i < _max_num_queues; i++) {
1060 if (yield->should_return()) {
1061 return;
1062 }
1063 if (preclean_discovered_reflist(_discoveredSoftRefs[i], is_alive,
1064 keep_alive, complete_gc, yield)) {
1065 log_reflist("SoftRef abort: ", _discoveredSoftRefs, _max_num_queues);
1066 return;
1067 }
1068 }
1069 log_reflist("SoftRef after: ", _discoveredSoftRefs, _max_num_queues);
1070 }
1071
1072 // Weak references
1073 {
1074 GCTraceTime(Debug, gc, ref) tm("Preclean WeakReferences", gc_timer);
1075 log_reflist("WeakRef before: ", _discoveredWeakRefs, _max_num_queues);
1076 for (uint i = 0; i < _max_num_queues; i++) {
1077 if (yield->should_return()) {
1078 return;
1079 }
1080 if (preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive,
1081 keep_alive, complete_gc, yield)) {
1082 log_reflist("WeakRef abort: ", _discoveredWeakRefs, _max_num_queues);
1083 return;
1084 }
1085 }
1086 log_reflist("WeakRef after: ", _discoveredWeakRefs, _max_num_queues);
1087 }
1088
1089 // Final references
1090 {
1091 GCTraceTime(Debug, gc, ref) tm("Preclean FinalReferences", gc_timer);
1092 log_reflist("FinalRef before: ", _discoveredFinalRefs, _max_num_queues);
1093 for (uint i = 0; i < _max_num_queues; i++) {
1094 if (yield->should_return()) {
1095 return;
1096 }
1097 if (preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive,
1098 keep_alive, complete_gc, yield)) {
1099 log_reflist("FinalRef abort: ", _discoveredFinalRefs, _max_num_queues);
1100 return;
1101 }
1102 }
1103 log_reflist("FinalRef after: ", _discoveredFinalRefs, _max_num_queues);
1104 }
1105
1106 // Phantom references
1107 {
1108 GCTraceTime(Debug, gc, ref) tm("Preclean PhantomReferences", gc_timer);
1109 log_reflist("PhantomRef before: ", _discoveredPhantomRefs, _max_num_queues);
1110 for (uint i = 0; i < _max_num_queues; i++) {
1111 if (yield->should_return()) {
1112 return;
1113 }
1114 if (preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive,
1115 keep_alive, complete_gc, yield)) {
1116 log_reflist("PhantomRef abort: ", _discoveredPhantomRefs, _max_num_queues);
1117 return;
1118 }
1119 }
1120 log_reflist("PhantomRef after: ", _discoveredPhantomRefs, _max_num_queues);
1121 }
1122 }
1123
1124 // Walk the given discovered ref list, and remove all reference objects
1125 // whose referents are still alive, whose referents are NULL or which
1126 // are not active (have a non-NULL next field). NOTE: When we are
1127 // thus precleaning the ref lists (which happens single-threaded today),
1128 // we do not disable refs discovery to honor the correct semantics of
1129 // java.lang.Reference. As a result, we need to be careful below
1130 // that ref removal steps interleave safely with ref discovery steps
1131 // (in this thread).
1132 bool ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list,
1133 BoolObjectClosure* is_alive,
1134 OopClosure* keep_alive,
1135 VoidClosure* complete_gc,
1136 YieldClosure* yield) {
1137 DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
1138 while (iter.has_next()) {
1139 if (yield->should_return_fine_grain()) {
1140 return true;
1141 }
1142 iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
1143 oop obj = iter.obj();
1144 oop next = java_lang_ref_Reference::next(obj);
1145 if (iter.referent() == NULL || iter.is_referent_alive() || next != NULL) {
1146 // The referent has been cleared, or is alive, or the Reference is not
1147 // active; we need to trace and mark its cohort.
1148 log_develop_trace(gc, ref)("Precleaning Reference (" INTPTR_FORMAT ": %s)",
1149 p2i(iter.obj()), iter.obj()->klass()->internal_name());
1150 // Remove Reference object from list
1151 iter.remove();
1152 // Keep alive its cohort.
1153 iter.make_referent_alive();
1154 if (UseCompressedOops) {
1155 narrowOop* next_addr = (narrowOop*)java_lang_ref_Reference::next_addr_raw(obj);
1156 keep_alive->do_oop(next_addr);
1157 } else {
1158 oop* next_addr = (oop*)java_lang_ref_Reference::next_addr_raw(obj);
1159 keep_alive->do_oop(next_addr);
1160 }
1161 iter.move_to_next();
1162 } else {
1163 iter.next();
1164 }
1165 }
1166 // Close the reachable set
1167 complete_gc->do_void();
1168
1169 NOT_PRODUCT(
1170 if (iter.processed() > 0) {
1171 log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " Refs out of " SIZE_FORMAT " Refs in discovered list " INTPTR_FORMAT,
1172 iter.removed(), iter.processed(), p2i(&refs_list));
1173 }
1174 )
1175 return false;
1176 }
1177
1178 const char* ReferenceProcessor::list_name(uint i) {
1179 assert(i <= _max_num_queues * number_of_subclasses_of_ref(),
1180 "Out of bounds index");
1181
1182 int j = i / _max_num_queues;
1183 switch (j) {
1184 case 0: return "SoftRef";
1185 case 1: return "WeakRef";
1186 case 2: return "FinalRef";
1187 case 3: return "PhantomRef";
1188 }
1189 ShouldNotReachHere();
1190 return NULL;
1191 }
|