1573 bool state_is_unloading = IsUnloadingState::is_unloading(state); |
1573 bool state_is_unloading = IsUnloadingState::is_unloading(state); |
1574 uint8_t state_unloading_cycle = IsUnloadingState::unloading_cycle(state); |
1574 uint8_t state_unloading_cycle = IsUnloadingState::unloading_cycle(state); |
1575 if (state_is_unloading) { |
1575 if (state_is_unloading) { |
1576 return true; |
1576 return true; |
1577 } |
1577 } |
1578 if (state_unloading_cycle == CodeCache::unloading_cycle()) { |
1578 uint8_t current_cycle = CodeCache::unloading_cycle(); |
|
1579 if (state_unloading_cycle == current_cycle) { |
1579 return false; |
1580 return false; |
1580 } |
1581 } |
1581 |
1582 |
1582 // The IsUnloadingBehaviour is responsible for checking if there are any dead |
1583 // The IsUnloadingBehaviour is responsible for checking if there are any dead |
1583 // oops in the CompiledMethod, by calling oops_do on it. |
1584 // oops in the CompiledMethod, by calling oops_do on it. |
1584 state_unloading_cycle = CodeCache::unloading_cycle(); |
1585 state_unloading_cycle = current_cycle; |
1585 state_is_unloading = IsUnloadingBehaviour::current()->is_unloading(this); |
1586 |
|
1587 if (is_zombie()) { |
|
1588 // Zombies without calculated unloading epoch are never unloading due to GC. |
|
1589 |
|
1590 // There are no races where a previously observed is_unloading() nmethod |
|
1591 // suddenly becomes not is_unloading() due to here being observed as zombie. |
|
1592 |
|
1593 // With STW unloading, all is_alive() && is_unloading() nmethods are unlinked |
|
1594 // and unloaded in the safepoint. That makes races where an nmethod is first |
|
1595 // observed as is_alive() && is_unloading() and subsequently observed as |
|
1596 // is_zombie() impossible. |
|
1597 |
|
1598 // With concurrent unloading, all references to is_unloading() nmethods are |
|
1599 // first unlinked (e.g. IC caches and dependency contexts). Then a global |
|
1600 // handshake operation is performed with all JavaThreads before finally |
|
1601 // unloading the nmethods. The sweeper never converts is_alive() && is_unloading() |
|
1602 // nmethods to zombies; it waits for them to become is_unloaded(). So before |
|
1603 // the global handshake, it is impossible for is_unloading() nmethods to |
|
1604 // racingly become is_zombie(). And is_unloading() is calculated for all is_alive() |
|
1605 // nmethods before taking that global handshake, meaning that it will never |
|
1606 // be recalculated after the handshake. |
|
1607 |
|
1608 // After that global handshake, is_unloading() nmethods are only observable |
|
1609 // to the iterators, and they will never trigger recomputation of the cached |
|
1610 // is_unloading_state, and hence may not suffer from such races. |
|
1611 |
|
1612 state_is_unloading = false; |
|
1613 } else { |
|
1614 state_is_unloading = IsUnloadingBehaviour::current()->is_unloading(this); |
|
1615 } |
1586 |
1616 |
1587 state = IsUnloadingState::create(state_is_unloading, state_unloading_cycle); |
1617 state = IsUnloadingState::create(state_is_unloading, state_unloading_cycle); |
1588 |
1618 |
1589 RawAccess<MO_RELAXED>::store(&_is_unloading_state, state); |
1619 RawAccess<MO_RELAXED>::store(&_is_unloading_state, state); |
1590 |
1620 |