You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by ka...@apache.org on 2014/03/25 19:29:57 UTC

[09/23] FIXED - TAP5-2214: Make tapestry5 java8 compatible - update ASM source to 5.0.1, should be jdk 1.5 compatible, see ASM bug "317132 ASM 5.0 do not supported JDK 1.5?"

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
index d2d461c..ce959df 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
@@ -1,7 +1,6 @@
 /***
  * ASM: a very small and fast Java bytecode manipulation framework
  * Copyright (c) 2000-2011 INRIA, France Telecom
- * Copyright (c) 2011 Google
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -30,22 +29,29 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
-import org.apache.tapestry5.internal.plastic.asm.*;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+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 org.apache.tapestry5.internal.plastic.asm.TypePath;
+
 /**
  * A node that represents a method.
- *
+ * 
  * @author Eric Bruneton
  */
-public class MethodNode extends MethodVisitor
-{
+public class MethodNode extends MethodVisitor {
 
     /**
-     * The method's access flags (see {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This field also
+     * The method's access flags (see {@link Opcodes}). This field also
      * indicates if the method is synthetic and/or deprecated.
      */
     public int access;
@@ -56,7 +62,7 @@ public class MethodNode extends MethodVisitor
     public String name;
 
     /**
-     * The method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+     * The method's descriptor (see {@link Type}).
      */
     public String desc;
 
@@ -67,16 +73,21 @@ public class MethodNode extends MethodVisitor
 
     /**
      * The internal names of the method's exception classes (see
-     * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). This list is a list of
+     * {@link Type#getInternalName() getInternalName}). This list is a list of
      * {@link String} objects.
      */
     public List<String> exceptions;
 
     /**
+     * The method parameter info (access flags and name)
+     */
+    public List<ParameterNode> parameters;
+
+    /**
      * The runtime visible annotations of this method. This list is a list of
      * {@link AnnotationNode} objects. May be <tt>null</tt>.
-     *
-     * @associates AnnotationNode
+     * 
+     * @associates org.objectweb.asm.tree.AnnotationNode
      * @label visible
      */
     public List<AnnotationNode> visibleAnnotations;
@@ -84,17 +95,35 @@ public class MethodNode extends MethodVisitor
     /**
      * The runtime invisible annotations of this method. This list is a list of
      * {@link AnnotationNode} objects. May be <tt>null</tt>.
-     *
-     * @associates AnnotationNode
+     * 
+     * @associates org.objectweb.asm.tree.AnnotationNode
      * @label invisible
      */
     public List<AnnotationNode> invisibleAnnotations;
 
     /**
+     * The runtime visible type annotations of this method. This list is a list
+     * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
+     * 
+     * @associates org.objectweb.asm.tree.TypeAnnotationNode
+     * @label visible
+     */
+    public List<TypeAnnotationNode> visibleTypeAnnotations;
+
+    /**
+     * The runtime invisible type annotations of this method. This list is a
+     * list of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
+     * 
+     * @associates org.objectweb.asm.tree.TypeAnnotationNode
+     * @label invisible
+     */
+    public List<TypeAnnotationNode> invisibleTypeAnnotations;
+
+    /**
      * The non standard attributes of this method. This list is a list of
-     * {@link org.apache.tapestry5.internal.plastic.asm.Attribute} objects. May be <tt>null</tt>.
-     *
-     * @associates Attribute
+     * {@link Attribute} objects. May be <tt>null</tt>.
+     * 
+     * @associates org.objectweb.asm.Attribute
      */
     public List<Attribute> attrs;
 
@@ -102,7 +131,7 @@ public class MethodNode extends MethodVisitor
      * The default value of this annotation interface method. This field must be
      * a {@link Byte}, {@link Boolean}, {@link Character}, {@link Short},
      * {@link Integer}, {@link Long}, {@link Float}, {@link Double},
-     * {@link String} or {@link org.apache.tapestry5.internal.plastic.asm.Type}, or an two elements String array (for
+     * {@link String} or {@link Type}, or an two elements String array (for
      * enumeration values), a {@link AnnotationNode}, or a {@link List} of
      * values of one of the preceding types. May be <tt>null</tt>.
      */
@@ -111,8 +140,8 @@ public class MethodNode extends MethodVisitor
     /**
      * The runtime visible parameter annotations of this method. These lists are
      * lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
-     *
-     * @associates AnnotationNode
+     * 
+     * @associates org.objectweb.asm.tree.AnnotationNode
      * @label invisible parameters
      */
     public List<AnnotationNode>[] visibleParameterAnnotations;
@@ -120,8 +149,8 @@ public class MethodNode extends MethodVisitor
     /**
      * The runtime invisible parameter annotations of this method. These lists
      * are lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
-     *
-     * @associates AnnotationNode
+     * 
+     * @associates org.objectweb.asm.tree.AnnotationNode
      * @label visible parameters
      */
     public List<AnnotationNode>[] invisibleParameterAnnotations;
@@ -129,8 +158,8 @@ public class MethodNode extends MethodVisitor
     /**
      * The instructions of this method. This list is a list of
      * {@link AbstractInsnNode} objects.
-     *
-     * @associates AbstractInsnNode
+     * 
+     * @associates org.objectweb.asm.tree.AbstractInsnNode
      * @label instructions
      */
     public InsnList instructions;
@@ -138,8 +167,8 @@ public class MethodNode extends MethodVisitor
     /**
      * The try catch blocks of this method. This list is a list of
      * {@link TryCatchBlockNode} objects.
-     *
-     * @associates TryCatchBlockNode
+     * 
+     * @associates org.objectweb.asm.tree.TryCatchBlockNode
      */
     public List<TryCatchBlockNode> tryCatchBlocks;
 
@@ -156,30 +185,53 @@ public class MethodNode extends MethodVisitor
     /**
      * The local variables of this method. This list is a list of
      * {@link LocalVariableNode} objects. May be <tt>null</tt>
-     *
-     * @associates LocalVariableNode
+     * 
+     * @associates org.objectweb.asm.tree.LocalVariableNode
      */
     public List<LocalVariableNode> localVariables;
 
     /**
+     * The visible local variable annotations of this method. This list is a
+     * list of {@link LocalVariableAnnotationNode} objects. May be <tt>null</tt>
+     * 
+     * @associates org.objectweb.asm.tree.LocalVariableAnnotationNode
+     */
+    public List<LocalVariableAnnotationNode> visibleLocalVariableAnnotations;
+
+    /**
+     * The invisible local variable annotations of this method. This list is a
+     * list of {@link LocalVariableAnnotationNode} objects. May be <tt>null</tt>
+     * 
+     * @associates org.objectweb.asm.tree.LocalVariableAnnotationNode
+     */
+    public List<LocalVariableAnnotationNode> invisibleLocalVariableAnnotations;
+
+    /**
      * If the accept method has been called on this object.
      */
     private boolean visited;
-    
+
     /**
      * Constructs an uninitialized {@link MethodNode}. <i>Subclasses must not
      * use this constructor</i>. Instead, they must use the
      * {@link #MethodNode(int)} version.
+     * 
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
      */
     public MethodNode() {
-        this(Opcodes.ASM4);
+        this(Opcodes.ASM5);
+        if (getClass() != MethodNode.class) {
+            throw new IllegalStateException();
+        }
     }
 
     /**
      * Constructs an uninitialized {@link MethodNode}.
-     *
-     * @param api the ASM API version implemented by this visitor. Must be one
-     *        of {@link Opcodes#ASM4}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
      */
     public MethodNode(final int api) {
         super(api);
@@ -190,57 +242,61 @@ public class MethodNode extends MethodVisitor
      * Constructs a new {@link MethodNode}. <i>Subclasses must not use this
      * constructor</i>. Instead, they must use the
      * {@link #MethodNode(int, int, String, String, String, String[])} version.
-     *
-     * @param access the method's access flags (see {@link Opcodes}). This
-     *        parameter also indicates if the method is synthetic and/or
-     *        deprecated.
-     * @param name the method's name.
-     * @param desc the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
-     * @param signature the method's signature. May be <tt>null</tt>.
-     * @param exceptions the internal names of the method's exception classes
-     *        (see {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). May be
-     *        <tt>null</tt>.
+     * 
+     * @param access
+     *            the method's access flags (see {@link Opcodes}). This
+     *            parameter also indicates if the method is synthetic and/or
+     *            deprecated.
+     * @param name
+     *            the method's name.
+     * @param desc
+     *            the method's descriptor (see {@link Type}).
+     * @param signature
+     *            the method's signature. May be <tt>null</tt>.
+     * @param exceptions
+     *            the internal names of the method's exception classes (see
+     *            {@link Type#getInternalName() getInternalName}). May be
+     *            <tt>null</tt>.
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
      */
-    public MethodNode(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final String[] exceptions)
-    {
-        this(Opcodes.ASM4, access, name, desc, signature, exceptions);
+    public MethodNode(final int access, final String name, final String desc,
+            final String signature, final String[] exceptions) {
+        this(Opcodes.ASM5, access, name, desc, signature, exceptions);
+        if (getClass() != MethodNode.class) {
+            throw new IllegalStateException();
+        }
     }
 
     /**
      * Constructs a new {@link MethodNode}.
-     *
-     * @param api the ASM API version implemented by this visitor. Must be one
-     *        of {@link Opcodes#ASM4}.
-     * @param access the method's access flags (see {@link Opcodes}). This
-     *        parameter also indicates if the method is synthetic and/or
-     *        deprecated.
-     * @param name the method's name.
-     * @param desc the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
-     * @param signature the method's signature. May be <tt>null</tt>.
-     * @param exceptions the internal names of the method's exception classes
-     *        (see {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). May be
-     *        <tt>null</tt>.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param access
+     *            the method's access flags (see {@link Opcodes}). This
+     *            parameter also indicates if the method is synthetic and/or
+     *            deprecated.
+     * @param name
+     *            the method's name.
+     * @param desc
+     *            the method's descriptor (see {@link Type}).
+     * @param signature
+     *            the method's signature. May be <tt>null</tt>.
+     * @param exceptions
+     *            the internal names of the method's exception classes (see
+     *            {@link Type#getInternalName() getInternalName}). May be
+     *            <tt>null</tt>.
      */
-    public MethodNode(
-        final int api,
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final String[] exceptions)
-    {
+    public MethodNode(final int api, final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
         super(api);
         this.access = access;
         this.name = name;
         this.desc = desc;
         this.signature = signature;
-        this.exceptions = new ArrayList<String>(exceptions == null
-                ? 0
+        this.exceptions = new ArrayList<String>(exceptions == null ? 0
                 : exceptions.length);
         boolean isAbstract = (access & Opcodes.ACC_ABSTRACT) != 0;
         if (!isAbstract) {
@@ -258,6 +314,14 @@ public class MethodNode extends MethodVisitor
     // ------------------------------------------------------------------------
 
     @Override
+    public void visitParameter(String name, int access) {
+        if (parameters == null) {
+            parameters = new ArrayList<ParameterNode>(5);
+        }
+        parameters.add(new ParameterNode(name, access));
+    }
+
+    @Override
     public AnnotationVisitor visitAnnotationDefault() {
         return new AnnotationNode(new ArrayList<Object>(0) {
             @Override
@@ -269,10 +333,8 @@ public class MethodNode extends MethodVisitor
     }
 
     @Override
-    public AnnotationVisitor visitAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
         AnnotationNode an = new AnnotationNode(desc);
         if (visible) {
             if (visibleAnnotations == null) {
@@ -289,28 +351,45 @@ public class MethodNode extends MethodVisitor
     }
 
     @Override
-    public AnnotationVisitor visitParameterAnnotation(
-        final int parameter,
-        final String desc,
-        final boolean visible)
-    {
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
+        if (visible) {
+            if (visibleTypeAnnotations == null) {
+                visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+            }
+            visibleTypeAnnotations.add(an);
+        } else {
+            if (invisibleTypeAnnotations == null) {
+                invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+            }
+            invisibleTypeAnnotations.add(an);
+        }
+        return an;
+    }
+
+    @Override
+    public AnnotationVisitor visitParameterAnnotation(final int parameter,
+            final String desc, final boolean visible) {
         AnnotationNode an = new AnnotationNode(desc);
         if (visible) {
             if (visibleParameterAnnotations == null) {
                 int params = Type.getArgumentTypes(this.desc).length;
-                visibleParameterAnnotations = (List<AnnotationNode>[])new List<?>[params];
+                visibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
             }
             if (visibleParameterAnnotations[parameter] == null) {
-                visibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(1);
+                visibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(
+                        1);
             }
             visibleParameterAnnotations[parameter].add(an);
         } else {
             if (invisibleParameterAnnotations == null) {
                 int params = Type.getArgumentTypes(this.desc).length;
-                invisibleParameterAnnotations = (List<AnnotationNode>[])new List<?>[params];
+                invisibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
             }
             if (invisibleParameterAnnotations[parameter] == null) {
-                invisibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(1);
+                invisibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(
+                        1);
             }
             invisibleParameterAnnotations[parameter].add(an);
         }
@@ -330,17 +409,10 @@ public class MethodNode extends MethodVisitor
     }
 
     @Override
-    public void visitFrame(
-        final int type,
-        final int nLocal,
-        final Object[] local,
-        final int nStack,
-        final Object[] stack)
-    {
-        instructions.add(new FrameNode(type, nLocal, local == null
-                ? null
-                : getLabelNodes(local), nStack, stack == null
-                ? null
+    public void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack) {
+        instructions.add(new FrameNode(type, nLocal, local == null ? null
+                : getLabelNodes(local), nStack, stack == null ? null
                 : getLabelNodes(stack)));
     }
 
@@ -365,32 +437,35 @@ public class MethodNode extends MethodVisitor
     }
 
     @Override
-    public void visitFieldInsn(
-        final int opcode,
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    public void visitFieldInsn(final int opcode, final String owner,
+            final String name, final String desc) {
         instructions.add(new FieldInsnNode(opcode, owner, name, desc));
     }
 
+    @Deprecated
     @Override
-    public void visitMethodInsn(
-        final int opcode,
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    public void visitMethodInsn(int opcode, String owner, String name,
+            String desc) {
+        if (api >= Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
         instructions.add(new MethodInsnNode(opcode, owner, name, desc));
     }
 
     @Override
-    public void visitInvokeDynamicInsn(
-        String name,
-        String desc,
-        Handle bsm,
-        Object... bsmArgs)
-    {
+    public void visitMethodInsn(int opcode, String owner, String name,
+            String desc, boolean itf) {
+        if (api < Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
+        instructions.add(new MethodInsnNode(opcode, owner, name, desc, itf));
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
         instructions.add(new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs));
     }
 
@@ -415,26 +490,16 @@ public class MethodNode extends MethodVisitor
     }
 
     @Override
-    public void visitTableSwitchInsn(
-        final int min,
-        final int max,
-        final Label dflt,
-        final Label... labels)
-    {
-        instructions.add(new TableSwitchInsnNode(min,
-                max,
-                getLabelNode(dflt),
+    public void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels) {
+        instructions.add(new TableSwitchInsnNode(min, max, getLabelNode(dflt),
                 getLabelNodes(labels)));
     }
 
     @Override
-    public void visitLookupSwitchInsn(
-        final Label dflt,
-        final int[] keys,
-        final Label[] labels)
-    {
-        instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt),
-                keys,
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
+        instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt), keys,
                 getLabelNodes(labels)));
     }
 
@@ -444,33 +509,89 @@ public class MethodNode extends MethodVisitor
     }
 
     @Override
-    public void visitTryCatchBlock(
-        final Label start,
-        final Label end,
-        final Label handler,
-        final String type)
-    {
+    public AnnotationVisitor visitInsnAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        // Finds the last real instruction, i.e. the instruction targeted by
+        // this annotation.
+        AbstractInsnNode insn = instructions.getLast();
+        while (insn.getOpcode() == -1) {
+            insn = insn.getPrevious();
+        }
+        // Adds the annotation to this instruction.
+        TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
+        if (visible) {
+            if (insn.visibleTypeAnnotations == null) {
+                insn.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
+                        1);
+            }
+            insn.visibleTypeAnnotations.add(an);
+        } else {
+            if (insn.invisibleTypeAnnotations == null) {
+                insn.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
+                        1);
+            }
+            insn.invisibleTypeAnnotations.add(an);
+        }
+        return an;
+    }
+
+    @Override
+    public void visitTryCatchBlock(final Label start, final Label end,
+            final Label handler, final String type) {
         tryCatchBlocks.add(new TryCatchBlockNode(getLabelNode(start),
-                getLabelNode(end),
-                getLabelNode(handler),
-                type));
+                getLabelNode(end), getLabelNode(handler), type));
+    }
+
+    @Override
+    public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        TryCatchBlockNode tcb = tryCatchBlocks.get((typeRef & 0x00FFFF00) >> 8);
+        TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
+        if (visible) {
+            if (tcb.visibleTypeAnnotations == null) {
+                tcb.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
+                        1);
+            }
+            tcb.visibleTypeAnnotations.add(an);
+        } else {
+            if (tcb.invisibleTypeAnnotations == null) {
+                tcb.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
+                        1);
+            }
+            tcb.invisibleTypeAnnotations.add(an);
+        }
+        return an;
     }
 
     @Override
-    public void visitLocalVariable(
-        final String name,
-        final String desc,
-        final String signature,
-        final Label start,
-        final Label end,
-        final int index)
-    {
-        localVariables.add(new LocalVariableNode(name,
-                desc,
-                signature,
-                getLabelNode(start),
-                getLabelNode(end),
-                index));
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
+        localVariables.add(new LocalVariableNode(name, desc, signature,
+                getLabelNode(start), getLabelNode(end), index));
+    }
+
+    @Override
+    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+            TypePath typePath, Label[] start, Label[] end, int[] index,
+            String desc, boolean visible) {
+        LocalVariableAnnotationNode an = new LocalVariableAnnotationNode(
+                typeRef, typePath, getLabelNodes(start), getLabelNodes(end),
+                index, desc);
+        if (visible) {
+            if (visibleLocalVariableAnnotations == null) {
+                visibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>(
+                        1);
+            }
+            visibleLocalVariableAnnotations.add(an);
+        } else {
+            if (invisibleLocalVariableAnnotations == null) {
+                invisibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>(
+                        1);
+            }
+            invisibleLocalVariableAnnotations.add(an);
+        }
+        return an;
     }
 
     @Override
@@ -493,13 +614,14 @@ public class MethodNode extends MethodVisitor
      * LabelNode if necessary. The default implementation of this method uses
      * the {@link Label#info} field to store associations between labels and
      * label nodes.
-     *
-     * @param l a Label.
+     * 
+     * @param l
+     *            a Label.
      * @return the LabelNode corresponding to l.
      */
     protected LabelNode getLabelNode(final Label l) {
         if (!(l.info instanceof LabelNode)) {
-            l.info = new LabelNode(l);
+            l.info = new LabelNode();
         }
         return (LabelNode) l.info;
     }
@@ -533,25 +655,71 @@ public class MethodNode extends MethodVisitor
      * version. This methods checks that this node, and all its nodes
      * recursively, do not contain elements that were introduced in more recent
      * versions of the ASM API than the given version.
-     *
-     * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}.
+     * 
+     * @param api
+     *            an ASM API version. Must be one of {@link Opcodes#ASM4} or
+     *            {@link Opcodes#ASM5}.
      */
     public void check(final int api) {
-        // nothing to do
+        if (api == Opcodes.ASM4) {
+            if (visibleTypeAnnotations != null
+                    && visibleTypeAnnotations.size() > 0) {
+                throw new RuntimeException();
+            }
+            if (invisibleTypeAnnotations != null
+                    && invisibleTypeAnnotations.size() > 0) {
+                throw new RuntimeException();
+            }
+            int n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size();
+            for (int i = 0; i < n; ++i) {
+                TryCatchBlockNode tcb = tryCatchBlocks.get(i);
+                if (tcb.visibleTypeAnnotations != null
+                        && tcb.visibleTypeAnnotations.size() > 0) {
+                    throw new RuntimeException();
+                }
+                if (tcb.invisibleTypeAnnotations != null
+                        && tcb.invisibleTypeAnnotations.size() > 0) {
+                    throw new RuntimeException();
+                }
+            }
+            for (int i = 0; i < instructions.size(); ++i) {
+                AbstractInsnNode insn = instructions.get(i);
+                if (insn.visibleTypeAnnotations != null
+                        && insn.visibleTypeAnnotations.size() > 0) {
+                    throw new RuntimeException();
+                }
+                if (insn.invisibleTypeAnnotations != null
+                        && insn.invisibleTypeAnnotations.size() > 0) {
+                    throw new RuntimeException();
+                }
+                if (insn instanceof MethodInsnNode) {
+                    boolean itf = ((MethodInsnNode) insn).itf;
+                    if (itf != (insn.opcode == Opcodes.INVOKEINTERFACE)) {
+                        throw new RuntimeException();
+                    }
+                }
+            }
+            if (visibleLocalVariableAnnotations != null
+                    && visibleLocalVariableAnnotations.size() > 0) {
+                throw new RuntimeException();
+            }
+            if (invisibleLocalVariableAnnotations != null
+                    && invisibleLocalVariableAnnotations.size() > 0) {
+                throw new RuntimeException();
+            }
+        }
     }
 
     /**
      * Makes the given class visitor visit this method.
-     *
-     * @param cv a class visitor.
+     * 
+     * @param cv
+     *            a class visitor.
      */
     public void accept(final ClassVisitor cv) {
         String[] exceptions = new String[this.exceptions.size()];
         this.exceptions.toArray(exceptions);
-        MethodVisitor mv = cv.visitMethod(access,
-                name,
-                desc,
-                signature,
+        MethodVisitor mv = cv.visitMethod(access, name, desc, signature,
                 exceptions);
         if (mv != null) {
             accept(mv);
@@ -560,12 +728,19 @@ public class MethodNode extends MethodVisitor
 
     /**
      * Makes the given method visitor visit this method.
-     *
-     * @param mv a method visitor.
+     * 
+     * @param mv
+     *            a method visitor.
      */
     public void accept(final MethodVisitor mv) {
-        // visits the method attributes
+        // visits the method parameters
         int i, j, n;
+        n = parameters == null ? 0 : parameters.size();
+        for (i = 0; i < n; i++) {
+            ParameterNode parameter = parameters.get(i);
+            mv.visitParameter(parameter.name, parameter.access);
+        }
+        // visits the method attributes
         if (annotationDefault != null) {
             AnnotationVisitor av = mv.visitAnnotationDefault();
             AnnotationNode.accept(av, null, annotationDefault);
@@ -583,8 +758,20 @@ public class MethodNode extends MethodVisitor
             AnnotationNode an = invisibleAnnotations.get(i);
             an.accept(mv.visitAnnotation(an.desc, false));
         }
-        n = visibleParameterAnnotations == null
-                ? 0
+        n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
+        for (i = 0; i < n; ++i) {
+            TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+            an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+                    true));
+        }
+        n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
+                .size();
+        for (i = 0; i < n; ++i) {
+            TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
+            an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+                    false));
+        }
+        n = visibleParameterAnnotations == null ? 0
                 : visibleParameterAnnotations.length;
         for (i = 0; i < n; ++i) {
             List<?> l = visibleParameterAnnotations[i];
@@ -596,8 +783,7 @@ public class MethodNode extends MethodVisitor
                 an.accept(mv.visitParameterAnnotation(i, an.desc, true));
             }
         }
-        n = invisibleParameterAnnotations == null
-                ? 0
+        n = invisibleParameterAnnotations == null ? 0
                 : invisibleParameterAnnotations.length;
         for (i = 0; i < n; ++i) {
             List<?> l = invisibleParameterAnnotations[i];
@@ -622,6 +808,7 @@ public class MethodNode extends MethodVisitor
             // visits try catch blocks
             n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size();
             for (i = 0; i < n; ++i) {
+                tryCatchBlocks.get(i).updateIndex(i);
                 tryCatchBlocks.get(i).accept(mv);
             }
             // visits instructions
@@ -631,6 +818,17 @@ public class MethodNode extends MethodVisitor
             for (i = 0; i < n; ++i) {
                 localVariables.get(i).accept(mv);
             }
+            // visits local variable annotations
+            n = visibleLocalVariableAnnotations == null ? 0
+                    : visibleLocalVariableAnnotations.size();
+            for (i = 0; i < n; ++i) {
+                visibleLocalVariableAnnotations.get(i).accept(mv, true);
+            }
+            n = invisibleLocalVariableAnnotations == null ? 0
+                    : invisibleLocalVariableAnnotations.size();
+            for (i = 0; i < n; ++i) {
+                invisibleLocalVariableAnnotations.get(i).accept(mv, false);
+            }
             // visits maxs
             mv.visitMaxs(maxStack, maxLocals);
             visited = true;

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
index d27837d..f0d2b6b 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
@@ -29,14 +29,14 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
+import java.util.Map;
+
 import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
 import org.apache.tapestry5.internal.plastic.asm.Opcodes;
 
-import java.util.Map;
-
 /**
  * A node that represents a MULTIANEWARRAY instruction.
- *
+ * 
  * @author Eric Bruneton
  */
 public class MultiANewArrayInsnNode extends AbstractInsnNode {
@@ -53,9 +53,11 @@ public class MultiANewArrayInsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link MultiANewArrayInsnNode}.
-     *
-     * @param desc an array type descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
-     * @param dims number of dimensions of the array to allocate.
+     * 
+     * @param desc
+     *            an array type descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+     * @param dims
+     *            number of dimensions of the array to allocate.
      */
     public MultiANewArrayInsnNode(final String desc, final int dims) {
         super(Opcodes.MULTIANEWARRAY);
@@ -71,11 +73,12 @@ public class MultiANewArrayInsnNode extends AbstractInsnNode {
     @Override
     public void accept(final MethodVisitor mv) {
         mv.visitMultiANewArrayInsn(desc, dims);
+        acceptAnnotations(mv);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new MultiANewArrayInsnNode(desc, dims);
+        return new MultiANewArrayInsnNode(desc, dims).cloneAnnotations(this);
     }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ParameterNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ParameterNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ParameterNode.java
new file mode 100644
index 0000000..d5435de
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ParameterNode.java
@@ -0,0 +1,76 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 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.tree;
+
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
+/**
+ * A node that represents a parameter access and name.
+ * 
+ * @author Remi Forax
+ */
+public class ParameterNode {
+    /**
+     * The parameter's name.
+     */
+    public String name;
+
+    /**
+     * The parameter's access flags (see {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}).
+     * Valid values are <tt>ACC_FINAL</tt>, <tt>ACC_SYNTHETIC</tt> and
+     * <tt>ACC_MANDATED</tt>.
+     */
+    public int access;
+
+    /**
+     * Constructs a new {@link ParameterNode}.
+     * 
+     * @param access
+     *            The parameter's access flags. Valid values are
+     *            <tt>ACC_FINAL</tt>, <tt>ACC_SYNTHETIC</tt> or/and
+     *            <tt>ACC_MANDATED</tt> (see {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}).
+     * @param name
+     *            the parameter's name.
+     */
+    public ParameterNode(final String name, final int access) {
+        this.name = name;
+        this.access = access;
+    }
+
+    /**
+     * Makes the given visitor visit this parameter declaration.
+     * 
+     * @param mv
+     *            a method visitor.
+     */
+    public void accept(final MethodVisitor mv) {
+        mv.visitParameter(name, access);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
index 17ad4ec..e9ef6f2 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
@@ -29,18 +29,18 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
-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 java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
 /**
  * A node that represents a TABLESWITCH instruction.
- *
+ * 
  * @author Eric Bruneton
  */
 public class TableSwitchInsnNode extends AbstractInsnNode {
@@ -68,19 +68,19 @@ public class TableSwitchInsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link TableSwitchInsnNode}.
-     *
-     * @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.
+     * 
+     * @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.
      */
-    public TableSwitchInsnNode(
-        final int min,
-        final int max,
-        final LabelNode dflt,
-        final LabelNode... labels)
-    {
+    public TableSwitchInsnNode(final int min, final int max,
+            final LabelNode dflt, final LabelNode... labels) {
         super(Opcodes.TABLESWITCH);
         this.min = min;
         this.max = max;
@@ -103,13 +103,12 @@ public class TableSwitchInsnNode extends AbstractInsnNode {
             labels[i] = this.labels.get(i).getLabel();
         }
         mv.visitTableSwitchInsn(min, max, dflt.getLabel(), labels);
+        acceptAnnotations(mv);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new TableSwitchInsnNode(min,
-                max,
-                clone(dflt, labels),
-                clone(this.labels, labels));
+        return new TableSwitchInsnNode(min, max, clone(dflt, labels), clone(
+                this.labels, labels)).cloneAnnotations(this);
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java
index 52ea45f..a4c8dde 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java
@@ -29,11 +29,13 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
+import java.util.List;
+
 import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
 
 /**
  * A node that represents a try catch block.
- *
+ * 
  * @author Eric Bruneton
  */
 public class TryCatchBlockNode {
@@ -60,21 +62,41 @@ public class TryCatchBlockNode {
     public String type;
 
     /**
+     * The runtime visible type annotations on the exception handler type. This
+     * list is a list of {@link TypeAnnotationNode} objects. May be
+     * <tt>null</tt>.
+     * 
+     * @associates org.objectweb.asm.tree.TypeAnnotationNode
+     * @label visible
+     */
+    public List<TypeAnnotationNode> visibleTypeAnnotations;
+
+    /**
+     * The runtime invisible type annotations on the exception handler type.
+     * This list is a list of {@link TypeAnnotationNode} objects. May be
+     * <tt>null</tt>.
+     * 
+     * @associates org.objectweb.asm.tree.TypeAnnotationNode
+     * @label invisible
+     */
+    public List<TypeAnnotationNode> invisibleTypeAnnotations;
+
+    /**
      * Constructs a new {@link TryCatchBlockNode}.
-     *
-     * @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.
-     * @param type internal name of the type of exceptions handled by the
-     *        handler, or <tt>null</tt> to catch any exceptions (for "finally"
-     *        blocks).
+     * 
+     * @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.
+     * @param type
+     *            internal name of the type of exceptions handled by the
+     *            handler, or <tt>null</tt> to catch any exceptions (for
+     *            "finally" blocks).
      */
-    public TryCatchBlockNode(
-        final LabelNode start,
-        final LabelNode end,
-        final LabelNode handler,
-        final String type)
-    {
+    public TryCatchBlockNode(final LabelNode start, final LabelNode end,
+            final LabelNode handler, final String type) {
         this.start = start;
         this.end = end;
         this.handler = handler;
@@ -82,13 +104,50 @@ public class TryCatchBlockNode {
     }
 
     /**
+     * Updates the index of this try catch block in the method's list of try
+     * catch block nodes. This index maybe stored in the 'target' field of the
+     * type annotations of this block.
+     * 
+     * @param index
+     *            the new index of this try catch block in the method's list of
+     *            try catch block nodes.
+     */
+    public void updateIndex(final int index) {
+        int newTypeRef = 0x42000000 | (index << 8);
+        if (visibleTypeAnnotations != null) {
+            for (TypeAnnotationNode tan : visibleTypeAnnotations) {
+                tan.typeRef = newTypeRef;
+            }
+        }
+        if (invisibleTypeAnnotations != null) {
+            for (TypeAnnotationNode tan : invisibleTypeAnnotations) {
+                tan.typeRef = newTypeRef;
+            }
+        }
+    }
+
+    /**
      * Makes the given visitor visit this try catch block.
-     *
-     * @param mv a method visitor.
+     * 
+     * @param mv
+     *            a method visitor.
      */
     public void accept(final MethodVisitor mv) {
-        mv.visitTryCatchBlock(start.getLabel(), end.getLabel(), handler == null
-                ? null
-                : handler.getLabel(), type);
+        mv.visitTryCatchBlock(start.getLabel(), end.getLabel(),
+                handler == null ? null : handler.getLabel(), type);
+        int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations
+                .size();
+        for (int i = 0; i < n; ++i) {
+            TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+            an.accept(mv.visitTryCatchAnnotation(an.typeRef, an.typePath,
+                    an.desc, true));
+        }
+        n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
+                .size();
+        for (int i = 0; i < n; ++i) {
+            TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
+            an.accept(mv.visitTryCatchAnnotation(an.typeRef, an.typePath,
+                    an.desc, false));
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java
new file mode 100644
index 0000000..66ec2d3
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java
@@ -0,0 +1,100 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 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.tree;
+
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+
+/**
+ * A node that represents a type annotationn.
+ * 
+ * @author Eric Bruneton
+ */
+public class TypeAnnotationNode extends AnnotationNode {
+
+    /**
+     * A reference to the annotated type. See {@link TypeReference}.
+     */
+    public int typeRef;
+
+    /**
+     * The path to the annotated type argument, wildcard bound, array element
+     * type, or static outer type within the referenced type. May be
+     * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+     */
+    public TypePath typePath;
+
+    /**
+     * Constructs a new {@link AnnotationNode}. <i>Subclasses must not use this
+     * constructor</i>. Instead, they must use the
+     * {@link #TypeAnnotationNode(int, int, TypePath, String)} version.
+     * 
+     * @param typeRef
+     *            a reference to the annotated type. See {@link TypeReference}.
+     * @param typePath
+     *            the path to the annotated type argument, wildcard bound, array
+     *            element type, or static inner type within 'typeRef'. May be
+     *            <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+     * @param desc
+     *            the class descriptor of the annotation class.
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public TypeAnnotationNode(final int typeRef, final TypePath typePath,
+            final String desc) {
+        this(Opcodes.ASM5, typeRef, typePath, desc);
+        if (getClass() != TypeAnnotationNode.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Constructs a new {@link AnnotationNode}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param typeRef
+     *            a reference to the annotated type. See {@link TypeReference}.
+     * @param typePath
+     *            the path to the annotated type argument, wildcard bound, array
+     *            element type, or static inner type within 'typeRef'. May be
+     *            <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+     * @param desc
+     *            the class descriptor of the annotation class.
+     */
+    public TypeAnnotationNode(final int api, final int typeRef,
+            final TypePath typePath, final String desc) {
+        super(api, desc);
+        this.typeRef = typeRef;
+        this.typePath = typePath;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
index e5bc30e..b4572e5 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
@@ -29,14 +29,14 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
 import java.util.Map;
 
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
 /**
  * A node that represents a type instruction. A type instruction is an
  * instruction that takes a type descriptor as parameter.
- *
+ * 
  * @author Eric Bruneton
  */
 public class TypeInsnNode extends AbstractInsnNode {
@@ -49,11 +49,13 @@ public class TypeInsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link TypeInsnNode}.
-     *
-     * @param opcode the opcode of the type instruction to be constructed. This
-     *        opcode must be NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
-     * @param desc the operand of the instruction to be constructed. This
-     *        operand is an internal name (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+     * 
+     * @param opcode
+     *            the opcode of the type instruction to be constructed. This
+     *            opcode must be NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
+     * @param desc
+     *            the operand of the instruction to be constructed. This operand
+     *            is an internal name (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
      */
     public TypeInsnNode(final int opcode, final String desc) {
         super(opcode);
@@ -62,9 +64,10 @@ public class TypeInsnNode extends AbstractInsnNode {
 
     /**
      * Sets the opcode of this instruction.
-     *
-     * @param opcode the new instruction opcode. This opcode must be NEW,
-     *        ANEWARRAY, CHECKCAST or INSTANCEOF.
+     * 
+     * @param opcode
+     *            the new instruction opcode. This opcode must be NEW,
+     *            ANEWARRAY, CHECKCAST or INSTANCEOF.
      */
     public void setOpcode(final int opcode) {
         this.opcode = opcode;
@@ -78,10 +81,11 @@ public class TypeInsnNode extends AbstractInsnNode {
     @Override
     public void accept(final MethodVisitor mv) {
         mv.visitTypeInsn(opcode, desc);
+        acceptAnnotations(mv);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new TypeInsnNode(opcode, desc);
+        return new TypeInsnNode(opcode, desc).cloneAnnotations(this);
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java
index 3819d31..58552de 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java
@@ -1,6 +1,6 @@
 /***
  * ASM: a very small and fast Java bytecode manipulation framework
-` * Copyright (c) 2000-2011 INRIA, France Telecom
+ * Copyright (c) 2000-2011 INRIA, France Telecom
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -29,15 +29,15 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
 import java.util.Map;
 
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
 /**
  * A node that represents a local variable instruction. A local variable
  * instruction is an instruction that loads or stores the value of a local
  * variable.
- *
+ * 
  * @author Eric Bruneton
  */
 public class VarInsnNode extends AbstractInsnNode {
@@ -50,12 +50,14 @@ public class VarInsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link VarInsnNode}.
-     *
-     * @param opcode the opcode of the local variable instruction to be
-     *        constructed. This opcode must be ILOAD, LLOAD, FLOAD, DLOAD,
-     *        ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
-     * @param var the operand of the instruction to be constructed. This operand
-     *        is the index of a local variable.
+     * 
+     * @param opcode
+     *            the opcode of the local variable instruction to be
+     *            constructed. This opcode must be ILOAD, LLOAD, FLOAD, DLOAD,
+     *            ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
+     * @param var
+     *            the operand of the instruction to be constructed. This operand
+     *            is the index of a local variable.
      */
     public VarInsnNode(final int opcode, final int var) {
         super(opcode);
@@ -64,10 +66,11 @@ public class VarInsnNode extends AbstractInsnNode {
 
     /**
      * Sets the opcode of this instruction.
-     *
-     * @param opcode the new instruction opcode. This opcode must be ILOAD,
-     *        LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE
-     *        or RET.
+     * 
+     * @param opcode
+     *            the new instruction opcode. This opcode must be ILOAD, LLOAD,
+     *            FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or
+     *            RET.
      */
     public void setOpcode(final int opcode) {
         this.opcode = opcode;
@@ -81,10 +84,11 @@ public class VarInsnNode extends AbstractInsnNode {
     @Override
     public void accept(final MethodVisitor mv) {
         mv.visitVarInsn(opcode, var);
+        acceptAnnotations(mv);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new VarInsnNode(opcode, var);
+        return new VarInsnNode(opcode, var).cloneAnnotations(this);
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Analyzer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Analyzer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Analyzer.java
new file mode 100644
index 0000000..a78fff4
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Analyzer.java
@@ -0,0 +1,549 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 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.tree.analysis;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.IincInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.InsnList;
+import org.apache.tapestry5.internal.plastic.asm.tree.JumpInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LabelNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LookupSwitchInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TableSwitchInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TryCatchBlockNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.VarInsnNode;
+
+/**
+ * A semantic bytecode analyzer. <i>This class does not fully check that JSR and
+ * RET instructions are valid.</i>
+ * 
+ * @param <V>
+ *            type of the Value used for the analysis.
+ * 
+ * @author Eric Bruneton
+ */
+public class Analyzer<V extends Value> implements Opcodes {
+
+    private final Interpreter<V> interpreter;
+
+    private int n;
+
+    private InsnList insns;
+
+    private List<TryCatchBlockNode>[] handlers;
+
+    private Frame<V>[] frames;
+
+    private Subroutine[] subroutines;
+
+    private boolean[] queued;
+
+    private int[] queue;
+
+    private int top;
+
+    /**
+     * Constructs a new {@link Analyzer}.
+     * 
+     * @param interpreter
+     *            the interpreter to be used to symbolically interpret the
+     *            bytecode instructions.
+     */
+    public Analyzer(final Interpreter<V> interpreter) {
+        this.interpreter = interpreter;
+    }
+
+    /**
+     * Analyzes the given method.
+     * 
+     * @param owner
+     *            the internal name of the class to which the method belongs.
+     * @param m
+     *            the method to be analyzed.
+     * @return the symbolic state of the execution stack frame at each bytecode
+     *         instruction of the method. The size of the returned array is
+     *         equal to the number of instructions (and labels) of the method. A
+     *         given frame is <tt>null</tt> if and only if the corresponding
+     *         instruction cannot be reached (dead code).
+     * @throws AnalyzerException
+     *             if a problem occurs during the analysis.
+     */
+    public Frame<V>[] analyze(final String owner, final MethodNode m)
+            throws AnalyzerException {
+        if ((m.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) {
+            frames = (Frame<V>[]) new Frame<?>[0];
+            return frames;
+        }
+        n = m.instructions.size();
+        insns = m.instructions;
+        handlers = (List<TryCatchBlockNode>[]) new List<?>[n];
+        frames = (Frame<V>[]) new Frame<?>[n];
+        subroutines = new Subroutine[n];
+        queued = new boolean[n];
+        queue = new int[n];
+        top = 0;
+
+        // computes exception handlers for each instruction
+        for (int i = 0; i < m.tryCatchBlocks.size(); ++i) {
+            TryCatchBlockNode tcb = m.tryCatchBlocks.get(i);
+            int begin = insns.indexOf(tcb.start);
+            int end = insns.indexOf(tcb.end);
+            for (int j = begin; j < end; ++j) {
+                List<TryCatchBlockNode> insnHandlers = handlers[j];
+                if (insnHandlers == null) {
+                    insnHandlers = new ArrayList<TryCatchBlockNode>();
+                    handlers[j] = insnHandlers;
+                }
+                insnHandlers.add(tcb);
+            }
+        }
+
+        // computes the subroutine for each instruction:
+        Subroutine main = new Subroutine(null, m.maxLocals, null);
+        List<AbstractInsnNode> subroutineCalls = new ArrayList<AbstractInsnNode>();
+        Map<LabelNode, Subroutine> subroutineHeads = new HashMap<LabelNode, Subroutine>();
+        findSubroutine(0, main, subroutineCalls);
+        while (!subroutineCalls.isEmpty()) {
+            JumpInsnNode jsr = (JumpInsnNode) subroutineCalls.remove(0);
+            Subroutine sub = subroutineHeads.get(jsr.label);
+            if (sub == null) {
+                sub = new Subroutine(jsr.label, m.maxLocals, jsr);
+                subroutineHeads.put(jsr.label, sub);
+                findSubroutine(insns.indexOf(jsr.label), sub, subroutineCalls);
+            } else {
+                sub.callers.add(jsr);
+            }
+        }
+        for (int i = 0; i < n; ++i) {
+            if (subroutines[i] != null && subroutines[i].start == null) {
+                subroutines[i] = null;
+            }
+        }
+
+        // initializes the data structures for the control flow analysis
+        Frame<V> current = newFrame(m.maxLocals, m.maxStack);
+        Frame<V> handler = newFrame(m.maxLocals, m.maxStack);
+        current.setReturn(interpreter.newValue(Type.getReturnType(m.desc)));
+        Type[] args = Type.getArgumentTypes(m.desc);
+        int local = 0;
+        if ((m.access & ACC_STATIC) == 0) {
+            Type ctype = Type.getObjectType(owner);
+            current.setLocal(local++, interpreter.newValue(ctype));
+        }
+        for (int i = 0; i < args.length; ++i) {
+            current.setLocal(local++, interpreter.newValue(args[i]));
+            if (args[i].getSize() == 2) {
+                current.setLocal(local++, interpreter.newValue(null));
+            }
+        }
+        while (local < m.maxLocals) {
+            current.setLocal(local++, interpreter.newValue(null));
+        }
+        merge(0, current, null);
+
+        init(owner, m);
+
+        // control flow analysis
+        while (top > 0) {
+            int insn = queue[--top];
+            Frame<V> f = frames[insn];
+            Subroutine subroutine = subroutines[insn];
+            queued[insn] = false;
+
+            AbstractInsnNode insnNode = null;
+            try {
+                insnNode = m.instructions.get(insn);
+                int insnOpcode = insnNode.getOpcode();
+                int insnType = insnNode.getType();
+
+                if (insnType == AbstractInsnNode.LABEL
+                        || insnType == AbstractInsnNode.LINE
+                        || insnType == AbstractInsnNode.FRAME) {
+                    merge(insn + 1, f, subroutine);
+                    newControlFlowEdge(insn, insn + 1);
+                } else {
+                    current.init(f).execute(insnNode, interpreter);
+                    subroutine = subroutine == null ? null : subroutine.copy();
+
+                    if (insnNode instanceof JumpInsnNode) {
+                        JumpInsnNode j = (JumpInsnNode) insnNode;
+                        if (insnOpcode != GOTO && insnOpcode != JSR) {
+                            merge(insn + 1, current, subroutine);
+                            newControlFlowEdge(insn, insn + 1);
+                        }
+                        int jump = insns.indexOf(j.label);
+                        if (insnOpcode == JSR) {
+                            merge(jump, current, new Subroutine(j.label,
+                                    m.maxLocals, j));
+                        } else {
+                            merge(jump, current, subroutine);
+                        }
+                        newControlFlowEdge(insn, jump);
+                    } else if (insnNode instanceof LookupSwitchInsnNode) {
+                        LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode;
+                        int jump = insns.indexOf(lsi.dflt);
+                        merge(jump, current, subroutine);
+                        newControlFlowEdge(insn, jump);
+                        for (int j = 0; j < lsi.labels.size(); ++j) {
+                            LabelNode label = lsi.labels.get(j);
+                            jump = insns.indexOf(label);
+                            merge(jump, current, subroutine);
+                            newControlFlowEdge(insn, jump);
+                        }
+                    } else if (insnNode instanceof TableSwitchInsnNode) {
+                        TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode;
+                        int jump = insns.indexOf(tsi.dflt);
+                        merge(jump, current, subroutine);
+                        newControlFlowEdge(insn, jump);
+                        for (int j = 0; j < tsi.labels.size(); ++j) {
+                            LabelNode label = tsi.labels.get(j);
+                            jump = insns.indexOf(label);
+                            merge(jump, current, subroutine);
+                            newControlFlowEdge(insn, jump);
+                        }
+                    } else if (insnOpcode == RET) {
+                        if (subroutine == null) {
+                            throw new AnalyzerException(insnNode,
+                                    "RET instruction outside of a sub routine");
+                        }
+                        for (int i = 0; i < subroutine.callers.size(); ++i) {
+                            JumpInsnNode caller = subroutine.callers.get(i);
+                            int call = insns.indexOf(caller);
+                            if (frames[call] != null) {
+                                merge(call + 1, frames[call], current,
+                                        subroutines[call], subroutine.access);
+                                newControlFlowEdge(insn, call + 1);
+                            }
+                        }
+                    } else if (insnOpcode != ATHROW
+                            && (insnOpcode < IRETURN || insnOpcode > RETURN)) {
+                        if (subroutine != null) {
+                            if (insnNode instanceof VarInsnNode) {
+                                int var = ((VarInsnNode) insnNode).var;
+                                subroutine.access[var] = true;
+                                if (insnOpcode == LLOAD || insnOpcode == DLOAD
+                                        || insnOpcode == LSTORE
+                                        || insnOpcode == DSTORE) {
+                                    subroutine.access[var + 1] = true;
+                                }
+                            } else if (insnNode instanceof IincInsnNode) {
+                                int var = ((IincInsnNode) insnNode).var;
+                                subroutine.access[var] = true;
+                            }
+                        }
+                        merge(insn + 1, current, subroutine);
+                        newControlFlowEdge(insn, insn + 1);
+                    }
+                }
+
+                List<TryCatchBlockNode> insnHandlers = handlers[insn];
+                if (insnHandlers != null) {
+                    for (int i = 0; i < insnHandlers.size(); ++i) {
+                        TryCatchBlockNode tcb = insnHandlers.get(i);
+                        Type type;
+                        if (tcb.type == null) {
+                            type = Type.getObjectType("java/lang/Throwable");
+                        } else {
+                            type = Type.getObjectType(tcb.type);
+                        }
+                        int jump = insns.indexOf(tcb.handler);
+                        if (newControlFlowExceptionEdge(insn, tcb)) {
+                            handler.init(f);
+                            handler.clearStack();
+                            handler.push(interpreter.newValue(type));
+                            merge(jump, handler, subroutine);
+                        }
+                    }
+                }
+            } catch (AnalyzerException e) {
+                throw new AnalyzerException(e.node, "Error at instruction "
+                        + insn + ": " + e.getMessage(), e);
+            } catch (Exception e) {
+                throw new AnalyzerException(insnNode, "Error at instruction "
+                        + insn + ": " + e.getMessage(), e);
+            }
+        }
+
+        return frames;
+    }
+
+    private void findSubroutine(int insn, final Subroutine sub,
+            final List<AbstractInsnNode> calls) throws AnalyzerException {
+        while (true) {
+            if (insn < 0 || insn >= n) {
+                throw new AnalyzerException(null,
+                        "Execution can fall off end of the code");
+            }
+            if (subroutines[insn] != null) {
+                return;
+            }
+            subroutines[insn] = sub.copy();
+            AbstractInsnNode node = insns.get(insn);
+
+            // calls findSubroutine recursively on normal successors
+            if (node instanceof JumpInsnNode) {
+                if (node.getOpcode() == JSR) {
+                    // do not follow a JSR, it leads to another subroutine!
+                    calls.add(node);
+                } else {
+                    JumpInsnNode jnode = (JumpInsnNode) node;
+                    findSubroutine(insns.indexOf(jnode.label), sub, calls);
+                }
+            } else if (node instanceof TableSwitchInsnNode) {
+                TableSwitchInsnNode tsnode = (TableSwitchInsnNode) node;
+                findSubroutine(insns.indexOf(tsnode.dflt), sub, calls);
+                for (int i = tsnode.labels.size() - 1; i >= 0; --i) {
+                    LabelNode l = tsnode.labels.get(i);
+                    findSubroutine(insns.indexOf(l), sub, calls);
+                }
+            } else if (node instanceof LookupSwitchInsnNode) {
+                LookupSwitchInsnNode lsnode = (LookupSwitchInsnNode) node;
+                findSubroutine(insns.indexOf(lsnode.dflt), sub, calls);
+                for (int i = lsnode.labels.size() - 1; i >= 0; --i) {
+                    LabelNode l = lsnode.labels.get(i);
+                    findSubroutine(insns.indexOf(l), sub, calls);
+                }
+            }
+
+            // calls findSubroutine recursively on exception handler successors
+            List<TryCatchBlockNode> insnHandlers = handlers[insn];
+            if (insnHandlers != null) {
+                for (int i = 0; i < insnHandlers.size(); ++i) {
+                    TryCatchBlockNode tcb = insnHandlers.get(i);
+                    findSubroutine(insns.indexOf(tcb.handler), sub, calls);
+                }
+            }
+
+            // if insn does not falls through to the next instruction, return.
+            switch (node.getOpcode()) {
+            case GOTO:
+            case RET:
+            case TABLESWITCH:
+            case LOOKUPSWITCH:
+            case IRETURN:
+            case LRETURN:
+            case FRETURN:
+            case DRETURN:
+            case ARETURN:
+            case RETURN:
+            case ATHROW:
+                return;
+            }
+            insn++;
+        }
+    }
+
+    /**
+     * Returns the symbolic stack frame for each instruction of the last
+     * recently analyzed method.
+     * 
+     * @return the symbolic state of the execution stack frame at each bytecode
+     *         instruction of the method. The size of the returned array is
+     *         equal to the number of instructions (and labels) of the method. A
+     *         given frame is <tt>null</tt> if the corresponding instruction
+     *         cannot be reached, or if an error occured during the analysis of
+     *         the method.
+     */
+    public Frame<V>[] getFrames() {
+        return frames;
+    }
+
+    /**
+     * Returns the exception handlers for the given instruction.
+     * 
+     * @param insn
+     *            the index of an instruction of the last recently analyzed
+     *            method.
+     * @return a list of {@link TryCatchBlockNode} objects.
+     */
+    public List<TryCatchBlockNode> getHandlers(final int insn) {
+        return handlers[insn];
+    }
+
+    /**
+     * Initializes this analyzer. This method is called just before the
+     * execution of control flow analysis loop in #analyze. The default
+     * implementation of this method does nothing.
+     * 
+     * @param owner
+     *            the internal name of the class to which the method belongs.
+     * @param m
+     *            the method to be analyzed.
+     * @throws AnalyzerException
+     *             if a problem occurs.
+     */
+    protected void init(String owner, MethodNode m) throws AnalyzerException {
+    }
+
+    /**
+     * Constructs a new frame with the given size.
+     * 
+     * @param nLocals
+     *            the maximum number of local variables of the frame.
+     * @param nStack
+     *            the maximum stack size of the frame.
+     * @return the created frame.
+     */
+    protected Frame<V> newFrame(final int nLocals, final int nStack) {
+        return new Frame<V>(nLocals, nStack);
+    }
+
+    /**
+     * Constructs a new frame that is identical to the given frame.
+     * 
+     * @param src
+     *            a frame.
+     * @return the created frame.
+     */
+    protected Frame<V> newFrame(final Frame<? extends V> src) {
+        return new Frame<V>(src);
+    }
+
+    /**
+     * Creates a control flow graph edge. The default implementation of this
+     * method does nothing. It can be overriden in order to construct the
+     * control flow graph of a method (this method is called by the
+     * {@link #analyze analyze} method during its visit of the method's code).
+     * 
+     * @param insn
+     *            an instruction index.
+     * @param successor
+     *            index of a successor instruction.
+     */
+    protected void newControlFlowEdge(final int insn, final int successor) {
+    }
+
+    /**
+     * Creates a control flow graph edge corresponding to an exception handler.
+     * The default implementation of this method does nothing. It can be
+     * overridden in order to construct the control flow graph of a method (this
+     * method is called by the {@link #analyze analyze} method during its visit
+     * of the method's code).
+     * 
+     * @param insn
+     *            an instruction index.
+     * @param successor
+     *            index of a successor instruction.
+     * @return true if this edge must be considered in the data flow analysis
+     *         performed by this analyzer, or false otherwise. The default
+     *         implementation of this method always returns true.
+     */
+    protected boolean newControlFlowExceptionEdge(final int insn,
+            final int successor) {
+        return true;
+    }
+
+    /**
+     * Creates a control flow graph edge corresponding to an exception handler.
+     * The default implementation of this method delegates to
+     * {@link #newControlFlowExceptionEdge(int, int)
+     * newControlFlowExceptionEdge(int, int)}. It can be overridden in order to
+     * construct the control flow graph of a method (this method is called by
+     * the {@link #analyze analyze} method during its visit of the method's
+     * code).
+     * 
+     * @param insn
+     *            an instruction index.
+     * @param tcb
+     *            TryCatchBlockNode corresponding to this edge.
+     * @return true if this edge must be considered in the data flow analysis
+     *         performed by this analyzer, or false otherwise. The default
+     *         implementation of this method delegates to
+     *         {@link #newControlFlowExceptionEdge(int, int)
+     *         newControlFlowExceptionEdge(int, int)}.
+     */
+    protected boolean newControlFlowExceptionEdge(final int insn,
+            final TryCatchBlockNode tcb) {
+        return newControlFlowExceptionEdge(insn, insns.indexOf(tcb.handler));
+    }
+
+    // -------------------------------------------------------------------------
+
+    private void merge(final int insn, final Frame<V> frame,
+            final Subroutine subroutine) throws AnalyzerException {
+        Frame<V> oldFrame = frames[insn];
+        Subroutine oldSubroutine = subroutines[insn];
+        boolean changes;
+
+        if (oldFrame == null) {
+            frames[insn] = newFrame(frame);
+            changes = true;
+        } else {
+            changes = oldFrame.merge(frame, interpreter);
+        }
+
+        if (oldSubroutine == null) {
+            if (subroutine != null) {
+                subroutines[insn] = subroutine.copy();
+                changes = true;
+            }
+        } else {
+            if (subroutine != null) {
+                changes |= oldSubroutine.merge(subroutine);
+            }
+        }
+        if (changes && !queued[insn]) {
+            queued[insn] = true;
+            queue[top++] = insn;
+        }
+    }
+
+    private void merge(final int insn, final Frame<V> beforeJSR,
+            final Frame<V> afterRET, final Subroutine subroutineBeforeJSR,
+            final boolean[] access) throws AnalyzerException {
+        Frame<V> oldFrame = frames[insn];
+        Subroutine oldSubroutine = subroutines[insn];
+        boolean changes;
+
+        afterRET.merge(beforeJSR, access);
+
+        if (oldFrame == null) {
+            frames[insn] = newFrame(afterRET);
+            changes = true;
+        } else {
+            changes = oldFrame.merge(afterRET, interpreter);
+        }
+
+        if (oldSubroutine != null && subroutineBeforeJSR != null) {
+            changes |= oldSubroutine.merge(subroutineBeforeJSR);
+        }
+        if (changes && !queued[insn]) {
+            queued[insn] = true;
+            queue[top++] = insn;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java
new file mode 100644
index 0000000..66c9df9
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java
@@ -0,0 +1,61 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 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.tree.analysis;
+
+import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
+
+/**
+ * Thrown if a problem occurs during the analysis of a method.
+ * 
+ * @author Bing Ran
+ * @author Eric Bruneton
+ */
+public class AnalyzerException extends Exception {
+
+    public final AbstractInsnNode node;
+
+    public AnalyzerException(final AbstractInsnNode node, final String msg) {
+        super(msg);
+        this.node = node;
+    }
+
+    public AnalyzerException(final AbstractInsnNode node, final String msg,
+            final Throwable exception) {
+        super(msg, exception);
+        this.node = node;
+    }
+
+    public AnalyzerException(final AbstractInsnNode node, final String msg,
+            final Object expected, final Value encountered) {
+        super((msg == null ? "Expected " : msg + ": expected ") + expected
+                + ", but found " + encountered);
+        this.node = node;
+    }
+}