}
}
- ClassFile(DataInput i) throws IOException {
+ ClassFile(DataInput i) throws IOException { this(i, false); }
+ ClassFile(DataInput i, boolean ssa) throws IOException {
int magic = i.readInt();
if (magic != 0xcafebabe) throw new ClassReadExn("invalid magic: " + Long.toString(0xffffffffL & magic, 16));
minor = i.readShort();
int numFields = i.readShort();
for(int j=0; j<numFields; j++) fields.addElement(new FieldGen(i, cp));
int numMethods = i.readShort();
- for(int j=0; j<numMethods; j++) methods.addElement(new MethodGen(this.getType(), i, cp));
+ for(int j=0; j<numMethods; j++) methods.addElement(ssa
+ ? new JSSA(this.getType(), i, cp)
+ : new MethodGen(this.getType(), i, cp));
attributes = new AttrGen(i, cp);
// FEATURE: Support these
/** 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 implements CGConst {
private final static boolean EMIT_NOPS = false;
private static final int NO_CODE = -1;
// Constructors //////////////////////////////////////////////////////////////////////////////
MethodGen(Type.Class.Method method, int flags) {
+ method.super();
if ((flags & ~VALID_METHOD_FLAGS) != 0) throw new IllegalArgumentException("invalid flags");
this.method = method;
this.flags = flags;
}
MethodGen(Type.Class c, DataInput in, ConstantPool cp) throws IOException {
- this.flags = in.readShort();
+ 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();
+ this.flags = flags;
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.method = m;
this.attrs = new ClassFile.AttrGen(in,cp);
if ((flags & (NATIVE|ABSTRACT))==0) {
// 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)
*/
// 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",
"", "", "", "", "", "",
"", "", "", ""
};
-
- 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(" ");
- }
- if ((flags & (NATIVE|ABSTRACT))==0) {
- sb.append("{\n");
- for(int i=0;i<size();i++) {
- sb.append(" ");
- for(int j=i==0?1:i;j<10000;j*=10) sb.append(" ");
- sb.append(i).append(": ");
- sb.append(OP_NAMES[op[i]&0xff]);
- String s = null;
- if (arg[i] instanceof Type) s = ((Type)arg[i]).debugToString();
- else if (arg[i] instanceof Type.Class.Member) s = ((Type.Class.Member)arg[i]).toString();
- else if (arg[i] instanceof String) s = "\"" + s + "\"";
- else if (arg[i] != null) s = arg[i].toString();
- if (s != null) sb.append(" ").append(s);
- sb.append("\n");
- }
- sb.append(" }\n");
- } else {
- sb.append(";");
+ for(int i=0;i<size();i++) {
+ sb.append(" ");
+ for(int j=i==0?1:i;j<10000;j*=10) sb.append(" ");
+ sb.append(i).append(": ");
+ sb.append(OP_NAMES[op[i]&0xff]);
+ String s = null;
+ if (arg[i] instanceof Type) s = ((Type)arg[i]).debugToString();
+ else if (arg[i] instanceof Type.Class.Member) s = ((Type.Class.Member)arg[i]).toString();
+ else if (arg[i] instanceof String) s = "\"" + s + "\"";
+ else if (arg[i] != null) s = arg[i].toString();
+ if (s != null) sb.append(" ").append(s);
+ sb.append("\n");
}
}
import java.util.StringTokenizer;
import java.util.Hashtable;
-public class Type {
+public class Type implements CGConst {
private static Hashtable instances = new Hashtable(); // this has to appear at the top of the file
sb.append(returnType.getDescriptor());
return sb.toString();
}
+ public abstract class Body implements HasFlags {
+ public abstract java.util.Hashtable getThrownExceptions();
+ public abstract void debugBodyToString(StringBuffer sb);
+ public void debugToString(StringBuffer sb, String constructorName) {
+ int flags = getFlags();
+ sb.append(" ").append(ClassFile.flagsToString(flags,false));
+ sb.append(Method.this.debugToString());
+ java.util.Hashtable thrownExceptions = getThrownExceptions();
+ if (thrownExceptions.size() > 0) {
+ sb.append("throws");
+ for(java.util.Enumeration e = thrownExceptions.keys();e.hasMoreElements();)
+ sb.append(" ").append(((Type.Class)e.nextElement()).debugToString()).append(",");
+ sb.setLength(sb.length()-1);
+ sb.append(" ");
+ }
+ if ((flags & (NATIVE|ABSTRACT))==0) {
+ sb.append("{\n");
+ debugBodyToString(sb);
+ sb.append(" }\n");
+ } else {
+ sb.append(";");
+ }
+ }
+ }
}
}