8161280: assert failed: reference count underflow for symbol

Reviewed-by: dholmes, coleenp, kbarrett
This commit is contained in:
Ioi Lam 2016-08-26 06:37:34 -07:00
parent 4aea7b3333
commit e710f3bd8b
2 changed files with 20 additions and 18 deletions

View file

@ -229,24 +229,25 @@ unsigned int Symbol::new_hash(juint seed) {
}
void Symbol::increment_refcount() {
// Only increment the refcount if positive. If negative either
// Only increment the refcount if non-negative. If negative either
// overflow has occurred or it is a permanent symbol in a read only
// shared archive.
if (_refcount >= 0) {
if (_refcount >= 0) { // not a permanent symbol
Atomic::inc(&_refcount);
NOT_PRODUCT(Atomic::inc(&_total_count);)
}
}
void Symbol::decrement_refcount() {
if (_refcount >= 0) {
Atomic::dec(&_refcount);
if (_refcount >= 0) { // not a permanent symbol
jshort new_value = Atomic::add(-1, &_refcount);
#ifdef ASSERT
if (_refcount < 0) {
if (new_value == -1) { // we have transitioned from 0 -> -1
print();
assert(false, "reference count underflow for symbol");
}
#endif
(void)new_value;
}
}

View file

@ -76,6 +76,7 @@ class Atomic : AllStatic {
// Atomically add to a location. Returns updated value. add*() provide:
// <fence> add-value-to-dest <membar StoreLoad|StoreStore>
inline static jshort add (jshort add_value, volatile jshort* dest);
inline static jint add (jint add_value, volatile jint* dest);
inline static size_t add (size_t add_value, volatile size_t* dest);
inline static intptr_t add_ptr(intptr_t add_value, volatile intptr_t* dest);
@ -208,10 +209,11 @@ inline jlong Atomic::add(jlong add_value, volatile jlong* dest) {
return old;
}
inline void Atomic::inc(volatile short* dest) {
// Most platforms do not support atomic increment on a 2-byte value. However,
inline jshort Atomic::add(jshort add_value, volatile jshort* dest) {
// Most platforms do not support atomic add on a 2-byte value. However,
// if the value occupies the most significant 16 bits of an aligned 32-bit
// word, then we can do this with an atomic add of 0x10000 to the 32-bit word.
// word, then we can do this with an atomic add of (add_value << 16)
// to the 32-bit word.
//
// The least significant parts of this 32-bit word will never be affected, even
// in case of overflow/underflow.
@ -219,21 +221,20 @@ inline void Atomic::inc(volatile short* dest) {
// Use the ATOMIC_SHORT_PAIR macro (see macros.hpp) to get the desired alignment.
#ifdef VM_LITTLE_ENDIAN
assert((intx(dest) & 0x03) == 0x02, "wrong alignment");
(void)Atomic::add(0x10000, (volatile int*)(dest-1));
jint new_value = Atomic::add(add_value << 16, (volatile jint*)(dest-1));
#else
assert((intx(dest) & 0x03) == 0x00, "wrong alignment");
(void)Atomic::add(0x10000, (volatile int*)(dest));
jint new_value = Atomic::add(add_value << 16, (volatile jint*)(dest));
#endif
return (jshort)(new_value >> 16); // preserves sign
}
inline void Atomic::dec(volatile short* dest) {
#ifdef VM_LITTLE_ENDIAN
assert((intx(dest) & 0x03) == 0x02, "wrong alignment");
(void)Atomic::add(-0x10000, (volatile int*)(dest-1));
#else
assert((intx(dest) & 0x03) == 0x00, "wrong alignment");
(void)Atomic::add(-0x10000, (volatile int*)(dest));
#endif
inline void Atomic::inc(volatile jshort* dest) {
(void)add(1, dest);
}
inline void Atomic::dec(volatile jshort* dest) {
(void)add(-1, dest);
}
#endif // SHARE_VM_RUNTIME_ATOMIC_HPP