From: adam Date: Mon, 27 Jun 2005 08:11:04 +0000 (+0000) Subject: brians changes to ConstantPool X-Git-Url: http://git.megacz.com/?p=org.ibex.classgen.git;a=commitdiff_plain;h=003452a667497f6bf7375cc0bea7aa589c2e7545 brians changes to ConstantPool darcs-hash:20050627081104-5007d-cc62baf6945aa9dc6874b6c7a846e05e94b6e592.gz --- diff --git a/src/org/ibex/classgen/ConstantPool.java b/src/org/ibex/classgen/ConstantPool.java index 6817ff8..eb2a565 100644 --- a/src/org/ibex/classgen/ConstantPool.java +++ b/src/org/ibex/classgen/ConstantPool.java @@ -5,7 +5,7 @@ import java.io.*; import org.ibex.classgen.util.*; -class ConstantPool { +class ConstantPool implements CGConst { private final Hashtable entries = new Hashtable(); private Ent[] entriesByIndex; // only valid when stable @@ -20,107 +20,132 @@ class ConstantPool { public abstract class Ent { int n; // this is the refcount if state == OPEN, index if >= STABLE int tag; + Object key; Ent(int tag) { this.tag = tag; } void dump(DataOutput o) throws IOException { o.writeByte(tag); } String debugToString() { return toString(); } // so we can remove this method when not debugging - abstract Object key() throws ClassFile.ClassReadExn; // be careful using this, it drags in a bunch of code + abstract Object _key(); + final Object key() { return key == null ? (key = _key()) : key; } + int slots() { return 1; } // number of slots this ent takes up + void ref() { + if(state != OPEN) throw new IllegalStateException("cp is not open"); + n++; + } + void unref() { + if(state != OPEN) throw new IllegalStateException("cp is not open"); + if(--n == 0) entries.remove(key()); + } + } + + class Utf8Ent extends Ent { + String s; + Utf8Ent() { super(CONSTANT_UTF8); } + Utf8Ent(String s) { this(); this.s = s; } + String debugToString() { return s; } + void dump(DataOutput o) throws IOException { super.dump(o); o.writeUTF(s); } + Object _key() { return new Utf8Key(s); } } - class IntEnt extends Ent { + class IntLitEnt extends Ent { final int i; - IntEnt(int i) { super(3); this.i = i; } + IntLitEnt(int i) { super(CONSTANT_INTEGER); this.i = i; } void dump(DataOutput o) throws IOException { super.dump(o); o.writeInt(i); } - Object key() { return new Integer(i); } + Object _key() { return new Integer(i); } } - - class FloatEnt extends Ent { + class FloatLitEnt extends Ent { final float f; - FloatEnt(float f) { super(4); this.f = f; } + FloatLitEnt(float f) { super(CONSTANT_FLOAT); this.f = f; } void dump(DataOutput o) throws IOException { super.dump(o); o.writeFloat(f); } - Object key() { return new Float(f); } + Object _key() { return new Float(f); } } - class LongEnt extends Ent { + class LongLitEnt extends Ent { final long l; - LongEnt(long l) { super(5); this.l = l; } + LongLitEnt(long l) { super(CONSTANT_LONG); this.l = l; } void dump(DataOutput o) throws IOException { super.dump(o); o.writeLong(l); } - Object key() { return new Long(l); } + Object _key() { return new Long(l); } + int slots() { return 2; } } - class DoubleEnt extends Ent { + class DoubleLitEnt extends Ent { final double d; - DoubleEnt(double d) { super(6); this.d = d; } + DoubleLitEnt(double d) { super(CONSTANT_DOUBLE); this.d = d; } void dump(DataOutput o) throws IOException { super.dump(o); o.writeDouble(d); } - Object key() { return new Double(d); } + Object _key() { return new Double(d); } + int slots() { return 2; } + } + class StringLitEnt extends Ent { + Utf8Ent utf8; + StringLitEnt() { super(CONSTANT_STRING); } + StringLitEnt(String s) { this(); this.utf8 = (Utf8Ent)addUtf8(s); } + void dump(DataOutput o) throws IOException { super.dump(o); o.writeShort(utf8.n); } + Object _key() { return utf8.s; } + void unref() { utf8.unref(); super.unref(); } + } + class ClassEnt extends Ent { + Utf8Ent utf8; + ClassEnt() { super(CONSTANT_CLASS); } + ClassEnt(String s) { this(); this.utf8 = (Utf8Ent) addUtf8(s); } + void dump(DataOutput o) throws IOException { super.dump(o); o.writeShort(utf8.n); } + Type.Class getTypeClass() { return (Type.Class) key(); } + Object _key() { return new Type.Class(utf8.s); } + void unref() { utf8.unref(); super.unref(); } + String debugToString() { return "[Class: " + utf8.s + "]"; } } - /* INVARIANTS: - tag >= 7 && tag <= 12 - if (tag == 7 || tag == 8) e0 instanceof Utf8Ent - if (tag == 9 || tag == 10 || tag == 11) { - e0 instanceof CPRefEnt && e0.tag == 7 - e1 instanceof CPRefEnt && e0.tag == 12 - } - if (tag == 12) { - e0 instanceof Utf8Ent - } - */ - class CPRefEnt extends Ent { - Ent e1; - Ent e2; - CPRefEnt(int tag) { super(tag); } + class NameAndTypeEnt extends Ent { + Utf8Ent name; + Utf8Ent type; - String debugToString() { return "[" + e1.n + ":" + e1.debugToString() + (e2 == null ? "" : " + " + e2.n + ":" + e2.debugToString()) + "]"; } + NameAndTypeEnt() { super(CONSTANT_NAMEANDTYPE); } + NameAndTypeEnt(String name, String type) { + this(); + this.name = (Utf8Ent) addUtf8(name); + this.type = (Utf8Ent) addUtf8(type); + } + void dump(DataOutput o) throws IOException { super.dump(o); o.writeShort(name.n); o.writeShort(type.n); } + Object _key() { return new NameAndTypeKey(name.s, type.s); } + void unref() { name.unref(); type.unref(); super.unref(); } + } + + class MemberEnt extends Ent { + ClassEnt klass; + NameAndTypeEnt member; - void dump(DataOutput o) throws IOException { - super.dump(o); - o.writeShort(e1.n); - if (e2 != null) o.writeShort(e2.n); + MemberEnt(int tag) { super(tag); } + MemberEnt(int tag, Type.Class klass, String name, String type) { + this(tag); + this.klass = (ClassEnt) add(klass); + this.member = addNameAndType(name,type); } - private String fixme() { throw new Error("fixme"); } - Object key() throws ClassFile.ClassReadExn { + void dump(DataOutput o) throws IOException { super.dump(o); o.writeShort(klass.n); o.writeShort(member.n); } + + Object _key() { + if(member.name == null) throw new Error("should never happen"); switch(tag) { - case 7: return Type.instance(((Utf8Ent)e1).s); - case 8: return (((Utf8Ent)e1).s); - case 9: { - NameAndTypeKey nt = (NameAndTypeKey) e2.key(); - Type t = Type.instance(nt.type); - if (t == null) throw new ClassFile.ClassReadExn("invalid type descriptor"); - return ((Type.Class)e1.key()).field(nt.name, t); - } - case 10: case 11: { - NameAndTypeKey nt = (NameAndTypeKey) e2.key(); - if (e1.key() == null) throw new Error(e1.tag + " => " + e1.key()); - return ((Type.Class)e1.key()).method("methodname", Type.VOID, new Type[0]); // FIXME FIXME - } - case 12: { - return new NameAndTypeKey(((Utf8Ent)e1).s, ((Utf8Ent)e2).s); - } + case CONSTANT_FIELDREF: + return klass.getTypeClass().field(member.name.s, Type.instance(member.type.s)); + case CONSTANT_METHODREF: + case CONSTANT_INTERFACEMETHODREF: + Type.Class.Method m = klass.getTypeClass().method(member.name.s + member.type.s); + return tag == CONSTANT_INTERFACEMETHODREF ? (Object) new InterfaceMethodKey(m) : (Object) m; + default: + throw new Error("should never happen"); } - throw new Error("FIXME " + tag); - } - } - - class Utf8Ent extends Ent { - String s; - Utf8Ent() { super(1); } - String debugToString() { return s; } - void dump(DataOutput o) throws IOException { super.dump(o); o.writeUTF(s); } - Object key() { - return s; } + void unref() { klass.unref(); member.unref(); super.unref(); } } /* * Cache Keys */ - public static class Utf8Key { + static class Utf8Key { String s; public Utf8Key(String s) { this.s = s; } public boolean equals(Object o) { return o instanceof Utf8Key && ((Utf8Key)o).s.equals(s); } public int hashCode() { return ~s.hashCode(); } } - public static class NameAndTypeKey { + static class NameAndTypeKey { String name; String type; NameAndTypeKey(String name, String type) { this.name = name; this.type = type; } @@ -132,92 +157,92 @@ class ConstantPool { public int hashCode() { return name.hashCode() ^ type.hashCode(); } } + static class InterfaceMethodKey { + Type.Class.Method method; + InterfaceMethodKey(Type.Class.Method method) { this.method = method; } + public int hashCode() { return ~method.hashCode(); } + public boolean equals(Object o) { return o instanceof InterfaceMethodKey && ((InterfaceMethodKey)o).method.equals(method); } + } + /* * Methods */ - public final Ent get(Object o) { return (Ent) entries.get(o); } - public final Ent getUtf8(String s) { return get(new Utf8Key(s)); } - public final int getIndex(Object o) { + Ent get(Object o) { return (Ent) entries.get(o); } + Utf8Ent getUtf8(String s) { return (Utf8Ent) get(new Utf8Key(s)); } + + int getIndex(Object o) { Ent e = get(o); if (e == null) throw new IllegalStateException("entry not found"); return getIndex(e); } - public final String getUtf8ByIndex(int i) { - return ((Utf8Ent)getByIndex(i)).s; - } - public final int getUtf8Index(String s) { + int getUtf8Index(String s) { Ent e = getUtf8(s); if (e == null) throw new IllegalStateException("entry not found"); return getIndex(e); } - public final int getIndex(Ent ent) { + int getIndex(Ent ent) { if (state < STABLE) throw new IllegalStateException("constant pool is not stable"); return ent.n; } - - public final Type getType(int index) throws ClassFile.ClassReadExn { - Ent e = getByIndex(index); - if (e instanceof Utf8Ent) return Type.instance(((Utf8Ent)e).s); - else return (Type)e.key(); - } - - public final Ent getByIndex(int index) { + + Ent getByIndex(int index) { if (state < STABLE) throw new IllegalStateException("constant pool is not stable"); Ent e; if (index >= 65536 || index >= entriesByIndex.length || (e = entriesByIndex[index]) == null) - throw new IllegalStateException("invalid cp index"); + throw new IllegalArgumentException("invalid cp index: " + index + "/" + entriesByIndex.length); return e; } - public final Ent addNameAndType(String name, String descriptor) { return add(new NameAndTypeKey(name, descriptor)); } - public final Ent addUtf8(String s) { return add(new Utf8Key(s)); } + String getUtf8KeyByIndex(int index) { + Ent e = getByIndex(index); + if(!(e instanceof Utf8Ent)) throw new IllegalArgumentException("that isn't a utf8 (" + e.debugToString() + ")"); + return ((Utf8Ent)e).s; + } + + Object getKeyByIndex(int index) { + Ent e = getByIndex(index); + return e == null ? null : e.key(); + } - public final Ent add(Object o) { return add(o, false); } - public final Ent add(Object o, boolean invokeInterface) { + NameAndTypeEnt addNameAndType(String name, String descriptor) { return (NameAndTypeEnt) add(new NameAndTypeKey(name, descriptor)); } + Utf8Ent addUtf8(String s) { return (Utf8Ent) add(new Utf8Key(s)); } + + Ent add(Object o) { + boolean isInterfaceMethod; if (state == SEALED) throw new IllegalStateException("constant pool is sealed"); - + Ent ent = get(o); if (ent != null) { if (state == OPEN) ent.n++; return ent; } - if (o instanceof Type.Class) { - CPRefEnt ce = new CPRefEnt(7); - ce.e1 = addUtf8(((Type.Class)o).internalForm()); - ent = ce; - } else if (o instanceof String) { - CPRefEnt ce = new CPRefEnt(8); - ce.e1 = addUtf8((String)o); - ent = ce; - } else if (o instanceof Integer) { ent = new IntEnt(((Integer)o).intValue()); - } else if (o instanceof Float) { ent = new FloatEnt(((Float)o).floatValue()); - } else if (o instanceof Long) { ent = new LongEnt(((Long)o).longValue()); - } else if (o instanceof Double) { ent = new DoubleEnt(((Double)o).doubleValue()); - } else if (o instanceof Utf8Key) { - Utf8Ent ue = new Utf8Ent(); - ue.s = ((Utf8Key)o).s; - ent = ue; - } else if (o instanceof NameAndTypeKey) { - CPRefEnt ce = new CPRefEnt(12); + if (o instanceof Type.Class) { ent = new ClassEnt(((Type.Class)o).internalForm()); } + else if (o instanceof String) { ent = new StringLitEnt((String)o); } + else if (o instanceof Integer) { ent = new IntLitEnt(((Integer)o).intValue()); } + else if (o instanceof Float) { ent = new FloatLitEnt(((Float)o).floatValue()); } + else if (o instanceof Long) { ent = new LongLitEnt(((Long)o).longValue()); } + else if (o instanceof Double) { ent = new DoubleLitEnt(((Double)o).doubleValue()); } + else if (o instanceof Utf8Key) { ent = new Utf8Ent(((Utf8Key)o).s); } + else if (o instanceof NameAndTypeKey) { NameAndTypeKey key = (NameAndTypeKey) o; - ce.e1 = addUtf8(key.name); - ce.e2 = addUtf8(key.type); - ent = ce; - } else if (o instanceof Type.Class.Member) { - Type.Class.Member key = (Type.Class.Member) o; - int tag = invokeInterface ? 11 : o instanceof Type.Class.Field ? 9 : o instanceof Type.Class.Method ? 10 : 0; + ent = new NameAndTypeEnt(key.name,key.type); + } + else if ((isInterfaceMethod = o instanceof InterfaceMethodKey) || o instanceof Type.Class.Member) { + Type.Class.Member m = isInterfaceMethod ? ((InterfaceMethodKey)o).method : (Type.Class.Member) o; + int tag = isInterfaceMethod ? CONSTANT_INTERFACEMETHODREF + : m instanceof Type.Class.Field ? CONSTANT_FIELDREF + : m instanceof Type.Class.Method ? CONSTANT_METHODREF + : 0; if (tag == 0) throw new Error("should never happen"); - CPRefEnt ce = new CPRefEnt(tag); - ce.e1 = add(key.getDeclaringClass()); - ce.e2 = addNameAndType(key.name, key.getDescriptor()); - ent = ce; - } else { + ent = new MemberEnt(tag, m.getDeclaringClass(), m.name, m.getDescriptor()); + } + else { throw new IllegalArgumentException("Unknown type passed to add"); } - int spaces = ent instanceof LongEnt ? 2 : 1; + int spaces = ent.slots(); if (usedSlots + spaces > 65536) throw new ClassFile.Exn("constant pool full"); ent.n = state == OPEN ? 1 : usedSlots; // refcount or index @@ -228,9 +253,9 @@ class ConstantPool { return ent; } - public int slots() { return usedSlots; } + int slots() { return usedSlots; } - public void seal() { state = SEALED; } + void seal() { state = SEALED; } private Ent[] asArray() { int count = entries.size(); @@ -249,11 +274,11 @@ class ConstantPool { Ent ent = ents[i]; ent.n = index; entriesByIndex[index] = ent; - index += ent instanceof LongEnt ? 2 : 1; + index += ent.slots(); } } - public void stable() { + void stable() { if (state != OPEN) return; state = STABLE; assignIndex(asArray()); @@ -271,7 +296,7 @@ class ConstantPool { } }; - public void optimize() { + void optimize() { if (state != OPEN) throw new IllegalStateException("can't optimize a stable constant pool"); Ent[] ents = asArray(); Sort.sort(ents, reverseCompareFunc); @@ -279,18 +304,7 @@ class ConstantPool { assignIndex(ents); } - public void unsafeReopen() { - if (state == OPEN) return; - for(int i=1;i= usedSlots) throw new ClassFile.ClassReadExn("invalid cp i"); - ce.e1 = entriesByIndex[e1s[i]]; - if (ce.e1 == null) throw new ClassFile.ClassReadExn("invalid cp i"); - if (ce.tag != 7 && ce.tag != 8) { - if (e2s[i] == 0 || e2s[i] >= usedSlots) throw new ClassFile.ClassReadExn("invalid cp i"); - ce.e2 = entriesByIndex[e2s[i]]; - if (ce.e2 == null) throw new ClassFile.ClassReadExn("invalid cp i"); - } - switch(ce.tag) { - case 7: - case 8: - if (!(ce.e1 instanceof Utf8Ent)) throw new ClassFile.ClassReadExn("expected a utf8 ent"); - break; - case 9: - case 10: - case 11: - if (!(ce.e1 instanceof CPRefEnt) || ((CPRefEnt)ce.e1).tag != 7) - throw new ClassFile.ClassReadExn("expected a type ent"); - if (!(ce.e2 instanceof CPRefEnt) || ((CPRefEnt)ce.e2).tag != 12) - throw new ClassFile.ClassReadExn("expected a name and type ent"); - break; - case 12: - if (!(ce.e1 instanceof Utf8Ent)) throw new ClassFile.ClassReadExn("expected a utf8 ent"); - if (!(ce.e2 instanceof Utf8Ent)) throw new ClassFile.ClassReadExn("expected a utf8 ent"); - break; + boolean isMem = e instanceof MemberEnt; + boolean isString = e instanceof StringLitEnt; + boolean isClass = e instanceof ClassEnt; + boolean isNameAndType = e instanceof NameAndTypeEnt; + if (isMem || isClass || isString || isNameAndType) { + if (e1s[i] == 0 || e1s[i] >= usedSlots) throw new ClassFile.ClassReadExn("invalid cp index"); + Ent e1 = entriesByIndex[e1s[i]]; + if(e1 == null) throw new ClassFile.ClassReadExn("invalid cp index"); + if(isClass) { + if(!(e1 instanceof Utf8Ent)) throw new ClassFile.ClassReadExn("expected a uft8ent"); + ((ClassEnt)e).utf8 = (Utf8Ent) e1; + } else if(isString) { + if(!(e1 instanceof Utf8Ent)) throw new ClassFile.ClassReadExn("expected a uft8ent"); + ((StringLitEnt)e).utf8 = (Utf8Ent) e1; + } else if(isMem || isNameAndType) { + if (e2s[i] == 0 || e2s[i] >= usedSlots) throw new ClassFile.ClassReadExn("invalid cp index"); + Ent e2 = entriesByIndex[e2s[i]]; + if(isMem) { + if(!(e1 instanceof ClassEnt)) throw new ClassFile.ClassReadExn("expected a classent"); + if(!(e2 instanceof NameAndTypeEnt)) throw new ClassFile.ClassReadExn("expected a nameandtypeent, not " + e2); + MemberEnt me = (MemberEnt) e; + me.klass = (ClassEnt) e1; + me.member = (NameAndTypeEnt) e2; + } else if(isNameAndType) { + if(!(e1 instanceof Utf8Ent)) throw new ClassFile.ClassReadExn("expected a uft8ent"); + if(!(e2 instanceof Utf8Ent)) throw new ClassFile.ClassReadExn("expected a uft8ent"); + NameAndTypeEnt nte = (NameAndTypeEnt) e; + nte.name = (Utf8Ent) e1; + nte.type = (Utf8Ent) e2; + } + } } + i += e.slots(); } - for(int i=1; i