8213411: JDK-8209189 incorrect for Big Endian (JVM crashes)
Reviewed-by: kvn, mdoerr
This commit is contained in:
parent
1ce3770481
commit
c9e3ee1fbb
@ -192,7 +192,7 @@ class CodeCache : AllStatic {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
static void do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred);
|
static void do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred);
|
||||||
static uint16_t unloading_cycle() { return _unloading_cycle; }
|
static uint8_t unloading_cycle() { return _unloading_cycle; }
|
||||||
static void increment_unloading_cycle();
|
static void increment_unloading_cycle();
|
||||||
static void asserted_non_scavengable_nmethods_do(CodeBlobClosure* f = NULL) PRODUCT_RETURN;
|
static void asserted_non_scavengable_nmethods_do(CodeBlobClosure* f = NULL) PRODUCT_RETURN;
|
||||||
static void release_exception_cache(ExceptionCache* entry);
|
static void release_exception_cache(ExceptionCache* entry);
|
||||||
|
@ -546,47 +546,72 @@ void CompiledMethod::unload_nmethod_caches(bool unloading_occurred) {
|
|||||||
DEBUG_ONLY(metadata_do(check_class));
|
DEBUG_ONLY(metadata_do(check_class));
|
||||||
}
|
}
|
||||||
|
|
||||||
// The IsUnloadingStruct represents a tuple comprising a result of
|
// The _is_unloading_state encodes a tuple comprising the unloading cycle
|
||||||
// IsUnloadingBehaviour::is_unloading() for a given unloading cycle.
|
// and the result of IsUnloadingBehaviour::is_unloading() fpr that cycle.
|
||||||
struct IsUnloadingStruct {
|
// This is the bit layout of the _is_unloading_state byte: 00000CCU
|
||||||
unsigned int _is_unloading:1;
|
// CC refers to the cycle, which has 2 bits, and U refers to the result of
|
||||||
unsigned int _unloading_cycle:2;
|
// IsUnloadingBehaviour::is_unloading() for that unloading cycle.
|
||||||
};
|
|
||||||
|
|
||||||
// The IsUnloadingUnion allows treating the tuple of the IsUnloadingStruct
|
class IsUnloadingState: public AllStatic {
|
||||||
// like a uint8_t, making it possible to read and write the tuple atomically.
|
static const uint8_t _is_unloading_mask = 1;
|
||||||
union IsUnloadingUnion {
|
static const uint8_t _is_unloading_shift = 0;
|
||||||
IsUnloadingStruct _inflated;
|
static const uint8_t _unloading_cycle_mask = 6;
|
||||||
uint8_t _value;
|
static const uint8_t _unloading_cycle_shift = 1;
|
||||||
|
|
||||||
|
static uint8_t set_is_unloading(uint8_t state, bool value) {
|
||||||
|
state &= ~_is_unloading_mask;
|
||||||
|
if (value) {
|
||||||
|
state |= 1 << _is_unloading_shift;
|
||||||
|
}
|
||||||
|
assert(is_unloading(state) == value, "unexpected unloading cycle overflow");
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t set_unloading_cycle(uint8_t state, uint8_t value) {
|
||||||
|
state &= ~_unloading_cycle_mask;
|
||||||
|
state |= value << _unloading_cycle_shift;
|
||||||
|
assert(unloading_cycle(state) == value, "unexpected unloading cycle overflow");
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool is_unloading(uint8_t state) { return (state & _is_unloading_mask) >> _is_unloading_shift == 1; }
|
||||||
|
static uint8_t unloading_cycle(uint8_t state) { return (state & _unloading_cycle_mask) >> _unloading_cycle_shift; }
|
||||||
|
|
||||||
|
static uint8_t create(bool is_unloading, uint8_t unloading_cycle) {
|
||||||
|
uint8_t state = 0;
|
||||||
|
state = set_is_unloading(state, is_unloading);
|
||||||
|
state = set_unloading_cycle(state, unloading_cycle);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool CompiledMethod::is_unloading() {
|
bool CompiledMethod::is_unloading() {
|
||||||
IsUnloadingUnion state;
|
uint8_t state = RawAccess<MO_RELAXED>::load(&_is_unloading_state);
|
||||||
state._value = RawAccess<MO_RELAXED>::load(&_is_unloading_state);
|
bool state_is_unloading = IsUnloadingState::is_unloading(state);
|
||||||
if (state._inflated._is_unloading == 1) {
|
uint8_t state_unloading_cycle = IsUnloadingState::unloading_cycle(state);
|
||||||
|
if (state_is_unloading) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (state._inflated._unloading_cycle == CodeCache::unloading_cycle()) {
|
if (state_unloading_cycle == CodeCache::unloading_cycle()) {
|
||||||
return state._inflated._is_unloading == 1;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The IsUnloadingBehaviour is responsible for checking if there are any dead
|
// The IsUnloadingBehaviour is responsible for checking if there are any dead
|
||||||
// oops in the CompiledMethod, by calling oops_do on it.
|
// oops in the CompiledMethod, by calling oops_do on it.
|
||||||
bool result = IsUnloadingBehaviour::current()->is_unloading(this);
|
state_unloading_cycle = CodeCache::unloading_cycle();
|
||||||
|
state_is_unloading = IsUnloadingBehaviour::current()->is_unloading(this);
|
||||||
|
|
||||||
state._inflated._unloading_cycle = CodeCache::unloading_cycle();
|
state = IsUnloadingState::create(state_is_unloading, state_unloading_cycle);
|
||||||
state._inflated._is_unloading = result ? 1 : 0;
|
|
||||||
|
|
||||||
RawAccess<MO_RELAXED>::store(&_is_unloading_state, state._value);
|
RawAccess<MO_RELAXED>::store(&_is_unloading_state, state);
|
||||||
|
|
||||||
return result;
|
return state_is_unloading;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompiledMethod::clear_unloading_state() {
|
void CompiledMethod::clear_unloading_state() {
|
||||||
IsUnloadingUnion state;
|
uint8_t state = IsUnloadingState::create(false, CodeCache::unloading_cycle());
|
||||||
state._inflated._unloading_cycle = CodeCache::unloading_cycle();
|
RawAccess<MO_RELAXED>::store(&_is_unloading_state, state);
|
||||||
state._inflated._is_unloading = 0;
|
|
||||||
RawAccess<MO_RELAXED>::store(&_is_unloading_state, state._value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called to clean up after class unloading for live nmethods and from the sweeper
|
// Called to clean up after class unloading for live nmethods and from the sweeper
|
||||||
|
Loading…
x
Reference in New Issue
Block a user