< prev index next >

src/hotspot/share/code/compiledMethod.cpp


528 // nmethods are unloaded.  Return postponed=true in the parallel case for                                                            
529 // inline caches found that point to nmethods that are not yet visited during                                                        
530 // the do_unloading walk.                                                                                                            
531 void CompiledMethod::unload_nmethod_caches(bool unloading_occurred) {                                                                
532   ResourceMark rm;                                                                                                                   
533 
534   // Exception cache only needs to be called if unloading occurred                                                                   
535   if (unloading_occurred) {                                                                                                          
536     clean_exception_cache();                                                                                                         
537   }                                                                                                                                  
538 
539   cleanup_inline_caches_impl(unloading_occurred, false);                                                                             
540 
541   // All static stubs need to be cleaned.                                                                                            
542   clean_ic_stubs();                                                                                                                  
543 
544   // Check that the metadata embedded in the nmethod is alive                                                                        
545   DEBUG_ONLY(metadata_do(check_class));                                                                                              
546 }                                                                                                                                    
547 
548 // The IsUnloadingStruct represents a tuple comprising a result of                                                                   
549 // IsUnloadingBehaviour::is_unloading() for a given unloading cycle.                                                                 
550 struct IsUnloadingStruct {                                                                                                           
551   unsigned int _is_unloading:1;                                                                                                      
552   unsigned int _unloading_cycle:2;                                                                                                   
553 };                                                                                                                                   
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
554 
555 // The IsUnloadingUnion allows treating the tuple of the IsUnloadingStruct                                                           
556 // like a uint8_t, making it possible to read and write the tuple atomically.                                                        
557 union IsUnloadingUnion {                                                                                                             
558   IsUnloadingStruct _inflated;                                                                                                       
559   uint8_t _value;                                                                                                                    
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
                                                                                                                                     
560 };                                                                                                                                   
561 
562 bool CompiledMethod::is_unloading() {                                                                                                
563   IsUnloadingUnion state;                                                                                                            
564   state._value = RawAccess<MO_RELAXED>::load(&_is_unloading_state);                                                                  
565   if (state._inflated._is_unloading == 1) {                                                                                          
                                                                                                                                     
566     return true;                                                                                                                     
567   }                                                                                                                                  
568   if (state._inflated._unloading_cycle == CodeCache::unloading_cycle()) {                                                            
569     return state._inflated._is_unloading == 1;                                                                                       
570   }                                                                                                                                  
571 
572   // The IsUnloadingBehaviour is responsible for checking if there are any dead                                                      
573   // oops in the CompiledMethod, by calling oops_do on it.                                                                           
574   bool result = IsUnloadingBehaviour::current()->is_unloading(this);                                                                 
                                                                                                                                     
575 
576   state._inflated._unloading_cycle = CodeCache::unloading_cycle();                                                                   
577   state._inflated._is_unloading = result ? 1 : 0;                                                                                    
578 
579   RawAccess<MO_RELAXED>::store(&_is_unloading_state, state._value);                                                                  
580 
581   return result;                                                                                                                     
582 }                                                                                                                                    
583 
584 void CompiledMethod::clear_unloading_state() {                                                                                       
585   IsUnloadingUnion state;                                                                                                            
586   state._inflated._unloading_cycle = CodeCache::unloading_cycle();                                                                   
587   state._inflated._is_unloading = 0;                                                                                                 
588   RawAccess<MO_RELAXED>::store(&_is_unloading_state, state._value);                                                                  
589 }                                                                                                                                    
590 
591 // Called to clean up after class unloading for live nmethods and from the sweeper                                                   
592 // for all methods.                                                                                                                  
593 void CompiledMethod::cleanup_inline_caches_impl(bool unloading_occurred, bool clean_all) {                                           
594   assert(CompiledICLocker::is_safe(this), "mt unsafe call");                                                                         
595   ResourceMark rm;                                                                                                                   
596 
597   // Find all calls in an nmethod and clear the ones that point to non-entrant,                                                      
598   // zombie and unloaded nmethods.                                                                                                   
599   RelocIterator iter(this, oops_reloc_begin());                                                                                      
600   while(iter.next()) {                                                                                                               
601 
602     switch (iter.type()) {                                                                                                           
603 
604     case relocInfo::virtual_call_type:                                                                                               
605       if (unloading_occurred) {                                                                                                      
606         // If class unloading occurred we first clear ICs where the cached metadata                                                  
607         // is referring to an unloaded klass or method.                                                                              

528 // nmethods are unloaded.  Return postponed=true in the parallel case for
529 // inline caches found that point to nmethods that are not yet visited during
530 // the do_unloading walk.
531 void CompiledMethod::unload_nmethod_caches(bool unloading_occurred) {
532   ResourceMark rm;
533 
534   // Exception cache only needs to be called if unloading occurred
535   if (unloading_occurred) {
536     clean_exception_cache();
537   }
538 
539   cleanup_inline_caches_impl(unloading_occurred, false);
540 
541   // All static stubs need to be cleaned.
542   clean_ic_stubs();
543 
544   // Check that the metadata embedded in the nmethod is alive
545   DEBUG_ONLY(metadata_do(check_class));
546 }
547 
548 // The _is_unloading_state encodes a tuple comprising the unloading cycle
549 // and the result of IsUnloadingBehaviour::is_unloading() fpr that cycle.
550 // This is the bit layout of the _is_unloading_state byte: 00000CCU
551 // CC refers to the cycle, which has 2 bits, and U refers to the result of
552 // IsUnloadingBehaviour::is_unloading() for that unloading cycle.
553 
554 class IsUnloadingState: public AllStatic {
555   static const uint8_t _is_unloading_mask = 1;
556   static const uint8_t _is_unloading_shift = 0;
557   static const uint8_t _unloading_cycle_mask = 6;
558   static const uint8_t _unloading_cycle_shift = 1;
559 
560   static uint8_t set_is_unloading(uint8_t state, bool value) {
561     state &= ~_is_unloading_mask;
562     if (value) {
563       state |= 1 << _is_unloading_shift;
564     }
565     assert(is_unloading(state) == value, "unexpected unloading cycle overflow");
566     return state;
567   }
568 
569   static uint8_t set_unloading_cycle(uint8_t state, uint8_t value) {
570     state &= ~_unloading_cycle_mask;
571     state |= value << _unloading_cycle_shift;
572     assert(unloading_cycle(state) == value, "unexpected unloading cycle overflow");
573     return state;
574   }
575 
576 public:
577   static bool is_unloading(uint8_t state) { return (state & _is_unloading_mask) >> _is_unloading_shift == 1; }
578   static uint8_t unloading_cycle(uint8_t state) { return (state & _unloading_cycle_mask) >> _unloading_cycle_shift; }
579 
580   static uint8_t create(bool is_unloading, uint8_t unloading_cycle) {
581     uint8_t state = 0;
582     state = set_is_unloading(state, is_unloading);
583     state = set_unloading_cycle(state, unloading_cycle);
584     return state;
585   }
586 };
587 
588 bool CompiledMethod::is_unloading() {
589   uint8_t state = RawAccess<MO_RELAXED>::load(&_is_unloading_state);
590   bool state_is_unloading = IsUnloadingState::is_unloading(state);
591   uint8_t state_unloading_cycle = IsUnloadingState::unloading_cycle(state);
592   if (state_is_unloading) {
593     return true;
594   }
595   if (state_unloading_cycle == CodeCache::unloading_cycle()) {
596     return false;
597   }
598 
599   // The IsUnloadingBehaviour is responsible for checking if there are any dead
600   // oops in the CompiledMethod, by calling oops_do on it.
601   state_unloading_cycle = CodeCache::unloading_cycle();
602   state_is_unloading = IsUnloadingBehaviour::current()->is_unloading(this);
603 
604   state = IsUnloadingState::create(state_is_unloading, state_unloading_cycle);

605 
606   RawAccess<MO_RELAXED>::store(&_is_unloading_state, state);
607 
608   return state_is_unloading;
609 }
610 
611 void CompiledMethod::clear_unloading_state() {
612   uint8_t state = IsUnloadingState::create(false, CodeCache::unloading_cycle());
613   RawAccess<MO_RELAXED>::store(&_is_unloading_state, state);


614 }
615 
616 // Called to clean up after class unloading for live nmethods and from the sweeper
617 // for all methods.
618 void CompiledMethod::cleanup_inline_caches_impl(bool unloading_occurred, bool clean_all) {
619   assert(CompiledICLocker::is_safe(this), "mt unsafe call");
620   ResourceMark rm;
621 
622   // Find all calls in an nmethod and clear the ones that point to non-entrant,
623   // zombie and unloaded nmethods.
624   RelocIterator iter(this, oops_reloc_begin());
625   while(iter.next()) {
626 
627     switch (iter.type()) {
628 
629     case relocInfo::virtual_call_type:
630       if (unloading_occurred) {
631         // If class unloading occurred we first clear ICs where the cached metadata
632         // is referring to an unloaded klass or method.
< prev index next >