bytecode-0.92.svn.20090106/0000755000175100017510000000000011130515001014614 5ustar moellermoellerbytecode-0.92.svn.20090106/test/0000755000175100017510000000000011130515001015573 5ustar moellermoellerbytecode-0.92.svn.20090106/test/MakeHelloWorld.java0000755000175100017510000000542307273254364021347 0ustar moellermoellerpackage test; import org.biojava.utils.bytecode.*; import java.util.*; import java.io.*; public class MakeHelloWorld { public static void main(String[] args) throws Exception { CodeClass cl_Object = IntrospectedCodeClass.forClass("java.lang.Object"); CodeClass cl_String = IntrospectedCodeClass.forClass("java.lang.String"); CodeClass cl_System = IntrospectedCodeClass.forClass("java.lang.System"); CodeClass cl_PrintStream = IntrospectedCodeClass.forClass("java.io.PrintStream"); CodeClass cl_pVoid = IntrospectedCodeClass.forClass(Void.TYPE); CodeClass i_Runnable = IntrospectedCodeClass.forClass(Runnable.class); CodeClass[] aInterfaces = { i_Runnable }; CodeField f_System_out = cl_System.getFieldByName("out"); CodeMethod m_PrintStream_println_I = oneIntMethod(cl_PrintStream.getMethodsByName("println")); CodeMethod m_Object_init = new SimpleCodeMethod("", cl_Object, cl_pVoid, new ArrayList(), CodeUtils.ACC_PUBLIC); CodeClass[] aMethodArgs = {}; GeneratedCodeClass cc = new GeneratedCodeClass("MyTestClass", IntrospectedCodeClass.forClass("java.lang.Object"), aInterfaces, CodeUtils.ACC_PUBLIC | CodeUtils.ACC_SUPER); GeneratedCodeMethod init = cc.createMethod("", cl_pVoid, aMethodArgs, CodeUtils.ACC_PUBLIC); InstructionVector iv = new InstructionVector(); iv.add(ByteCode.make_aload(init.getThis())); iv.add(ByteCode.make_invokespecial(m_Object_init)); iv.add(ByteCode.make_return()); cc.setCodeGenerator(init, iv); GeneratedCodeMethod run = cc.createMethod("run", cl_pVoid, aMethodArgs, CodeUtils.ACC_PUBLIC); iv = new InstructionVector(); Label loopTest = new Label(); Label loopStart = new Label(); Label loopEnd = new Label(); iv.add(ByteCode.make_iconst(1)); iv.add(ByteCode.make_goto(loopStart)); iv.add(loopTest); iv.add(ByteCode.make_dup()); iv.add(ByteCode.make_iconst(10)); iv.add(ByteCode.make_if_icmpgt(loopEnd)); iv.add(loopStart); iv.add(ByteCode.make_dup()); iv.add(ByteCode.make_getstatic(f_System_out)); iv.add(ByteCode.make_swap()); iv.add(ByteCode.make_invokevirtual(m_PrintStream_println_I)); iv.add(ByteCode.make_iconst(1)); iv.add(ByteCode.make_iadd()); iv.add(ByteCode.make_goto(loopTest)); iv.add(loopEnd); iv.add(ByteCode.make_return()); cc.setCodeGenerator(run, iv); FileOutputStream fos = new FileOutputStream("MyTestClass.class"); cc.createCode(fos); fos.close(); } static CodeMethod oneIntMethod(Set methods) { CodeClass cl_pInt = IntrospectedCodeClass.forClass(Integer.TYPE); for (Iterator i = methods.iterator(); i.hasNext(); ) { CodeMethod cm = (CodeMethod) i.next(); if (cm.numParameters() != 1) continue; if (cm.getParameterType(0) == cl_pInt) return cm; } return null; } } bytecode-0.92.svn.20090106/test/Runner.java0000755000175100017510000000044007166654572017747 0ustar moellermoellerpackage test; public class Runner { public static void main(String[] args) throws Exception { if(args.length != 1) { throw new Exception("Use: test.Runner runnableClass"); } Class cl = Class.forName(args[0]); Runnable r = (Runnable) cl.newInstance(); r.run(); } } bytecode-0.92.svn.20090106/manifest/0000755000175100017510000000000011130515001016422 5ustar moellermoellerbytecode-0.92.svn.20090106/manifest/defaultmanifest.txt0000644000175100017510000000000007703537432022353 0ustar moellermoellerbytecode-0.92.svn.20090106/src/0000755000175100017510000000000011130515001015403 5ustar moellermoellerbytecode-0.92.svn.20090106/src/org/0000755000175100017510000000000011130515001016172 5ustar moellermoellerbytecode-0.92.svn.20090106/src/org/biojava/0000755000175100017510000000000011130515001017605 5ustar moellermoellerbytecode-0.92.svn.20090106/src/org/biojava/utils/0000755000175100017510000000000011130515001020745 5ustar moellermoellerbytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/0000755000175100017510000000000011130515001022543 5ustar moellermoellerbytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/Label.java0000755000175100017510000000274211130400365024443 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * A Label used to mark a position in byte code. * *

* Labels are used as the targets for jumps, and for exception handlers. Labels * can be named. They implement CodeGenerator, which allows them to be added * to things like an InstructionVector. The writeCode method takes care of * marking the label with the context. *

* * @author Thomas Down * @author Matthew Pocock */ public class Label implements CodeGenerator { public String name; public Label() { name = null; } public Label(String name) { this.name = name; } public String toString() { if (name != null) return name; return super.toString(); } public void writeCode(CodeContext ctx) throws CodeException { ctx.markLabel(this); } public int stackDepth() { return 0; } public int stackDelta() { return 0; } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/IntrospectedCodeMethod.java0000755000175100017510000000371311130400365030022 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; import java.lang.reflect.*; /** * Wrap up details about a method in a Java class file * * @author Thomas Down */ class IntrospectedCodeMethod implements CodeMethod { private final Method _method; public IntrospectedCodeMethod(Method m) { _method = m; } public String getName() { return _method.getName(); } public String getFullName() { return _method.getDeclaringClass().getName() + "." + getName(); } public CodeClass getContainingClass() { return IntrospectedCodeClass.forClass(_method.getDeclaringClass()); } public String getDescriptor() { StringBuffer sb = new StringBuffer(); sb.append('('); for (int i = 0; i < numParameters(); ++i) { CodeClass cc = getParameterType(i); sb.append(cc.getDescriptor()); } sb.append(')'); sb.append(getReturnType().getDescriptor()); return sb.toString(); } public int getModifiers() { return _method.getModifiers(); } public CodeClass getReturnType() { return IntrospectedCodeClass.forClass(_method.getReturnType()); } public int numParameters() { return _method.getParameterTypes().length; } public CodeClass getParameterType(int pos) { return IntrospectedCodeClass.forClass(_method.getParameterTypes()[pos]); } public String toString() { return super.toString() + " " + getDescriptor(); } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/CodeClass.java0000755000175100017510000000606611130400365025267 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; import java.util.*; /** * Interface for Java classes within the bytecode generation framework. * Any class (or interface) can be viewed as a CodeClass, whether it * is pre-existing or being generated. * * @author Thomas Down * @author Matthew Pocock */ public interface CodeClass { String getName(); String getJName(); String getDescriptor(); CodeClass getSuperClass(); List getInterfaces(); /** * Get all methods declared by this class and its super classes, removing * all super class methods that are over ridden. * *

* This should return methods, regardless of their accessability. *

* * @return a Set containing all methods */ Set getMethods(); /** * Get the name of all methods that could be invoked through this class with * a given name. * * @param name the name of the method * @return a Set of CodeMethod instances with that name */ Set getMethodsByName(String name); /** * Get a method by name and argument list. * * @param name the name of the method * @param args the arguments it takes * @return a matching method * @throws NoSuchMethodException if there is no maching method */ CodeMethod getMethod(String name, CodeClass[] args) throws NoSuchMethodException; /** * Get a constructor by argument list. * * @param args the arguments it takes * @return a matching constructor * @throws NoSuchMethodException if there is no matching constructor */ CodeMethod getConstructor(CodeClass[] args) throws NoSuchMethodException; /** * Get a field by its name. * * @param name the field name * @return a CodeField representing the field * @throws NoSuchFieldException if there is no field by that name accessible * through this class */ CodeField getFieldByName(String name) throws NoSuchFieldException; /** * Get all fields accessible through this class. * * @return a Set of all accessible fields */ Set getFields(); /** * Get the modifiers associated with the class. * * @return the modifier integer */ int getModifiers(); /** * Discover if the class represents a primitive type. * * @return true if the class represents a primative type */ public boolean isPrimitive(); /** * Discover if the class is an array type. * * @return true if the class is an array type */ public boolean isArray(); } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/IntrospectedCodeClass.java0000755000175100017510000002163011130400365027645 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; import java.util.*; import java.lang.reflect.*; // fix for array types so that their descriptors are not prefixed with L /** * CodeClass instances that represent normal Java Class objects. * *

* Instances of IntrospectedCodeClass are generated using the static factory * methods named forClass(). These methods ensure that the same * IntrospectedCodeClass instance is returned for multiple invocations with * the same argument. *

* * @author Thomas Down * @author Matthew Pocock */ public class IntrospectedCodeClass implements CodeClass { private static Map introspectedClasses; private static Map primitiveDescriptors; static { introspectedClasses = new HashMap(); primitiveDescriptors = new HashMap(); primitiveDescriptors.put(Byte.TYPE, "B"); primitiveDescriptors.put(Character.TYPE, "C"); primitiveDescriptors.put(Double.TYPE, "D"); primitiveDescriptors.put(Float.TYPE, "F"); primitiveDescriptors.put(Integer.TYPE, "I"); primitiveDescriptors.put(Long.TYPE, "J"); primitiveDescriptors.put(Short.TYPE, "S"); primitiveDescriptors.put(Boolean.TYPE, "Z"); primitiveDescriptors.put(Void.TYPE, "V"); } /** * Get the CodeClass for a Java Class. * * @param c the Java Class to reflect * @return a CodeClass representing the class */ public static CodeClass forClass(Class c) { CodeClass cc = (CodeClass) introspectedClasses.get(c); if (cc == null) { cc = new IntrospectedCodeClass(c); introspectedClasses.put(c, cc); } return cc; } /** * Get the CodeClass for a Java class name. * * @param name the Java class name to reflect * @return a CodeClass representing the class */ public static CodeClass forClass(String name) throws ClassNotFoundException { Class c = ClassLoader.getSystemClassLoader().loadClass(name); return forClass(c); } public static CodeMethod forMethod(Method method) { return new IntrospectedCodeMethod(method); } // // Instance // private Class clazz; private IntrospectedCodeClass(Class c) { this.clazz = c; } public String getName() { return clazz.getName(); } public String getJName() { String name = getName(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < name.length(); ++i) { char c = name.charAt(i); if (c == '.') sb.append('/'); else sb.append(c); } return sb.toString(); } public String getDescriptor() { if (clazz.isPrimitive()) { String desc = (String) primitiveDescriptors.get(clazz); if (desc == null) { throw new RuntimeException("Unknown primitive type " + clazz.getName() + ", eeek!"); } return desc; } if (clazz.isArray()) { return "[" + IntrospectedCodeClass.forClass(clazz.getComponentType()).getDescriptor(); } else { String name = getName(); StringBuffer sb = new StringBuffer(); sb.append('L'); for (int i = 0; i < name.length(); ++i) { char c = name.charAt(i); if (c == '.') { sb.append('/'); } else { sb.append(c); } } sb.append(';'); return sb.toString(); } } public int getModifiers() { return clazz.getModifiers(); } public CodeClass getSuperClass() { return IntrospectedCodeClass.forClass(clazz.getSuperclass()); } public List getInterfaces() { Class[] interfaces = clazz.getInterfaces(); return Arrays.asList(interfaces); } private Set _methods; private Map _methsByNameSig; private Map _methsByName; public Set getMethods() { initMethods(); return _methods; } private void initMethods() { if (_methods == null) { Map meths = new HashMap(); popMeths(this.clazz, meths); popIMeths(this.clazz, meths); _methods = new HashSet(meths.values()); _methsByNameSig = new HashMap(); _methsByName = new HashMap(); for(Iterator i = _methods.iterator(); i.hasNext(); ) { CodeMethod m = (CodeMethod) i.next(); Set mbn = (Set) _methsByName.get(m.getName()); if(mbn == null) { _methsByName.put(m.getName(), mbn = new HashSet()); } mbn.add(m); _methsByNameSig.put(makeNameSig(m), m); } } } private void popMeths(Class clazz, Map meths) { Method[] methods = clazz.getDeclaredMethods(); for(int i = 0; i < methods.length; i++) { Method m = methods[i]; ArrayList sigList = new ArrayList(); sigList.add(m.getName()); sigList.addAll(Arrays.asList(m.getParameterTypes())); if(!meths.containsKey(sigList)) { meths.put(sigList, new IntrospectedCodeMethod(m)); } } Class sup = clazz.getSuperclass(); if(sup != null) { popMeths(sup, meths); } } private void popIMeths(Class clazz, Map meths) { if(clazz.isInterface()) { Method[] methods = clazz.getDeclaredMethods(); for(int i = 0; i < methods.length; i++) { Method m = methods[i]; ArrayList sigList = new ArrayList(); sigList.add(m.getName()); sigList.addAll(Arrays.asList(m.getParameterTypes())); if(!meths.containsKey(sigList)) { meths.put(sigList, new IntrospectedCodeMethod(m)); } } Class[] interfaces = clazz.getInterfaces(); for(int i = 0; i < interfaces.length; i++) { popIMeths(interfaces[i], meths); } } Class sup = clazz.getSuperclass(); if(sup != null) { popIMeths(sup, meths); } } private List makeNameSig(CodeMethod m) { List res = new ArrayList(); res.add(m.getName()); for(int i = 0; i < m.numParameters(); i++) { res.add(m.getParameterType(i)); } return res; } public CodeField getFieldByName(String name) throws NoSuchFieldException { try { Field f = clazz.getField(name); return new CodeField(this, name, IntrospectedCodeClass.forClass(f.getType()), f.getModifiers()); } catch (NoSuchFieldException ex) { throw (NoSuchFieldException) new NoSuchFieldException( "Can't find field " + name + " in class " + getName() ).initCause(ex); } } private Set _fields; public Set getFields() { if(_fields == null) { _fields = new HashSet(); Field[] fields = clazz.getFields(); for(int fi = 0; fi < fields.length; fi++) { Field f = fields[fi]; _fields.add(new CodeField(this, f.getName(), IntrospectedCodeClass.forClass(f.getType()), f.getModifiers())); } _fields = Collections.unmodifiableSet(_fields); } return _fields; } public Set getMethodsByName(String name) { initMethods(); Set hits = (Set) _methsByName.get(name); if(hits == null) { return Collections.EMPTY_SET; } else { return hits; } } public CodeMethod getMethod(String name, CodeClass[] args) throws NoSuchMethodException { initMethods(); List nameSig = new ArrayList(); nameSig.add(name); for(int i = 0; i < args.length; i++) { nameSig.add(args[i]); } CodeMethod cm = (CodeMethod) _methsByNameSig.get(nameSig); if(cm == null) { throw new NoSuchMethodException( "Could not find method " + getName() + "." + name + "(" + CodeUtils.classListToString(args) + ")"); } return cm; } public CodeMethod getConstructor(CodeClass[] args) throws NoSuchMethodException { try { Class[] argsC = new Class[args.length]; for (int i = 0; i < args.length; i++) { argsC[i] = ((IntrospectedCodeClass) args[i]).clazz; } return new IntrospectedCodeConstructor(clazz.getConstructor(argsC)); } catch (NoSuchMethodException nsme) { throw (NoSuchMethodException) new NoSuchMethodException( "Could not find constructor new " + getName() + "(" + CodeUtils.classListToString(args) + ")" ).initCause(nsme); } } public boolean isPrimitive() { return clazz.isPrimitive(); } public boolean isArray() { return clazz.isArray(); } public String toString() { return this.getClass().getName() + ": " + clazz.getName(); } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/ShortInstruction.java0000755000175100017510000000234011130400365026757 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Instructions which take a one-byte operand. * * @author Thomas Down * @author Matthew Pocock */ class ShortInstruction implements Instruction { private final byte opcode; private final int val; private final int delta; ShortInstruction(byte opcode, int val, int delta) { this.opcode = opcode; this.val = val; this.delta = delta; } public void writeCode(CodeContext ctx) throws CodeException { ctx.writeByte(opcode); ctx.writeShort(val); } public int stackDepth() { return Math.max(delta, 0); } public int stackDelta() { return delta; } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/package.html0000644000175100017510000001517207702323032025045 0ustar moellermoeller A Java object-model for a Java Bytecode Macro-Assembler.

Description

The ByteCode package is able to generate Java Bytecode that can be used to define Java classes. It is not restricted to things that can be expressed as Java code (as in .java files), and is more flexible than basic Java bytecode.

This package supports generating classes, interfaces, methods, fields, and the like. It follows the macro-assembler pattern, where users can effectively extend the bytecode instruction set with their own instructions that at compile time expand to real bytecode instructions. Many useful pseudo-instructions are provided, such as IfExpression. This package also supports some advanced functionality such as templating. Templating supports both object and primitive types and types can be resolved at the level of complete methods or single expressions.

The ByteCode package has no support whatsoever for editing Java Bytecode. In particular, there is no support for search-and-replace or optimization.

The main classes for generating bytecode are {@link org.biojava.utils.bytecode.CodeUtils}, {@link org.biojava.utils.bytecode.ByteCode}, {@link org.biojava.utils.bytecode.InstructionVector} and {@link org.biojava.utils.bytecode.GeneratedCodeClass}. You will probably also use {@link org.biojava.utils.bytecode.GeneratedClassLoader}, as it does the actual work of building and loading classes.

It is probably a requirement of using this package effectively that you have memorised or have handy a copy of the Java VM specification. This is available from the Sun web site.

Class Reflection

The ByteCode package represents classes, methods and fields using its own APIs. These, for obvious reasons, closely resemble those provided by the core Java APIs. The three interfaces {@link org.biojava.utils.bytecode.CodeClass}, {@link org.biojava.utils.bytecode.CodeMethod} and {@link org.biojava.utils.bytecode.CodeField} represent these basic concepts.

Classes from the Java VM are reflected into this model using {@link org.biojava.utils.bytecode.IntrospectedCodeClass}. To get an instance, use the factory method {@link org.biojava.utils.bytecode.IntrospectedCodeClass#forClass(Class)} or {@link org.biojava.utils.bytecode.IntrospectedCodeClass#forClass(String)}.

Class Generation

Classes that you generate yourself will be represented by instances of {@link org.biojava.utils.bytecode.GeneratedCodeClass}. Methods are created by calling {@link org.biojava.utils.bytecode.GeneratedCodeClass#createMethod}, which will return a {@link org.biojava.utils.bytecode.GeneratedCodeMethod}. The method can then be implemented by associating a {@link org.biojava.utils.bytecode.CodeGenerator} with the method on that particular class using {@link org.biojava.utils.bytecode.GeneratedCodeClass#setCodeGenerator}.

Fields are generated by calling {@link org.biojava.utils.bytecode.GeneratedCodeClass#createField}.

The classes themselves are instantiated into the VM using {@link org.biojava.utils.bytecode.GeneratedClassLoader}. This implements {@link java.lang.ClassLoader#defineClass} and over-rides the other necessary book-keeping methods. You may wish to sub-class or wrap this class in an application to generate the desired behavior.

An example

We are going to implement HelloWorld in bytecode. Here is the (annotated) code.

Firstly, lets define our application structure...

public class BCHelloWorld {
  public static void main(String[] args)
  throws Throwable {
    createHelloWorld().run();
  }

  public static Runnable createHelloWorld() {
    ...
  }
}
We will fill in the createHelloWorld method to actualy do the work of printing out hello world by implementing a Runnable with a run() method. Firstly, we need a load of types, methods and a field or two.
CodeClass cl_Object = IntrospectedCodeClass.forClass(Object.class);
CodeClass cl_String = IntrospectedCodeClass.forClass(String.class);
CodeClass cl_System = IntrospectedCodeClass.forClass(System.class);
CodeClass cl_PrintStream = IntrospectedCodeClass.forClass(PrintStream.class);
CodeClass cl_Void = IntrospectedCodeClass.forClass(Void.TYPE);
CodeClass cl_Runnable = IntrospectedCodeClass.forClass(Runnable.class);

CodeField f_System_out = cl_System.getFieldByName("out");

CodeMethod m_PrintStream_printLn = cl_PrintStream.getMethod(
    "printLn",
    new CodeClass[] { cl_String } );
CodeMethod m_Object_init = cl_Object.getConstructor(CodeUtils.EMPTY_LIST);
Now we are ready to create our code class. It will be called HelloWorldRunnable, inherit directly from Object, implement Runnable, and be a public class.
GeneratedCodeClass ourClass = new GeneratedCodeClass(
    "HelloWorldRunnable",
    cl_Object,
    new CodeClass[] { cl_Runnable },
    CodeUtils.ACC_PUBLIC | CodeUtils.ACC_SUPER);
This will need a constructor. Remember, constructors have the name >init<:, and you must be sure to call the super-constructor explicitly. Normaly the javac compiler does this for you.
GeneratedCodeMethod init = ourClass.createMethod(
    "<init>",
    cl_Void,
    CodeUtils.EMPTY_LIST,
    CodeUtils.ACC_PUBLIC);
InstructionVector initIV = new InstructionVector();
initIV.add(ByteCode.make_aload(init.getThis()));
initIV.add(ByteCode.make_invokespecial(m_Object_init));
initIV.add(ByteCode.make_return());
ourClass.setCodeGenerator(init, initIV);
To be a Runnable implementation, we must also provide a run() method. This will take no arguments, return void and be publically accessible. Also, the body of this method will print out "Hello World" and then we can all feel pleased with ourselves.
GeneratedCodeMethod run = ourClass.createMethod(
    "run",
    cl_Void,
    CodeUtils.EMPTY_LIST,
    CodeUtils.ACC_PUBLIC);
InstructionVector runIV = new InstructionVector();
runIV.add(ByteCode.make_getstatic(f_System_out));
runIV.add(ByteCode.make_sconst("Hello World");
runIV.add(ByteCode.make_invokevirtual(m_PrintStream_printLn));
runIV.add(ByteCode.make_return());
ourClass.setCodeGenerator(run, runIV);
Now we want to load in a class with this deffinition and instantiate it.
GeneratedClassLoader gcl = new GeneratedClassLoader(class.getClassLoader());
Class newClass = gcl.defineClass(ourClass);
return (Runnable) newClass.newInstance();
And there you are. With any luck, if you type all of this in, and the fates smile on you, and biojava.jar is arround for linking against, you should have generated your very own unuque HelloWorld class.

Good luck.

bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/FieldInstruction.java0000755000175100017510000000242211130400365026704 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Instructions which act on fields. * * @author Thomas Down * @author Matthew Pocock */ class FieldInstruction implements Instruction { private final CodeField field; private final byte opcode; FieldInstruction(byte op, CodeField f) { if(f == null) { throw new NullPointerException("CodeField can not be null"); } this.opcode = op; this.field = f; } public void writeCode(CodeContext ctx) throws CodeException { ctx.writeByte(opcode); ctx.writeShort(ctx.getConstants().resolveField(field)); } public int stackDepth() { return stackDelta(); } public int stackDelta() { return 1; } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/IntrospectedCodeConstructor.java0000755000175100017510000000365211130400365031131 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; import java.lang.reflect.*; /** * Wrap up details about a constructor in a Java class file * * @author Matthew Pocock */ class IntrospectedCodeConstructor implements CodeMethod { private final Constructor _constructor; public IntrospectedCodeConstructor(Constructor m) { _constructor = m; } public String getName() { return ""; // all constructors are called } public String getFullName() { return _constructor.getDeclaringClass().getName() + "." + getName(); } public CodeClass getContainingClass() { return IntrospectedCodeClass.forClass(_constructor.getDeclaringClass()); } public String getDescriptor() { StringBuffer sb = new StringBuffer(); sb.append('('); for (int i = 0; i < numParameters(); ++i) { CodeClass cc = getParameterType(i); sb.append(cc.getDescriptor()); } sb.append(')'); sb.append(getReturnType().getDescriptor()); return sb.toString(); } public int getModifiers() { return _constructor.getModifiers(); } public CodeClass getReturnType() { return CodeUtils.TYPE_VOID; } public int numParameters() { return _constructor.getParameterTypes().length; } public CodeClass getParameterType(int pos) { return IntrospectedCodeClass.forClass(_constructor.getParameterTypes()[pos]); } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/CodeException.java0000755000175100017510000000154611130400365026156 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * An exception indicating that something went wrong generating byte code. */ public class CodeException extends Exception { public CodeException() { super(); } public CodeException(String msg) { super(msg); } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/InstructionVector.java0000755000175100017510000000573311130400365027133 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; import java.util.*; /** * A list of Instructions and/or other CodeGenerator objects. * * @author Thomas Down * @author Matthew Pocock */ public class InstructionVector implements CodeGenerator { private final List instructions; private final Label startLabel; private final Label endLabel; private StatsCache statsCache; // gets set to null on edits { instructions = new ArrayList(); startLabel = new Label(); endLabel = new Label(); statsCache = null; } public void add(CodeGenerator g) { statsCache = null; instructions.add(g); } public int size() { return instructions.size(); } public void add(int pos, CodeGenerator g) { statsCache = null; instructions.add(pos, g); } public void remove(int pos) { statsCache = null; instructions.remove(pos); } public CodeGenerator generatorAt(int pos) { return (CodeGenerator) instructions.get(pos); } public Label getStartLabel() { return startLabel; } public Label getEndLabel() { return endLabel; } public void writeCode(CodeContext ctx) throws CodeException { CodeContext subctx = ctx.subContext(); subctx.open(); subctx.markLabel(startLabel); for (Iterator i = instructions.iterator(); i.hasNext(); ) { CodeGenerator cg = (CodeGenerator) i.next(); cg.writeCode(subctx); } subctx.markLabel(endLabel); subctx.close(); // Wrap up the subcontt } public int stackDepth() { StatsCache statsCache = getStatsCache(); return statsCache.depth; } public int stackDelta() { StatsCache statsCache = getStatsCache(); return statsCache.delta; } private StatsCache getStatsCache() { if(statsCache == null) { int depth = 0; int delta = 0; for(Iterator i = instructions.iterator(); i.hasNext(); ) { CodeGenerator cg = (CodeGenerator) i.next(); int dp = cg.stackDepth(); int dl = cg.stackDelta(); dp += delta; delta += dl; depth = Math.max(depth, dp); } statsCache = new StatsCache(depth, delta); } return statsCache; } private static class StatsCache { public final int depth; public final int delta; public StatsCache(int depth, int delta) { this.depth = depth; this.delta = delta; } } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/ByteInstruction.java0000755000175100017510000000233711130400365026571 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Instructions which take a one-byte operand. * * @author Thomas Down * @author Matthew Pocock */ class ByteInstruction implements Instruction { private final byte opcode; private final byte val; private final int delta; ByteInstruction(byte opcode, byte val, int delta) { this.opcode = opcode; this.val = val; this.delta = delta; } public void writeCode(CodeContext ctx) throws CodeException { ctx.writeByte(opcode); ctx.writeByte(val); } public int stackDepth() { return Math.max(delta, 0); } public int stackDelta() { return delta; } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/Instruction.java0000755000175100017510000000140411130400365025737 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Base class for java bytecode instructions. * * @author Thomas Down */ public interface Instruction extends CodeGenerator { } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/IntConstantInstruction.java0000755000175100017510000000241411130400365030126 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Instructions which load int constants * * @author Thomas Down * @author Matthew Pocock */ class IntConstantInstruction implements Instruction { private final int i; IntConstantInstruction(int i) { this.i = i; } public void writeCode(CodeContext ctx) throws CodeException { int i_indx = ctx.getConstants().resolveInt(i); if (i_indx < 256) { ctx.writeByte(ByteCode.op_ldc); ctx.writeByte((byte) i_indx); } else { ctx.writeByte(ByteCode.op_ldc_w); ctx.writeShort(i_indx); } } public int stackDepth() { return stackDelta(); } public int stackDelta() { return 1; } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/ParametricCodeGenerator.java0000644000175100017510000000134211130400365030145 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; public interface ParametricCodeGenerator extends CodeGenerator { public ParametricType getType(); } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/ClassInstruction.java0000755000175100017510000000250111130400365026724 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Instructions which use a Class. * * @author Matthew Pocock */ class ClassInstruction implements Instruction { private final CodeClass clazz; private final byte opcode; private final int delta; ClassInstruction(byte op, CodeClass c, int delta) { if(c == null) { throw new NullPointerException("CodeClass can not be null"); } this.opcode = op; this.clazz = c; this.delta = delta; } public void writeCode(CodeContext ctx) throws CodeException { ctx.writeByte(opcode); ctx.writeShort(ctx.getConstants().resolveClass(clazz)); } public int stackDepth() { return Math.max(delta, 0); } public int stackDelta() { return delta; } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/PParametricCodeGenerator.java0000644000175100017510000000141011130400365030261 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; public interface PParametricCodeGenerator extends CodeGenerator { public ParametricType getType1(); public ParametricType getType2(); } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/FloatConstantInstruction.java0000755000175100017510000000244211130400365030442 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Instructions which load float constants * * @author Thomas Down * @author Matthew Pocock */ class FloatConstantInstruction implements Instruction { private final float val; FloatConstantInstruction(float val) { this.val = val; } public void writeCode(CodeContext ctx) throws CodeException { int i_indx = ctx.getConstants().resolveFloat(val); if (i_indx < 256) { ctx.writeByte(ByteCode.op_ldc); ctx.writeByte((byte) i_indx); } else { ctx.writeByte(ByteCode.op_ldc_w); ctx.writeShort(i_indx); } } public int stackDepth() { return stackDelta(); } public int stackDelta() { return 1; } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/NoOperandsInstruction.java0000755000175100017510000000225011130400365027730 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Instructions (like nop, dadd, etc.) which take no operands. * * @author Thomas Down * @author Matthew Pocock */ class NoOperandsInstruction implements Instruction { private final byte opcode; private final int delta; public NoOperandsInstruction(byte b, int delta) { this.opcode = b; this.delta = delta; } public void writeCode(CodeContext ctx) throws CodeException { ctx.writeByte(opcode); } public int stackDepth() { return Math.max(delta, 0); } public int stackDelta() { return delta; } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/CodeMethod.java0000755000175100017510000000355311130400365025440 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Wrap up details about a method in a Java class file * * @author Thomas Down * @author Matthew Pocock */ public interface CodeMethod { /** * The name of the method. * * @return the method name */ public String getName(); /** * The class that contains this method * * @return the containing class */ public CodeClass getContainingClass(); /** * The fully qualified name for this class * * @return the full name */ public String getFullName(); /** * A human-readable description of the class * * @return the class description */ public String getDescriptor(); /** * Get the modifiers, such as PUBLIC, ABSTRACT and so on * * @return the class modifiers */ public int getModifiers(); /** * Get the return type * * @return the return type */ public CodeClass getReturnType(); /** * Get the number of parameters taken by this method * * @return the number of parameters */ public int numParameters(); /** * Get the type of the parameter at a given position * * @param pos the position to fetch the parameter type for * @return the type of the parameter at that position */ public CodeClass getParameterType(int pos); } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/ParametricType.java0000644000175100017510000001157611130400365026357 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * A template type. * *

Template types are resolved at code-generation type rather than at * Instruction generation type. They let you bind the concrete type for opcodes * at the last minute, so the same max conditional could be used for all * primative types, with the type only being bound at the last moment.

* *

Two ParametricType instances are the same if they are the same object, * regardless of their names.

* * @author Matthew Pocock */ public class ParametricType { private static CodeClass[] OBJECT_CC; static { OBJECT_CC = new CodeClass[] { IntrospectedCodeClass.forClass(Object.class) }; } /** * Create a new ParametricType that claims nothing. * * @param name the name given to this type * @return a new ParametricType instance with that name */ public static ParametricType createType(String name) { return new ParametricType(name, false, false, false); } /** * Create a new ParametricType that claims to resolve to a primative type. * * @param name the name given to this type * @return a new ParametricType instance with that name */ public static ParametricType createPrimitiveType(String name) { return new ParametricType(name, true, false, false); } /** * Create a new ParametricType that claims to resolve to an object type. * * @param name the name given to this type * @return a new ParametricType instance with that name */ public static ParametricType createObjectType(String name) { return new ParametricType(name, false, true, false); } /** * Create a new ParametricType that claims to resolve to an array type. All * array types are object types. * * @param name the name given to this type * @return a new ParametricType instance with that name */ public static ParametricType createArrayType(String name) { return new ParametricType(name, false, true, true); } /** * Create a new ParametricType that claims to be castable to all the classes * in a list. Since neither Java nor bytecode support multiple inheritance, * the classes must either be interfaces, or classes that fall into an * inheritance path. * * @param name the name given to this type * @param classes an array of Class objects that any bound type must be * castable to * @return a new ParametricType that can bind to classes with these properties */ public static ParametricType createType( String name, CodeClass[] classes ) { return new ParametricType(name, classes); } private final String name; private final boolean isPrimitive; private final boolean isObject; private final boolean isArray; private final CodeClass[] classes; private ParametricType( String name, boolean isPrimitive, boolean isObject, boolean isArray ) { this.name = name; this.isPrimitive = isPrimitive; this.isObject = isObject; this.isArray = isArray; if(isObject) { this.classes = OBJECT_CC; } else { this.classes = CodeUtils.EMPTY_LIST; } } private ParametricType( String name, CodeClass[] classes ) { this.name = name; this.classes = classes; this.isObject = true; this.isPrimitive = false; this.isArray = false; } /** * Get the name of this type. * * Names are not unique. * * @return the name given to this type */ public String getName() { return name; } /** * Discover if this type must resolve to a primative. * *

It is an error for a parametric type to resolve to a non-primative if * this flag is set.

* * @return true if this is guaranteed to resolve to a primative */ public boolean isPrimitive() { return isPrimitive; } public boolean isObject() { return isObject; } public boolean isArray() { return isArray; } public boolean canAccept(CodeClass cc) { if(cc.isArray() && this.isArray()) { return true; } if(!cc.isPrimitive() && this.isObject()) { return true; } if(cc.isPrimitive() && this.isPrimitive()) { return true; } return false; } public CodeClass[] getClasses() { return classes; } public String toString() { return "GenericType:" + name; } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/GeneratedCodeClass.java0000755000175100017510000003412611130400365027104 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; import java.util.*; import java.io.*; /** * A CodeClass implementation that is used to generate new classes. * *

* When creating classes, instantiate one of these, add fields and methods. * Associate CodeGenerator instances with methods. Then, use * GeneratedClassLoader to make a new class. *

* * @author Matthew Pocock */ public class GeneratedCodeClass implements CodeClass { private String name; private CodeClass superClass; private List interfaces; private int modifiers; private Map methods; private Map fields; private String sourceFile; private boolean deprecated; { methods = new HashMap(); fields = new HashMap(); sourceFile = null; } public GeneratedCodeClass( String name, Class superClass, Class[] interfaces, int modifiers ) throws CodeException { this.name = name; this.modifiers = modifiers; this.superClass = IntrospectedCodeClass.forClass(superClass); this.interfaces = new ArrayList(Arrays.asList(interfaces)); for (Iterator i = this.interfaces.iterator(); i.hasNext();) { Class clazz = (Class) i.next(); if (!clazz.isInterface()) { throw new CodeException( "Attempted to create class implemneting non-interface " + clazz ); } } } public GeneratedCodeClass(String name, CodeClass superClass, CodeClass[] interfaces, int modifiers) throws CodeException { this.name = name; this.modifiers = modifiers; this.superClass = superClass; this.interfaces = new ArrayList(Arrays.asList(interfaces)); for (Iterator i = this.interfaces.iterator(); i.hasNext();) { Object obj = i.next(); if (!(obj instanceof CodeClass)) { throw new CodeException( "Interface list must contain CodeClass instances" ); } } } /** * Set the source file associated with this code class. * *

* The source file appears in debugging output and stack traces. Use this * method to set the source file that this generated class will clame to be * from. You can use non-file names e.g. uri:myGenerator:proxy/foo *

* *

* To un-set the source file, use null. *

* * @param sourceFile the source file for this class */ public void setSourceFile(String sourceFile) { this.sourceFile = sourceFile; } /** * Get the source file associated with this code class. * *

* Null indicates that no source file is set. *

* * @return the source file for this code class */ public String getSourceFile() { return sourceFile; } /** * Set the deprecation flag. * *

* If deprecated is true, the class will be flagged as deprecated. *

* * @param deprecated the new value of the deprecation */ public void setDeprecated(boolean deprecated) { this.deprecated = deprecated; } /** * Get the deprecation flag. * * @return wether or not this class is deprecated */ public boolean isDeprecated() { return deprecated; } public List getInterfaces() { return Collections.unmodifiableList(interfaces); } public Set getMethods() { return methods.keySet(); } public Set getMethodsByName(String name) { Set all = getMethods(); Set some = new HashSet(); for (Iterator i = all.iterator(); i.hasNext();) { CodeMethod m = (CodeMethod) i.next(); if (m.getName().equals(name)) { some.add(m); } } return some; } public CodeMethod getConstructor(CodeClass[] args) throws NoSuchMethodException { return getMethod("", args); } public CodeMethod getMethod(String name, CodeClass[] args) throws NoSuchMethodException { Set poss = getMethodsByName(name); METHOD_LOOP: for (Iterator i = poss.iterator(); i.hasNext();) { CodeMethod meth = (CodeMethod) i.next(); if (meth.numParameters() != args.length) { continue METHOD_LOOP; } for (int j = 0; j < args.length; j++) { if (!meth.getParameterType(j).equals(args[j])) { continue METHOD_LOOP; } } return meth; } StringBuffer methodSig = new StringBuffer( "Could not find method " + getName() + "." + name + "(" ); if (args.length > 0) { methodSig.append(args[0].getName()); } for (int i = 1; i < args.length; i++) { methodSig.append(","); methodSig.append(args[i].getName()); } methodSig.append(")"); throw new NoSuchMethodException(methodSig.toString()); } public Set getFields() { return fields.keySet(); } public CodeClass getSuperClass() { return superClass; } public CodeField getFieldByName(String name) throws NoSuchFieldException { CodeField f = (CodeField) fields.get(name); if (f == null) { throw new NoSuchFieldException("No field for " + name + " in class " + getName()); } return f; } public String getName() { return name; } public String getJName() { String name = getName(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < name.length(); ++i) { char c = name.charAt(i); if (c == '.') sb.append('/'); else sb.append(c); } return sb.toString(); } public int getModifiers() { return modifiers; } public String getDescriptor() { String name = getName(); StringBuffer sb = new StringBuffer(); sb.append('L'); for (int i = 0; i < name.length(); ++i) { char c = name.charAt(i); if (c == '.') sb.append('/'); else sb.append(c); } sb.append(';'); return sb.toString(); } /** * Create a new method. * *

* This defines the shape of a method that will be generated. Use * {@link #setCodeGenerator} to associate code with the method. *

* *

* The argNames will become the names of local variables for each argument. *

* * @param name the method name * @param type the return type * @param args arguments taken * @param argNames names of the arguments * @param mods access modifiers * @return a new GeneratedCodeMethod * @throws CodeException if the method could not be created */ public GeneratedCodeMethod createMethod( String name, CodeClass type, CodeClass[] args, String[] argNames, int mods ) throws CodeException { GeneratedCodeMethod cm = new GeneratedCodeMethod(this, name, type, args, argNames, mods); if (methods.containsKey(cm)) { throw new CodeException("Attempt to create multiple methods with same signatures."); } methods.put(cm, null); return cm; } /** * Create a new method. * *

* This defines the shape of a method that will be generated. Use * {@link #setCodeGenerator} to associate code with the method. *

* * @param name the method name * @param type the return type * @param args arguments taken * @param mods access modifiers * @return a new GeneratedCodeMethod * @throws CodeException if the method could not be created */ public GeneratedCodeMethod createMethod( String name, CodeClass type, CodeClass[] args, int mods ) throws CodeException { return createMethod(name, type, args, new String[0], mods); } public CodeField createField(String name, CodeClass clazz, int mods) throws CodeException { if (fields.containsKey(name)) { throw new CodeException("Attempt to create multiple fields named " + name); } CodeField cf = new CodeField(this, name, clazz, mods); fields.put(name, cf); return cf; } public void setCodeGenerator(CodeMethod method, CodeGenerator cg) throws CodeException { if (!methods.containsKey(method)) { throw new CodeException("Class doesn't provide method " + method.getName()); } methods.put(method, cg); } public void createCode(OutputStream os) throws IOException, CodeException { DataOutputStream dos = new DataOutputStream(os); // Write classfile header dos.writeInt((int) (0xcafebabe)); // Magic dos.writeShort(3); // Minor version dos.writeShort(45); // Major version (check!) ConstantPool cp = new ConstantPool(); // The rest of the classfile gets written to a buffer, accumulating a constant pool along the way ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream bdos = new DataOutputStream(baos); bdos.writeShort(modifiers); bdos.writeShort(cp.resolveClass(this)); // this-class ID bdos.writeShort(cp.resolveClass(superClass)); // super-class ID bdos.writeShort(interfaces.size()); // number_of_interfaces for (Iterator i = interfaces.iterator(); i.hasNext();) { bdos.writeShort(cp.resolveClass((CodeClass) i.next())); // interface ID } // Write the fields bdos.writeShort(fields.size()); for (Iterator i = fields.values().iterator(); i.hasNext();) { CodeField cf = (CodeField) i.next(); bdos.writeShort(cf.getModifiers()); bdos.writeShort(cp.resolveUtf8(cf.getName())); bdos.writeShort(cp.resolveUtf8(cf.getType().getDescriptor())); bdos.writeShort(0); // No attributes right now } // Write the methods (wahey!) Set methSet = methods.entrySet(); bdos.writeShort(methSet.size()); for (Iterator i = methSet.iterator(); i.hasNext();) { Map.Entry me = (Map.Entry) i.next(); GeneratedCodeMethod cm = (GeneratedCodeMethod) me.getKey(); CodeGenerator cg = (CodeGenerator) me.getValue(); bdos.writeShort(cm.getModifiers()); // access_flags bdos.writeShort(cp.resolveUtf8(cm.getName())); // name_index bdos.writeShort(cp.resolveUtf8(cm.getDescriptor())); // descriptor_index // Actually generate the code MethodRootContext ctx = new MethodRootContext(this, cm, cp); ctx.open(); LocalVariable thisP = cm.getThis(); if (thisP != null) { // Non-static method ctx.resolveLocal(thisP); } for (int parm = 0; parm < cm.numParameters(); ++parm) { ctx.resolveLocal(cm.getVariable(parm)); } cg.writeCode(ctx); ctx.close(); Set thrownExceptions = cm.getThrownExceptions(); // number of method attirbutes int numMethAttrs = 1; // we always have code // do we have exceptions? if(!thrownExceptions.isEmpty()) { numMethAttrs++; } bdos.writeShort(numMethAttrs); // attributes_count // start attribute_info for method // Code attribute List exceptionTable = ctx.getExceptionTable(); bdos.writeShort(cp.resolveUtf8("Code")); bdos.writeInt(12 + ctx.getOffset() + exceptionTable.size() * 8); bdos.writeShort(cg.stackDepth()); bdos.writeShort(ctx.getMaxLocals()); bdos.writeInt(ctx.getOffset()); ctx.writeTo(bdos); bdos.writeShort(exceptionTable.size()); for (Iterator ei = exceptionTable.iterator(); ei.hasNext();) { ExceptionMemento em = (ExceptionMemento) ei.next(); if (!(em.isFullyResolved())) throw new CodeException("Exception table entry refers to unresolved label"); bdos.writeShort(em.startHandled.getOffset()); bdos.writeShort(em.endHandled.getOffset()); bdos.writeShort(em.handler.getOffset()); if (em.eClass != null) bdos.writeShort(cp.resolveClass(em.eClass)); else bdos.writeShort(0); // For `finally' } bdos.writeShort(0); // Code has no sub-attributes // Exceptions attribute if (thrownExceptions.size() > 0) { bdos.writeShort(cp.resolveUtf8("Exceptions")); // attribute_name_index bdos.writeInt(2 + thrownExceptions.size() * 2); // attribute_length bdos.writeShort(thrownExceptions.size()); // number_of_exceptions for (Iterator tei = thrownExceptions.iterator(); tei.hasNext();) { CodeClass exClass = (CodeClass) tei.next(); bdos.writeShort(cp.resolveClass(exClass)); // exception class } } } // class-wide attributes // // currently, these are SourceFile and Deprecated only int classAttributes = 0; if(sourceFile != null) { classAttributes++; } if(deprecated) { classAttributes++; } bdos.writeShort(classAttributes); // attributes_count // write the source file attribute if(sourceFile != null) { bdos.writeShort(cp.resolveUtf8("SourceFile")); // attribute_name_index bdos.writeInt(2); // attribute_length bdos.writeShort(cp.resolveUtf8(sourceFile)); // sourcefile_index } // write the deprecate attribute if(isDeprecated()) { bdos.writeShort(cp.resolveUtf8("Deprecated")); // attribute_name_index bdos.writeInt(0); // attribute_length } // All constants will now have been resolved, so we can finally write the cpool dos.writeShort(cp.constantPoolSize()); cp.writeConstantPool(dos); // Append the rest of the classfile to the stream baos.writeTo(dos); } public boolean isPrimitive() { return false; } public boolean isArray() { return false; } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/CodeContext.java0000755000175100017510000001510311130400365025636 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Interface which encapsulates the stream to which Java bytecode can * be written. * *

* The context takes care of all the book-keeping tasks associated with emitting * well-formed byte code. For example, the context manages jumps and local * variables. *

* *

* Most of the funcionality here is very low level. You will almost certainly * want to use CodeGenerator instances to manipulate a CodeContext, rather than * writing to it yourself. *

* * @author Thomas Down * @author Matthew Pocock */ public interface CodeContext { /** * Get the class for which a method is being generated. * * @return the current class */ public CodeClass getCodeClass(); /** * Get the method which is being generated. * * @return the current method */ public CodeMethod getCodeMethod(); /** * Get the constants pool for this context. * * @return the contant pool */ public ConstantPool getConstants(); // Write methods. /** * Write a single byte to the context. * *

* This can be used both to write opcodes and to write byte data to the * context. *

* * @param b the byte to write */ public void writeByte(byte b) throws CodeException; /** * Write a short (2 bytes) to the context. * * @param i the short to write */ public void writeShort(int i) throws CodeException; /** * Write the offset of a Label to the context. * *

This can be called before or after markLabel is invoked for the * corresponding label. The context will ensure that the offset is * correctly written before the method is fully emitted.

* * @param lab the Label to write */ public void writeLabel(Label lab) throws CodeException; /** * Resolve a local variable to the local variable slot assigned to it. * *

The context will ensure that local variables are stored in their * own bits of the local variable area. It may chose to re-use portions * of this area as local variables go out of scope.

* * @param lv the LocalVariable to resolve * @return the index of the local variable slot */ public int resolveLocal(LocalVariable lv) throws CodeException; /** * Mark a label at the current point in the stream. * *

This can be used as the target for branching instructions, such as * GOTO and IF.

* * @param lab the Label to mark * @throws CodeException if the label has previously been marked */ public void markLabel(Label lab) throws CodeException; /** * Register a concrete type for a parametric type. * *

This is the mechanism where-by real CodeClass types are associated * with the virtual ParametricType types. If type pubishes that it * is a primative, an object or an array, then the concreteType must be * compattible. It's an error to bind the VOID type.

* * @for.developer * You should probably call * ParametricType.canAccept(concreteType) to make sure of this. * This implementation will shield you from any modifications to the exact * semantics of ParametricType. * * @param type ParametricType the parametric type to register * @param concreteType the CodeClass that it resolves to * @throws CodeException if the type has already been registered or if the * guarantees about type made in the parametric type are violated */ public void registerParametricType(ParametricType type, CodeClass concreteType) throws CodeException; /** * Resolve a parametric type to a concrete class. * *

The type will be resolved by first searching through all those * registered with this context. If it found there, this value is returned. * If it is not, then the emediate parent context is searched. This parent * is responsible for searching its parent and so on. If a context has no * parent and the type is not registered with this context, it should raise * a CodeException.

* * @param type the ParametricType to resolve * @return the ColdeClass associated with that parametric type * @throws CodeException if the type has not been registered */ public CodeClass resolveParametricType(ParametricType type) throws CodeException; /** * Open a sub context. * *

The sub context should inherit all the state of the parent context. * Modifications to the state of the child (for example, local variable * management or registered labels) should not be propogated to the parent. * Modifications to the parent should not be propogated to the child. * However, contexts should be used serialy, and only one context should be * accessible to a code generator at a time, so in practice, there should be * no way for a code generator using a child context to alter the state of * or discover the state of the parent context.

*/ public CodeContext subContext(); /** * Open the context for writing. * *

This must be called before any code writing methods are called. It * can not be called more than once.

*/ public void open() throws CodeException; /** * Close the context for writing. It is at this point that any process * necisary for comitting the bytecode will be executed. * *

This must be called after all code writing methods have been called. * It can not be called more than once.

*/ public void close() throws CodeException; // Exception tables /** * Add an exception table entry. * * @param startHandled the beginning of the try block * @param endHandled the end of the try block * @param eClass the exception class * @param handler the beginning of the exception handler * @throws CodeException */ public void addExceptionTableEntry(Label startHandled, Label endHandled, CodeClass eClass, Label handler) throws CodeException; } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/GeneratedCodeMethod.java0000755000175100017510000001114211130400365027250 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; import java.util.*; /** * A method that will be generated. * *

* These are instantiated by factory methods on {@link GeneratedCodeClass}, and * can not be instantiated directly. *

* * @author Thomas Down * @author Matthew Pocock */ public final class GeneratedCodeMethod implements CodeMethod { private final String name; private List args; private List localvars; private LocalVariable thisV; private int modifiers; private CodeClass type; private CodeClass container; private Set thrownExceptions; private Map nameToLocals; GeneratedCodeMethod( CodeClass container, String name, CodeClass type, CodeClass[] args, String[] names, int modifiers ) { this.container = container; this.name = name; this.args = new ArrayList(Arrays.asList(args)); this.modifiers = modifiers; this.type = type; nameToLocals = new HashMap(); localvars = new ArrayList(); for(int i = 0; i < this.args.size(); ++i) { if(i < names.length) { LocalVariable arg = new LocalVariable(args[i], names[i]); localvars.add(arg); nameToLocals.put(names[i], arg); } else { localvars.add(new LocalVariable(args[i])); } } if((modifiers & CodeUtils.ACC_STATIC) == 0) { thisV = new LocalVariable(container, "this"); nameToLocals.put("this", thisV); } } public String getName() { return name; } public String getFullName() { return container.getName() + "." + name; } public CodeClass getContainingClass() { return container; } public String getDescriptor() { StringBuffer sb = new StringBuffer(); sb.append('('); for(Iterator i = args.iterator(); i.hasNext(); ) { CodeClass cc = (CodeClass) i.next(); sb.append(cc.getDescriptor()); } sb.append(')'); sb.append(type.getDescriptor()); return sb.toString(); } public int getModifiers() { return modifiers; } public CodeClass getReturnType() { return type; } public int numParameters() { return args.size(); } public CodeClass getParameterType(int pos) { return (CodeClass) args.get(pos); } /** * Gets the Variable attribute of the GeneratedCodeMethod object. * *

* There is one local variable for each of the arguments of the method, * indexed from 0. *

* * @param pos the index of the local variable * @return the local variable */ public LocalVariable getVariable(int pos) { return (LocalVariable) localvars.get(pos); } /** * Gets the Variable attribute of the GenerateCodeMethod object by name. * *

* All methods have a variable under the string "this". If it was constructed * with a String [] naming the args, the locals for each local can be * retrieved by name. *

* * @param argName a String naming the local * @return the LocalVariable for that argName * @throws NoSuchElementException if there is no local with that name */ public LocalVariable getVariable(String argName) throws NoSuchElementException { LocalVariable lv = (LocalVariable) nameToLocals.get(argName); if(lv == null) { throw new NoSuchElementException( "Can't find local for argName " + argName ); } return lv; } /** * Gets the This attribute of the GeneratedCodeMethod object * * @return The This value */ public LocalVariable getThis() { return thisV; } /** * Gets the ThrownExceptions attribute of the GeneratedCodeMethod object * * @return The ThrownExceptions value */ public Set getThrownExceptions() { return Collections.unmodifiableSet(thrownExceptions); } /** * Adds a feature to the ThrownException attribute of the GeneratedCodeMethod object * * @param cc The feature to be added to the ThrownException attribute */ public void addThrownException(CodeClass cc) { thrownExceptions.add(cc); } { thrownExceptions = new HashSet(); } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/LabelInstruction.java0000755000175100017510000000242711130400365026705 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Instructions which jump to a label. * * @author Thomas Down * @author Matthew Pocock */ class LabelInstruction implements Instruction { private final Label l; private final byte opcode; private final int delta; LabelInstruction(byte op, Label l, int delta) { if(l == null) { throw new NullPointerException("Label can not be null"); } this.opcode = op; this.l = l; this.delta = delta; } public void writeCode(CodeContext ctx) throws CodeException { ctx.writeByte(opcode); ctx.writeLabel(l); } public int stackDepth() { return 0; } public int stackDelta() { return delta; } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/MethodInstruction.java0000755000175100017510000000361311130400365027104 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Instructions which call a method. * * @author Thomas Down * @author Matthew Pocock */ class MethodInstruction implements Instruction { private final CodeMethod meth; private final byte opcode; MethodInstruction(byte op, CodeMethod m) { if(m == null) { throw new NullPointerException("CodeMethod can not be null"); } this.opcode = op; this.meth = m; } public void writeCode(CodeContext ctx) throws CodeException { ctx.writeByte(opcode); if (opcode == ByteCode.op_invokeinterface) { ctx.writeShort(ctx.getConstants().resolveInterfaceMethod(meth)); int count = 1; for (int i = 0; i < meth.numParameters(); ++i) { CodeClass ptype = meth.getParameterType(i); count += CodeUtils.wordsForType(ptype); } ctx.writeByte((byte) count); ctx.writeByte((byte) 0); } else { ctx.writeShort(ctx.getConstants().resolveMethod(meth)); } } public int stackDepth() { return 0; } public int stackDelta() { int popped = 0; if( (meth.getModifiers() & CodeUtils.ACC_STATIC) == 0) { popped++; } popped += meth.numParameters(); int pushed = (meth.getReturnType() == CodeUtils.TYPE_VOID) ? 0 : 1; return pushed - popped; } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/ChildContext.java0000755000175100017510000001334511130400365026015 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; import java.util.*; /** * CodeContext implementation which provides a lightweight subContext of any * ParentContext. * * @author Thomas Down * @author Matthew Pocock */ class ChildContext implements CodeContext, ParentContext { ParentContext ourParent; private List outstandingRefs; private Map markedLabels; private Map localVariables; private int usedLocals; private Map resolvedParametrics; { outstandingRefs = new ArrayList(); markedLabels = new HashMap(); localVariables = new HashMap(); resolvedParametrics = new HashMap(); } ChildContext(ParentContext p) { this.ourParent = p; usedLocals = ourParent.getUsedLocals(); } public CodeClass getCodeClass() { return ourParent.getCodeClass(); } public CodeMethod getCodeMethod() { return ourParent.getCodeMethod(); } public ConstantPool getConstants() { return ourParent.getConstants(); } public void writeByte(byte b) throws CodeException { ourParent.writeByte(b); } public void writeShort(int i) throws CodeException { ourParent.writeShort(i); } public void writeShortAt(int pos, int i) { ourParent.writeShortAt(pos, i); } public void markLabel(Label l) throws CodeException { if (markedLabels.containsKey(l)) throw new CodeException("Attempt to duplicate marked label"); markedLabels.put(l, new Integer(getOffset())); } public void promoteOutstandingReference(OutstandingReference or) { outstandingRefs.add(or); } public void writeLabel(Label l) throws CodeException { outstandingRefs.add(new BranchFixup(l, getOffset(), this)); writeShort(0); } public int getOffset() { return ourParent.getOffset(); } public void open() { } public void close() throws CodeException { for (ListIterator li = outstandingRefs.listIterator(); li.hasNext(); ) { OutstandingReference or = (OutstandingReference) li.next(); Integer off = (Integer) markedLabels.get(or.getLabel()); if (off != null) { or.resolve(off.intValue()); } else { ourParent.promoteOutstandingReference(or); // See if parent can resolve this. } } } public CodeContext subContext() { return new ChildContext(this); } public int resolveLocal(LocalVariable lv) { // System.out.println("ChildContext.resolveLocal(" + lv + ")"); Integer slot = (Integer) localVariables.get(lv); if (slot != null) { // System.out.println("resolved to " + slot); return slot.intValue(); } // System.out.println("Trying to resolve slot in parent " + ourParent); int locSlot = ourParent.resolveLocalNoCreate(lv); if (locSlot >= 0) { // System.out.println("Parent had local " + lv + " at " + locSlot); } else { // Need to create the variable; locSlot = usedLocals; usedLocals += lv.needSlots(); setMaxLocals(usedLocals); // System.out.println("Generated new slot for local " + lv + " at " + locSlot); } // We'll add the slot to our map, even if it's just a copy from the parent. localVariables.put(lv, new Integer(locSlot)); // System.out.println("ChildContext: Resolved local variable " + lv + " to slot " + locSlot); return locSlot; } public int resolveLocalNoCreate(LocalVariable lv) { Integer slot = (Integer) localVariables.get(lv); if (slot != null) { return slot.intValue(); } else { return ourParent.resolveLocalNoCreate(lv); } } public void registerParametricType( ParametricType type, CodeClass concreteType ) throws CodeException { if(resolvedParametrics.containsKey(type)) { throw new CodeException("Failed to regiter parametric type " + type + ". Attempted to register for " + concreteType + " but it is already registered for " + resolvedParametrics.get(type) ); } if(!type.canAccept(concreteType)) { throw new CodeException( "Parametric type is not compattible with concrete type: " + type + " : " + concreteType ); } resolvedParametrics.put(type, concreteType); } public CodeClass resolveParametricType(ParametricType type) throws CodeException { CodeClass cc = (CodeClass) resolvedParametrics.get(type); if(cc == null) { return ourParent.resolveParametricType(type); } return cc; } public int getUsedLocals() { return usedLocals; } public void setMaxLocals(int m) { ourParent.setMaxLocals(m); } public void addExceptionTableEntry(Label startHandled, Label endHandled, CodeClass eClass, Label handler) { SimpleReference rStartHandled = new SimpleReference(startHandled); SimpleReference rEndHandled = new SimpleReference(endHandled); SimpleReference rHandler = new SimpleReference(handler); outstandingRefs.add(rStartHandled); outstandingRefs.add(rEndHandled); outstandingRefs.add(rHandler); addExceptionTableEntry(new ExceptionMemento(rStartHandled, rEndHandled, eClass, rHandler)); } public void addExceptionTableEntry(ExceptionMemento em) { ourParent.addExceptionTableEntry(em); } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/MethodRootContext.java0000755000175100017510000001374111130400365027056 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; import java.util.*; import java.io.*; /** * @author Thomas Down * @author Matthew Pocock */ class MethodRootContext implements CodeContext, ParentContext { private final CodeClass codeClass; private final CodeMethod codeMethod; private final ConstantPool cpool; private byte[] sink; private int offset; private List outstandingRefs; private Map markedLabels; private Map localVariables; private int usedLocals; private int maxLocals; private Map resolvedParametrics; private List exceptionTable; { outstandingRefs = new ArrayList(); markedLabels = new HashMap(); localVariables = new HashMap(); exceptionTable = new ArrayList(); resolvedParametrics = new HashMap(); } MethodRootContext(CodeClass cc, CodeMethod cm, ConstantPool cp) { this.codeClass = cc; this.codeMethod = cm; this.cpool = cp; sink = new byte[65536]; offset = 0; // Should allocate local variables from method; usedLocals = maxLocals = 0; } public CodeClass getCodeClass() { return codeClass; } public CodeMethod getCodeMethod() { return codeMethod; } public ConstantPool getConstants() { return cpool; } public void writeByte(byte b) { sink[offset++] = b; } public void writeShort(int i) { sink[offset++] = (byte) ((i>>8) & 0xff); sink[offset++] = (byte) ((i) & 0xff); } public void writeShortAt(int pos, int i) { sink[pos] = (byte) ((i>>8) & 0xff); sink[pos+1] = (byte) ((i) & 0xff); } public void writeLabel(Label l) { outstandingRefs.add(new BranchFixup(l, getOffset(), this)); writeShort(0); } public void markLabel(Label l) throws CodeException { if (markedLabels.containsKey(l)) throw new CodeException("Attempt to duplicate marked label"); markedLabels.put(l, new Integer(getOffset())); } public int resolveLocal(LocalVariable lv) { // System.out.println("MethodRootContext.resolveLocal(" + lv + ")"); Integer slot = (Integer) localVariables.get(lv); if (slot != null) { // System.out.println("resolved to " + slot); return slot.intValue(); } int newLocal = usedLocals; usedLocals += lv.needSlots(); setMaxLocals(usedLocals); localVariables.put(lv, new Integer(newLocal)); // System.out.println("created at" + newLocal); return newLocal; } public int resolveLocalNoCreate(LocalVariable lv) { // System.out.println("MethodRootContext.resolveLocalNoCreate(" + lv + ")"); Integer slot = (Integer) localVariables.get(lv); if (slot != null) { // System.out.println("at " + slot); return slot.intValue(); } else { // System.out.println("not here"); return -1; } } public void registerParametricType( ParametricType type, CodeClass concreteType ) throws CodeException { if(resolvedParametrics.containsKey(type)) { throw new CodeException("Failed to regiter parametric type " + type + ". Attempted to register for " + concreteType + " but it is already registered for " + resolvedParametrics.get(type) ); } if(!type.canAccept(concreteType)) { throw new CodeException( "Parametric type is not compattible with concrete type: " + type + " : " + concreteType ); } resolvedParametrics.put(type, concreteType); } public CodeClass resolveParametricType(ParametricType type) throws CodeException { CodeClass cc = (CodeClass) resolvedParametrics.get(type); if(cc == null) { throw new CodeException("Can not resolve type: " + type); } return cc; } public int getOffset() { return offset; } public void open() { } public void close() throws CodeException { for (ListIterator li = outstandingRefs.listIterator(); li.hasNext(); ) { OutstandingReference or = (OutstandingReference) li.next(); Integer off = (Integer) markedLabels.get(or.getLabel()); if (off != null) { or.resolve(off.intValue()); } else { throw new CodeException("Reference to label " + or.getLabel() + " still outstanding at top level"); } } } public CodeContext subContext() { return new ChildContext(this); } public void promoteOutstandingReference(OutstandingReference or) { outstandingRefs.add(or); } public void writeTo(OutputStream os) throws IOException { os.write(sink, 0, offset); } public void setMaxLocals(int newMax) { if (newMax > maxLocals) maxLocals = newMax; } public int getMaxLocals() { return maxLocals; } public int getUsedLocals() { return usedLocals; } public void addExceptionTableEntry( Label startHandled, Label endHandled, CodeClass eClass, Label handler ) { SimpleReference rStartHandled = new SimpleReference(startHandled); SimpleReference rEndHandled = new SimpleReference(endHandled); SimpleReference rHandler = new SimpleReference(handler); outstandingRefs.add(rStartHandled); outstandingRefs.add(rEndHandled); outstandingRefs.add(rHandler); addExceptionTableEntry(new ExceptionMemento(rStartHandled, rEndHandled, eClass, rHandler)); } public void addExceptionTableEntry(ExceptionMemento em) { exceptionTable.add(em); } public List getExceptionTable() { return Collections.unmodifiableList(exceptionTable); } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/MarkLabel.java0000644000175100017510000000212411130400365025245 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; import java.util.*; /** * A CodeGenerator that just marks a label that can be used for jumps. * * @author Matthew Pocock */ public class MarkLabel implements CodeGenerator { private final Label label; public MarkLabel(Label label) { this.label = label; } public void writeCode(CodeContext ctx) throws CodeException { ctx.markLabel(label); } public int stackDepth() { return 0; } public int stackDelta() { return 0; } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/CodeUtils.java0000755000175100017510000001241711130400365025317 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Utility code for things you will frequently need. * *

* This class provides common constants representing access modifiers and * types. There are also some utility methods for munging data. *

* * @author Thomas Down * @author Matthew Pocock */ public class CodeUtils { public static final int ACC_PUBLIC = 0x0001; public static final int ACC_PRIVATE = 0x0002; public static final int ACC_PROTECTED = 0x0004; public static final int ACC_STATIC = 0x0008; public static final int ACC_FINAL = 0x0010; public static final int ACC_SUPER = 0x0020; public static final int ACC_SYNCHRONIZED = 0x0020; public static final int ACC_VOLATILE = 0x0040; public static final int ACC_TRANSIENT = 0x0080; public static final int ACC_NATIVE = 0x0100; public static final int ACC_INTERFACE = 0x0200; public static final int ACC_ABSTRACT = 0x0400; public static final int ACC_STRICT = 0x0800; public static final CodeClass TYPE_VOID; public static final CodeClass TYPE_INT; public static final CodeClass TYPE_FLOAT; public static final CodeClass TYPE_DOUBLE; public static final CodeClass TYPE_LONG; public static final CodeClass TYPE_BYTE; public static final CodeClass TYPE_SHORT; public static final CodeClass TYPE_CHAR; public static final CodeClass TYPE_BOOLEAN; public static final CodeClass TYPE_OBJECT; public static final CodeClass[] EMPTY_LIST; public static final CodeGenerator DO_NOTHING; static { TYPE_VOID = IntrospectedCodeClass.forClass(Void.TYPE); TYPE_BYTE = IntrospectedCodeClass.forClass(Byte.TYPE); TYPE_INT = IntrospectedCodeClass.forClass(Integer.TYPE); TYPE_FLOAT = IntrospectedCodeClass.forClass(Float.TYPE); TYPE_DOUBLE = IntrospectedCodeClass.forClass(Double.TYPE); TYPE_LONG = IntrospectedCodeClass.forClass(Long.TYPE); TYPE_SHORT = IntrospectedCodeClass.forClass(Short.TYPE); TYPE_CHAR = IntrospectedCodeClass.forClass(Character.TYPE); TYPE_BOOLEAN = IntrospectedCodeClass.forClass(Boolean.TYPE); TYPE_OBJECT = IntrospectedCodeClass.forClass(Object.class); EMPTY_LIST = new CodeClass[0]; DO_NOTHING = new CodeGenerator() { public void writeCode(CodeContext cxt) { return; } public int stackDepth() { return 0; } public int stackDelta() { return 0; } }; } /** * Format an array of classes as a comma-seperated list. * *

* The names of each class in classes will be seperated by a comma and a space * and will use CodeClass.getName() to produce strings for each one. Their * names will be present in the return value in the same order they are found * in the classes array *

* * @param classes the array of classes to format * @return a String containing the list of class names */ public static String classListToString(CodeClass[] classes) { StringBuffer sb = new StringBuffer(); if(classes.length > 0) { sb.append(classes[0].getName()); } for(int a = 1; a < classes.length; a++) { sb.append(", "); sb.append(classes[a].getName()); } return sb.toString(); } /** * Number of words needed for local variables of this type. * *

Longs and doubles require 2 words (64 bits), where as everything * else needs 1 word (32 bits). Void needs no words. * This just hides that knowledge.

* * @param cc the CodeClass to check word size for * @return number of words needed for this type */ public static int wordsForType(CodeClass cc) { if( (cc == TYPE_DOUBLE) || (cc == TYPE_LONG) ) { return 2; } else if(cc == TYPE_VOID) { return 0; } else { return 1; } } /** * Returns true if the class is a floating point number. * *

* Double and Float are floating point numbers. All other classes are not. *

* * @param cc the class to check * @return true if the class can be used to represent floating point numbers */ public static boolean isFloatType(CodeClass cc) { return cc == TYPE_DOUBLE || cc == TYPE_FLOAT; } /** * Returns true if the class is an integer number. * *

* All numeric types are integer (whole number) types, except for the floating * point types. All other classes are not integer types. *

* * @param cc the class to check * @return true if the class can be used to represent integer numbers */ public static boolean isIntegerType(CodeClass cc) { return cc == TYPE_LONG || cc == TYPE_BOOLEAN || cc == TYPE_BYTE || cc == TYPE_CHAR || cc == TYPE_LONG || cc == TYPE_SHORT; } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/ByteCode.java0000755000175100017510000021670211130400365025125 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Factory for objects which encapsulate individual Java bytecode instructions. * Most methods in this class are auto-generated. * *

There are two classes of methods. The first ones are for creating objects * that directly represent opcodes. These effectively wrap one of the opcode * constants. The others do something more clever. For example, make_if emits * something that is equivalent to a normal Java if statement.

* *

Generic types are supported using the factory methods that take * ParametricType arguments. * * @author Thomas Down * @author Matthew Pocock */ public class ByteCode { // // iconst and friends // public static Instruction make_iconst(int i) { if (i >= -1 && i <= 5) { return new NoOperandsInstruction((byte) (op_iconst_0 + i), 1); } else if (i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE) { return new ByteInstruction(op_bipush, (byte) i, 1); } else if (i >= Short.MIN_VALUE && i <= Short.MAX_VALUE) { return new ShortInstruction(op_sipush, i, 1); } return new IntConstantInstruction(i); } // // String constants // public static Instruction make_sconst(String s) { return new StringConstantInstruction(s); } // // Double constants // public static Instruction make_dconst(double d) { if (d == 0.0) { return new NoOperandsInstruction(op_dconst_0, 1); } else if (d == 1.0) { return new NoOperandsInstruction(op_dconst_1, 1); } else { return new DoubleInstruction(d); } } // // Long constants // public static Instruction make_lconst(long l) { if (l == 0L) { return new NoOperandsInstruction(op_lconst_0, 1); } else if (l == 1L) { return new NoOperandsInstruction(op_lconst_1, 1); } else { return new LongConstantInstruction(l); } } // // Float constants // public static Instruction make_fconst(float f) { if (f == 0.0F) { return new NoOperandsInstruction(op_fconst_0, 1); } else if (f == 1.0F) { return new NoOperandsInstruction(op_fconst_1, 1); } else if (f == 2.0F) { return new NoOperandsInstruction(op_fconst_2, 1); } else { return new FloatConstantInstruction(f); } } // // Generate instruction objects for invokes // public static Instruction make_invokevirtual(CodeMethod cm) { return new MethodInstruction(op_invokevirtual, cm); } public static Instruction make_invokespecial(CodeMethod cm) { return new MethodInstruction(op_invokespecial, cm); } public static Instruction make_invokestatic(CodeMethod cm) { return new MethodInstruction(op_invokestatic, cm); } public static Instruction make_invokeinterface(CodeMethod cm) { return new MethodInstruction(op_invokeinterface, cm); } // // Generate instruction objects for fields // public static Instruction make_getfield(CodeField cf) { return new FieldInstruction(op_getfield, cf); } public static Instruction make_putfield(CodeField cf) { return new FieldInstruction(op_putfield, cf); } public static Instruction make_getstatic(CodeField cf) { return new FieldInstruction(op_getstatic, cf); } public static Instruction make_putstatic(CodeField cf) { return new FieldInstruction(op_putstatic, cf); } // // Generate instruction objects for loads // public static Instruction make_iload(LocalVariable lv) throws CodeException { CodeClass cc = lv.getType(); if (cc != CodeUtils.TYPE_INT && cc != CodeUtils.TYPE_SHORT && cc != CodeUtils.TYPE_CHAR && cc != CodeUtils.TYPE_BYTE && cc != CodeUtils.TYPE_BOOLEAN) { throw new CodeException(cc.getName() + " is not a VM `i' type"); } return new LocalVariableInstruction(op_iload, op_iload_0, lv); } public static Instruction make_lload(LocalVariable lv) throws CodeException { if (lv.getType() != CodeUtils.TYPE_LONG) { throw new CodeException(lv.getType().getName() + " is not a long"); } return new LocalVariableInstruction(op_lload, op_lload_0, lv); } public static Instruction make_fload(LocalVariable lv) throws CodeException { if (lv.getType() != CodeUtils.TYPE_FLOAT) { throw new CodeException(lv.getType().getName() + " is not a float"); } return new LocalVariableInstruction(op_fload, op_fload_0, lv); } public static Instruction make_dload(LocalVariable lv) throws CodeException { if (lv.getType() != CodeUtils.TYPE_DOUBLE) { throw new CodeException(lv.getType().getName() + " is not a double"); } return new LocalVariableInstruction(op_dload, op_dload_0, lv); } public static Instruction make_aload(LocalVariable lv) throws CodeException { if (lv.getType().isPrimitive()) { throw new CodeException(lv.getType().getName() + " is a primitive type"); } return new LocalVariableInstruction(op_aload, op_aload_0, lv); } // // Generate instruction objects for stores // public static Instruction make_istore(LocalVariable lv) throws CodeException { CodeClass cc = lv.getType(); if (cc != CodeUtils.TYPE_INT && cc != CodeUtils.TYPE_SHORT && cc != CodeUtils.TYPE_CHAR && cc != CodeUtils.TYPE_BYTE && cc != CodeUtils.TYPE_BOOLEAN) { throw new CodeException(cc.getName() + " is not a VM `i' type"); } return new LocalVariableInstruction(op_istore, op_istore_0, lv); } public static Instruction make_lstore(LocalVariable lv) throws CodeException { if (lv.getType() != CodeUtils.TYPE_LONG) { throw new CodeException(lv.getType().getName() + " is not a long"); } return new LocalVariableInstruction(op_lstore, op_lstore_0, lv); } public static Instruction make_fstore(LocalVariable lv) throws CodeException { if (lv.getType() != CodeUtils.TYPE_FLOAT) { throw new CodeException(lv.getType().getName() + " is not a float"); } return new LocalVariableInstruction(op_fstore, op_fstore_0, lv); } public static Instruction make_dstore(LocalVariable lv) throws CodeException { if (lv.getType() != CodeUtils.TYPE_DOUBLE) { throw new CodeException(lv.getType().getName() + " is not a double"); } return new LocalVariableInstruction(op_dstore, op_dstore_0, lv); } public static Instruction make_astore(LocalVariable lv) throws CodeException { if (lv.getType().isPrimitive()) { throw new CodeException(lv.getType().getName() + " is a primitive type"); } return new LocalVariableInstruction(op_astore, op_astore_0, lv); } // // Generate the Instruction objects for all this `if's // /** * Return the Instruction object for the ifeq instruction. */ public static Instruction make_ifeq(Label lab) { return make_if(op_ifeq, lab); } /** * Return the Instruction object for the ifne instruction. */ public static Instruction make_ifne(Label lab) { return make_if(op_ifne, lab); } /** * Return the Instruction object for the iflt instruction. * */ public static Instruction make_iflt(Label lab) { return new LabelInstruction(op_iflt, lab, -1); } /** * Return the Instruction object for the ifge instruction. * */ public static Instruction make_ifge(Label lab) { return new LabelInstruction(op_ifge, lab, -1); } /** * Return the Instruction object for the ifgt instruction. * */ public static Instruction make_ifgt(Label lab) { return new LabelInstruction(op_ifgt, lab, -1); } /** * Return the Instruction object for the ifle instruction. */ public static Instruction make_ifle(Label lab) { return new LabelInstruction(op_ifle, lab, -1); } /** * Return the Instruction object for the if_icmpeq instruction. */ public static Instruction make_if_icmpeq(Label l) { return new LabelInstruction(op_if_icmpeq, l, -2); } /** * Return the Instruction object for the if_icmpne instruction. */ public static Instruction make_if_icmpne(Label l) { return new LabelInstruction(op_if_icmpne, l, -2); } /** * Return the Instruction object for the if_icmplt instruction. */ public static Instruction make_if_icmplt(Label l) { return new LabelInstruction(op_if_icmplt, l, -2); } /** * Return the Instruction object for the if_icmpge instruction. */ public static Instruction make_if_icmpge(Label l) { return new LabelInstruction(op_if_icmpge, l, -2); } /** * Return the Instruction object for the if_icmpgt instruction. */ public static Instruction make_if_icmpgt(Label l) { return new LabelInstruction(op_if_icmpgt, l, -2); } /** * Return the Instruction object for the if_icmple instruction. */ public static Instruction make_if_icmple(Label l) { return new LabelInstruction(op_if_icmple, l, -2); } /** * Return the Instruction object for the if_acmpeq instruction. */ public static Instruction make_if_acmpeq(Label l) { return new LabelInstruction(op_if_acmpeq, l, -2); } /** * Return the Instruction object for the if_acmpne instruction. */ public static Instruction make_if_acmpne(Label l) { return new LabelInstruction(op_if_acmpne, l, -2); } /** * Return the Instruction object for the ifnull instruction. */ public static Instruction make_ifnull(Label l) { return new LabelInstruction(op_ifnull, l, -1); } /** * Return the Instruction object for the ifnonnull instruction. */ public static Instruction make_ifnonnull(Label l) { return new LabelInstruction(op_ifnonnull, l, -1); } // // The other label instructions // public static Instruction make_goto(Label l) { return new LabelInstruction(op_goto, l, 0); } public static Instruction make_jsr(Label l) { return new LabelInstruction(op_jsr, l, 1); } // // Generate the Instruction objects for all the no-operands instructions // /** * Return the Instruction object for the nop instruction. */ public static Instruction make_nop() { return new NoOperandsInstruction(op_nop, 0); } /** * Return the Instruction object for the aconst_null instruction. */ public static Instruction make_aconst_null() { return new NoOperandsInstruction(op_aconst_null, 1); } /** * Return the Instruction object for the iaload instruction. */ public static Instruction make_iaload() { return new NoOperandsInstruction(op_iaload, -1); } /** * Return the Instruction object for the laload instruction. */ public static Instruction make_laload() { return new NoOperandsInstruction(op_laload, -1); } /** * Return the Instruction object for the faload instruction. */ public static Instruction make_faload() { return new NoOperandsInstruction(op_faload, -1); } /** * Return the Instruction object for the daload instruction. */ public static Instruction make_daload() { return new NoOperandsInstruction(op_daload, -1); } /** * Return the Instruction object for the aaload instruction. */ public static Instruction make_aaload() { return new NoOperandsInstruction(op_aaload, -1); } /** * Return the Instruction object for the baload instruction. */ public static Instruction make_baload() { return new NoOperandsInstruction(op_baload, -1); } /** * Return the Instruction object for the caload instruction. */ public static Instruction make_caload() { return new NoOperandsInstruction(op_caload, -1); } /** * Return the Instruction object for the saload instruction. */ public static Instruction make_saload() { return new NoOperandsInstruction(op_saload, -1); } /** * Return the Instruction object for the iastore instruction. */ public static Instruction make_iastore() { return new NoOperandsInstruction(op_iastore, -3); } /** * Return the Instruction object for the lastore instruction. */ public static Instruction make_lastore() { return new NoOperandsInstruction(op_lastore, -3); } /** * Return the Instruction object for the fastore instruction. */ public static Instruction make_fastore() { return new NoOperandsInstruction(op_fastore, -3); } /** * Return the Instruction object for the dastore instruction. */ public static Instruction make_dastore() { return new NoOperandsInstruction(op_dastore, -3); } /** * Return the Instruction object for the aastore instruction. */ public static Instruction make_aastore() { return new NoOperandsInstruction(op_aastore, -3); } /** * Return the Instruction object for the bastore instruction. */ public static Instruction make_bastore() { return new NoOperandsInstruction(op_bastore, -3); } /** * Return the Instruction object for the castore instruction. */ public static Instruction make_castore() { return new NoOperandsInstruction(op_castore, -3); } /** * Return the Instruction object for the sastore instruction. */ public static Instruction make_sastore() { return new NoOperandsInstruction(op_sastore, -3); } /** * Return the Instruction object for the pop instruction. */ public static Instruction make_pop() { return new NoOperandsInstruction(op_pop, -1); } /** * Return the Instruction object for the pop2 instruction. */ public static Instruction make_pop2() { return new NoOperandsInstruction(op_pop2, -2); } /** * Return the Instruction object for the dup instruction. */ public static Instruction make_dup() { return new NoOperandsInstruction(op_dup, 1); } /** * Return the Instruction object for the dup_x1 instruction. */ public static Instruction make_dup_x1() { return new NoOperandsInstruction(op_dup_x1, 1); } /** * Return the Instruction object for the dup_x2 instruction. */ public static Instruction make_dup_x2() { return new NoOperandsInstruction(op_dup_x2, 1); } /** * Return the Instruction object for the dup2 instruction. */ public static Instruction make_dup2() { return new NoOperandsInstruction(op_dup2, 2); } /** * Return the Instruction object for the dup2_x1 instruction. */ public static Instruction make_dup2_x1() { return new NoOperandsInstruction(op_dup2_x1, 2); } /** * Return the Instruction object for the dup2_x2 instruction. */ public static Instruction make_dup2_x2() { return new NoOperandsInstruction(op_dup2_x2, 2); } /** * Return the Instruction object for the swap instruction. */ public static Instruction make_swap() { return new NoOperandsInstruction(op_swap, 0); } /** * Return the Instruction object for the iadd instruction. */ public static Instruction make_iadd() { return new NoOperandsInstruction(op_iadd, -1); } /** * Return the Instruction object for the ladd instruction. */ public static Instruction make_ladd() { return new NoOperandsInstruction(op_ladd, -1); } /** * Return the Instruction object for the fadd instruction. */ public static Instruction make_fadd() { return new NoOperandsInstruction(op_fadd, -1); } /** * Return the Instruction object for the dadd instruction. */ public static Instruction make_dadd() { return new NoOperandsInstruction(op_dadd, -1); } /** * Return the Instruction object for the isub instruction. */ public static Instruction make_isub() { return new NoOperandsInstruction(op_isub, -1); } /** * Return the Instruction object for the lsub instruction. */ public static Instruction make_lsub() { return new NoOperandsInstruction(op_lsub, -1); } /** * Return the Instruction object for the fsub instruction. */ public static Instruction make_fsub() { return new NoOperandsInstruction(op_fsub, -1); } /** * Return the Instruction object for the dsub instruction. */ public static Instruction make_dsub() { return new NoOperandsInstruction(op_dsub, -1); } /** * Return the Instruction object for the imul instruction. */ public static Instruction make_imul() { return new NoOperandsInstruction(op_imul, -1); } /** * Return the Instruction object for the lmul instruction. */ public static Instruction make_lmul() { return new NoOperandsInstruction(op_lmul, -1); } /** * Return the Instruction object for the fmul instruction. */ public static Instruction make_fmul() { return new NoOperandsInstruction(op_fmul, -1); } /** * Return the Instruction object for the dmul instruction. */ public static Instruction make_dmul() { return new NoOperandsInstruction(op_dmul, -1); } /** * Return the Instruction object for the idiv instruction. */ public static Instruction make_idiv() { return new NoOperandsInstruction(op_idiv, -1); } /** * Return the Instruction object for the ldiv instruction. */ public static Instruction make_ldiv() { return new NoOperandsInstruction(op_ldiv, -1); } /** * Return the Instruction object for the fdiv instruction. */ public static Instruction make_fdiv() { return new NoOperandsInstruction(op_fdiv, -1); } /** * Return the Instruction object for the ddiv instruction. */ public static Instruction make_ddiv() { return new NoOperandsInstruction(op_ddiv, -1); } /** * Return the Instruction object for the irem instruction. */ public static Instruction make_irem() { return new NoOperandsInstruction(op_irem, -1); } /** * Return the Instruction object for the lrem instruction. */ public static Instruction make_lrem() { return new NoOperandsInstruction(op_lrem, -1); } /** * Return the Instruction object for the frem instruction. */ public static Instruction make_frem() { return new NoOperandsInstruction(op_frem, -1); } /** * Return the Instruction object for the drem instruction. */ public static Instruction make_drem() { return new NoOperandsInstruction(op_drem, -1); } /** * Return the Instruction object for the ineg instruction. */ public static Instruction make_ineg() { return new NoOperandsInstruction(op_ineg, 0); } /** * Return the Instruction object for the lneg instruction. */ public static Instruction make_lneg() { return new NoOperandsInstruction(op_lneg, 0); } /** * Return the Instruction object for the fneg instruction. */ public static Instruction make_fneg() { return new NoOperandsInstruction(op_fneg, 0); } /** * Return the Instruction object for the dneg instruction. */ public static Instruction make_dneg() { return new NoOperandsInstruction(op_dneg, 0); } /** * Return the Instruction object for the ishl instruction. */ public static Instruction make_ishl() { return new NoOperandsInstruction(op_ishl, -1); } /** * Return the Instruction object for the lshl instruction. */ public static Instruction make_lshl() { return new NoOperandsInstruction(op_lshl, -1); } /** * Return the Instruction object for the ishr instruction. */ public static Instruction make_ishr() { return new NoOperandsInstruction(op_ishr, -1); } /** * Return the Instruction object for the lshr instruction. */ public static Instruction make_lshr() { return new NoOperandsInstruction(op_lshr, -1); } /** * Return the Instruction object for the iushr instruction. */ public static Instruction make_iushr() { return new NoOperandsInstruction(op_iushr, -1); } /** * Return the Instruction object for the lushr instruction. */ public static Instruction make_lushr() { return new NoOperandsInstruction(op_lushr, -1); } /** * Return the Instruction object for the iand instruction. */ public static Instruction make_iand() { return new NoOperandsInstruction(op_iand, -1); } /** * Return the Instruction object for the land instruction. */ public static Instruction make_land() { return new NoOperandsInstruction(op_land, -1); } /** * Return the Instruction object for the ior instruction. */ public static Instruction make_ior() { return new NoOperandsInstruction(op_ior, -1); } /** * Return the Instruction object for the lor instruction. */ public static Instruction make_lor() { return new NoOperandsInstruction(op_lor, -1); } /** * Return the Instruction object for the ixor instruction. */ public static Instruction make_ixor() { return new NoOperandsInstruction(op_ixor, -1); } /** * Return the Instruction object for the lxor instruction. */ public static Instruction make_lxor() { return new NoOperandsInstruction(op_lxor, -1); } /** * Return the Instruction object for the i2l instruction. */ public static Instruction make_i2l() { return new NoOperandsInstruction(op_i2l, 0); } /** * Return the Instruction object for the i2f instruction. */ public static Instruction make_i2f() { return new NoOperandsInstruction(op_i2f, 0); } /** * Return the Instruction object for the i2d instruction. */ public static Instruction make_i2d() { return new NoOperandsInstruction(op_i2d, 0); } /** * Return the Instruction object for the l2i instruction. */ public static Instruction make_l2i() { return new NoOperandsInstruction(op_l2i, 0); } /** * Return the Instruction object for the l2f instruction. */ public static Instruction make_l2f() { return new NoOperandsInstruction(op_l2f, 0); } /** * Return the Instruction object for the l2d instruction. */ public static Instruction make_l2d() { return new NoOperandsInstruction(op_l2d, 0); } /** * Return the Instruction object for the f2i instruction. */ public static Instruction make_f2i() { return new NoOperandsInstruction(op_f2i, 0); } /** * Return the Instruction object for the f2l instruction. */ public static Instruction make_f2l() { return new NoOperandsInstruction(op_f2l, 0); } /** * Return the Instruction object for the f2d instruction. */ public static Instruction make_f2d() { return new NoOperandsInstruction(op_f2d, 0); } /** * Return the Instruction object for the d2i instruction. */ public static Instruction make_d2i() { return new NoOperandsInstruction(op_d2i, 0); } /** * Return the Instruction object for the d2l instruction. */ public static Instruction make_d2l() { return new NoOperandsInstruction(op_d2l, 0); } /** * Return the Instruction object for the d2f instruction. */ public static Instruction make_d2f() { return new NoOperandsInstruction(op_d2f, 0); } /** * Return the Instruction object for the i2b instruction. */ public static Instruction make_i2b() { return new NoOperandsInstruction(op_i2b, 0); } /** * Return the Instruction object for the i2c instruction. */ public static Instruction make_i2c() { return new NoOperandsInstruction(op_i2c, 0); } /** * Return the Instruction object for the i2s instruction. */ public static Instruction make_i2s() { return new NoOperandsInstruction(op_i2s, 0); } /** * Return the Instruction object for the lcmp instruction. */ public static Instruction make_lcmp() { return new NoOperandsInstruction(op_lcmp, -1); } /** * Return the Instruction object for the fcmpl instruction. */ public static Instruction make_fcmpl() { return new NoOperandsInstruction(op_fcmpl, -1); } /** * Return the Instruction object for the fcmpg instruction. */ public static Instruction make_fcmpg() { return new NoOperandsInstruction(op_fcmpg, -1); } /** * Return the Instruction object for the dcmpl instruction. */ public static Instruction make_dcmpl() { return new NoOperandsInstruction(op_dcmpl, -1); } /** * Return the Instruction object for the dcmpg instruction. */ public static Instruction make_dcmpg() { return new NoOperandsInstruction(op_dcmpg, -1); } /** * Return the Instruction object for the ireturn instruction. */ public static Instruction make_ireturn() { return new NoOperandsInstruction(op_ireturn, -1); } /** * Return the Instruction object for the lreturn instruction. */ public static Instruction make_lreturn() { return new NoOperandsInstruction(op_lreturn, -1); } /** * Return the Instruction object for the freturn instruction. */ public static Instruction make_freturn() { return new NoOperandsInstruction(op_freturn, -1); } /** * Return the Instruction object for the dreturn instruction. */ public static Instruction make_dreturn() { return new NoOperandsInstruction(op_dreturn, -1); } /** * Return the Instruction object for the areturn instruction. */ public static Instruction make_areturn() { return new NoOperandsInstruction(op_areturn, -1); } /** * Return the Instruction object for the return instruction. */ public static Instruction make_return() { return new NoOperandsInstruction(op_return, 0); } /** * Return the Instruction object for the arraylength instruction. */ public static Instruction make_arraylength() { return new NoOperandsInstruction(op_arraylength, 0); } /** * Return the Instruction object for the athrow instruction. */ public static Instruction make_athrow() { return new NoOperandsInstruction(op_athrow, 0); } /** * Return the Instruction object for the monitorenter instruction. * */ public static Instruction make_monitorenter() { return new NoOperandsInstruction(op_monitorenter, -1); } /** * Return the Instruction object for the monitorexit instruction. */ public static Instruction make_monitorexit() { return new NoOperandsInstruction(op_monitorexit, -1); } /** * Return the Instruction object for the wide instruction. */ public static Instruction make_wide() { return new NoOperandsInstruction(op_wide, 0); } /** * Return the Instruction object for the breakpoint instruction. */ public static Instruction make_breakpoint() { return new NoOperandsInstruction(op_breakpoint, 0); } /** * Return the Instruction object for the invokevirtual_quick_w instruction. * * Apparently now undocumented. Presumably deprecated. */ public static Instruction make_invokevirtual_quick_w() { // fixme - I have no idea what the stack-depth change is here // should we even be using this class? return new NoOperandsInstruction(op_invokevirtual_quick_w, 0); } /** * Return the Instruction object for the impdep1 instruction. */ public static Instruction make_impdep1() { return new NoOperandsInstruction(op_impdep1, 0); } /** * Return the Instruction object for the impdep2 instruction. */ public static Instruction make_impdep2() { return new NoOperandsInstruction(op_impdep2, 0); } public static Instruction make_checkcast(CodeClass clazz) { return new ClassInstruction(op_checkcast, clazz, 0); } public static Instruction make_instanceof(CodeClass clazz) { return new ClassInstruction(op_instanceof, clazz, 0); } // new instruction added by hand - mrp public static Instruction make_new(CodeClass clazz) { return new ClassInstruction(op_new, clazz, 1); } public static Instruction make_newarray(CodeClass clazz) throws CodeException { if (clazz.isPrimitive()) { int type = -1; if (clazz == CodeUtils.TYPE_BOOLEAN) { type = 4; } else if (clazz == CodeUtils.TYPE_CHAR) { type = 5; } else if (clazz == CodeUtils.TYPE_FLOAT) { type = 6; } else if (clazz == CodeUtils.TYPE_DOUBLE) { type = 7; } else if (clazz == CodeUtils.TYPE_BYTE) { type = 8; } else if (clazz == CodeUtils.TYPE_SHORT) { type = 9; } else if (clazz == CodeUtils.TYPE_INT) { type = 10; } else if (clazz == CodeUtils.TYPE_LONG) { type = 11; } if (type < 0) { throw new CodeException("Invalid type " + clazz.getName()); } return new ByteInstruction(op_newarray, (byte) type, 0); } else { return new ClassInstruction(op_anewarray, clazz, 0); } } /** * A convenient one-stop method to get a return statement suitable for a * method. * * @param method the CodeMethod to return from * @return a return Instruction that fits this method's return type */ public static Instruction make_return(CodeMethod method) { return make_return(method.getReturnType()); } /** * Creates the return Instruction suitable for a given class or type. * * @param clazz the CodeClass representing the class or type to return * @return the apropreate return instruction */ public static Instruction make_return(CodeClass clazz) { if (false) { } else if(CodeUtils.TYPE_VOID.equals(clazz)) { return make_return(); } else if( CodeUtils.TYPE_BYTE.equals(clazz) || CodeUtils.TYPE_SHORT.equals(clazz) || CodeUtils.TYPE_CHAR.equals(clazz) || CodeUtils.TYPE_BOOLEAN.equals(clazz) || CodeUtils.TYPE_INT.equals(clazz) ) { return make_ireturn(); } else if(CodeUtils.TYPE_LONG.equals(clazz)) { return make_lreturn(); } else if(CodeUtils.TYPE_FLOAT.equals(clazz)) { return make_freturn(); } else if(CodeUtils.TYPE_DOUBLE.equals(clazz)) { return make_dreturn(); } return make_areturn(); } /** * Make an invoke opcode that is suited to the method. * *

Constructors and private methods are invoked by invokespecial. * Static methods are invoked by invokestatic. Methods referred to by * interface are invoked by invokeinterface, and methods referred to * by classes are invoked by invokeabstract.

* * @param cm the CodeMethod to invoke * @return an invocation Instruction suited to the method */ public static Instruction make_invoke(CodeMethod cm) { int modifiers = cm.getModifiers(); if( (CodeUtils.ACC_STATIC & modifiers) != 0 ) { return make_invokestatic(cm); } else if( (CodeUtils.ACC_INTERFACE) != 0 ) { return make_invokeinterface(cm); } else if( (CodeUtils.ACC_PRIVATE) != 0 ) { return make_invokespecial(cm); } else { return make_invokevirtual(cm); } } /** * Synchronize the processing of an entire block of code on a local * variable. The local variable must refer to a Java object. It is safe to * replace the value of the local variable within the block. * * @param lockVar Label for the local variable to lock on * @param code the CodeGenerator that will make the body of the synchronized * block * @throws CodeException if locVar holds a primative value */ public static CodeGenerator make_synchronizedBlock( LocalVariable lockVar, CodeGenerator code ) throws CodeException { InstructionVector block = new InstructionVector(); block.add(make_aload(lockVar)); block.add(make_dup()); // defencive copy incase the local is re-assigned block.add(make_monitorenter()); block.add(code); block.add(make_monitorexit()); return block; } /** * Synchronize the processing of an entire block of code on the object on * the top of the stack. * * @param lockVar Label for the local variable to lock on * @param code the CodeGenerator that will make the body of the synchronized * block */ public static CodeGenerator make_synchronizedBlock(CodeGenerator code) { InstructionVector block = new InstructionVector(); block.add(make_dup()); block.add(make_monitorenter()); block.add(code); block.add(make_monitorexit()); return block; } public static CodeGenerator make_markLabel(Label lab) { return new MarkLabel(lab); } /** * Make an if Instruction for the opcode and label. * *

Obcodes for IF jump to the label if the condition is true, or execute * the next instruction ontherwise. In this case, op will be used to compare * the top of the stack and if the condition is true, will cause a jump to * the label. Otherwise, the next instruction in the stream will be used. *

* * @param op if opcode * @param lab Label to jump to * @return an Instruction that will perform an if * @throws IllegalArgumentException if the op code is not an if instruction */ public static Instruction make_if(byte op, Label lab) { if(op >= op_ifeq && op <= op_ifle) { return new LabelInstruction(op, lab, -1); } else if(op >= op_if_icmpeq && op <= op_if_acmpne) { return new LabelInstruction(op, lab, -2); } else { throw new IllegalArgumentException("Opcode must be an if. " + op); } } public static ParametricCodeGenerator make_newraray(final ParametricType type) { return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDepth() { return 0; } public int stackDelta() { return 0; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); make_newarray(cc).writeCode(ctx); } }; } /** * Load an element of a parametric type to an array. * *

This is the parametric version of the make_<x>aload() factory * methods.

* * @param type the ParametricType giving the element type of the array * @return a ParametricCodeGenerator that will load the correct type. */ public static ParametricCodeGenerator make_array_load(final ParametricType type) { return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDepth() { return 0; } public int stackDelta() { return -1; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); if(!cc.isPrimitive()) { ctx.writeByte(op_aaload); } else if(cc == CodeUtils.TYPE_INT) { ctx.writeByte(op_iaload); } else if(cc == CodeUtils.TYPE_LONG) { ctx.writeByte(op_daload); } else if(cc == CodeUtils.TYPE_FLOAT) { ctx.writeByte(op_faload); } else if(cc == CodeUtils.TYPE_DOUBLE) { ctx.writeByte(op_daload); } else if(cc == CodeUtils.TYPE_BYTE) { ctx.writeByte(op_baload); } else if(cc == CodeUtils.TYPE_CHAR) { ctx.writeByte(op_caload); } else if(cc == CodeUtils.TYPE_SHORT) { ctx.writeByte(op_saload); } else { throw new CodeException("Confused. Don't recognize type: " + cc); } } }; } /** * Store an element of a parametric type to an array. * *

This is the parametric version of the make_<x>astore() factory * methods.

* * @param type the ParametricType giving the element type of the array * @return a ParametricCodeGenerator that will store the correct type. */ public static ParametricCodeGenerator make_arrayStore(final ParametricType type) { return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDepth() { return 0; } public int stackDelta() { return -3; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); if(!cc.isPrimitive()) { ctx.writeByte(op_aastore); } else if(cc == CodeUtils.TYPE_INT) { ctx.writeByte(op_iastore); } else if(cc == CodeUtils.TYPE_LONG) { ctx.writeByte(op_dastore); } else if(cc == CodeUtils.TYPE_FLOAT) { ctx.writeByte(op_fastore); } else if(cc == CodeUtils.TYPE_DOUBLE) { ctx.writeByte(op_dastore); } else if(cc == CodeUtils.TYPE_BYTE) { ctx.writeByte(op_bastore); } else if(cc == CodeUtils.TYPE_CHAR) { ctx.writeByte(op_castore); } else if(cc == CodeUtils.TYPE_SHORT) { ctx.writeByte(op_sastore); } else { throw new CodeException("Confused. Don't recognize type: " + cc); } } }; } /** * Load an item of a parametric type from a local variable. * *

This is the parametric version of the make_<x>load() factory * methods.

* * @param type the ParametricType giving the type to load * @param lv the LocalVariable to load from * @return a ParametricCodeGenerator that will load the correct type. */ public ParametricCodeGenerator make_load( final ParametricType type, final LocalVariable lv ) throws CodeException { return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDepth() { return 1; } public int stackDelta() { return 1; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); Instruction ins; if(!cc.isPrimitive()) { ins = make_aload(lv); } else if(cc == CodeUtils.TYPE_INT) { ins = make_iload(lv); } else if(cc == CodeUtils.TYPE_LONG) { ins = make_lload(lv); } else if(cc == CodeUtils.TYPE_FLOAT) { ins = make_fload(lv); } else if(cc == CodeUtils.TYPE_DOUBLE) { ins = make_dload(lv); } else if(cc == CodeUtils.TYPE_BYTE) { ins = make_iload(lv); } else if(cc == CodeUtils.TYPE_CHAR) { ins = make_iload(lv); } else if(cc == CodeUtils.TYPE_SHORT) { ins = make_iload(lv); } else { throw new CodeException("Confused. Don't recognize type: " + cc); } ins.writeCode(ctx); } }; } /** * Store an item of a parametric type to a local variable. * *

This is the parametric version of the make_<x>save() factory * methods.

* * @param type the ParametricType giving the type to save * @param lv the LocalVariable to load from * @return a ParametricCodeGenerator that will save the correct type. */ public ParametricCodeGenerator make_save( final ParametricType type, final LocalVariable lv ) throws CodeException { return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDepth() { return 0; } public int stackDelta() { return -1; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); Instruction ins; if(!cc.isPrimitive()) { ins = make_astore(lv); } else if(cc == CodeUtils.TYPE_INT) { ins = make_istore(lv); } else if(cc == CodeUtils.TYPE_LONG) { ins = make_lstore(lv); } else if(cc == CodeUtils.TYPE_FLOAT) { ins = make_fstore(lv); } else if(cc == CodeUtils.TYPE_DOUBLE) { ins = make_dstore(lv); } else if(cc == CodeUtils.TYPE_BYTE) { ins = make_istore(lv); } else if(cc == CodeUtils.TYPE_CHAR) { ins = make_istore(lv); } else if(cc == CodeUtils.TYPE_SHORT) { ins = make_istore(lv); } else { throw new CodeException("Confused. Don't recognize type: " + cc); } ins.writeCode(ctx); } }; } /** * Make a return statement for the parametric type. * * @param type the ParametricType to return */ public ParametricCodeGenerator make_return(final ParametricType type) { return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDepth() { return 0; } public int stackDelta() { return -1; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); if(!cc.isPrimitive()) { ctx.writeByte(op_areturn); } else if(cc == CodeUtils.TYPE_INT) { ctx.writeByte(op_ireturn); } else if(cc == CodeUtils.TYPE_LONG) { ctx.writeByte(op_lreturn); } else if(cc == CodeUtils.TYPE_FLOAT) { ctx.writeByte(op_freturn); } else if(cc == CodeUtils.TYPE_DOUBLE) { ctx.writeByte(op_dreturn); } else if(cc == CodeUtils.TYPE_BYTE) { ctx.writeByte(op_ireturn); } else if(cc == CodeUtils.TYPE_CHAR) { ctx.writeByte(op_ireturn); } else if(cc == CodeUtils.TYPE_SHORT) { ctx.writeByte(op_ireturn); } else { throw new CodeException("Confused. Don't recognize type: " + cc); } } }; } public PParametricCodeGenerator make_cast( final ParametricType from, final ParametricType to ) throws CodeException { if(from.isObject()) { throw new CodeException("Can not cast from non-primative type: " + from); } if(to.isObject()) { throw new CodeException("Can not cast to non-primative type: " + to); } return new PParametricCodeGenerator() { public ParametricType getType1() { return from; } public ParametricType getType2() { return to; } public int stackDepth() { return 0; } public int stackDelta() { return 0; } public void writeCode(CodeContext ctx) throws CodeException { if(from == to) { return; } CodeClass fromc = ctx.resolveParametricType(from); CodeClass toc = ctx.resolveParametricType(to); if(!fromc.isPrimitive()) { throw new CodeException("Can't cast from non-primitive type: " + fromc); } if(!toc.isPrimitive()) { throw new CodeException("Can't cast to non-primitive type: " + toc); } if(fromc == CodeUtils.TYPE_DOUBLE) { if(toc == CodeUtils.TYPE_FLOAT) { ctx.writeByte(op_d2f); } else if(toc == CodeUtils.TYPE_LONG) { ctx.writeByte(op_d2l); } else { ctx.writeByte(op_d2i); } } else if(fromc == CodeUtils.TYPE_LONG) { if(toc == CodeUtils.TYPE_FLOAT) { ctx.writeByte(op_l2f); } else if(toc == CodeUtils.TYPE_DOUBLE) { ctx.writeByte(op_l2d); } else { ctx.writeByte(op_d2i); } } else { // something equivalent to integer if(toc == CodeUtils.TYPE_FLOAT) { ctx.writeByte(op_i2f); } else if(toc == CodeUtils.TYPE_DOUBLE) { ctx.writeByte(op_i2d); } else if(toc == CodeUtils.TYPE_LONG) { ctx.writeByte(op_i2l); } else if(toc == CodeUtils.TYPE_BYTE) { ctx.writeByte(op_i2b); } else if(toc == CodeUtils.TYPE_CHAR) { ctx.writeByte(op_i2c); } else if(toc == CodeUtils.TYPE_SHORT) { ctx.writeByte(op_i2s); } } } }; } public ParametricCodeGenerator make_add(final ParametricType type) throws CodeException { if(type.isObject()) { throw new CodeException("Can't add non-primitive type: " + type); } return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDelta() { return -1; } public int stackDepth() { return 0; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); if(!cc.isPrimitive()) { throw new CodeException( "We can only add primitive types: " + type + " : " + cc ); } if(cc == CodeUtils.TYPE_DOUBLE) { ctx.writeByte(op_dadd); } else if(cc == CodeUtils.TYPE_LONG) { ctx.writeByte(op_ladd); } else if(cc == CodeUtils.TYPE_FLOAT) { ctx.writeByte(op_fadd); } else { ctx.writeByte(op_iadd); } } }; } public ParametricCodeGenerator make_sub(final ParametricType type) throws CodeException { if(type.isObject()) { throw new CodeException("Can't sub non-primitive type: " + type); } return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDelta() { return -1; } public int stackDepth() { return 0; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); if(!cc.isPrimitive()) { throw new CodeException( "We can only sub primitive types: " + type + " : " + cc ); } if(cc == CodeUtils.TYPE_DOUBLE) { ctx.writeByte(op_dsub); } else if(cc == CodeUtils.TYPE_LONG) { ctx.writeByte(op_lsub); } else if(cc == CodeUtils.TYPE_FLOAT) { ctx.writeByte(op_fsub); } else { ctx.writeByte(op_isub); } } }; } public ParametricCodeGenerator make_mul(final ParametricType type) throws CodeException { if(type.isObject()) { throw new CodeException("Can't mul non-primitive type: " + type); } return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDelta() { return -1; } public int stackDepth() { return 0; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); if(!cc.isPrimitive()) { throw new CodeException( "We can only mul primitive types: " + type + " : " + cc ); } if(cc == CodeUtils.TYPE_DOUBLE) { ctx.writeByte(op_dmul); } else if(cc == CodeUtils.TYPE_LONG) { ctx.writeByte(op_lmul); } else if(cc == CodeUtils.TYPE_FLOAT) { ctx.writeByte(op_fmul); } else { ctx.writeByte(op_imul); } } }; } public ParametricCodeGenerator make_div(final ParametricType type) throws CodeException { if(type.isObject()) { throw new CodeException("Can't div non-primitive type: " + type); } return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDelta() { return -1; } public int stackDepth() { return 0; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); if(!cc.isPrimitive()) { throw new CodeException( "We can only div primitive types: " + type + " : " + cc ); } if(cc == CodeUtils.TYPE_DOUBLE) { ctx.writeByte(op_ddiv); } else if(cc == CodeUtils.TYPE_LONG) { ctx.writeByte(op_ldiv); } else if(cc == CodeUtils.TYPE_FLOAT) { ctx.writeByte(op_fdiv); } else { ctx.writeByte(op_idiv); } } }; } public ParametricCodeGenerator make_rem(final ParametricType type) throws CodeException { if(type.isObject()) { throw new CodeException("Can't rem non-primitive type: " + type); } return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDelta() { return -1; } public int stackDepth() { return 0; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); if(!cc.isPrimitive()) { throw new CodeException( "We can only rem primitive types: " + type + " : " + cc ); } if(cc == CodeUtils.TYPE_DOUBLE) { ctx.writeByte(op_drem); } else if(cc == CodeUtils.TYPE_LONG) { ctx.writeByte(op_lrem); } else if(cc == CodeUtils.TYPE_FLOAT) { ctx.writeByte(op_frem); } else { ctx.writeByte(op_irem); } } }; } public ParametricCodeGenerator make_neg(final ParametricType type) throws CodeException { if(type.isObject()) { throw new CodeException("Can't add non-primitive type: " + type); } return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDelta() { return 0; } public int stackDepth() { return 0; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); if(!cc.isPrimitive()) { throw new CodeException( "We can only add primitive types: " + type + " : " + cc ); } if(cc == CodeUtils.TYPE_DOUBLE) { ctx.writeByte(op_dneg); } else if(cc == CodeUtils.TYPE_LONG) { ctx.writeByte(op_lneg); } else if(cc == CodeUtils.TYPE_FLOAT) { ctx.writeByte(op_fneg); } else { ctx.writeByte(op_ineg); } } }; } public ParametricCodeGenerator make_shiftLeft(final ParametricType type) throws CodeException { if(type.isObject()) { throw new CodeException("Can't shift non-primitive type: " + type); } return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDelta() { return -1; } public int stackDepth() { return 0; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); if(!cc.isPrimitive()) { throw new CodeException("Can't shift non-primitive type: " + cc); } if(CodeUtils.isFloatType(cc)) { throw new CodeException("Can't shift floating point type: " + cc); } if(cc == CodeUtils.TYPE_LONG) { ctx.writeByte(op_lshl); } else { ctx.writeByte(op_ishl); } } }; } public ParametricCodeGenerator make_shiftRight(final ParametricType type) throws CodeException { if(type.isObject()) { throw new CodeException("Can't shift non-primitive type: " + type); } return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDelta() { return -1; } public int stackDepth() { return 0; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); if(!cc.isPrimitive()) { throw new CodeException("Can't shift non-primitive type: " + cc); } if(CodeUtils.isFloatType(cc)) { throw new CodeException("Can't shift floating point type: " + cc); } if(cc == CodeUtils.TYPE_LONG) { ctx.writeByte(op_lshr); } else { ctx.writeByte(op_ishr); } } }; } public ParametricCodeGenerator make_shiftRightLogical(final ParametricType type) throws CodeException { if(type.isObject()) { throw new CodeException("Can't shift non-primitive type: " + type); } return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDelta() { return -1; } public int stackDepth() { return 0; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); if(!cc.isPrimitive()) { throw new CodeException("Can't shift non-primitive type: " + cc); } if(CodeUtils.isFloatType(cc)) { throw new CodeException("Can't shift floating point type: " + cc); } if(cc == CodeUtils.TYPE_LONG) { ctx.writeByte(op_lushr); } else { ctx.writeByte(op_iushr); } } }; } public ParametricCodeGenerator make_and(final ParametricType type) throws CodeException { if(type.isObject()) { throw new CodeException("Can't and non-primitive type: " + type); } return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDelta() { return -1; } public int stackDepth() { return 0; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); if(!cc.isPrimitive()) { throw new CodeException("Can't and non-primitive type: " + cc); } if(CodeUtils.isFloatType(cc)) { throw new CodeException("Can't and floating point type: " + cc); } if(cc == CodeUtils.TYPE_LONG) { ctx.writeByte(op_land); } else { ctx.writeByte(op_iand); } } }; } public ParametricCodeGenerator make_or(final ParametricType type) throws CodeException { if(type.isObject()) { throw new CodeException("Can't and non-primitive type: " + type); } return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDelta() { return -1; } public int stackDepth() { return 0; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); if(!cc.isPrimitive()) { throw new CodeException("Can't or non-primitive type: " + cc); } if(CodeUtils.isFloatType(cc)) { throw new CodeException("Can't or floating point type: " + cc); } if(cc == CodeUtils.TYPE_LONG) { ctx.writeByte(op_lor); } else { ctx.writeByte(op_ior); } } }; } public ParametricCodeGenerator make_xor(final ParametricType type) throws CodeException { if(type.isObject()) { throw new CodeException("Can't and non-primitive type: " + type); } return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDelta() { return -1; } public int stackDepth() { return 0; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); if(!cc.isPrimitive()) { throw new CodeException("Can't xor non-primitive type: " + cc); } if(CodeUtils.isFloatType(cc)) { throw new CodeException("Can't xor floating point type: " + cc); } if(cc == CodeUtils.TYPE_LONG) { ctx.writeByte(op_lxor); } else { ctx.writeByte(op_ixor); } } }; } public ParametricCodeGenerator make_cmpg(final ParametricType type) throws CodeException { if(type.isObject()) { throw new CodeException("Can't cmpg non-primitive type: " + type); } return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDelta() { return -1; } public int stackDepth() { return 0; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); if(!CodeUtils.isFloatType(cc)) { throw new CodeException("Can only cmpg floating point types: " + cc); } if(cc == CodeUtils.TYPE_DOUBLE) { ctx.writeByte(op_dcmpg); } else { ctx.writeByte(op_fcmpg); } } }; } public ParametricCodeGenerator make_cmpl(final ParametricType type) throws CodeException { if(type.isObject()) { throw new CodeException("Can't cmpl non-primitive type: " + type); } return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDelta() { return -1; } public int stackDepth() { return 0; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); if(!CodeUtils.isFloatType(cc)) { throw new CodeException("Can only cmpl floating point types: " + cc); } if(cc == CodeUtils.TYPE_DOUBLE) { ctx.writeByte(op_dcmpl); } else { ctx.writeByte(op_fcmpl); } } }; } public ParametricCodeGenerator make_dup(final ParametricType type) throws CodeException { return new ParametricCodeGenerator() { public ParametricType getType() { return type; } public int stackDelta() { return 1; } public int stackDepth() { return 1; } public void writeCode(CodeContext ctx) throws CodeException { CodeClass cc = ctx.resolveParametricType(type); if(CodeUtils.wordsForType(cc) == 2) { ctx.writeByte(op_dup2); } else { ctx.writeByte(op_dup); } } }; } // // Java opcodes // public final static byte op_nop = 0; public final static byte op_aconst_null = 1; public final static byte op_iconst_m1 = 2; public final static byte op_iconst_0 = 3; public final static byte op_iconst_1 = 4; public final static byte op_iconst_2 = 5; public final static byte op_iconst_3 = 6; public final static byte op_iconst_4 = 7; public final static byte op_iconst_5 = 8; public final static byte op_lconst_0 = 9; public final static byte op_lconst_1 = 10; public final static byte op_fconst_0 = 11; public final static byte op_fconst_1 = 12; public final static byte op_fconst_2 = 13; public final static byte op_dconst_0 = 14; public final static byte op_dconst_1 = 15; public final static byte op_bipush = 16; public final static byte op_sipush = 17; public final static byte op_ldc = 18; public final static byte op_ldc_w = 19; public final static byte op_ldc2_w = 20; public final static byte op_iload = 21; public final static byte op_lload = 22; public final static byte op_fload = 23; public final static byte op_dload = 24; public final static byte op_aload = 25; public final static byte op_iload_0 = 26; public final static byte op_iload_1 = 27; public final static byte op_iload_2 = 28; public final static byte op_iload_3 = 29; public final static byte op_lload_0 = 30; public final static byte op_lload_1 = 31; public final static byte op_lload_2 = 32; public final static byte op_lload_3 = 33; public final static byte op_fload_0 = 34; public final static byte op_fload_1 = 35; public final static byte op_fload_2 = 36; public final static byte op_fload_3 = 37; public final static byte op_dload_0 = 38; public final static byte op_dload_1 = 39; public final static byte op_dload_2 = 40; public final static byte op_dload_3 = 41; public final static byte op_aload_0 = 42; public final static byte op_aload_1 = 43; public final static byte op_aload_2 = 44; public final static byte op_aload_3 = 45; public final static byte op_iaload = 46; public final static byte op_laload = 47; public final static byte op_faload = 48; public final static byte op_daload = 49; public final static byte op_aaload = 50; public final static byte op_baload = 51; public final static byte op_caload = 52; public final static byte op_saload = 53; public final static byte op_istore = 54; public final static byte op_lstore = 55; public final static byte op_fstore = 56; public final static byte op_dstore = 57; public final static byte op_astore = 58; public final static byte op_istore_0 = 59; public final static byte op_istore_1 = 60; public final static byte op_istore_2 = 61; public final static byte op_istore_3 = 62; public final static byte op_lstore_0 = 63; public final static byte op_lstore_1 = 64; public final static byte op_lstore_2 = 65; public final static byte op_lstore_3 = 66; public final static byte op_fstore_0 = 67; public final static byte op_fstore_1 = 68; public final static byte op_fstore_2 = 69; public final static byte op_fstore_3 = 70; public final static byte op_dstore_0 = 71; public final static byte op_dstore_1 = 72; public final static byte op_dstore_2 = 73; public final static byte op_dstore_3 = 74; public final static byte op_astore_0 = 75; public final static byte op_astore_1 = 76; public final static byte op_astore_2 = 77; public final static byte op_astore_3 = 78; public final static byte op_iastore = 79; public final static byte op_lastore = 80; public final static byte op_fastore = 81; public final static byte op_dastore = 82; public final static byte op_aastore = 83; public final static byte op_bastore = 84; public final static byte op_castore = 85; public final static byte op_sastore = 86; public final static byte op_pop = 87; public final static byte op_pop2 = 88; public final static byte op_dup = 89; public final static byte op_dup_x1 = 90; public final static byte op_dup_x2 = 91; public final static byte op_dup2 = 92; public final static byte op_dup2_x1 = 93; public final static byte op_dup2_x2 = 94; public final static byte op_swap = 95; public final static byte op_iadd = 96; public final static byte op_ladd = 97; public final static byte op_fadd = 98; public final static byte op_dadd = 99; public final static byte op_isub = 100; public final static byte op_lsub = 101; public final static byte op_fsub = 102; public final static byte op_dsub = 103; public final static byte op_imul = 104; public final static byte op_lmul = 105; public final static byte op_fmul = 106; public final static byte op_dmul = 107; public final static byte op_idiv = 108; public final static byte op_ldiv = 109; public final static byte op_fdiv = 110; public final static byte op_ddiv = 111; public final static byte op_irem = 112; public final static byte op_lrem = 113; public final static byte op_frem = 114; public final static byte op_drem = 115; public final static byte op_ineg = 116; public final static byte op_lneg = 117; public final static byte op_fneg = 118; public final static byte op_dneg = 119; public final static byte op_ishl = 120; public final static byte op_lshl = 121; public final static byte op_ishr = 122; public final static byte op_lshr = 123; public final static byte op_iushr = 124; public final static byte op_lushr = 125; public final static byte op_iand = 126; public final static byte op_land = 127; public final static byte op_ior = (byte) 128; public final static byte op_lor = (byte) 129; public final static byte op_ixor = (byte) 130; public final static byte op_lxor = (byte) 131; public final static byte op_iinc = (byte) 132; public final static byte op_i2l = (byte) 133; public final static byte op_i2f = (byte) 134; public final static byte op_i2d = (byte) 135; public final static byte op_l2i = (byte) 136; public final static byte op_l2f = (byte) 137; public final static byte op_l2d = (byte) 138; public final static byte op_f2i = (byte) 139; public final static byte op_f2l = (byte) 140; public final static byte op_f2d = (byte) 141; public final static byte op_d2i = (byte) 142; public final static byte op_d2l = (byte) 143; public final static byte op_d2f = (byte) 144; public final static byte op_i2b = (byte) 145; public final static byte op_i2c = (byte) 146; public final static byte op_i2s = (byte) 147; public final static byte op_lcmp = (byte) 148; public final static byte op_fcmpl = (byte) 149; public final static byte op_fcmpg = (byte) 150; public final static byte op_dcmpl = (byte) 151; public final static byte op_dcmpg = (byte) 152; public final static byte op_ifeq = (byte) 153; public final static byte op_ifne = (byte) 154; public final static byte op_iflt = (byte) 155; public final static byte op_ifge = (byte) 156; public final static byte op_ifgt = (byte) 157; public final static byte op_ifle = (byte) 158; public final static byte op_if_icmpeq = (byte) 159; public final static byte op_if_icmpne = (byte) 160; public final static byte op_if_icmplt = (byte) 161; public final static byte op_if_icmpge = (byte) 162; public final static byte op_if_icmpgt = (byte) 163; public final static byte op_if_icmple = (byte) 164; public final static byte op_if_acmpeq = (byte) 165; public final static byte op_if_acmpne = (byte) 166; public final static byte op_goto = (byte) 167; public final static byte op_jsr = (byte) 168; public final static byte op_ret = (byte) 169; public final static byte op_tableswitch = (byte) 170; public final static byte op_lookupswitch = (byte) 171; public final static byte op_ireturn = (byte) 172; public final static byte op_lreturn = (byte) 173; public final static byte op_freturn = (byte) 174; public final static byte op_dreturn = (byte) 175; public final static byte op_areturn = (byte) 176; public final static byte op_return = (byte) 177; public final static byte op_getstatic = (byte) 178; public final static byte op_putstatic = (byte) 179; public final static byte op_getfield = (byte) 180; public final static byte op_putfield = (byte) 181; public final static byte op_invokevirtual = (byte) 182; public final static byte op_invokespecial = (byte) 183; public final static byte op_invokestatic = (byte) 184; public final static byte op_invokeinterface = (byte) 185; public final static byte op_new = (byte) 187; public final static byte op_newarray = (byte) 188; public final static byte op_anewarray = (byte) 189; public final static byte op_arraylength = (byte) 190; public final static byte op_athrow = (byte) 191; public final static byte op_checkcast = (byte) 192; public final static byte op_instanceof = (byte) 193; public final static byte op_monitorenter = (byte) 194; public final static byte op_monitorexit = (byte) 195; public final static byte op_wide = (byte) 196; public final static byte op_multianewarray = (byte) 197; public final static byte op_ifnull = (byte) 198; public final static byte op_ifnonnull = (byte) 199; public final static byte op_goto_w = (byte) 200; public final static byte op_jsr_w = (byte) 201; public final static byte op_breakpoint = (byte) 202; public final static byte op_ldc_quick = (byte) 203; public final static byte op_ldc_w_quick = (byte) 204; public final static byte op_ldc2_w_quick = (byte) 205; public final static byte op_getfield_quick = (byte) 206; public final static byte op_putfield_quick = (byte) 207; public final static byte op_getfield2_quick = (byte) 208; public final static byte op_putfield2_quick = (byte) 209; public final static byte op_getstatic_quick = (byte) 210; public final static byte op_putstatic_quick = (byte) 211; public final static byte op_getstatic2_quick = (byte) 212; public final static byte op_putstatic2_quick = (byte) 213; public final static byte op_invokevirtual_quick = (byte) 214; public final static byte op_invokenonvirtual_quick = (byte) 215; public final static byte op_invokesuper_quick = (byte) 216; public final static byte op_invokestatic_quick = (byte) 217; public final static byte op_invokeinterface_quick = (byte) 218; public final static byte op_invokevirtualobject_quick = (byte) 219; public final static byte op_new_quick = (byte) 221; public final static byte op_anewarray_quick = (byte) 222; public final static byte op_multianewarray_quick = (byte) 223; public final static byte op_checkcast_quick = (byte) 224; public final static byte op_instanceof_quick = (byte) 225; public final static byte op_invokevirtual_quick_w = (byte) 226; public final static byte op_getfield_quick_w = (byte) 227; public final static byte op_putfield_quick_w = (byte) 228; public final static byte op_impdep1 = (byte) 254; public final static byte op_impdep2 = (byte) 255; } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/ParentContext.java0000755000175100017510000000177011130400365026222 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; interface ParentContext extends CodeContext { public void promoteOutstandingReference(OutstandingReference ref); public void writeShortAt(int pos, int i); public int getOffset(); public int resolveLocalNoCreate(LocalVariable lv); public void setMaxLocals(int m); public int getUsedLocals(); public void addExceptionTableEntry(ExceptionMemento em); } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/LocalVariable.java0000755000175100017510000000525611130400365026127 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * A local variable. * *

* Local variables are used as identifiers for things that can be stored and * loaded from the local variable slots associated with each method. By using * LocalVariable intances, you are removed from the taudry task of book-keeping * these slots. *

* *

* To use a local variable, create an intance and then use it in a code * generator. The method will keep track of which local variables are in scope, * and will handle all the nastiness for you. You can re-use the same * local variable instance in different contexts, and it will be sanely * allocated different or the same slots. *

* *

* The JVM stores some things in single words, and others in pairs of words. * To hide this detail from you, local variables take a class that indicates * the type of thing they will store. Please populate this sensibly. *

* * @author Thomas Down * @author Matthew Pocock */ public final class LocalVariable { private final String name; private final CodeClass clazz; /** * Create a new local variable that will store values of a given type. * * @param clazz the type of the values stored in this variable */ public LocalVariable(CodeClass clazz) { this.clazz = clazz; this.name = null; } /** * Create a new local variable with a type and a name. * *

* The name may appear in debug output from the generator, and possibly in * stack-traces. *

* * @param clazz the type of the values stored in this variable * @param name the name of the variable */ public LocalVariable(CodeClass clazz, String name) { this.clazz = clazz; this.name = name; } public String getName() { return name; } public int needSlots() { return (clazz == CodeUtils.TYPE_LONG || clazz == CodeUtils.TYPE_DOUBLE) ? 2 : 1; } public CodeClass getType() { return clazz; } public String toString() { return super.toString() + "[slots: " + needSlots() + ", name: " + name + ", class: " + clazz + "]"; } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/CodeGenerator.java0000755000175100017510000000362111130400365026142 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Interface for an object which can produce Java bytecode. * * @author Thomas Down * @author Matthew Pocock */ public interface CodeGenerator { /** * Write the byte or bytes for this CodeGenerator to a CodeContext. * * @param ctx a CodeContext to write to * @throws CodeException if there was some failure in writing to the context */ public void writeCode(CodeContext ctx) throws CodeException; /** * Return the total depth of the stack required by this CodeGenerator. * *

For single byte-code instructions, this will be the same as * stackDelta() if stackDelta() is positive, zero otherwise. For a * compound instruction, this will be the maximum stack depth required to * execute all sub-instructions.

* * @return the stack depth needed */ public int stackDepth(); /** * Return the change in the stack dept this generator will cause. * *

In the case of an instruction that adds items to the stack, stackDelta * will be positive. For instructions that removes items from the stack, * this will be negative.

* * @return the change between stack depth before and after execution of this * code */ public int stackDelta(); } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/LocalVariableInstruction.java0000755000175100017510000000321311130400365030360 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Instructions which load or store to a local variable. * * @author Thomas Down * @author Matthew Pocock */ class LocalVariableInstruction implements Instruction { private final LocalVariable var; private final byte opcode; private final byte specialOpCodeBase; LocalVariableInstruction(byte op, byte special, LocalVariable var) { if(var == null) { throw new NullPointerException("LocalVariable can not be null"); } this.opcode = op; specialOpCodeBase = special; this.var = var; } public void writeCode(CodeContext ctx) throws CodeException { int slot = ctx.resolveLocal(var); if (slot <= 3) { ctx.writeByte((byte) (specialOpCodeBase + slot)); } else if (slot < 256) { ctx.writeByte(opcode); ctx.writeByte((byte) slot); } else { ctx.writeByte(ByteCode.op_wide); ctx.writeByte(opcode); ctx.writeShort(slot); } } public int stackDepth() { return stackDelta(); } public int stackDelta() { return 1; } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/SimpleReference.java0000755000175100017510000000203411130400365026466 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; class SimpleReference implements OutstandingReference { private final Label label; private int offset = -1; public SimpleReference(Label l) { this.label = l; } public Label getLabel() { return label; } public void resolve(int offset) { this.offset = offset; } public int getOffset() { return offset; } public boolean isResolved() { return (offset >= 0); } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/BranchFixup.java0000755000175100017510000000225611130400365025635 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Encapsulate a refererence to a Label which has not been resolved. * * @author Thomas Down */ class BranchFixup implements OutstandingReference { private final Label label; private final int branchSource; private final ParentContext cc; public BranchFixup(Label l, int bs, ParentContext cc) { this.label = l; this.branchSource = bs; this.cc = cc; } public Label getLabel() { return label; } public void resolve(int offset) throws CodeException { cc.writeShortAt(branchSource, offset - branchSource + 1); } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/StringConstantInstruction.java0000755000175100017510000000264711130400365030652 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Instructions which load or store to a local variable. * * @author Thomas Down * @author Matthew Pocock */ class StringConstantInstruction implements Instruction { private final String s; StringConstantInstruction(String s) { if(s == null) { throw new NullPointerException("Can't make a StringConstantInstruction for a null string"); } this.s = s; } public void writeCode(CodeContext ctx) throws CodeException { int i_indx = ctx.getConstants().resolveString(s); if (i_indx < 256) { ctx.writeByte(ByteCode.op_ldc); ctx.writeByte((byte) i_indx); } else { ctx.writeByte(ByteCode.op_ldc_w); ctx.writeShort(i_indx); } } public int stackDepth() { return stackDelta(); } public int stackDelta() { return 1; } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/LongConstantInstruction.java0000755000175100017510000000224011130400365030270 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Instructions which retrieve a long from the constant pool. * * @author Thomas Down * @author Matthew Pocock */ class LongConstantInstruction implements Instruction { private final long val; LongConstantInstruction(long val) { this.val = val; } public void writeCode(CodeContext ctx) throws CodeException { ctx.writeByte(ByteCode.op_ldc2_w); ctx.writeShort(ctx.getConstants().resolveLong(val)); } public int stackDepth() { return stackDelta(); } public int stackDelta() { return 1; } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/ConstantPool.java0000755000175100017510000002120111130400365026036 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; import java.util.*; import java.io.*; /** * Build a Java class file constant pool. * * @author Thomas Down * @author Matthew Pocock */ public class ConstantPool { private static final byte CONSTANT_Class = 7; private static final byte CONSTANT_Fieldref = 9; private static final byte CONSTANT_Methodref = 10; private static final byte CONSTANT_InterfaceMethodref = 11; private static final byte CONSTANT_String = 8; private static final byte CONSTANT_Integer = 3; private static final byte CONSTANT_Float = 4; private static final byte CONSTANT_Long = 5; private static final byte CONSTANT_Double = 6; private static final byte CONSTANT_NameAndType = 12; private static final byte CONSTANT_Utf8 = 1; private List constants; { constants = new ArrayList(); constants.add(null); // Initial padder. } // Publically visible constant types public int resolveClass(CodeClass c) { return resolve(new CPTypedStringEntry(CONSTANT_Class, resolveUtf8(c.getJName()))); } public int resolveField(CodeField f) { try { return resolve(new CPRefEntry(CONSTANT_Fieldref, resolveClass(f.getContainingClass()), resolveNameAndType(f.getName(), f.getType().getDescriptor()))); } catch (NullPointerException npe) { throw new Error("Can't resolve filed " + f); } } public int resolveMethod(CodeMethod m) { return resolve(new CPRefEntry(CONSTANT_Methodref, resolveClass(m.getContainingClass()), resolveNameAndType(m.getName(), m.getDescriptor()))); } public int resolveInterfaceMethod(CodeMethod m) { return resolve(new CPRefEntry(CONSTANT_InterfaceMethodref, resolveClass(m.getContainingClass()), resolveNameAndType(m.getName(), m.getDescriptor()))); } public int resolveString(String s) { return resolve(new CPTypedStringEntry(CONSTANT_String, resolveUtf8(s))); } public int resolveInt(int i) { return resolve(new CPIntEntry(i)); } public int resolveFloat(float f) { return resolve(new CPFloatEntry(f)); } public int resolveLong(long l) { return resolve(new CPLongEntry(l)); } public int resolveDouble(double d) { return resolve(new CPDoubleEntry(d)); } // internal resolvers public int resolveUtf8(String s) { return resolve(new CPUtf8Entry(s)); } public int resolveNameAndType(String name, String desc) { return resolve(new CPNameAndTypeEntry(resolveUtf8(name), resolveUtf8(desc))); } // The master resolver private int resolve(CPEntry e) { for (int i = 1; i < constants.size(); ++i) { CPEntry e2 = (CPEntry) constants.get(i); if (e2 != null && e.equals(e2)) return i; } int i = constants.size(); constants.add(e); for (int k = 1; k < e.needSlots(); ++k) constants.add(null); return i; } // Output again public int constantPoolSize() { return constants.size(); } public void writeConstantPool(DataOutput d) throws IOException { // int count = 1; for (Iterator i = constants.iterator(); i.hasNext(); ) { CPEntry e = (CPEntry) i.next(); if (e != null) { // System.out.println("Writing constant " + count + " " + e); // count += e.needSlots(); e.write(d); } } } // Types for storing the cpool private static interface CPEntry { public void write(DataOutput d) throws IOException; public int needSlots(); } private static class CPTypedStringEntry implements CPEntry { byte tag; int name; CPTypedStringEntry(byte tag, int name) { this.tag = tag; this.name = name; } public boolean equals(Object o) { if (! (o instanceof CPTypedStringEntry)) return false; CPTypedStringEntry cte = (CPTypedStringEntry) o; return (cte.name == name && cte.tag == tag); } public void write(DataOutput d) throws IOException { d.writeByte(tag); d.writeShort(name); } public int needSlots() { return 1; } public String toString() { return "CPTypedStringEntry tag=" + tag + " name=" + name; } } private static class CPRefEntry implements CPEntry { byte tag; int clazz; int name; CPRefEntry(byte tag, int clazz, int name) { this.tag = tag; this.clazz = clazz; this.name = name; } public boolean equals(Object o) { if (! (o instanceof CPRefEntry)) return false; CPRefEntry cte = (CPRefEntry) o; return (cte.clazz == clazz && cte.name == name && cte.tag == tag); } public void write(DataOutput d) throws IOException { d.writeByte(tag); d.writeShort(clazz); d.writeShort(name); } public int needSlots() { return 1; } public String toString() { return "CPRefEntry tag=" + tag + " class=" + clazz + " name=" + name; } } private static class CPIntEntry implements CPEntry { int val; CPIntEntry(int val) { this.val = val; } public boolean equals(Object o) { if (! (o instanceof CPIntEntry)) return false; return (((CPIntEntry) o).val == val); } public void write(DataOutput d) throws IOException { d.writeByte(CONSTANT_Integer); d.writeInt(val); } public int needSlots() { return 1; } public String toString() { return "CPIntEntry val=" + val; } } private static class CPLongEntry implements CPEntry { long val; CPLongEntry(long val) { this.val = val; } public boolean equals(Object o) { if (! (o instanceof CPLongEntry)) return false; return (((CPLongEntry) o).val == val); } public void write(DataOutput d) throws IOException { d.writeByte(CONSTANT_Long); d.writeLong(val); } public int needSlots() { return 2; } public String toString() { return "CPLongEntry val=" + val; } } private static class CPFloatEntry implements CPEntry { float val; CPFloatEntry(float val) { this.val = val; } public boolean equals(Object o) { if (! (o instanceof CPFloatEntry)) return false; return (((CPFloatEntry) o).val == val) || (Float.isNaN(((CPFloatEntry) o).val) && Float.isNaN(val)); } public void write(DataOutput d) throws IOException { d.writeByte(CONSTANT_Float); d.writeFloat(val); } public int needSlots() { return 1; } public String toString() { return "CPFloatEntry val=" + val; } } private static class CPDoubleEntry implements CPEntry { double val; CPDoubleEntry(double val) { this.val = val; } public boolean equals(Object o) { if (! (o instanceof CPDoubleEntry)) return false; return (((CPDoubleEntry) o).val == val) || (Double.isNaN(((CPDoubleEntry) o).val) && Double.isNaN(val)); } public void write(DataOutput d) throws IOException { d.writeByte(CONSTANT_Double); d.writeDouble(val); } public int needSlots() { return 2; } public String toString() { return "CPDoubleEntry val=" + val; } } private static class CPUtf8Entry implements CPEntry { String val; CPUtf8Entry(String val) { this.val = val; } public boolean equals(Object o) { if (! (o instanceof CPUtf8Entry)) return false; return (((CPUtf8Entry) o).val.equals(val)); } public void write(DataOutput d) throws IOException { d.writeByte(CONSTANT_Utf8); d.writeUTF(val); } public int needSlots() { return 1; } public String toString() { return "CPUtf8Entry val=" + val; } } private static class CPNameAndTypeEntry implements CPEntry { int name; int desc; CPNameAndTypeEntry(int name, int desc) { this.name = name; this.desc = desc; } public boolean equals(Object o) { if (! (o instanceof CPNameAndTypeEntry)) return false; CPNameAndTypeEntry cpnte = (CPNameAndTypeEntry) o; return (cpnte.desc == desc && cpnte.name == name); } public void write(DataOutput d) throws IOException { d.writeByte(CONSTANT_NameAndType); d.writeShort(name); d.writeShort(desc); } public int needSlots() { return 1; } public String toString() { return "CPNameAndTypeEntry name=" + name + " desc=" + desc; } } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/GeneratedClassLoader.java0000755000175100017510000000431311130400365027433 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; import java.io.*; import java.util.*; /** * A class loader that actually produces real Java classes from * GeneratedCodeClass instances. * * @author Thomas Down * @author Matthew Pocock */ public class GeneratedClassLoader extends ClassLoader { private Set generatedClasses = new HashSet(); /** * Create a new loader with the default parent. */ public GeneratedClassLoader() { super(); } /** * Create a new loader with an explicitly set parent class loader. * * @param parent the parent ClassLoader */ public GeneratedClassLoader(ClassLoader parent) { super(parent); } /** * Define a class based upon a GeneratedCodeClass. * * @param cc the GeneratedCodeClass to define * @return the newly defined class * @throws CodeException if there was a failure defining the class */ public Class defineClass(GeneratedCodeClass cc) throws CodeException { try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); cc.createCode(bos); byte[] code = bos.toByteArray(); Class clazz = defineClass(cc.getName(), code, 0, code.length); generatedClasses.add(clazz.getName()); return clazz; } catch (IOException ex) { // Seems unlikely... throw new CodeException(); } } /** * Discover if a class for this name has already been defined by this class * loader. * * @param name the name of the class * @return true if the class has already been defined by this loader */ public boolean hasGeneratedClass(String name) { return generatedClasses.contains(name); } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/DoubleInstruction.java0000755000175100017510000000217611130400365027101 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Instructions which retrieve a double from the constant pool. * * @author Matthew Pocock */ class DoubleInstruction implements Instruction { private double val; DoubleInstruction(double val) { this.val = val; } public void writeCode(CodeContext ctx) throws CodeException { ctx.writeByte(ByteCode.op_ldc2_w); ctx.writeShort(ctx.getConstants().resolveDouble(val)); } public int stackDepth() { return stackDelta(); } public int stackDelta() { return 1; } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/IfExpression.java0000755000175100017510000000515611130400365026044 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; import java.util.*; /** * A CodeGenerator that provides something semanticaly identical to if. *

* It generates code of the form: *

* conditional branch to trueLabel
* ifFalse instructions here
* branch to endLabel
* trueLabel
* ifTrue instructions here
* endLabel * * * @author Matthew Pocock */ public class IfExpression implements CodeGenerator { private Instruction ifInstruction; private CodeGenerator ifTrue; private CodeGenerator ifFalse; private Label trueLabel; private Label endLabel; private Instruction skipTrue; private InstructionVector instructions; public IfExpression( byte ifInstruction, CodeGenerator ifTrue, CodeGenerator ifFalse ) { this.trueLabel = new Label(); this.endLabel = new Label(); this.skipTrue = ByteCode.make_goto(endLabel); this.ifInstruction = ByteCode.make_if(ifInstruction, trueLabel); this.ifTrue = ifTrue; this.ifFalse = ifFalse; // lazyness - avoid work later instructions = new InstructionVector(); instructions.add(this.ifInstruction); instructions.add(this.ifFalse); instructions.add(this.skipTrue); instructions.add(ByteCode.make_markLabel(trueLabel)); instructions.add(this.ifTrue); instructions.add(ByteCode.make_markLabel(endLabel)); } public Instruction getIfInstruction() { return ifInstruction; } public CodeGenerator getIfTrue() { return ifTrue; } public CodeGenerator getIfFalse() { return ifFalse; } public void writeCode(CodeContext ctx) throws CodeException { instructions.writeCode(ctx); } public int stackDepth() { // custom handlers needed because of jumps return ifInstruction.stackDepth() + Math.max(ifFalse.stackDepth(), ifTrue.stackDepth()); } public int stackDelta() { // custom handler needed because of jumps return ifInstruction.stackDepth() + Math.max(ifFalse.stackDepth(), ifTrue.stackDepth()); // these should agree } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/CodeField.java0000755000175100017510000000415111130400365025236 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Wrap up details about a field in a Java class file. * *

* Instances of this type will be instantiated by CodeClass instances, using * the getField() methods. *

* * @author Thomas Down * @author Matthew Pocock */ public final class CodeField { private final String name; private final CodeClass clazz; private final int modifiers; private final CodeClass container; CodeField(CodeClass container, String name, CodeClass clazz, int mods) { this.container = container; this.name = name; this.clazz = clazz; this.modifiers = mods; } /** * Get the name of the field. * * @return the name of the field */ public String getName() { return name; } /** * Get the fully qualified name of the field. * * @return the fully qualified name */ public String getFullName() { return container.getName() + "." + getName(); } /** * Get the class that contains this field. * * @return the containing class */ public CodeClass getContainingClass() { return container; } /** * Get the type of the field. * * @return */ public CodeClass getType() { return clazz; } /** * Get the moddifiers applied to this field. * * @return the modifiers */ public int getModifiers() { return modifiers; } public String toString() { return super.toString() + " type: " + getType() + " class: " + clazz.getName() + " name: " + getName(); } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/ExceptionMemento.java0000755000175100017510000000226511130400365026707 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; class ExceptionMemento { SimpleReference startHandled; SimpleReference endHandled; CodeClass eClass; SimpleReference handler; public ExceptionMemento(SimpleReference startHandled, SimpleReference endHandled, CodeClass eClass, SimpleReference handler) { this.startHandled = startHandled; this.endHandled = endHandled; this.eClass = eClass; this.handler = handler; } public boolean isFullyResolved() { return startHandled.isResolved() && endHandled.isResolved() && handler.isResolved(); } } bytecode-0.92.svn.20090106/src/org/biojava/utils/bytecode/OutstandingReference.java0000755000175100017510000000153611130400365027542 0ustar moellermoeller/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.utils.bytecode; /** * Encapsulate a refererence to a Label which has not been resolved. * * @author Thomas Down */ interface OutstandingReference { public Label getLabel(); public void resolve(int offset) throws CodeException; } bytecode-0.92.svn.20090106/opcodes.txt0000755000175100017510000000614407165150173017043 0ustar moellermoeller0 nop 0 1 aconst_null 0 2 iconst_m1 0 3 iconst_0 0 4 iconst_1 0 5 iconst_2 0 6 iconst_3 0 7 iconst_4 0 8 iconst_5 0 9 lconst_0 0 10 lconst_1 0 11 fconst_0 0 12 fconst_1 0 13 fconst_2 0 14 dconst_0 0 15 dconst_1 0 16 bipush 1 17 sipush 2 18 ldc 1 19 ldc_w 2 20 ldc2_w 2 21 iload 1 22 lload 1 23 fload 1 24 dload 1 25 aload 1 26 iload_0 0 27 iload_1 0 28 iload_2 0 29 iload_3 0 30 lload_0 0 31 lload_1 0 32 lload_2 0 33 lload_3 0 34 fload_0 0 35 fload_1 0 36 fload_2 0 37 fload_3 0 38 dload_0 0 39 dload_1 0 40 dload_2 0 41 dload_3 0 42 aload_0 0 43 aload_1 0 44 aload_2 0 45 aload_3 0 46 iaload 0 47 laload 0 48 faload 0 49 daload 0 50 aaload 0 51 baload 0 52 caload 0 53 saload 0 54 istore 1 55 lstore 1 56 fstore 1 57 dstore 1 58 astore 1 59 istore_0 0 60 istore_1 0 61 istore_2 0 62 istore_3 0 63 lstore_0 0 64 lstore_1 0 65 lstore_2 0 66 lstore_3 0 67 fstore_0 0 68 fstore_1 0 69 fstore_2 0 70 fstore_3 0 71 dstore_0 0 72 dstore_1 0 73 dstore_2 0 74 dstore_3 0 75 astore_0 0 76 astore_1 0 77 astore_2 0 78 astore_3 0 79 iastore 0 80 lastore 0 81 fastore 0 82 dastore 0 83 aastore 0 84 bastore 0 85 castore 0 86 sastore 0 87 pop 0 88 pop2 0 89 dup 0 90 dup_x1 0 91 dup_x2 0 92 dup2 0 93 dup2_x1 0 94 dup2_x2 0 95 swap 0 96 iadd 0 97 ladd 0 98 fadd 0 99 dadd 0 100 isub 0 101 lsub 0 102 fsub 0 103 dsub 0 104 imul 0 105 lmul 0 106 fmul 0 107 dmul 0 108 idiv 0 109 ldiv 0 110 fdiv 0 111 ddiv 0 112 irem 0 113 lrem 0 114 frem 0 115 drem 0 116 ineg 0 117 lneg 0 118 fneg 0 119 dneg 0 120 ishl 0 121 lshl 0 122 ishr 0 123 lshr 0 124 iushr 0 125 lushr 0 126 iand 0 127 land 0 128 ior 0 129 lor 0 130 ixor 0 131 lxor 0 132 iinc 2 133 i2l 0 134 i2f 0 135 i2d 0 136 l2i 0 137 l2f 0 138 l2d 0 139 f2i 0 140 f2l 0 141 f2d 0 142 d2i 0 143 d2l 0 144 d2f 0 145 i2b 0 146 i2c 0 147 i2s 0 148 lcmp 0 149 fcmpl 0 150 fcmpg 0 151 dcmpl 0 152 dcmpg 0 153 ifeq 2 154 ifne 2 155 iflt 2 156 ifge 2 157 ifgt 2 158 ifle 2 159 if_icmpeq 2 160 if_icmpne 2 161 if_icmplt 2 162 if_icmpge 2 163 if_icmpgt 2 164 if_icmple 2 165 if_acmpeq 2 166 if_acmpne 2 167 goto 2 168 jsr 2 169 ret 1 170 tableswitch - 171 lookupswitch - 172 ireturn 0 173 lreturn 0 174 freturn 0 175 dreturn 0 176 areturn 0 177 return 0 178 getstatic 2 179 putstatic 2 180 getfield 2 181 putfield 2 182 invokevirtual 2 183 invokespecial 2 184 invokestatic 2 185 invokeinterface 2 187 new 2 188 newarray 1 189 anewarray 2 190 arraylength 0 191 athrow 0 192 checkcast 2 193 instanceof 2 194 monitorenter 0 195 monitorexit 0 196 wide 0 197 multianewarray 3 198 ifnull 2 199 ifnonnull 2 200 goto_w 4 201 jsr_w 4 202 breakpoint 0 203 ldc_quick 1 204 ldc_w_quick 2 205 ldc2_w_quick 2 206 getfield_quick 2 207 putfield_quick 2 208 getfield2_quick 2 209 putfield2_quick 2 210 getstatic_quick 2 211 putstatic_quick 2 212 getstatic2_quick 2 213 putstatic2_quick 2 214 invokevirtual_quick 2 215 invokenonvirtual_quick 2 216 invokesuper_quick 2 217 invokestatic_quick 2 218 invokeinterface_quick 2 219 invokevirtualobject_quick 2 221 new_quick 2 222 anewarray_quick 2 223 multianewarray_quick 3 224 checkcast_quick 2 225 instanceof_quick 2 226 invokevirtual_quick_w 0 227 getfield_quick_w 2 228 putfield_quick_w 2 254 impdep1 0 255 impdep2 0 bytecode-0.92.svn.20090106/build.xml0000755000175100017510000002765007702313734016475 0ustar moellermoeller