mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-08 17:38:38 +00:00
8009575: Reduce Symbol::_refcount from 4 bytes to 2 bytes
Added Atomic::inc(short*) to support this change. Reviewed-by: coleenp, dcubed, dholmes, minqi
This commit is contained in:
parent
1c281a9fb3
commit
196c8abc3d
@ -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]);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -379,7 +379,7 @@ typedef BinaryTreeDictionary<Metablock, FreeList> 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 */ \
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user