*/
public final class ConstPool {
LongVector items;
- int numOfItems;
+ int numOfItems;
HashMap classes;
HashMap strings;
- int thisClassInfo;
+ ConstInfo[] constInfoCache;
+ int[] constInfoIndexCache;
+ int thisClassInfo;
+
+ private static final int CACHE_SIZE = 32;
+
+ /**
+ * A hash function for CACHE_SIZE
+ */
+ private static int hashFunc(int a, int b) {
+ int h = -2128831035;
+ final int prime = 16777619;
+ h = (h ^ (a & 0xff)) * prime;
+ h = (h ^ (b & 0xff)) * prime;
+
+ // changing the hash key size from 32bit to 5bit
+ h = (h >> 5) ^ (h & 0x1f);
+ return h & 0x1f; // 0..31
+ }
/**
* <code>CONSTANT_Class</code>
addItem(null); // index 0 is reserved by the JVM.
classes = new HashMap();
strings = new HashMap();
+ constInfoCache = new ConstInfo[CACHE_SIZE];
+ constInfoIndexCache = new int[CACHE_SIZE];
thisClassInfo = addClassInfo(thisclass);
}
public ConstPool(DataInputStream in) throws IOException {
classes = new HashMap();
strings = new HashMap();
+ constInfoCache = new ConstInfo[CACHE_SIZE];
+ constInfoIndexCache = new int[CACHE_SIZE];
thisClassInfo = 0;
/* read() initializes items and numOfItems, and do addItem(null).
*/
void prune() {
classes = new HashMap();
strings = new HashMap();
+ constInfoCache = new ConstInfo[CACHE_SIZE];
+ constInfoIndexCache = new int[CACHE_SIZE];
}
/**
}
ConstInfo getItem(int n) {
- return (ConstInfo)items.elementAt(n);
+ return items.elementAt(n);
}
/**
* @return the index of the added entry.
*/
public int addNameAndTypeInfo(int name, int type) {
- return addItem(new NameAndTypeInfo(name, type));
+ int h = hashFunc(name, type);
+ ConstInfo ci = constInfoCache[h];
+ if (ci != null && ci instanceof NameAndTypeInfo && ci.hashCheck(name, type))
+ return constInfoIndexCache[h];
+ else {
+ NameAndTypeInfo item = new NameAndTypeInfo(name, type);
+ constInfoCache[h] = item;
+ int i = addItem(item);
+ constInfoIndexCache[h] = i;
+ return i;
+ }
}
/**
* @return the index of the added entry.
*/
public int addFieldrefInfo(int classInfo, int nameAndTypeInfo) {
- return addItem(new FieldrefInfo(classInfo, nameAndTypeInfo));
+ int h = hashFunc(classInfo, nameAndTypeInfo);
+ ConstInfo ci = constInfoCache[h];
+ if (ci != null && ci instanceof FieldrefInfo && ci.hashCheck(classInfo, nameAndTypeInfo))
+ return constInfoIndexCache[h];
+ else {
+ FieldrefInfo item = new FieldrefInfo(classInfo, nameAndTypeInfo);
+ constInfoCache[h] = item;
+ int i = addItem(item);
+ constInfoIndexCache[h] = i;
+ return i;
+ }
}
/**
* @return the index of the added entry.
*/
public int addMethodrefInfo(int classInfo, int nameAndTypeInfo) {
- return addItem(new MethodrefInfo(classInfo, nameAndTypeInfo));
+ int h = hashFunc(classInfo, nameAndTypeInfo);
+ ConstInfo ci = constInfoCache[h];
+ if (ci != null && ci instanceof MethodrefInfo && ci.hashCheck(classInfo, nameAndTypeInfo))
+ return constInfoIndexCache[h];
+ else {
+ MethodrefInfo item = new MethodrefInfo(classInfo, nameAndTypeInfo);
+ constInfoCache[h] = item;
+ int i = addItem(item);
+ constInfoIndexCache[h] = i;
+ return i;
+ }
}
/**
*/
public int addInterfaceMethodrefInfo(int classInfo,
int nameAndTypeInfo) {
- return addItem(new InterfaceMethodrefInfo(classInfo,
- nameAndTypeInfo));
+ int h = hashFunc(classInfo, nameAndTypeInfo);
+ ConstInfo ci = constInfoCache[h];
+ if (ci != null && ci instanceof InterfaceMethodrefInfo && ci.hashCheck(classInfo, nameAndTypeInfo))
+ return constInfoIndexCache[h];
+ else {
+ InterfaceMethodrefInfo item =new InterfaceMethodrefInfo(classInfo, nameAndTypeInfo);
+ constInfoCache[h] = item;
+ int i = addItem(item);
+ constInfoIndexCache[h] = i;
+ return i;
+ }
}
/**
LongVector v = items;
int size = numOfItems;
for (int i = 1; i < size; ++i) {
- String className = ((ConstInfo) v.elementAt(i)).getClassName(this);
+ String className = v.elementAt(i).getClassName(this);
if (className != null)
result.add(className);
}
int size = numOfItems;
classes = new HashMap(classes.size() * 2);
for (int i = 1; i < size; ++i) {
- ConstInfo ci = (ConstInfo)v.elementAt(i);
+ ConstInfo ci = v.elementAt(i);
ci.renameClass(this, oldName, newName);
ci.makeHashtable(this);
}
int size = numOfItems;
classes = new HashMap(classes.size() * 2);
for (int i = 1; i < size; ++i) {
- ConstInfo ci = (ConstInfo)v.elementAt(i);
+ ConstInfo ci = v.elementAt(i);
ci.renameClass(this, classnames);
ci.makeHashtable(this);
}
int i = 1;
while (true) {
- ConstInfo info = (ConstInfo)items.elementAt(i++);
+ ConstInfo info = items.elementAt(i++);
if (info == null)
break;
else
LongVector v = items;
int size = numOfItems;
for (int i = 1; i < size; ++i)
- ((ConstInfo)v.elementAt(i)).write(out);
+ v.elementAt(i).write(out);
}
/**
for (int i = 1; i < size; ++i) {
out.print(i);
out.print(" ");
- ((ConstInfo)items.elementAt(i)).print(out);
+ items.elementAt(i).print(out);
}
}
}
void makeHashtable(ConstPool cp) {} // called after read() finishes in ConstPool.
+ boolean hashCheck(int a, int b) { return false; }
+
public String toString() {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
PrintWriter out = new PrintWriter(bout);
typeDescriptor = in.readUnsignedShort();
}
+ boolean hashCheck(int a, int b) { return a == memberName && b == typeDescriptor; }
+
public int getTag() { return tag; }
public void renameClass(ConstPool cp, String oldName, String newName) {
return copy2(dest, classIndex2, ntIndex2);
}
+ boolean hashCheck(int a, int b) { return a == classIndex && b == nameAndTypeIndex; }
+
abstract protected int copy2(ConstPool dest, int cindex, int ntindex);
public void write(DataOutputStream out) throws IOException {