Author: tcurdt Date: Mon Jul 4 02:01:47 2005 New Revision: 209036 URL: http://svn.apache.org/viewcvs?rev=209036&view=rev Log: first steps of an ASM based implementation
Added: jakarta/commons/sandbox/javaflow/trunk/lib/asm-20050703.234510.jar (with props) jakarta/commons/sandbox/javaflow/trunk/lib/asm-analysis-20050703.234510.jar (with props) jakarta/commons/sandbox/javaflow/trunk/lib/asm-attrs-20050703.234510.jar (with props) jakarta/commons/sandbox/javaflow/trunk/lib/asm-common-20050703.234510.jar (with props) jakarta/commons/sandbox/javaflow/trunk/lib/asm-tree-20050703.234510.jar (with props) jakarta/commons/sandbox/javaflow/trunk/lib/asm-util-20050703.234510.jar (with props) jakarta/commons/sandbox/javaflow/trunk/lib/asm-xml-20050703.234510.jar (with props) jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/BytecodeClassLoader.java jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/testcode/Test.java Modified: jakarta/commons/sandbox/javaflow/trunk/project.properties jakarta/commons/sandbox/javaflow/trunk/project.xml jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/Continuation.java jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/Stack.java jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/asm/AsmClassTransformer.java Added: jakarta/commons/sandbox/javaflow/trunk/lib/asm-20050703.234510.jar URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/lib/asm-20050703.234510.jar?rev=209036&view=auto ============================================================================== Binary file - no diff available. Propchange: jakarta/commons/sandbox/javaflow/trunk/lib/asm-20050703.234510.jar ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: jakarta/commons/sandbox/javaflow/trunk/lib/asm-analysis-20050703.234510.jar URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/lib/asm-analysis-20050703.234510.jar?rev=209036&view=auto ============================================================================== Binary file - no diff available. Propchange: jakarta/commons/sandbox/javaflow/trunk/lib/asm-analysis-20050703.234510.jar ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: jakarta/commons/sandbox/javaflow/trunk/lib/asm-attrs-20050703.234510.jar URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/lib/asm-attrs-20050703.234510.jar?rev=209036&view=auto ============================================================================== Binary file - no diff available. Propchange: jakarta/commons/sandbox/javaflow/trunk/lib/asm-attrs-20050703.234510.jar ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: jakarta/commons/sandbox/javaflow/trunk/lib/asm-common-20050703.234510.jar URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/lib/asm-common-20050703.234510.jar?rev=209036&view=auto ============================================================================== Binary file - no diff available. Propchange: jakarta/commons/sandbox/javaflow/trunk/lib/asm-common-20050703.234510.jar ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: jakarta/commons/sandbox/javaflow/trunk/lib/asm-tree-20050703.234510.jar URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/lib/asm-tree-20050703.234510.jar?rev=209036&view=auto ============================================================================== Binary file - no diff available. Propchange: jakarta/commons/sandbox/javaflow/trunk/lib/asm-tree-20050703.234510.jar ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: jakarta/commons/sandbox/javaflow/trunk/lib/asm-util-20050703.234510.jar URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/lib/asm-util-20050703.234510.jar?rev=209036&view=auto ============================================================================== Binary file - no diff available. Propchange: jakarta/commons/sandbox/javaflow/trunk/lib/asm-util-20050703.234510.jar ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: jakarta/commons/sandbox/javaflow/trunk/lib/asm-xml-20050703.234510.jar URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/lib/asm-xml-20050703.234510.jar?rev=209036&view=auto ============================================================================== Binary file - no diff available. Propchange: jakarta/commons/sandbox/javaflow/trunk/lib/asm-xml-20050703.234510.jar ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Modified: jakarta/commons/sandbox/javaflow/trunk/project.properties URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/project.properties?rev=209036&r1=209035&r2=209036&view=diff ============================================================================== --- jakarta/commons/sandbox/javaflow/trunk/project.properties (original) +++ jakarta/commons/sandbox/javaflow/trunk/project.properties Mon Jul 4 02:01:47 2005 @@ -34,8 +34,12 @@ # ------------------------------------------------------------------------ # Jars set explicity by path. # ------------------------------------------------------------------------ -maven.jar.commons-jci = ${basedir}/lib/commons-jci-r159148.jar -maven.jar.bcel = ${basedir}/lib/jakarta-bcel-20040329.jar +maven.jar.commons-jci = lib/commons-jci-r159148.jar +maven.jar.bcel = lib/jakarta-bcel-20040329.jar maven.jar.commons-io = lib/commons-io-20050621.133116.jar -maven.jar.asm = lib/asm-2.0.jar -maven.jar.asm-tree = lib/asm-tree-2.0.jar +maven.jar.asm = lib/asm-20050703.234510.jar +maven.jar.asm-tree = lib/asm-tree-20050703.234510.jar +maven.jar.asm-analysis = lib/asm-analysis-20050703.234510.jar +maven.jar.asm-common = lib/asm-common-20050703.234510.jar +maven.jar.asm-util = lib/asm-util-20050703.234510.jar + Modified: jakarta/commons/sandbox/javaflow/trunk/project.xml URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/project.xml?rev=209036&r1=209035&r2=209036&view=diff ============================================================================== --- jakarta/commons/sandbox/javaflow/trunk/project.xml (original) +++ jakarta/commons/sandbox/javaflow/trunk/project.xml Mon Jul 4 02:01:47 2005 @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <project> <!-- - <extend>../commons-build/sandbox-project.xml</extend> --> + <extend>../commons-build/sandbox-project.xml</extend> <pomVersion>1</pomVersion> <artifactId>commons-javaflow</artifactId> <name>Commons Javaflow</name> @@ -88,13 +88,36 @@ <dependency> <groupId>asm</groupId> <artifactId>asm</artifactId> - <version>2.0</version> + <jar>${basedir}/lib/asm-20050703.234510.jar</jar> + <version>SNAPSHOT</version> <type>jar</type> </dependency> <dependency> <groupId>asm</groupId> <artifactId>asm-tree</artifactId> - <version>2.0</version> + <jar>${basedir}/lib/asm-tree-20050703.234510.jar</jar> + <version>SNAPSHOT</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>asm</groupId> + <artifactId>asm-analysis</artifactId> + <jar>${basedir}/lib/asm-analysis-20050703.234510.jar</jar> + <version>SNAPSHOT</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>asm</groupId> + <artifactId>asm-common</artifactId> + <jar>${basedir}/lib/asm-common-20050703.234510.jar</jar> + <version>SNAPSHOT</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>asm</groupId> + <artifactId>asm-util</artifactId> + <jar>${basedir}/lib/asm-util-20050703.234510.jar</jar> + <version>SNAPSHOT</version> <type>jar</type> </dependency> </dependencies> Modified: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/Continuation.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/Continuation.java?rev=209036&r1=209035&r2=209036&view=diff ============================================================================== --- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/Continuation.java (original) +++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/Continuation.java Mon Jul 4 02:01:47 2005 @@ -141,7 +141,9 @@ log.error("could not execute " + continuation, e); } finally { if (continuation.capturing) { - continuation.stack.popReference(); + if (continuation.stack.hasReference()) { + continuation.stack.popReference(); + } } continuation.context = null; @@ -160,9 +162,10 @@ final Continuation continuation = Continuation.currentContinuation(); - if (continuation == null) + if (continuation == null) { throw new IllegalStateException("no continuation is running"); - + } + continuation.capturing = !continuation.restoring; continuation.restoring = false; Added: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/BytecodeClassLoader.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/BytecodeClassLoader.java?rev=209036&view=auto ============================================================================== --- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/BytecodeClassLoader.java (added) +++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/BytecodeClassLoader.java Mon Jul 4 02:01:47 2005 @@ -0,0 +1,39 @@ +package org.apache.commons.javaflow.bytecode; + +import org.objectweb.asm.ClassAdapter; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.commons.EmptyVisitor; + + +public final class BytecodeClassLoader extends ClassLoader { + + class NameClassAdapter extends ClassAdapter { + private String className; + + public NameClassAdapter() { + super(new EmptyVisitor()); + } + + public void visit( int version, int access, String name, String signature, String superName, String[] interfaces ) { + className = name; + } + + public String getName() { + return className; + } + } + + public Class loadClass( final byte[] bytecode ) { + final NameClassAdapter nameClassAdapter = new NameClassAdapter(); + + new ClassReader(bytecode).accept(nameClassAdapter, false); + + final String name = nameClassAdapter.getName().replace('/', '.'); + + System.out.println("loading class " + name); + + final Class clazz = defineClass(name, bytecode, 0, bytecode.length); + + return clazz; + } +} Modified: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/Stack.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/Stack.java?rev=209036&r1=209035&r2=209036&view=diff ============================================================================== --- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/Stack.java (original) +++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/Stack.java Mon Jul 4 02:01:47 2005 @@ -71,6 +71,10 @@ rTop = parent.rTop; } + public boolean hasDouble() { + return dTop > 0; + } + public double popDouble() { if (dTop==0) { throw new EmptyStackException("pop double"); @@ -81,6 +85,10 @@ return d; } + public boolean hasFloat() { + return fTop > 0; + } + public float popFloat() { if (fTop==0) { throw new EmptyStackException("pop float"); @@ -91,6 +99,10 @@ return f; } + public boolean hasInt() { + return iTop > 0; + } + public int popInt() { if (iTop==0) { throw new EmptyStackException("pop int"); @@ -101,6 +113,10 @@ return i; } + public boolean hasLong() { + return lTop > 0; + } + public long popLong() { if (lTop==0) { throw new EmptyStackException("pop long"); @@ -111,6 +127,10 @@ return l; } + public boolean hasObject() { + return oTop > 0; + } + public Object popObject() { if (oTop==0) { throw new EmptyStackException("pop object"); @@ -124,6 +144,10 @@ log.debug("pop object "+ clazz + "/" + clazzLoader + " [" + o + "] " + toString()); return o; + } + + public boolean hasReference() { + return rTop > 0; } public Object popReference() { Modified: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/asm/AsmClassTransformer.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/asm/AsmClassTransformer.java?rev=209036&r1=209035&r2=209036&view=diff ============================================================================== --- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/asm/AsmClassTransformer.java (original) +++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/asm/AsmClassTransformer.java Mon Jul 4 02:01:47 2005 @@ -15,35 +15,230 @@ */ package org.apache.commons.javaflow.bytecode.asm; +import java.util.ArrayList; +import java.util.Collection; +import org.apache.commons.io.IOUtils; +import org.apache.commons.javaflow.bytecode.BytecodeClassLoader; import org.apache.commons.javaflow.bytecode.ClassTransformer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.objectweb.asm.ClassAdapter; import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.tree.ClassNode; - +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodAdapter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.analysis.Analyzer; +import org.objectweb.asm.tree.analysis.BasicVerifier; +import org.objectweb.asm.tree.analysis.Frame; /** * @author tcurdt - * */ public final class AsmClassTransformer implements ClassTransformer { private final static Log log = LogFactory.getLog(AsmClassTransformer.class); - public byte[] transform(final byte[] original) { + class MyClassAdapter extends ClassAdapter { - final ClassReader cr = new ClassReader(original); - final ClassNode cn = new ClassNode(); - - cr.accept(cn, true); + private String className; + + public MyClassAdapter(ClassVisitor cv) { + super(cv); + } + + + public void visit( int version, int access, String name, String signature, String superName, String[] interfaces ) { + cv.visit(version, access, name, signature, superName, interfaces); + className = name; + } + + + public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions ) { + // return a MethodNode so that the visited method will be stored as + // a tree + // (instead of being transformed on the fly and passed directly to + // the next visitor in the chain) + + if (inScope(className, name) && "main".equals(name)) { + return new MethodNode(access, name, desc, signature, exceptions) { + + private Collection labels = new ArrayList(); + + public void visitMethodInsn( int opcode, String owner, String name, String desc ) { + + if (needsFrameGuard(opcode, owner, name, desc) && inScope(owner, name)) { + System.out.println("creating label for " + owner + "." + name); + + final Label label = new Label(); + super.visitLabel(label); + labels.add(label); + } + + super.visitMethodInsn(opcode, owner, name, desc); + } + + public void visitEnd() { + // once the MethodNode is complete, compute the frames + final Frame[] frames; + if (instructions.size() > 0) { + Analyzer a = new Analyzer(new BasicVerifier()); + try { + a.analyze(className, this); + } catch (Exception ignored) { + } + frames = a.getFrames(); + } else { + frames = new Frame[0]; + } + System.out.println(labels.size() + " labels for method " + name); + System.out.println(frames.length + " frame states for method " + name); + // now make the next visitor in the chain (i.e. cv) visit + // this method + accept(new ClassAdapter(cv) { + + public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions ) { + // insert an adapter to transform the method based + // on the computed frames + + final Label[] la = new Label[labels.size()]; + labels.toArray(la); + + return new MyMethodAdapter( + cv.visitMethod(access, name, desc, signature, exceptions), + frames, + la, + name + ); + } + }); + } + }; + } else { + return super.visitMethod(access, name, desc, signature, exceptions); + } + } + } + + class MyMethodAdapter extends MethodAdapter { + + private final Frame[] frames; + private final Label[] labels; + private final String name; + private int currentInsn; // position in the *original* code + + + public MyMethodAdapter(MethodVisitor mv, Frame[] frames, Label[] labels, String name) { + super(mv); + this.frames = frames; + this.name = name; + this.labels = labels; + } + + public void visitCode() { + mv.visitCode(); + + mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); + mv.visitLdcInsn("entering " + name); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); + + //mv.visitTableSwitchInsn(0, labels.length-1 , null, labels); + //mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "", "", ""); + } + + public void visitInsn( int opcode ) { + + if (opcode == Opcodes.RETURN) { + mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); + mv.visitLdcInsn("returning from " + name); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); + } + + mv.visitInsn(opcode); + ++currentInsn; + } + + + public void visitMethodInsn( int opcode, String owner, String name, String desc ) { + if (needsFrameGuard(opcode, owner, name, desc) && inScope(owner, name)) { + + mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); + mv.visitLdcInsn("before " + name); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); + + mv.visitMethodInsn(opcode, owner, name, desc); + + mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); + mv.visitLdcInsn("after " + name); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); + + } else { + mv.visitMethodInsn(opcode, owner, name, desc); + } + // insert your code here if necessary, + // you can use frames[currentInsn] to know frame types at this + // point + ++currentInsn; + } + } + + private boolean inScope(String owner, String name) { + if (owner.startsWith("org/apache/commons/javaflow")) { + return true; + } + return false; + } + private boolean needsFrameGuard( int opcode, String owner, String name, String desc ) { + if (opcode == Opcodes.INVOKEINTERFACE || + opcode == Opcodes.INVOKESPECIAL || + opcode == Opcodes.INVOKESTATIC || + opcode == Opcodes.INVOKEVIRTUAL ) { + return true; + } + return false; + } + + public byte[] transform( final byte[] original ) { + // new ClassReader(original).accept(new TraceClassVisitor(new + // ClassWriter(false), new PrintWriter(System.out)), false); + final ClassReader cr = new ClassReader(original); final ClassWriter cw = new ClassWriter(true, false); - cn.accept(cn); - + final ClassVisitor cv = new MyClassAdapter(cw); + cr.accept(cv, false); final byte[] transformed = cw.toByteArray(); - return null; + //new ClassReader(transformed).accept(new TraceClassVisitor(new ClassWriter(false), new PrintWriter(System.out)), false); + + return transformed; } + + public static void main( String[] args ) throws Exception { + final byte[] original = IOUtils.toByteArray(ClassLoader.getSystemResourceAsStream("org/apache/commons/javaflow/testcode/Test.class")); + + System.out.println("original=" + original.length); + final byte[] transformed = new AsmClassTransformer().transform(original); + System.out.println("transformed=" + transformed.length); + + /* + System.out.println("running the original"); + Class originalClass = new BytecodeClassLoader().loadClass(original); + Runnable orignalRunnable = (Runnable) originalClass.newInstance(); + try { + orignalRunnable.run(); + } catch(IllegalStateException e) { + } + System.out.println("original finished"); + */ + + System.out.println("running the transformed"); + Class transformedClass = new BytecodeClassLoader().loadClass(transformed); + Runnable transformedRunnable = (Runnable) transformedClass.newInstance(); + transformedRunnable.run(); + System.out.println("transformed finished"); + } } Added: jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/testcode/Test.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/testcode/Test.java?rev=209036&view=auto ============================================================================== --- jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/testcode/Test.java (added) +++ jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/testcode/Test.java Mon Jul 4 02:01:47 2005 @@ -0,0 +1,62 @@ +package org.apache.commons.javaflow.testcode; + +import java.lang.reflect.Method; +import java.util.Map; +import junit.framework.TestCase; +import org.apache.commons.javaflow.Continuation; +import org.apache.commons.javaflow.ContinuationContext; +import org.apache.commons.javaflow.MethodLookup; +import org.apache.commons.javaflow.utils.ReflectionUtils; + +public class Test implements Runnable { + + public final class MapMethodLookup implements MethodLookup { + + private final Map methods; + + + public MapMethodLookup(Map methods) { + super(); + this.methods = methods; + } + + + public Method getMethod(final String methodName) { + final Method method = (Method) methods.get(methodName); + if (method == null) { + throw new NullPointerException("method " + methodName + " could not be found"); + } + return method; + } + } + + private ContinuationContext createContinuationContext(final Class clazz) { + + final Map methods = ReflectionUtils.discoverMethods(clazz); + TestCase.assertNotNull(methods); + TestCase.assertTrue(methods.size() > 0); + + final MethodLookup lookup = new MapMethodLookup(methods); + + final ContinuationContext context = new ContinuationContext(); + context.setMethodLookup(lookup); + + return context; + } + + public void run() { + System.out.println("running in " + this.getClass().getClassLoader().hashCode()); + + final ContinuationContext context = createContinuationContext(this.getClass()); + + final Continuation continuation = Continuation.startWith("main", context); + + System.out.println("finished in " + this.getClass().getClassLoader().hashCode()); + } + + public void main() { + + Continuation.suspend(); + + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]