src/hotspot/share/gc/shared/parallelCleaning.cpp
changeset 52385 5c679ec60888
parent 51537 a5d47d1b2a74
child 52448 bc5c7f63dbae
equal deleted inserted replaced
52384:d6dc479bcdd3 52385:5c679ec60888
    25 #include "precompiled.hpp"
    25 #include "precompiled.hpp"
    26 #include "classfile/symbolTable.hpp"
    26 #include "classfile/symbolTable.hpp"
    27 #include "classfile/stringTable.hpp"
    27 #include "classfile/stringTable.hpp"
    28 #include "code/codeCache.hpp"
    28 #include "code/codeCache.hpp"
    29 #include "gc/shared/parallelCleaning.hpp"
    29 #include "gc/shared/parallelCleaning.hpp"
       
    30 #include "logging/log.hpp"
    30 #include "memory/resourceArea.hpp"
    31 #include "memory/resourceArea.hpp"
    31 #include "logging/log.hpp"
    32 #include "logging/log.hpp"
    32 
    33 
    33 StringCleaningTask::StringCleaningTask(BoolObjectClosure* is_alive, StringDedupUnlinkOrOopsDoClosure* dedup_closure, bool process_strings) :
    34 StringCleaningTask::StringCleaningTask(BoolObjectClosure* is_alive, StringDedupUnlinkOrOopsDoClosure* dedup_closure, bool process_strings) :
    34   AbstractGangTask("String Unlinking"),
    35   AbstractGangTask("String Unlinking"),
    65     StringDedup::parallel_unlink(_dedup_closure, worker_id);
    66     StringDedup::parallel_unlink(_dedup_closure, worker_id);
    66   }
    67   }
    67 }
    68 }
    68 
    69 
    69 CodeCacheUnloadingTask::CodeCacheUnloadingTask(uint num_workers, BoolObjectClosure* is_alive, bool unloading_occurred) :
    70 CodeCacheUnloadingTask::CodeCacheUnloadingTask(uint num_workers, BoolObjectClosure* is_alive, bool unloading_occurred) :
    70       _is_alive(is_alive),
    71       _unloading_scope(is_alive),
    71       _unloading_occurred(unloading_occurred),
    72       _unloading_occurred(unloading_occurred),
    72       _num_workers(num_workers),
    73       _num_workers(num_workers),
    73       _first_nmethod(NULL),
    74       _first_nmethod(NULL),
    74       _claimed_nmethod(NULL),
    75       _claimed_nmethod(NULL) {
    75       _postponed_list(NULL),
       
    76       _num_entered_barrier(0) {
       
    77   CompiledMethod::increase_unloading_clock();
       
    78   // Get first alive nmethod
    76   // Get first alive nmethod
    79   CompiledMethodIterator iter = CompiledMethodIterator();
    77   CompiledMethodIterator iter = CompiledMethodIterator();
    80   if(iter.next_alive()) {
    78   if(iter.next_alive()) {
    81     _first_nmethod = iter.method();
    79     _first_nmethod = iter.method();
    82   }
    80   }
    84 }
    82 }
    85 
    83 
    86 CodeCacheUnloadingTask::~CodeCacheUnloadingTask() {
    84 CodeCacheUnloadingTask::~CodeCacheUnloadingTask() {
    87   CodeCache::verify_clean_inline_caches();
    85   CodeCache::verify_clean_inline_caches();
    88 
    86 
    89   CodeCache::set_needs_cache_clean(false);
       
    90   guarantee(CodeCache::scavenge_root_nmethods() == NULL, "Must be");
    87   guarantee(CodeCache::scavenge_root_nmethods() == NULL, "Must be");
    91 
    88 
    92   CodeCache::verify_icholder_relocations();
    89   CodeCache::verify_icholder_relocations();
    93 }
    90 }
    94 
    91 
    95 Monitor* CodeCacheUnloadingTask::_lock = new Monitor(Mutex::leaf, "Code Cache Unload lock", false, Monitor::_safepoint_check_never);
    92 Monitor* CodeCacheUnloadingTask::_lock = new Monitor(Mutex::leaf, "Code Cache Unload lock", false, Monitor::_safepoint_check_never);
    96 
       
    97 void CodeCacheUnloadingTask::add_to_postponed_list(CompiledMethod* nm) {
       
    98   CompiledMethod* old;
       
    99   do {
       
   100     old = _postponed_list;
       
   101     nm->set_unloading_next(old);
       
   102   } while (Atomic::cmpxchg(nm, &_postponed_list, old) != old);
       
   103 }
       
   104 
       
   105 void CodeCacheUnloadingTask::clean_nmethod(CompiledMethod* nm) {
       
   106   bool postponed = nm->do_unloading_parallel(_is_alive, _unloading_occurred);
       
   107 
       
   108   if (postponed) {
       
   109     // This nmethod referred to an nmethod that has not been cleaned/unloaded yet.
       
   110     add_to_postponed_list(nm);
       
   111   }
       
   112 
       
   113   // Mark that this nmethod has been cleaned/unloaded.
       
   114   // After this call, it will be safe to ask if this nmethod was unloaded or not.
       
   115   nm->set_unloading_clock(CompiledMethod::global_unloading_clock());
       
   116 }
       
   117 
       
   118 void CodeCacheUnloadingTask::clean_nmethod_postponed(CompiledMethod* nm) {
       
   119   nm->do_unloading_parallel_postponed();
       
   120 }
       
   121 
    93 
   122 void CodeCacheUnloadingTask::claim_nmethods(CompiledMethod** claimed_nmethods, int *num_claimed_nmethods) {
    94 void CodeCacheUnloadingTask::claim_nmethods(CompiledMethod** claimed_nmethods, int *num_claimed_nmethods) {
   123   CompiledMethod* first;
    95   CompiledMethod* first;
   124   CompiledMethodIterator last;
    96   CompiledMethodIterator last;
   125 
    97 
   141     }
   113     }
   142 
   114 
   143   } while (Atomic::cmpxchg(last.method(), &_claimed_nmethod, first) != first);
   115   } while (Atomic::cmpxchg(last.method(), &_claimed_nmethod, first) != first);
   144 }
   116 }
   145 
   117 
   146 CompiledMethod* CodeCacheUnloadingTask::claim_postponed_nmethod() {
   118 void CodeCacheUnloadingTask::work(uint worker_id) {
   147   CompiledMethod* claim;
       
   148   CompiledMethod* next;
       
   149 
       
   150   do {
       
   151     claim = _postponed_list;
       
   152     if (claim == NULL) {
       
   153       return NULL;
       
   154     }
       
   155 
       
   156     next = claim->unloading_next();
       
   157 
       
   158   } while (Atomic::cmpxchg(next, &_postponed_list, claim) != claim);
       
   159 
       
   160   return claim;
       
   161 }
       
   162 
       
   163 void CodeCacheUnloadingTask::barrier_mark(uint worker_id) {
       
   164   MonitorLockerEx ml(_lock, Mutex::_no_safepoint_check_flag);
       
   165   _num_entered_barrier++;
       
   166   if (_num_entered_barrier == _num_workers) {
       
   167     ml.notify_all();
       
   168   }
       
   169 }
       
   170 
       
   171 void CodeCacheUnloadingTask::barrier_wait(uint worker_id) {
       
   172   if (_num_entered_barrier < _num_workers) {
       
   173     MonitorLockerEx ml(_lock, Mutex::_no_safepoint_check_flag);
       
   174     while (_num_entered_barrier < _num_workers) {
       
   175         ml.wait(Mutex::_no_safepoint_check_flag, 0, false);
       
   176     }
       
   177   }
       
   178 }
       
   179 
       
   180 void CodeCacheUnloadingTask::work_first_pass(uint worker_id) {
       
   181   // The first nmethods is claimed by the first worker.
   119   // The first nmethods is claimed by the first worker.
   182   if (worker_id == 0 && _first_nmethod != NULL) {
   120   if (worker_id == 0 && _first_nmethod != NULL) {
   183     clean_nmethod(_first_nmethod);
   121     _first_nmethod->do_unloading(_unloading_occurred);
   184     _first_nmethod = NULL;
   122     _first_nmethod = NULL;
   185   }
   123   }
   186 
   124 
   187   int num_claimed_nmethods;
   125   int num_claimed_nmethods;
   188   CompiledMethod* claimed_nmethods[MaxClaimNmethods];
   126   CompiledMethod* claimed_nmethods[MaxClaimNmethods];
   193     if (num_claimed_nmethods == 0) {
   131     if (num_claimed_nmethods == 0) {
   194       break;
   132       break;
   195     }
   133     }
   196 
   134 
   197     for (int i = 0; i < num_claimed_nmethods; i++) {
   135     for (int i = 0; i < num_claimed_nmethods; i++) {
   198       clean_nmethod(claimed_nmethods[i]);
   136       claimed_nmethods[i]->do_unloading(_unloading_occurred);
   199     }
   137     }
   200   }
       
   201 }
       
   202 
       
   203 void CodeCacheUnloadingTask::work_second_pass(uint worker_id) {
       
   204   CompiledMethod* nm;
       
   205   // Take care of postponed nmethods.
       
   206   while ((nm = claim_postponed_nmethod()) != NULL) {
       
   207     clean_nmethod_postponed(nm);
       
   208   }
   138   }
   209 }
   139 }
   210 
   140 
   211 KlassCleaningTask::KlassCleaningTask() :
   141 KlassCleaningTask::KlassCleaningTask() :
   212   _clean_klass_tree_claimed(0),
   142   _clean_klass_tree_claimed(0),
   255   _klass_cleaning_task() {
   185   _klass_cleaning_task() {
   256 }
   186 }
   257 
   187 
   258 // The parallel work done by all worker threads.
   188 // The parallel work done by all worker threads.
   259 void ParallelCleaningTask::work(uint worker_id) {
   189 void ParallelCleaningTask::work(uint worker_id) {
   260     // Do first pass of code cache cleaning.
   190   // Do first pass of code cache cleaning.
   261     _code_cache_task.work_first_pass(worker_id);
   191   _code_cache_task.work(worker_id);
   262 
   192 
   263     // Let the threads mark that the first pass is done.
   193   // Clean the Strings and Symbols.
   264     _code_cache_task.barrier_mark(worker_id);
   194   _string_task.work(worker_id);
   265 
       
   266     // Clean the Strings and Symbols.
       
   267     _string_task.work(worker_id);
       
   268 
       
   269     // Wait for all workers to finish the first code cache cleaning pass.
       
   270     _code_cache_task.barrier_wait(worker_id);
       
   271 
       
   272     // Do the second code cache cleaning work, which realize on
       
   273     // the liveness information gathered during the first pass.
       
   274     _code_cache_task.work_second_pass(worker_id);
       
   275 
   195 
   276   // Clean all klasses that were not unloaded.
   196   // Clean all klasses that were not unloaded.
   277   // The weak metadata in klass doesn't need to be
   197   // The weak metadata in klass doesn't need to be
   278   // processed if there was no unloading.
   198   // processed if there was no unloading.
   279   if (_unloading_occurred) {
   199   if (_unloading_occurred) {