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() { 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 // overflow has occurred or it is a permanent symbol in a read only
// shared archive. // shared archive.
if (_refcount >= 0) { if (_refcount >= 0) { // not a permanent symbol
Atomic::inc(&_refcount); Atomic::inc(&_refcount);
NOT_PRODUCT(Atomic::inc(&_total_count);) NOT_PRODUCT(Atomic::inc(&_total_count);)
} }
} }
void Symbol::decrement_refcount() { void Symbol::decrement_refcount() {
if (_refcount >= 0) { if (_refcount >= 0) { // not a permanent symbol
Atomic::dec(&_refcount); jshort new_value = Atomic::add(-1, &_refcount);
#ifdef ASSERT #ifdef ASSERT
if (_refcount < 0) { if (new_value == -1) { // we have transitioned from 0 -> -1
print(); print();
assert(false, "reference count underflow for symbol"); assert(false, "reference count underflow for symbol");
} }
#endif #endif
(void)new_value;
} }
} }

View file

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