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
--- 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) */ \
/***********************************************************/ \