8239347: Refactor Symbol to make _length a standalone field again
Reviewed-by: iklam, coleenp
This commit is contained in:
parent
90ee2c3d6e
commit
58a5910393
@ -213,7 +213,7 @@ int generateJvmOffsets(GEN_variant gen_variant) {
|
|||||||
GEN_VALUE(AccessFlags_NATIVE, JVM_ACC_NATIVE);
|
GEN_VALUE(AccessFlags_NATIVE, JVM_ACC_NATIVE);
|
||||||
GEN_VALUE(ConstMethod_has_linenumber_table, ConstMethod::_has_linenumber_table);
|
GEN_VALUE(ConstMethod_has_linenumber_table, ConstMethod::_has_linenumber_table);
|
||||||
GEN_OFFS(AccessFlags, _flags);
|
GEN_OFFS(AccessFlags, _flags);
|
||||||
GEN_OFFS(Symbol, _length_and_refcount);
|
GEN_OFFS(Symbol, _length);
|
||||||
GEN_OFFS(Symbol, _body);
|
GEN_OFFS(Symbol, _body);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ dtrace:helper:ustack:
|
|||||||
copyin_offset(OFFSET_HeapBlockHeader_used);
|
copyin_offset(OFFSET_HeapBlockHeader_used);
|
||||||
copyin_offset(OFFSET_oopDesc_metadata);
|
copyin_offset(OFFSET_oopDesc_metadata);
|
||||||
|
|
||||||
copyin_offset(OFFSET_Symbol_length_and_refcount);
|
copyin_offset(OFFSET_Symbol_length);
|
||||||
copyin_offset(OFFSET_Symbol_body);
|
copyin_offset(OFFSET_Symbol_body);
|
||||||
|
|
||||||
copyin_offset(OFFSET_Method_constMethod);
|
copyin_offset(OFFSET_Method_constMethod);
|
||||||
@ -463,17 +463,15 @@ dtrace:helper:ustack:
|
|||||||
/* The symbol is a CPSlot and has lower bit set to indicate metadata */
|
/* The symbol is a CPSlot and has lower bit set to indicate metadata */
|
||||||
this->nameSymbol &= (~1); /* remove metadata lsb */
|
this->nameSymbol &= (~1); /* remove metadata lsb */
|
||||||
|
|
||||||
/* Because sparc is big endian, the top half length is at the correct offset. */
|
|
||||||
this->nameSymbolLength = copyin_uint16(this->nameSymbol +
|
this->nameSymbolLength = copyin_uint16(this->nameSymbol +
|
||||||
OFFSET_Symbol_length_and_refcount);
|
OFFSET_Symbol_length);
|
||||||
|
|
||||||
this->signatureSymbol = copyin_ptr(this->constantPool +
|
this->signatureSymbol = copyin_ptr(this->constantPool +
|
||||||
this->signatureIndex * sizeof (pointer) + SIZE_ConstantPool);
|
this->signatureIndex * sizeof (pointer) + SIZE_ConstantPool);
|
||||||
this->signatureSymbol &= (~1); /* remove metadata lsb */
|
this->signatureSymbol &= (~1); /* remove metadata lsb */
|
||||||
|
|
||||||
/* Because sparc is big endian, the top half length is at the correct offset. */
|
|
||||||
this->signatureSymbolLength = copyin_uint16(this->signatureSymbol +
|
this->signatureSymbolLength = copyin_uint16(this->signatureSymbol +
|
||||||
OFFSET_Symbol_length_and_refcount);
|
OFFSET_Symbol_length);
|
||||||
|
|
||||||
this->klassPtr = copyin_ptr(this->constantPool +
|
this->klassPtr = copyin_ptr(this->constantPool +
|
||||||
OFFSET_ConstantPool_pool_holder);
|
OFFSET_ConstantPool_pool_holder);
|
||||||
@ -481,9 +479,8 @@ dtrace:helper:ustack:
|
|||||||
this->klassSymbol = copyin_ptr(this->klassPtr +
|
this->klassSymbol = copyin_ptr(this->klassPtr +
|
||||||
OFFSET_Klass_name);
|
OFFSET_Klass_name);
|
||||||
|
|
||||||
/* Because sparc is big endian, the top half length is at the correct offset. */
|
|
||||||
this->klassSymbolLength = copyin_uint16(this->klassSymbol +
|
this->klassSymbolLength = copyin_uint16(this->klassSymbol +
|
||||||
OFFSET_Symbol_length_and_refcount);
|
OFFSET_Symbol_length);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enough for three strings, plus the '.', plus the trailing '\0'.
|
* Enough for three strings, plus the '.', plus the trailing '\0'.
|
||||||
|
@ -37,21 +37,18 @@
|
|||||||
#include "runtime/os.hpp"
|
#include "runtime/os.hpp"
|
||||||
#include "utilities/utf8.hpp"
|
#include "utilities/utf8.hpp"
|
||||||
|
|
||||||
uint32_t Symbol::pack_length_and_refcount(int length, int refcount) {
|
uint32_t Symbol::pack_hash_and_refcount(short hash, int refcount) {
|
||||||
STATIC_ASSERT(max_symbol_length == ((1 << 16) - 1));
|
|
||||||
STATIC_ASSERT(PERM_REFCOUNT == ((1 << 16) - 1));
|
STATIC_ASSERT(PERM_REFCOUNT == ((1 << 16) - 1));
|
||||||
assert(length >= 0, "negative length");
|
|
||||||
assert(length <= max_symbol_length, "too long symbol");
|
|
||||||
assert(refcount >= 0, "negative refcount");
|
assert(refcount >= 0, "negative refcount");
|
||||||
assert(refcount <= PERM_REFCOUNT, "invalid refcount");
|
assert(refcount <= PERM_REFCOUNT, "invalid refcount");
|
||||||
uint32_t hi = length;
|
uint32_t hi = hash;
|
||||||
uint32_t lo = refcount;
|
uint32_t lo = refcount;
|
||||||
return (hi << 16) | lo;
|
return (hi << 16) | lo;
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol::Symbol(const u1* name, int length, int refcount) {
|
Symbol::Symbol(const u1* name, int length, int refcount) {
|
||||||
_length_and_refcount = pack_length_and_refcount(length, refcount);
|
_hash_and_refcount = pack_hash_and_refcount((short)os::random(), refcount);
|
||||||
_identity_hash = (short)os::random();
|
_length = length;
|
||||||
_body[0] = 0; // in case length == 0
|
_body[0] = 0; // in case length == 0
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
byte_at_put(i, name[i]);
|
byte_at_put(i, name[i]);
|
||||||
@ -78,7 +75,7 @@ void Symbol::operator delete(void *p) {
|
|||||||
void Symbol::set_permanent() {
|
void Symbol::set_permanent() {
|
||||||
// This is called at a safepoint during dumping of a dynamic CDS archive.
|
// This is called at a safepoint during dumping of a dynamic CDS archive.
|
||||||
assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
|
assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
|
||||||
_length_and_refcount = pack_length_and_refcount(length(), PERM_REFCOUNT);
|
_hash_and_refcount = pack_hash_and_refcount(extract_hash(_hash_and_refcount), PERM_REFCOUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -282,7 +279,7 @@ void Symbol::print_as_signature_external_parameters(outputStream *os) {
|
|||||||
// a thread could be concurrently removing the Symbol. This is used during SymbolTable
|
// a thread could be concurrently removing the Symbol. This is used during SymbolTable
|
||||||
// lookup to avoid reviving a dead Symbol.
|
// lookup to avoid reviving a dead Symbol.
|
||||||
bool Symbol::try_increment_refcount() {
|
bool Symbol::try_increment_refcount() {
|
||||||
uint32_t found = _length_and_refcount;
|
uint32_t found = _hash_and_refcount;
|
||||||
while (true) {
|
while (true) {
|
||||||
uint32_t old_value = found;
|
uint32_t old_value = found;
|
||||||
int refc = extract_refcount(old_value);
|
int refc = extract_refcount(old_value);
|
||||||
@ -291,7 +288,7 @@ bool Symbol::try_increment_refcount() {
|
|||||||
} else if (refc == 0) {
|
} else if (refc == 0) {
|
||||||
return false; // dead, can't revive.
|
return false; // dead, can't revive.
|
||||||
} else {
|
} else {
|
||||||
found = Atomic::cmpxchg(&_length_and_refcount, old_value, old_value + 1);
|
found = Atomic::cmpxchg(&_hash_and_refcount, old_value, old_value + 1);
|
||||||
if (found == old_value) {
|
if (found == old_value) {
|
||||||
return true; // successfully updated.
|
return true; // successfully updated.
|
||||||
}
|
}
|
||||||
@ -321,7 +318,7 @@ void Symbol::increment_refcount() {
|
|||||||
// to check the value after attempting to decrement so that if another
|
// to check the value after attempting to decrement so that if another
|
||||||
// thread increments to PERM_REFCOUNT the value is not decremented.
|
// thread increments to PERM_REFCOUNT the value is not decremented.
|
||||||
void Symbol::decrement_refcount() {
|
void Symbol::decrement_refcount() {
|
||||||
uint32_t found = _length_and_refcount;
|
uint32_t found = _hash_and_refcount;
|
||||||
while (true) {
|
while (true) {
|
||||||
uint32_t old_value = found;
|
uint32_t old_value = found;
|
||||||
int refc = extract_refcount(old_value);
|
int refc = extract_refcount(old_value);
|
||||||
@ -334,7 +331,7 @@ void Symbol::decrement_refcount() {
|
|||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
found = Atomic::cmpxchg(&_length_and_refcount, old_value, old_value - 1);
|
found = Atomic::cmpxchg(&_hash_and_refcount, old_value, old_value - 1);
|
||||||
if (found == old_value) {
|
if (found == old_value) {
|
||||||
return; // successfully updated.
|
return; // successfully updated.
|
||||||
}
|
}
|
||||||
@ -344,7 +341,7 @@ void Symbol::decrement_refcount() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Symbol::make_permanent() {
|
void Symbol::make_permanent() {
|
||||||
uint32_t found = _length_and_refcount;
|
uint32_t found = _hash_and_refcount;
|
||||||
while (true) {
|
while (true) {
|
||||||
uint32_t old_value = found;
|
uint32_t old_value = found;
|
||||||
int refc = extract_refcount(old_value);
|
int refc = extract_refcount(old_value);
|
||||||
@ -357,8 +354,8 @@ void Symbol::make_permanent() {
|
|||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
int len = extract_length(old_value);
|
int hash = extract_hash(old_value);
|
||||||
found = Atomic::cmpxchg(&_length_and_refcount, old_value, pack_length_and_refcount(len, PERM_REFCOUNT));
|
found = Atomic::cmpxchg(&_hash_and_refcount, old_value, pack_hash_and_refcount(hash, PERM_REFCOUNT));
|
||||||
if (found == old_value) {
|
if (found == old_value) {
|
||||||
return; // successfully updated.
|
return; // successfully updated.
|
||||||
}
|
}
|
||||||
|
@ -106,14 +106,13 @@ class Symbol : public MetaspaceObj {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// This is an int because it needs atomic operation on the refcount. Mask length
|
// This is an int because it needs atomic operation on the refcount. Mask hash
|
||||||
// in high half word. length is the number of UTF8 characters in the symbol
|
// in high half word. length is the number of UTF8 characters in the symbol
|
||||||
volatile uint32_t _length_and_refcount;
|
volatile uint32_t _hash_and_refcount;
|
||||||
short _identity_hash;
|
u2 _length;
|
||||||
u1 _body[2];
|
u1 _body[2];
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
// max_symbol_length must fit into the top 16 bits of _length_and_refcount
|
|
||||||
max_symbol_length = (1 << 16) -1
|
max_symbol_length = (1 << 16) -1
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -137,11 +136,11 @@ class Symbol : public MetaspaceObj {
|
|||||||
|
|
||||||
void operator delete(void* p);
|
void operator delete(void* p);
|
||||||
|
|
||||||
static int extract_length(uint32_t value) { return value >> 16; }
|
static short extract_hash(uint32_t value) { return (short)(value >> 16); }
|
||||||
static int extract_refcount(uint32_t value) { return value & 0xffff; }
|
static int extract_refcount(uint32_t value) { return value & 0xffff; }
|
||||||
static uint32_t pack_length_and_refcount(int length, int refcount);
|
static uint32_t pack_hash_and_refcount(short hash, int refcount);
|
||||||
|
|
||||||
int length() const { return extract_length(_length_and_refcount); }
|
int length() const { return _length; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Low-level access (used with care, since not GC-safe)
|
// Low-level access (used with care, since not GC-safe)
|
||||||
@ -157,12 +156,12 @@ class Symbol : public MetaspaceObj {
|
|||||||
static int max_length() { return max_symbol_length; }
|
static int max_length() { return max_symbol_length; }
|
||||||
unsigned identity_hash() const {
|
unsigned identity_hash() const {
|
||||||
unsigned addr_bits = (unsigned)((uintptr_t)this >> (LogMinObjAlignmentInBytes + 3));
|
unsigned addr_bits = (unsigned)((uintptr_t)this >> (LogMinObjAlignmentInBytes + 3));
|
||||||
return ((unsigned)_identity_hash & 0xffff) |
|
return ((unsigned)extract_hash(_hash_and_refcount) & 0xffff) |
|
||||||
((addr_bits ^ (length() << 8) ^ (( _body[0] << 8) | _body[1])) << 16);
|
((addr_bits ^ (length() << 8) ^ (( _body[0] << 8) | _body[1])) << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reference counting. See comments above this class for when to use.
|
// Reference counting. See comments above this class for when to use.
|
||||||
int refcount() const { return extract_refcount(_length_and_refcount); }
|
int refcount() const { return extract_refcount(_hash_and_refcount); }
|
||||||
bool try_increment_refcount();
|
bool try_increment_refcount();
|
||||||
void increment_refcount();
|
void increment_refcount();
|
||||||
void decrement_refcount();
|
void decrement_refcount();
|
||||||
|
@ -327,8 +327,8 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
|
|||||||
nonstatic_field(ConstMethod, _size_of_parameters, u2) \
|
nonstatic_field(ConstMethod, _size_of_parameters, u2) \
|
||||||
nonstatic_field(ObjArrayKlass, _element_klass, Klass*) \
|
nonstatic_field(ObjArrayKlass, _element_klass, Klass*) \
|
||||||
nonstatic_field(ObjArrayKlass, _bottom_klass, Klass*) \
|
nonstatic_field(ObjArrayKlass, _bottom_klass, Klass*) \
|
||||||
volatile_nonstatic_field(Symbol, _length_and_refcount, unsigned int) \
|
volatile_nonstatic_field(Symbol, _hash_and_refcount, unsigned int) \
|
||||||
nonstatic_field(Symbol, _identity_hash, short) \
|
nonstatic_field(Symbol, _length, u2) \
|
||||||
unchecked_nonstatic_field(Symbol, _body, sizeof(u1)) /* NOTE: no type */ \
|
unchecked_nonstatic_field(Symbol, _body, sizeof(u1)) /* NOTE: no type */ \
|
||||||
nonstatic_field(Symbol, _body[0], u1) \
|
nonstatic_field(Symbol, _body[0], u1) \
|
||||||
nonstatic_field(TypeArrayKlass, _max_length, jint) \
|
nonstatic_field(TypeArrayKlass, _max_length, jint) \
|
||||||
|
@ -552,8 +552,7 @@ name_for_methodPtr(jvm_agent_t* J, uint64_t methodPtr, char * result, size_t siz
|
|||||||
CHECK_FAIL(err);
|
CHECK_FAIL(err);
|
||||||
// The symbol is a CPSlot and has lower bit set to indicate metadata
|
// The symbol is a CPSlot and has lower bit set to indicate metadata
|
||||||
nameSymbol &= (~1); // remove metadata lsb
|
nameSymbol &= (~1); // remove metadata lsb
|
||||||
// The length is in the top half of the word.
|
err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2);
|
||||||
err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length_and_refcount, &nameSymbolLength, 2);
|
|
||||||
CHECK_FAIL(err);
|
CHECK_FAIL(err);
|
||||||
nameString = (char*)calloc(nameSymbolLength + 1, 1);
|
nameString = (char*)calloc(nameSymbolLength + 1, 1);
|
||||||
err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength);
|
err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength);
|
||||||
@ -565,7 +564,7 @@ name_for_methodPtr(jvm_agent_t* J, uint64_t methodPtr, char * result, size_t siz
|
|||||||
err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_ConstantPool, &signatureSymbol);
|
err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_ConstantPool, &signatureSymbol);
|
||||||
CHECK_FAIL(err);
|
CHECK_FAIL(err);
|
||||||
signatureSymbol &= (~1); // remove metadata lsb
|
signatureSymbol &= (~1); // remove metadata lsb
|
||||||
err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length_and_refcount, &signatureSymbolLength, 2);
|
err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2);
|
||||||
CHECK_FAIL(err);
|
CHECK_FAIL(err);
|
||||||
signatureString = (char*)calloc(signatureSymbolLength + 1, 1);
|
signatureString = (char*)calloc(signatureSymbolLength + 1, 1);
|
||||||
err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength);
|
err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength);
|
||||||
@ -576,7 +575,7 @@ name_for_methodPtr(jvm_agent_t* J, uint64_t methodPtr, char * result, size_t siz
|
|||||||
CHECK_FAIL(err);
|
CHECK_FAIL(err);
|
||||||
err = read_pointer(J, klassPtr + OFFSET_Klass_name, &klassSymbol);
|
err = read_pointer(J, klassPtr + OFFSET_Klass_name, &klassSymbol);
|
||||||
CHECK_FAIL(err);
|
CHECK_FAIL(err);
|
||||||
err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length_and_refcount, &klassSymbolLength, 2);
|
err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length, &klassSymbolLength, 2);
|
||||||
CHECK_FAIL(err);
|
CHECK_FAIL(err);
|
||||||
klassString = (char*)calloc(klassSymbolLength + 1, 1);
|
klassString = (char*)calloc(klassSymbolLength + 1, 1);
|
||||||
err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength);
|
err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength);
|
||||||
|
@ -45,9 +45,9 @@ public class Symbol extends VMObject {
|
|||||||
|
|
||||||
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
|
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
|
||||||
Type type = db.lookupType("Symbol");
|
Type type = db.lookupType("Symbol");
|
||||||
lengthAndRefcount = type.getCIntegerField("_length_and_refcount");
|
lengthField = type.getCIntegerField("_length");
|
||||||
baseOffset = type.getField("_body").getOffset();
|
baseOffset = type.getField("_body").getOffset();
|
||||||
idHash = type.getCIntegerField("_identity_hash");
|
idHashAndRefcount = type.getCIntegerField("_hash_and_refcount");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Symbol create(Address addr) {
|
public static Symbol create(Address addr) {
|
||||||
@ -66,19 +66,18 @@ public class Symbol extends VMObject {
|
|||||||
private static long baseOffset; // tells where the array part starts
|
private static long baseOffset; // tells where the array part starts
|
||||||
|
|
||||||
// Fields
|
// Fields
|
||||||
private static CIntegerField lengthAndRefcount;
|
private static CIntegerField lengthField;
|
||||||
|
// idHash is a short packed into the high bits of a 32-bit integer with refcount
|
||||||
|
private static CIntegerField idHashAndRefcount;
|
||||||
|
|
||||||
// Accessors for declared fields
|
// Accessors for declared fields
|
||||||
public long getLength() {
|
public long getLength() {
|
||||||
long i = lengthAndRefcount.getValue(this.addr);
|
return lengthField.getValue(this.addr);
|
||||||
return (i >> 16) & 0xffff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte getByteAt(long index) {
|
public byte getByteAt(long index) {
|
||||||
return addr.getJByteAt(baseOffset + index);
|
return addr.getJByteAt(baseOffset + index);
|
||||||
}
|
}
|
||||||
// _identity_hash is a short
|
|
||||||
private static CIntegerField idHash;
|
|
||||||
|
|
||||||
public long identityHash() {
|
public long identityHash() {
|
||||||
long addr_value = getAddress().asLongValue();
|
long addr_value = getAddress().asLongValue();
|
||||||
@ -87,7 +86,8 @@ public class Symbol extends VMObject {
|
|||||||
int length = (int)getLength();
|
int length = (int)getLength();
|
||||||
int byte0 = getByteAt(0);
|
int byte0 = getByteAt(0);
|
||||||
int byte1 = getByteAt(1);
|
int byte1 = getByteAt(1);
|
||||||
long id_hash = 0xffffL & (long)idHash.getValue(this.addr);
|
long id_hash = (long)idHashAndRefcount.getValue(this.addr);
|
||||||
|
id_hash = (id_hash >> 16) & 0xffff;
|
||||||
return (id_hash |
|
return (id_hash |
|
||||||
((addr_bits ^ (length << 8) ^ ((byte0 << 8) | byte1)) << 16)) & 0xffffffffL;
|
((addr_bits ^ (length << 8) ^ ((byte0 << 8) | byte1)) << 16)) & 0xffffffffL;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user