src/share/vm/memory/referenceProcessor.cpp

Print this page




  85   // Initialize the master soft ref clock.
  86   java_lang_ref_SoftReference::set_clock(os::javaTimeMillis());
  87 
  88   if (HAS_PENDING_EXCEPTION) {
  89       Handle ex(THREAD, PENDING_EXCEPTION);
  90       vm_exit_during_initialization(ex);
  91   }
  92   assert(_sentinelRef != NULL && _sentinelRef->is_oop(),
  93          "Just constructed it!");
  94   _always_clear_soft_ref_policy = new AlwaysClearPolicy();
  95   _default_soft_ref_policy      = new COMPILER2_PRESENT(LRUMaxHeapPolicy())
  96                                       NOT_COMPILER2(LRUCurrentHeapPolicy());
  97   if (_always_clear_soft_ref_policy == NULL || _default_soft_ref_policy == NULL) {
  98     vm_exit_during_initialization("Could not allocate reference policy object");
  99   }
 100   guarantee(RefDiscoveryPolicy == ReferenceBasedDiscovery ||
 101             RefDiscoveryPolicy == ReferentBasedDiscovery,
 102             "Unrecongnized RefDiscoveryPolicy");
 103 }
 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,
 131                                        bool      atomic_discovery,
 132                                        bool      mt_discovery,
 133                                        int       mt_degree,
 134                                        bool      mt_processing,





 135                                        bool      discovered_list_needs_barrier)  :
 136   _discovering_refs(false),
 137   _enqueuing_is_done(false),
 138   _is_alive_non_header(NULL),
 139   _discovered_list_needs_barrier(discovered_list_needs_barrier),
 140   _bs(NULL),
 141   _processing_is_mt(mt_processing),
 142   _next_id(0)
 143 {
 144   _span = span;
 145   _discovery_is_atomic = atomic_discovery;
 146   _discovery_is_mt     = mt_discovery;
 147   _num_q               = mt_degree;
 148   _max_num_q           = mt_degree;
 149   _discoveredSoftRefs  = NEW_C_HEAP_ARRAY(DiscoveredList, _max_num_q * subclasses_of_ref);
 150   if (_discoveredSoftRefs == NULL) {
 151     vm_exit_during_initialization("Could not allocated RefProc Array");
 152   }
 153   _discoveredWeakRefs    = &_discoveredSoftRefs[_max_num_q];
 154   _discoveredFinalRefs   = &_discoveredWeakRefs[_max_num_q];
 155   _discoveredPhantomRefs = &_discoveredFinalRefs[_max_num_q];
 156   assert(sentinel_ref() != NULL, "_sentinelRef is NULL");
 157   // Initialized all entries to _sentinelRef
 158   for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) {
 159         _discoveredSoftRefs[i].set_head(sentinel_ref());
 160     _discoveredSoftRefs[i].set_length(0);
 161   }
 162   // If we do barreirs, cache a copy of the barrier set.
 163   if (discovered_list_needs_barrier) {
 164     _bs = Universe::heap()->barrier_set();
 165   }

 166 }
 167 
 168 #ifndef PRODUCT
 169 void ReferenceProcessor::verify_no_references_recorded() {
 170   guarantee(!_discovering_refs, "Discovering refs?");
 171   for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) {
 172     guarantee(_discoveredSoftRefs[i].empty(),
 173               "Found non-empty discovered list");
 174   }
 175 }
 176 #endif
 177 
 178 void ReferenceProcessor::weak_oops_do(OopClosure* f) {
 179   // Should this instead be
 180   // for (int i = 0; i < subclasses_of_ref; i++_ {
 181   //   for (int j = 0; j < _num_q; j++) {
 182   //     int index = i * _max_num_q + j;
 183   for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) {
 184     if (UseCompressedOops) {
 185       f->do_oop((narrowOop*)_discoveredSoftRefs[i].adr_head());


 934   BoolObjectClosure*           is_alive,
 935   OopClosure*                  keep_alive,
 936   VoidClosure*                 complete_gc,
 937   AbstractRefProcTaskExecutor* task_executor)
 938 {
 939   bool mt_processing = task_executor != NULL && _processing_is_mt;
 940   // If discovery used MT and a dynamic number of GC threads, then
 941   // the queues must be balanced for correctness if fewer than the
 942   // maximum number of queues were used.  The number of queue used
 943   // during discovery may be different than the number to be used
 944   // for processing so don't depend of _num_q < _max_num_q as part
 945   // of the test.
 946   bool must_balance = _discovery_is_mt;
 947 
 948   if ((mt_processing && ParallelRefProcBalancingEnabled) ||
 949       must_balance) {
 950     balance_queues(refs_lists);
 951   }
 952   if (PrintReferenceGC && PrintGCDetails) {
 953     size_t total = 0;
 954     for (int i = 0; i < _num_q; ++i) {
 955       total += refs_lists[i].length();
 956     }
 957     gclog_or_tty->print(", %u refs", total);
 958   }
 959 
 960   // Phase 1 (soft refs only):
 961   // . Traverse the list and remove any SoftReferences whose
 962   //   referents are not alive, but that should be kept alive for
 963   //   policy reasons. Keep alive the transitive closure of all
 964   //   such referents.
 965   if (policy != NULL) {
 966     if (mt_processing) {
 967       RefProcPhase1Task phase1(*this, refs_lists, policy, true /*marks_oops_alive*/);
 968       task_executor->execute(phase1);
 969     } else {
 970       for (int i = 0; i < _num_q; i++) {
 971         process_phase1(refs_lists[i], policy,
 972                        is_alive, keep_alive, complete_gc);
 973       }
 974     }
 975   } else { // policy == NULL
 976     assert(refs_lists != _discoveredSoftRefs,
 977            "Policy must be specified for soft references.");
 978   }
 979 
 980   // Phase 2:
 981   // . Traverse the list and remove any refs whose referents are alive.
 982   if (mt_processing) {
 983     RefProcPhase2Task phase2(*this, refs_lists, !discovery_is_atomic() /*marks_oops_alive*/);
 984     task_executor->execute(phase2);
 985   } else {
 986     for (int i = 0; i < _num_q; i++) {
 987       process_phase2(refs_lists[i], is_alive, keep_alive, complete_gc);
 988     }
 989   }
 990 
 991   // Phase 3:
 992   // . Traverse the list and process referents as appropriate.
 993   if (mt_processing) {
 994     RefProcPhase3Task phase3(*this, refs_lists, clear_referent, true /*marks_oops_alive*/);
 995     task_executor->execute(phase3);
 996   } else {
 997     for (int i = 0; i < _num_q; i++) {
 998       process_phase3(refs_lists[i], clear_referent,
 999                      is_alive, keep_alive, complete_gc);
1000     }
1001   }
1002 }
1003 
1004 void ReferenceProcessor::clean_up_discovered_references() {
1005   // loop over the lists
1006   // Should this instead be
1007   // for (int i = 0; i < subclasses_of_ref; i++_ {
1008   //   for (int j = 0; j < _num_q; j++) {
1009   //     int index = i * _max_num_q + j;
1010   for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) {
1011     if (TraceReferenceGC && PrintGCDetails && ((i % _num_q) == 0)) {
1012       gclog_or_tty->print_cr(
1013         "\nScrubbing %s discovered list of Null referents",
1014         list_name(i));
1015     }
1016     clean_up_discovered_reflist(_discoveredSoftRefs[i]);
1017   }




  85   // Initialize the master soft ref clock.
  86   java_lang_ref_SoftReference::set_clock(os::javaTimeMillis());
  87 
  88   if (HAS_PENDING_EXCEPTION) {
  89       Handle ex(THREAD, PENDING_EXCEPTION);
  90       vm_exit_during_initialization(ex);
  91   }
  92   assert(_sentinelRef != NULL && _sentinelRef->is_oop(),
  93          "Just constructed it!");
  94   _always_clear_soft_ref_policy = new AlwaysClearPolicy();
  95   _default_soft_ref_policy      = new COMPILER2_PRESENT(LRUMaxHeapPolicy())
  96                                       NOT_COMPILER2(LRUCurrentHeapPolicy());
  97   if (_always_clear_soft_ref_policy == NULL || _default_soft_ref_policy == NULL) {
  98     vm_exit_during_initialization("Could not allocate reference policy object");
  99   }
 100   guarantee(RefDiscoveryPolicy == ReferenceBasedDiscovery ||
 101             RefDiscoveryPolicy == ReferentBasedDiscovery,
 102             "Unrecongnized RefDiscoveryPolicy");
 103 }
 104 

























 105 ReferenceProcessor::ReferenceProcessor(MemRegion span,



 106                                        bool      mt_processing,
 107                                        int       mt_processing_degree,
 108                                        bool      mt_discovery,
 109                                        int       mt_discovery_degree,
 110                                        bool      atomic_discovery,
 111                                        BoolObjectClosure* is_alive_non_header,
 112                                        bool      discovered_list_needs_barrier)  :
 113   _discovering_refs(false),
 114   _enqueuing_is_done(false),
 115   _is_alive_non_header(is_alive_non_header),
 116   _discovered_list_needs_barrier(discovered_list_needs_barrier),
 117   _bs(NULL),
 118   _processing_is_mt(mt_processing),
 119   _next_id(0)
 120 {
 121   _span = span;
 122   _discovery_is_atomic = atomic_discovery;
 123   _discovery_is_mt     = mt_discovery;
 124   _num_q               = mt_processing_degree;
 125   _max_num_q           = MAX2(mt_processing_degree, mt_discovery_degree);
 126   _discoveredSoftRefs  = NEW_C_HEAP_ARRAY(DiscoveredList, _max_num_q * subclasses_of_ref);
 127   if (_discoveredSoftRefs == NULL) {
 128     vm_exit_during_initialization("Could not allocated RefProc Array");
 129   }
 130   _discoveredWeakRefs    = &_discoveredSoftRefs[_max_num_q];
 131   _discoveredFinalRefs   = &_discoveredWeakRefs[_max_num_q];
 132   _discoveredPhantomRefs = &_discoveredFinalRefs[_max_num_q];
 133   assert(sentinel_ref() != NULL, "_sentinelRef is NULL");
 134   // Initialized all entries to _sentinelRef
 135   for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) {
 136         _discoveredSoftRefs[i].set_head(sentinel_ref());
 137     _discoveredSoftRefs[i].set_length(0);
 138   }
 139   // If we do barreirs, cache a copy of the barrier set.
 140   if (discovered_list_needs_barrier) {
 141     _bs = Universe::heap()->barrier_set();
 142   }
 143   setup_policy(false /* default soft ref policy */);
 144 }
 145 
 146 #ifndef PRODUCT
 147 void ReferenceProcessor::verify_no_references_recorded() {
 148   guarantee(!_discovering_refs, "Discovering refs?");
 149   for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) {
 150     guarantee(_discoveredSoftRefs[i].empty(),
 151               "Found non-empty discovered list");
 152   }
 153 }
 154 #endif
 155 
 156 void ReferenceProcessor::weak_oops_do(OopClosure* f) {
 157   // Should this instead be
 158   // for (int i = 0; i < subclasses_of_ref; i++_ {
 159   //   for (int j = 0; j < _num_q; j++) {
 160   //     int index = i * _max_num_q + j;
 161   for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) {
 162     if (UseCompressedOops) {
 163       f->do_oop((narrowOop*)_discoveredSoftRefs[i].adr_head());


 912   BoolObjectClosure*           is_alive,
 913   OopClosure*                  keep_alive,
 914   VoidClosure*                 complete_gc,
 915   AbstractRefProcTaskExecutor* task_executor)
 916 {
 917   bool mt_processing = task_executor != NULL && _processing_is_mt;
 918   // If discovery used MT and a dynamic number of GC threads, then
 919   // the queues must be balanced for correctness if fewer than the
 920   // maximum number of queues were used.  The number of queue used
 921   // during discovery may be different than the number to be used
 922   // for processing so don't depend of _num_q < _max_num_q as part
 923   // of the test.
 924   bool must_balance = _discovery_is_mt;
 925 
 926   if ((mt_processing && ParallelRefProcBalancingEnabled) ||
 927       must_balance) {
 928     balance_queues(refs_lists);
 929   }
 930   if (PrintReferenceGC && PrintGCDetails) {
 931     size_t total = 0;
 932     for (int i = 0; i < _max_num_q; ++i) {
 933       total += refs_lists[i].length();
 934     }
 935     gclog_or_tty->print(", %u refs", total);
 936   }
 937 
 938   // Phase 1 (soft refs only):
 939   // . Traverse the list and remove any SoftReferences whose
 940   //   referents are not alive, but that should be kept alive for
 941   //   policy reasons. Keep alive the transitive closure of all
 942   //   such referents.
 943   if (policy != NULL) {
 944     if (mt_processing) {
 945       RefProcPhase1Task phase1(*this, refs_lists, policy, true /*marks_oops_alive*/);
 946       task_executor->execute(phase1);
 947     } else {
 948       for (int i = 0; i < _max_num_q; i++) {
 949         process_phase1(refs_lists[i], policy,
 950                        is_alive, keep_alive, complete_gc);
 951       }
 952     }
 953   } else { // policy == NULL
 954     assert(refs_lists != _discoveredSoftRefs,
 955            "Policy must be specified for soft references.");
 956   }
 957 
 958   // Phase 2:
 959   // . Traverse the list and remove any refs whose referents are alive.
 960   if (mt_processing) {
 961     RefProcPhase2Task phase2(*this, refs_lists, !discovery_is_atomic() /*marks_oops_alive*/);
 962     task_executor->execute(phase2);
 963   } else {
 964     for (int i = 0; i < _max_num_q; i++) {
 965       process_phase2(refs_lists[i], is_alive, keep_alive, complete_gc);
 966     }
 967   }
 968 
 969   // Phase 3:
 970   // . Traverse the list and process referents as appropriate.
 971   if (mt_processing) {
 972     RefProcPhase3Task phase3(*this, refs_lists, clear_referent, true /*marks_oops_alive*/);
 973     task_executor->execute(phase3);
 974   } else {
 975     for (int i = 0; i < _max_num_q; i++) {
 976       process_phase3(refs_lists[i], clear_referent,
 977                      is_alive, keep_alive, complete_gc);
 978     }
 979   }
 980 }
 981 
 982 void ReferenceProcessor::clean_up_discovered_references() {
 983   // loop over the lists
 984   // Should this instead be
 985   // for (int i = 0; i < subclasses_of_ref; i++_ {
 986   //   for (int j = 0; j < _num_q; j++) {
 987   //     int index = i * _max_num_q + j;
 988   for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) {
 989     if (TraceReferenceGC && PrintGCDetails && ((i % _num_q) == 0)) {
 990       gclog_or_tty->print_cr(
 991         "\nScrubbing %s discovered list of Null referents",
 992         list_name(i));
 993     }
 994     clean_up_discovered_reflist(_discoveredSoftRefs[i]);
 995   }