31 DiscoveredList() : _len(0), _compressed_head(0), _oop_head(NULL) { }
32 oop head() const {
33 return UseCompressedOops ? oopDesc::decode_heap_oop_not_null(_compressed_head) :
34 _oop_head;
35 }
36 HeapWord* adr_head() {
37 return UseCompressedOops ? (HeapWord*)&_compressed_head :
38 (HeapWord*)&_oop_head;
39 }
40 void set_head(oop o) {
41 if (UseCompressedOops) {
42 // Must compress the head ptr.
43 _compressed_head = oopDesc::encode_heap_oop_not_null(o);
44 } else {
45 _oop_head = o;
46 }
47 }
48 bool empty() const { return head() == ReferenceProcessor::sentinel_ref(); }
49 size_t length() { return _len; }
50 void set_length(size_t len) { _len = len; }
51 private:
52 // Set value depending on UseCompressedOops. This could be a template class
53 // but then we have to fix all the instantiations and declarations that use this class.
54 oop _oop_head;
55 narrowOop _compressed_head;
56 size_t _len;
57 };
58
59 oop ReferenceProcessor::_sentinelRef = NULL;
60
61 const int subclasses_of_ref = REF_PHANTOM - REF_OTHER;
62
63 void referenceProcessor_init() {
64 ReferenceProcessor::init_statics();
65 }
66
67 void ReferenceProcessor::init_statics() {
68 assert(_sentinelRef == NULL, "should be initialized precisely once");
69 EXCEPTION_MARK;
70 _sentinelRef = instanceKlass::cast(
419 inline DiscoveredListIterator(DiscoveredList& refs_list,
420 OopClosure* keep_alive,
421 BoolObjectClosure* is_alive);
422
423 // End Of List.
424 inline bool has_next() const { return _next != ReferenceProcessor::sentinel_ref(); }
425
426 // Get oop to the Reference object.
427 inline oop obj() const { return _ref; }
428
429 // Get oop to the referent object.
430 inline oop referent() const { return _referent; }
431
432 // Returns true if referent is alive.
433 inline bool is_referent_alive() const;
434
435 // Loads data for the current reference.
436 // The "allow_null_referent" argument tells us to allow for the possibility
437 // of a NULL referent in the discovered Reference object. This typically
438 // happens in the case of concurrent collectors that may have done the
439 // discovery concurrently or interleaved with mutator execution.
440 inline void load_ptrs(DEBUG_ONLY(bool allow_null_referent));
441
442 // Move to the next discovered reference.
443 inline void next();
444
445 // Remove the current reference from the list and move to the next.
446 inline void remove();
447
448 // Make the Reference object active again.
449 inline void make_active() { java_lang_ref_Reference::set_next(_ref, NULL); }
450
451 // Make the referent alive.
452 inline void make_referent_alive() {
453 if (UseCompressedOops) {
454 _keep_alive->do_oop((narrowOop*)_referent_addr);
455 } else {
456 _keep_alive->do_oop((oop*)_referent_addr);
457 }
458 }
459
460 // Update the discovered field.
461 inline void update_discovered() {
462 // First _prev_next ref actually points into DiscoveredList (gross).
463 if (UseCompressedOops) {
464 _keep_alive->do_oop((narrowOop*)_prev_next);
465 } else {
466 _keep_alive->do_oop((oop*)_prev_next);
467 }
468 }
469
470 // NULL out referent pointer.
471 inline void clear_referent() { oop_store_raw(_referent_addr, NULL); }
472
473 // Statistics
474 NOT_PRODUCT(
475 inline size_t processed() const { return _processed; }
476 inline size_t removed() const { return _removed; }
477 )
478
479 private:
480 inline void move_to_next();
481
482 private:
483 DiscoveredList& _refs_list;
484 HeapWord* _prev_next;
485 oop _ref;
486 HeapWord* _discovered_addr;
487 oop _next;
488 HeapWord* _referent_addr;
489 oop _referent;
490 OopClosure* _keep_alive;
491 BoolObjectClosure* _is_alive;
492 DEBUG_ONLY(
493 oop _first_seen; // cyclic linked list check
494 )
495 NOT_PRODUCT(
496 size_t _processed;
497 size_t _removed;
498 )
499 };
536 "bad referent");
537 }
538
539 inline void DiscoveredListIterator::next() {
540 _prev_next = _discovered_addr;
541 move_to_next();
542 }
543
544 inline void DiscoveredListIterator::remove() {
545 assert(_ref->is_oop(), "Dropping a bad reference");
546 oop_store_raw(_discovered_addr, NULL);
547 // First _prev_next ref actually points into DiscoveredList (gross).
548 if (UseCompressedOops) {
549 // Remove Reference object from list.
550 oopDesc::encode_store_heap_oop_not_null((narrowOop*)_prev_next, _next);
551 } else {
552 // Remove Reference object from list.
553 oopDesc::store_heap_oop((oop*)_prev_next, _next);
554 }
555 NOT_PRODUCT(_removed++);
556 move_to_next();
557 }
558
559 inline void DiscoveredListIterator::move_to_next() {
560 _ref = _next;
561 assert(_ref != _first_seen, "cyclic ref_list found");
562 NOT_PRODUCT(_processed++);
563 }
564
565 // NOTE: process_phase*() are largely similar, and at a high level
566 // merely iterate over the extant list applying a predicate to
567 // each of its elements and possibly removing that element from the
568 // list and applying some further closures to that element.
569 // We should consider the possibility of replacing these
570 // process_phase*() methods by abstracting them into
571 // a single general iterator invocation that receives appropriate
572 // closures that accomplish this work.
573
574 // (SoftReferences only) Traverse the list and remove any SoftReferences whose
575 // referents are not alive, but that should be kept alive for policy reasons.
576 // Keep alive the transitive closure of all such referents.
577 void
578 ReferenceProcessor::process_phase1(DiscoveredList& refs_list,
579 ReferencePolicy* policy,
580 BoolObjectClosure* is_alive,
581 OopClosure* keep_alive,
582 VoidClosure* complete_gc) {
583 assert(policy != NULL, "Must have a non-NULL policy");
584 DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
585 // Decide which softly reachable refs should be kept alive.
586 while (iter.has_next()) {
587 iter.load_ptrs(DEBUG_ONLY(!discovery_is_atomic() /* allow_null_referent */));
588 bool referent_is_dead = (iter.referent() != NULL) && !iter.is_referent_alive();
589 if (referent_is_dead && !policy->should_clear_reference(iter.obj())) {
590 if (TraceReferenceGC) {
591 gclog_or_tty->print_cr("Dropping reference (" INTPTR_FORMAT ": %s" ") by policy",
592 iter.obj(), iter.obj()->blueprint()->internal_name());
593 }
594 // Make the Reference object active again
595 iter.make_active();
596 // keep the referent around
597 iter.make_referent_alive();
598 // Remove Reference object from list
599 iter.remove();
600 } else {
601 iter.next();
602 }
603 }
604 // Close the reachable set
605 complete_gc->do_void();
606 NOT_PRODUCT(
607 if (PrintGCDetails && TraceReferenceGC) {
608 gclog_or_tty->print(" Dropped %d dead Refs out of %d "
609 "discovered Refs by policy ", iter.removed(), iter.processed());
610 }
611 )
612 }
613
614 // Traverse the list and remove any Refs that are not active, or
615 // whose referents are either alive or NULL.
616 void
617 ReferenceProcessor::pp2_work(DiscoveredList& refs_list,
618 BoolObjectClosure* is_alive,
619 OopClosure* keep_alive) {
620 assert(discovery_is_atomic(), "Error");
621 DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
622 while (iter.has_next()) {
623 iter.load_ptrs(DEBUG_ONLY(false /* allow_null_referent */));
624 DEBUG_ONLY(oop next = java_lang_ref_Reference::next(iter.obj());)
625 assert(next == NULL, "Should not discover inactive Reference");
626 if (iter.is_referent_alive()) {
627 if (TraceReferenceGC) {
628 gclog_or_tty->print_cr("Dropping strongly reachable reference (" INTPTR_FORMAT ": %s)",
629 iter.obj(), iter.obj()->blueprint()->internal_name());
630 }
631 // The referent is reachable after all.
632 // Update the referent pointer as necessary: Note that this
633 // should not entail any recursive marking because the
634 // referent must already have been traversed.
635 iter.make_referent_alive();
636 // Remove Reference object from list
637 iter.remove();
638 } else {
639 iter.next();
640 }
641 }
642 NOT_PRODUCT(
643 if (PrintGCDetails && TraceReferenceGC) {
644 gclog_or_tty->print(" Dropped %d active Refs out of %d "
645 "Refs in discovered list ", iter.removed(), iter.processed());
646 }
647 )
648 }
649
650 void
651 ReferenceProcessor::pp2_work_concurrent_discovery(DiscoveredList& refs_list,
652 BoolObjectClosure* is_alive,
653 OopClosure* keep_alive,
654 VoidClosure* complete_gc) {
655 assert(!discovery_is_atomic(), "Error");
656 DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
657 while (iter.has_next()) {
658 iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
659 HeapWord* next_addr = java_lang_ref_Reference::next_addr(iter.obj());
660 oop next = java_lang_ref_Reference::next(iter.obj());
661 if ((iter.referent() == NULL || iter.is_referent_alive() ||
662 next != NULL)) {
663 assert(next->is_oop_or_null(), "bad next field");
664 // Remove Reference object from list
665 iter.remove();
666 // Trace the cohorts
667 iter.make_referent_alive();
668 if (UseCompressedOops) {
669 keep_alive->do_oop((narrowOop*)next_addr);
670 } else {
671 keep_alive->do_oop((oop*)next_addr);
672 }
673 } else {
674 iter.next();
675 }
676 }
677 // Now close the newly reachable set
678 complete_gc->do_void();
679 NOT_PRODUCT(
680 if (PrintGCDetails && TraceReferenceGC) {
681 gclog_or_tty->print(" Dropped %d active Refs out of %d "
682 "Refs in discovered list ", iter.removed(), iter.processed());
683 }
684 )
685 }
686
687 // Traverse the list and process the referents, by either
688 // clearing them or keeping them (and their reachable
689 // closure) alive.
690 void
691 ReferenceProcessor::process_phase3(DiscoveredList& refs_list,
692 bool clear_referent,
815 size_t avg_refs = total_refs / _num_q + 1;
816 int to_idx = 0;
817 for (int from_idx = 0; from_idx < _num_q; from_idx++) {
818 while (ref_lists[from_idx].length() > avg_refs) {
819 assert(to_idx < _num_q, "Sanity Check!");
820 if (ref_lists[to_idx].length() < avg_refs) {
821 // move superfluous refs
822 size_t refs_to_move =
823 MIN2(ref_lists[from_idx].length() - avg_refs,
824 avg_refs - ref_lists[to_idx].length());
825 oop move_head = ref_lists[from_idx].head();
826 oop move_tail = move_head;
827 oop new_head = move_head;
828 // find an element to split the list on
829 for (size_t j = 0; j < refs_to_move; ++j) {
830 move_tail = new_head;
831 new_head = java_lang_ref_Reference::discovered(new_head);
832 }
833 java_lang_ref_Reference::set_discovered(move_tail, ref_lists[to_idx].head());
834 ref_lists[to_idx].set_head(move_head);
835 ref_lists[to_idx].set_length(ref_lists[to_idx].length() + refs_to_move);
836 ref_lists[from_idx].set_head(new_head);
837 ref_lists[from_idx].set_length(ref_lists[from_idx].length() - refs_to_move);
838 } else {
839 ++to_idx;
840 }
841 }
842 }
843 }
844
845 void
846 ReferenceProcessor::process_discovered_reflist(
847 DiscoveredList refs_lists[],
848 ReferencePolicy* policy,
849 bool clear_referent,
850 BoolObjectClosure* is_alive,
851 OopClosure* keep_alive,
852 VoidClosure* complete_gc,
853 AbstractRefProcTaskExecutor* task_executor)
854 {
855 bool mt = task_executor != NULL && _processing_is_mt;
856 if (mt && ParallelRefProcBalancingEnabled) {
857 balance_queues(refs_lists);
906 is_alive, keep_alive, complete_gc);
907 }
908 }
909 }
910
911 void ReferenceProcessor::clean_up_discovered_references() {
912 // loop over the lists
913 for (int i = 0; i < _num_q * subclasses_of_ref; i++) {
914 if (TraceReferenceGC && PrintGCDetails && ((i % _num_q) == 0)) {
915 gclog_or_tty->print_cr(
916 "\nScrubbing %s discovered list of Null referents",
917 list_name(i));
918 }
919 clean_up_discovered_reflist(_discoveredSoftRefs[i]);
920 }
921 }
922
923 void ReferenceProcessor::clean_up_discovered_reflist(DiscoveredList& refs_list) {
924 assert(!discovery_is_atomic(), "Else why call this method?");
925 DiscoveredListIterator iter(refs_list, NULL, NULL);
926 size_t length = refs_list.length();
927 while (iter.has_next()) {
928 iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
929 oop next = java_lang_ref_Reference::next(iter.obj());
930 assert(next->is_oop_or_null(), "bad next field");
931 // If referent has been cleared or Reference is not active,
932 // drop it.
933 if (iter.referent() == NULL || next != NULL) {
934 debug_only(
935 if (PrintGCDetails && TraceReferenceGC) {
936 gclog_or_tty->print_cr("clean_up_discovered_list: Dropping Reference: "
937 INTPTR_FORMAT " with next field: " INTPTR_FORMAT
938 " and referent: " INTPTR_FORMAT,
939 iter.obj(), next, iter.referent());
940 }
941 )
942 // Remove Reference object from list
943 iter.remove();
944 --length;
945 } else {
946 iter.next();
947 }
948 }
949 refs_list.set_length(length);
950 NOT_PRODUCT(
951 if (PrintGCDetails && TraceReferenceGC) {
952 gclog_or_tty->print(
953 " Removed %d Refs with NULL referents out of %d discovered Refs",
954 iter.removed(), iter.processed());
955 }
956 )
957 }
958
959 inline DiscoveredList* ReferenceProcessor::get_discovered_list(ReferenceType rt) {
960 int id = 0;
961 // Determine the queue index to use for this object.
962 if (_discovery_is_mt) {
963 // During a multi-threaded discovery phase,
964 // each thread saves to its "own" list.
965 Thread* thr = Thread::current();
966 assert(thr->is_GC_task_thread(),
967 "Dubious cast from Thread* to WorkerThread*?");
968 id = ((WorkerThread*)thr)->id();
969 } else {
1007 HeapWord* discovered_addr) {
1008 assert(_discovery_is_mt, "!_discovery_is_mt should have been handled by caller");
1009 // First we must make sure this object is only enqueued once. CAS in a non null
1010 // discovered_addr.
1011 oop current_head = refs_list.head();
1012
1013 // Note: In the case of G1, this pre-barrier is strictly
1014 // not necessary because the only case we are interested in
1015 // here is when *discovered_addr is NULL, so this will expand to
1016 // nothing. As a result, I am just manually eliding this out for G1.
1017 if (_discovered_list_needs_barrier && !UseG1GC) {
1018 _bs->write_ref_field_pre((void*)discovered_addr, current_head); guarantee(false, "Needs to be fixed: YSR");
1019 }
1020 oop retest = oopDesc::atomic_compare_exchange_oop(current_head, discovered_addr,
1021 NULL);
1022 if (retest == NULL) {
1023 // This thread just won the right to enqueue the object.
1024 // We have separate lists for enqueueing so no synchronization
1025 // is necessary.
1026 refs_list.set_head(obj);
1027 refs_list.set_length(refs_list.length() + 1);
1028 if (_discovered_list_needs_barrier) {
1029 _bs->write_ref_field((void*)discovered_addr, current_head); guarantee(false, "Needs to be fixed: YSR");
1030 }
1031
1032 } else {
1033 // If retest was non NULL, another thread beat us to it:
1034 // The reference has already been discovered...
1035 if (TraceReferenceGC) {
1036 gclog_or_tty->print_cr("Already enqueued reference (" INTPTR_FORMAT ": %s)",
1037 obj, obj->blueprint()->internal_name());
1038 }
1039 }
1040 }
1041
1042 // We mention two of several possible choices here:
1043 // #0: if the reference object is not in the "originating generation"
1044 // (or part of the heap being collected, indicated by our "span"
1045 // we don't treat it specially (i.e. we scan it as we would
1046 // a normal oop, treating its references as strong references).
1047 // This means that references can't be enqueued unless their
1151
1152 if (_discovery_is_mt) {
1153 add_to_discovered_list_mt(*list, obj, discovered_addr);
1154 } else {
1155 // If "_discovered_list_needs_barrier", we do write barriers when
1156 // updating the discovered reference list. Otherwise, we do a raw store
1157 // here: the field will be visited later when processing the discovered
1158 // references.
1159 oop current_head = list->head();
1160 // As in the case further above, since we are over-writing a NULL
1161 // pre-value, we can safely elide the pre-barrier here for the case of G1.
1162 assert(discovered == NULL, "control point invariant");
1163 if (_discovered_list_needs_barrier && !UseG1GC) { // safe to elide for G1
1164 _bs->write_ref_field_pre((oop*)discovered_addr, current_head);
1165 }
1166 oop_store_raw(discovered_addr, current_head);
1167 if (_discovered_list_needs_barrier) {
1168 _bs->write_ref_field((oop*)discovered_addr, current_head);
1169 }
1170 list->set_head(obj);
1171 list->set_length(list->length() + 1);
1172 }
1173
1174 // In the MT discovery case, it is currently possible to see
1175 // the following message multiple times if several threads
1176 // discover a reference about the same time. Only one will
1177 // however have actually added it to the disocvered queue.
1178 // One could let add_to_discovered_list_mt() return an
1179 // indication for success in queueing (by 1 thread) or
1180 // failure (by all other threads), but I decided the extra
1181 // code was not worth the effort for something that is
1182 // only used for debugging support.
1183 if (TraceReferenceGC) {
1184 oop referent = java_lang_ref_Reference::referent(obj);
1185 if (PrintGCDetails) {
1186 gclog_or_tty->print_cr("Enqueued reference (" INTPTR_FORMAT ": %s)",
1187 obj, obj->blueprint()->internal_name());
1188 }
1189 assert(referent->is_oop(), "Enqueued a bad referent");
1190 }
1191 assert(obj->is_oop(), "Enqueued a bad reference");
1192 return true;
1193 }
1194
1195 // Preclean the discovered references by removing those
1196 // whose referents are alive, and by marking from those that
1197 // are not active. These lists can be handled here
1198 // in any order and, indeed, concurrently.
1199 void ReferenceProcessor::preclean_discovered_references(
1200 BoolObjectClosure* is_alive,
1201 OopClosure* keep_alive,
1202 VoidClosure* complete_gc,
1203 YieldClosure* yield) {
1204
1205 NOT_PRODUCT(verify_ok_to_handle_reflists());
1206
1207 // Soft references
1208 {
1209 TraceTime tt("Preclean SoftReferences", PrintGCDetails && PrintReferenceGC,
1210 false, gclog_or_tty);
1211 for (int i = 0; i < _num_q; i++) {
1212 preclean_discovered_reflist(_discoveredSoftRefs[i], is_alive,
1213 keep_alive, complete_gc, yield);
1214 }
1215 }
1216 if (yield->should_return()) {
1217 return;
1218 }
1219
1220 // Weak references
1221 {
1222 TraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC,
1223 false, gclog_or_tty);
1224 for (int i = 0; i < _num_q; i++) {
1225 preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive,
1226 keep_alive, complete_gc, yield);
1227 }
1228 }
1229 if (yield->should_return()) {
1230 return;
1231 }
1232
1233 // Final references
1234 {
1235 TraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC,
1236 false, gclog_or_tty);
1237 for (int i = 0; i < _num_q; i++) {
1238 preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive,
1239 keep_alive, complete_gc, yield);
1240 }
1241 }
1242 if (yield->should_return()) {
1243 return;
1244 }
1245
1246 // Phantom references
1247 {
1248 TraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC,
1249 false, gclog_or_tty);
1250 for (int i = 0; i < _num_q; i++) {
1251 preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive,
1252 keep_alive, complete_gc, yield);
1253 }
1254 }
1255 }
1256
1257 // Walk the given discovered ref list, and remove all reference objects
1258 // whose referents are still alive, whose referents are NULL or which
1259 // are not active (have a non-NULL next field). NOTE: For this to work
1260 // correctly, refs discovery can not be happening concurrently with this
1261 // step.
1262 void
1263 ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list,
1264 BoolObjectClosure* is_alive,
1265 OopClosure* keep_alive,
1266 VoidClosure* complete_gc,
1267 YieldClosure* yield) {
1268 DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
1269 size_t length = refs_list.length();
1270 while (iter.has_next()) {
1271 iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
1272 oop obj = iter.obj();
1273 oop next = java_lang_ref_Reference::next(obj);
1274 if (iter.referent() == NULL || iter.is_referent_alive() ||
1275 next != NULL) {
1276 // The referent has been cleared, or is alive, or the Reference is not
1277 // active; we need to trace and mark its cohort.
1278 if (TraceReferenceGC) {
1279 gclog_or_tty->print_cr("Precleaning Reference (" INTPTR_FORMAT ": %s)",
1280 iter.obj(), iter.obj()->blueprint()->internal_name());
1281 }
1282 // Remove Reference object from list
1283 iter.remove();
1284 --length;
1285 // Keep alive its cohort.
1286 iter.make_referent_alive();
1287 if (UseCompressedOops) {
1288 narrowOop* next_addr = (narrowOop*)java_lang_ref_Reference::next_addr(obj);
1289 keep_alive->do_oop(next_addr);
1290 } else {
1291 oop* next_addr = (oop*)java_lang_ref_Reference::next_addr(obj);
1292 keep_alive->do_oop(next_addr);
1293 }
1294 } else {
1295 iter.next();
1296 }
1297 }
1298 refs_list.set_length(length);
1299
1300 // Close the reachable set
1301 complete_gc->do_void();
1302
1303 NOT_PRODUCT(
1304 if (PrintGCDetails && PrintReferenceGC) {
1305 gclog_or_tty->print(" Dropped %d Refs out of %d "
1306 "Refs in discovered list ", iter.removed(), iter.processed());
1307 }
1308 )
1309 }
1310
1311 const char* ReferenceProcessor::list_name(int i) {
1312 assert(i >= 0 && i <= _num_q * subclasses_of_ref, "Out of bounds index");
1313 int j = i / _num_q;
1314 switch (j) {
1315 case 0: return "SoftRef";
1316 case 1: return "WeakRef";
1317 case 2: return "FinalRef";
1318 case 3: return "PhantomRef";
1319 }
|
31 DiscoveredList() : _len(0), _compressed_head(0), _oop_head(NULL) { }
32 oop head() const {
33 return UseCompressedOops ? oopDesc::decode_heap_oop_not_null(_compressed_head) :
34 _oop_head;
35 }
36 HeapWord* adr_head() {
37 return UseCompressedOops ? (HeapWord*)&_compressed_head :
38 (HeapWord*)&_oop_head;
39 }
40 void set_head(oop o) {
41 if (UseCompressedOops) {
42 // Must compress the head ptr.
43 _compressed_head = oopDesc::encode_heap_oop_not_null(o);
44 } else {
45 _oop_head = o;
46 }
47 }
48 bool empty() const { return head() == ReferenceProcessor::sentinel_ref(); }
49 size_t length() { return _len; }
50 void set_length(size_t len) { _len = len; }
51 void inc_length(size_t inc) { _len += inc; assert(_len > 0, "Error"); }
52 void dec_length(size_t dec) { _len -= dec; }
53 private:
54 // Set value depending on UseCompressedOops. This could be a template class
55 // but then we have to fix all the instantiations and declarations that use this class.
56 oop _oop_head;
57 narrowOop _compressed_head;
58 size_t _len;
59 };
60
61 oop ReferenceProcessor::_sentinelRef = NULL;
62
63 const int subclasses_of_ref = REF_PHANTOM - REF_OTHER;
64
65 void referenceProcessor_init() {
66 ReferenceProcessor::init_statics();
67 }
68
69 void ReferenceProcessor::init_statics() {
70 assert(_sentinelRef == NULL, "should be initialized precisely once");
71 EXCEPTION_MARK;
72 _sentinelRef = instanceKlass::cast(
421 inline DiscoveredListIterator(DiscoveredList& refs_list,
422 OopClosure* keep_alive,
423 BoolObjectClosure* is_alive);
424
425 // End Of List.
426 inline bool has_next() const { return _next != ReferenceProcessor::sentinel_ref(); }
427
428 // Get oop to the Reference object.
429 inline oop obj() const { return _ref; }
430
431 // Get oop to the referent object.
432 inline oop referent() const { return _referent; }
433
434 // Returns true if referent is alive.
435 inline bool is_referent_alive() const;
436
437 // Loads data for the current reference.
438 // The "allow_null_referent" argument tells us to allow for the possibility
439 // of a NULL referent in the discovered Reference object. This typically
440 // happens in the case of concurrent collectors that may have done the
441 // discovery concurrently, or interleaved, with mutator execution.
442 inline void load_ptrs(DEBUG_ONLY(bool allow_null_referent));
443
444 // Move to the next discovered reference.
445 inline void next();
446
447 // Remove the current reference from the list
448 inline void remove();
449
450 // Make the Reference object active again.
451 inline void make_active() { java_lang_ref_Reference::set_next(_ref, NULL); }
452
453 // Make the referent alive.
454 inline void make_referent_alive() {
455 if (UseCompressedOops) {
456 _keep_alive->do_oop((narrowOop*)_referent_addr);
457 } else {
458 _keep_alive->do_oop((oop*)_referent_addr);
459 }
460 }
461
462 // Update the discovered field.
463 inline void update_discovered() {
464 // First _prev_next ref actually points into DiscoveredList (gross).
465 if (UseCompressedOops) {
466 _keep_alive->do_oop((narrowOop*)_prev_next);
467 } else {
468 _keep_alive->do_oop((oop*)_prev_next);
469 }
470 }
471
472 // NULL out referent pointer.
473 inline void clear_referent() { oop_store_raw(_referent_addr, NULL); }
474
475 // Statistics
476 NOT_PRODUCT(
477 inline size_t processed() const { return _processed; }
478 inline size_t removed() const { return _removed; }
479 )
480
481 inline void move_to_next();
482
483 private:
484 DiscoveredList& _refs_list;
485 HeapWord* _prev_next;
486 oop _ref;
487 HeapWord* _discovered_addr;
488 oop _next;
489 HeapWord* _referent_addr;
490 oop _referent;
491 OopClosure* _keep_alive;
492 BoolObjectClosure* _is_alive;
493 DEBUG_ONLY(
494 oop _first_seen; // cyclic linked list check
495 )
496 NOT_PRODUCT(
497 size_t _processed;
498 size_t _removed;
499 )
500 };
537 "bad referent");
538 }
539
540 inline void DiscoveredListIterator::next() {
541 _prev_next = _discovered_addr;
542 move_to_next();
543 }
544
545 inline void DiscoveredListIterator::remove() {
546 assert(_ref->is_oop(), "Dropping a bad reference");
547 oop_store_raw(_discovered_addr, NULL);
548 // First _prev_next ref actually points into DiscoveredList (gross).
549 if (UseCompressedOops) {
550 // Remove Reference object from list.
551 oopDesc::encode_store_heap_oop_not_null((narrowOop*)_prev_next, _next);
552 } else {
553 // Remove Reference object from list.
554 oopDesc::store_heap_oop((oop*)_prev_next, _next);
555 }
556 NOT_PRODUCT(_removed++);
557 _refs_list.dec_length(1);
558 }
559
560 inline void DiscoveredListIterator::move_to_next() {
561 _ref = _next;
562 assert(_ref != _first_seen, "cyclic ref_list found");
563 NOT_PRODUCT(_processed++);
564 }
565
566 // NOTE: process_phase*() are largely similar, and at a high level
567 // merely iterate over the extant list applying a predicate to
568 // each of its elements and possibly removing that element from the
569 // list and applying some further closures to that element.
570 // We should consider the possibility of replacing these
571 // process_phase*() methods by abstracting them into
572 // a single general iterator invocation that receives appropriate
573 // closures that accomplish this work.
574
575 // (SoftReferences only) Traverse the list and remove any SoftReferences whose
576 // referents are not alive, but that should be kept alive for policy reasons.
577 // Keep alive the transitive closure of all such referents.
578 void
579 ReferenceProcessor::process_phase1(DiscoveredList& refs_list,
580 ReferencePolicy* policy,
581 BoolObjectClosure* is_alive,
582 OopClosure* keep_alive,
583 VoidClosure* complete_gc) {
584 assert(policy != NULL, "Must have a non-NULL policy");
585 DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
586 // Decide which softly reachable refs should be kept alive.
587 while (iter.has_next()) {
588 iter.load_ptrs(DEBUG_ONLY(!discovery_is_atomic() /* allow_null_referent */));
589 bool referent_is_dead = (iter.referent() != NULL) && !iter.is_referent_alive();
590 if (referent_is_dead && !policy->should_clear_reference(iter.obj())) {
591 if (TraceReferenceGC) {
592 gclog_or_tty->print_cr("Dropping reference (" INTPTR_FORMAT ": %s" ") by policy",
593 iter.obj(), iter.obj()->blueprint()->internal_name());
594 }
595 // Remove Reference object from list
596 iter.remove();
597 // Make the Reference object active again
598 iter.make_active();
599 // keep the referent around
600 iter.make_referent_alive();
601 iter.move_to_next();
602 } else {
603 iter.next();
604 }
605 }
606 // Close the reachable set
607 complete_gc->do_void();
608 NOT_PRODUCT(
609 if (PrintGCDetails && TraceReferenceGC) {
610 gclog_or_tty->print(" Dropped %d dead Refs out of %d "
611 "discovered Refs by policy ", iter.removed(), iter.processed());
612 }
613 )
614 }
615
616 // Traverse the list and remove any Refs that are not active, or
617 // whose referents are either alive or NULL.
618 void
619 ReferenceProcessor::pp2_work(DiscoveredList& refs_list,
620 BoolObjectClosure* is_alive,
621 OopClosure* keep_alive) {
622 assert(discovery_is_atomic(), "Error");
623 DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
624 while (iter.has_next()) {
625 iter.load_ptrs(DEBUG_ONLY(false /* allow_null_referent */));
626 DEBUG_ONLY(oop next = java_lang_ref_Reference::next(iter.obj());)
627 assert(next == NULL, "Should not discover inactive Reference");
628 if (iter.is_referent_alive()) {
629 if (TraceReferenceGC) {
630 gclog_or_tty->print_cr("Dropping strongly reachable reference (" INTPTR_FORMAT ": %s)",
631 iter.obj(), iter.obj()->blueprint()->internal_name());
632 }
633 // The referent is reachable after all.
634 // Remove Reference object from list.
635 iter.remove();
636 // Update the referent pointer as necessary: Note that this
637 // should not entail any recursive marking because the
638 // referent must already have been traversed.
639 iter.make_referent_alive();
640 iter.move_to_next();
641 } else {
642 iter.next();
643 }
644 }
645 NOT_PRODUCT(
646 if (PrintGCDetails && TraceReferenceGC) {
647 gclog_or_tty->print(" Dropped %d active Refs out of %d "
648 "Refs in discovered list ", iter.removed(), iter.processed());
649 }
650 )
651 }
652
653 void
654 ReferenceProcessor::pp2_work_concurrent_discovery(DiscoveredList& refs_list,
655 BoolObjectClosure* is_alive,
656 OopClosure* keep_alive,
657 VoidClosure* complete_gc) {
658 assert(!discovery_is_atomic(), "Error");
659 DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
660 while (iter.has_next()) {
661 iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
662 HeapWord* next_addr = java_lang_ref_Reference::next_addr(iter.obj());
663 oop next = java_lang_ref_Reference::next(iter.obj());
664 if ((iter.referent() == NULL || iter.is_referent_alive() ||
665 next != NULL)) {
666 assert(next->is_oop_or_null(), "bad next field");
667 // Remove Reference object from list
668 iter.remove();
669 // Trace the cohorts
670 iter.make_referent_alive();
671 if (UseCompressedOops) {
672 keep_alive->do_oop((narrowOop*)next_addr);
673 } else {
674 keep_alive->do_oop((oop*)next_addr);
675 }
676 iter.move_to_next();
677 } else {
678 iter.next();
679 }
680 }
681 // Now close the newly reachable set
682 complete_gc->do_void();
683 NOT_PRODUCT(
684 if (PrintGCDetails && TraceReferenceGC) {
685 gclog_or_tty->print(" Dropped %d active Refs out of %d "
686 "Refs in discovered list ", iter.removed(), iter.processed());
687 }
688 )
689 }
690
691 // Traverse the list and process the referents, by either
692 // clearing them or keeping them (and their reachable
693 // closure) alive.
694 void
695 ReferenceProcessor::process_phase3(DiscoveredList& refs_list,
696 bool clear_referent,
819 size_t avg_refs = total_refs / _num_q + 1;
820 int to_idx = 0;
821 for (int from_idx = 0; from_idx < _num_q; from_idx++) {
822 while (ref_lists[from_idx].length() > avg_refs) {
823 assert(to_idx < _num_q, "Sanity Check!");
824 if (ref_lists[to_idx].length() < avg_refs) {
825 // move superfluous refs
826 size_t refs_to_move =
827 MIN2(ref_lists[from_idx].length() - avg_refs,
828 avg_refs - ref_lists[to_idx].length());
829 oop move_head = ref_lists[from_idx].head();
830 oop move_tail = move_head;
831 oop new_head = move_head;
832 // find an element to split the list on
833 for (size_t j = 0; j < refs_to_move; ++j) {
834 move_tail = new_head;
835 new_head = java_lang_ref_Reference::discovered(new_head);
836 }
837 java_lang_ref_Reference::set_discovered(move_tail, ref_lists[to_idx].head());
838 ref_lists[to_idx].set_head(move_head);
839 ref_lists[to_idx].inc_length(refs_to_move);
840 ref_lists[from_idx].set_head(new_head);
841 ref_lists[from_idx].dec_length(refs_to_move);
842 } else {
843 ++to_idx;
844 }
845 }
846 }
847 }
848
849 void
850 ReferenceProcessor::process_discovered_reflist(
851 DiscoveredList refs_lists[],
852 ReferencePolicy* policy,
853 bool clear_referent,
854 BoolObjectClosure* is_alive,
855 OopClosure* keep_alive,
856 VoidClosure* complete_gc,
857 AbstractRefProcTaskExecutor* task_executor)
858 {
859 bool mt = task_executor != NULL && _processing_is_mt;
860 if (mt && ParallelRefProcBalancingEnabled) {
861 balance_queues(refs_lists);
910 is_alive, keep_alive, complete_gc);
911 }
912 }
913 }
914
915 void ReferenceProcessor::clean_up_discovered_references() {
916 // loop over the lists
917 for (int i = 0; i < _num_q * subclasses_of_ref; i++) {
918 if (TraceReferenceGC && PrintGCDetails && ((i % _num_q) == 0)) {
919 gclog_or_tty->print_cr(
920 "\nScrubbing %s discovered list of Null referents",
921 list_name(i));
922 }
923 clean_up_discovered_reflist(_discoveredSoftRefs[i]);
924 }
925 }
926
927 void ReferenceProcessor::clean_up_discovered_reflist(DiscoveredList& refs_list) {
928 assert(!discovery_is_atomic(), "Else why call this method?");
929 DiscoveredListIterator iter(refs_list, NULL, NULL);
930 while (iter.has_next()) {
931 iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
932 oop next = java_lang_ref_Reference::next(iter.obj());
933 assert(next->is_oop_or_null(), "bad next field");
934 // If referent has been cleared or Reference is not active,
935 // drop it.
936 if (iter.referent() == NULL || next != NULL) {
937 debug_only(
938 if (PrintGCDetails && TraceReferenceGC) {
939 gclog_or_tty->print_cr("clean_up_discovered_list: Dropping Reference: "
940 INTPTR_FORMAT " with next field: " INTPTR_FORMAT
941 " and referent: " INTPTR_FORMAT,
942 iter.obj(), next, iter.referent());
943 }
944 )
945 // Remove Reference object from list
946 iter.remove();
947 iter.move_to_next();
948 } else {
949 iter.next();
950 }
951 }
952 NOT_PRODUCT(
953 if (PrintGCDetails && TraceReferenceGC) {
954 gclog_or_tty->print(
955 " Removed %d Refs with NULL referents out of %d discovered Refs",
956 iter.removed(), iter.processed());
957 }
958 )
959 }
960
961 inline DiscoveredList* ReferenceProcessor::get_discovered_list(ReferenceType rt) {
962 int id = 0;
963 // Determine the queue index to use for this object.
964 if (_discovery_is_mt) {
965 // During a multi-threaded discovery phase,
966 // each thread saves to its "own" list.
967 Thread* thr = Thread::current();
968 assert(thr->is_GC_task_thread(),
969 "Dubious cast from Thread* to WorkerThread*?");
970 id = ((WorkerThread*)thr)->id();
971 } else {
1009 HeapWord* discovered_addr) {
1010 assert(_discovery_is_mt, "!_discovery_is_mt should have been handled by caller");
1011 // First we must make sure this object is only enqueued once. CAS in a non null
1012 // discovered_addr.
1013 oop current_head = refs_list.head();
1014
1015 // Note: In the case of G1, this pre-barrier is strictly
1016 // not necessary because the only case we are interested in
1017 // here is when *discovered_addr is NULL, so this will expand to
1018 // nothing. As a result, I am just manually eliding this out for G1.
1019 if (_discovered_list_needs_barrier && !UseG1GC) {
1020 _bs->write_ref_field_pre((void*)discovered_addr, current_head); guarantee(false, "Needs to be fixed: YSR");
1021 }
1022 oop retest = oopDesc::atomic_compare_exchange_oop(current_head, discovered_addr,
1023 NULL);
1024 if (retest == NULL) {
1025 // This thread just won the right to enqueue the object.
1026 // We have separate lists for enqueueing so no synchronization
1027 // is necessary.
1028 refs_list.set_head(obj);
1029 refs_list.inc_length(1);
1030 if (_discovered_list_needs_barrier) {
1031 _bs->write_ref_field((void*)discovered_addr, current_head); guarantee(false, "Needs to be fixed: YSR");
1032 }
1033
1034 } else {
1035 // If retest was non NULL, another thread beat us to it:
1036 // The reference has already been discovered...
1037 if (TraceReferenceGC) {
1038 gclog_or_tty->print_cr("Already enqueued reference (" INTPTR_FORMAT ": %s)",
1039 obj, obj->blueprint()->internal_name());
1040 }
1041 }
1042 }
1043
1044 // We mention two of several possible choices here:
1045 // #0: if the reference object is not in the "originating generation"
1046 // (or part of the heap being collected, indicated by our "span"
1047 // we don't treat it specially (i.e. we scan it as we would
1048 // a normal oop, treating its references as strong references).
1049 // This means that references can't be enqueued unless their
1153
1154 if (_discovery_is_mt) {
1155 add_to_discovered_list_mt(*list, obj, discovered_addr);
1156 } else {
1157 // If "_discovered_list_needs_barrier", we do write barriers when
1158 // updating the discovered reference list. Otherwise, we do a raw store
1159 // here: the field will be visited later when processing the discovered
1160 // references.
1161 oop current_head = list->head();
1162 // As in the case further above, since we are over-writing a NULL
1163 // pre-value, we can safely elide the pre-barrier here for the case of G1.
1164 assert(discovered == NULL, "control point invariant");
1165 if (_discovered_list_needs_barrier && !UseG1GC) { // safe to elide for G1
1166 _bs->write_ref_field_pre((oop*)discovered_addr, current_head);
1167 }
1168 oop_store_raw(discovered_addr, current_head);
1169 if (_discovered_list_needs_barrier) {
1170 _bs->write_ref_field((oop*)discovered_addr, current_head);
1171 }
1172 list->set_head(obj);
1173 list->inc_length(1);
1174 }
1175
1176 // In the MT discovery case, it is currently possible to see
1177 // the following message multiple times if several threads
1178 // discover a reference about the same time. Only one will
1179 // however have actually added it to the disocvered queue.
1180 // One could let add_to_discovered_list_mt() return an
1181 // indication for success in queueing (by 1 thread) or
1182 // failure (by all other threads), but I decided the extra
1183 // code was not worth the effort for something that is
1184 // only used for debugging support.
1185 if (TraceReferenceGC) {
1186 oop referent = java_lang_ref_Reference::referent(obj);
1187 if (PrintGCDetails) {
1188 gclog_or_tty->print_cr("Enqueued reference (" INTPTR_FORMAT ": %s)",
1189 obj, obj->blueprint()->internal_name());
1190 }
1191 assert(referent->is_oop(), "Enqueued a bad referent");
1192 }
1193 assert(obj->is_oop(), "Enqueued a bad reference");
1194 return true;
1195 }
1196
1197 // Preclean the discovered references by removing those
1198 // whose referents are alive, and by marking from those that
1199 // are not active. These lists can be handled here
1200 // in any order and, indeed, concurrently.
1201 void ReferenceProcessor::preclean_discovered_references(
1202 BoolObjectClosure* is_alive,
1203 OopClosure* keep_alive,
1204 VoidClosure* complete_gc,
1205 YieldClosure* yield) {
1206
1207 NOT_PRODUCT(verify_ok_to_handle_reflists());
1208
1209 // Soft references
1210 {
1211 TraceTime tt("Preclean SoftReferences", PrintGCDetails && PrintReferenceGC,
1212 false, gclog_or_tty);
1213 for (int i = 0; i < _num_q; i++) {
1214 if (yield->should_return()) {
1215 return;
1216 }
1217 preclean_discovered_reflist(_discoveredSoftRefs[i], is_alive,
1218 keep_alive, complete_gc, yield);
1219 }
1220 }
1221
1222 // Weak references
1223 {
1224 TraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC,
1225 false, gclog_or_tty);
1226 for (int i = 0; i < _num_q; i++) {
1227 if (yield->should_return()) {
1228 return;
1229 }
1230 preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive,
1231 keep_alive, complete_gc, yield);
1232 }
1233 }
1234
1235 // Final references
1236 {
1237 TraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC,
1238 false, gclog_or_tty);
1239 for (int i = 0; i < _num_q; i++) {
1240 if (yield->should_return()) {
1241 return;
1242 }
1243 preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive,
1244 keep_alive, complete_gc, yield);
1245 }
1246 }
1247
1248 // Phantom references
1249 {
1250 TraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC,
1251 false, gclog_or_tty);
1252 for (int i = 0; i < _num_q; i++) {
1253 if (yield->should_return()) {
1254 return;
1255 }
1256 preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive,
1257 keep_alive, complete_gc, yield);
1258 }
1259 }
1260 }
1261
1262 // Walk the given discovered ref list, and remove all reference objects
1263 // whose referents are still alive, whose referents are NULL or which
1264 // are not active (have a non-NULL next field). NOTE: When we are
1265 // thus precleaning the ref lists (which happens single-threaded today),
1266 // we do not disable refs discovery to honour the correct semantics of
1267 // java.lang.Reference. As a result, we need to be careful below
1268 // that ref removal steps interleave safely with ref discovery steps
1269 // (in this thread).
1270 void
1271 ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list,
1272 BoolObjectClosure* is_alive,
1273 OopClosure* keep_alive,
1274 VoidClosure* complete_gc,
1275 YieldClosure* yield) {
1276 DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
1277 while (iter.has_next()) {
1278 iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
1279 oop obj = iter.obj();
1280 oop next = java_lang_ref_Reference::next(obj);
1281 if (iter.referent() == NULL || iter.is_referent_alive() ||
1282 next != NULL) {
1283 // The referent has been cleared, or is alive, or the Reference is not
1284 // active; we need to trace and mark its cohort.
1285 if (TraceReferenceGC) {
1286 gclog_or_tty->print_cr("Precleaning Reference (" INTPTR_FORMAT ": %s)",
1287 iter.obj(), iter.obj()->blueprint()->internal_name());
1288 }
1289 // Remove Reference object from list
1290 iter.remove();
1291 // Keep alive its cohort.
1292 iter.make_referent_alive();
1293 if (UseCompressedOops) {
1294 narrowOop* next_addr = (narrowOop*)java_lang_ref_Reference::next_addr(obj);
1295 keep_alive->do_oop(next_addr);
1296 } else {
1297 oop* next_addr = (oop*)java_lang_ref_Reference::next_addr(obj);
1298 keep_alive->do_oop(next_addr);
1299 }
1300 iter.move_to_next();
1301 } else {
1302 iter.next();
1303 }
1304 }
1305 // Close the reachable set
1306 complete_gc->do_void();
1307
1308 NOT_PRODUCT(
1309 if (PrintGCDetails && PrintReferenceGC) {
1310 gclog_or_tty->print(" Dropped %d Refs out of %d "
1311 "Refs in discovered list ", iter.removed(), iter.processed());
1312 }
1313 )
1314 }
1315
1316 const char* ReferenceProcessor::list_name(int i) {
1317 assert(i >= 0 && i <= _num_q * subclasses_of_ref, "Out of bounds index");
1318 int j = i / _num_q;
1319 switch (j) {
1320 case 0: return "SoftRef";
1321 case 1: return "WeakRef";
1322 case 2: return "FinalRef";
1323 case 3: return "PhantomRef";
1324 }
|