8071962: The SA code needs to be updated to support Symbol lookup from the shared archive.
authorjiangli
Fri, 30 Jan 2015 20:31:05 -0500
changeset 28822 fa57694ade05
parent 28818 ba7d959f65e7
child 28823 9c678eaab37e
8071962: The SA code needs to be updated to support Symbol lookup from the shared archive. Summary: Support shared symbols lookup. Reviewed-by: minqi, sspitsyn, dsamersoff, iklam
hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SymbolTable.java
hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/CompactHashTable.java
hotspot/src/share/vm/classfile/compactHashtable.hpp
hotspot/src/share/vm/runtime/vmStructs.cpp
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SymbolTable.java	Thu Jan 29 14:50:43 2015 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SymbolTable.java	Fri Jan 30 20:31:05 2015 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,15 +44,22 @@
   private static synchronized void initialize(TypeDataBase db) {
     Type type = db.lookupType("SymbolTable");
     theTableField  = type.getAddressField("_the_table");
+    sharedTableField = type.getAddressField("_shared_table");
   }
 
   // Fields
   private static AddressField theTableField;
+  private static AddressField sharedTableField;
+
+  private CompactHashTable sharedTable;
 
   // 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 shared = sharedTableField.getStaticFieldAddress();
+    table.sharedTable = (CompactHashTable)VMObjectFactory.newObject(CompactHashTable.class, shared);
+    return table;
   }
 
   public SymbolTable(Address addr) {
@@ -73,8 +80,9 @@
 
   /** Clone of VM's "temporary" probe routine, as the SA currently
       does not support mutation so lookup() would have no effect
-      anyway. Returns null if the given string is not in the symbol
-      table. */
+      anyway. Searches the regular symbol table and the shared symbol
+      table. Null is returned if the given name is not found in both
+      tables. */
   public Symbol probe(byte[] name) {
     long hashValue = hashSymbol(name);
     for (HashtableEntry e = (HashtableEntry) bucket(hashToIndex(hashValue)); e != null; e = (HashtableEntry) e.next()) {
@@ -85,7 +93,8 @@
          }
       }
     }
-    return null;
+
+    return sharedTable.probe(name, hashValue);
   }
 
   public interface SymbolVisitor {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/CompactHashTable.java	Fri Jan 30 20:31:05 2015 -0500
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+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 CompactHashTable extends VMObject {
+  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("SymbolCompactHashTable");
+    baseAddressField = type.getAddressField("_base_address");
+    bucketCountField = type.getCIntegerField("_bucket_count");
+    tableEndOffsetField = type.getCIntegerField("_table_end_offset");
+    bucketsField = type.getAddressField("_buckets");
+    uintSize = db.lookupType("juint").getSize();
+  }
+
+  // Fields
+  private static CIntegerField bucketCountField;
+  private static CIntegerField tableEndOffsetField;
+  private static AddressField  baseAddressField;
+  private static AddressField  bucketsField;
+  private static long uintSize;
+
+  private static int BUCKET_OFFSET_MASK = 0x3FFFFFFF;
+  private static int BUCKET_TYPE_SHIFT = 30;
+  private static int COMPACT_BUCKET_TYPE = 1;
+
+  public CompactHashTable(Address addr) {
+    super(addr);
+  }
+
+  private int bucketCount() {
+    return (int)bucketCountField.getValue(addr);
+  }
+
+  private int tableEndOffset() {
+    return (int)tableEndOffsetField.getValue(addr);
+  }
+
+  private boolean isCompactBucket(int bucket_info) {
+    return (bucket_info >> BUCKET_TYPE_SHIFT) == COMPACT_BUCKET_TYPE;
+  }
+
+  private int bucketOffset(int bucket_info) {
+    return bucket_info & BUCKET_OFFSET_MASK;
+  }
+
+  public Symbol probe(byte[] name, long hash) {
+    long    symOffset;
+    Symbol  sym;
+    Address baseAddress = baseAddressField.getValue(addr);
+    Address bucket = bucketsField.getValue(addr);
+    Address bucketEnd = bucket;
+    long index = hash % bucketCount();
+    int bucketInfo = (int)bucket.getCIntegerAt(index * uintSize, uintSize, true);
+    int bucketOffset = bucketOffset(bucketInfo);
+    int nextBucketInfo = (int)bucket.getCIntegerAt((index+1) * uintSize, uintSize, true);
+    int nextBucketOffset = bucketOffset(nextBucketInfo);
+
+    bucket = bucket.addOffsetTo(bucketOffset * uintSize);
+
+    if (isCompactBucket(bucketInfo)) {
+      symOffset = bucket.getCIntegerAt(0, uintSize, true);
+      sym = Symbol.create(baseAddress.addOffsetTo(symOffset));
+      if (sym.equals(name)) {
+        return sym;
+      }
+    } else {
+      bucketEnd = bucket.addOffsetTo(nextBucketOffset * uintSize);
+      while (bucket.lessThan(bucketEnd)) {
+        long symHash = bucket.getCIntegerAt(0, uintSize, true);
+        if (symHash == hash) {
+          symOffset = bucket.getCIntegerAt(uintSize, uintSize, true);
+          Address symAddr = baseAddress.addOffsetTo(symOffset);
+          sym = Symbol.create(symAddr);
+          if (sym.equals(name)) {
+            return sym;
+          }
+        }
+        bucket = bucket.addOffsetTo(2 * uintSize);
+      }
+    }
+    return null;
+  }
+}
--- a/hotspot/src/share/vm/classfile/compactHashtable.hpp	Thu Jan 29 14:50:43 2015 -0800
+++ b/hotspot/src/share/vm/classfile/compactHashtable.hpp	Fri Jan 30 20:31:05 2015 -0500
@@ -188,6 +188,7 @@
 // dump time.
 //
 template <class T, class N> class CompactHashtable VALUE_OBJ_CLASS_SPEC {
+  friend class VMStructs;
   uintx  _base_address;
   juint  _entry_count;
   juint  _bucket_count;
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Thu Jan 29 14:50:43 2015 -0800
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Fri Jan 30 20:31:05 2015 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 #include "classfile/javaClasses.hpp"
 #include "classfile/loaderConstraints.hpp"
 #include "classfile/placeholders.hpp"
+#include "classfile/compactHashtable.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "ci/ciField.hpp"
@@ -243,6 +244,7 @@
 typedef Hashtable<Klass*, mtClass>            KlassHashtable;
 typedef HashtableEntry<Klass*, mtClass>       KlassHashtableEntry;
 typedef TwoOopHashtable<Symbol*, mtClass>     SymbolTwoOopHashtable;
+typedef CompactHashtable<Symbol*, char>       SymbolCompactHashTable;
 
 //--------------------------------------------------------------------------------
 // VM_STRUCTS
@@ -624,6 +626,7 @@
   /***************/                                                                                                                  \
                                                                                                                                      \
      static_field(SymbolTable,                  _the_table,                                   SymbolTable*)                          \
+     static_field(SymbolTable,                  _shared_table,                                SymbolCompactHashTable)                \
                                                                                                                                      \
   /***************/                                                                                                                  \
   /* StringTable */                                                                                                                  \
@@ -632,6 +635,16 @@
      static_field(StringTable,                  _the_table,                                   StringTable*)                          \
                                                                                                                                      \
   /********************/                                                                                                             \
+  /* CompactHashTable */                                                                                                             \
+  /********************/                                                                                                             \
+                                                                                                                                     \
+  nonstatic_field(SymbolCompactHashTable, _base_address, uintx)                                                                      \
+  nonstatic_field(SymbolCompactHashTable, _entry_count, juint)                                                                       \
+  nonstatic_field(SymbolCompactHashTable, _bucket_count, juint)                                                                      \
+  nonstatic_field(SymbolCompactHashTable, _table_end_offset, juint)                                                                  \
+  nonstatic_field(SymbolCompactHashTable, _buckets, juint*)                                                                          \
+                                                                                                                                     \
+  /********************/                                                                                                             \
   /* SystemDictionary */                                                                                                             \
   /********************/                                                                                                             \
                                                                                                                                      \
@@ -1580,6 +1593,8 @@
     declare_type(ResourceArea, Arena)                                     \
   declare_toplevel_type(Chunk)                                            \
                                                                           \
+  declare_toplevel_type(SymbolCompactHashTable)                           \
+                                                                          \
   /***********************************************************/           \
   /* Thread hierarchy (needed for run-time type information) */           \
   /***********************************************************/           \