You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by ko...@apache.org on 2006/01/04 08:41:13 UTC
svn commit: r365853 -
/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAnalyzer.java
Author: kohsuke
Date: Tue Jan 3 23:41:11 2006
New Revision: 365853
URL: http://svn.apache.org/viewcvs?rev=365853&view=rev
Log:
applied another patch (but this time manually!) from Eugene.
Modified:
jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAnalyzer.java
Modified: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAnalyzer.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAnalyzer.java?rev=365853&r1=365852&r2=365853&view=diff
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAnalyzer.java (original)
+++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAnalyzer.java Tue Jan 3 23:41:11 2006
@@ -38,12 +38,12 @@
import org.objectweb.asm.tree.analysis.DataflowInterpreter;
import org.objectweb.asm.tree.analysis.DataflowValue;
import org.objectweb.asm.tree.analysis.Frame;
-import org.objectweb.asm.tree.analysis.BasicVerifier;
+import org.objectweb.asm.tree.analysis.SimpleVerifier;
/**
* ContinuationMethodAdapter
- *
+ *
* @author Evgueni Koulechov
*/
public class ContinuationMethodAnalyzer extends MethodNode implements Opcodes {
@@ -84,14 +84,34 @@
public void visitEnd() {
if(instructions.size()==0 || labels.size()==0) {
accept(mv);
- return;
- }
-
- this.stackRecorderVar = maxLocals;
- try {
- moveNew();
+ return;
+ }
- analyzer = new Analyzer(new BasicVerifier());
+ this.stackRecorderVar = maxLocals;
+ try {
+ moveNew();
+
+// TraceMethodVisitor mv = new TraceMethodVisitor();
+// System.err.println(name + desc);
+// for (int j = 0; j < instructions.size(); ++j) {
+// ((AbstractInsnNode) instructions.get(j)).accept(mv);
+// System.err.print(" " + mv.text.get(j)); // mv.text.get(j));
+// }
+// System.err.println();
+
+ // analyzer = new Analyzer(new BasicVerifier());
+ analyzer = new Analyzer(new SimpleVerifier() {
+ protected Class getClass( Type t) {
+ try {
+ if (t.getSort() == Type.ARRAY) {
+ return Class.forName(t.getDescriptor().replace('/', '.'), true, Thread.currentThread().getContextClassLoader());
+ }
+ return Class.forName(t.getClassName(), true, Thread.currentThread().getContextClassLoader());
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+ });
analyzer.analyze(className, this);
accept(new ContinuationMethodAdapter(this));
@@ -124,63 +144,121 @@
AbstractInsnNode ins = (AbstractInsnNode) it.next();
if(ins.getOpcode()==NEW) {
movable.put(ins, mnode);
- } else if(ins.getOpcode()==DUP) {
+ } else {
+ // other known patterns
int n1 = a.getIndex(ins);
- AbstractInsnNode ins1 = (AbstractInsnNode) instructions.get(n1-1);
- if(ins1.getOpcode()==NEW) {
- movable.put(ins1, mnode);
+ if(ins.getOpcode()==DUP) { // <init> with params
+ AbstractInsnNode ins1 = (AbstractInsnNode) instructions.get(n1-1);
+ if(ins1.getOpcode()==NEW) {
+ movable.put(ins1, mnode);
+ }
+ } else if(ins.getOpcode()==SWAP) { // in exception handler
+ AbstractInsnNode ins1 = (AbstractInsnNode) instructions.get(n1-1);
+ AbstractInsnNode ins2 = (AbstractInsnNode) instructions.get(n1-2);
+ if(ins1.getOpcode()==DUP_X1 && ins2.getOpcode()==NEW) {
+ movable.put(ins2, mnode);
+ }
}
- }
- }
+ }
+ }
}
- for( Iterator it = movable.entrySet().iterator(); it.hasNext();) {
- Map.Entry e = (Map.Entry) it.next();
- AbstractInsnNode node1 = (AbstractInsnNode) e.getKey();
- int n1 = instructions.indexOf(node1);
- AbstractInsnNode node2 = (AbstractInsnNode) instructions.get(n1+1);
- boolean hasCopy = node2.getOpcode()==DUP;
-
- instructions.remove(node1); // NEW
- if(hasCopy) {
- instructions.remove(node2); // DUP
- }
+ int updateMaxStack = 0;
+ for( Iterator it = movable.entrySet().iterator(); it.hasNext();) {
+ Map.Entry e = (Map.Entry) it.next();
+ AbstractInsnNode node1 = (AbstractInsnNode) e.getKey();
+ int n1 = instructions.indexOf(node1);
+ AbstractInsnNode node2 = (AbstractInsnNode) instructions.get(n1+1);
+ AbstractInsnNode node3 = (AbstractInsnNode) instructions.get(n1+2);
+ int producer = node2.getOpcode();
+
+ instructions.remove(node1); // NEW
+ boolean requireDup = false;
+ if(producer==DUP) {
+ instructions.remove(node2); // DUP
+ requireDup = true;
+ } else if(producer==DUP_X1) {
+ instructions.remove(node2); // DUP_X1
+ instructions.remove(node3); // SWAP
+ requireDup = true;
+ }
- MethodInsnNode mnode = (MethodInsnNode) e.getValue();
- int nm = instructions.indexOf(mnode);
+ MethodInsnNode mnode = (MethodInsnNode) e.getValue();
+ int nm = instructions.indexOf(mnode);
- int varOffset = stackRecorderVar+1;
- Type[] args = Type.getArgumentTypes(mnode.desc);
+ int varOffset = stackRecorderVar+1;
+ Type[] args = Type.getArgumentTypes(mnode.desc);
- // save stack
- for (int j = args.length - 1; j >= 0; j--) {
- Type type = args[j];
- instructions.add(nm++, new VarInsnNode(type.getOpcode(ISTORE), varOffset));
- varOffset += type.getSize();
- }
- if(varOffset>maxLocals) {
- maxLocals = varOffset;
- }
+ // optimizations for some common cases
+ if(args.length==0) {
+ instructions.add(nm++, node1); // NEW
+ if(requireDup) {
+ instructions.add(nm++, new InsnNode(DUP));
+ }
+ continue;
+ }
- instructions.add(nm++, node1); // NEW
- if(hasCopy) {
- instructions.add(nm++, node2); // DUP
- }
+ if(args.length==1 && args[0].getSize()==1) {
+ instructions.add(nm++, node1); // NEW
+ if(requireDup) {
+ instructions.add(nm++, new InsnNode(DUP));
+ instructions.add(nm++, new InsnNode(DUP2_X1));
+ instructions.add(nm++, new InsnNode(POP2));
+ updateMaxStack = updateMaxStack<2 ? 2 : updateMaxStack; // a two extra slots for temp values
+ } else {
+ instructions.add(nm++, new InsnNode(SWAP));
+ }
+ continue;
+ }
+
+ // TODO this one untested!
+ if((args.length==1 && args[0].getSize()==2) ||
+ (args.length==2 && args[0].getSize()==1 && args[1].getSize()==1)) {
+ instructions.add(nm++, node1); // NEW
+ if(requireDup) {
+ instructions.add(nm++, new InsnNode(DUP));
+ instructions.add(nm++, new InsnNode(DUP2_X2));
+ instructions.add(nm++, new InsnNode(POP2));
+ updateMaxStack = updateMaxStack<2 ? 2 : updateMaxStack; // a two extra slots for temp values
+ } else {
+ instructions.add(nm++, new InsnNode(DUP_X2));
+ instructions.add(nm++, new InsnNode(POP));
+ updateMaxStack = updateMaxStack<1 ? 1 : updateMaxStack; // an extra slot for temp value
+ }
+ continue;
+ }
- // restore stack
+ // generic code using temporary locals
+ // save stack
+ for (int j = args.length - 1; j >= 0; j--) {
+ Type type = args[j];
+ instructions.add(nm++, new VarInsnNode(type.getOpcode(ISTORE), varOffset));
+ varOffset += type.getSize();
+ }
+ if(varOffset>maxLocals) {
+ maxLocals = varOffset;
+ }
+
+ instructions.add(nm++, node1); // NEW
+ if(requireDup) {
+ instructions.add(nm++, new InsnNode(DUP));
+ }
+
+ // restore stack
for( int j = 0; j < args.length; j++) {
Type type = args[j];
varOffset -= type.getSize();
instructions.add(nm++, new VarInsnNode(type.getOpcode(ILOAD), varOffset));
// clean up store to avoid memory leak?
if(type.getSort()==Type.OBJECT || type.getSort()==Type.ARRAY) {
+ updateMaxStack = updateMaxStack<1 ? 1 : updateMaxStack; // an extra slot for ACONST_NULL
instructions.add(nm++, new InsnNode(ACONST_NULL));
instructions.add(nm++, new VarInsnNode(type.getOpcode(ISTORE), varOffset));
}
}
}
- // TODO: when we move the NEW instructions, we need to update the maxStacks
- // accordingly
+
+ maxStack += updateMaxStack;
}
// TODO
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org