Date: Thu, 8 Jun 2023 19:52:36 +0800
Subject: [PATCH 55/59] Fix jmap heapdump symbols when the class is loaded from dynamicCDS' jsa

---
 .../sun/jvm/hotspot/memory/SymbolTable.java   | 16 +++++++-
 .../utilities/OffsetCompactHashTable.java     | 39 +++++++++++++++++++
 .../src/share/vm/classfile/symbolTable.cpp    | 16 ++------
 .../src/share/vm/classfile/symbolTable.hpp    | 15 +++++++
 hotspot/src/share/vm/runtime/vmStructs.cpp    | 16 +++++++-
 5 files changed, 86 insertions(+), 16 deletions(-)
 create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/OffsetCompactHashTable.java

diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SymbolTable.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SymbolTable.java
index 7510d08bf..015415fab 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SymbolTable.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SymbolTable.java
@@ -44,15 +44,21 @@ public class SymbolTable extends sun.jvm.hotspot.utilities.Hashtable {
   private static synchronized void initialize(TypeDataBase db) {
     Type type = db.lookupType("SymbolTable");
     theTableField  = type.getAddressField("_the_table");
+    dynamicSharedTableField = type.getAddressField("_dynamic_shared_table");
   }
 
   // Fields
   private static AddressField theTableField;
+  private static AddressField dynamicSharedTableField;
+  private OffsetCompactHashTable dynamicSharedTable;
 
   // Accessors
   public static SymbolTable getTheTable() {
     Address tmp = theTableField.getValue();
-    return (SymbolTable) VMObjectFactory.newObject(SymbolTable.class, tmp);
+    SymbolTable table = (SymbolTable) VMObjectFactory.newObject(SymbolTable.class, tmp);
+    Address dynamicShared = dynamicSharedTableField.getStaticFieldAddress();
+    table.dynamicSharedTable = (OffsetCompactHashTable)VMObjectFactory.newObject(OffsetCompactHashTable.class, dynamicShared);
+    return table;
   }
 
   public SymbolTable(Address addr) {
@@ -77,14 +83,20 @@ public class SymbolTable extends sun.jvm.hotspot.utilities.Hashtable {
       table. */
   public Symbol probe(byte[] name) {
     long hashValue = hashSymbol(name);
+
+    Symbol sym = null;
     for (HashtableEntry e = (HashtableEntry) bucket(hashToIndex(hashValue)); e != null; e = (HashtableEntry) e.next()) {
       if (e.hash() == hashValue) {
-         Symbol sym = Symbol.create(e.literalValue());
+         sym = Symbol.create(e.literalValue());
          if (sym.equals(name)) {
            return sym;
          }
       }
     }
+    if(sym == null && dynamicSharedTable != null) {
+      sym = dynamicSharedTable.probe(name, hashValue);
+      return sym;
+    }
     return null;
   }
 
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/OffsetCompactHashTable.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/OffsetCompactHashTable.java
new file mode 100644
index 000000000..42c72d0c3
--- /dev/null
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/OffsetCompactHashTable.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2012-2023. All rights reserved.
+ */
+
+package sun.jvm.hotspot.utilities;
+
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.oops.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.utilities.*;
+
+public class OffsetCompactHashTable extends CompactHashTable {
+  static {
+    VM.registerVMInitializedObserver(new Observer() {
+      public void update(Observable o, Object data) {
+        initialize(VM.getVM().getTypeDataBase());
+      }
+    });
+  }
+
+  private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
+    Type type = db.lookupType("SymbolOffsetCompactHashtable");
+    baseAddressField = type.getAddressField("_base_address");
+    bucketCountField = type.getCIntegerField("_bucket_count");
+    entryCountField = type.getCIntegerField("_entry_count");
+    bucketsField = type.getAddressField("_buckets");
+    entriesField = type.getAddressField("_entries");
+    uintSize = db.lookupType("u4").getSize();
+  }
+
+  public OffsetCompactHashTable(Address addr) {
+    super(addr);
+  }
+
+}
+
+
diff --git a/hotspot/src/share/vm/classfile/symbolTable.cpp b/hotspot/src/share/vm/classfile/symbolTable.cpp
index 6a2d8077f..06da1e40e 100644
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp
@@ -44,18 +44,10 @@

 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC

-inline bool symbol_equals_compact_hashtable_entry(Symbol* value, const char* key, int len) {
-  if (value->equals(key, len)) {
-    return true;
-  } else {
-    return false;
-  }
-}
-
-static OffsetCompactHashtable<
+OffsetCompactHashtable<
   const char*, Symbol*,
   symbol_equals_compact_hashtable_entry
-> _dynamic_shared_table;
+> SymbolTable::_dynamic_shared_table;

 // --------------------------------------------------------------------------

@@ -254,7 +246,6 @@ Symbol* SymbolTable::lookup_shared(const char* name,
       // always uses the same original hash code.
       hash = java_lang_String::hash_code((const jbyte*)name, len);
     }
-
     sym = _dynamic_shared_table.lookup(name, hash, len);
   }
   return sym;
diff --git a/hotspot/src/share/vm/classfile/symbolTable.hpp b/hotspot/src/share/vm/classfile/symbolTable.hpp
index 96eb173d1..f861e161f 100644
--- a/hotspot/src/share/vm/classfile/symbolTable.hpp
+++ b/hotspot/src/share/vm/classfile/symbolTable.hpp
@@ -75,11 +75,25 @@ class TempNewSymbol : public StackObj {
   operator Symbol*()                             { return _temp; }
 };

+inline bool symbol_equals_compact_hashtable_entry(Symbol* value, const char* key, int len) {
+  if (value->equals(key, len)) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
 class SymbolTable : public RehashableHashtable<Symbol*, mtSymbol> {
   friend class VMStructs;
   friend class ClassFileParser;

 private:
+  // The dynamic shared table
+  static OffsetCompactHashtable<
+          const char*, Symbol*,
+          symbol_equals_compact_hashtable_entry
+  > _dynamic_shared_table;
+
   // The symbol table
   static SymbolTable* _the_table;

diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp
index 5d1cf2b8e..744c43e02 100644
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "classfile/symbolTable.hpp"
 #include "classfile/dictionary.hpp"
 #include "classfile/javaClasses.hpp"
 #include "classfile/loaderConstraints.hpp"
@@ -252,6 +253,8 @@ typedef Hashtable<Klass*, mtClass>            KlassHashtable;
 typedef HashtableEntry<Klass*, mtClass>       KlassHashtableEntry;
 typedef TwoOopHashtable<Symbol*, mtClass>     SymbolTwoOopHashtable;
 
+typedef OffsetCompactHashtable<const char*, Symbol*, symbol_equals_compact_hashtable_entry>  SymbolOffsetCompactHashtable;
+
 //--------------------------------------------------------------------------------
 // VM_STRUCTS
 //
@@ -628,9 +631,19 @@ typedef TwoOopHashtable<Symbol*, mtClass>     SymbolTwoOopHashtable;
   /***************/                                                                                                                  \
   /* SymbolTable */                                                                                                                  \
   /***************/                                                                                                                  \
-                                                                                                                                     \
+     static_field(SymbolTable,                  _dynamic_shared_table,                        SymbolOffsetCompactHashtable)          \
      static_field(SymbolTable,                  _the_table,                                   SymbolTable*)                          \
                                                                                                                                      \
+  /********************************/                                                                                                 \
+  /* SymbolOffsetCompactHashtable */                                                                                                 \
+  /********************************/                                                                                                 \
+                                                                                                                                     \
+     nonstatic_field(SymbolOffsetCompactHashtable,      _base_address,                         address)                              \
+     nonstatic_field(SymbolOffsetCompactHashtable,      _entry_count,                          u4)                                   \
+     nonstatic_field(SymbolOffsetCompactHashtable,      _bucket_count,                         u4)                                   \
+     nonstatic_field(SymbolOffsetCompactHashtable,      _buckets,                              u4*)                                  \
+     nonstatic_field(SymbolOffsetCompactHashtable,      _entries,                              u4*)                                  \
+                                                                                                                                     \
   /***************/                                                                                                                  \
   /* StringTable */                                                                                                                  \
   /***************/                                                                                                                  \
@@ -1574,6 +1587,7 @@ typedef TwoOopHashtable<Symbol*, mtClass>     SymbolTwoOopHashtable;
     declare_type(KlassTwoOopHashtable, KlassHashtable)                    \
     declare_type(Dictionary, KlassTwoOopHashtable)                        \
     declare_type(PlaceholderTable, SymbolTwoOopHashtable)                 \
+  declare_toplevel_type(SymbolOffsetCompactHashtable)                     \
   declare_toplevel_type(BasicHashtableEntry<mtInternal>)                  \
   declare_type(IntptrHashtableEntry, BasicHashtableEntry<mtInternal>)     \
     declare_type(DictionaryEntry, KlassHashtableEntry)                    \
-- 
2.22.0

