tapestry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hls...@apache.org
Subject [3/17] TAP5-1852: Upgrade Plastic to use ASM 4.0 - Remove unused utility classes
Date Wed, 30 May 2012 19:20:36 GMT
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d6e5f413/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java
index 17b6fae..f0676b7 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java
@@ -1,6 +1,6 @@
 /***
  * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2007 INRIA, France Telecom
+ * Copyright (c) 2000-2011 INRIA, France Telecom
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -30,12 +30,12 @@
 package org.apache.tapestry5.internal.plastic.asm;
 
 /**
- * A visitor to visit a Java method. The methods of this interface must be
+ * A visitor to visit a Java method. The methods of this class must be
  * called in the following order: [ <tt>visitAnnotationDefault</tt> ] (
  * <tt>visitAnnotation</tt> | <tt>visitParameterAnnotation</tt> |
  * <tt>visitAttribute</tt> )* [ <tt>visitCode</tt> ( <tt>visitFrame</tt> |
  * <tt>visit</tt><i>X</i>Insn</tt> | <tt>visitLabel</tt> | <tt>visitTryCatchBlock</tt> |
- * <tt>visitLocalVariable</tt> | <tt>visitLineNumber</tt>)* <tt>visitMaxs</tt> ]
+ * <tt>visitLocalVariable</tt> | <tt>visitLineNumber</tt> )* <tt>visitMaxs</tt> ]
  * <tt>visitEnd</tt>. In addition, the <tt>visit</tt><i>X</i>Insn</tt>
  * and <tt>visitLabel</tt> methods must be called in the sequential order of
  * the bytecode instructions of the visited code, <tt>visitTryCatchBlock</tt>
@@ -43,10 +43,48 @@ package org.apache.tapestry5.internal.plastic.asm;
  * visited, and the <tt>visitLocalVariable</tt> and <tt>visitLineNumber</tt>
  * methods must be called <i>after</i> the labels passed as arguments have been
  * visited.
- * 
+ *
  * @author Eric Bruneton
  */
-public interface MethodVisitor {
+public abstract class MethodVisitor {
+
+    /**
+     * The ASM API version implemented by this visitor. The value of this field
+     * must be one of {@link Opcodes#ASM4}.
+     */
+    protected final int api;
+
+    /**
+     * The method visitor to which this visitor must delegate method calls. May
+     * be null.
+     */
+    protected MethodVisitor mv;
+
+    /**
+     * Constructs a new {@link MethodVisitor}.
+     *
+     * @param api the ASM API version implemented by this visitor. Must be one
+     *        of {@link Opcodes#ASM4}.
+     */
+    public MethodVisitor(final int api) {
+        this(api, null);
+    }
+
+    /**
+     * Constructs a new {@link MethodVisitor}.
+     *
+     * @param api the ASM API version implemented by this visitor. Must be one
+     *        of {@link Opcodes#ASM4}.
+     * @param mv the method visitor to which this visitor must delegate method
+     *        calls. May be null.
+     */
+    public MethodVisitor(final int api, final MethodVisitor mv) {
+        /*if (api != Opcodes.ASM4) {
+            throw new IllegalArgumentException();
+        }*/
+        this.api = api;
+        this.mv = mv;
+    }
 
     // -------------------------------------------------------------------------
     // Annotations and non standard attributes
@@ -54,7 +92,7 @@ public interface MethodVisitor {
 
     /**
      * Visits the default value of this annotation interface method.
-     * 
+     *
      * @return a visitor to the visit the actual default value of this
      *         annotation interface method, or <tt>null</tt> if this visitor
      *         is not interested in visiting this default value. The 'name'
@@ -62,43 +100,67 @@ public interface MethodVisitor {
      *         ignored. Moreover, exacly one visit method must be called on this
      *         annotation visitor, followed by visitEnd.
      */
-    AnnotationVisitor visitAnnotationDefault();
+    public AnnotationVisitor visitAnnotationDefault() {
+        if (mv != null) {
+            return mv.visitAnnotationDefault();
+        }
+        return null;
+    }
 
     /**
      * Visits an annotation of this method.
-     * 
+     *
      * @param desc the class descriptor of the annotation class.
      * @param visible <tt>true</tt> if the annotation is visible at runtime.
      * @return a visitor to visit the annotation values, or <tt>null</tt> if
      *         this visitor is not interested in visiting this annotation.
      */
-    AnnotationVisitor visitAnnotation(String desc, boolean visible);
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        if (mv != null) {
+            return mv.visitAnnotation(desc, visible);
+        }
+        return null;
+    }
 
     /**
      * Visits an annotation of a parameter this method.
-     * 
+     *
      * @param parameter the parameter index.
      * @param desc the class descriptor of the annotation class.
      * @param visible <tt>true</tt> if the annotation is visible at runtime.
      * @return a visitor to visit the annotation values, or <tt>null</tt> if
      *         this visitor is not interested in visiting this annotation.
      */
-    AnnotationVisitor visitParameterAnnotation(
+    public AnnotationVisitor visitParameterAnnotation(
         int parameter,
         String desc,
-        boolean visible);
+        boolean visible)
+    {
+        if (mv != null) {
+            return mv.visitParameterAnnotation(parameter, desc, visible);
+        }
+        return null;
+    }
 
     /**
      * Visits a non standard attribute of this method.
-     * 
+     *
      * @param attr an attribute.
      */
-    void visitAttribute(Attribute attr);
+    public void visitAttribute(Attribute attr) {
+        if (mv != null) {
+            mv.visitAttribute(attr);
+        }
+    }
 
     /**
      * Starts the visit of the method's code, if any (i.e. non abstract method).
      */
-    void visitCode();
+    public void visitCode() {
+        if (mv != null) {
+            mv.visitCode();
+        }
+    }
 
     /**
      * Visits the current state of the local variables and operand stack
@@ -126,7 +188,7 @@ public interface MethodVisitor {
      * locals are absent and with the empty stack (<code>nLocals</code> is 1,
      * 2 or 3). </li> <li>{@link Opcodes#F_FULL} representing complete frame
      * data.</li> </li> </ul>
-     * 
+     *
      * @param type the type of this stack map frame. Must be
      *        {@link Opcodes#F_NEW} for expanded frames, or
      *        {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
@@ -141,22 +203,27 @@ public interface MethodVisitor {
      *        {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
      *        {@link Opcodes#UNINITIALIZED_THIS} (long and double are
      *        represented by a single element). Reference types are represented
-     *        by String objects (representing internal names), and uninitialized 
-     *        types by Label objects (this label designates the NEW instruction 
+     *        by String objects (representing internal names), and uninitialized
+     *        types by Label objects (this label designates the NEW instruction
      *        that created this uninitialized value).
      * @param nStack the number of operand stack elements in the visited frame.
      * @param stack the operand stack types in this frame. This array must not
      *        be modified. Its content has the same format as the "local" array.
-     * @throw IllegalStateException if a frame is visited just after another
+     * @throws IllegalStateException if a frame is visited just after another
      *        one, without any instruction between the two (unless this frame
      *        is a Opcodes#F_SAME frame, in which case it is silently ignored).
      */
-    void visitFrame(
+    public void visitFrame(
         int type,
         int nLocal,
         Object[] local,
         int nStack,
-        Object[] stack);
+        Object[] stack)
+    {
+        if (mv != null) {
+            mv.visitFrame(type, nLocal, local, nStack, stack);
+        }
+    }
 
     // -------------------------------------------------------------------------
     // Normal instructions
@@ -164,7 +231,7 @@ public interface MethodVisitor {
 
     /**
      * Visits a zero operand instruction.
-     * 
+     *
      * @param opcode the opcode of the instruction to be visited. This opcode is
      *        either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2,
      *        ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, FCONST_0,
@@ -180,11 +247,15 @@ public interface MethodVisitor {
      *        FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW,
      *        MONITORENTER, or MONITOREXIT.
      */
-    void visitInsn(int opcode);
+    public void visitInsn(int opcode) {
+        if (mv != null) {
+            mv.visitInsn(opcode);
+        }
+    }
 
     /**
      * Visits an instruction with a single int operand.
-     * 
+     *
      * @param opcode the opcode of the instruction to be visited. This opcode is
      *        either BIPUSH, SIPUSH or NEWARRAY.
      * @param operand the operand of the instruction to be visited.<br> When
@@ -197,36 +268,48 @@ public interface MethodVisitor {
      *        {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT},
      *        {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.
      */
-    void visitIntInsn(int opcode, int operand);
+    public void visitIntInsn(int opcode, int operand) {
+        if (mv != null) {
+            mv.visitIntInsn(opcode, operand);
+        }
+    }
 
     /**
      * Visits a local variable instruction. A local variable instruction is an
      * instruction that loads or stores the value of a local variable.
-     * 
+     *
      * @param opcode the opcode of the local variable instruction to be visited.
      *        This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE,
      *        LSTORE, FSTORE, DSTORE, ASTORE or RET.
      * @param var the operand of the instruction to be visited. This operand is
      *        the index of a local variable.
      */
-    void visitVarInsn(int opcode, int var);
+    public void visitVarInsn(int opcode, int var) {
+        if (mv != null) {
+            mv.visitVarInsn(opcode, var);
+        }
+    }
 
     /**
      * Visits a type instruction. A type instruction is an instruction that
      * takes the internal name of a class as parameter.
-     * 
+     *
      * @param opcode the opcode of the type instruction to be visited. This
      *        opcode is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
      * @param type the operand of the instruction to be visited. This operand
-     *        must be the internal name of an object or array class (see {@link 
+     *        must be the internal name of an object or array class (see {@link
      *        Type#getInternalName() getInternalName}).
      */
-    void visitTypeInsn(int opcode, String type);
+    public void visitTypeInsn(int opcode, String type) {
+        if (mv != null) {
+            mv.visitTypeInsn(opcode, type);
+        }
+    }
 
     /**
      * Visits a field instruction. A field instruction is an instruction that
      * loads or stores the value of a field of an object.
-     * 
+     *
      * @param opcode the opcode of the type instruction to be visited. This
      *        opcode is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
      * @param owner the internal name of the field's owner class (see {@link
@@ -234,27 +317,52 @@ public interface MethodVisitor {
      * @param name the field's name.
      * @param desc the field's descriptor (see {@link Type Type}).
      */
-    void visitFieldInsn(int opcode, String owner, String name, String desc);
+    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
+        if (mv != null) {
+            mv.visitFieldInsn(opcode, owner, name, desc);
+        }
+    }
 
     /**
      * Visits a method instruction. A method instruction is an instruction that
      * invokes a method.
-     * 
+     *
      * @param opcode the opcode of the type instruction to be visited. This
-     *        opcode is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC,
-     *        INVOKEINTERFACE or INVOKEDYNAMIC.
+     *        opcode is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC
+     *        or INVOKEINTERFACE.
      * @param owner the internal name of the method's owner class (see {@link
-     *        Type#getInternalName() getInternalName})
-     *        or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#INVOKEDYNAMIC_OWNER}.
+     *        Type#getInternalName() getInternalName}).
+     * @param name the method's name.
+     * @param desc the method's descriptor (see {@link Type Type}).
+     */
+    public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+        if (mv != null) {
+            mv.visitMethodInsn(opcode, owner, name, desc);
+        }
+    }
+
+    /**
+     * Visits an invokedynamic instruction.
+     *
      * @param name the method's name.
      * @param desc the method's descriptor (see {@link Type Type}).
+     * @param bsm the bootstrap method.
+     * @param bsmArgs the bootstrap method constant arguments. Each argument
+     *        must be an {@link Integer}, {@link Float}, {@link Long},
+     *        {@link Double}, {@link String}, {@link Type} or {@link Handle}
+     *        value. This method is allowed to modify the content of the array
+     *        so a caller should expect that this array may change.
      */
-    void visitMethodInsn(int opcode, String owner, String name, String desc);
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
+        if (mv != null) {
+            mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+        }
+    }
 
     /**
      * Visits a jump instruction. A jump instruction is an instruction that may
      * jump to another instruction.
-     * 
+     *
      * @param opcode the opcode of the type instruction to be visited. This
      *        opcode is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
      *        IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ,
@@ -263,67 +371,127 @@ public interface MethodVisitor {
      *        is a label that designates the instruction to which the jump
      *        instruction may jump.
      */
-    void visitJumpInsn(int opcode, Label label);
+    public void visitJumpInsn(int opcode, Label label) {
+        if (mv != null) {
+            mv.visitJumpInsn(opcode, label);
+        }
+    }
 
     /**
      * Visits a label. A label designates the instruction that will be visited
      * just after it.
-     * 
+     *
      * @param label a {@link Label Label} object.
      */
-    void visitLabel(Label label);
+    public void visitLabel(Label label) {
+        if (mv != null) {
+            mv.visitLabel(label);
+        }
+    }
 
     // -------------------------------------------------------------------------
     // Special instructions
     // -------------------------------------------------------------------------
 
     /**
-     * Visits a LDC instruction.
-     * 
+     * Visits a LDC instruction. Note that new constant types may be added in
+     * future versions of the Java Virtual Machine. To easily detect new
+     * constant types, implementations of this method should check for
+     * unexpected constant types, like this:
+     * <pre>
+     * if (cst instanceof Integer) {
+     *   // ...
+     * } else if (cst instanceof Float) {
+     *   // ...
+     * } else if (cst instanceof Long) {
+     *   // ...
+     * } else if (cst instanceof Double) {
+     *   // ...
+     * } else if (cst instanceof String) {
+     *   // ...
+     * } else if (cst instanceof Type) {
+     *   int sort = ((Type) cst).getSort();
+     *   if (sort == Type.OBJECT) {
+     *     // ...
+     *   } else if (sort == Type.ARRAY) {
+     *     // ...
+     *   } else if (sort == Type.METHOD) {
+     *     // ...
+     *   } else {
+     *     // throw an exception
+     *   }
+     * } else if (cst instanceof Handle) {
+     *   // ...
+     * } else {
+     *   // throw an exception
+     * }</pre>
+     *
      * @param cst the constant to be loaded on the stack. This parameter must be
      *        a non null {@link Integer}, a {@link Float}, a {@link Long}, a
-     *        {@link Double} a {@link String} (or a {@link Type} for
-     *        <tt>.class</tt> constants, for classes whose version is 49.0 or
-     *        more).
+     *        {@link Double}, a {@link String}, a {@link Type} of OBJECT or ARRAY
+     *        sort for <tt>.class</tt> constants, for classes whose version is
+     *        49.0, a {@link Type} of METHOD sort or a {@link Handle} for
+     *        MethodType and MethodHandle constants, for classes whose version
+     *        is 51.0.
      */
-    void visitLdcInsn(Object cst);
+    public void visitLdcInsn(Object cst) {
+        if (mv != null) {
+            mv.visitLdcInsn(cst);
+        }
+    }
 
     /**
      * Visits an IINC instruction.
-     * 
+     *
      * @param var index of the local variable to be incremented.
      * @param increment amount to increment the local variable by.
      */
-    void visitIincInsn(int var, int increment);
+    public void visitIincInsn(int var, int increment) {
+        if (mv != null) {
+            mv.visitIincInsn(var, increment);
+        }
+    }
 
     /**
      * Visits a TABLESWITCH instruction.
-     * 
+     *
      * @param min the minimum key value.
      * @param max the maximum key value.
      * @param dflt beginning of the default handler block.
      * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
      *        the beginning of the handler block for the <tt>min + i</tt> key.
      */
-    void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels);
+    public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
+        if (mv != null) {
+            mv.visitTableSwitchInsn(min, max, dflt, labels);
+        }
+    }
 
     /**
      * Visits a LOOKUPSWITCH instruction.
-     * 
+     *
      * @param dflt beginning of the default handler block.
      * @param keys the values of the keys.
      * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
      *        the beginning of the handler block for the <tt>keys[i]</tt> key.
      */
-    void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels);
+    public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
+        if (mv != null) {
+            mv.visitLookupSwitchInsn(dflt, keys, labels);
+        }
+    }
 
     /**
      * Visits a MULTIANEWARRAY instruction.
-     * 
+     *
      * @param desc an array type descriptor (see {@link Type Type}).
      * @param dims number of dimensions of the array to allocate.
      */
-    void visitMultiANewArrayInsn(String desc, int dims);
+    public void visitMultiANewArrayInsn(String desc, int dims) {
+        if (mv != null) {
+            mv.visitMultiANewArrayInsn(desc, dims);
+        }
+    }
 
     // -------------------------------------------------------------------------
     // Exceptions table entries, debug information, max stack and max locals
@@ -331,7 +499,7 @@ public interface MethodVisitor {
 
     /**
      * Visits a try catch block.
-     * 
+     *
      * @param start beginning of the exception handler's scope (inclusive).
      * @param end end of the exception handler's scope (exclusive).
      * @param handler beginning of the exception handler's code.
@@ -342,11 +510,15 @@ public interface MethodVisitor {
      *         visited by this visitor (by the {@link #visitLabel visitLabel}
      *         method).
      */
-    void visitTryCatchBlock(Label start, Label end, Label handler, String type);
+    public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
+        if (mv != null) {
+            mv.visitTryCatchBlock(start, end, handler, type);
+        }
+    }
 
     /**
      * Visits a local variable declaration.
-     * 
+     *
      * @param name the name of a local variable.
      * @param desc the type descriptor of this local variable.
      * @param signature the type signature of this local variable. May be
@@ -361,17 +533,22 @@ public interface MethodVisitor {
      *         been visited by this visitor (by the
      *         {@link #visitLabel visitLabel} method).
      */
-    void visitLocalVariable(
+    public void visitLocalVariable(
         String name,
         String desc,
         String signature,
         Label start,
         Label end,
-        int index);
+        int index)
+    {
+        if (mv != null) {
+            mv.visitLocalVariable(name, desc, signature, start, end, index);
+        }
+    }
 
     /**
      * Visits a line number declaration.
-     * 
+     *
      * @param line a line number. This number refers to the source file from
      *        which the class was compiled.
      * @param start the first instruction corresponding to this line number.
@@ -379,21 +556,33 @@ public interface MethodVisitor {
      *         visited by this visitor (by the {@link #visitLabel visitLabel}
      *         method).
      */
-    void visitLineNumber(int line, Label start);
+    public void visitLineNumber(int line, Label start) {
+        if (mv != null) {
+            mv.visitLineNumber(line, start);
+        }
+    }
 
     /**
      * Visits the maximum stack size and the maximum number of local variables
      * of the method.
-     * 
+     *
      * @param maxStack maximum stack size of the method.
      * @param maxLocals maximum number of local variables for the method.
      */
-    void visitMaxs(int maxStack, int maxLocals);
+    public void visitMaxs(int maxStack, int maxLocals) {
+        if (mv != null) {
+            mv.visitMaxs(maxStack, maxLocals);
+        }
+    }
 
     /**
      * Visits the end of the method. This method, which is the last one to be
      * called, is used to inform the visitor that all the annotations and
      * attributes of the method have been visited.
      */
-    void visitEnd();
+    public void visitEnd() {
+        if (mv != null) {
+            mv.visitEnd();
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d6e5f413/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
index cd50a3e..70b26b8 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
@@ -1,6 +1,6 @@
 /***
  * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2007 INRIA, France Telecom
+ * Copyright (c) 2000-2011 INRIA, France Telecom
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -33,11 +33,11 @@ package org.apache.tapestry5.internal.plastic.asm;
  * A {@link MethodVisitor} that generates methods in bytecode form. Each visit
  * method of this class appends the bytecode corresponding to the visited
  * instruction to a byte vector, in the order these methods are called.
- * 
+ *
  * @author Eric Bruneton
  * @author Eugene Kuleshov
  */
-class MethodWriter implements MethodVisitor {
+class MethodWriter extends MethodVisitor {
 
     /**
      * Pseudo access flag used to denote constructors.
@@ -96,7 +96,7 @@ class MethodWriter implements MethodVisitor {
      * Indicates that the stack map frames must be recomputed from scratch. In
      * this case the maximum stack size and number of local variables is also
      * recomputed from scratch.
-     * 
+     *
      * @see #compute
      */
     private static final int FRAMES = 0;
@@ -104,24 +104,19 @@ class MethodWriter implements MethodVisitor {
     /**
      * Indicates that the maximum stack size and number of local variables must
      * be automatically computed.
-     * 
+     *
      * @see #compute
      */
     private static final int MAXS = 1;
 
     /**
      * Indicates that nothing must be automatically computed.
-     * 
+     *
      * @see #compute
      */
     private static final int NOTHING = 2;
 
     /**
-     * Next method writer (see {@link ClassWriter#firstMethod firstMethod}).
-     */
-    MethodWriter next;
-
-    /**
      * The class writer to which this method must be added.
      */
     final ClassWriter cw;
@@ -234,6 +229,11 @@ class MethodWriter implements MethodVisitor {
     private int maxLocals;
 
     /**
+     *  Number of local variables in the current stack map frame.
+     */
+    private int currentLocals;
+
+    /**
      * Number of stack map frames in the StackMapTable attribute.
      */
     private int frameCount;
@@ -251,7 +251,7 @@ class MethodWriter implements MethodVisitor {
 
     /**
      * The last frame that was written in the StackMapTable attribute.
-     * 
+     *
      * @see #frame
      */
     private int[] previousFrame;
@@ -346,7 +346,7 @@ class MethodWriter implements MethodVisitor {
 
     /**
      * Indicates what must be automatically computed.
-     * 
+     *
      * @see #FRAMES
      * @see #MAXS
      * @see #NOTHING
@@ -395,7 +395,7 @@ class MethodWriter implements MethodVisitor {
 
     /**
      * Constructs a new {@link MethodWriter}.
-     * 
+     *
      * @param cw the class writer in which the method must be added.
      * @param access the method's access flags (see {@link Opcodes}).
      * @param name the method's name.
@@ -418,10 +418,11 @@ class MethodWriter implements MethodVisitor {
         final boolean computeMaxs,
         final boolean computeFrames)
     {
+        super(Opcodes.ASM4);
         if (cw.firstMethod == null) {
             cw.firstMethod = this;
         } else {
-            cw.lastMethod.next = this;
+            cw.lastMethod.mv = this;
         }
         cw.lastMethod = this;
         this.cw = cw;
@@ -450,6 +451,7 @@ class MethodWriter implements MethodVisitor {
                 --size;
             }
             maxLocals = size;
+            currentLocals = size;
             // creates and visits the label for the first basic block
             labels = new Label();
             labels.status |= Label.PUSHED;
@@ -458,9 +460,10 @@ class MethodWriter implements MethodVisitor {
     }
 
     // ------------------------------------------------------------------------
-    // Implementation of the MethodVisitor interface
+    // Implementation of the MethodVisitor abstract class
     // ------------------------------------------------------------------------
 
+    @Override
     public AnnotationVisitor visitAnnotationDefault() {
         if (!ClassReader.ANNOTATIONS) {
             return null;
@@ -469,6 +472,7 @@ class MethodWriter implements MethodVisitor {
         return new AnnotationWriter(cw, false, annd, null, 0);
     }
 
+    @Override
     public AnnotationVisitor visitAnnotation(
         final String desc,
         final boolean visible)
@@ -490,6 +494,7 @@ class MethodWriter implements MethodVisitor {
         return aw;
     }
 
+    @Override
     public AnnotationVisitor visitParameterAnnotation(
         final int parameter,
         final String desc,
@@ -524,6 +529,7 @@ class MethodWriter implements MethodVisitor {
         return aw;
     }
 
+    @Override
     public void visitAttribute(final Attribute attr) {
         if (attr.isCodeAttribute()) {
             attr.next = cattrs;
@@ -534,9 +540,11 @@ class MethodWriter implements MethodVisitor {
         }
     }
 
+    @Override
     public void visitCode() {
     }
 
+    @Override
     public void visitFrame(
         final int type,
         final int nLocal,
@@ -549,6 +557,7 @@ class MethodWriter implements MethodVisitor {
         }
 
         if (type == Opcodes.F_NEW) {
+            currentLocals = nLocal;
             startFrame(code.length, nLocal, nStack);
             for (int i = 0; i < nLocal; ++i) {
                 if (local[i] instanceof String) {
@@ -593,6 +602,7 @@ class MethodWriter implements MethodVisitor {
 
             switch (type) {
                 case Opcodes.F_FULL:
+                    currentLocals = nLocal;
                     stackMap.putByte(FULL_FRAME)
                             .putShort(delta)
                             .putShort(nLocal);
@@ -605,6 +615,7 @@ class MethodWriter implements MethodVisitor {
                     }
                     break;
                 case Opcodes.F_APPEND:
+                    currentLocals += nLocal;
                     stackMap.putByte(SAME_FRAME_EXTENDED + nLocal)
                             .putShort(delta);
                     for (int i = 0; i < nLocal; ++i) {
@@ -612,6 +623,7 @@ class MethodWriter implements MethodVisitor {
                     }
                     break;
                 case Opcodes.F_CHOP:
+                    currentLocals -= nLocal;
                     stackMap.putByte(SAME_FRAME_EXTENDED - nLocal)
                             .putShort(delta);
                     break;
@@ -636,8 +648,12 @@ class MethodWriter implements MethodVisitor {
             previousFrameOffset = code.length;
             ++frameCount;
         }
+
+        maxStack = Math.max(maxStack, nStack);
+        maxLocals = Math.max(maxLocals, currentLocals);
     }
 
+    @Override
     public void visitInsn(final int opcode) {
         // adds the instruction to the bytecode of the method
         code.putByte(opcode);
@@ -663,6 +679,7 @@ class MethodWriter implements MethodVisitor {
         }
     }
 
+    @Override
     public void visitIntInsn(final int opcode, final int operand) {
         // Label currentBlock = this.currentBlock;
         if (currentBlock != null) {
@@ -686,6 +703,7 @@ class MethodWriter implements MethodVisitor {
         }
     }
 
+    @Override
     public void visitVarInsn(final int opcode, final int var) {
         // Label currentBlock = this.currentBlock;
         if (currentBlock != null) {
@@ -744,6 +762,7 @@ class MethodWriter implements MethodVisitor {
         }
     }
 
+    @Override
     public void visitTypeInsn(final int opcode, final String type) {
         Item i = cw.newClassItem(type);
         // Label currentBlock = this.currentBlock;
@@ -764,6 +783,7 @@ class MethodWriter implements MethodVisitor {
         code.put12(opcode, i.index);
     }
 
+    @Override
     public void visitFieldInsn(
         final int opcode,
         final String owner,
@@ -805,6 +825,7 @@ class MethodWriter implements MethodVisitor {
         code.put12(opcode, i.index);
     }
 
+    @Override
     public void visitMethodInsn(
         final int opcode,
         final String owner,
@@ -812,9 +833,7 @@ class MethodWriter implements MethodVisitor {
         final String desc)
     {
         boolean itf = opcode == Opcodes.INVOKEINTERFACE;
-        Item i = (opcode == Opcodes.INVOKEDYNAMIC) ?
-                cw.newNameTypeItem(name, desc):
-                cw.newMethodItem(owner, name, desc, itf);
+        Item i = cw.newMethodItem(owner, name, desc, itf);
         int argSize = i.intVal;
         // Label currentBlock = this.currentBlock;
         if (currentBlock != null) {
@@ -838,7 +857,7 @@ class MethodWriter implements MethodVisitor {
                     i.intVal = argSize;
                 }
                 int size;
-                if (opcode == Opcodes.INVOKESTATIC || opcode == Opcodes.INVOKEDYNAMIC) {
+                if (opcode == Opcodes.INVOKESTATIC) {
                     size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1;
                 } else {
                     size = stackSize - (argSize >> 2) + (argSize & 0x03);
@@ -859,12 +878,54 @@ class MethodWriter implements MethodVisitor {
             code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0);
         } else {
             code.put12(opcode, i.index);
-            if (opcode==Opcodes.INVOKEDYNAMIC) {
-                code.putShort(0);
+        }
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(
+        final String name,
+        final String desc,
+        final Handle bsm,
+        final Object... bsmArgs)
+    {
+        Item i = cw.newInvokeDynamicItem(name, desc, bsm, bsmArgs);
+        int argSize = i.intVal;
+        // Label currentBlock = this.currentBlock;
+        if (currentBlock != null) {
+            if (compute == FRAMES) {
+                currentBlock.frame.execute(Opcodes.INVOKEDYNAMIC, 0, cw, i);
+            } else {
+                /*
+                 * computes the stack size variation. In order not to recompute
+                 * several times this variation for the same Item, we use the
+                 * intVal field of this item to store this variation, once it
+                 * has been computed. More precisely this intVal field stores
+                 * the sizes of the arguments and of the return value
+                 * corresponding to desc.
+                 */
+                if (argSize == 0) {
+                    // the above sizes have not been computed yet,
+                    // so we compute them...
+                    argSize = Type.getArgumentsAndReturnSizes(desc);
+                    // ... and we save them in order
+                    // not to recompute them in the future
+                    i.intVal = argSize;
+                }
+                int size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1;
+
+                // updates current and max stack sizes
+                if (size > maxStackSize) {
+                    maxStackSize = size;
+                }
+                stackSize = size;
             }
         }
+        // adds the instruction to the bytecode of the method
+        code.put12(Opcodes.INVOKEDYNAMIC, i.index);
+        code.putShort(0);
     }
 
+    @Override
     public void visitJumpInsn(final int opcode, final Label label) {
         Label nextInsn = null;
         // Label currentBlock = this.currentBlock;
@@ -956,6 +1017,7 @@ class MethodWriter implements MethodVisitor {
         }
     }
 
+    @Override
     public void visitLabel(final Label label) {
         // resolves previous forward references to label, if any
         resize |= label.resolve(this, code.length, code.data);
@@ -1010,6 +1072,7 @@ class MethodWriter implements MethodVisitor {
         }
     }
 
+    @Override
     public void visitLdcInsn(final Object cst) {
         Item i = cw.newConstItem(cst);
         // Label currentBlock = this.currentBlock;
@@ -1043,6 +1106,7 @@ class MethodWriter implements MethodVisitor {
         }
     }
 
+    @Override
     public void visitIincInsn(final int var, final int increment) {
         if (currentBlock != null) {
             if (compute == FRAMES) {
@@ -1066,11 +1130,12 @@ class MethodWriter implements MethodVisitor {
         }
     }
 
+    @Override
     public void visitTableSwitchInsn(
         final int min,
         final int max,
         final Label dflt,
-        final Label[] labels)
+        final Label... labels)
     {
         // adds the instruction to the bytecode of the method
         int source = code.length;
@@ -1085,6 +1150,7 @@ class MethodWriter implements MethodVisitor {
         visitSwitchInsn(dflt, labels);
     }
 
+    @Override
     public void visitLookupSwitchInsn(
         final Label dflt,
         final int[] keys,
@@ -1130,6 +1196,7 @@ class MethodWriter implements MethodVisitor {
         }
     }
 
+    @Override
     public void visitMultiANewArrayInsn(final String desc, final int dims) {
         Item i = cw.newClassItem(desc);
         // Label currentBlock = this.currentBlock;
@@ -1146,6 +1213,7 @@ class MethodWriter implements MethodVisitor {
         code.put12(Opcodes.MULTIANEWARRAY, i.index).putByte(dims);
     }
 
+    @Override
     public void visitTryCatchBlock(
         final Label start,
         final Label end,
@@ -1167,6 +1235,7 @@ class MethodWriter implements MethodVisitor {
         lastHandler = h;
     }
 
+    @Override
     public void visitLocalVariable(
         final String name,
         final String desc,
@@ -1205,6 +1274,7 @@ class MethodWriter implements MethodVisitor {
         }
     }
 
+    @Override
     public void visitLineNumber(final int line, final Label start) {
         if (lineNumber == null) {
             lineNumber = new ByteVector();
@@ -1214,6 +1284,7 @@ class MethodWriter implements MethodVisitor {
         lineNumber.putShort(line);
     }
 
+    @Override
     public void visitMaxs(final int maxStack, final int maxLocals) {
         if (ClassReader.FRAMES && compute == FRAMES) {
             // completes the control flow graph with exception handler blocks
@@ -1315,11 +1386,20 @@ class MethodWriter implements MethodVisitor {
                         frame[frameIndex++] = Frame.OBJECT
                                 | cw.addType("java/lang/Throwable");
                         endFrame();
+                        // removes the start-end range from the exception handlers
+                        firstHandler = Handler.remove(firstHandler, l, k);
                     }
                 }
                 l = l.successor;
             }
-            
+
+            handler = firstHandler;
+            handlerCount = 0;
+            while (handler != null) {
+                handlerCount += 1;
+                handler = handler.next;
+            }
+
             this.maxStack = max;
         } else if (compute == MAXS) {
             // completes the control flow graph with exception handler blocks
@@ -1437,13 +1517,14 @@ class MethodWriter implements MethodVisitor {
                     b = b.next;
                 }
             }
-            this.maxStack = max;
+            this.maxStack = Math.max(maxStack, max);
         } else {
             this.maxStack = maxStack;
             this.maxLocals = maxLocals;
         }
     }
 
+    @Override
     public void visitEnd() {
     }
 
@@ -1453,7 +1534,7 @@ class MethodWriter implements MethodVisitor {
 
     /**
      * Adds a successor to the {@link #currentBlock currentBlock} block.
-     * 
+     *
      * @param info information about the control flow edge to be added.
      * @param successor the successor block to be added to the current block.
      */
@@ -1491,7 +1572,7 @@ class MethodWriter implements MethodVisitor {
 
     /**
      * Visits a frame that has been computed from scratch.
-     * 
+     *
      * @param f the frame that must be visited.
      */
     private void visitFrame(final Frame f) {
@@ -1545,7 +1626,7 @@ class MethodWriter implements MethodVisitor {
 
     /**
      * Starts the visit of a stack map frame.
-     * 
+     *
      * @param offset the offset of the instruction to which the frame
      *        corresponds.
      * @param nLocal the number of local variables in the frame.
@@ -1675,7 +1756,7 @@ class MethodWriter implements MethodVisitor {
      * StackMapTableAttribute. This method converts types from the format used
      * in {@link Label} to the format used in StackMapTable attributes. In
      * particular, it converts type table indexes to constant pool indexes.
-     * 
+     *
      * @param start index of the first type in {@link #frame} to write.
      * @param end index of last type in {@link #frame} to write (exclusive).
      */
@@ -1754,7 +1835,7 @@ class MethodWriter implements MethodVisitor {
 
     /**
      * Returns the size of the bytecode of this method.
-     * 
+     *
      * @return the size of the bytecode of this method.
      */
     final int getSize() {
@@ -1771,6 +1852,9 @@ class MethodWriter implements MethodVisitor {
         }
         int size = 8;
         if (code.length > 0) {
+            if (code.length > 65536) {
+                throw new RuntimeException("Method code too large!");
+            }
             cw.newUTF8("Code");
             size += 18 + code.length + 8 * handlerCount;
             if (localVar != null) {
@@ -1851,7 +1935,7 @@ class MethodWriter implements MethodVisitor {
 
     /**
      * Puts the bytecode of this method in the given byte vector.
-     * 
+     *
      * @param out the byte vector into which the bytecode of this method must be
      *        copied.
      */
@@ -2054,17 +2138,17 @@ class MethodWriter implements MethodVisitor {
          * so on. The first step of the algorithm consists in finding all the
          * instructions that need to be resized, without modifying the code.
          * This is done by the following "fix point" algorithm:
-         * 
+         *
          * Parse the code to find the jump instructions whose offset will need
          * more than 2 bytes to be stored (the future offset is computed from
          * the current offset and from the number of bytes that will be inserted
          * or removed between the source and target instructions). For each such
          * instruction, adds an entry in (a copy of) the indexes and sizes
          * arrays (if this has not already been done in a previous iteration!).
-         * 
+         *
          * If at least one entry has been added during the previous step, go
          * back to the beginning, otherwise stop.
-         * 
+         *
          * In fact the real algorithm is complicated by the fact that the size
          * of TABLESWITCH and LOOKUPSWITCH instructions depends on their
          * position in the bytecode (because of padding). In order to ensure the
@@ -2191,7 +2275,8 @@ class MethodWriter implements MethodVisitor {
                     case ClassWriter.IINC_INSN:
                         u += 3;
                         break;
-                    case ClassWriter.ITFDYNMETH_INSN:
+                    case ClassWriter.ITFMETH_INSN:
+                    case ClassWriter.INDYMETH_INSN:
                         u += 5;
                         break;
                     // case ClassWriter.MANA_INSN:
@@ -2354,7 +2439,8 @@ class MethodWriter implements MethodVisitor {
                     newCode.putByteArray(b, u, 3);
                     u += 3;
                     break;
-                case ClassWriter.ITFDYNMETH_INSN:
+                case ClassWriter.ITFMETH_INSN:
+                case ClassWriter.INDYMETH_INSN:
                     newCode.putByteArray(b, u, 5);
                     u += 5;
                     break;
@@ -2467,7 +2553,7 @@ class MethodWriter implements MethodVisitor {
 
     /**
      * Reads an unsigned short value in the given byte array.
-     * 
+     *
      * @param b a byte array.
      * @param index the start index of the value to be read.
      * @return the read value.
@@ -2478,7 +2564,7 @@ class MethodWriter implements MethodVisitor {
 
     /**
      * Reads a signed short value in the given byte array.
-     * 
+     *
      * @param b a byte array.
      * @param index the start index of the value to be read.
      * @return the read value.
@@ -2489,7 +2575,7 @@ class MethodWriter implements MethodVisitor {
 
     /**
      * Reads a signed int value in the given byte array.
-     * 
+     *
      * @param b a byte array.
      * @param index the start index of the value to be read.
      * @return the read value.
@@ -2501,7 +2587,7 @@ class MethodWriter implements MethodVisitor {
 
     /**
      * Writes a short value in the given byte array.
-     * 
+     *
      * @param b a byte array.
      * @param index where the first byte of the short value must be written.
      * @param s the value to be written in the given byte array.
@@ -2516,7 +2602,7 @@ class MethodWriter implements MethodVisitor {
      * to have several entries for the same instruction in the <tt>indexes</tt>
      * and <tt>sizes</tt>: two entries (index=a,size=b) and (index=a,size=b')
      * are equivalent to a single entry (index=a,size=b+b').
-     * 
+     *
      * @param indexes current positions of the instructions to be resized. Each
      *        instruction must be designated by the index of its <i>last</i>
      *        byte, plus one (or, in other words, by the index of the <i>first</i>
@@ -2553,7 +2639,7 @@ class MethodWriter implements MethodVisitor {
 
     /**
      * Updates the offset of the given label.
-     * 
+     *
      * @param indexes current positions of the instructions to be resized. Each
      *        instruction must be designated by the index of its <i>last</i>
      *        byte, plus one (or, in other words, by the index of the <i>first</i>

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d6e5f413/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java
index 18ccda6..ac7c671 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java
@@ -1,6 +1,6 @@
 /***
  * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2007 INRIA, France Telecom
+ * Copyright (c) 2000-2011 INRIA, France Telecom
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -37,12 +37,16 @@ package org.apache.tapestry5.internal.plastic.asm;
  * opcodes are therefore not defined in this interface. Likewise for LDC,
  * automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and
  * JSR_W.
- * 
+ *
  * @author Eric Bruneton
  * @author Eugene Kuleshov
  */
 public interface Opcodes {
 
+    // ASM API versions
+
+    int ASM4 = 4 << 16 | 0 << 8 | 0;
+
     // versions
 
     int V1_1 = 3 << 16 | 45;
@@ -89,6 +93,18 @@ public interface Opcodes {
     int T_INT = 10;
     int T_LONG = 11;
 
+    // tags for Handle
+
+    int H_GETFIELD = 1;
+    int H_GETSTATIC = 2;
+    int H_PUTFIELD = 3;
+    int H_PUTSTATIC = 4;
+    int H_INVOKEVIRTUAL = 5;
+    int H_INVOKESTATIC = 6;
+    int H_INVOKESPECIAL = 7;
+    int H_NEWINVOKESPECIAL = 8;
+    int H_INVOKEINTERFACE = 9;
+
     // stack map frame types
 
     /**
@@ -135,11 +151,6 @@ public interface Opcodes {
     Integer NULL = new Integer(5);
     Integer UNINITIALIZED_THIS = new Integer(6);
 
-    /** 
-     * Represents a owner of an invokedynamic call.
-     */
-    String INVOKEDYNAMIC_OWNER = "java/lang/dyn/Dynamic";
-    
     // opcodes // visit method (- = idem)
 
     int NOP = 0; // visitInsn
@@ -328,7 +339,7 @@ public interface Opcodes {
     int INVOKESPECIAL = 183; // -
     int INVOKESTATIC = 184; // -
     int INVOKEINTERFACE = 185; // -
-    int INVOKEDYNAMIC = 186; // -
+    int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsn
     int NEW = 187; // visitTypeInsn
     int NEWARRAY = 188; // visitIntInsn
     int ANEWARRAY = 189; // visitTypeInsn

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d6e5f413/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java
index c1d3e27..6011aa4 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java
@@ -1,6 +1,6 @@
 /***
  * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2007 INRIA, France Telecom
+ * Copyright (c) 2000-2011 INRIA, France Telecom
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -33,9 +33,9 @@ import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 
 /**
- * A Java type. This class can be used to make it easier to manipulate type and
- * method descriptors.
- * 
+ * A Java field or method type. This class can be used to make it easier to
+ * manipulate type and method descriptors.
+ *
  * @author Eric Bruneton
  * @author Chris Nokleberg
  */
@@ -92,11 +92,16 @@ public class Type {
     public static final int ARRAY = 9;
 
     /**
-     * The sort of object reference type. See {@link #getSort getSort}.
+     * The sort of object reference types. See {@link #getSort getSort}.
      */
     public static final int OBJECT = 10;
 
     /**
+     * The sort of method types. See {@link #getSort getSort}.
+     */
+    public static final int METHOD = 11;
+
+    /**
      * The <tt>void</tt> type.
      */
     public static final Type VOID_TYPE = new Type(VOID, null, ('V' << 24)
@@ -184,7 +189,7 @@ public class Type {
 
     /**
      * Constructs a reference type.
-     * 
+     *
      * @param sort the sort of the reference type to be constructed.
      * @param buf a buffer containing the descriptor of the previous type.
      * @param off the offset of this descriptor in the previous buffer.
@@ -200,8 +205,8 @@ public class Type {
 
     /**
      * Returns the Java type corresponding to the given type descriptor.
-     * 
-     * @param typeDescriptor a type descriptor.
+     *
+     * @param typeDescriptor a field or method type descriptor.
      * @return the Java type corresponding to the given type descriptor.
      */
     public static Type getType(final String typeDescriptor) {
@@ -210,7 +215,7 @@ public class Type {
 
     /**
      * Returns the Java type corresponding to the given internal name.
-     * 
+     *
      * @param internalName an internal name.
      * @return the Java type corresponding to the given internal name.
      */
@@ -220,12 +225,35 @@ public class Type {
     }
 
     /**
+     * Returns the Java type corresponding to the given method descriptor.
+     * Equivalent to <code>Type.getType(methodDescriptor)</code>.
+     *
+     * @param methodDescriptor a method descriptor.
+     * @return the Java type corresponding to the given method descriptor.
+     */
+    public static Type getMethodType(final String methodDescriptor) {
+        return getType(methodDescriptor.toCharArray(), 0);
+    }
+
+    /**
+     * Returns the Java method type corresponding to the given argument and
+     * return types.
+     *
+     * @param returnType the return type of the method.
+     * @param argumentTypes the argument types of the method.
+     * @return the Java type corresponding to the given argument and return types.
+     */
+    public static Type getMethodType(final Type returnType, final Type... argumentTypes) {
+        return getType(getMethodDescriptor(returnType, argumentTypes));
+    }
+
+    /**
      * Returns the Java type corresponding to the given class.
-     * 
+     *
      * @param c a class.
      * @return the Java type corresponding to the given class.
      */
-    public static Type getType(final Class c) {
+    public static Type getType(final Class<?> c) {
         if (c.isPrimitive()) {
             if (c == Integer.TYPE) {
                 return INT_TYPE;
@@ -252,9 +280,29 @@ public class Type {
     }
 
     /**
+     * Returns the Java method type corresponding to the given constructor.
+     *
+     * @param c a {@link Constructor Constructor} object.
+     * @return the Java method type corresponding to the given constructor.
+     */
+    public static Type getType(final Constructor<?> c) {
+        return getType(getConstructorDescriptor(c));
+    }
+
+    /**
+     * Returns the Java method type corresponding to the given method.
+     *
+     * @param m a {@link Method Method} object.
+     * @return the Java method type corresponding to the given method.
+     */
+    public static Type getType(final Method m) {
+        return getType(getMethodDescriptor(m));
+    }
+
+    /**
      * Returns the Java types corresponding to the argument types of the given
      * method descriptor.
-     * 
+     *
      * @param methodDescriptor a method descriptor.
      * @return the Java types corresponding to the argument types of the given
      *         method descriptor.
@@ -289,13 +337,13 @@ public class Type {
     /**
      * Returns the Java types corresponding to the argument types of the given
      * method.
-     * 
+     *
      * @param method a method.
      * @return the Java types corresponding to the argument types of the given
      *         method.
      */
     public static Type[] getArgumentTypes(final Method method) {
-        Class[] classes = method.getParameterTypes();
+        Class<?>[] classes = method.getParameterTypes();
         Type[] types = new Type[classes.length];
         for (int i = classes.length - 1; i >= 0; --i) {
             types[i] = getType(classes[i]);
@@ -306,7 +354,7 @@ public class Type {
     /**
      * Returns the Java type corresponding to the return type of the given
      * method descriptor.
-     * 
+     *
      * @param methodDescriptor a method descriptor.
      * @return the Java type corresponding to the return type of the given
      *         method descriptor.
@@ -319,7 +367,7 @@ public class Type {
     /**
      * Returns the Java type corresponding to the return type of the given
      * method.
-     * 
+     *
      * @param method a method.
      * @return the Java type corresponding to the return type of the given
      *         method.
@@ -330,7 +378,7 @@ public class Type {
 
     /**
      * Computes the size of the arguments and of the return value of a method.
-     * 
+     *
      * @param desc the descriptor of a method.
      * @return the size of the arguments of the method (plus one for the
      *         implicit this argument), argSize, and the size of its return
@@ -367,8 +415,10 @@ public class Type {
     }
 
     /**
-     * Returns the Java type corresponding to the given type descriptor.
-     * 
+     * Returns the Java type corresponding to the given type descriptor. For
+     * method descriptors, buf is supposed to contain nothing more than the
+     * descriptor itself.
+     *
      * @param buf a buffer containing a type descriptor.
      * @param off the offset of this descriptor in the previous buffer.
      * @return the Java type corresponding to the given type descriptor.
@@ -406,13 +456,15 @@ public class Type {
                     }
                 }
                 return new Type(ARRAY, buf, off, len + 1);
-                // case 'L':
-            default:
+            case 'L':
                 len = 1;
                 while (buf[off + len] != ';') {
                     ++len;
                 }
                 return new Type(OBJECT, buf, off + 1, len - 1);
+            // case '(':
+            default:
+                return new Type(METHOD, buf, 0, buf.length);
         }
     }
 
@@ -422,12 +474,12 @@ public class Type {
 
     /**
      * Returns the sort of this Java type.
-     * 
+     *
      * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN},
      *         {@link #CHAR CHAR}, {@link #BYTE BYTE}, {@link #SHORT SHORT},
      *         {@link #INT INT}, {@link #FLOAT FLOAT}, {@link #LONG LONG},
-     *         {@link #DOUBLE DOUBLE}, {@link #ARRAY ARRAY} or
-     *         {@link #OBJECT OBJECT}.
+     *         {@link #DOUBLE DOUBLE}, {@link #ARRAY ARRAY},
+     *         {@link #OBJECT OBJECT} or {@link #METHOD METHOD}.
      */
     public int getSort() {
         return sort;
@@ -436,7 +488,7 @@ public class Type {
     /**
      * Returns the number of dimensions of this array type. This method should
      * only be used for an array type.
-     * 
+     *
      * @return the number of dimensions of this array type.
      */
     public int getDimensions() {
@@ -450,7 +502,7 @@ public class Type {
     /**
      * Returns the type of the elements of this array type. This method should
      * only be used for an array type.
-     * 
+     *
      * @return Returns the type of the elements of this array type.
      */
     public Type getElementType() {
@@ -458,9 +510,10 @@ public class Type {
     }
 
     /**
-     * Returns the name of the class corresponding to this type.
-     * 
-     * @return the fully qualified name of the class corresponding to this type.
+     * Returns the binary name of the class corresponding to this type. This
+     * method must not be used on method types.
+     *
+     * @return the binary name of the class corresponding to this type.
      */
     public String getClassName() {
         switch (sort) {
@@ -488,9 +541,10 @@ public class Type {
                     b.append("[]");
                 }
                 return b.toString();
-                // case OBJECT:
-            default:
+            case OBJECT:
                 return new String(buf, off, len).replace('/', '.');
+            default:
+                return null;
         }
     }
 
@@ -499,20 +553,54 @@ public class Type {
      * array type. The internal name of a class is its fully qualified name (as
      * returned by Class.getName(), where '.' are replaced by '/'. This method
      * should only be used for an object or array type.
-     * 
+     *
      * @return the internal name of the class corresponding to this object type.
      */
     public String getInternalName() {
         return new String(buf, off, len);
     }
 
+    /**
+     * Returns the argument types of methods of this type. This method should
+     * only be used for method types.
+     *
+     * @return the argument types of methods of this type.
+     */
+    public Type[] getArgumentTypes() {
+        return getArgumentTypes(getDescriptor());
+    }
+
+    /**
+     * Returns the return type of methods of this type. This method should only
+     * be used for method types.
+     *
+     * @return the return type of methods of this type.
+     */
+    public Type getReturnType() {
+        return getReturnType(getDescriptor());
+    }
+
+    /**
+     * Returns the size of the arguments and of the return value of methods of
+     * this type. This method should only be used for method types.
+     *
+     * @return the size of the arguments (plus one for the implicit this
+     *         argument), argSize, and the size of the return value, retSize,
+     *         packed into a single int i = <tt>(argSize << 2) | retSize</tt>
+     *         (argSize is therefore equal to <tt>i >> 2</tt>, and retSize to
+     *         <tt>i & 0x03</tt>).
+     */
+    public int getArgumentsAndReturnSizes() {
+        return getArgumentsAndReturnSizes(getDescriptor());
+    }
+
     // ------------------------------------------------------------------------
     // Conversion to type descriptors
     // ------------------------------------------------------------------------
 
     /**
      * Returns the descriptor corresponding to this Java type.
-     * 
+     *
      * @return the descriptor corresponding to this Java type.
      */
     public String getDescriptor() {
@@ -524,7 +612,7 @@ public class Type {
     /**
      * Returns the descriptor corresponding to the given argument and return
      * types.
-     * 
+     *
      * @param returnType the return type of the method.
      * @param argumentTypes the argument types of the method.
      * @return the descriptor corresponding to the given argument and return
@@ -532,7 +620,7 @@ public class Type {
      */
     public static String getMethodDescriptor(
         final Type returnType,
-        final Type[] argumentTypes)
+        final Type... argumentTypes)
     {
         StringBuffer buf = new StringBuffer();
         buf.append('(');
@@ -547,19 +635,19 @@ public class Type {
     /**
      * Appends the descriptor corresponding to this Java type to the given
      * string buffer.
-     * 
+     *
      * @param buf the string buffer to which the descriptor must be appended.
      */
     private void getDescriptor(final StringBuffer buf) {
         if (this.buf == null) {
             // descriptor is in byte 3 of 'off' for primitive types (buf == null)
             buf.append((char) ((off & 0xFF000000) >>> 24));
-        } else if (sort == ARRAY) {
-            buf.append(this.buf, off, len);
-        } else { // sort == OBJECT
+        } else if (sort == OBJECT) {
             buf.append('L');
             buf.append(this.buf, off, len);
             buf.append(';');
+        } else { // sort == ARRAY || sort == METHOD
+            buf.append(this.buf, off, len);
         }
     }
 
@@ -572,21 +660,21 @@ public class Type {
      * Returns the internal name of the given class. The internal name of a
      * class is its fully qualified name, as returned by Class.getName(), where
      * '.' are replaced by '/'.
-     * 
+     *
      * @param c an object or array class.
      * @return the internal name of the given class.
      */
-    public static String getInternalName(final Class c) {
+    public static String getInternalName(final Class<?> c) {
         return c.getName().replace('.', '/');
     }
 
     /**
      * Returns the descriptor corresponding to the given Java type.
-     * 
+     *
      * @param c an object class, a primitive class or an array class.
      * @return the descriptor corresponding to the given class.
      */
-    public static String getDescriptor(final Class c) {
+    public static String getDescriptor(final Class<?> c) {
         StringBuffer buf = new StringBuffer();
         getDescriptor(buf, c);
         return buf.toString();
@@ -594,12 +682,12 @@ public class Type {
 
     /**
      * Returns the descriptor corresponding to the given constructor.
-     * 
+     *
      * @param c a {@link Constructor Constructor} object.
      * @return the descriptor of the given constructor.
      */
-    public static String getConstructorDescriptor(final Constructor c) {
-        Class[] parameters = c.getParameterTypes();
+    public static String getConstructorDescriptor(final Constructor<?> c) {
+        Class<?>[] parameters = c.getParameterTypes();
         StringBuffer buf = new StringBuffer();
         buf.append('(');
         for (int i = 0; i < parameters.length; ++i) {
@@ -610,12 +698,12 @@ public class Type {
 
     /**
      * Returns the descriptor corresponding to the given method.
-     * 
+     *
      * @param m a {@link Method Method} object.
      * @return the descriptor of the given method.
      */
     public static String getMethodDescriptor(final Method m) {
-        Class[] parameters = m.getParameterTypes();
+        Class<?>[] parameters = m.getParameterTypes();
         StringBuffer buf = new StringBuffer();
         buf.append('(');
         for (int i = 0; i < parameters.length; ++i) {
@@ -628,12 +716,12 @@ public class Type {
 
     /**
      * Appends the descriptor of the given class to the given string buffer.
-     * 
+     *
      * @param buf the string buffer to which the descriptor must be appended.
      * @param c the class whose descriptor must be computed.
      */
-    private static void getDescriptor(final StringBuffer buf, final Class c) {
-        Class d = c;
+    private static void getDescriptor(final StringBuffer buf, final Class<?> c) {
+        Class<?> d = c;
         while (true) {
             if (d.isPrimitive()) {
                 char car;
@@ -680,8 +768,9 @@ public class Type {
     // ------------------------------------------------------------------------
 
     /**
-     * Returns the size of values of this type.
-     * 
+     * Returns the size of values of this type. This method must not be used for
+     * method types.
+     *
      * @return the size of values of this type, i.e., 2 for <tt>long</tt> and
      *         <tt>double</tt>, 0 for <tt>void</tt> and 1 otherwise.
      */
@@ -691,8 +780,9 @@ public class Type {
     }
 
     /**
-     * Returns a JVM instruction opcode adapted to this Java type.
-     * 
+     * Returns a JVM instruction opcode adapted to this Java type. This method
+     * must not be used for method types.
+     *
      * @param opcode a JVM instruction opcode. This opcode must be one of ILOAD,
      *        ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL,
      *        ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
@@ -718,10 +808,11 @@ public class Type {
 
     /**
      * Tests if the given object is equal to this type.
-     * 
+     *
      * @param o the object to be compared to this type.
      * @return <tt>true</tt> if the given object is equal to this type.
      */
+    @Override
     public boolean equals(final Object o) {
         if (this == o) {
             return true;
@@ -733,7 +824,7 @@ public class Type {
         if (sort != t.sort) {
             return false;
         }
-        if (sort == OBJECT || sort == ARRAY) {
+        if (sort >= ARRAY) {
             if (len != t.len) {
                 return false;
             }
@@ -748,12 +839,13 @@ public class Type {
 
     /**
      * Returns a hash code value for this type.
-     * 
+     *
      * @return a hash code value for this type.
      */
+    @Override
     public int hashCode() {
         int hc = 13 * sort;
-        if (sort == OBJECT || sort == ARRAY) {
+        if (sort >= ARRAY) {
             for (int i = off, end = i + len; i < end; i++) {
                 hc = 17 * (hc + buf[i]);
             }
@@ -763,9 +855,10 @@ public class Type {
 
     /**
      * Returns a string representation of this type.
-     * 
+     *
      * @return the descriptor of this type.
      */
+    @Override
     public String toString() {
         return getDescriptor();
     }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d6e5f413/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/attrs/package.html
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/attrs/package.html b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/attrs/package.html
index 51f0a02..28d827d 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/attrs/package.html
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/attrs/package.html
@@ -1,7 +1,7 @@
 <html>
 <!--
  * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2005 INRIA, France Telecom
+ * Copyright (c) 2000-2011 INRIA, France Telecom
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -37,9 +37,9 @@ By default ASM strips optional attributes, in order to keep them in
 the bytecode that is being readed you should pass an array of required attribute
 instances to {@link org.objectweb.asm.ClassReader#accept(org.objectweb.asm.ClassVisitor, org.objectweb.asm.Attribute[], boolean) ClassReader.accept()} method.
 In order to add custom attributes to the manually constructed bytecode concrete
-subclasses of the {@link org.objectweb.asm.Attribute Attribute} can be passed to 
-the visitAttribute methods of the 
-{@link org.objectweb.asm.ClassVisitor ClassVisitor}, 
+subclasses of the {@link org.objectweb.asm.Attribute Attribute} can be passed to
+the visitAttribute methods of the
+{@link org.objectweb.asm.ClassVisitor ClassVisitor},
 {@link org.objectweb.asm.FieldVisitor FieldVisitor} and
 {@link org.objectweb.asm.MethodVisitor MethodVisitor} interfaces.
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d6e5f413/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java
deleted file mode 100644
index f50b84c..0000000
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java
+++ /dev/null
@@ -1,613 +0,0 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2007 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.apache.tapestry5.internal.plastic.asm.commons;
-
-import org.apache.tapestry5.internal.plastic.asm.Label;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import org.apache.tapestry5.internal.plastic.asm.Type;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A {@link org.apache.tapestry5.internal.plastic.asm.MethodAdapter} to insert before, after and around
- * advices in methods and constructors. <p> The behavior for constructors is
- * like this: <ol>
- *
- * <li>as long as the INVOKESPECIAL for the object initialization has not been
- * reached, every bytecode instruction is dispatched in the ctor code visitor</li>
- *
- * <li>when this one is reached, it is only added in the ctor code visitor and
- * a JP invoke is added</li>
- *
- * <li>after that, only the other code visitor receives the instructions</li>
- *
- * </ol>
- *
- * @author Eugene Kuleshov
- * @author Eric Bruneton
- */
-public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes
-{
-    private static final Object THIS = new Object();
-    private static final Object OTHER = new Object();
-
-    protected int methodAccess;
-    protected String methodDesc;
-
-    private boolean constructor;
-    private boolean superInitialized;
-    private List stackFrame;
-    private Map branches;
-
-    /**
-     * Creates a new {@link AdviceAdapter}.
-     *
-     * @param mv the method visitor to which this adapter delegates calls.
-     * @param access the method's access flags (see {@link Opcodes}).
-     * @param name the method's name.
-     * @param desc the method's descriptor (see {@link Type Type}).
-     */
-    protected AdviceAdapter(
-        final MethodVisitor mv,
-        final int access,
-        final String name,
-        final String desc)
-    {
-        super(mv, access, name, desc);
-        methodAccess = access;
-        methodDesc = desc;
-
-        constructor = "<init>".equals(name);
-    }
-
-    public void visitCode() {
-        mv.visitCode();
-        if (constructor) {
-            stackFrame = new ArrayList();
-            branches = new HashMap();
-        } else {
-            superInitialized = true;
-            onMethodEnter();
-        }
-    }
-
-    public void visitLabel(final Label label) {
-        mv.visitLabel(label);
-
-        if (constructor && branches != null) {
-            List frame = (List) branches.get(label);
-            if (frame != null) {
-                stackFrame = frame;
-                branches.remove(label);
-            }
-        }
-    }
-
-    public void visitInsn(final int opcode) {
-        if (constructor) {
-            int s;
-            switch (opcode) {
-                case RETURN: // empty stack
-                    onMethodExit(opcode);
-                    break;
-
-                case IRETURN: // 1 before n/a after
-                case FRETURN: // 1 before n/a after
-                case ARETURN: // 1 before n/a after
-                case ATHROW: // 1 before n/a after
-                    popValue();
-                    onMethodExit(opcode);
-                    break;
-
-                case LRETURN: // 2 before n/a after
-                case DRETURN: // 2 before n/a after
-                    popValue();
-                    popValue();
-                    onMethodExit(opcode);
-                    break;
-
-                case NOP:
-                case LALOAD: // remove 2 add 2
-                case DALOAD: // remove 2 add 2
-                case LNEG:
-                case DNEG:
-                case FNEG:
-                case INEG:
-                case L2D:
-                case D2L:
-                case F2I:
-                case I2B:
-                case I2C:
-                case I2S:
-                case I2F:
-                case ARRAYLENGTH:
-                    break;
-
-                case ACONST_NULL:
-                case ICONST_M1:
-                case ICONST_0:
-                case ICONST_1:
-                case ICONST_2:
-                case ICONST_3:
-                case ICONST_4:
-                case ICONST_5:
-                case FCONST_0:
-                case FCONST_1:
-                case FCONST_2:
-                case F2L: // 1 before 2 after
-                case F2D:
-                case I2L:
-                case I2D:
-                    pushValue(OTHER);
-                    break;
-
-                case LCONST_0:
-                case LCONST_1:
-                case DCONST_0:
-                case DCONST_1:
-                    pushValue(OTHER);
-                    pushValue(OTHER);
-                    break;
-
-                case IALOAD: // remove 2 add 1
-                case FALOAD: // remove 2 add 1
-                case AALOAD: // remove 2 add 1
-                case BALOAD: // remove 2 add 1
-                case CALOAD: // remove 2 add 1
-                case SALOAD: // remove 2 add 1
-                case POP:
-                case IADD:
-                case FADD:
-                case ISUB:
-                case LSHL: // 3 before 2 after
-                case LSHR: // 3 before 2 after
-                case LUSHR: // 3 before 2 after
-                case L2I: // 2 before 1 after
-                case L2F: // 2 before 1 after
-                case D2I: // 2 before 1 after
-                case D2F: // 2 before 1 after
-                case FSUB:
-                case FMUL:
-                case FDIV:
-                case FREM:
-                case FCMPL: // 2 before 1 after
-                case FCMPG: // 2 before 1 after
-                case IMUL:
-                case IDIV:
-                case IREM:
-                case ISHL:
-                case ISHR:
-                case IUSHR:
-                case IAND:
-                case IOR:
-                case IXOR:
-                case MONITORENTER:
-                case MONITOREXIT:
-                    popValue();
-                    break;
-
-                case POP2:
-                case LSUB:
-                case LMUL:
-                case LDIV:
-                case LREM:
-                case LADD:
-                case LAND:
-                case LOR:
-                case LXOR:
-                case DADD:
-                case DMUL:
-                case DSUB:
-                case DDIV:
-                case DREM:
-                    popValue();
-                    popValue();
-                    break;
-
-                case IASTORE:
-                case FASTORE:
-                case AASTORE:
-                case BASTORE:
-                case CASTORE:
-                case SASTORE:
-                case LCMP: // 4 before 1 after
-                case DCMPL:
-                case DCMPG:
-                    popValue();
-                    popValue();
-                    popValue();
-                    break;
-
-                case LASTORE:
-                case DASTORE:
-                    popValue();
-                    popValue();
-                    popValue();
-                    popValue();
-                    break;
-
-                case DUP:
-                    pushValue(peekValue());
-                    break;
-
-                case DUP_X1:
-                    s = stackFrame.size();
-                    stackFrame.add(s - 2, stackFrame.get(s - 1));
-                    break;
-
-                case DUP_X2:
-                    s = stackFrame.size();
-                    stackFrame.add(s - 3, stackFrame.get(s - 1));
-                    break;
-
-                case DUP2:
-                    s = stackFrame.size();
-                    stackFrame.add(s - 2, stackFrame.get(s - 1));
-                    stackFrame.add(s - 2, stackFrame.get(s - 1));
-                    break;
-
-                case DUP2_X1:
-                    s = stackFrame.size();
-                    stackFrame.add(s - 3, stackFrame.get(s - 1));
-                    stackFrame.add(s - 3, stackFrame.get(s - 1));
-                    break;
-
-                case DUP2_X2:
-                    s = stackFrame.size();
-                    stackFrame.add(s - 4, stackFrame.get(s - 1));
-                    stackFrame.add(s - 4, stackFrame.get(s - 1));
-                    break;
-
-                case SWAP:
-                    s = stackFrame.size();
-                    stackFrame.add(s - 2, stackFrame.get(s - 1));
-                    stackFrame.remove(s);
-                    break;
-            }
-        } else {
-            switch (opcode) {
-                case RETURN:
-                case IRETURN:
-                case FRETURN:
-                case ARETURN:
-                case LRETURN:
-                case DRETURN:
-                case ATHROW:
-                    onMethodExit(opcode);
-                    break;
-            }
-        }
-        mv.visitInsn(opcode);
-    }
-
-    public void visitVarInsn(final int opcode, final int var) {
-        super.visitVarInsn(opcode, var);
-
-        if (constructor) {
-            switch (opcode) {
-                case ILOAD:
-                case FLOAD:
-                    pushValue(OTHER);
-                    break;
-                case LLOAD:
-                case DLOAD:
-                    pushValue(OTHER);
-                    pushValue(OTHER);
-                    break;
-                case ALOAD:
-                    pushValue(var == 0 ? THIS : OTHER);
-                    break;
-                case ASTORE:
-                case ISTORE:
-                case FSTORE:
-                    popValue();
-                    break;
-                case LSTORE:
-                case DSTORE:
-                    popValue();
-                    popValue();
-                    break;
-            }
-        }
-    }
-
-    public void visitFieldInsn(
-        final int opcode,
-        final String owner,
-        final String name,
-        final String desc)
-    {
-        mv.visitFieldInsn(opcode, owner, name, desc);
-
-        if (constructor) {
-            char c = desc.charAt(0);
-            boolean longOrDouble = c == 'J' || c == 'D';
-            switch (opcode) {
-                case GETSTATIC:
-                    pushValue(OTHER);
-                    if (longOrDouble) {
-                        pushValue(OTHER);
-                    }
-                    break;
-                case PUTSTATIC:
-                    popValue();
-                    if (longOrDouble) {
-                        popValue();
-                    }
-                    break;
-                case PUTFIELD:
-                    popValue();
-                    if (longOrDouble) {
-                        popValue();
-                        popValue();
-                    }
-                    break;
-                // case GETFIELD:
-                default:
-                    if (longOrDouble) {
-                        pushValue(OTHER);
-                    }
-            }
-        }
-    }
-
-    public void visitIntInsn(final int opcode, final int operand) {
-        mv.visitIntInsn(opcode, operand);
-
-        if (constructor && opcode!=NEWARRAY) {
-            pushValue(OTHER);
-        }
-    }
-
-    public void visitLdcInsn(final Object cst) {
-        mv.visitLdcInsn(cst);
-
-        if (constructor) {
-            pushValue(OTHER);
-            if (cst instanceof Double || cst instanceof Long) {
-                pushValue(OTHER);
-            }
-        }
-    }
-
-    public void visitMultiANewArrayInsn(final String desc, final int dims) {
-        mv.visitMultiANewArrayInsn(desc, dims);
-
-        if (constructor) {
-            for (int i = 0; i < dims; i++) {
-                popValue();
-            }
-            pushValue(OTHER);
-        }
-    }
-
-    public void visitTypeInsn(final int opcode, final String type) {
-        mv.visitTypeInsn(opcode, type);
-
-        // ANEWARRAY, CHECKCAST or INSTANCEOF don't change stack
-        if (constructor && opcode == NEW) {
-            pushValue(OTHER);
-        }
-    }
-
-    public void visitMethodInsn(
-        final int opcode,
-        final String owner,
-        final String name,
-        final String desc)
-    {
-        mv.visitMethodInsn(opcode, owner, name, desc);
-
-        if (constructor) {
-            Type[] types = Type.getArgumentTypes(desc);
-            for (int i = 0; i < types.length; i++) {
-                popValue();
-                if (types[i].getSize() == 2) {
-                    popValue();
-                }
-            }
-            switch (opcode) {
-                // case INVOKESTATIC:
-                // case INVOKEDYNAMIC
-                // break;
-
-                case INVOKEINTERFACE:
-                case INVOKEVIRTUAL:
-                    popValue(); // objectref
-                    break;
-
-                case INVOKESPECIAL:
-                    Object type = popValue(); // objectref
-                    if (type == THIS && !superInitialized) {
-                        onMethodEnter();
-                        superInitialized = true;
-                        // once super has been initialized it is no longer
-                        // necessary to keep track of stack state
-                        constructor = false;
-                    }
-                    break;
-            }
-
-            Type returnType = Type.getReturnType(desc);
-            if (returnType != Type.VOID_TYPE) {
-                pushValue(OTHER);
-                if (returnType.getSize() == 2) {
-                    pushValue(OTHER);
-                }
-            }
-        }
-    }
-
-    public void visitJumpInsn(final int opcode, final Label label) {
-        mv.visitJumpInsn(opcode, label);
-
-        if (constructor) {
-            switch (opcode) {
-                case IFEQ:
-                case IFNE:
-                case IFLT:
-                case IFGE:
-                case IFGT:
-                case IFLE:
-                case IFNULL:
-                case IFNONNULL:
-                    popValue();
-                    break;
-
-                case IF_ICMPEQ:
-                case IF_ICMPNE:
-                case IF_ICMPLT:
-                case IF_ICMPGE:
-                case IF_ICMPGT:
-                case IF_ICMPLE:
-                case IF_ACMPEQ:
-                case IF_ACMPNE:
-                    popValue();
-                    popValue();
-                    break;
-
-                case JSR:
-                    pushValue(OTHER);
-                    break;
-            }
-            addBranch(label);
-        }
-    }
-
-    public void visitLookupSwitchInsn(
-        final Label dflt,
-        final int[] keys,
-        final Label[] labels)
-    {
-        mv.visitLookupSwitchInsn(dflt, keys, labels);
-
-        if (constructor) {
-            popValue();
-            addBranches(dflt, labels);
-        }
-    }
-
-    public void visitTableSwitchInsn(
-        final int min,
-        final int max,
-        final Label dflt,
-        final Label[] labels)
-    {
-        mv.visitTableSwitchInsn(min, max, dflt, labels);
-
-        if (constructor) {
-            popValue();
-            addBranches(dflt, labels);
-        }
-    }
-
-    private void addBranches(final Label dflt, final Label[] labels) {
-        addBranch(dflt);
-        for (int i = 0; i < labels.length; i++) {
-            addBranch(labels[i]);
-        }
-    }
-
-    private void addBranch(final Label label) {
-        if (branches.containsKey(label)) {
-            return;
-        }
-        branches.put(label, new ArrayList(stackFrame));
-    }
-
-    private Object popValue() {
-        return stackFrame.remove(stackFrame.size() - 1);
-    }
-
-    private Object peekValue() {
-        return stackFrame.get(stackFrame.size() - 1);
-    }
-
-    private void pushValue(final Object o) {
-        stackFrame.add(o);
-    }
-
-    /**
-     * Called at the beginning of the method or after super class class call in
-     * the constructor. <br><br>
-     *
-     * <i>Custom code can use or change all the local variables, but should not
-     * change state of the stack.</i>
-     */
-    protected void onMethodEnter() {
-    }
-
-    /**
-     * Called before explicit exit from the method using either return or throw.
-     * Top element on the stack contains the return value or exception instance.
-     * For example:
-     *
-     * <pre>
-     *   public void onMethodExit(int opcode) {
-     *     if(opcode==RETURN) {
-     *         visitInsn(ACONST_NULL);
-     *     } else if(opcode==ARETURN || opcode==ATHROW) {
-     *         dup();
-     *     } else {
-     *         if(opcode==LRETURN || opcode==DRETURN) {
-     *             dup2();
-     *         } else {
-     *             dup();
-     *         }
-     *         box(Type.getReturnType(this.methodDesc));
-     *     }
-     *     visitIntInsn(SIPUSH, opcode);
-     *     visitMethodInsn(INVOKESTATIC, owner, "onExit", "(Ljava/lang/Object;I)V");
-     *   }
-     *
-     *   // an actual call back method
-     *   public static void onExit(Object param, int opcode) {
-     *     ...
-     * </pre>
-     *
-     * <br><br>
-     *
-     * <i>Custom code can use or change all the local variables, but should not
-     * change state of the stack.</i>
-     *
-     * @param opcode one of the RETURN, IRETURN, FRETURN, ARETURN, LRETURN,
-     *        DRETURN or ATHROW
-     *
-     */
-    protected void onMethodExit(int opcode) {
-    }
-
-    // TODO onException, onMethodCall
-
-}


Mime
View raw message