changeset 58115:d23e418e91fe

8239347: Refactor Symbol to make _length a standalone field again Reviewed-by: iklam, coleenp
author redestad
date Thu, 20 Feb 2020 13:18:30 +0100
parents 9b999cf5e13a
children 461e0b7e6dfe
files make/hotspot/src/native/dtrace/generateJvmOffsets.cpp src/hotspot/os/solaris/dtrace/jhelper.d src/hotspot/share/oops/symbol.cpp src/hotspot/share/oops/symbol.hpp src/hotspot/share/runtime/vmStructs.cpp src/java.base/solaris/native/libjvm_db/libjvm_db.c src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Symbol.java
diffstat 7 files changed, 38 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp	Fri Feb 07 08:38:40 2020 +0100
+++ b/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp	Thu Feb 20 13:18:30 2020 +0100
@@ -213,7 +213,7 @@
   GEN_VALUE(AccessFlags_NATIVE, JVM_ACC_NATIVE);
   GEN_VALUE(ConstMethod_has_linenumber_table, ConstMethod::_has_linenumber_table);
   GEN_OFFS(AccessFlags, _flags);
-  GEN_OFFS(Symbol, _length_and_refcount);
+  GEN_OFFS(Symbol, _length);
   GEN_OFFS(Symbol, _body);
   printf("\n");
 
--- a/src/hotspot/os/solaris/dtrace/jhelper.d	Fri Feb 07 08:38:40 2020 +0100
+++ b/src/hotspot/os/solaris/dtrace/jhelper.d	Thu Feb 20 13:18:30 2020 +0100
@@ -111,7 +111,7 @@
   copyin_offset(OFFSET_HeapBlockHeader_used);
   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_Method_constMethod);
@@ -463,17 +463,15 @@
   /* The symbol is a CPSlot and has lower bit set to indicate metadata */
   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 +
-      OFFSET_Symbol_length_and_refcount);
+      OFFSET_Symbol_length);
 
   this->signatureSymbol = copyin_ptr(this->constantPool +
       this->signatureIndex * sizeof (pointer) + SIZE_ConstantPool);
   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 +
-      OFFSET_Symbol_length_and_refcount);
+      OFFSET_Symbol_length);
 
   this->klassPtr = copyin_ptr(this->constantPool +
       OFFSET_ConstantPool_pool_holder);
@@ -481,9 +479,8 @@
   this->klassSymbol = copyin_ptr(this->klassPtr +
       OFFSET_Klass_name);
 
-  /* Because sparc is big endian, the top half length is at the correct offset. */
   this->klassSymbolLength = copyin_uint16(this->klassSymbol +
-      OFFSET_Symbol_length_and_refcount);
+      OFFSET_Symbol_length);
 
   /*
    * Enough for three strings, plus the '.', plus the trailing '\0'.
--- a/src/hotspot/share/oops/symbol.cpp	Fri Feb 07 08:38:40 2020 +0100
+++ b/src/hotspot/share/oops/symbol.cpp	Thu Feb 20 13:18:30 2020 +0100
@@ -37,21 +37,18 @@
 #include "runtime/os.hpp"
 #include "utilities/utf8.hpp"
 
-uint32_t Symbol::pack_length_and_refcount(int length, int refcount) {
-  STATIC_ASSERT(max_symbol_length == ((1 << 16) - 1));
+uint32_t Symbol::pack_hash_and_refcount(short hash, int refcount) {
   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 <= PERM_REFCOUNT, "invalid refcount");
-  uint32_t hi = length;
+  uint32_t hi = hash;
   uint32_t lo = refcount;
   return (hi << 16) | lo;
 }
 
 Symbol::Symbol(const u1* name, int length, int refcount) {
-  _length_and_refcount =  pack_length_and_refcount(length, refcount);
-  _identity_hash = (short)os::random();
+  _hash_and_refcount =  pack_hash_and_refcount((short)os::random(), refcount);
+  _length = length;
   _body[0] = 0;  // in case length == 0
   for (int i = 0; i < length; i++) {
     byte_at_put(i, name[i]);
@@ -78,7 +75,7 @@
 void Symbol::set_permanent() {
   // This is called at a safepoint during dumping of a dynamic CDS archive.
   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 @@
 // a thread could be concurrently removing the Symbol.  This is used during SymbolTable
 // lookup to avoid reviving a dead Symbol.
 bool Symbol::try_increment_refcount() {
-  uint32_t found = _length_and_refcount;
+  uint32_t found = _hash_and_refcount;
   while (true) {
     uint32_t old_value = found;
     int refc = extract_refcount(old_value);
@@ -291,7 +288,7 @@
     } else if (refc == 0) {
       return false; // dead, can't revive.
     } 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) {
         return true; // successfully updated.
       }
@@ -321,7 +318,7 @@
 // to check the value after attempting to decrement so that if another
 // thread increments to PERM_REFCOUNT the value is not decremented.
 void Symbol::decrement_refcount() {
-  uint32_t found = _length_and_refcount;
+  uint32_t found = _hash_and_refcount;
   while (true) {
     uint32_t old_value = found;
     int refc = extract_refcount(old_value);
@@ -334,7 +331,7 @@
 #endif
       return;
     } 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) {
         return;  // successfully updated.
       }
@@ -344,7 +341,7 @@
 }
 
 void Symbol::make_permanent() {
-  uint32_t found = _length_and_refcount;
+  uint32_t found = _hash_and_refcount;
   while (true) {
     uint32_t old_value = found;
     int refc = extract_refcount(old_value);
@@ -357,8 +354,8 @@
 #endif
       return;
     } else {
-      int len = extract_length(old_value);
-      found = Atomic::cmpxchg(&_length_and_refcount, old_value, pack_length_and_refcount(len, PERM_REFCOUNT));
+      int hash = extract_hash(old_value);
+      found = Atomic::cmpxchg(&_hash_and_refcount, old_value, pack_hash_and_refcount(hash, PERM_REFCOUNT));
       if (found == old_value) {
         return;  // successfully updated.
       }
--- a/src/hotspot/share/oops/symbol.hpp	Fri Feb 07 08:38:40 2020 +0100
+++ b/src/hotspot/share/oops/symbol.hpp	Thu Feb 20 13:18:30 2020 +0100
@@ -106,14 +106,13 @@
 
  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
-  volatile uint32_t _length_and_refcount;
-  short _identity_hash;
+  volatile uint32_t _hash_and_refcount;
+  u2 _length;
   u1 _body[2];
 
   enum {
-    // max_symbol_length must fit into the top 16 bits of _length_and_refcount
     max_symbol_length = (1 << 16) -1
   };
 
@@ -137,11 +136,11 @@
 
   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 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:
   // Low-level access (used with care, since not GC-safe)
@@ -157,12 +156,12 @@
   static int max_length() { return max_symbol_length; }
   unsigned identity_hash() const {
     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);
   }
 
   // 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();
   void increment_refcount();
   void decrement_refcount();
--- a/src/hotspot/share/runtime/vmStructs.cpp	Fri Feb 07 08:38:40 2020 +0100
+++ b/src/hotspot/share/runtime/vmStructs.cpp	Thu Feb 20 13:18:30 2020 +0100
@@ -327,8 +327,8 @@
   nonstatic_field(ConstMethod,                 _size_of_parameters,                           u2)                                    \
   nonstatic_field(ObjArrayKlass,               _element_klass,                                Klass*)                                \
   nonstatic_field(ObjArrayKlass,               _bottom_klass,                                 Klass*)                                \
-  volatile_nonstatic_field(Symbol,             _length_and_refcount,                          unsigned int)                          \
-  nonstatic_field(Symbol,                      _identity_hash,                                short)                                 \
+  volatile_nonstatic_field(Symbol,             _hash_and_refcount,                            unsigned int)                          \
+  nonstatic_field(Symbol,                      _length,                                       u2)                                    \
   unchecked_nonstatic_field(Symbol,            _body,                                         sizeof(u1)) /* NOTE: no type */        \
   nonstatic_field(Symbol,                      _body[0],                                      u1)                                    \
   nonstatic_field(TypeArrayKlass,              _max_length,                                   jint)                                  \
--- a/src/java.base/solaris/native/libjvm_db/libjvm_db.c	Fri Feb 07 08:38:40 2020 +0100
+++ b/src/java.base/solaris/native/libjvm_db/libjvm_db.c	Thu Feb 20 13:18:30 2020 +0100
@@ -552,8 +552,7 @@
   CHECK_FAIL(err);
   // The symbol is a CPSlot and has lower bit set to indicate metadata
   nameSymbol &= (~1); // remove metadata lsb
-  // The length is in the top half of the word.
-  err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length_and_refcount, &nameSymbolLength, 2);
+  err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2);
   CHECK_FAIL(err);
   nameString = (char*)calloc(nameSymbolLength + 1, 1);
   err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength);
@@ -565,7 +564,7 @@
   err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_ConstantPool, &signatureSymbol);
   CHECK_FAIL(err);
   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);
   signatureString = (char*)calloc(signatureSymbolLength + 1, 1);
   err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength);
@@ -576,7 +575,7 @@
   CHECK_FAIL(err);
   err = read_pointer(J, klassPtr + OFFSET_Klass_name, &klassSymbol);
   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);
   klassString = (char*)calloc(klassSymbolLength + 1, 1);
   err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength);
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Symbol.java	Fri Feb 07 08:38:40 2020 +0100
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Symbol.java	Thu Feb 20 13:18:30 2020 +0100
@@ -45,9 +45,9 @@
 
   private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
     Type type  = db.lookupType("Symbol");
-    lengthAndRefcount = type.getCIntegerField("_length_and_refcount");
+    lengthField = type.getCIntegerField("_length");
     baseOffset = type.getField("_body").getOffset();
-    idHash = type.getCIntegerField("_identity_hash");
+    idHashAndRefcount = type.getCIntegerField("_hash_and_refcount");
   }
 
   public static Symbol create(Address addr) {
@@ -66,19 +66,18 @@
   private static long baseOffset; // tells where the array part starts
 
   // 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
   public long getLength() {
-    long i = lengthAndRefcount.getValue(this.addr);
-    return (i >> 16) & 0xffff;
+    return lengthField.getValue(this.addr);
   }
 
   public byte getByteAt(long index) {
     return addr.getJByteAt(baseOffset + index);
   }
-  // _identity_hash is a short
-  private static CIntegerField idHash;
 
   public long identityHash() {
     long addr_value = getAddress().asLongValue();
@@ -87,7 +86,8 @@
     int  length = (int)getLength();
     int  byte0 = getByteAt(0);
     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 |
       ((addr_bits ^ (length << 8) ^ ((byte0 << 8) | byte1)) << 16)) & 0xffffffffL;
   }