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