< prev index next >

src/hotspot/share/gc/g1/g1CollectedHeap.cpp

Print this page




3441     }
3442   }
3443 
3444   size_t strings_processed() const { return (size_t)_strings_processed; }
3445   size_t strings_removed()   const { return (size_t)_strings_removed; }
3446 
3447   size_t symbols_processed() const { return (size_t)_symbols_processed; }
3448   size_t symbols_removed()   const { return (size_t)_symbols_removed; }
3449 };
3450 
3451 class G1CodeCacheUnloadingTask VALUE_OBJ_CLASS_SPEC {
3452 private:
3453   static Monitor* _lock;
3454 
3455   BoolObjectClosure* const _is_alive;
3456   const bool               _unloading_occurred;
3457   const uint               _num_workers;
3458 
3459   // Variables used to claim nmethods.
3460   CompiledMethod* _first_nmethod;
3461   volatile CompiledMethod* _claimed_nmethod;
3462 
3463   // The list of nmethods that need to be processed by the second pass.
3464   volatile CompiledMethod* _postponed_list;
3465   volatile uint            _num_entered_barrier;
3466 
3467  public:
3468   G1CodeCacheUnloadingTask(uint num_workers, BoolObjectClosure* is_alive, bool unloading_occurred) :
3469       _is_alive(is_alive),
3470       _unloading_occurred(unloading_occurred),
3471       _num_workers(num_workers),
3472       _first_nmethod(NULL),
3473       _claimed_nmethod(NULL),
3474       _postponed_list(NULL),
3475       _num_entered_barrier(0)
3476   {
3477     CompiledMethod::increase_unloading_clock();
3478     // Get first alive nmethod
3479     CompiledMethodIterator iter = CompiledMethodIterator();
3480     if(iter.next_alive()) {
3481       _first_nmethod = iter.method();
3482     }
3483     _claimed_nmethod = (volatile CompiledMethod*)_first_nmethod;
3484   }
3485 
3486   ~G1CodeCacheUnloadingTask() {
3487     CodeCache::verify_clean_inline_caches();
3488 
3489     CodeCache::set_needs_cache_clean(false);
3490     guarantee(CodeCache::scavenge_root_nmethods() == NULL, "Must be");
3491 
3492     CodeCache::verify_icholder_relocations();
3493   }
3494 
3495  private:
3496   void add_to_postponed_list(CompiledMethod* nm) {
3497       CompiledMethod* old;
3498       do {
3499         old = (CompiledMethod*)_postponed_list;
3500         nm->set_unloading_next(old);
3501       } while (Atomic::cmpxchg(nm, &_postponed_list, old) != old);
3502   }
3503 
3504   void clean_nmethod(CompiledMethod* nm) {
3505     bool postponed = nm->do_unloading_parallel(_is_alive, _unloading_occurred);
3506 
3507     if (postponed) {
3508       // This nmethod referred to an nmethod that has not been cleaned/unloaded yet.
3509       add_to_postponed_list(nm);
3510     }
3511 
3512     // Mark that this thread has been cleaned/unloaded.
3513     // After this call, it will be safe to ask if this nmethod was unloaded or not.
3514     nm->set_unloading_clock(CompiledMethod::global_unloading_clock());
3515   }
3516 
3517   void clean_nmethod_postponed(CompiledMethod* nm) {
3518     nm->do_unloading_parallel_postponed(_is_alive, _unloading_occurred);
3519   }
3520 
3521   static const int MaxClaimNmethods = 16;
3522 
3523   void claim_nmethods(CompiledMethod** claimed_nmethods, int *num_claimed_nmethods) {
3524     CompiledMethod* first;
3525     CompiledMethodIterator last;
3526 
3527     do {
3528       *num_claimed_nmethods = 0;
3529 
3530       first = (CompiledMethod*)_claimed_nmethod;
3531       last = CompiledMethodIterator(first);
3532 
3533       if (first != NULL) {
3534 
3535         for (int i = 0; i < MaxClaimNmethods; i++) {
3536           if (!last.next_alive()) {
3537             break;
3538           }
3539           claimed_nmethods[i] = last.method();
3540           (*num_claimed_nmethods)++;
3541         }
3542       }
3543 
3544     } while (Atomic::cmpxchg(last.method(), &_claimed_nmethod, first) != first);
3545   }
3546 
3547   CompiledMethod* claim_postponed_nmethod() {
3548     CompiledMethod* claim;
3549     CompiledMethod* next;
3550 
3551     do {
3552       claim = (CompiledMethod*)_postponed_list;
3553       if (claim == NULL) {
3554         return NULL;
3555       }
3556 
3557       next = claim->unloading_next();
3558 
3559     } while (Atomic::cmpxchg(next, &_postponed_list, claim) != claim);
3560 
3561     return claim;
3562   }
3563 
3564  public:
3565   // Mark that we're done with the first pass of nmethod cleaning.
3566   void barrier_mark(uint worker_id) {
3567     MonitorLockerEx ml(_lock, Mutex::_no_safepoint_check_flag);
3568     _num_entered_barrier++;
3569     if (_num_entered_barrier == _num_workers) {
3570       ml.notify_all();
3571     }
3572   }




3441     }
3442   }
3443 
3444   size_t strings_processed() const { return (size_t)_strings_processed; }
3445   size_t strings_removed()   const { return (size_t)_strings_removed; }
3446 
3447   size_t symbols_processed() const { return (size_t)_symbols_processed; }
3448   size_t symbols_removed()   const { return (size_t)_symbols_removed; }
3449 };
3450 
3451 class G1CodeCacheUnloadingTask VALUE_OBJ_CLASS_SPEC {
3452 private:
3453   static Monitor* _lock;
3454 
3455   BoolObjectClosure* const _is_alive;
3456   const bool               _unloading_occurred;
3457   const uint               _num_workers;
3458 
3459   // Variables used to claim nmethods.
3460   CompiledMethod* _first_nmethod;
3461   CompiledMethod* volatile _claimed_nmethod;
3462 
3463   // The list of nmethods that need to be processed by the second pass.
3464   CompiledMethod* volatile _postponed_list;
3465   volatile uint            _num_entered_barrier;
3466 
3467  public:
3468   G1CodeCacheUnloadingTask(uint num_workers, BoolObjectClosure* is_alive, bool unloading_occurred) :
3469       _is_alive(is_alive),
3470       _unloading_occurred(unloading_occurred),
3471       _num_workers(num_workers),
3472       _first_nmethod(NULL),
3473       _claimed_nmethod(NULL),
3474       _postponed_list(NULL),
3475       _num_entered_barrier(0)
3476   {
3477     CompiledMethod::increase_unloading_clock();
3478     // Get first alive nmethod
3479     CompiledMethodIterator iter = CompiledMethodIterator();
3480     if(iter.next_alive()) {
3481       _first_nmethod = iter.method();
3482     }
3483     _claimed_nmethod = _first_nmethod;
3484   }
3485 
3486   ~G1CodeCacheUnloadingTask() {
3487     CodeCache::verify_clean_inline_caches();
3488 
3489     CodeCache::set_needs_cache_clean(false);
3490     guarantee(CodeCache::scavenge_root_nmethods() == NULL, "Must be");
3491 
3492     CodeCache::verify_icholder_relocations();
3493   }
3494 
3495  private:
3496   void add_to_postponed_list(CompiledMethod* nm) {
3497       CompiledMethod* old;
3498       do {
3499         old = _postponed_list;
3500         nm->set_unloading_next(old);
3501       } while (Atomic::cmpxchg(nm, &_postponed_list, old) != old);
3502   }
3503 
3504   void clean_nmethod(CompiledMethod* nm) {
3505     bool postponed = nm->do_unloading_parallel(_is_alive, _unloading_occurred);
3506 
3507     if (postponed) {
3508       // This nmethod referred to an nmethod that has not been cleaned/unloaded yet.
3509       add_to_postponed_list(nm);
3510     }
3511 
3512     // Mark that this thread has been cleaned/unloaded.
3513     // After this call, it will be safe to ask if this nmethod was unloaded or not.
3514     nm->set_unloading_clock(CompiledMethod::global_unloading_clock());
3515   }
3516 
3517   void clean_nmethod_postponed(CompiledMethod* nm) {
3518     nm->do_unloading_parallel_postponed(_is_alive, _unloading_occurred);
3519   }
3520 
3521   static const int MaxClaimNmethods = 16;
3522 
3523   void claim_nmethods(CompiledMethod** claimed_nmethods, int *num_claimed_nmethods) {
3524     CompiledMethod* first;
3525     CompiledMethodIterator last;
3526 
3527     do {
3528       *num_claimed_nmethods = 0;
3529 
3530       first = _claimed_nmethod;
3531       last = CompiledMethodIterator(first);
3532 
3533       if (first != NULL) {
3534 
3535         for (int i = 0; i < MaxClaimNmethods; i++) {
3536           if (!last.next_alive()) {
3537             break;
3538           }
3539           claimed_nmethods[i] = last.method();
3540           (*num_claimed_nmethods)++;
3541         }
3542       }
3543 
3544     } while (Atomic::cmpxchg(last.method(), &_claimed_nmethod, first) != first);
3545   }
3546 
3547   CompiledMethod* claim_postponed_nmethod() {
3548     CompiledMethod* claim;
3549     CompiledMethod* next;
3550 
3551     do {
3552       claim = _postponed_list;
3553       if (claim == NULL) {
3554         return NULL;
3555       }
3556 
3557       next = claim->unloading_next();
3558 
3559     } while (Atomic::cmpxchg(next, &_postponed_list, claim) != claim);
3560 
3561     return claim;
3562   }
3563 
3564  public:
3565   // Mark that we're done with the first pass of nmethod cleaning.
3566   void barrier_mark(uint worker_id) {
3567     MonitorLockerEx ml(_lock, Mutex::_no_safepoint_check_flag);
3568     _num_entered_barrier++;
3569     if (_num_entered_barrier == _num_workers) {
3570       ml.notify_all();
3571     }
3572   }


< prev index next >