8161280: assert failed: reference count underflow for symbol
Reviewed-by: dholmes, coleenp, kbarrett
--- a/hotspot/src/share/vm/oops/symbol.cpp Fri Aug 26 13:11:20 2016 +0300
+++ b/hotspot/src/share/vm/oops/symbol.cpp Fri Aug 26 06:37:34 2016 -0700
@@ -229,24 +229,25 @@
}
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;
}
}
--- a/hotspot/src/share/vm/runtime/atomic.hpp Fri Aug 26 13:11:20 2016 +0300
+++ b/hotspot/src/share/vm/runtime/atomic.hpp Fri Aug 26 06:37:34 2016 -0700
@@ -76,6 +76,7 @@
// 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 @@
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 @@
// 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