X-Git-Url: http://git.megacz.com/?p=org.ibex.classgen.git;a=blobdiff_plain;f=src%2Forg%2Fibex%2Fclassgen%2FMethodGen.java;h=ef40595c82287c4be889e97590ec72c3023c970f;hp=baf7fe3f4e79842af1741c592987e7ac48e5cf94;hb=ddf408851103280fd02c37c7afd806a94b2a3ec3;hpb=72cc9664e25a90f5241c9f4c39319889cd36ed15 diff --git a/src/org/ibex/classgen/MethodGen.java b/src/org/ibex/classgen/MethodGen.java index baf7fe3..ef40595 100644 --- a/src/org/ibex/classgen/MethodGen.java +++ b/src/org/ibex/classgen/MethodGen.java @@ -5,50 +5,47 @@ import java.util.*; /** A class representing a method in a generated classfile @see ClassFile#addMethod */ -public class MethodGen implements CGConst { +public class MethodGen extends Type.Class.Method.Body { private final static boolean EMIT_NOPS = false; private static final int NO_CODE = -1; - private final Type.Class.Method method; - private final int flags; - private final ClassFile.AttrGen attrs; + public final Type.Class.Method method; private final ClassFile.AttrGen codeAttrs; private final Vector exnTable = new Vector(); private final Hashtable thrownExceptions = new Hashtable(); - private int maxStack = 16; - private int maxLocals; + int maxStack = 16; + int maxLocals; private int size; private int capacity; private byte[] op; private Object[] arg; private ConstantPool.Ent[] cparg; - + + // Constructors ////////////////////////////////////////////////////////////////////////////// MethodGen(Type.Class.Method method, int flags) { - if ((flags & ~VALID_METHOD_FLAGS) != 0) throw new IllegalArgumentException("invalid flags"); + method.super(flags, new ClassFile.AttrGen()); this.method = method; - this.flags = flags; - - attrs = new ClassFile.AttrGen(); codeAttrs = new ClassFile.AttrGen(); - - if (((flags & INTERFACE) != 0) || (flags & (ABSTRACT|NATIVE)) != 0) size = capacity = -1; - + if (!isConcrete()) size = capacity = -1; maxLocals = Math.max(method.getNumArgs() + (flags&STATIC)==0 ? 1 : 0, 4); } MethodGen(Type.Class c, DataInput in, ConstantPool cp) throws IOException { - this.flags = in.readShort(); - if ((flags & ~VALID_METHOD_FLAGS) != 0) throw new ClassFile.ClassReadExn("invalid flags"); - String name = cp.getUtf8KeyByIndex(in.readShort()); - this.method = c.method(name+cp.getUtf8KeyByIndex(in.readShort())); - this.attrs = new ClassFile.AttrGen(in,cp); + this(in.readShort(), cp.getUtf8KeyByIndex(in.readShort()), c, in, cp); } + + private MethodGen(short flags, String name, Type.Class c, DataInput in, ConstantPool cp) throws IOException { + this(flags, name, c.method(name,cp.getUtf8KeyByIndex(in.readShort())), c, in, cp); } + private MethodGen(short flags, String name, Type.Class.Method m, + Type.Class c, DataInput in, ConstantPool cp) throws IOException { + m.super(flags, new ClassFile.AttrGen(in,cp)); + this.method = m; - if ((flags & (NATIVE|ABSTRACT))==0) { + if (isConcrete()) { byte[] codeAttr = (byte[]) attrs.get("Code"); if (codeAttr == null) throw new ClassFile.ClassReadExn("code attr expected"); DataInputStream ci = new DataInputStream(new ByteArrayInputStream(codeAttr)); @@ -136,7 +133,7 @@ public class MethodGen implements CGConst { break; } case MULTIANEWARRAY: - arg = new MultiANewArray((Type.Class)cp.getKeyByIndex(in.readUnsignedShort()),in.readUnsignedByte()); + arg = new MultiANewArray((Type.Array)cp.getKeyByIndex(in.readUnsignedShort()),in.readUnsignedByte()); break; case INVOKEINTERFACE: { ConstantPool.Ent ent = cp.getByIndex(in.readUnsignedShort()); @@ -291,7 +288,8 @@ public class MethodGen implements CGConst { } /** Adds a exception type that can be thrown from this method - NOTE: This isn't enforced by the JVM. This is for reference only. A method can throw exceptions not declared to be thrown + NOTE: This isn't enforced by the JVM. This is for reference + only. A method can throw exceptions not declared to be thrown @param type The type of exception that can be thrown */ public final void addThrow(Type.Class type) { thrownExceptions.put(type, type); } @@ -315,6 +313,9 @@ public class MethodGen implements CGConst { // Accessors ////////////////////////////////////////////////////////////////////////////// + public int getFlags() { return flags; } + public Hashtable getThrownExceptions() { return thrownExceptions; } + /** Returns the size (in instructions) of this method @return The size of the method (in instructions) */ @@ -531,9 +532,9 @@ public class MethodGen implements CGConst { } public static class MultiANewArray { - public Type.Class type; + public Type.Array type; public int dims; - public MultiANewArray(Type.Class type, int dims) { this.type = type; this.dims = dims; } + public MultiANewArray(Type.Array type, int dims) { this.type = type; this.dims = dims; } } public static class Wide { @@ -547,30 +548,6 @@ public class MethodGen implements CGConst { // Emitting Bits ////////////////////////////////////////////////////////////////////////////// - /** Negates the IF* instruction, op (IF_ICMPGT -> IF_ICMPLE, IFNE -> IFEQ, etc) - @exception IllegalArgumentException if op isn't an IF* instruction */ - public static byte negate(byte op) { - switch(op) { - case IFEQ: return IFNE; - case IFNE: return IFEQ; - case IFLT: return IFGE; - case IFGE: return IFLT; - case IFGT: return IFLE; - case IFLE: return IFGT; - case IF_ICMPEQ: return IF_ICMPNE; - case IF_ICMPNE: return IF_ICMPEQ; - case IF_ICMPLT: return IF_ICMPGE; - case IF_ICMPGE: return IF_ICMPLT; - case IF_ICMPGT: return IF_ICMPLE; - case IF_ICMPLE: return IF_ICMPGT; - case IF_ACMPEQ: return IF_ACMPNE; - case IF_ACMPNE: return IF_ACMPEQ; - - default: - throw new IllegalArgumentException("Can't negate " + Integer.toHexString(op)); - } - } - private Object resolveTarget(Object arg) { int target; if (arg instanceof PhantomTarget) { @@ -591,7 +568,7 @@ public class MethodGen implements CGConst { */ void finish(ConstantPool cp) { cp.addUtf8(method.name); - cp.addUtf8(method.getDescriptor()); + cp.addUtf8(method.getTypeDescriptor()); for(Enumeration e = thrownExceptions.keys();e.hasMoreElements();) cp.add(e.nextElement()); @@ -865,7 +842,9 @@ public class MethodGen implements CGConst { } else if (argLength == 7) { throw new Error("should never happen - variable length instruction not explicitly handled"); } else { - int iarg = ((Integer)arg).intValue(); + int iarg = (arg instanceof Type.Primitive) + ? ((Type.Primitive)arg).toArraySpec() + : ((Integer)arg).intValue(); if (argLength == 1) { if ((opdata & OP_UNSIGNED_FLAG) != 0 ? iarg >= 256 : (iarg < -128 || iarg >= 128)) throw new ClassFile.Exn("overflow of s/u1 option"); @@ -913,7 +892,7 @@ public class MethodGen implements CGConst { o.writeShort(flags); o.writeShort(cp.getUtf8Index(method.name)); - o.writeShort(cp.getUtf8Index(method.getDescriptor())); + o.writeShort(cp.getUtf8Index(method.getTypeDescriptor())); attrs.dump(o,cp); } @@ -966,7 +945,7 @@ public class MethodGen implements CGConst { // Debugging ////////////////////////////////////////////////////////////////////////////// - public void debugToString(StringBuffer sb, String constructorName) { + public void debugBodyToString(StringBuffer sb) { // This is intentionally a local variable so it can be removed by gcclass final String[] OP_NAMES = new String[]{ "nop", "aconst_null", "iconst_m1", "iconst_0", "iconst_1", "iconst_2", @@ -1013,35 +992,46 @@ public class MethodGen implements CGConst { "", "", "", "", "", "", "", "", "", "" }; - - sb.append(" ").append(ClassFile.flagsToString(flags,false)); - sb.append(method.debugToString()); - if (thrownExceptions.size() > 0) { - sb.append("throws"); - for(Enumeration e = thrownExceptions.keys();e.hasMoreElements();) - sb.append(" ").append(((Type.Class)e.nextElement()).debugToString()).append(","); - sb.setLength(sb.length()-1); - sb.append(" "); + for(int i=0;iop (IF_ICMPGT -> IF_ICMPLE, IFNE -> IFEQ, etc) + @exception IllegalArgumentException if op isn't an IF* instruction */ + public static byte negate(byte op) { + switch(op) { + case IFEQ: return IFNE; + case IFNE: return IFEQ; + case IFLT: return IFGE; + case IFGE: return IFLT; + case IFGT: return IFLE; + case IFLE: return IFGT; + case IF_ICMPEQ: return IF_ICMPNE; + case IF_ICMPNE: return IF_ICMPEQ; + case IF_ICMPLT: return IF_ICMPGE; + case IF_ICMPGE: return IF_ICMPLT; + case IF_ICMPGT: return IF_ICMPLE; + case IF_ICMPLE: return IF_ICMPGT; + case IF_ACMPEQ: return IF_ACMPNE; + case IF_ACMPNE: return IF_ACMPEQ; + + default: + throw new IllegalArgumentException("Can't negate " + Integer.toHexString(op)); } } + }