--- old/agent/src/share/classes/sun/jvm/hotspot/memory/SymbolTable.java 2015-01-29 18:58:02.787721555 -0500 +++ new/agent/src/share/classes/sun/jvm/hotspot/memory/SymbolTable.java 2015-01-29 18:58:02.147684941 -0500 @@ -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) { @@ -76,16 +83,19 @@ anyway. Returns null if the given string is not in the symbol table. */ public Symbol probe(byte[] name) { + Symbol sym; long hashValue = hashSymbol(name); 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; } } } - return null; + + sym = sharedTable.probe(name, hashValue); + return sym; } public interface SymbolVisitor { --- old/src/share/vm/classfile/compactHashtable.hpp 2015-01-29 18:58:04.879841255 -0500 +++ new/src/share/vm/classfile/compactHashtable.hpp 2015-01-29 18:58:04.199802345 -0500 @@ -188,6 +188,7 @@ // dump time. // template class CompactHashtable VALUE_OBJ_CLASS_SPEC { + friend class VMStructs; uintx _base_address; juint _entry_count; juint _bucket_count; --- old/src/share/vm/runtime/vmStructs.cpp 2015-01-29 18:58:07.227975594 -0500 +++ new/src/share/vm/runtime/vmStructs.cpp 2015-01-29 18:58:06.591939203 -0500 @@ -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 KlassHashtable; typedef HashtableEntry KlassHashtableEntry; typedef TwoOopHashtable SymbolTwoOopHashtable; +typedef CompactHashtable SymbolCompactHashTable; //-------------------------------------------------------------------------------- // VM_STRUCTS @@ -617,6 +619,7 @@ /***************/ \ \ static_field(SymbolTable, _the_table, SymbolTable*) \ + static_field(SymbolTable, _shared_table, SymbolCompactHashTable) \ \ /***************/ \ /* StringTable */ \ @@ -625,6 +628,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 */ \ /********************/ \ \ @@ -1572,6 +1585,8 @@ declare_type(ResourceArea, Arena) \ declare_toplevel_type(Chunk) \ \ + declare_toplevel_type(SymbolCompactHashTable) \ + \ /***********************************************************/ \ /* Thread hierarchy (needed for run-time type information) */ \ /***********************************************************/ \ @@ -2940,7 +2955,7 @@ }; VMTypeEntry VMStructs::localHotSpotVMTypes[] = { - + VM_TYPES(GENERATE_VM_TYPE_ENTRY, GENERATE_TOPLEVEL_VM_TYPE_ENTRY, GENERATE_OOP_VM_TYPE_ENTRY, --- /dev/null 2014-12-13 10:35:39.117184000 -0500 +++ new/agent/src/share/classes/sun/jvm/hotspot/utilities/CompactHashTable.java 2015-01-29 18:58:08.728061418 -0500 @@ -0,0 +1,121 @@ +/* + * 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 long uintxSize; + + 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; + } +}