src/hotspot/share/code/compiledMethod.cpp
changeset 52453 6e99148dbf33
parent 52410 9d3abb1b7b1f
child 52659 8b26bd8b1832
equal deleted inserted replaced
52452:3315e47741c7 52453:6e99148dbf33
   544 
   544 
   545   // Check that the metadata embedded in the nmethod is alive
   545   // Check that the metadata embedded in the nmethod is alive
   546   DEBUG_ONLY(metadata_do(check_class));
   546   DEBUG_ONLY(metadata_do(check_class));
   547 }
   547 }
   548 
   548 
   549 // The IsUnloadingStruct represents a tuple comprising a result of
   549 // The _is_unloading_state encodes a tuple comprising the unloading cycle
   550 // IsUnloadingBehaviour::is_unloading() for a given unloading cycle.
   550 // and the result of IsUnloadingBehaviour::is_unloading() fpr that cycle.
   551 struct IsUnloadingStruct {
   551 // This is the bit layout of the _is_unloading_state byte: 00000CCU
   552   unsigned int _is_unloading:1;
   552 // CC refers to the cycle, which has 2 bits, and U refers to the result of
   553   unsigned int _unloading_cycle:2;
   553 // IsUnloadingBehaviour::is_unloading() for that unloading cycle.
       
   554 
       
   555 class IsUnloadingState: public AllStatic {
       
   556   static const uint8_t _is_unloading_mask = 1;
       
   557   static const uint8_t _is_unloading_shift = 0;
       
   558   static const uint8_t _unloading_cycle_mask = 6;
       
   559   static const uint8_t _unloading_cycle_shift = 1;
       
   560 
       
   561   static uint8_t set_is_unloading(uint8_t state, bool value) {
       
   562     state &= ~_is_unloading_mask;
       
   563     if (value) {
       
   564       state |= 1 << _is_unloading_shift;
       
   565     }
       
   566     assert(is_unloading(state) == value, "unexpected unloading cycle overflow");
       
   567     return state;
       
   568   }
       
   569 
       
   570   static uint8_t set_unloading_cycle(uint8_t state, uint8_t value) {
       
   571     state &= ~_unloading_cycle_mask;
       
   572     state |= value << _unloading_cycle_shift;
       
   573     assert(unloading_cycle(state) == value, "unexpected unloading cycle overflow");
       
   574     return state;
       
   575   }
       
   576 
       
   577 public:
       
   578   static bool is_unloading(uint8_t state) { return (state & _is_unloading_mask) >> _is_unloading_shift == 1; }
       
   579   static uint8_t unloading_cycle(uint8_t state) { return (state & _unloading_cycle_mask) >> _unloading_cycle_shift; }
       
   580 
       
   581   static uint8_t create(bool is_unloading, uint8_t unloading_cycle) {
       
   582     uint8_t state = 0;
       
   583     state = set_is_unloading(state, is_unloading);
       
   584     state = set_unloading_cycle(state, unloading_cycle);
       
   585     return state;
       
   586   }
   554 };
   587 };
   555 
   588 
   556 // The IsUnloadingUnion allows treating the tuple of the IsUnloadingStruct
       
   557 // like a uint8_t, making it possible to read and write the tuple atomically.
       
   558 union IsUnloadingUnion {
       
   559   IsUnloadingStruct _inflated;
       
   560   uint8_t _value;
       
   561 };
       
   562 
       
   563 bool CompiledMethod::is_unloading() {
   589 bool CompiledMethod::is_unloading() {
   564   IsUnloadingUnion state;
   590   uint8_t state = RawAccess<MO_RELAXED>::load(&_is_unloading_state);
   565   state._value = RawAccess<MO_RELAXED>::load(&_is_unloading_state);
   591   bool state_is_unloading = IsUnloadingState::is_unloading(state);
   566   if (state._inflated._is_unloading == 1) {
   592   uint8_t state_unloading_cycle = IsUnloadingState::unloading_cycle(state);
       
   593   if (state_is_unloading) {
   567     return true;
   594     return true;
   568   }
   595   }
   569   if (state._inflated._unloading_cycle == CodeCache::unloading_cycle()) {
   596   if (state_unloading_cycle == CodeCache::unloading_cycle()) {
   570     return state._inflated._is_unloading == 1;
   597     return false;
   571   }
   598   }
   572 
   599 
   573   // The IsUnloadingBehaviour is responsible for checking if there are any dead
   600   // The IsUnloadingBehaviour is responsible for checking if there are any dead
   574   // oops in the CompiledMethod, by calling oops_do on it.
   601   // oops in the CompiledMethod, by calling oops_do on it.
   575   bool result = IsUnloadingBehaviour::current()->is_unloading(this);
   602   state_unloading_cycle = CodeCache::unloading_cycle();
   576 
   603   state_is_unloading = IsUnloadingBehaviour::current()->is_unloading(this);
   577   state._inflated._unloading_cycle = CodeCache::unloading_cycle();
   604 
   578   state._inflated._is_unloading = result ? 1 : 0;
   605   state = IsUnloadingState::create(state_is_unloading, state_unloading_cycle);
   579 
   606 
   580   RawAccess<MO_RELAXED>::store(&_is_unloading_state, state._value);
   607   RawAccess<MO_RELAXED>::store(&_is_unloading_state, state);
   581 
   608 
   582   return result;
   609   return state_is_unloading;
   583 }
   610 }
   584 
   611 
   585 void CompiledMethod::clear_unloading_state() {
   612 void CompiledMethod::clear_unloading_state() {
   586   IsUnloadingUnion state;
   613   uint8_t state = IsUnloadingState::create(false, CodeCache::unloading_cycle());
   587   state._inflated._unloading_cycle = CodeCache::unloading_cycle();
   614   RawAccess<MO_RELAXED>::store(&_is_unloading_state, state);
   588   state._inflated._is_unloading = 0;
       
   589   RawAccess<MO_RELAXED>::store(&_is_unloading_state, state._value);
       
   590 }
   615 }
   591 
   616 
   592 // Called to clean up after class unloading for live nmethods and from the sweeper
   617 // Called to clean up after class unloading for live nmethods and from the sweeper
   593 // for all methods.
   618 // for all methods.
   594 void CompiledMethod::cleanup_inline_caches_impl(bool unloading_occurred, bool clean_all) {
   619 void CompiledMethod::cleanup_inline_caches_impl(bool unloading_occurred, bool clean_all) {