You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by tc...@apache.org on 2005/12/25 05:10:28 UTC
svn commit: r358963 [1/2] - in /jakarta/commons/sandbox/javaflow/trunk: ./
lib/ src/java/org/apache/commons/javaflow/
src/java/org/apache/commons/javaflow/ant/
src/java/org/apache/commons/javaflow/bytecode/
src/java/org/apache/commons/javaflow/bytecode...
Author: tcurdt
Date: Sat Dec 24 20:09:27 2005
New Revision: 358963
URL: http://svn.apache.org/viewcvs?rev=358963&view=rev
Log:
added asm implementation contributed by Eugene Kuleshov, some nitpicking
Added:
jakarta/commons/sandbox/javaflow/trunk/lib/asm-all-2.2.1.jar (with props)
jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/StackRecorder.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationClassAdapter.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAdapter.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAnalyzer.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/AsmClassTransformerClassLoader.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/BlackRedTestCase.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/ClassAccess2TestClass.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/ClassAccessTestCase.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/CounterTestCase.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/DefaultConstructorDump.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/DefaultConstructorTestCase.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/InvokerTestCase.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/NewObjectTestCase.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/NoReferenceTestCase.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/SimpleSerializableTestCase.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/SimpleTestCase.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/StackTestCase.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/TransformerTestCase.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/BlackRed.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/ClassAccess1.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/ClassAccess2.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/ClassAccess3.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/CounterFlow.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/DefaultConstructor.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/Invoker.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/NewObject.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/NoReference.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/Simple.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/SimpleSerializable.java (with props)
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/Stack.java (with props)
Removed:
jakarta/commons/sandbox/javaflow/trunk/lib/asm-20050703.234510.jar
jakarta/commons/sandbox/javaflow/trunk/lib/asm-analysis-20050703.234510.jar
jakarta/commons/sandbox/javaflow/trunk/lib/asm-attrs-20050703.234510.jar
jakarta/commons/sandbox/javaflow/trunk/lib/asm-common-20050703.234510.jar
jakarta/commons/sandbox/javaflow/trunk/lib/asm-tree-20050703.234510.jar
jakarta/commons/sandbox/javaflow/trunk/lib/asm-util-20050703.234510.jar
jakarta/commons/sandbox/javaflow/trunk/lib/asm-xml-20050703.234510.jar
Modified:
jakarta/commons/sandbox/javaflow/trunk/maven.xml
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/ContinuationClassLoader.java
jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/AntRewriteTask.java
jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/tasks.properties
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/transformation/asm/AsmClassTransformer.java
jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/TestClassLoader.java
Added: jakarta/commons/sandbox/javaflow/trunk/lib/asm-all-2.2.1.jar
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/lib/asm-all-2.2.1.jar?rev=358963&view=auto
==============================================================================
Binary file - no diff available.
Propchange: jakarta/commons/sandbox/javaflow/trunk/lib/asm-all-2.2.1.jar
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Modified: jakarta/commons/sandbox/javaflow/trunk/maven.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/maven.xml?rev=358963&r1=358962&r2=358963&view=diff
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/maven.xml (original)
+++ jakarta/commons/sandbox/javaflow/trunk/maven.xml Sat Dec 24 20:09:27 2005
@@ -1,3 +1,4 @@
+<?xml version="1.0"?>
<project
xmlns:j="jelly:core"
xmlns:util="jelly:util"
@@ -17,9 +18,18 @@
/>
<rewrite srcDir="target/test-classes" dstDir="target/test-classes">
+ <include name="org/apache/commons/javaflow/bytecode/transformation/asm/data/**"/>
+ <include name="org/apache/commons/javaflow/flow/**"/>
+<!--
+ <include name="org.apache.commons.javaflow.bytecode.transformation.asm.data.**"/>
+ <include name="org.apache.commons.javaflow.flow.**"/>
<includes>
- <include>**/*Flow*.java</include>
- </includes>
+ <include>org.apache.commons.javaflow.bytecode.transformation.asm.data.**</include>
+ <include>org/apache/commons/javaflow/bytecode/transformation/asm/data/**</include>
+ <include>org.apache.commons.javaflow.flow.**</include>
+ <include>org/apache/commons/javaflow/flow/**</include>
+ </includes>
+-->
</rewrite>
</postGoal>
Modified: jakarta/commons/sandbox/javaflow/trunk/project.properties
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/project.properties?rev=358963&r1=358962&r2=358963&view=diff
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/project.properties (original)
+++ jakarta/commons/sandbox/javaflow/trunk/project.properties Sat Dec 24 20:09:27 2005
@@ -35,9 +35,4 @@
maven.jar.commons-jci = lib/commons-jci-r291284.jar
maven.jar.bcel = lib/jakarta-bcel-20050813.jar
maven.jar.commons-io = lib/commons-io-20050621.133116.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
-
+maven.jar.asm-all = lib/asm-all-2.2.1.jar
Modified: jakarta/commons/sandbox/javaflow/trunk/project.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/project.xml?rev=358963&r1=358962&r2=358963&view=diff
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/project.xml (original)
+++ jakarta/commons/sandbox/javaflow/trunk/project.xml Sat Dec 24 20:09:27 2005
@@ -92,6 +92,13 @@
</developer>
</developers>
+ <contributors>
+ <contributor>
+ <name>Eugene Kuleshov</name>
+ <email>eu at javatx.org</email>
+ </contributor>
+ </contributors>
+
<dependencies>
<dependency>
<groupId>commons-logging</groupId>
@@ -144,37 +151,9 @@
</dependency>
<dependency>
<groupId>asm</groupId>
- <artifactId>asm</artifactId>
- <jar>${basedir}/lib/asm-20050703.234510.jar</jar>
- <version>SNAPSHOT</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>asm</groupId>
- <artifactId>asm-tree</artifactId>
- <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>
+ <artifactId>asm-all</artifactId>
+ <version>2.2.1</version>
+ <jar>${basedir}/lib/asm-all-2.2.1.jar</jar>
<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=358963&r1=358962&r2=358963&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 Sat Dec 24 20:09:27 2005
@@ -41,18 +41,16 @@
*/
public final class Continuation implements Serializable {
- private final static Log log = LogFactory.getLog(Continuation.class);
+ private static final Log log = LogFactory.getLog(Continuation.class);
+ private static final long serialVersionUID = 2L;
- private final StackRecorder stack;
+ private final StackRecorder stackRecorder;
- private static final long serialVersionUID = 1L;
-
-
/**
* Create a new continuation, which continue a previous continuation.
*/
- private Continuation(StackRecorder sr) {
- stack = sr;
+ private Continuation( final StackRecorder pStackRecorder ) {
+ stackRecorder = pStackRecorder;
}
@@ -87,8 +85,8 @@
* @return
* always return a non-null valid object.
*/
- public static Continuation startSuspendedWith( final Runnable target ) {
- return new Continuation(new StackRecorder(target));
+ public static Continuation startSuspendedWith( final Runnable pTarget ) {
+ return new Continuation(new StackRecorder(pTarget));
}
/**
@@ -100,8 +98,8 @@
*
* @see #startWith(Runnable, Object).
*/
- public static Continuation startWith( final Runnable target ) {
- return startWith(target,null);
+ public static Continuation startWith( final Runnable pTarget ) {
+ return startWith(pTarget, null);
}
/**
@@ -121,14 +119,14 @@
* a new non-null continuation is returned.
* @see #getContext()
*/
- public static Continuation startWith( final Runnable target, final Object context ) {
- if(target==null) {
+ public static Continuation startWith( final Runnable pTarget, final Object pContext ) {
+ if(pTarget == null) {
throw new IllegalArgumentException("target is null");
}
- log.debug("starting new flow from " + ReflectionUtils.getClassName(target) + "/" + ReflectionUtils.getClassLoaderName(target));
+ log.debug("starting new flow from " + ReflectionUtils.getClassName(pTarget) + "/" + ReflectionUtils.getClassLoaderName(pTarget));
- return execute(new StackRecorder(target), context);
+ return execute(new StackRecorder(pTarget), pContext);
}
/**
@@ -139,18 +137,19 @@
*
* @see #continueWith(Continuation, Object)
*/
- public static Continuation continueWith(final Continuation resumed) {
- return continueWith(resumed,null);
+ public static Continuation continueWith(final Continuation pOldContinuation) {
+ return continueWith(pOldContinuation, null);
}
/**
- * Resumes the execution of the specified continuation from where it's left off.
+ * Resumes the execution of the specified continuation from where it's left off
+ * and creates a new continuation representing the new state.
*
* This method blocks until the continuation suspends or completes.
*
- * @param resumed
+ * @param pOldContinuation
* The resumed continuation to be executed. Must not be null.
- * @param context
+ * @param pContext
* This value can be obtained from {@link #getContext()} until this method returns.
* Can be null.
* @return
@@ -159,27 +158,27 @@
* a new non-null continuation is returned.
* @see #getContext()
*/
- public static Continuation continueWith(final Continuation resumed, final Object context) {
- if(resumed==null) {
+ public static Continuation continueWith(final Continuation pOldContinuation, final Object pContext) {
+ if(pOldContinuation == null) {
throw new IllegalArgumentException("continuation parameter must not be null.");
}
- log.debug("continueing with continuation " + ReflectionUtils.getClassName(resumed) + "/" + ReflectionUtils.getClassLoaderName(resumed));
+ log.debug("continueing with continuation " + ReflectionUtils.getClassName(pOldContinuation) + "/" + ReflectionUtils.getClassLoaderName(pOldContinuation));
- return execute(new StackRecorder(resumed.stack),context);
+ return execute(new StackRecorder(pOldContinuation.stackRecorder),pContext);
}
- private static Continuation execute(StackRecorder stack, final Object context) {
- stack = stack.execute(context);
- if(stack==null) {
+ private static Continuation execute( StackRecorder pStackRecorder, final Object pContext) {
+ pStackRecorder = pStackRecorder.execute(pContext);
+ if(pStackRecorder == null) {
return null;
} else {
- return new Continuation(stack);
+ return new Continuation(pStackRecorder);
}
}
public boolean isSerializable() {
- return stack.isSerializable();
+ return stackRecorder.isSerializable();
}
/**
Modified: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ContinuationClassLoader.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ContinuationClassLoader.java?rev=358963&r1=358962&r2=358963&view=diff
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ContinuationClassLoader.java (original)
+++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ContinuationClassLoader.java Sat Dec 24 20:09:27 2005
@@ -1,423 +1,423 @@
-/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.javaflow;
-
-import org.apache.commons.javaflow.bytecode.transformation.ResourceTransformer;
-import org.apache.commons.javaflow.bytecode.transformation.bcel.BcelClassTransformer;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.ProtectionDomain;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * {@link URLClassLoader} with bytecode instrumentation for javaflow.
- *
- * <p>
- * This class loader is useful where the application can set up multiple
- * class loaders (such as in a container environment,
- * <a href="http://classworlds.codehaus.org/">ClassWorlds</a>, or
- * <a href="http://forehead.werken.com/">Forehead</a>) and when you can
- * isolate the continuation-enabled portion of your application into a separate
- * jar file.
- */
-public final class ContinuationClassLoader extends URLClassLoader {
-
- private final static Log log = LogFactory.getLog(ContinuationClassLoader.class);
-
- private final ResourceTransformer transformer;
-
- /**
- * Indicates whether the parent class loader should be
- * consulted before trying to load with this class loader.
- */
- private boolean parentFirst = true;
-
- /**
- * These are the package roots that are to be loaded by the parent class
- * loader regardless of whether the parent class loader is being searched
- * first or not.
- */
- private List systemPackages = new ArrayList();
-
- /**
- * These are the package roots that are to be loaded by this class loader
- * regardless of whether the parent class loader is being searched first
- * or not.
- */
- private List loaderPackages = new ArrayList();
-
- /**
- * Whether or not this classloader will ignore the base
- * classloader if it can't find a class.
- *
- * @see #setIsolated(boolean)
- */
- private boolean ignoreBase = false;
-
- /* The context to be used when loading classes and resources */
- private final AccessControlContext acc;
-
- private static final int BUFFER_SIZE = 4096;
-
- /**
- * Creates a classloader by using the classpath given.
- *
- * @param urls
- * The URLs from which to load classes and resources
- * @param parent
- * The parent classloader to which unsatisfied loading
- * attempts are delegated. May be <code>null</code>,
- * in which case the {@link ClassLoader#getSystemClassLoader() system classloader}
- * is used as the parent.
- * @param transformer
- * This transformer is used to perform the byte-code enhancement.
- * May not be null.
- */
- public ContinuationClassLoader(URL[] urls, ClassLoader parent, ResourceTransformer transformer) {
- super(urls,fixNullParent(parent));
- if(transformer==null)
- throw new IllegalArgumentException();
- this.transformer = transformer;
- acc = AccessController.getContext();
- }
-
- public ContinuationClassLoader(URL[] urls, ClassLoader parent) {
- this(urls,parent,new BcelClassTransformer());
- }
-
- private static ClassLoader fixNullParent(ClassLoader classLoader) {
- if(classLoader!=null) {
- return classLoader;
- } else {
- return getSystemClassLoader();
- }
- }
-
- /**
- * Control whether class lookup is delegated to the parent loader first
- * or after this loader. Use with extreme caution. Setting this to
- * false violates the class loader hierarchy and can lead to Linkage errors
- *
- * @param parentFirst if true, delegate initial class search to the parent
- * classloader.
- */
- public void setParentFirst(boolean parentFirst) {
- this.parentFirst = parentFirst;
- }
-
- /**
- * Sets whether this classloader should run in isolated mode. In
- * isolated mode, classes not found on the given classpath will
- * not be referred to the parent class loader but will cause a
- * ClassNotFoundException.
- *
- * @param isolated Whether or not this classloader should run in
- * isolated mode.
- */
- public void setIsolated(boolean isolated) {
- ignoreBase = isolated;
- }
-
- /**
- * Adds a package root to the list of packages which must be loaded on the
- * parent loader.
- *
- * All subpackages are also included.
- *
- * @param packageRoot The root of all packages to be included.
- * Should not be <code>null</code>.
- */
- public synchronized void addSystemPackageRoot(String packageRoot) {
- systemPackages.add(appendDot(packageRoot));
- }
-
- /**
- * Adds a package root to the list of packages which must be loaded using
- * this loader.
- *
- * All subpackages are also included.
- *
- * @param packageRoot The root of all packages to be included.
- * Should not be <code>null</code>.
- */
- public synchronized void addLoaderPackageRoot(String packageRoot) {
- loaderPackages.add(appendDot(packageRoot));
- }
-
- private String appendDot(String str) {
- if(str.endsWith("."))
- str += '.';
- return str;
- }
-
- /**
- * Loads a class through this class loader even if that class is available
- * on the parent classpath.
- *
- * This ensures that any classes which are loaded by the returned class
- * will use this classloader.
- *
- * @param classname The name of the class to be loaded.
- * Must not be <code>null</code>.
- *
- * @return the required Class object
- *
- * @exception ClassNotFoundException if the requested class does not exist
- * on this loader's classpath.
- */
- public Class forceLoadClass(String classname)
- throws ClassNotFoundException {
- log.debug("force loading " + classname);
-
- Class theClass = findLoadedClass(classname);
-
- if (theClass == null) {
- theClass = findClass(classname);
- }
-
- return theClass;
- }
-
- /**
- * Tests whether or not the parent classloader should be checked for
- * a resource before this one. If the resource matches both the
- * "use parent classloader first" and the "use this classloader first"
- * lists, the latter takes priority.
- *
- * @param resourceName The name of the resource to check.
- * Must not be <code>null</code>.
- *
- * @return whether or not the parent classloader should be checked for a
- * resource before this one is.
- */
- private synchronized boolean isParentFirst(String resourceName) {
- // default to the global setting and then see
- // if this class belongs to a package which has been
- // designated to use a specific loader first
- // (this one or the parent one)
-
- // XXX - shouldn't this always return false in isolated mode?
-
- boolean useParentFirst = parentFirst;
-
- for (Iterator itr = systemPackages.iterator(); itr.hasNext();) {
- String packageName = (String) itr.next();
- if (resourceName.startsWith(packageName)) {
- useParentFirst = true;
- break;
- }
- }
-
- for (Iterator itr = loaderPackages.iterator(); itr.hasNext();) {
- String packageName = (String) itr.next();
- if (resourceName.startsWith(packageName)) {
- useParentFirst = false;
- break;
- }
- }
-
- return useParentFirst;
- }
-
- /**
- * Loads a class with this class loader.
- *
- * This class attempts to load the class in an order determined by whether
- * or not the class matches the system/loader package lists, with the
- * loader package list taking priority. If the classloader is in isolated
- * mode, failure to load the class in this loader will result in a
- * ClassNotFoundException.
- *
- * @param classname The name of the class to be loaded.
- * Must not be <code>null</code>.
- * @param resolve <code>true</code> if all classes upon which this class
- * depends are to be loaded.
- *
- * @return the required Class object
- *
- * @exception ClassNotFoundException if the requested class does not exist
- * on the system classpath (when not in isolated mode) or this loader's
- * classpath.
- */
- protected synchronized Class loadClass(String classname, boolean resolve)
- throws ClassNotFoundException {
- // 'sync' is needed - otherwise 2 threads can load the same class
- // twice, resulting in LinkageError: duplicated class definition.
- // findLoadedClass avoids that, but without sync it won't work.
-
- Class theClass = findLoadedClass(classname);
- if (theClass != null) {
- return theClass;
- }
-
- if (isParentFirst(classname)) {
- try {
- theClass = getParent().loadClass(classname);
- log.debug("Class " + classname + " loaded from parent loader "
- + "(parentFirst)");
- } catch (ClassNotFoundException cnfe) {
- theClass = findClass(classname);
- log.debug("Class " + classname + " loaded from ant loader "
- + "(parentFirst)");
- }
- } else {
- try {
- theClass = findClass(classname);
- log.debug("Class " + classname + " loaded from ant loader");
- } catch (ClassNotFoundException cnfe) {
- if (ignoreBase) {
- throw cnfe;
- }
- theClass = getParent().loadClass(classname);
- log.debug("Class " + classname + " loaded from parent loader");
- }
- }
-
- if (resolve) {
- resolveClass(theClass);
- }
-
- return theClass;
- }
-
- /**
- * Define a class given its bytes
- *
- * @param classData the bytecode data for the class
- * @param classname the name of the class
- *
- * @return the Class instance created from the given data
- */
- protected Class defineClassFromData(final byte[] classData, final String classname) {
- return (Class)AccessController.doPrivileged(new PrivilegedAction() {
- public Object run() {
- // define a package if necessary.
- int i = classname.lastIndexOf('.');
- if (i>0) {
- String packageName = classname.substring(0,i);
- Package pkg = getPackage(packageName);
- if(pkg==null) {
- definePackage(packageName,null,null,null,null,null,null,null);
- }
- }
-
- byte[] newData = transformer.transform(classData);
- ProtectionDomain domain = this.getClass().getProtectionDomain();
- return defineClass(classname,newData,0,newData.length,domain);
- }
- },acc);
- }
-
- /**
- * Reads a class definition from a stream.
- *
- * @param stream The stream from which the class is to be read.
- * Must not be <code>null</code>.
- * @param classname The name of the class in the stream.
- * Must not be <code>null</code>.
- *
- * @return the Class object read from the stream.
- *
- * @exception IOException if there is a problem reading the class from the
- * stream.
- * @exception SecurityException if there is a security problem while
- * reading the class from the stream.
- */
- private Class getClassFromStream(InputStream stream, String classname)
- throws IOException, SecurityException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- int bytesRead;
- byte[] buffer = new byte[BUFFER_SIZE];
-
- while ((bytesRead = stream.read(buffer, 0, BUFFER_SIZE)) != -1) {
- baos.write(buffer, 0, bytesRead);
- }
-
- byte[] classData = baos.toByteArray();
- return defineClassFromData(classData, classname);
- }
-
- /**
- * Searches for and load a class on the classpath of this class loader.
- *
- * @param name The name of the class to be loaded. Must not be
- * <code>null</code>.
- *
- * @return the required Class object
- *
- * @exception ClassNotFoundException if the requested class does not exist
- * on this loader's classpath.
- */
- public Class findClass(final String name) throws ClassNotFoundException {
- log.debug("Finding class " + name);
-
- // locate the class file
- String classFileName = name.replace('.', '/') + ".class";
-
- InputStream stream = getResourceAsStream(classFileName);
- if(stream==null)
- throw new ClassNotFoundException(name);
-
- try {
- return getClassFromStream(stream, name);
- } catch (IOException e) {
- throw new ClassNotFoundException(name,e);
- } finally {
- try {
- stream.close();
- } catch (IOException e) {
- // ignore
- }
- }
- }
-
- /**
- * Finds the resource with the given name. A resource is
- * some data (images, audio, text, etc) that can be accessed by class
- * code in a way that is independent of the location of the code.
- *
- * @param name The name of the resource for which a stream is required.
- * Must not be <code>null</code>.
- * @return a URL for reading the resource, or <code>null</code> if the
- * resource could not be found or the caller doesn't have
- * adequate privileges to get the resource.
- */
- public synchronized URL getResource(String name) {
- // we need to search the components of the path to see if
- // we can find the class we want.
- if (isParentFirst(name)) {
- return super.getResource(name);
- }
-
- // try this class loader first, then parent
- URL url = findResource(name);
- if(url==null) {
- url = getParent().getResource(name);
- }
- return url;
- }
-}
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.javaflow;
+
+import org.apache.commons.javaflow.bytecode.transformation.ResourceTransformer;
+import org.apache.commons.javaflow.bytecode.transformation.bcel.BcelClassTransformer;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * {@link URLClassLoader} with bytecode instrumentation for javaflow.
+ *
+ * <p>
+ * This class loader is useful where the application can set up multiple
+ * class loaders (such as in a container environment,
+ * <a href="http://classworlds.codehaus.org/">ClassWorlds</a>, or
+ * <a href="http://forehead.werken.com/">Forehead</a>) and when you can
+ * isolate the continuation-enabled portion of your application into a separate
+ * jar file.
+ */
+public final class ContinuationClassLoader extends URLClassLoader {
+
+ private final static Log log = LogFactory.getLog(ContinuationClassLoader.class);
+
+ private final ResourceTransformer transformer;
+
+ /**
+ * Indicates whether the parent class loader should be
+ * consulted before trying to load with this class loader.
+ */
+ private boolean parentFirst = true;
+
+ /**
+ * These are the package roots that are to be loaded by the parent class
+ * loader regardless of whether the parent class loader is being searched
+ * first or not.
+ */
+ private List systemPackages = new ArrayList();
+
+ /**
+ * These are the package roots that are to be loaded by this class loader
+ * regardless of whether the parent class loader is being searched first
+ * or not.
+ */
+ private List loaderPackages = new ArrayList();
+
+ /**
+ * Whether or not this classloader will ignore the base
+ * classloader if it can't find a class.
+ *
+ * @see #setIsolated(boolean)
+ */
+ private boolean ignoreBase = false;
+
+ /* The context to be used when loading classes and resources */
+ private final AccessControlContext acc;
+
+ private static final int BUFFER_SIZE = 4096;
+
+ /**
+ * Creates a classloader by using the classpath given.
+ *
+ * @param urls
+ * The URLs from which to load classes and resources
+ * @param parent
+ * The parent classloader to which unsatisfied loading
+ * attempts are delegated. May be <code>null</code>,
+ * in which case the {@link ClassLoader#getSystemClassLoader() system classloader}
+ * is used as the parent.
+ * @param transformer
+ * This transformer is used to perform the byte-code enhancement.
+ * May not be null.
+ */
+ public ContinuationClassLoader(URL[] urls, ClassLoader parent, ResourceTransformer transformer) {
+ super(urls,fixNullParent(parent));
+ if(transformer==null)
+ throw new IllegalArgumentException();
+ this.transformer = transformer;
+ acc = AccessController.getContext();
+ }
+
+ public ContinuationClassLoader(URL[] urls, ClassLoader parent) {
+ this(urls,parent,new BcelClassTransformer());
+ }
+
+ private static ClassLoader fixNullParent(ClassLoader classLoader) {
+ if(classLoader!=null) {
+ return classLoader;
+ } else {
+ return getSystemClassLoader();
+ }
+ }
+
+ /**
+ * Control whether class lookup is delegated to the parent loader first
+ * or after this loader. Use with extreme caution. Setting this to
+ * false violates the class loader hierarchy and can lead to Linkage errors
+ *
+ * @param parentFirst if true, delegate initial class search to the parent
+ * classloader.
+ */
+ public void setParentFirst(boolean parentFirst) {
+ this.parentFirst = parentFirst;
+ }
+
+ /**
+ * Sets whether this classloader should run in isolated mode. In
+ * isolated mode, classes not found on the given classpath will
+ * not be referred to the parent class loader but will cause a
+ * ClassNotFoundException.
+ *
+ * @param isolated Whether or not this classloader should run in
+ * isolated mode.
+ */
+ public void setIsolated(boolean isolated) {
+ ignoreBase = isolated;
+ }
+
+ /**
+ * Adds a package root to the list of packages which must be loaded on the
+ * parent loader.
+ *
+ * All subpackages are also included.
+ *
+ * @param packageRoot The root of all packages to be included.
+ * Should not be <code>null</code>.
+ */
+ public synchronized void addSystemPackageRoot(String packageRoot) {
+ systemPackages.add(appendDot(packageRoot));
+ }
+
+ /**
+ * Adds a package root to the list of packages which must be loaded using
+ * this loader.
+ *
+ * All subpackages are also included.
+ *
+ * @param packageRoot The root of all packages to be included.
+ * Should not be <code>null</code>.
+ */
+ public synchronized void addLoaderPackageRoot(String packageRoot) {
+ loaderPackages.add(appendDot(packageRoot));
+ }
+
+ private String appendDot(String str) {
+ if(str.endsWith("."))
+ str += '.';
+ return str;
+ }
+
+ /**
+ * Loads a class through this class loader even if that class is available
+ * on the parent classpath.
+ *
+ * This ensures that any classes which are loaded by the returned class
+ * will use this classloader.
+ *
+ * @param classname The name of the class to be loaded.
+ * Must not be <code>null</code>.
+ *
+ * @return the required Class object
+ *
+ * @exception ClassNotFoundException if the requested class does not exist
+ * on this loader's classpath.
+ */
+ public Class forceLoadClass(String classname)
+ throws ClassNotFoundException {
+ log.debug("force loading " + classname);
+
+ Class theClass = findLoadedClass(classname);
+
+ if (theClass == null) {
+ theClass = findClass(classname);
+ }
+
+ return theClass;
+ }
+
+ /**
+ * Tests whether or not the parent classloader should be checked for
+ * a resource before this one. If the resource matches both the
+ * "use parent classloader first" and the "use this classloader first"
+ * lists, the latter takes priority.
+ *
+ * @param resourceName The name of the resource to check.
+ * Must not be <code>null</code>.
+ *
+ * @return whether or not the parent classloader should be checked for a
+ * resource before this one is.
+ */
+ private synchronized boolean isParentFirst(String resourceName) {
+ // default to the global setting and then see
+ // if this class belongs to a package which has been
+ // designated to use a specific loader first
+ // (this one or the parent one)
+
+ // XXX - shouldn't this always return false in isolated mode?
+
+ boolean useParentFirst = parentFirst;
+
+ for (Iterator itr = systemPackages.iterator(); itr.hasNext();) {
+ String packageName = (String) itr.next();
+ if (resourceName.startsWith(packageName)) {
+ useParentFirst = true;
+ break;
+ }
+ }
+
+ for (Iterator itr = loaderPackages.iterator(); itr.hasNext();) {
+ String packageName = (String) itr.next();
+ if (resourceName.startsWith(packageName)) {
+ useParentFirst = false;
+ break;
+ }
+ }
+
+ return useParentFirst;
+ }
+
+ /**
+ * Loads a class with this class loader.
+ *
+ * This class attempts to load the class in an order determined by whether
+ * or not the class matches the system/loader package lists, with the
+ * loader package list taking priority. If the classloader is in isolated
+ * mode, failure to load the class in this loader will result in a
+ * ClassNotFoundException.
+ *
+ * @param classname The name of the class to be loaded.
+ * Must not be <code>null</code>.
+ * @param resolve <code>true</code> if all classes upon which this class
+ * depends are to be loaded.
+ *
+ * @return the required Class object
+ *
+ * @exception ClassNotFoundException if the requested class does not exist
+ * on the system classpath (when not in isolated mode) or this loader's
+ * classpath.
+ */
+ protected synchronized Class loadClass(String classname, boolean resolve)
+ throws ClassNotFoundException {
+ // 'sync' is needed - otherwise 2 threads can load the same class
+ // twice, resulting in LinkageError: duplicated class definition.
+ // findLoadedClass avoids that, but without sync it won't work.
+
+ Class theClass = findLoadedClass(classname);
+ if (theClass != null) {
+ return theClass;
+ }
+
+ if (isParentFirst(classname)) {
+ try {
+ theClass = getParent().loadClass(classname);
+ log.debug("Class " + classname + " loaded from parent loader "
+ + "(parentFirst)");
+ } catch (ClassNotFoundException cnfe) {
+ theClass = findClass(classname);
+ log.debug("Class " + classname + " loaded from ant loader "
+ + "(parentFirst)");
+ }
+ } else {
+ try {
+ theClass = findClass(classname);
+ log.debug("Class " + classname + " loaded from ant loader");
+ } catch (ClassNotFoundException cnfe) {
+ if (ignoreBase) {
+ throw cnfe;
+ }
+ theClass = getParent().loadClass(classname);
+ log.debug("Class " + classname + " loaded from parent loader");
+ }
+ }
+
+ if (resolve) {
+ resolveClass(theClass);
+ }
+
+ return theClass;
+ }
+
+ /**
+ * Define a class given its bytes
+ *
+ * @param classData the bytecode data for the class
+ * @param classname the name of the class
+ *
+ * @return the Class instance created from the given data
+ */
+ protected Class defineClassFromData(final byte[] classData, final String classname) {
+ return (Class)AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ // define a package if necessary.
+ int i = classname.lastIndexOf('.');
+ if (i>0) {
+ String packageName = classname.substring(0,i);
+ Package pkg = getPackage(packageName);
+ if(pkg==null) {
+ definePackage(packageName,null,null,null,null,null,null,null);
+ }
+ }
+
+ byte[] newData = transformer.transform(classData);
+ ProtectionDomain domain = this.getClass().getProtectionDomain();
+ return defineClass(classname,newData,0,newData.length,domain);
+ }
+ },acc);
+ }
+
+ /**
+ * Reads a class definition from a stream.
+ *
+ * @param stream The stream from which the class is to be read.
+ * Must not be <code>null</code>.
+ * @param classname The name of the class in the stream.
+ * Must not be <code>null</code>.
+ *
+ * @return the Class object read from the stream.
+ *
+ * @exception IOException if there is a problem reading the class from the
+ * stream.
+ * @exception SecurityException if there is a security problem while
+ * reading the class from the stream.
+ */
+ private Class getClassFromStream(InputStream stream, String classname)
+ throws IOException, SecurityException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ int bytesRead;
+ byte[] buffer = new byte[BUFFER_SIZE];
+
+ while ((bytesRead = stream.read(buffer, 0, BUFFER_SIZE)) != -1) {
+ baos.write(buffer, 0, bytesRead);
+ }
+
+ byte[] classData = baos.toByteArray();
+ return defineClassFromData(classData, classname);
+ }
+
+ /**
+ * Searches for and load a class on the classpath of this class loader.
+ *
+ * @param name The name of the class to be loaded. Must not be
+ * <code>null</code>.
+ *
+ * @return the required Class object
+ *
+ * @exception ClassNotFoundException if the requested class does not exist
+ * on this loader's classpath.
+ */
+ public Class findClass(final String name) throws ClassNotFoundException {
+ log.debug("Finding class " + name);
+
+ // locate the class file
+ String classFileName = name.replace('.', '/') + ".class";
+
+ InputStream stream = getResourceAsStream(classFileName);
+ if(stream==null)
+ throw new ClassNotFoundException(name);
+
+ try {
+ return getClassFromStream(stream, name);
+ } catch (IOException e) {
+ throw new ClassNotFoundException(name,e);
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * Finds the resource with the given name. A resource is
+ * some data (images, audio, text, etc) that can be accessed by class
+ * code in a way that is independent of the location of the code.
+ *
+ * @param name The name of the resource for which a stream is required.
+ * Must not be <code>null</code>.
+ * @return a URL for reading the resource, or <code>null</code> if the
+ * resource could not be found or the caller doesn't have
+ * adequate privileges to get the resource.
+ */
+ public synchronized URL getResource(String name) {
+ // we need to search the components of the path to see if
+ // we can find the class we want.
+ if (isParentFirst(name)) {
+ return super.getResource(name);
+ }
+
+ // try this class loader first, then parent
+ URL url = findResource(name);
+ if(url==null) {
+ url = getParent().getResource(name);
+ }
+ return url;
+ }
+}
Modified: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/AntRewriteTask.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/AntRewriteTask.java?rev=358963&r1=358962&r2=358963&view=diff
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/AntRewriteTask.java (original)
+++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/AntRewriteTask.java Sat Dec 24 20:09:27 2005
@@ -48,6 +48,7 @@
public void setSrcDir(final File pFile) {
srcDir = pFile;
+ fileset.setDir(srcDir);
}
/**
@@ -75,10 +76,11 @@
public void execute() throws BuildException {
- fileset.setDir(srcDir);
final DirectoryScanner ds = fileset.getDirectoryScanner(getProject());
+// final DirectoryScanner ds = getDirectoryScanner(srcDir);
final String[] fileNames = ds.getIncludedFiles();
+
try {
for (int i = 0; i < fileNames.length; i++) {
final String fileName = fileNames[i];
Modified: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/tasks.properties
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/tasks.properties?rev=358963&r1=358962&r2=358963&view=diff
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/tasks.properties (original)
+++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/tasks.properties Sat Dec 24 20:09:27 2005
@@ -1 +1 @@
-javaflow=org.apache.commons.javaflow.ant.AntRewriteTask
+javaflow=org.apache.commons.javaflow.ant.AntRewriteTask
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=358963&r1=358962&r2=358963&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 Sat Dec 24 20:09:27 2005
@@ -32,8 +32,7 @@
*/
public class Stack implements Serializable {
- private final static Log log = LogFactory.getLog(Stack.class);
-
+ private static final Log log = LogFactory.getLog(Stack.class);
private static final long serialVersionUID = 2L;
private int[] istack;
Added: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/StackRecorder.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/StackRecorder.java?rev=358963&view=auto
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/StackRecorder.java (added)
+++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/StackRecorder.java Sat Dec 24 20:09:27 2005
@@ -0,0 +1,149 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.javaflow.bytecode;
+
+import org.apache.commons.javaflow.utils.ReflectionUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Adds additional behaviors necessary for stack capture/restore
+ * on top of {@link Stack}.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public final class StackRecorder extends Stack {
+
+ private static final Log log = LogFactory.getLog(StackRecorder.class);
+ private static final long serialVersionUID = 2L;
+
+ private static final ThreadLocal threadMap = new ThreadLocal();
+
+ private transient boolean restoring = false;
+ private transient boolean capturing = false;
+
+ /** Context object given by the user */
+ private transient Object context;
+
+ /**
+ * Creates a new empty {@link StackRecorder} that runs the given target.
+ */
+ public StackRecorder( final Runnable pTarget ) {
+ super(pTarget);
+ }
+
+ /**
+ * Creates a clone of the given {@link StackRecorder}.
+ */
+ public StackRecorder(final Stack pParent) {
+ super(pParent);
+ }
+
+ public static void suspend() {
+ log.debug("suspend()");
+
+ final StackRecorder stackRecorder = get();
+ if(stackRecorder == null) {
+ throw new IllegalStateException("No continuation is running");
+ }
+
+ stackRecorder.capturing = !stackRecorder.restoring;
+ stackRecorder.restoring = false;
+ }
+
+ /**
+ * True, if the continuation restores the previous stack trace to the last
+ * invocation of suspend().
+ */
+ public boolean isRestoring() {
+ return restoring;
+ }
+
+ /**
+ * True, is the continuation freeze the strack trace, and stops the
+ * continuation.
+ */
+ public boolean isCapturing() {
+ return capturing;
+ }
+
+ public StackRecorder execute(final Object context) {
+ final StackRecorder old = registerThread();
+ try {
+ restoring = !isEmpty(); // start restoring if we have a filled stack
+ this.context = context;
+
+ if (restoring) {
+ log.debug("Restoring state of " + ReflectionUtils.getClassName(runnable) + "/" + ReflectionUtils.getClassLoaderName(runnable));
+ }
+
+ log.debug("calling runnable");
+ runnable.run();
+
+ if (capturing) {
+ if(isEmpty()) {
+ // if we were really capturing the stack, at least we should have
+ // one object in the reference stack. Otherwise, it usually means
+ // that the application wasn't instrumented correctly.
+ throw new IllegalStateException("stack corruption. Is "+runnable.getClass()+" instrumented for javaflow?");
+ }
+ // top of the reference stack is the object that we'll call into
+ // when resuming this continuation. we have a separate Runnable
+ // for this, so throw it away
+ popReference();
+ return this;
+ } else {
+ return null; // nothing more to continue
+ }
+ } catch(Error e) {
+ log.error(e.getMessage(),e);
+ throw e;
+ } catch(RuntimeException e) {
+ log.error(e.getMessage(),e);
+ throw e;
+ } finally {
+ this.context = null;
+ deregisterThread(old);
+ }
+ }
+
+ public Object getContext() {
+ return context;
+ }
+
+ /**
+ * Bind this stack recorder to running thread.
+ */
+ private StackRecorder registerThread() {
+ StackRecorder old = get();
+ threadMap.set(this);
+ return old;
+ }
+
+ /**
+ * Unbind the current stack recorder to running thread.
+ */
+ private void deregisterThread(final StackRecorder old) {
+ threadMap.set(old);
+ }
+
+ /**
+ * Return the continuation, which is associated to the current thread.
+ */
+ public static StackRecorder get() {
+ return (StackRecorder)threadMap.get();
+ }
+}
Propchange: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/StackRecorder.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/StackRecorder.java
------------------------------------------------------------------------------
svn:keywords = Id
Modified: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/AsmClassTransformer.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/AsmClassTransformer.java?rev=358963&r1=358962&r2=358963&view=diff
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/AsmClassTransformer.java (original)
+++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/AsmClassTransformer.java Sat Dec 24 20:09:27 2005
@@ -15,234 +15,59 @@
*/
package org.apache.commons.javaflow.bytecode.transformation.asm;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collection;
-import org.apache.commons.io.IOUtils;
+import java.io.IOException;
+import java.io.InputStream;
+
import org.apache.commons.javaflow.bytecode.transformation.ResourceTransformer;
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.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.DataflowInterpreter;
-import org.objectweb.asm.tree.analysis.Frame;
-import org.objectweb.asm.util.TraceClassVisitor;
+import org.objectweb.asm.util.CheckClassAdapter;
+
/**
- * @author tcurdt
+ * AsmClassTransformer
+ *
+ * @author Eugene Kuleshov
*/
public final class AsmClassTransformer implements ResourceTransformer {
-
private final static Log log = LogFactory.getLog(AsmClassTransformer.class);
+
- class MyClassAdapter extends ClassAdapter {
-
- 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 DataflowInterpreter());
- //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 " + this.name);
- System.out.println(frames.length + " frame states for method " + this.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( InputStream is) throws IOException {
+ return transform( new ClassReader(is));
}
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);
- final ClassVisitor cv = new MyClassAdapter(cw);
- cr.accept(cv, false);
- final byte[] transformed = cw.toByteArray();
-
- return transformed;
+ return transform( new ClassReader(original));
}
+
+ private byte[] transform( ClassReader cr ) {
+ // final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ final ClassWriter cw = new ClassWriter(true, false);
+ // print bytecode before transformation
+ // cr.accept(new TraceClassVisitor(new ContinuationClassAdapter(this, cw), new PrintWriter(System.out)), false);
+
+ // prints bytecode after transformation
+ // cr.accept(new ContinuationClassAdapter(this, new TraceClassVisitor(cw, new PrintWriter(System.err))), 0);
+ // cr.accept(new ContinuationClassAdapter(this, new TraceClassVisitor(cw, new PrintWriter(System.err))), false);
- public static void main( String[] args ) throws Exception {
- final byte[] original = IOUtils.toByteArray(ClassLoader.getSystemResourceAsStream("org/apache/commons/javaflow/testcode/Test.class"));
+ cr.accept(new ContinuationClassAdapter(new CheckClassAdapter( cw)), false);
+
+ byte[] bytecode = cw.toByteArray();
+
+ // CheckClassAdapter.verify(new ClassReader(bytecode), true);
+ // new ClassReader(bytecode).accept(new ASMifierClassVisitor(new PrintWriter(System.err)), false);
- System.out.println("original=" + original.length);
- final byte[] transformed = new AsmClassTransformer().transform(original);
- System.out.println("transformed=" + transformed.length);
+ // ClassWriter cww = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
+ // new ClassReader(bytecode).accept(cww, ClassReader.SKIP_DEBUG);
+ // new ClassReader(cww.toByteArray()).accept(new TraceClassVisitor(new PrintWriter(System.err)), 0);
- /*
- 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");
- */
-
- new ClassReader(transformed).accept(new TraceClassVisitor(new ClassWriter(false), new PrintWriter(System.out)), false);
-
- /*
- System.out.println("running the transformed");
- Class transformedClass = new BytecodeClassLoader().loadClass(transformed);
- Runnable transformedRunnable = (Runnable) transformedClass.newInstance();
- transformedRunnable.run();
- System.out.println("transformed finished");
- */
+ return bytecode;
}
-}
\ No newline at end of file
+
+}
+
Added: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationClassAdapter.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationClassAdapter.java?rev=358963&view=auto
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationClassAdapter.java (added)
+++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationClassAdapter.java Sat Dec 24 20:09:27 2005
@@ -0,0 +1,51 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.javaflow.bytecode.transformation.asm;
+
+import org.objectweb.asm.ClassAdapter;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
+
+
+/**
+ * ContinuationClassAdapter
+ *
+ * @author Evgueni Koulechov
+ */
+public class ContinuationClassAdapter extends ClassAdapter {
+ private String className;
+
+ public ContinuationClassAdapter(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 ) {
+ MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
+ // TODO skip native and abstract methods?
+ if (!"<init>".equals(name) && mv!=null) {
+ return new ContinuationMethodAnalyzer(className, this.cv, mv, access, name, desc, signature, exceptions);
+ }
+ return mv;
+ }
+
+}
+
Propchange: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationClassAdapter.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationClassAdapter.java
------------------------------------------------------------------------------
svn:keywords = Id
Added: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAdapter.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAdapter.java?rev=358963&view=auto
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAdapter.java (added)
+++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAdapter.java Sat Dec 24 20:09:27 2005
@@ -0,0 +1,329 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.javaflow.bytecode.transformation.asm;
+
+import java.util.List;
+
+import org.apache.commons.javaflow.bytecode.StackRecorder;
+
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodAdapter;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.MethodInsnNode;
+import org.objectweb.asm.tree.analysis.Analyzer;
+import org.objectweb.asm.tree.analysis.BasicValue;
+import org.objectweb.asm.tree.analysis.Frame;
+
+
+/**
+ * ContinuationMethodAdapter
+ *
+ * @author Evgueni Koulechov
+ */
+public final class ContinuationMethodAdapter extends MethodAdapter implements Opcodes {
+ private static final String STACK_RECORDER = Type.getInternalName(StackRecorder.class);
+ private static final String POP_METHOD = "pop";
+ private static final String PUSH_METHOD = "push";
+
+ private final Analyzer analyzer;
+ private Label startLabel = new Label();
+ private final List labels;
+ private final List nodes;
+ private final int stackRecorderVar;
+ private final boolean isStatic;
+ private final String methodDesc;
+
+ private int currentIndex = 0;
+ private Frame currentFrame = null;
+
+
+ public ContinuationMethodAdapter(ContinuationMethodAnalyzer a) {
+ super(a.mv);
+ this.analyzer = a.analyzer;
+ this.labels = a.labels;
+ this.nodes = a.nodes;
+ this.stackRecorderVar = a.maxLocals;
+ this.isStatic = (a.access & ACC_STATIC)>0;
+ this.methodDesc = a.desc;
+ }
+
+ public void visitCode() {
+ mv.visitCode();
+
+ int fsize = labels.size();
+ Label[] restoreLabels = new Label[fsize];
+ for( int i = 0; i < restoreLabels.length; i++) {
+ restoreLabels[i] = new Label();
+ }
+
+ // verify if restoring
+ Label l0 = new Label();
+
+ mv.visitMethodInsn(INVOKESTATIC, STACK_RECORDER, "get", "()L"+STACK_RECORDER+";");
+ mv.visitInsn(DUP);
+ mv.visitVarInsn(ASTORE, stackRecorderVar);
+ mv.visitLabel(startLabel);
+
+ mv.visitJumpInsn(IFNULL, l0);
+ mv.visitVarInsn(ALOAD, stackRecorderVar);
+ mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, "isRestoring", "()Z");
+ mv.visitJumpInsn(IFEQ, l0);
+
+ mv.visitVarInsn(ALOAD, stackRecorderVar);
+ mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, POP_METHOD + "Int", "()I");
+ mv.visitTableSwitchInsn(0, fsize-1, l0, restoreLabels);
+
+ // switch cases
+ for(int i = 0; i<fsize; i++) {
+ Label frameLabel = (Label) labels.get(i);
+ mv.visitLabel(restoreLabels[i]);
+
+ MethodInsnNode mnode = (MethodInsnNode) nodes.get(i);
+
+ Frame frame = analyzer.getFrames()[analyzer.getIndex(mnode)];
+
+ // locals
+ int lsize = frame.getLocals();
+ for( int j = lsize-1; j>=0; j--) {
+ BasicValue value = (BasicValue) frame.getLocal(j);
+ if(value==null) {
+ mv.visitInsn(ACONST_NULL);
+ mv.visitVarInsn(ASTORE, j);
+ } else if(value==BasicValue.UNINITIALIZED_VALUE) {
+ // TODO ??
+ } else if(value==BasicValue.RETURNADDRESS_VALUE) {
+ // TODO ??
+ } else {
+ mv.visitVarInsn(ALOAD, stackRecorderVar);
+ Type type = value.getType();
+ if(value.isReference()) {
+ mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, POP_METHOD + "Object", "()Ljava/lang/Object;");
+ Type t = value.getType();
+ String desc = t.getDescriptor();
+ if(desc.charAt(0)=='[') {
+ mv.visitTypeInsn(CHECKCAST, desc);
+ } else {
+ mv.visitTypeInsn(CHECKCAST, t.getInternalName());
+ }
+ mv.visitVarInsn(ASTORE, j);
+
+ } else {
+ mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, getPopMethod(type), "()"+type.getDescriptor());
+ mv.visitVarInsn(type.getOpcode(ISTORE), j);
+ }
+ }
+ }
+
+ // stack
+ int argSize = Type.getArgumentTypes(mnode.desc).length;
+ int ownerSize = mnode.getOpcode()==INVOKESTATIC ? 0 : 1; // TODO
+ int initSize = mnode.name.equals("<init>") ? 2 : 0;
+ int ssize = frame.getStackSize();
+ for(int j = 0; j < ssize - argSize - ownerSize - initSize; j++) {
+ BasicValue value = (BasicValue) frame.getStack(j);
+ if(value==null) {
+ mv.visitInsn(ACONST_NULL);
+ } else if(value==BasicValue.UNINITIALIZED_VALUE) {
+ // TODO ??
+ } else if(value==BasicValue.RETURNADDRESS_VALUE) {
+ // TODO ??
+ } else if(value.isReference()) {
+ mv.visitVarInsn(ALOAD, stackRecorderVar);
+ mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, POP_METHOD + "Object", "()Ljava/lang/Object;");
+ mv.visitTypeInsn(CHECKCAST, value.getType().getInternalName());
+ } else {
+ Type type = value.getType();
+ mv.visitVarInsn(ALOAD, stackRecorderVar);
+ mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, getPopMethod(type), "()"+type.getDescriptor());
+ }
+ }
+
+ if(mnode.getOpcode()!=INVOKESTATIC) {
+ mv.visitVarInsn(ALOAD, stackRecorderVar);
+ mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, POP_METHOD + "Reference", "()Ljava/lang/Object;");
+ mv.visitTypeInsn(CHECKCAST, ((BasicValue) frame.getStack(ssize-argSize-1)).getType().getInternalName());
+ }
+
+ // Create null types for the parameters of the method invocation
+ Type[] paramTypes = Type.getArgumentTypes(mnode.desc);
+ for (int j = 0; j < paramTypes.length; j++) {
+ pushDefault(paramTypes[j]);
+ }
+
+ // continue to the next method
+ mv.visitJumpInsn(GOTO, frameLabel);
+ }
+
+ // end of start block
+ mv.visitLabel(l0);
+ }
+
+ public void visitLabel( Label label) {
+ if(currentIndex<labels.size() && label==labels.get(currentIndex)) {
+ int i = analyzer.getIndex(nodes.get(currentIndex));
+ currentFrame = analyzer.getFrames()[i];
+ }
+ mv.visitLabel(label);
+ }
+
+ public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+ mv.visitMethodInsn(opcode, owner, name, desc);
+
+ if(currentFrame!=null) {
+ Label fl = new Label();
+
+ mv.visitVarInsn(ALOAD, stackRecorderVar);
+ mv.visitJumpInsn(IFNULL, fl);
+ mv.visitVarInsn(ALOAD, stackRecorderVar);
+ mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, "isCapturing", "()Z");
+ mv.visitJumpInsn(IFEQ, fl);
+
+ // save stack
+ Type returnType = Type.getReturnType(desc);
+ boolean hasReturn = returnType!=Type.VOID_TYPE;
+ if(hasReturn) {
+ mv.visitInsn(returnType.getSize()==1 ? POP : POP2);
+ }
+
+ Type[] params = Type.getArgumentTypes(desc);
+ int argSize = params.length;
+ int ownerSize = opcode==INVOKESTATIC ? 0 : 1; // TODO
+ int ssize = currentFrame.getStackSize() - argSize - ownerSize;
+ for(int i = 0; i < ssize; i++) {
+ BasicValue value = (BasicValue) currentFrame.getStack(i);
+ if(value==null) {
+ mv.visitInsn(POP);
+ } else if(value==BasicValue.UNINITIALIZED_VALUE) {
+ // TODO ??
+ } else if(value.isReference()) {
+ mv.visitVarInsn(ALOAD, stackRecorderVar);
+ mv.visitInsn(SWAP);
+ mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, PUSH_METHOD + "Object", "(Ljava/lang/Object;)V");
+ } else {
+ Type type = value.getType();
+ mv.visitVarInsn(ALOAD, stackRecorderVar);
+ if(type.getSize()>1) {
+ mv.visitInsn(DUP); // dummy stack entry
+ mv.visitInsn(DUP2_X2); // swap2 for long/double
+ mv.visitInsn(POP2);
+ mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, getPushMethod(type), "("+type.getDescriptor()+")V");
+ mv.visitInsn(POP); // remove dummy stack entry
+ } else {
+ mv.visitInsn(SWAP);
+ mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, getPushMethod(type), "("+type.getDescriptor()+")V");
+ }
+ }
+ }
+
+ if(!isStatic) {
+ mv.visitVarInsn(ALOAD, stackRecorderVar);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, PUSH_METHOD + "Reference", "(Ljava/lang/Object;)V");
+ }
+
+ // save locals
+ int fsize = currentFrame.getLocals();
+ for( int j = 0; j<fsize; j++) {
+ BasicValue value = (BasicValue) currentFrame.getLocal(j);
+ if(value==null) {
+ // no need to save null
+ } else if(value==BasicValue.UNINITIALIZED_VALUE) {
+ // no need to save uninitialized objects
+ } else if(value.isReference()) {
+ mv.visitVarInsn(ALOAD, stackRecorderVar);
+ mv.visitVarInsn(ALOAD, j);
+ mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, PUSH_METHOD + "Object", "(Ljava/lang/Object;)V");
+ } else {
+ mv.visitVarInsn(ALOAD, stackRecorderVar);
+ Type type = value.getType();
+ mv.visitVarInsn(type.getOpcode(ILOAD), j);
+ mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, getPushMethod(type), "("+type.getDescriptor()+")V");
+ }
+ }
+
+ mv.visitVarInsn(ALOAD, stackRecorderVar);
+ mv.visitIntInsn(BIPUSH, currentIndex); // TODO optimize to iconst_0...
+ mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, "pushInt", "(I)V");
+
+ Type methodReturnType = Type.getReturnType(methodDesc);
+ pushDefault(methodReturnType);
+ mv.visitInsn(methodReturnType.getOpcode(IRETURN));
+ mv.visitLabel(fl);
+
+ currentIndex++;
+ currentFrame = null;
+ }
+ }
+
+
+ public void visitMaxs( int maxStack, int maxLocals) {
+ Label endLabel = new Label();
+ mv.visitLabel(endLabel);
+
+ mv.visitLocalVariable("__stackRecorder", "L"+STACK_RECORDER+";", null, startLabel, endLabel, stackRecorderVar);
+
+ mv.visitMaxs(0, 0);
+ }
+
+ void pushDefault(Type type) {
+ switch(type.getSort()) {
+ case Type.VOID:
+ break;
+ case Type.DOUBLE:
+ mv.visitInsn(DCONST_0);
+ break;
+ case Type.LONG:
+ mv.visitInsn(LCONST_0);
+ break;
+ case Type.FLOAT:
+ mv.visitInsn(FCONST_0);
+ break;
+ case Type.OBJECT:
+ case Type.ARRAY:
+ mv.visitInsn(ACONST_NULL);
+ break;
+ default:
+ mv.visitInsn(ICONST_0);
+ break;
+ }
+ }
+
+ private static String[] SUFFIXES = {
+ "Object", // 0 void
+ "Int", // 1 boolean
+ "Int", // 2 char
+ "Int", // 3 byte
+ "Int", // 4 short
+ "Int", // 5 int
+ "Float", // 6 float
+ "Long", // 7 long
+ "Double", // 8 double
+ "Object", // 9 array
+ "Object", // 10 object
+ };
+
+
+ String getPopMethod(Type type) {
+ return POP_METHOD + SUFFIXES[type.getSort()];
+ }
+
+ String getPushMethod(Type type) {
+ return PUSH_METHOD + SUFFIXES[type.getSort()];
+ }
+
+}
+
Propchange: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAdapter.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAdapter.java
------------------------------------------------------------------------------
svn:keywords = Id
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org