diff --git a/src/share/vm/oops/symbol.cpp b/src/share/vm/oops/symbol.cpp index 8ee933bf1350afa1f7d512b287b66874ca3c19a9..f5fdfec99747b268fab77224056d9d5ac1d34d45 100644 --- a/src/share/vm/oops/symbol.cpp +++ b/src/share/vm/oops/symbol.cpp @@ -32,7 +32,9 @@ #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" -Symbol::Symbol(const u1* name, int length, int refcount) : _refcount(refcount), _length(length) { +Symbol::Symbol(const u1* name, int length, int refcount) { + _refcount = refcount; + _length = length; _identity_hash = os::random(); for (int i = 0; i < _length; i++) { byte_at_put(i, name[i]); diff --git a/src/share/vm/oops/symbol.hpp b/src/share/vm/oops/symbol.hpp index d06edf052fc57bb7618380f9c882678ece5204bb..a71bdd454c32fd2471673585260cc706cc4a02a7 100644 --- a/src/share/vm/oops/symbol.hpp +++ b/src/share/vm/oops/symbol.hpp @@ -27,6 +27,7 @@ #include "utilities/utf8.hpp" #include "memory/allocation.hpp" +#include "runtime/atomic.hpp" // A Symbol is a canonicalized string. // All Symbols reside in global SymbolTable and are reference counted. @@ -101,14 +102,22 @@ // type without virtual functions. class ClassLoaderData; -class Symbol : public MetaspaceObj { +// We separate the fields in SymbolBase from Symbol::_body so that +// Symbol::size(int) can correctly calculate the space needed. +class SymbolBase : public MetaspaceObj { + public: + ATOMIC_SHORT_PAIR( + volatile short _refcount, // needs atomic operation + unsigned short _length // number of UTF8 characters in the symbol (does not need atomic op) + ); + int _identity_hash; +}; + +class Symbol : private SymbolBase { friend class VMStructs; friend class SymbolTable; friend class MoveSymbols; private: - volatile int _refcount; - int _identity_hash; - unsigned short _length; // number of UTF8 characters in the symbol jbyte _body[1]; enum { @@ -117,7 +126,7 @@ class Symbol : public MetaspaceObj { }; static int size(int length) { - size_t sz = heap_word_size(sizeof(Symbol) + (length > 0 ? length - 1 : 0)); + size_t sz = heap_word_size(sizeof(SymbolBase) + (length > 0 ? length : 0)); return align_object_size(sz); } diff --git a/src/share/vm/runtime/atomic.cpp b/src/share/vm/runtime/atomic.cpp index dbb66b2f63f89845c76efff8a344731fe65a7f42..87c80ad333579c1c7c873b1039f123e66b291607 100644 --- a/src/share/vm/runtime/atomic.cpp +++ b/src/share/vm/runtime/atomic.cpp @@ -80,3 +80,32 @@ jlong Atomic::add(jlong add_value, volatile jlong* dest) { } return old; } + +void Atomic::inc(volatile short* dest) { + // Most platforms do not support atomic increment 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. + // + // The least significant parts of this 32-bit word will never be affected, even + // in case of overflow/underflow. + // + // Use the ATOMIC_SHORT_PAIR macro to get the desired alignment. +#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 +} + +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 +} + diff --git a/src/share/vm/runtime/atomic.hpp b/src/share/vm/runtime/atomic.hpp index ae40def88d62f3bb3aed168f47ccb6049cde58b9..3f35c3de22a716f65aa9dc3f1e36ca3ab3823c62 100644 --- a/src/share/vm/runtime/atomic.hpp +++ b/src/share/vm/runtime/atomic.hpp @@ -64,11 +64,13 @@ class Atomic : AllStatic { // Atomically increment location inline static void inc (volatile jint* dest); + static void inc (volatile jshort* dest); inline static void inc_ptr(volatile intptr_t* dest); inline static void inc_ptr(volatile void* dest); // Atomically decrement a location inline static void dec (volatile jint* dest); + static void dec (volatile jshort* dest); inline static void dec_ptr(volatile intptr_t* dest); inline static void dec_ptr(volatile void* dest); @@ -95,4 +97,24 @@ class Atomic : AllStatic { inline static void* cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value); }; +// To use Atomic::inc(jshort* dest) and Atomic::dec(jshort* dest), the address must be specially +// aligned, such that (*dest) occupies the upper 16 bits of an aligned 32-bit word. The best way to +// achieve is to place your short value next to another short value, which doesn't need atomic ops. +// +// Example +// ATOMIC_SHORT_PAIR( +// volatile short _refcount, // needs atomic operation +// unsigned short _length // number of UTF8 characters in the symbol (does not need atomic op) +// ); + +#ifdef VM_LITTLE_ENDIAN +#define ATOMIC_SHORT_PAIR(atomic_decl, non_atomic_decl) \ + non_atomic_decl; \ + atomic_decl +#else +#define ATOMIC_SHORT_PAIR(atomic_decl, non_atomic_decl) \ + atomic_decl ; \ + non_atomic_decl +#endif + #endif // SHARE_VM_RUNTIME_ATOMIC_HPP diff --git a/src/share/vm/runtime/vmStructs.cpp b/src/share/vm/runtime/vmStructs.cpp index dff270f163116e3c2bcc6ce88fd4d6cf55bf5464..caf785a2cfb36b4dfc3c74ba005bf36bc9e17451 100644 --- a/src/share/vm/runtime/vmStructs.cpp +++ b/src/share/vm/runtime/vmStructs.cpp @@ -379,7 +379,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; nonstatic_field(ConstMethod, _size_of_parameters, u2) \ nonstatic_field(ObjArrayKlass, _element_klass, Klass*) \ nonstatic_field(ObjArrayKlass, _bottom_klass, Klass*) \ - volatile_nonstatic_field(Symbol, _refcount, int) \ + volatile_nonstatic_field(Symbol, _refcount, short) \ nonstatic_field(Symbol, _identity_hash, int) \ nonstatic_field(Symbol, _length, unsigned short) \ unchecked_nonstatic_field(Symbol, _body, sizeof(jbyte)) /* NOTE: no type */ \