public int hashCode() { return ~s.hashCode(); }
}
+ static class NameAndTypeKey {
+ String name;
+ String type;
+ NameAndTypeKey(String name, String type) { this.name = name; this.type = type; }
+ public boolean equals(Object o_) {
+ if(!(o_ instanceof NameAndTypeKey)) return false;
+ NameAndTypeKey o = (NameAndTypeKey) o_;
+ return o.name.equals(name) && o.type.equals(type);
+ }
+ public int hashCode() { return name.hashCode() ^ type.hashCode(); }
+ }
+
/*
* Methods
*/
return e.getIndex();
}
- public final Ent addNameAndType(String name, String descriptor) { return add(new ClassGen.NameAndType(name,descriptor)); }
+ 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)); }
public final Ent add(Object o) {
Utf8Ent ue = new Utf8Ent();
ue.s = ((Utf8Key)o).s;
ent = ue;
- } else if(o instanceof ClassGen.NameAndType) {
+ } else if(o instanceof NameAndTypeKey) {
CPRefEnt ce = new CPRefEnt(12);
- ClassGen.NameAndType key = (ClassGen.NameAndType) o;
+ NameAndTypeKey key = (NameAndTypeKey) o;
ce.e1 = addUtf8(key.name);
ce.e2 = addUtf8(key.type);
ent = ce;
- } else if(o instanceof ClassGen.FieldMethodRef) {
- ClassGen.FieldMethodRef key = (ClassGen.FieldMethodRef) o;
- int tag = o instanceof FieldRef ? 9 : o instanceof MethodRef ? 10 : o instanceof ClassGen.InterfaceMethodRef ? 11 : 0;
+ } else if(o instanceof ClassGen.FieldOrMethodRef) {
+ ClassGen.FieldOrMethodRef key = (ClassGen.FieldOrMethodRef) o;
+ int tag = o instanceof FieldRef ? 9 : o instanceof MethodRef ? 10 : o instanceof MethodRef.I ? 11 : 0;
if(tag == 0) throw new Error("should never happen");
CPRefEnt ce = new CPRefEnt(tag);
ce.e1 = add(key.klass);
- ce.e2 = add(key.nameAndType);
+ ce.e2 = addNameAndType(key.name,key.descriptor);
ent = ce;
} else {
throw new IllegalArgumentException("Unknown type passed to add");
public Exn(String s) { super(s); }
}
- public static class NameAndType {
- String name;
- String type;
- NameAndType(String name, String type) { this.name = name; this.type = type; }
- public boolean equals(Object o_) {
- if(!(o_ instanceof NameAndType)) return false;
- NameAndType o = (NameAndType) o_;
- return o.name.equals(name) && o.type.equals(type);
- }
- public int hashCode() { return name.hashCode() ^ type.hashCode(); }
- }
-
- public static abstract class FieldMethodRef {
+ public static abstract class FieldOrMethodRef {
Type.Object klass;
- NameAndType nameAndType;
- FieldMethodRef(Type.Object klass, NameAndType nameAndType) { this.klass = klass; this.nameAndType = nameAndType; }
+ String name;
+ String descriptor;
+
+ FieldOrMethodRef(Type.Object klass, String name, String descriptor) { this.klass = klass; this.name = name; this.descriptor = descriptor; }
+ FieldOrMethodRef(FieldOrMethodRef o) { this.klass = o.klass; this.name = o.name; this.descriptor = o.descriptor; }
public boolean equals(Object o_) {
- if(!(o_ instanceof FieldMethodRef)) return false;
- FieldMethodRef o = (FieldMethodRef) o_;
- return o.klass.equals(klass) && o.nameAndType.equals(nameAndType);
+ if(!(o_ instanceof FieldOrMethodRef)) return false;
+ FieldOrMethodRef o = (FieldOrMethodRef) o_;
+ return o.klass.equals(klass) && o.name.equals(name) && o.descriptor.equals(descriptor);
}
- public int hashCode() { return klass.hashCode() ^ nameAndType.hashCode(); }
- }
-
- public static class InterfaceMethodRef extends FieldMethodRef {
- public InterfaceMethodRef(MethodRef r) { super(r.klass,r.nameAndType); }
- public InterfaceMethodRef(Type.Object c, NameAndType t) { super(c,t); }
+ public int hashCode() { return klass.hashCode() ^ name.hashCode() ^ descriptor.hashCode(); }
}
static class AttrGen {
package org.ibex.classgen;
-public class FieldRef extends ClassGen.FieldMethodRef {
- public FieldRef (Type.Object c, ClassGen.NameAndType t) { super(c,t); }
- public FieldRef(Type.Object c, String name, Type t) { super(c,new ClassGen.NameAndType(name,t.getDescriptor())); }
+public class FieldRef extends ClassGen.FieldOrMethodRef {
+ public FieldRef(Type.Object c, String name, Type t) { super(c,name,t.getDescriptor()); }
+ public FieldRef(String s, String name, Type t) { this(new Type.Object(s),name,t); }
}
public final void set(int pos, byte op, boolean b) { set(pos,op,b?1:0); }
- public final void set(int pos, byte op, int n) {
- if(op == LDC) {
- switch(n) {
- case -1: set(pos,ICONST_M1); return;
- case 0: set(pos,ICONST_0); return;
- case 1: set(pos,ICONST_1); return;
- case 2: set(pos,ICONST_2); return;
- case 3: set(pos,ICONST_3); return;
- case 4: set(pos,ICONST_4); return;
- case 5: set(pos,ICONST_5); return;
- }
- Object arg;
- if(n >= -128 && n <= 127) { op = BIPUSH; arg = N(n); }
- else if(n >= -32767 && n <= 32767) { op = SIPUSH; arg = N(n); }
- else { arg = cp.add(N(n)); }
- this.op[pos] = op;
- this.arg[pos] = arg;
- } else {
- set(pos,op,N(n));
- }
- }
- public void set(int pos, byte op, Object arg) {
- switch(op) {
+ // This MUST handle x{LOAD,STORE} and LDC with an int arg WITHOUT falling back to set(int,byte,Object)
+ public final void set(int pos, byte op, int n) {
+ Object arg = null;
+ OUTER: switch(op) {
+ case LDC:
+ switch(n) {
+ case -1: op = ICONST_M1; break OUTER;
+ case 0: op = ICONST_0; break OUTER;
+ case 1: op = ICONST_1; break OUTER;
+ case 2: op = ICONST_2; break OUTER;
+ case 3: op = ICONST_3; break OUTER;
+ case 4: op = ICONST_4; break OUTER;
+ case 5: op = ICONST_5; break OUTER;
+ }
+ if(n >= -128 && n <= 127) { op = BIPUSH; arg = N(n); }
+ else if(n >= -32767 && n <= 32767) { op = SIPUSH; arg = N(n); }
+ else { arg = cp.add(N(n)); }
+ break;
case ILOAD: case ISTORE: case LLOAD: case LSTORE: case FLOAD:
case FSTORE: case DLOAD: case DSTORE: case ALOAD: case ASTORE:
- {
- int iarg = ((Integer)arg).intValue();
- if(iarg >= 0 && iarg <= 3) {
+ if(n >= 0 && n <= 3) {
byte base = 0;
switch(op) {
- case ILOAD: base = ILOAD_0; break;
+ case ILOAD: base = ILOAD_0; break;
case ISTORE: base = ISTORE_0; break;
- case LLOAD: base = LLOAD_0; break;
+ case LLOAD: base = LLOAD_0; break;
case LSTORE: base = LSTORE_0; break;
- case FLOAD: base = FLOAD_0; break;
+ case FLOAD: base = FLOAD_0; break;
case FSTORE: base = FSTORE_0; break;
- case DLOAD: base = DLOAD_0; break;
+ case DLOAD: base = DLOAD_0; break;
case DSTORE: base = DSTORE_0; break;
- case ALOAD: base = ALOAD_0; break;
+ case ALOAD: base = ALOAD_0; break;
case ASTORE: base = ASTORE_0; break;
}
- op = (byte)((base&0xff) + iarg);
+ op = (byte)((base&0xff) + n);
} else {
- if(iarg >= maxLocals) maxLocals = iarg + 1;
+ if(n >= maxLocals) maxLocals = n + 1;
+ arg = N(n);
}
break;
- }
+ default:
+ set(pos,op,N(n));
+ return;
+ }
+ this.op[pos] = op;
+ this.arg[pos] = arg;
+ }
+
+ public final void set(int pos, byte op, Object arg) {
+ switch(op) {
+ case ILOAD: case ISTORE: case LLOAD: case LSTORE: case FLOAD:
+ case FSTORE: case DLOAD: case DSTORE: case ALOAD: case ASTORE:
+ // set(int,byte,int) always handles these ops itself
+ set(pos,op,((Integer)arg).intValue());
+ return;
case LDC:
+ // set(int,byte,int) always handles these opts itself
if(arg instanceof Integer) { set(pos,op,((Integer)arg).intValue()); return; }
if(arg instanceof Boolean) { set(pos,op,((Boolean)arg).booleanValue()); return; }
+
if(arg instanceof Long) {
long l = ((Long)arg).longValue();
- if(l == 0L) { set(pos,LCONST_0); return; }
- if(l == 1L) { set(pos,LCONST_1); return; }
+ if(l == 0L) { this.op[pos] = LCONST_0; return; }
+ if(l == 1L) { this.op[pos] = LCONST_1; return; }
}
if(arg instanceof Long || arg instanceof Double) op = LDC2_W;
- // fall through
- default: {
- int opdata = OP_DATA[op&0xff];
- if((opdata&OP_CPENT_FLAG) != 0 && !(arg instanceof CPGen.Ent))
- arg = cp.add(arg);
- else if((opdata&OP_VALID_FLAG) == 0)
- throw new IllegalArgumentException("unknown bytecode");
break;
- }
+ case INVOKEINTERFACE:
+ if(arg instanceof MethodRef) arg = new MethodRef.I((MethodRef)arg);
+ break;
}
+ int opdata = OP_DATA[op&0xff];
+ if((opdata&OP_CPENT_FLAG) != 0 && !(arg instanceof CPGen.Ent))
+ arg = cp.add(arg);
+ else if((opdata&OP_VALID_FLAG) == 0)
+ throw new IllegalArgumentException("unknown bytecode");
this.op[pos] = op;
this.arg[pos] = arg;
}
public int size() { return targets.length; }
public int getTarget(int pos) { return ((Integer)targets[pos]).intValue(); }
- public int getDefaultTarget() { return ((Integer)defaultTarget).intValue(); }
+ public int getDefaultTarget() { return ((Integer)defaultTarget).intValue(); }
}
public static class TSI extends SI {
case TABLESWITCH:
case LOOKUPSWITCH: {
SI si = (SI) arg[i];
- p++; // opcpde itself
+ p++; // opcode itself
p = (p + 3) & ~3; // padding
p += 4; // default
if(op == TABLESWITCH) p += 4 + 4 + si.size() * 4; // lo, hi, targets
}
break;
}
+ case WIDE:
+ throw new Error("WIDE instruction not yet supported");
default:
if((opdata & OP_BRANCH_FLAG) != 0) {
if(argLength == 1) o.writeByte(v);
else if(argLength == 2) o.writeShort(v);
else throw new Error("should never happen");
- } else if(argLength == -1) {
+ } else if(argLength == 7) {
throw new Error("should never happen - variable length instruction not explicitly handled");
} else {
int iarg = ((Integer)arg).intValue();
package org.ibex.classgen;
-public class MethodRef extends ClassGen.FieldMethodRef {
- public MethodRef(Type.Object c, ClassGen.NameAndType t) { super(c,t); }
- public MethodRef(Type.Object c, String name, String descriptor) {
- this(c,new ClassGen.NameAndType(name,descriptor));
- }
+public class MethodRef extends ClassGen.FieldOrMethodRef {
public MethodRef(Type.Object c, String name, Type ret, Type[] args) {
- this(c,name,getDescriptor(ret,args));
+ super(c,name,getDescriptor(ret,args));
}
public MethodRef(String s, String name, Type ret, Type[] args) {
this(new Type.Object(s),name,ret,args);
}
+ MethodRef(MethodRef i) { super(i); }
static String getDescriptor(Type ret, Type[] args) {
StringBuffer sb = new StringBuffer(args.length*4);
sb.append(ret.getDescriptor());
return sb.toString();
}
+
+ public static class I extends MethodRef {
+ public I(Type.Object c, String name, Type ret, Type[] args) { super(c,name,ret,args); }
+ public I(String s, String name, Type ret, Type[] args) { super(s,name,ret,args); }
+ I(MethodRef m) { super(m); }
+ }
}
-