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

[01/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?"

Repository: tapestry-5
Updated Branches:
  refs/heads/5.3 1a03c5661 -> a0ac605db


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/asm-xml.dtd
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/asm-xml.dtd b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/asm-xml.dtd
new file mode 100644
index 0000000..b862085
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/asm-xml.dtd
@@ -0,0 +1,349 @@
+<!--
+  ASM XML Adapter
+  Copyright (c) 2004-2011, Eugene Kuleshov
+  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.
+-->
+
+<!--
+  This DTD must be used to create XML documents to be processed by
+  org.objectweb.asm.xml.ASMContentHandler
+-->
+
+<!--
+  Root element used to aggregate multiple classes into single document.
+-->
+<!ELEMENT classes ( class+ )>
+
+<!--
+  Root element for a single class.
+-->
+<!ELEMENT class ( interfaces, ( field | innerclass | method )*)>
+<!ATTLIST class access CDATA #REQUIRED>
+<!ATTLIST class name CDATA #REQUIRED>
+<!ATTLIST class parent CDATA #REQUIRED>
+<!ATTLIST class major CDATA #REQUIRED>
+<!ATTLIST class minor CDATA #REQUIRED>
+<!ATTLIST class source CDATA #IMPLIED>
+
+<!ELEMENT interfaces ( interface* )>
+<!ELEMENT interface EMPTY>
+<!ATTLIST interface name CDATA #REQUIRED>
+
+<!ELEMENT field EMPTY>
+<!ATTLIST field access CDATA #REQUIRED>
+<!ATTLIST field desc CDATA #REQUIRED>
+<!ATTLIST field name CDATA #REQUIRED>
+<!--
+  All characters out of interval 0x20 to 0x7f (inclusive) must
+  be encoded (\uXXXX) and character '\' must be replaced by "\\"
+-->
+<!ATTLIST field value CDATA #IMPLIED>
+
+<!ELEMENT innerclass EMPTY>
+<!ATTLIST innerclass access CDATA #REQUIRED>
+<!ATTLIST innerclass innerName CDATA #IMPLIED>
+<!ATTLIST innerclass name CDATA #REQUIRED>
+<!ATTLIST innerclass outerName CDATA #IMPLIED>
+
+<!--
+  Root element for method definition.
+-->
+<!ELEMENT method ( exceptions, code? )>
+<!ATTLIST method access CDATA #REQUIRED>
+<!ATTLIST method desc CDATA #REQUIRED>
+<!ATTLIST method name CDATA #REQUIRED>
+
+<!ELEMENT exceptions ( exception* )>
+<!ELEMENT exception EMPTY>
+<!ATTLIST exception name CDATA #REQUIRED>
+
+<!--
+  code element contains bytecode instructions and definitions for labels, line numbers, try/catch and max
+-->
+<!ELEMENT code (( AALOAD | AASTORE | ACONST_NULL | ALOAD | ANEWARRAY | ARETURN | ARRAYLENGTH | ASTORE | ATHROW | BALOAD | BASTORE | BIPUSH | CALOAD | CASTORE | CHECKCAST | D2F | D2I | D2L | DADD | DALOAD | DASTORE | DCMPG | DCMPL | DCONST_0 | DCONST_1 | DDIV | DLOAD | DMUL | DNEG | DREM | DRETURN | DSTORE | DSUB | DUP | DUP2 | DUP2_X1 | DUP2_X2 | DUP_X1 | DUP_X2 | SWAP | F2D | F2I | F2L | FADD | FALOAD | FASTORE | FCMPG | FCMPL | FCONST_0 | FCONST_1 | FCONST_2 | FDIV | FLOAD | FMUL | FNEG | FREM | FRETURN | FSTORE | FSUB | GETFIELD | GETSTATIC | GOTO | I2B | I2C | I2D | I2F | I2L | I2S | IADD | IALOAD | IAND | IASTORE | ICONST_0 | ICONST_1 | ICONST_2 | ICONST_3 | ICONST_4 | ICONST_5 | ICONST_M1 | IDIV | IFEQ | IFGE | IFGT | IFLE | IFLT | IFNE | IFNONNULL | IFNULL | IF_ACMPEQ | IF_ACMPNE | IF_ICMPEQ | IF_ICMPGE | IF_ICMPGT | IF_ICMPLE | IF_ICMPLT | IF_ICMPNE | IINC | ILOAD | IMUL | INEG | INSTANCEOF | INVOKEINTERFACE | INVOKESPECIAL | INVOKESTATIC | INVOKEVIRTUAL | IOR | IREM | IRETU
 RN | ISHL | ISHR | ISTORE | ISUB | IUSHR | IXOR | JSR | L2D | L2F | L2I | LADD | LALOAD | LAND | LASTORE | LCMP | LCONST_0 | LCONST_1 | LDC | LDIV | LLOAD | LMUL | LNEG | LOOKUPSWITCH | LOR | LREM | LRETURN | LSHL | LSHR | LSTORE | LSUB | LUSHR | LXOR | MONITORENTER | MONITOREXIT | MULTIANEWARRAY | NEW | NEWARRAY | NOP | POP | POP2 | PUTFIELD | PUTSTATIC | RET | RETURN | SALOAD | SASTORE | SIPUSH | TABLESWITCH | Label | LineNumber | TryCatch )*, Max)>
+
+<!ELEMENT Label EMPTY>
+<!ATTLIST Label name CDATA #REQUIRED>
+
+<!ELEMENT TryCatch EMPTY>
+<!ATTLIST TryCatch end CDATA #REQUIRED>
+<!ATTLIST TryCatch handler CDATA #REQUIRED>
+<!ATTLIST TryCatch start CDATA #REQUIRED>
+<!ATTLIST TryCatch type CDATA #IMPLIED>
+
+<!ELEMENT LineNumber EMPTY>
+<!ATTLIST LineNumber line CDATA #REQUIRED>
+<!ATTLIST LineNumber start CDATA #REQUIRED>
+
+<!ELEMENT Max EMPTY>
+<!ATTLIST Max maxLocals CDATA #REQUIRED>
+<!ATTLIST Max maxStack CDATA #REQUIRED>
+
+<!ELEMENT AALOAD EMPTY>
+<!ELEMENT AASTORE EMPTY>
+<!ELEMENT ACONST_NULL EMPTY>
+<!ELEMENT ALOAD EMPTY>
+<!ATTLIST ALOAD var CDATA #REQUIRED>
+<!ELEMENT ANEWARRAY EMPTY>
+<!ATTLIST ANEWARRAY desc CDATA #REQUIRED>
+<!ELEMENT ARETURN EMPTY>
+<!ELEMENT ARRAYLENGTH EMPTY>
+<!ELEMENT ASTORE EMPTY>
+<!ATTLIST ASTORE var CDATA #REQUIRED>
+<!ELEMENT ATHROW EMPTY>
+<!ELEMENT BALOAD EMPTY>
+<!ELEMENT BASTORE EMPTY>
+<!ELEMENT BIPUSH EMPTY>
+<!ATTLIST BIPUSH value CDATA #REQUIRED>
+<!ELEMENT CALOAD EMPTY>
+<!ELEMENT CASTORE EMPTY>
+<!ELEMENT CHECKCAST EMPTY>
+<!ATTLIST CHECKCAST desc CDATA #REQUIRED>
+<!ELEMENT D2F EMPTY>
+<!ELEMENT D2I EMPTY>
+<!ELEMENT D2L EMPTY>
+<!ELEMENT DADD EMPTY>
+<!ELEMENT DALOAD EMPTY>
+<!ELEMENT DASTORE EMPTY>
+<!ELEMENT DCMPG EMPTY>
+<!ELEMENT DCMPL EMPTY>
+<!ELEMENT DCONST_0 EMPTY>
+<!ELEMENT DCONST_1 EMPTY>
+<!ELEMENT DDIV EMPTY>
+<!ELEMENT DLOAD EMPTY>
+<!ATTLIST DLOAD var CDATA #REQUIRED>
+<!ELEMENT DMUL EMPTY>
+<!ELEMENT DNEG EMPTY>
+<!ELEMENT DREM EMPTY>
+<!ELEMENT DRETURN EMPTY>
+<!ELEMENT DSTORE EMPTY>
+<!ATTLIST DSTORE var CDATA #REQUIRED>
+<!ELEMENT DSUB EMPTY>
+<!ELEMENT DUP EMPTY>
+<!ELEMENT DUP2 EMPTY>
+<!ELEMENT DUP2_X1 EMPTY>
+<!ELEMENT DUP2_X2 EMPTY>
+<!ELEMENT DUP_X1 EMPTY>
+<!ELEMENT DUP_X2 EMPTY>
+<!ELEMENT SWAP EMPTY>
+<!ELEMENT F2D EMPTY>
+<!ELEMENT F2I EMPTY>
+<!ELEMENT F2L EMPTY>
+<!ELEMENT FADD EMPTY>
+<!ELEMENT FALOAD EMPTY>
+<!ELEMENT FASTORE EMPTY>
+<!ELEMENT FCMPG EMPTY>
+<!ELEMENT FCMPL EMPTY>
+<!ELEMENT FCONST_0 EMPTY>
+<!ELEMENT FCONST_1 EMPTY>
+<!ELEMENT FCONST_2 EMPTY>
+<!ELEMENT FDIV EMPTY>
+<!ELEMENT FLOAD EMPTY>
+<!ATTLIST FLOAD var CDATA #REQUIRED>
+<!ELEMENT FMUL EMPTY>
+<!ELEMENT FNEG EMPTY>
+<!ELEMENT FREM EMPTY>
+<!ELEMENT FRETURN EMPTY>
+<!ELEMENT FSTORE EMPTY>
+<!ATTLIST FSTORE var CDATA #REQUIRED>
+<!ELEMENT FSUB EMPTY>
+<!ELEMENT GETFIELD EMPTY>
+<!ATTLIST GETFIELD desc CDATA #REQUIRED>
+<!ATTLIST GETFIELD name CDATA #REQUIRED>
+<!ATTLIST GETFIELD owner CDATA #REQUIRED>
+<!ELEMENT GETSTATIC EMPTY>
+<!ATTLIST GETSTATIC desc CDATA #REQUIRED>
+<!ATTLIST GETSTATIC name CDATA #REQUIRED>
+<!ATTLIST GETSTATIC owner CDATA #REQUIRED>
+<!ELEMENT GOTO EMPTY>
+<!ATTLIST GOTO label CDATA #REQUIRED>
+<!ELEMENT I2B EMPTY>
+<!ELEMENT I2C EMPTY>
+<!ELEMENT I2D EMPTY>
+<!ELEMENT I2F EMPTY>
+<!ELEMENT I2L EMPTY>
+<!ELEMENT I2S EMPTY>
+<!ELEMENT IADD EMPTY>
+<!ELEMENT IALOAD EMPTY>
+<!ELEMENT IAND EMPTY>
+<!ELEMENT IASTORE EMPTY>
+<!ELEMENT ICONST_0 EMPTY>
+<!ELEMENT ICONST_1 EMPTY>
+<!ELEMENT ICONST_2 EMPTY>
+<!ELEMENT ICONST_3 EMPTY>
+<!ELEMENT ICONST_4 EMPTY>
+<!ELEMENT ICONST_5 EMPTY>
+<!ELEMENT ICONST_M1 EMPTY>
+<!ELEMENT IDIV EMPTY>
+<!ELEMENT IFEQ EMPTY>
+<!ATTLIST IFEQ label CDATA #REQUIRED>
+<!ELEMENT IFGE EMPTY>
+<!ATTLIST IFGE label CDATA #REQUIRED>
+<!ELEMENT IFGT EMPTY>
+<!ATTLIST IFGT label CDATA #REQUIRED>
+<!ELEMENT IFLE EMPTY>
+<!ATTLIST IFLE label CDATA #REQUIRED>
+<!ELEMENT IFLT EMPTY>
+<!ATTLIST IFLT label CDATA #REQUIRED>
+<!ELEMENT IFNE EMPTY>
+<!ATTLIST IFNE label CDATA #REQUIRED>
+<!ELEMENT IFNONNULL EMPTY>
+<!ATTLIST IFNONNULL label CDATA #REQUIRED>
+<!ELEMENT IFNULL EMPTY>
+<!ATTLIST IFNULL label CDATA #REQUIRED>
+<!ELEMENT IF_ACMPEQ EMPTY>
+<!ATTLIST IF_ACMPEQ label CDATA #REQUIRED>
+<!ELEMENT IF_ACMPNE EMPTY>
+<!ATTLIST IF_ACMPNE label CDATA #REQUIRED>
+<!ELEMENT IF_ICMPEQ EMPTY>
+<!ATTLIST IF_ICMPEQ label CDATA #REQUIRED>
+<!ELEMENT IF_ICMPGE EMPTY>
+<!ATTLIST IF_ICMPGE label CDATA #REQUIRED>
+<!ELEMENT IF_ICMPGT EMPTY>
+<!ATTLIST IF_ICMPGT label CDATA #REQUIRED>
+<!ELEMENT IF_ICMPLE EMPTY>
+<!ATTLIST IF_ICMPLE label CDATA #REQUIRED>
+<!ELEMENT IF_ICMPLT EMPTY>
+<!ATTLIST IF_ICMPLT label CDATA #REQUIRED>
+<!ELEMENT IF_ICMPNE EMPTY>
+<!ATTLIST IF_ICMPNE label CDATA #REQUIRED>
+<!ELEMENT IINC EMPTY>
+<!ATTLIST IINC inc CDATA #REQUIRED>
+<!ATTLIST IINC var CDATA #REQUIRED>
+<!ELEMENT ILOAD EMPTY>
+<!ATTLIST ILOAD var CDATA #REQUIRED>
+<!ELEMENT IMUL EMPTY>
+<!ELEMENT INEG EMPTY>
+<!ELEMENT INSTANCEOF EMPTY>
+<!ATTLIST INSTANCEOF desc CDATA #REQUIRED>
+<!ELEMENT INVOKEINTERFACE EMPTY>
+<!ATTLIST INVOKEINTERFACE desc CDATA #REQUIRED>
+<!ATTLIST INVOKEINTERFACE name CDATA #REQUIRED>
+<!ATTLIST INVOKEINTERFACE owner CDATA #REQUIRED>
+<!ELEMENT INVOKESPECIAL EMPTY>
+<!ATTLIST INVOKESPECIAL desc CDATA #REQUIRED>
+<!ATTLIST INVOKESPECIAL name CDATA #REQUIRED>
+<!ATTLIST INVOKESPECIAL owner CDATA #REQUIRED>
+<!ELEMENT INVOKESTATIC EMPTY>
+<!ATTLIST INVOKESTATIC desc CDATA #REQUIRED>
+<!ATTLIST INVOKESTATIC name CDATA #REQUIRED>
+<!ATTLIST INVOKESTATIC owner CDATA #REQUIRED>
+<!ELEMENT INVOKEVIRTUAL EMPTY>
+<!ATTLIST INVOKEVIRTUAL desc CDATA #REQUIRED>
+<!ATTLIST INVOKEVIRTUAL name CDATA #REQUIRED>
+<!ATTLIST INVOKEVIRTUAL owner CDATA #REQUIRED>
+<!ELEMENT INVOKEDYNAMIC ( bsmArgs+ )>
+<!ATTLIST INVOKEDYNAMIC desc CDATA #REQUIRED>
+<!ATTLIST INVOKEDYNAMIC name CDATA #REQUIRED>
+<!ATTLIST INVOKEDYNAMIC bsm CDATA #REQUIRED>
+<!ELEMENT bsmArgs EMPTY>
+<!ATTLIST bsmArgs cst CDATA #REQUIRED>
+<!ATTLIST bsmArgs desc CDATA #REQUIRED>
+<!ELEMENT IOR EMPTY>
+<!ELEMENT IREM EMPTY>
+<!ELEMENT IRETURN EMPTY>
+<!ELEMENT ISHL EMPTY>
+<!ELEMENT ISHR EMPTY>
+<!ELEMENT ISTORE EMPTY>
+<!ATTLIST ISTORE var CDATA #REQUIRED>
+<!ELEMENT ISUB EMPTY>
+<!ELEMENT IUSHR EMPTY>
+<!ELEMENT IXOR EMPTY>
+<!ELEMENT JSR EMPTY>
+<!ATTLIST JSR label CDATA #REQUIRED>
+<!ELEMENT L2D EMPTY>
+<!ELEMENT L2F EMPTY>
+<!ELEMENT L2I EMPTY>
+<!ELEMENT LADD EMPTY>
+<!ELEMENT LALOAD EMPTY>
+<!ELEMENT LAND EMPTY>
+<!ELEMENT LASTORE EMPTY>
+<!ELEMENT LCMP EMPTY>
+<!ELEMENT LCONST_0 EMPTY>
+<!ELEMENT LCONST_1 EMPTY>
+<!ELEMENT LDC EMPTY>
+<!--
+  All characters out of interval 0x20 to 0x7f (inclusive) must
+  be encoded (\uXXXX) and character '\' must be replaced by "\\"
+-->
+<!ATTLIST LDC cst CDATA #REQUIRED>
+<!ATTLIST LDC desc CDATA #REQUIRED>
+<!ELEMENT LDIV EMPTY>
+<!ELEMENT LLOAD EMPTY>
+<!ATTLIST LLOAD var CDATA #REQUIRED>
+<!ELEMENT LMUL EMPTY>
+<!ELEMENT LNEG EMPTY>
+<!ELEMENT LOR EMPTY>
+<!ELEMENT LREM EMPTY>
+<!ELEMENT LRETURN EMPTY>
+<!ELEMENT LSHL EMPTY>
+<!ELEMENT LSHR EMPTY>
+<!ELEMENT LSTORE EMPTY>
+<!ATTLIST LSTORE var CDATA #REQUIRED>
+<!ELEMENT LSUB EMPTY>
+<!ELEMENT LUSHR EMPTY>
+<!ELEMENT LXOR EMPTY>
+<!ELEMENT MONITORENTER EMPTY>
+<!ELEMENT MONITOREXIT EMPTY>
+<!ELEMENT MULTIANEWARRAY EMPTY>
+<!ATTLIST MULTIANEWARRAY desc CDATA #REQUIRED>
+<!ATTLIST MULTIANEWARRAY dims CDATA #REQUIRED>
+<!ELEMENT NEW EMPTY>
+<!ATTLIST NEW desc CDATA #REQUIRED>
+<!ELEMENT NEWARRAY EMPTY>
+<!ATTLIST NEWARRAY value CDATA #REQUIRED>
+<!ELEMENT NOP EMPTY>
+<!ELEMENT POP EMPTY>
+<!ELEMENT POP2 EMPTY>
+<!ELEMENT PUTFIELD EMPTY>
+<!ATTLIST PUTFIELD desc CDATA #REQUIRED>
+<!ATTLIST PUTFIELD name CDATA #REQUIRED>
+<!ATTLIST PUTFIELD owner CDATA #REQUIRED>
+<!ELEMENT PUTSTATIC EMPTY>
+<!ATTLIST PUTSTATIC desc CDATA #REQUIRED>
+<!ATTLIST PUTSTATIC name CDATA #REQUIRED>
+<!ATTLIST PUTSTATIC owner CDATA #REQUIRED>
+<!ELEMENT RET EMPTY>
+<!ATTLIST RET var CDATA #REQUIRED>
+<!ELEMENT RETURN EMPTY>
+<!ELEMENT SALOAD EMPTY>
+<!ELEMENT SASTORE EMPTY>
+<!ELEMENT SIPUSH EMPTY>
+<!ATTLIST SIPUSH value CDATA #REQUIRED>
+
+<!ELEMENT LOOKUPSWITCH ( label+ )>
+<!ATTLIST LOOKUPSWITCH dflt CDATA #REQUIRED>
+
+<!ELEMENT TABLESWITCH ( label+ )>
+<!ATTLIST TABLESWITCH dflt CDATA #REQUIRED>
+<!ATTLIST TABLESWITCH max CDATA #REQUIRED>
+<!ATTLIST TABLESWITCH min CDATA #REQUIRED>
+
+<!ELEMENT label EMPTY>
+<!ATTLIST label key CDATA #IMPLIED>
+<!ATTLIST label name CDATA #REQUIRED>
+

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/package.html
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/package.html b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/package.html
new file mode 100644
index 0000000..d7bbe66
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/package.html
@@ -0,0 +1,96 @@
+<html>
+<!--
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * 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.
+-->
+<body>
+Provides <a href="http://sax.sourceforge.net/">SAX 2.0</a> adapters for ASM
+visitors to convert classes to and from XML.
+These adapters can be chained with other SAX compliant content handlers and
+filters, eg. XSLT or XQuery engines. This package is bundled as
+a separate <tt>asm-xml.jar</tt> library and requires <tt>asm.jar</tt>.
+<p>
+<tt>ASMContentHandler</tt> and <tt>SAXClassAdapter/SAXCodeAdapter</tt>
+are using <a href="asm-xml.dtd">asm-xml.dtd</a>.
+Here is the example of bytecode to bytecode XSLT transformation.
+
+<pre>
+    SAXTransformerFactory saxtf = ( SAXTransformerFactory) TransformerFactory.newInstance();
+    Templates templates = saxtf.newTemplates( xsltSource);
+
+    TransformerHandler handler = saxtf.newTransformerHandler( templates);
+    handler.setResult( new SAXResult( new ASMContentHandler( outputStream, computeMax)));
+
+    ClassReader cr = new ClassReader( bytecode);
+    cr.accept( new SAXClassAdapter( handler, cr.getVersion(), false), false);
+</pre>
+
+See JAXP and SAX documentation for more detils.
+
+<p>
+There are few illustrations of the bytecode transformation with XSLT in
+examples directory. The following XSLT procesors has been tested.
+
+<blockquote>
+<table border="1" cellspacing="0" cellpadding="3">
+<tr>
+<th>Engine</td>
+<th>javax.xml.transform.TransformerFactory property</td>
+</tr>
+
+<tr>
+<td>jd.xslt</td>
+<td>jd.xml.xslt.trax.TransformerFactoryImpl</td>
+</tr>
+
+<tr>
+<td>Saxon</td>
+<td>net.sf.saxon.TransformerFactoryImpl</td>
+</tr>
+
+<tr>
+<td>Caucho</td>
+<td>com.caucho.xsl.Xsl</td>
+</tr>
+
+<tr>
+<td>Xalan interpeter</td>
+<td>org.apache.xalan.processor.TransformerFactory</td>
+</tr>
+
+<tr>
+<td>Xalan xsltc</td>
+<td>org.apache.xalan.xsltc.trax.TransformerFactoryImpl</td>
+</tr>
+</table>
+</blockquote>
+
+@since ASM 1.4.3
+
+</body>
+</html>


[15/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java
new file mode 100644
index 0000000..ceb051f
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java
@@ -0,0 +1,1628 @@
+/***
+ * 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.commons;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+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;
+
+/**
+ * A {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor} with convenient methods to generate
+ * code. For example, using this adapter, the class below
+ * 
+ * <pre>
+ * public class Example {
+ *     public static void main(String[] args) {
+ *         System.out.println(&quot;Hello world!&quot;);
+ *     }
+ * }
+ * </pre>
+ * 
+ * can be generated as follows:
+ * 
+ * <pre>
+ * ClassWriter cw = new ClassWriter(true);
+ * cw.visit(V1_1, ACC_PUBLIC, &quot;Example&quot;, null, &quot;java/lang/Object&quot;, null);
+ * 
+ * Method m = Method.getMethod(&quot;void &lt;init&gt; ()&quot;);
+ * GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cw);
+ * mg.loadThis();
+ * mg.invokeConstructor(Type.getType(Object.class), m);
+ * mg.returnValue();
+ * mg.endMethod();
+ * 
+ * m = Method.getMethod(&quot;void main (String[])&quot;);
+ * mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw);
+ * mg.getStatic(Type.getType(System.class), &quot;out&quot;, Type.getType(PrintStream.class));
+ * mg.push(&quot;Hello world!&quot;);
+ * mg.invokeVirtual(Type.getType(PrintStream.class),
+ *         Method.getMethod(&quot;void println (String)&quot;));
+ * mg.returnValue();
+ * mg.endMethod();
+ * 
+ * cw.visitEnd();
+ * </pre>
+ * 
+ * @author Juozas Baliuka
+ * @author Chris Nokleberg
+ * @author Eric Bruneton
+ * @author Prashant Deva
+ */
+public class GeneratorAdapter extends LocalVariablesSorter {
+
+    private static final String CLDESC = "Ljava/lang/Class;";
+
+    private static final Type BYTE_TYPE = Type.getObjectType("java/lang/Byte");
+
+    private static final Type BOOLEAN_TYPE = Type
+            .getObjectType("java/lang/Boolean");
+
+    private static final Type SHORT_TYPE = Type
+            .getObjectType("java/lang/Short");
+
+    private static final Type CHARACTER_TYPE = Type
+            .getObjectType("java/lang/Character");
+
+    private static final Type INTEGER_TYPE = Type
+            .getObjectType("java/lang/Integer");
+
+    private static final Type FLOAT_TYPE = Type
+            .getObjectType("java/lang/Float");
+
+    private static final Type LONG_TYPE = Type.getObjectType("java/lang/Long");
+
+    private static final Type DOUBLE_TYPE = Type
+            .getObjectType("java/lang/Double");
+
+    private static final Type NUMBER_TYPE = Type
+            .getObjectType("java/lang/Number");
+
+    private static final Type OBJECT_TYPE = Type
+            .getObjectType("java/lang/Object");
+
+    private static final Method BOOLEAN_VALUE = Method
+            .getMethod("boolean booleanValue()");
+
+    private static final Method CHAR_VALUE = Method
+            .getMethod("char charValue()");
+
+    private static final Method INT_VALUE = Method.getMethod("int intValue()");
+
+    private static final Method FLOAT_VALUE = Method
+            .getMethod("float floatValue()");
+
+    private static final Method LONG_VALUE = Method
+            .getMethod("long longValue()");
+
+    private static final Method DOUBLE_VALUE = Method
+            .getMethod("double doubleValue()");
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int ADD = Opcodes.IADD;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int SUB = Opcodes.ISUB;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int MUL = Opcodes.IMUL;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int DIV = Opcodes.IDIV;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int REM = Opcodes.IREM;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int NEG = Opcodes.INEG;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int SHL = Opcodes.ISHL;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int SHR = Opcodes.ISHR;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int USHR = Opcodes.IUSHR;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int AND = Opcodes.IAND;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int OR = Opcodes.IOR;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int XOR = Opcodes.IXOR;
+
+    /**
+     * Constant for the {@link #ifCmp ifCmp} method.
+     */
+    public static final int EQ = Opcodes.IFEQ;
+
+    /**
+     * Constant for the {@link #ifCmp ifCmp} method.
+     */
+    public static final int NE = Opcodes.IFNE;
+
+    /**
+     * Constant for the {@link #ifCmp ifCmp} method.
+     */
+    public static final int LT = Opcodes.IFLT;
+
+    /**
+     * Constant for the {@link #ifCmp ifCmp} method.
+     */
+    public static final int GE = Opcodes.IFGE;
+
+    /**
+     * Constant for the {@link #ifCmp ifCmp} method.
+     */
+    public static final int GT = Opcodes.IFGT;
+
+    /**
+     * Constant for the {@link #ifCmp ifCmp} method.
+     */
+    public static final int LE = Opcodes.IFLE;
+
+    /**
+     * Access flags of the method visited by this adapter.
+     */
+    private final int access;
+
+    /**
+     * Return type of the method visited by this adapter.
+     */
+    private final Type returnType;
+
+    /**
+     * Argument types of the method visited by this adapter.
+     */
+    private final Type[] argumentTypes;
+
+    /**
+     * Types of the local variables of the method visited by this adapter.
+     */
+    private final List<Type> localTypes = new ArrayList<Type>();
+
+    /**
+     * Creates a new {@link GeneratorAdapter}. <i>Subclasses must not use this
+     * constructor</i>. Instead, they must use the
+     * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
+     * version.
+     * 
+     * @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}).
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public GeneratorAdapter(final MethodVisitor mv, final int access,
+            final String name, final String desc) {
+        this(Opcodes.ASM5, mv, access, name, desc);
+        if (getClass() != GeneratorAdapter.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Creates a new {@link GeneratorAdapter}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @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 GeneratorAdapter(final int api, final MethodVisitor mv,
+            final int access, final String name, final String desc) {
+        super(api, access, desc, mv);
+        this.access = access;
+        this.returnType = Type.getReturnType(desc);
+        this.argumentTypes = Type.getArgumentTypes(desc);
+    }
+
+    /**
+     * Creates a new {@link GeneratorAdapter}. <i>Subclasses must not use this
+     * constructor</i>. Instead, they must use the
+     * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
+     * version.
+     * 
+     * @param access
+     *            access flags of the adapted method.
+     * @param method
+     *            the adapted method.
+     * @param mv
+     *            the method visitor to which this adapter delegates calls.
+     */
+    public GeneratorAdapter(final int access, final Method method,
+            final MethodVisitor mv) {
+        this(mv, access, null, method.getDescriptor());
+    }
+
+    /**
+     * Creates a new {@link GeneratorAdapter}. <i>Subclasses must not use this
+     * constructor</i>. Instead, they must use the
+     * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
+     * version.
+     * 
+     * @param access
+     *            access flags of the adapted method.
+     * @param method
+     *            the adapted method.
+     * @param signature
+     *            the signature of the adapted method (may be <tt>null</tt>).
+     * @param exceptions
+     *            the exceptions thrown by the adapted method (may be
+     *            <tt>null</tt>).
+     * @param cv
+     *            the class visitor to which this adapter delegates calls.
+     */
+    public GeneratorAdapter(final int access, final Method method,
+            final String signature, final Type[] exceptions,
+            final ClassVisitor cv) {
+        this(access, method, cv
+                .visitMethod(access, method.getName(), method.getDescriptor(),
+                        signature, getInternalNames(exceptions)));
+    }
+
+    /**
+     * Returns the internal names of the given types.
+     * 
+     * @param types
+     *            a set of types.
+     * @return the internal names of the given types.
+     */
+    private static String[] getInternalNames(final Type[] types) {
+        if (types == null) {
+            return null;
+        }
+        String[] names = new String[types.length];
+        for (int i = 0; i < names.length; ++i) {
+            names[i] = types[i].getInternalName();
+        }
+        return names;
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to push constants on the stack
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value
+     *            the value to be pushed on the stack.
+     */
+    public void push(final boolean value) {
+        push(value ? 1 : 0);
+    }
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value
+     *            the value to be pushed on the stack.
+     */
+    public void push(final int value) {
+        if (value >= -1 && value <= 5) {
+            mv.visitInsn(Opcodes.ICONST_0 + value);
+        } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
+            mv.visitIntInsn(Opcodes.BIPUSH, value);
+        } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
+            mv.visitIntInsn(Opcodes.SIPUSH, value);
+        } else {
+            mv.visitLdcInsn(new Integer(value));
+        }
+    }
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value
+     *            the value to be pushed on the stack.
+     */
+    public void push(final long value) {
+        if (value == 0L || value == 1L) {
+            mv.visitInsn(Opcodes.LCONST_0 + (int) value);
+        } else {
+            mv.visitLdcInsn(new Long(value));
+        }
+    }
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value
+     *            the value to be pushed on the stack.
+     */
+    public void push(final float value) {
+        int bits = Float.floatToIntBits(value);
+        if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2
+            mv.visitInsn(Opcodes.FCONST_0 + (int) value);
+        } else {
+            mv.visitLdcInsn(new Float(value));
+        }
+    }
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value
+     *            the value to be pushed on the stack.
+     */
+    public void push(final double value) {
+        long bits = Double.doubleToLongBits(value);
+        if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d
+            mv.visitInsn(Opcodes.DCONST_0 + (int) value);
+        } else {
+            mv.visitLdcInsn(new Double(value));
+        }
+    }
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value
+     *            the value to be pushed on the stack. May be <tt>null</tt>.
+     */
+    public void push(final String value) {
+        if (value == null) {
+            mv.visitInsn(Opcodes.ACONST_NULL);
+        } else {
+            mv.visitLdcInsn(value);
+        }
+    }
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value
+     *            the value to be pushed on the stack.
+     */
+    public void push(final Type value) {
+        if (value == null) {
+            mv.visitInsn(Opcodes.ACONST_NULL);
+        } else {
+            switch (value.getSort()) {
+            case Type.BOOLEAN:
+                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean",
+                        "TYPE", CLDESC);
+                break;
+            case Type.CHAR:
+                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Character",
+                        "TYPE", CLDESC);
+                break;
+            case Type.BYTE:
+                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Byte", "TYPE",
+                        CLDESC);
+                break;
+            case Type.SHORT:
+                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Short", "TYPE",
+                        CLDESC);
+                break;
+            case Type.INT:
+                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Integer",
+                        "TYPE", CLDESC);
+                break;
+            case Type.FLOAT:
+                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Float", "TYPE",
+                        CLDESC);
+                break;
+            case Type.LONG:
+                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Long", "TYPE",
+                        CLDESC);
+                break;
+            case Type.DOUBLE:
+                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Double",
+                        "TYPE", CLDESC);
+                break;
+            default:
+                mv.visitLdcInsn(value);
+            }
+        }
+    }
+
+    /**
+     * Generates the instruction to push a handle on the stack.
+     * 
+     * @param handle
+     *            the handle to be pushed on the stack.
+     */
+    public void push(final Handle handle) {
+        mv.visitLdcInsn(handle);
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to load and store method arguments
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the index of the given method argument in the frame's local
+     * variables array.
+     * 
+     * @param arg
+     *            the index of a method argument.
+     * @return the index of the given method argument in the frame's local
+     *         variables array.
+     */
+    private int getArgIndex(final int arg) {
+        int index = (access & Opcodes.ACC_STATIC) == 0 ? 1 : 0;
+        for (int i = 0; i < arg; i++) {
+            index += argumentTypes[i].getSize();
+        }
+        return index;
+    }
+
+    /**
+     * Generates the instruction to push a local variable on the stack.
+     * 
+     * @param type
+     *            the type of the local variable to be loaded.
+     * @param index
+     *            an index in the frame's local variables array.
+     */
+    private void loadInsn(final Type type, final int index) {
+        mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), index);
+    }
+
+    /**
+     * Generates the instruction to store the top stack value in a local
+     * variable.
+     * 
+     * @param type
+     *            the type of the local variable to be stored.
+     * @param index
+     *            an index in the frame's local variables array.
+     */
+    private void storeInsn(final Type type, final int index) {
+        mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), index);
+    }
+
+    /**
+     * Generates the instruction to load 'this' on the stack.
+     */
+    public void loadThis() {
+        if ((access & Opcodes.ACC_STATIC) != 0) {
+            throw new IllegalStateException(
+                    "no 'this' pointer within static method");
+        }
+        mv.visitVarInsn(Opcodes.ALOAD, 0);
+    }
+
+    /**
+     * Generates the instruction to load the given method argument on the stack.
+     * 
+     * @param arg
+     *            the index of a method argument.
+     */
+    public void loadArg(final int arg) {
+        loadInsn(argumentTypes[arg], getArgIndex(arg));
+    }
+
+    /**
+     * Generates the instructions to load the given method arguments on the
+     * stack.
+     * 
+     * @param arg
+     *            the index of the first method argument to be loaded.
+     * @param count
+     *            the number of method arguments to be loaded.
+     */
+    public void loadArgs(final int arg, final int count) {
+        int index = getArgIndex(arg);
+        for (int i = 0; i < count; ++i) {
+            Type t = argumentTypes[arg + i];
+            loadInsn(t, index);
+            index += t.getSize();
+        }
+    }
+
+    /**
+     * Generates the instructions to load all the method arguments on the stack.
+     */
+    public void loadArgs() {
+        loadArgs(0, argumentTypes.length);
+    }
+
+    /**
+     * Generates the instructions to load all the method arguments on the stack,
+     * as a single object array.
+     */
+    public void loadArgArray() {
+        push(argumentTypes.length);
+        newArray(OBJECT_TYPE);
+        for (int i = 0; i < argumentTypes.length; i++) {
+            dup();
+            push(i);
+            loadArg(i);
+            box(argumentTypes[i]);
+            arrayStore(OBJECT_TYPE);
+        }
+    }
+
+    /**
+     * Generates the instruction to store the top stack value in the given
+     * method argument.
+     * 
+     * @param arg
+     *            the index of a method argument.
+     */
+    public void storeArg(final int arg) {
+        storeInsn(argumentTypes[arg], getArgIndex(arg));
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to load and store local variables
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the type of the given local variable.
+     * 
+     * @param local
+     *            a local variable identifier, as returned by
+     *            {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+     * @return the type of the given local variable.
+     */
+    public Type getLocalType(final int local) {
+        return localTypes.get(local - firstLocal);
+    }
+
+    @Override
+    protected void setLocalType(final int local, final Type type) {
+        int index = local - firstLocal;
+        while (localTypes.size() < index + 1) {
+            localTypes.add(null);
+        }
+        localTypes.set(index, type);
+    }
+
+    /**
+     * Generates the instruction to load the given local variable on the stack.
+     * 
+     * @param local
+     *            a local variable identifier, as returned by
+     *            {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+     */
+    public void loadLocal(final int local) {
+        loadInsn(getLocalType(local), local);
+    }
+
+    /**
+     * Generates the instruction to load the given local variable on the stack.
+     * 
+     * @param local
+     *            a local variable identifier, as returned by
+     *            {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+     * @param type
+     *            the type of this local variable.
+     */
+    public void loadLocal(final int local, final Type type) {
+        setLocalType(local, type);
+        loadInsn(type, local);
+    }
+
+    /**
+     * Generates the instruction to store the top stack value in the given local
+     * variable.
+     * 
+     * @param local
+     *            a local variable identifier, as returned by
+     *            {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+     */
+    public void storeLocal(final int local) {
+        storeInsn(getLocalType(local), local);
+    }
+
+    /**
+     * Generates the instruction to store the top stack value in the given local
+     * variable.
+     * 
+     * @param local
+     *            a local variable identifier, as returned by
+     *            {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+     * @param type
+     *            the type of this local variable.
+     */
+    public void storeLocal(final int local, final Type type) {
+        setLocalType(local, type);
+        storeInsn(type, local);
+    }
+
+    /**
+     * Generates the instruction to load an element from an array.
+     * 
+     * @param type
+     *            the type of the array element to be loaded.
+     */
+    public void arrayLoad(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
+    }
+
+    /**
+     * Generates the instruction to store an element in an array.
+     * 
+     * @param type
+     *            the type of the array element to be stored.
+     */
+    public void arrayStore(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to manage the stack
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates a POP instruction.
+     */
+    public void pop() {
+        mv.visitInsn(Opcodes.POP);
+    }
+
+    /**
+     * Generates a POP2 instruction.
+     */
+    public void pop2() {
+        mv.visitInsn(Opcodes.POP2);
+    }
+
+    /**
+     * Generates a DUP instruction.
+     */
+    public void dup() {
+        mv.visitInsn(Opcodes.DUP);
+    }
+
+    /**
+     * Generates a DUP2 instruction.
+     */
+    public void dup2() {
+        mv.visitInsn(Opcodes.DUP2);
+    }
+
+    /**
+     * Generates a DUP_X1 instruction.
+     */
+    public void dupX1() {
+        mv.visitInsn(Opcodes.DUP_X1);
+    }
+
+    /**
+     * Generates a DUP_X2 instruction.
+     */
+    public void dupX2() {
+        mv.visitInsn(Opcodes.DUP_X2);
+    }
+
+    /**
+     * Generates a DUP2_X1 instruction.
+     */
+    public void dup2X1() {
+        mv.visitInsn(Opcodes.DUP2_X1);
+    }
+
+    /**
+     * Generates a DUP2_X2 instruction.
+     */
+    public void dup2X2() {
+        mv.visitInsn(Opcodes.DUP2_X2);
+    }
+
+    /**
+     * Generates a SWAP instruction.
+     */
+    public void swap() {
+        mv.visitInsn(Opcodes.SWAP);
+    }
+
+    /**
+     * Generates the instructions to swap the top two stack values.
+     * 
+     * @param prev
+     *            type of the top - 1 stack value.
+     * @param type
+     *            type of the top stack value.
+     */
+    public void swap(final Type prev, final Type type) {
+        if (type.getSize() == 1) {
+            if (prev.getSize() == 1) {
+                swap(); // same as dupX1(), pop();
+            } else {
+                dupX2();
+                pop();
+            }
+        } else {
+            if (prev.getSize() == 1) {
+                dup2X1();
+                pop2();
+            } else {
+                dup2X2();
+                pop2();
+            }
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to do mathematical and logical operations
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates the instruction to do the specified mathematical or logical
+     * operation.
+     * 
+     * @param op
+     *            a mathematical or logical operation. Must be one of ADD, SUB,
+     *            MUL, DIV, REM, NEG, SHL, SHR, USHR, AND, OR, XOR.
+     * @param type
+     *            the type of the operand(s) for this operation.
+     */
+    public void math(final int op, final Type type) {
+        mv.visitInsn(type.getOpcode(op));
+    }
+
+    /**
+     * Generates the instructions to compute the bitwise negation of the top
+     * stack value.
+     */
+    public void not() {
+        mv.visitInsn(Opcodes.ICONST_1);
+        mv.visitInsn(Opcodes.IXOR);
+    }
+
+    /**
+     * Generates the instruction to increment the given local variable.
+     * 
+     * @param local
+     *            the local variable to be incremented.
+     * @param amount
+     *            the amount by which the local variable must be incremented.
+     */
+    public void iinc(final int local, final int amount) {
+        mv.visitIincInsn(local, amount);
+    }
+
+    /**
+     * Generates the instructions to cast a numerical value from one type to
+     * another.
+     * 
+     * @param from
+     *            the type of the top stack value
+     * @param to
+     *            the type into which this value must be cast.
+     */
+    public void cast(final Type from, final Type to) {
+        if (from != to) {
+            if (from == Type.DOUBLE_TYPE) {
+                if (to == Type.FLOAT_TYPE) {
+                    mv.visitInsn(Opcodes.D2F);
+                } else if (to == Type.LONG_TYPE) {
+                    mv.visitInsn(Opcodes.D2L);
+                } else {
+                    mv.visitInsn(Opcodes.D2I);
+                    cast(Type.INT_TYPE, to);
+                }
+            } else if (from == Type.FLOAT_TYPE) {
+                if (to == Type.DOUBLE_TYPE) {
+                    mv.visitInsn(Opcodes.F2D);
+                } else if (to == Type.LONG_TYPE) {
+                    mv.visitInsn(Opcodes.F2L);
+                } else {
+                    mv.visitInsn(Opcodes.F2I);
+                    cast(Type.INT_TYPE, to);
+                }
+            } else if (from == Type.LONG_TYPE) {
+                if (to == Type.DOUBLE_TYPE) {
+                    mv.visitInsn(Opcodes.L2D);
+                } else if (to == Type.FLOAT_TYPE) {
+                    mv.visitInsn(Opcodes.L2F);
+                } else {
+                    mv.visitInsn(Opcodes.L2I);
+                    cast(Type.INT_TYPE, to);
+                }
+            } else {
+                if (to == Type.BYTE_TYPE) {
+                    mv.visitInsn(Opcodes.I2B);
+                } else if (to == Type.CHAR_TYPE) {
+                    mv.visitInsn(Opcodes.I2C);
+                } else if (to == Type.DOUBLE_TYPE) {
+                    mv.visitInsn(Opcodes.I2D);
+                } else if (to == Type.FLOAT_TYPE) {
+                    mv.visitInsn(Opcodes.I2F);
+                } else if (to == Type.LONG_TYPE) {
+                    mv.visitInsn(Opcodes.I2L);
+                } else if (to == Type.SHORT_TYPE) {
+                    mv.visitInsn(Opcodes.I2S);
+                }
+            }
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to do boxing and unboxing operations
+    // ------------------------------------------------------------------------
+
+    private static Type getBoxedType(final Type type) {
+        switch (type.getSort()) {
+        case Type.BYTE:
+            return BYTE_TYPE;
+        case Type.BOOLEAN:
+            return BOOLEAN_TYPE;
+        case Type.SHORT:
+            return SHORT_TYPE;
+        case Type.CHAR:
+            return CHARACTER_TYPE;
+        case Type.INT:
+            return INTEGER_TYPE;
+        case Type.FLOAT:
+            return FLOAT_TYPE;
+        case Type.LONG:
+            return LONG_TYPE;
+        case Type.DOUBLE:
+            return DOUBLE_TYPE;
+        }
+        return type;
+    }
+
+    /**
+     * Generates the instructions to box the top stack value. This value is
+     * replaced by its boxed equivalent on top of the stack.
+     * 
+     * @param type
+     *            the type of the top stack value.
+     */
+    public void box(final Type type) {
+        if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
+            return;
+        }
+        if (type == Type.VOID_TYPE) {
+            push((String) null);
+        } else {
+            Type boxed = getBoxedType(type);
+            newInstance(boxed);
+            if (type.getSize() == 2) {
+                // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o
+                dupX2();
+                dupX2();
+                pop();
+            } else {
+                // p -> po -> opo -> oop -> o
+                dupX1();
+                swap();
+            }
+            invokeConstructor(boxed, new Method("<init>", Type.VOID_TYPE,
+                    new Type[] { type }));
+        }
+    }
+
+    /**
+     * Generates the instructions to box the top stack value using Java 5's
+     * valueOf() method. This value is replaced by its boxed equivalent on top
+     * of the stack.
+     * 
+     * @param type
+     *            the type of the top stack value.
+     */
+    public void valueOf(final Type type) {
+        if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
+            return;
+        }
+        if (type == Type.VOID_TYPE) {
+            push((String) null);
+        } else {
+            Type boxed = getBoxedType(type);
+            invokeStatic(boxed, new Method("valueOf", boxed,
+                    new Type[] { type }));
+        }
+    }
+
+    /**
+     * Generates the instructions to unbox the top stack value. This value is
+     * replaced by its unboxed equivalent on top of the stack.
+     * 
+     * @param type
+     *            the type of the top stack value.
+     */
+    public void unbox(final Type type) {
+        Type t = NUMBER_TYPE;
+        Method sig = null;
+        switch (type.getSort()) {
+        case Type.VOID:
+            return;
+        case Type.CHAR:
+            t = CHARACTER_TYPE;
+            sig = CHAR_VALUE;
+            break;
+        case Type.BOOLEAN:
+            t = BOOLEAN_TYPE;
+            sig = BOOLEAN_VALUE;
+            break;
+        case Type.DOUBLE:
+            sig = DOUBLE_VALUE;
+            break;
+        case Type.FLOAT:
+            sig = FLOAT_VALUE;
+            break;
+        case Type.LONG:
+            sig = LONG_VALUE;
+            break;
+        case Type.INT:
+        case Type.SHORT:
+        case Type.BYTE:
+            sig = INT_VALUE;
+        }
+        if (sig == null) {
+            checkCast(type);
+        } else {
+            checkCast(t);
+            invokeVirtual(t, sig);
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to jump to other instructions
+    // ------------------------------------------------------------------------
+
+    /**
+     * Creates a new {@link Label}.
+     * 
+     * @return a new {@link Label}.
+     */
+    public Label newLabel() {
+        return new Label();
+    }
+
+    /**
+     * Marks the current code position with the given label.
+     * 
+     * @param label
+     *            a label.
+     */
+    public void mark(final Label label) {
+        mv.visitLabel(label);
+    }
+
+    /**
+     * Marks the current code position with a new label.
+     * 
+     * @return the label that was created to mark the current code position.
+     */
+    public Label mark() {
+        Label label = new Label();
+        mv.visitLabel(label);
+        return label;
+    }
+
+    /**
+     * Generates the instructions to jump to a label based on the comparison of
+     * the top two stack values.
+     * 
+     * @param type
+     *            the type of the top two stack values.
+     * @param mode
+     *            how these values must be compared. One of EQ, NE, LT, GE, GT,
+     *            LE.
+     * @param label
+     *            where to jump if the comparison result is <tt>true</tt>.
+     */
+    public void ifCmp(final Type type, final int mode, final Label label) {
+        switch (type.getSort()) {
+        case Type.LONG:
+            mv.visitInsn(Opcodes.LCMP);
+            break;
+        case Type.DOUBLE:
+            mv.visitInsn(mode == GE || mode == GT ? Opcodes.DCMPL
+                    : Opcodes.DCMPG);
+            break;
+        case Type.FLOAT:
+            mv.visitInsn(mode == GE || mode == GT ? Opcodes.FCMPL
+                    : Opcodes.FCMPG);
+            break;
+        case Type.ARRAY:
+        case Type.OBJECT:
+            switch (mode) {
+            case EQ:
+                mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
+                return;
+            case NE:
+                mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
+                return;
+            }
+            throw new IllegalArgumentException("Bad comparison for type "
+                    + type);
+        default:
+            int intOp = -1;
+            switch (mode) {
+            case EQ:
+                intOp = Opcodes.IF_ICMPEQ;
+                break;
+            case NE:
+                intOp = Opcodes.IF_ICMPNE;
+                break;
+            case GE:
+                intOp = Opcodes.IF_ICMPGE;
+                break;
+            case LT:
+                intOp = Opcodes.IF_ICMPLT;
+                break;
+            case LE:
+                intOp = Opcodes.IF_ICMPLE;
+                break;
+            case GT:
+                intOp = Opcodes.IF_ICMPGT;
+                break;
+            }
+            mv.visitJumpInsn(intOp, label);
+            return;
+        }
+        mv.visitJumpInsn(mode, label);
+    }
+
+    /**
+     * Generates the instructions to jump to a label based on the comparison of
+     * the top two integer stack values.
+     * 
+     * @param mode
+     *            how these values must be compared. One of EQ, NE, LT, GE, GT,
+     *            LE.
+     * @param label
+     *            where to jump if the comparison result is <tt>true</tt>.
+     */
+    public void ifICmp(final int mode, final Label label) {
+        ifCmp(Type.INT_TYPE, mode, label);
+    }
+
+    /**
+     * Generates the instructions to jump to a label based on the comparison of
+     * the top integer stack value with zero.
+     * 
+     * @param mode
+     *            how these values must be compared. One of EQ, NE, LT, GE, GT,
+     *            LE.
+     * @param label
+     *            where to jump if the comparison result is <tt>true</tt>.
+     */
+    public void ifZCmp(final int mode, final Label label) {
+        mv.visitJumpInsn(mode, label);
+    }
+
+    /**
+     * Generates the instruction to jump to the given label if the top stack
+     * value is null.
+     * 
+     * @param label
+     *            where to jump if the condition is <tt>true</tt>.
+     */
+    public void ifNull(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFNULL, label);
+    }
+
+    /**
+     * Generates the instruction to jump to the given label if the top stack
+     * value is not null.
+     * 
+     * @param label
+     *            where to jump if the condition is <tt>true</tt>.
+     */
+    public void ifNonNull(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFNONNULL, label);
+    }
+
+    /**
+     * Generates the instruction to jump to the given label.
+     * 
+     * @param label
+     *            where to jump if the condition is <tt>true</tt>.
+     */
+    public void goTo(final Label label) {
+        mv.visitJumpInsn(Opcodes.GOTO, label);
+    }
+
+    /**
+     * Generates a RET instruction.
+     * 
+     * @param local
+     *            a local variable identifier, as returned by
+     *            {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+     */
+    public void ret(final int local) {
+        mv.visitVarInsn(Opcodes.RET, local);
+    }
+
+    /**
+     * Generates the instructions for a switch statement.
+     * 
+     * @param keys
+     *            the switch case keys.
+     * @param generator
+     *            a generator to generate the code for the switch cases.
+     */
+    public void tableSwitch(final int[] keys,
+            final TableSwitchGenerator generator) {
+        float density;
+        if (keys.length == 0) {
+            density = 0;
+        } else {
+            density = (float) keys.length
+                    / (keys[keys.length - 1] - keys[0] + 1);
+        }
+        tableSwitch(keys, generator, density >= 0.5f);
+    }
+
+    /**
+     * Generates the instructions for a switch statement.
+     * 
+     * @param keys
+     *            the switch case keys.
+     * @param generator
+     *            a generator to generate the code for the switch cases.
+     * @param useTable
+     *            <tt>true</tt> to use a TABLESWITCH instruction, or
+     *            <tt>false</tt> to use a LOOKUPSWITCH instruction.
+     */
+    public void tableSwitch(final int[] keys,
+            final TableSwitchGenerator generator, final boolean useTable) {
+        for (int i = 1; i < keys.length; ++i) {
+            if (keys[i] < keys[i - 1]) {
+                throw new IllegalArgumentException(
+                        "keys must be sorted ascending");
+            }
+        }
+        Label def = newLabel();
+        Label end = newLabel();
+        if (keys.length > 0) {
+            int len = keys.length;
+            int min = keys[0];
+            int max = keys[len - 1];
+            int range = max - min + 1;
+            if (useTable) {
+                Label[] labels = new Label[range];
+                Arrays.fill(labels, def);
+                for (int i = 0; i < len; ++i) {
+                    labels[keys[i] - min] = newLabel();
+                }
+                mv.visitTableSwitchInsn(min, max, def, labels);
+                for (int i = 0; i < range; ++i) {
+                    Label label = labels[i];
+                    if (label != def) {
+                        mark(label);
+                        generator.generateCase(i + min, end);
+                    }
+                }
+            } else {
+                Label[] labels = new Label[len];
+                for (int i = 0; i < len; ++i) {
+                    labels[i] = newLabel();
+                }
+                mv.visitLookupSwitchInsn(def, keys, labels);
+                for (int i = 0; i < len; ++i) {
+                    mark(labels[i]);
+                    generator.generateCase(keys[i], end);
+                }
+            }
+        }
+        mark(def);
+        generator.generateDefault();
+        mark(end);
+    }
+
+    /**
+     * Generates the instruction to return the top stack value to the caller.
+     */
+    public void returnValue() {
+        mv.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to load and store fields
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates a get field or set field instruction.
+     * 
+     * @param opcode
+     *            the instruction's opcode.
+     * @param ownerType
+     *            the class in which the field is defined.
+     * @param name
+     *            the name of the field.
+     * @param fieldType
+     *            the type of the field.
+     */
+    private void fieldInsn(final int opcode, final Type ownerType,
+            final String name, final Type fieldType) {
+        mv.visitFieldInsn(opcode, ownerType.getInternalName(), name,
+                fieldType.getDescriptor());
+    }
+
+    /**
+     * Generates the instruction to push the value of a static field on the
+     * stack.
+     * 
+     * @param owner
+     *            the class in which the field is defined.
+     * @param name
+     *            the name of the field.
+     * @param type
+     *            the type of the field.
+     */
+    public void getStatic(final Type owner, final String name, final Type type) {
+        fieldInsn(Opcodes.GETSTATIC, owner, name, type);
+    }
+
+    /**
+     * Generates the instruction to store the top stack value in a static field.
+     * 
+     * @param owner
+     *            the class in which the field is defined.
+     * @param name
+     *            the name of the field.
+     * @param type
+     *            the type of the field.
+     */
+    public void putStatic(final Type owner, final String name, final Type type) {
+        fieldInsn(Opcodes.PUTSTATIC, owner, name, type);
+    }
+
+    /**
+     * Generates the instruction to push the value of a non static field on the
+     * stack.
+     * 
+     * @param owner
+     *            the class in which the field is defined.
+     * @param name
+     *            the name of the field.
+     * @param type
+     *            the type of the field.
+     */
+    public void getField(final Type owner, final String name, final Type type) {
+        fieldInsn(Opcodes.GETFIELD, owner, name, type);
+    }
+
+    /**
+     * Generates the instruction to store the top stack value in a non static
+     * field.
+     * 
+     * @param owner
+     *            the class in which the field is defined.
+     * @param name
+     *            the name of the field.
+     * @param type
+     *            the type of the field.
+     */
+    public void putField(final Type owner, final String name, final Type type) {
+        fieldInsn(Opcodes.PUTFIELD, owner, name, type);
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to invoke methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates an invoke method instruction.
+     * 
+     * @param opcode
+     *            the instruction's opcode.
+     * @param type
+     *            the class in which the method is defined.
+     * @param method
+     *            the method to be invoked.
+     */
+    private void invokeInsn(final int opcode, final Type type,
+            final Method method, final boolean itf) {
+        String owner = type.getSort() == Type.ARRAY ? type.getDescriptor()
+                : type.getInternalName();
+        mv.visitMethodInsn(opcode, owner, method.getName(),
+                method.getDescriptor(), itf);
+    }
+
+    /**
+     * Generates the instruction to invoke a normal method.
+     * 
+     * @param owner
+     *            the class in which the method is defined.
+     * @param method
+     *            the method to be invoked.
+     */
+    public void invokeVirtual(final Type owner, final Method method) {
+        invokeInsn(Opcodes.INVOKEVIRTUAL, owner, method, false);
+    }
+
+    /**
+     * Generates the instruction to invoke a constructor.
+     * 
+     * @param type
+     *            the class in which the constructor is defined.
+     * @param method
+     *            the constructor to be invoked.
+     */
+    public void invokeConstructor(final Type type, final Method method) {
+        invokeInsn(Opcodes.INVOKESPECIAL, type, method, false);
+    }
+
+    /**
+     * Generates the instruction to invoke a static method.
+     * 
+     * @param owner
+     *            the class in which the method is defined.
+     * @param method
+     *            the method to be invoked.
+     */
+    public void invokeStatic(final Type owner, final Method method) {
+        invokeInsn(Opcodes.INVOKESTATIC, owner, method, false);
+    }
+
+    /**
+     * Generates the instruction to invoke an interface method.
+     * 
+     * @param owner
+     *            the class in which the method is defined.
+     * @param method
+     *            the method to be invoked.
+     */
+    public void invokeInterface(final Type owner, final Method method) {
+        invokeInsn(Opcodes.INVOKEINTERFACE, owner, method, true);
+    }
+
+    /**
+     * Generates 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.
+     */
+    public void invokeDynamic(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to create objects and arrays
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates a type dependent instruction.
+     * 
+     * @param opcode
+     *            the instruction's opcode.
+     * @param type
+     *            the instruction's operand.
+     */
+    private void typeInsn(final int opcode, final Type type) {
+        mv.visitTypeInsn(opcode, type.getInternalName());
+    }
+
+    /**
+     * Generates the instruction to create a new object.
+     * 
+     * @param type
+     *            the class of the object to be created.
+     */
+    public void newInstance(final Type type) {
+        typeInsn(Opcodes.NEW, type);
+    }
+
+    /**
+     * Generates the instruction to create a new array.
+     * 
+     * @param type
+     *            the type of the array elements.
+     */
+    public void newArray(final Type type) {
+        int typ;
+        switch (type.getSort()) {
+        case Type.BOOLEAN:
+            typ = Opcodes.T_BOOLEAN;
+            break;
+        case Type.CHAR:
+            typ = Opcodes.T_CHAR;
+            break;
+        case Type.BYTE:
+            typ = Opcodes.T_BYTE;
+            break;
+        case Type.SHORT:
+            typ = Opcodes.T_SHORT;
+            break;
+        case Type.INT:
+            typ = Opcodes.T_INT;
+            break;
+        case Type.FLOAT:
+            typ = Opcodes.T_FLOAT;
+            break;
+        case Type.LONG:
+            typ = Opcodes.T_LONG;
+            break;
+        case Type.DOUBLE:
+            typ = Opcodes.T_DOUBLE;
+            break;
+        default:
+            typeInsn(Opcodes.ANEWARRAY, type);
+            return;
+        }
+        mv.visitIntInsn(Opcodes.NEWARRAY, typ);
+    }
+
+    // ------------------------------------------------------------------------
+    // Miscelaneous instructions
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates the instruction to compute the length of an array.
+     */
+    public void arrayLength() {
+        mv.visitInsn(Opcodes.ARRAYLENGTH);
+    }
+
+    /**
+     * Generates the instruction to throw an exception.
+     */
+    public void throwException() {
+        mv.visitInsn(Opcodes.ATHROW);
+    }
+
+    /**
+     * Generates the instructions to create and throw an exception. The
+     * exception class must have a constructor with a single String argument.
+     * 
+     * @param type
+     *            the class of the exception to be thrown.
+     * @param msg
+     *            the detailed message of the exception.
+     */
+    public void throwException(final Type type, final String msg) {
+        newInstance(type);
+        dup();
+        push(msg);
+        invokeConstructor(type, Method.getMethod("void <init> (String)"));
+        throwException();
+    }
+
+    /**
+     * Generates the instruction to check that the top stack value is of the
+     * given type.
+     * 
+     * @param type
+     *            a class or interface type.
+     */
+    public void checkCast(final Type type) {
+        if (!type.equals(OBJECT_TYPE)) {
+            typeInsn(Opcodes.CHECKCAST, type);
+        }
+    }
+
+    /**
+     * Generates the instruction to test if the top stack value is of the given
+     * type.
+     * 
+     * @param type
+     *            a class or interface type.
+     */
+    public void instanceOf(final Type type) {
+        typeInsn(Opcodes.INSTANCEOF, type);
+    }
+
+    /**
+     * Generates the instruction to get the monitor of the top stack value.
+     */
+    public void monitorEnter() {
+        mv.visitInsn(Opcodes.MONITORENTER);
+    }
+
+    /**
+     * Generates the instruction to release the monitor of the top stack value.
+     */
+    public void monitorExit() {
+        mv.visitInsn(Opcodes.MONITOREXIT);
+    }
+
+    // ------------------------------------------------------------------------
+    // Non instructions
+    // ------------------------------------------------------------------------
+
+    /**
+     * Marks the end of the visited method.
+     */
+    public void endMethod() {
+        if ((access & Opcodes.ACC_ABSTRACT) == 0) {
+            mv.visitMaxs(0, 0);
+        }
+        mv.visitEnd();
+    }
+
+    /**
+     * Marks the start of an exception handler.
+     * 
+     * @param start
+     *            beginning of the exception handler's scope (inclusive).
+     * @param end
+     *            end of the exception handler's scope (exclusive).
+     * @param exception
+     *            internal name of the type of exceptions handled by the
+     *            handler.
+     */
+    public void catchException(final Label start, final Label end,
+            final Type exception) {
+        if (exception == null) {
+            mv.visitTryCatchBlock(start, end, mark(), null);
+        } else {
+            mv.visitTryCatchBlock(start, end, mark(),
+                    exception.getInternalName());
+        }
+    }
+}


[21/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
index dced23c..8c8e29b 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
@@ -30,19 +30,20 @@
 package org.apache.tapestry5.internal.plastic.asm;
 
 /**
- * A visitor to visit a Java class. The methods of this class must be called
- * in the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
+ * A visitor to visit a Java class. The methods of this class must be called in
+ * the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
  * <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
- * <tt>visitAttribute</tt> )* ( <tt>visitInnerClass</tt> |
- * <tt>visitField</tt> | <tt>visitMethod</tt> )* <tt>visitEnd</tt>.
- *
+ * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (
+ * <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )*
+ * <tt>visitEnd</tt>.
+ * 
  * @author Eric Bruneton
  */
 public abstract class ClassVisitor {
 
     /**
      * The ASM API version implemented by this visitor. The value of this field
-     * must be one of {@link Opcodes#ASM4}.
+     * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
      */
     protected final int api;
 
@@ -54,9 +55,10 @@ public abstract class ClassVisitor {
 
     /**
      * Constructs a new {@link ClassVisitor}.
-     *
-     * @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 ClassVisitor(final int api) {
         this(api, null);
@@ -64,47 +66,49 @@ public abstract class ClassVisitor {
 
     /**
      * Constructs a new {@link ClassVisitor}.
-     *
-     * @param api the ASM API version implemented by this visitor. Must be one
-     *        of {@link Opcodes#ASM4}.
-     * @param cv the class visitor to which this visitor must delegate method
-     *        calls. May be null.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param cv
+     *            the class visitor to which this visitor must delegate method
+     *            calls. May be null.
      */
     public ClassVisitor(final int api, final ClassVisitor cv) {
-        /*if (api != Opcodes.ASM4) {
+        if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
             throw new IllegalArgumentException();
-        }*/
+        }
         this.api = api;
         this.cv = cv;
     }
 
     /**
      * Visits the header of the class.
-     *
-     * @param version the class version.
-     * @param access the class's access flags (see {@link Opcodes}). This
-     *        parameter also indicates if the class is deprecated.
-     * @param name the internal name of the class (see
-     *        {@link Type#getInternalName() getInternalName}).
-     * @param signature the signature of this class. May be <tt>null</tt> if
-     *        the class is not a generic one, and does not extend or implement
-     *        generic classes or interfaces.
-     * @param superName the internal of name of the super class (see
-     *        {@link Type#getInternalName() getInternalName}). For interfaces,
-     *        the super class is {@link Object}. May be <tt>null</tt>, but
-     *        only for the {@link Object} class.
-     * @param interfaces the internal names of the class's interfaces (see
-     *        {@link Type#getInternalName() getInternalName}). May be
-     *        <tt>null</tt>.
+     * 
+     * @param version
+     *            the class version.
+     * @param access
+     *            the class's access flags (see {@link Opcodes}). This parameter
+     *            also indicates if the class is deprecated.
+     * @param name
+     *            the internal name of the class (see
+     *            {@link Type#getInternalName() getInternalName}).
+     * @param signature
+     *            the signature of this class. May be <tt>null</tt> if the class
+     *            is not a generic one, and does not extend or implement generic
+     *            classes or interfaces.
+     * @param superName
+     *            the internal of name of the super class (see
+     *            {@link Type#getInternalName() getInternalName}). For
+     *            interfaces, the super class is {@link Object}. May be
+     *            <tt>null</tt>, but only for the {@link Object} class.
+     * @param interfaces
+     *            the internal names of the class's interfaces (see
+     *            {@link Type#getInternalName() getInternalName}). May be
+     *            <tt>null</tt>.
      */
-    public void visit(
-        int version,
-        int access,
-        String name,
-        String signature,
-        String superName,
-        String[] interfaces)
-    {
+    public void visit(int version, int access, String name, String signature,
+            String superName, String[] interfaces) {
         if (cv != null) {
             cv.visit(version, access, name, signature, superName, interfaces);
         }
@@ -112,12 +116,14 @@ public abstract class ClassVisitor {
 
     /**
      * Visits the source of the class.
-     *
-     * @param source the name of the source file from which the class was
-     *        compiled. May be <tt>null</tt>.
-     * @param debug additional debug information to compute the correspondance
-     *        between source and compiled elements of the class. May be
-     *        <tt>null</tt>.
+     * 
+     * @param source
+     *            the name of the source file from which the class was compiled.
+     *            May be <tt>null</tt>.
+     * @param debug
+     *            additional debug information to compute the correspondance
+     *            between source and compiled elements of the class. May be
+     *            <tt>null</tt>.
      */
     public void visitSource(String source, String debug) {
         if (cv != null) {
@@ -128,26 +134,31 @@ public abstract class ClassVisitor {
     /**
      * Visits the enclosing class of the class. This method must be called only
      * if the class has an enclosing class.
-     *
-     * @param owner internal name of the enclosing class of the class.
-     * @param name the name of the method that contains the class, or
-     *        <tt>null</tt> if the class is not enclosed in a method of its
-     *        enclosing class.
-     * @param desc the descriptor of the method that contains the class, or
-     *        <tt>null</tt> if the class is not enclosed in a method of its
-     *        enclosing class.
+     * 
+     * @param owner
+     *            internal name of the enclosing class of the class.
+     * @param name
+     *            the name of the method that contains the class, or
+     *            <tt>null</tt> if the class is not enclosed in a method of its
+     *            enclosing class.
+     * @param desc
+     *            the descriptor of the method that contains the class, or
+     *            <tt>null</tt> if the class is not enclosed in a method of its
+     *            enclosing class.
      */
     public void visitOuterClass(String owner, String name, String desc) {
-        if (cv != null)  {
+        if (cv != null) {
             cv.visitOuterClass(owner, name, desc);
         }
     }
 
     /**
      * Visits an annotation of the class.
-     *
-     * @param desc the class descriptor of the annotation class.
-     * @param visible <tt>true</tt> if the annotation is visible at runtime.
+     * 
+     * @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.
      */
@@ -159,9 +170,43 @@ public abstract class ClassVisitor {
     }
 
     /**
+     * Visits an annotation on a type in the class signature.
+     * 
+     * @param typeRef
+     *            a reference to the annotated type. The sort of this type
+     *            reference must be {@link TypeReference#CLASS_TYPE_PARAMETER
+     *            CLASS_TYPE_PARAMETER},
+     *            {@link TypeReference#CLASS_TYPE_PARAMETER_BOUND
+     *            CLASS_TYPE_PARAMETER_BOUND} or
+     *            {@link TypeReference#CLASS_EXTENDS CLASS_EXTENDS}. 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.
+     * @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.
+     */
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        if (api < Opcodes.ASM5) {
+            throw new RuntimeException();
+        }
+        if (cv != null) {
+            return cv.visitTypeAnnotation(typeRef, typePath, desc, visible);
+        }
+        return null;
+    }
+
+    /**
      * Visits a non standard attribute of the class.
-     *
-     * @param attr an attribute.
+     * 
+     * @param attr
+     *            an attribute.
      */
     public void visitAttribute(Attribute attr) {
         if (cv != null) {
@@ -172,24 +217,23 @@ public abstract class ClassVisitor {
     /**
      * Visits information about an inner class. This inner class is not
      * necessarily a member of the class being visited.
-     *
-     * @param name the internal name of an inner class (see
-     *        {@link Type#getInternalName() getInternalName}).
-     * @param outerName the internal name of the class to which the inner class
-     *        belongs (see {@link Type#getInternalName() getInternalName}). May
-     *        be <tt>null</tt> for not member classes.
-     * @param innerName the (simple) name of the inner class inside its
-     *        enclosing class. May be <tt>null</tt> for anonymous inner
-     *        classes.
-     * @param access the access flags of the inner class as originally declared
-     *        in the enclosing class.
+     * 
+     * @param name
+     *            the internal name of an inner class (see
+     *            {@link Type#getInternalName() getInternalName}).
+     * @param outerName
+     *            the internal name of the class to which the inner class
+     *            belongs (see {@link Type#getInternalName() getInternalName}).
+     *            May be <tt>null</tt> for not member classes.
+     * @param innerName
+     *            the (simple) name of the inner class inside its enclosing
+     *            class. May be <tt>null</tt> for anonymous inner classes.
+     * @param access
+     *            the access flags of the inner class as originally declared in
+     *            the enclosing class.
      */
-    public void visitInnerClass(
-        String name,
-        String outerName,
-        String innerName,
-        int access)
-    {
+    public void visitInnerClass(String name, String outerName,
+            String innerName, int access) {
         if (cv != null) {
             cv.visitInnerClass(name, outerName, innerName, access);
         }
@@ -197,34 +241,33 @@ public abstract class ClassVisitor {
 
     /**
      * Visits a field of the class.
-     *
-     * @param access the field's access flags (see {@link Opcodes}). This
-     *        parameter also indicates if the field is synthetic and/or
-     *        deprecated.
-     * @param name the field's name.
-     * @param desc the field's descriptor (see {@link Type Type}).
-     * @param signature the field's signature. May be <tt>null</tt> if the
-     *        field's type does not use generic types.
-     * @param value the field's initial value. This parameter, which may be
-     *        <tt>null</tt> if the field does not have an initial value, must
-     *        be an {@link Integer}, a {@link Float}, a {@link Long}, a
-     *        {@link Double} or a {@link String} (for <tt>int</tt>,
-     *        <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields
-     *        respectively). <i>This parameter is only used for static fields</i>.
-     *        Its value is ignored for non static fields, which must be
-     *        initialized through bytecode instructions in constructors or
-     *        methods.
+     * 
+     * @param access
+     *            the field's access flags (see {@link Opcodes}). This parameter
+     *            also indicates if the field is synthetic and/or deprecated.
+     * @param name
+     *            the field's name.
+     * @param desc
+     *            the field's descriptor (see {@link Type Type}).
+     * @param signature
+     *            the field's signature. May be <tt>null</tt> if the field's
+     *            type does not use generic types.
+     * @param value
+     *            the field's initial value. This parameter, which may be
+     *            <tt>null</tt> if the field does not have an initial value,
+     *            must be an {@link Integer}, a {@link Float}, a {@link Long}, a
+     *            {@link Double} or a {@link String} (for <tt>int</tt>,
+     *            <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields
+     *            respectively). <i>This parameter is only used for static
+     *            fields</i>. Its value is ignored for non static fields, which
+     *            must be initialized through bytecode instructions in
+     *            constructors or methods.
      * @return a visitor to visit field annotations and attributes, or
-     *         <tt>null</tt> if this class visitor is not interested in
-     *         visiting these annotations and attributes.
+     *         <tt>null</tt> if this class visitor is not interested in visiting
+     *         these annotations and attributes.
      */
-    public FieldVisitor visitField(
-        int access,
-        String name,
-        String desc,
-        String signature,
-        Object value)
-    {
+    public FieldVisitor visitField(int access, String name, String desc,
+            String signature, Object value) {
         if (cv != null) {
             return cv.visitField(access, name, desc, signature, value);
         }
@@ -233,31 +276,31 @@ public abstract class ClassVisitor {
 
     /**
      * Visits a method of the class. This method <i>must</i> return a new
-     * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is
-     * called, i.e., it should not return a previously returned visitor.
-     *
-     * @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 Type}).
-     * @param signature the method's signature. May be <tt>null</tt> if the
-     *        method parameters, return type and exceptions do not use generic
-     *        types.
-     * @param exceptions the internal names of the method's exception classes
-     *        (see {@link Type#getInternalName() getInternalName}). May be
-     *        <tt>null</tt>.
+     * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is called,
+     * i.e., it should not return a previously returned visitor.
+     * 
+     * @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 Type}).
+     * @param signature
+     *            the method's signature. May be <tt>null</tt> if the method
+     *            parameters, return type and exceptions do not use generic
+     *            types.
+     * @param exceptions
+     *            the internal names of the method's exception classes (see
+     *            {@link Type#getInternalName() getInternalName}). May be
+     *            <tt>null</tt>.
      * @return an object to visit the byte code of the method, or <tt>null</tt>
      *         if this class visitor is not interested in visiting the code of
      *         this method.
      */
-    public MethodVisitor visitMethod(
-        int access,
-        String name,
-        String desc,
-        String signature,
-        String[] exceptions)
-    {
+    public MethodVisitor visitMethod(int access, String name, String desc,
+            String signature, String[] exceptions) {
         if (cv != null) {
             return cv.visitMethod(access, name, desc, signature, exceptions);
         }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
index ab7547b..6cd89a5 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
@@ -35,7 +35,7 @@ package org.apache.tapestry5.internal.plastic.asm;
  * file format. It can be used alone, to generate a Java class "from scratch",
  * or with one or more {@link ClassReader ClassReader} and adapter class visitor
  * to generate a modified class from one or more existing Java classes.
- *
+ * 
  * @author Eric Bruneton
  */
 public class ClassWriter extends ClassVisitor {
@@ -47,7 +47,7 @@ public class ClassWriter extends ClassVisitor {
      * {@link MethodVisitor} returned by the {@link #visitMethod visitMethod}
      * method will be ignored, and computed automatically from the signature and
      * the bytecode of each method.
-     *
+     * 
      * @see #ClassWriter(int)
      */
     public static final int COMPUTE_MAXS = 1;
@@ -60,18 +60,24 @@ public class ClassWriter extends ClassVisitor {
      * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
      * recomputed from the bytecode. In other words, computeFrames implies
      * computeMaxs.
-     *
+     * 
      * @see #ClassWriter(int)
      */
     public static final int COMPUTE_FRAMES = 2;
 
     /**
-     * Pseudo access flag to distinguish between the synthetic attribute and
-     * the synthetic access flag.
+     * Pseudo access flag to distinguish between the synthetic attribute and the
+     * synthetic access flag.
      */
     static final int ACC_SYNTHETIC_ATTRIBUTE = 0x40000;
 
     /**
+     * Factor to convert from ACC_SYNTHETIC_ATTRIBUTE to Opcode.ACC_SYNTHETIC.
+     */
+    static final int TO_ACC_SYNTHETIC = ACC_SYNTHETIC_ATTRIBUTE
+            / Opcodes.ACC_SYNTHETIC;
+
+    /**
      * The type of instructions without any argument.
      */
     static final int NOARG_INSN = 0;
@@ -238,8 +244,8 @@ public class ClassWriter extends ClassVisitor {
 
     /**
      * The base value for all CONSTANT_MethodHandle constant pool items.
-     * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into
-     * 9 different items.
+     * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9
+     * different items.
      */
     static final int HANDLE_BASE = 20;
 
@@ -266,9 +272,8 @@ public class ClassWriter extends ClassVisitor {
     static final int TYPE_MERGED = 32;
 
     /**
-     * The type of BootstrapMethods items. These items are stored in a
-     * special class attribute named BootstrapMethods and
-     * not in the constant pool.
+     * The type of BootstrapMethods items. These items are stored in a special
+     * class attribute named BootstrapMethods and not in the constant pool.
      */
     static final int BSM = 33;
 
@@ -327,10 +332,10 @@ public class ClassWriter extends ClassVisitor {
      * necessarily be stored in the constant pool. This type table is used by
      * the control flow and data flow analysis algorithm used to compute stack
      * map frames from scratch. This array associates to each index <tt>i</tt>
-     * the Item whose index is <tt>i</tt>. All Item objects stored in this
-     * array are also stored in the {@link #items} hash table. These two arrays
-     * allow to retrieve an Item from its index or, conversely, to get the index
-     * of an Item from its value. Each Item stores an internal name in its
+     * the Item whose index is <tt>i</tt>. All Item objects stored in this array
+     * are also stored in the {@link #items} hash table. These two arrays allow
+     * to retrieve an Item from its index or, conversely, to get the index of an
+     * Item from its value. Each Item stores an internal name in its
      * {@link Item#strVal1} field.
      */
     Item[] typeTable;
@@ -412,6 +417,16 @@ public class ClassWriter extends ClassVisitor {
     private AnnotationWriter ianns;
 
     /**
+     * The runtime visible type annotations of this class.
+     */
+    private AnnotationWriter tanns;
+
+    /**
+     * The runtime invisible type annotations of this class.
+     */
+    private AnnotationWriter itanns;
+
+    /**
      * The non standard attributes of this class.
      */
     private Attribute attrs;
@@ -439,16 +454,16 @@ public class ClassWriter extends ClassVisitor {
     /**
      * The fields of this class. These fields are stored in a linked list of
      * {@link FieldWriter} objects, linked to each other by their
-     * {@link FieldWriter#fv} field. This field stores the first element of
-     * this list.
+     * {@link FieldWriter#fv} field. This field stores the first element of this
+     * list.
      */
     FieldWriter firstField;
 
     /**
      * The fields of this class. These fields are stored in a linked list of
      * {@link FieldWriter} objects, linked to each other by their
-     * {@link FieldWriter#fv} field. This field stores the last element of
-     * this list.
+     * {@link FieldWriter#fv} field. This field stores the last element of this
+     * list.
      */
     FieldWriter lastField;
 
@@ -463,8 +478,8 @@ public class ClassWriter extends ClassVisitor {
     /**
      * The methods of this class. These methods are stored in a linked list of
      * {@link MethodWriter} objects, linked to each other by their
-     * {@link MethodWriter#mv} field. This field stores the last element of
-     * this list.
+     * {@link MethodWriter#mv} field. This field stores the last element of this
+     * list.
      */
     MethodWriter lastMethod;
 
@@ -472,12 +487,12 @@ public class ClassWriter extends ClassVisitor {
      * <tt>true</tt> if the maximum stack size and number of local variables
      * must be automatically computed.
      */
-    private final boolean computeMaxs;
+    private boolean computeMaxs;
 
     /**
      * <tt>true</tt> if the stack map frames must be recomputed from scratch.
      */
-    private final boolean computeFrames;
+    private boolean computeFrames;
 
     /**
      * <tt>true</tt> if the stack map tables of this class are invalid. The
@@ -583,12 +598,14 @@ public class ClassWriter extends ClassVisitor {
 
     /**
      * Constructs a new {@link ClassWriter} object.
-     *
-     * @param flags option flags that can be used to modify the default behavior
-     *        of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
+     * 
+     * @param flags
+     *            option flags that can be used to modify the default behavior
+     *            of this class. See {@link #COMPUTE_MAXS},
+     *            {@link #COMPUTE_FRAMES}.
      */
     public ClassWriter(final int flags) {
-        super(Opcodes.ASM4);
+        super(Opcodes.ASM5);
         index = 1;
         pool = new ByteVector();
         items = new Item[256];
@@ -605,27 +622,33 @@ public class ClassWriter extends ClassVisitor {
      * Constructs a new {@link ClassWriter} object and enables optimizations for
      * "mostly add" bytecode transformations. These optimizations are the
      * following:
-     *
-     * <ul> <li>The constant pool from the original class is copied as is in the
-     * new class, which saves time. New constant pool entries will be added at
-     * the end if necessary, but unused constant pool entries <i>won't be
-     * removed</i>.</li> <li>Methods that are not transformed are copied as is
-     * in the new class, directly from the original class bytecode (i.e. without
-     * emitting visit events for all the method instructions), which saves a
-     * <i>lot</i> of time. Untransformed methods are detected by the fact that
-     * the {@link ClassReader} receives {@link MethodVisitor} objects that come
-     * from a {@link ClassWriter} (and not from any other {@link ClassVisitor}
-     * instance).</li> </ul>
-     *
-     * @param classReader the {@link ClassReader} used to read the original
-     *        class. It will be used to copy the entire constant pool from the
-     *        original class and also to copy other fragments of original
-     *        bytecode where applicable.
-     * @param flags option flags that can be used to modify the default behavior
-     *        of this class. <i>These option flags do not affect methods that
-     *        are copied as is in the new class. This means that the maximum
-     *        stack size nor the stack frames will be computed for these
-     *        methods</i>. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
+     * 
+     * <ul>
+     * <li>The constant pool from the original class is copied as is in the new
+     * class, which saves time. New constant pool entries will be added at the
+     * end if necessary, but unused constant pool entries <i>won't be
+     * removed</i>.</li>
+     * <li>Methods that are not transformed are copied as is in the new class,
+     * directly from the original class bytecode (i.e. without emitting visit
+     * events for all the method instructions), which saves a <i>lot</i> of
+     * time. Untransformed methods are detected by the fact that the
+     * {@link ClassReader} receives {@link MethodVisitor} objects that come from
+     * a {@link ClassWriter} (and not from any other {@link ClassVisitor}
+     * instance).</li>
+     * </ul>
+     * 
+     * @param classReader
+     *            the {@link ClassReader} used to read the original class. It
+     *            will be used to copy the entire constant pool from the
+     *            original class and also to copy other fragments of original
+     *            bytecode where applicable.
+     * @param flags
+     *            option flags that can be used to modify the default behavior
+     *            of this class. <i>These option flags do not affect methods
+     *            that are copied as is in the new class. This means that the
+     *            maximum stack size nor the stack frames will be computed for
+     *            these methods</i>. See {@link #COMPUTE_MAXS},
+     *            {@link #COMPUTE_FRAMES}.
      */
     public ClassWriter(final ClassReader classReader, final int flags) {
         this(flags);
@@ -638,14 +661,9 @@ public class ClassWriter extends ClassVisitor {
     // ------------------------------------------------------------------------
 
     @Override
-    public final void visit(
-        final int version,
-        final int access,
-        final String name,
-        final String signature,
-        final String superName,
-        final String[] interfaces)
-    {
+    public final void visit(final int version, final int access,
+            final String name, final String signature, final String superName,
+            final String[] interfaces) {
         this.version = version;
         this.access = access;
         this.name = newClass(name);
@@ -669,16 +687,14 @@ public class ClassWriter extends ClassVisitor {
             sourceFile = newUTF8(file);
         }
         if (debug != null) {
-            sourceDebug = new ByteVector().putUTF8(debug);
+            sourceDebug = new ByteVector().encodeUTF8(debug, 0,
+                    Integer.MAX_VALUE);
         }
     }
 
     @Override
-    public final void visitOuterClass(
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    public final void visitOuterClass(final String owner, final String name,
+            final String desc) {
         enclosingMethodOwner = newClass(owner);
         if (name != null && desc != null) {
             enclosingMethod = newNameType(name, desc);
@@ -686,10 +702,8 @@ public class ClassWriter extends ClassVisitor {
     }
 
     @Override
-    public final AnnotationVisitor visitAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public final AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
         if (!ClassReader.ANNOTATIONS) {
             return null;
         }
@@ -708,55 +722,76 @@ public class ClassWriter extends ClassVisitor {
     }
 
     @Override
+    public final AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, final String desc, final boolean visible) {
+        if (!ClassReader.ANNOTATIONS) {
+            return null;
+        }
+        ByteVector bv = new ByteVector();
+        // write target_type and target_info
+        AnnotationWriter.putTarget(typeRef, typePath, bv);
+        // write type, and reserve space for values count
+        bv.putShort(newUTF8(desc)).putShort(0);
+        AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv,
+                bv.length - 2);
+        if (visible) {
+            aw.next = tanns;
+            tanns = aw;
+        } else {
+            aw.next = itanns;
+            itanns = aw;
+        }
+        return aw;
+    }
+
+    @Override
     public final void visitAttribute(final Attribute attr) {
         attr.next = attrs;
         attrs = attr;
     }
 
     @Override
-    public final void visitInnerClass(
-        final String name,
-        final String outerName,
-        final String innerName,
-        final int access)
-    {
+    public final void visitInnerClass(final String name,
+            final String outerName, final String innerName, final int access) {
         if (innerClasses == null) {
             innerClasses = new ByteVector();
         }
-        ++innerClassesCount;
-        innerClasses.putShort(name == null ? 0 : newClass(name));
-        innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
-        innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
-        innerClasses.putShort(access);
+        // �4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the
+        // constant_pool table which represents a class or interface C that is
+        // not a package member must have exactly one corresponding entry in the
+        // classes array". To avoid duplicates we keep track in the intVal field
+        // of the Item of each CONSTANT_Class_info entry C whether an inner
+        // class entry has already been added for C (this field is unused for
+        // class entries, and changing its value does not change the hashcode
+        // and equality tests). If so we store the index of this inner class
+        // entry (plus one) in intVal. This hack allows duplicate detection in
+        // O(1) time.
+        Item nameItem = newClassItem(name);
+        if (nameItem.intVal == 0) {
+            ++innerClassesCount;
+            innerClasses.putShort(nameItem.index);
+            innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
+            innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
+            innerClasses.putShort(access);
+            nameItem.intVal = innerClassesCount;
+        } else {
+            // Compare the inner classes entry nameItem.intVal - 1 with the
+            // arguments of this method and throw an exception if there is a
+            // difference?
+        }
     }
 
     @Override
-    public final FieldVisitor visitField(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final Object value)
-    {
+    public final FieldVisitor visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
         return new FieldWriter(this, access, name, desc, signature, value);
     }
 
     @Override
-    public final MethodVisitor visitMethod(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final String[] exceptions)
-    {
-        return new MethodWriter(this,
-                access,
-                name,
-                desc,
-                signature,
-                exceptions,
-                computeMaxs,
-                computeFrames);
+    public final MethodVisitor visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        return new MethodWriter(this, access, name, desc, signature,
+                exceptions, computeMaxs, computeFrames);
     }
 
     @Override
@@ -769,11 +804,11 @@ public class ClassWriter extends ClassVisitor {
 
     /**
      * Returns the bytecode of the class that was build with this class writer.
-     *
+     * 
      * @return the bytecode of the class that was build with this class writer.
      */
     public byte[] toByteArray() {
-        if (index > Short.MAX_VALUE) {
+        if (index > 0xFFFF) {
             throw new RuntimeException("Class file too large!");
         }
         // computes the real size of the bytecode of this class
@@ -793,8 +828,9 @@ public class ClassWriter extends ClassVisitor {
             mb = (MethodWriter) mb.mv;
         }
         int attributeCount = 0;
-        if (bootstrapMethods != null) {  // we put it as first argument in order
-                                         // to improve a bit ClassReader.copyBootstrapMethods
+        if (bootstrapMethods != null) {
+            // we put it as first attribute in order to improve a bit
+            // ClassReader.copyBootstrapMethods
             ++attributeCount;
             size += 8 + bootstrapMethods.length;
             newUTF8("BootstrapMethods");
@@ -811,7 +847,7 @@ public class ClassWriter extends ClassVisitor {
         }
         if (sourceDebug != null) {
             ++attributeCount;
-            size += sourceDebug.length + 4;
+            size += sourceDebug.length + 6;
             newUTF8("SourceDebugExtension");
         }
         if (enclosingMethodOwner != 0) {
@@ -824,12 +860,13 @@ public class ClassWriter extends ClassVisitor {
             size += 6;
             newUTF8("Deprecated");
         }
-        if ((access & Opcodes.ACC_SYNTHETIC) != 0
-                && ((version & 0xFFFF) < Opcodes.V1_5 || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0))
-        {
-            ++attributeCount;
-            size += 6;
-            newUTF8("Synthetic");
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            if ((version & 0xFFFF) < Opcodes.V1_5
+                    || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+                ++attributeCount;
+                size += 6;
+                newUTF8("Synthetic");
+            }
         }
         if (innerClasses != null) {
             ++attributeCount;
@@ -846,6 +883,16 @@ public class ClassWriter extends ClassVisitor {
             size += 8 + ianns.getSize();
             newUTF8("RuntimeInvisibleAnnotations");
         }
+        if (ClassReader.ANNOTATIONS && tanns != null) {
+            ++attributeCount;
+            size += 8 + tanns.getSize();
+            newUTF8("RuntimeVisibleTypeAnnotations");
+        }
+        if (ClassReader.ANNOTATIONS && itanns != null) {
+            ++attributeCount;
+            size += 8 + itanns.getSize();
+            newUTF8("RuntimeInvisibleTypeAnnotations");
+        }
         if (attrs != null) {
             attributeCount += attrs.getCount();
             size += attrs.getSize(this, null, 0, -1, -1);
@@ -856,9 +903,8 @@ public class ClassWriter extends ClassVisitor {
         ByteVector out = new ByteVector(size);
         out.putInt(0xCAFEBABE).putInt(version);
         out.putShort(index).putByteArray(pool.data, 0, pool.length);
-        int mask = Opcodes.ACC_DEPRECATED
-                | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
-                | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC));
+        int mask = Opcodes.ACC_DEPRECATED | ACC_SYNTHETIC_ATTRIBUTE
+                | ((access & ACC_SYNTHETIC_ATTRIBUTE) / TO_ACC_SYNTHETIC);
         out.putShort(access & ~mask).putShort(name).putShort(superName);
         out.putShort(interfaceCount);
         for (int i = 0; i < interfaceCount; ++i) {
@@ -877,9 +923,10 @@ public class ClassWriter extends ClassVisitor {
             mb = (MethodWriter) mb.mv;
         }
         out.putShort(attributeCount);
-        if (bootstrapMethods != null) {   // should be the first class attribute ?
+        if (bootstrapMethods != null) {
             out.putShort(newUTF8("BootstrapMethods"));
-            out.putInt(bootstrapMethods.length + 2).putShort(bootstrapMethodsCount);
+            out.putInt(bootstrapMethods.length + 2).putShort(
+                    bootstrapMethodsCount);
             out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length);
         }
         if (ClassReader.SIGNATURES && signature != 0) {
@@ -889,9 +936,9 @@ public class ClassWriter extends ClassVisitor {
             out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);
         }
         if (sourceDebug != null) {
-            int len = sourceDebug.length - 2;
+            int len = sourceDebug.length;
             out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
-            out.putByteArray(sourceDebug.data, 2, len);
+            out.putByteArray(sourceDebug.data, 0, len);
         }
         if (enclosingMethodOwner != 0) {
             out.putShort(newUTF8("EnclosingMethod")).putInt(4);
@@ -900,10 +947,11 @@ public class ClassWriter extends ClassVisitor {
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             out.putShort(newUTF8("Deprecated")).putInt(0);
         }
-        if ((access & Opcodes.ACC_SYNTHETIC) != 0
-                && ((version & 0xFFFF) < Opcodes.V1_5 || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0))
-        {
-            out.putShort(newUTF8("Synthetic")).putInt(0);
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            if ((version & 0xFFFF) < Opcodes.V1_5
+                    || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+                out.putShort(newUTF8("Synthetic")).putInt(0);
+            }
         }
         if (innerClasses != null) {
             out.putShort(newUTF8("InnerClasses"));
@@ -918,13 +966,34 @@ public class ClassWriter extends ClassVisitor {
             out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
             ianns.put(out);
         }
+        if (ClassReader.ANNOTATIONS && tanns != null) {
+            out.putShort(newUTF8("RuntimeVisibleTypeAnnotations"));
+            tanns.put(out);
+        }
+        if (ClassReader.ANNOTATIONS && itanns != null) {
+            out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations"));
+            itanns.put(out);
+        }
         if (attrs != null) {
             attrs.put(this, null, 0, -1, -1, out);
         }
         if (invalidFrames) {
-            ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
-            new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES);
-            return cw.toByteArray();
+            anns = null;
+            ianns = null;
+            attrs = null;
+            innerClassesCount = 0;
+            innerClasses = null;
+            bootstrapMethodsCount = 0;
+            bootstrapMethods = null;
+            firstField = null;
+            lastField = null;
+            firstMethod = null;
+            lastMethod = null;
+            computeMaxs = false;
+            computeFrames = true;
+            invalidFrames = false;
+            new ClassReader(out.data).accept(this, ClassReader.SKIP_FRAMES);
+            return toByteArray();
         }
         return out.data;
     }
@@ -936,11 +1005,12 @@ public class ClassWriter extends ClassVisitor {
     /**
      * Adds a number or string constant to the constant pool of the class being
      * build. Does nothing if the constant pool already contains a similar item.
-     *
-     * @param cst the value of the constant to be added to the constant pool.
-     *        This parameter must be an {@link Integer}, a {@link Float}, a
-     *        {@link Long}, a {@link Double}, a {@link String} or a
-     *        {@link Type}.
+     * 
+     * @param cst
+     *            the value of the constant to be added to the constant pool.
+     *            This parameter must be an {@link Integer}, a {@link Float}, a
+     *            {@link Long}, a {@link Double}, a {@link String} or a
+     *            {@link Type}.
      * @return a new or already existing constant item with the given value.
      */
     Item newConstItem(final Object cst) {
@@ -973,12 +1043,12 @@ public class ClassWriter extends ClassVisitor {
         } else if (cst instanceof Type) {
             Type t = (Type) cst;
             int s = t.getSort();
-            if (s == Type.ARRAY) {
-                return newClassItem(t.getDescriptor());
-            } else if (s == Type.OBJECT) {
+            if (s == Type.OBJECT) {
                 return newClassItem(t.getInternalName());
-            } else { // s == Type.METHOD
+            } else if (s == Type.METHOD) {
                 return newMethodTypeItem(t.getDescriptor());
+            } else { // s == primitive type or array
+                return newClassItem(t.getDescriptor());
             }
         } else if (cst instanceof Handle) {
             Handle h = (Handle) cst;
@@ -993,10 +1063,11 @@ public class ClassWriter extends ClassVisitor {
      * build. Does nothing if the constant pool already contains a similar item.
      * <i>This method is intended for {@link Attribute} sub classes, and is
      * normally not needed by class generators or adapters.</i>
-     *
-     * @param cst the value of the constant to be added to the constant pool.
-     *        This parameter must be an {@link Integer}, a {@link Float}, a
-     *        {@link Long}, a {@link Double} or a {@link String}.
+     * 
+     * @param cst
+     *            the value of the constant to be added to the constant pool.
+     *            This parameter must be an {@link Integer}, a {@link Float}, a
+     *            {@link Long}, a {@link Double} or a {@link String}.
      * @return the index of a new or already existing constant item with the
      *         given value.
      */
@@ -1009,8 +1080,9 @@ public class ClassWriter extends ClassVisitor {
      * nothing if the constant pool already contains a similar item. <i>This
      * method is intended for {@link Attribute} sub classes, and is normally not
      * needed by class generators or adapters.</i>
-     *
-     * @param value the String value.
+     * 
+     * @param value
+     *            the String value.
      * @return the index of a new or already existing UTF8 item.
      */
     public int newUTF8(final String value) {
@@ -1029,8 +1101,9 @@ public class ClassWriter extends ClassVisitor {
      * Does nothing if the constant pool already contains a similar item.
      * <i>This method is intended for {@link Attribute} sub classes, and is
      * normally not needed by class generators or adapters.</i>
-     *
-     * @param value the internal name of the class.
+     * 
+     * @param value
+     *            the internal name of the class.
      * @return a new or already existing class reference item.
      */
     Item newClassItem(final String value) {
@@ -1049,8 +1122,9 @@ public class ClassWriter extends ClassVisitor {
      * Does nothing if the constant pool already contains a similar item.
      * <i>This method is intended for {@link Attribute} sub classes, and is
      * normally not needed by class generators or adapters.</i>
-     *
-     * @param value the internal name of the class.
+     * 
+     * @param value
+     *            the internal name of the class.
      * @return the index of a new or already existing class reference item.
      */
     public int newClass(final String value) {
@@ -1062,8 +1136,9 @@ public class ClassWriter extends ClassVisitor {
      * build. Does nothing if the constant pool already contains a similar item.
      * <i>This method is intended for {@link Attribute} sub classes, and is
      * normally not needed by class generators or adapters.</i>
-     *
-     * @param methodDesc method descriptor of the method type.
+     * 
+     * @param methodDesc
+     *            method descriptor of the method type.
      * @return a new or already existing method type reference item.
      */
     Item newMethodTypeItem(final String methodDesc) {
@@ -1082,8 +1157,9 @@ public class ClassWriter extends ClassVisitor {
      * build. Does nothing if the constant pool already contains a similar item.
      * <i>This method is intended for {@link Attribute} sub classes, and is
      * normally not needed by class generators or adapters.</i>
-     *
-     * @param methodDesc method descriptor of the method type.
+     * 
+     * @param methodDesc
+     *            method descriptor of the method type.
      * @return the index of a new or already existing method type reference
      *         item.
      */
@@ -1096,34 +1172,35 @@ public class ClassWriter extends ClassVisitor {
      * if the constant pool already contains a similar item. <i>This method is
      * intended for {@link Attribute} sub classes, and is normally not needed by
      * class generators or adapters.</i>
-     *
-     * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
-     *        {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
-     *        {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
-     *        {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
-     *        {@link Opcodes#H_NEWINVOKESPECIAL} or
-     *        {@link Opcodes#H_INVOKEINTERFACE}.
-     * @param owner the internal name of the field or method owner class.
-     * @param name the name of the field or method.
-     * @param desc the descriptor of the field or method.
+     * 
+     * @param tag
+     *            the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
+     *            {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
+     *            {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
+     *            {@link Opcodes#H_INVOKESTATIC},
+     *            {@link Opcodes#H_INVOKESPECIAL},
+     *            {@link Opcodes#H_NEWINVOKESPECIAL} or
+     *            {@link Opcodes#H_INVOKEINTERFACE}.
+     * @param owner
+     *            the internal name of the field or method owner class.
+     * @param name
+     *            the name of the field or method.
+     * @param desc
+     *            the descriptor of the field or method.
      * @return a new or an already existing method type reference item.
      */
-    Item newHandleItem(
-        final int tag,
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    Item newHandleItem(final int tag, final String owner, final String name,
+            final String desc) {
         key4.set(HANDLE_BASE + tag, owner, name, desc);
         Item result = get(key4);
         if (result == null) {
             if (tag <= Opcodes.H_PUTSTATIC) {
                 put112(HANDLE, tag, newField(owner, name, desc));
             } else {
-                put112(HANDLE, tag, newMethod(owner,
-                        name,
-                        desc,
-                        tag == Opcodes.H_INVOKEINTERFACE));
+                put112(HANDLE,
+                        tag,
+                        newMethod(owner, name, desc,
+                                tag == Opcodes.H_INVOKEINTERFACE));
             }
             result = new Item(index++, key4);
             put(result);
@@ -1132,29 +1209,30 @@ public class ClassWriter extends ClassVisitor {
     }
 
     /**
-     * Adds a handle to the constant pool of the class being
-     * build. Does nothing if the constant pool already contains a similar item.
-     * <i>This method is intended for {@link Attribute} sub classes, and is
-     * normally not needed by class generators or adapters.</i>
-     *
-     * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
-     *        {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
-     *        {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
-     *        {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
-     *        {@link Opcodes#H_NEWINVOKESPECIAL} or
-     *        {@link Opcodes#H_INVOKEINTERFACE}.
-     * @param owner the internal name of the field or method owner class.
-     * @param name the name of the field or method.
-     * @param desc the descriptor of the field or method.
+     * Adds a handle to the constant pool of the class being build. Does nothing
+     * if the constant pool already contains a similar item. <i>This method is
+     * intended for {@link Attribute} sub classes, and is normally not needed by
+     * class generators or adapters.</i>
+     * 
+     * @param tag
+     *            the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
+     *            {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
+     *            {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
+     *            {@link Opcodes#H_INVOKESTATIC},
+     *            {@link Opcodes#H_INVOKESPECIAL},
+     *            {@link Opcodes#H_NEWINVOKESPECIAL} or
+     *            {@link Opcodes#H_INVOKEINTERFACE}.
+     * @param owner
+     *            the internal name of the field or method owner class.
+     * @param name
+     *            the name of the field or method.
+     * @param desc
+     *            the descriptor of the field or method.
      * @return the index of a new or already existing method type reference
      *         item.
      */
-    public int newHandle(
-        final int tag,
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    public int newHandle(final int tag, final String owner, final String name,
+            final String desc) {
         return newHandleItem(tag, owner, name, desc).index;
     }
 
@@ -1163,20 +1241,20 @@ public class ClassWriter extends ClassVisitor {
      * build. Does nothing if the constant pool already contains a similar item.
      * <i>This method is intended for {@link Attribute} sub classes, and is
      * normally not needed by class generators or adapters.</i>
-     *
-     * @param name name of the invoked method.
-     * @param desc descriptor of the invoke method.
-     * @param bsm the bootstrap method.
-     * @param bsmArgs the bootstrap method constant arguments.
-     *
+     * 
+     * @param name
+     *            name of the invoked method.
+     * @param desc
+     *            descriptor of the invoke method.
+     * @param bsm
+     *            the bootstrap method.
+     * @param bsmArgs
+     *            the bootstrap method constant arguments.
+     * 
      * @return a new or an already existing invokedynamic type reference item.
      */
-    Item newInvokeDynamicItem(
-        final String name,
-        final String desc,
-        final Handle bsm,
-        final Object... bsmArgs)
-    {
+    Item newInvokeDynamicItem(final String name, final String desc,
+            final Handle bsm, final Object... bsmArgs) {
         // cache for performance
         ByteVector bootstrapMethods = this.bootstrapMethods;
         if (bootstrapMethods == null) {
@@ -1186,9 +1264,7 @@ public class ClassWriter extends ClassVisitor {
         int position = bootstrapMethods.length; // record current position
 
         int hashCode = bsm.hashCode();
-        bootstrapMethods.putShort(newHandle(bsm.tag,
-                bsm.owner,
-                bsm.name,
+        bootstrapMethods.putShort(newHandle(bsm.tag, bsm.owner, bsm.name,
                 bsm.desc));
 
         int argsLength = bsmArgs.length;
@@ -1249,35 +1325,37 @@ public class ClassWriter extends ClassVisitor {
      * build. Does nothing if the constant pool already contains a similar item.
      * <i>This method is intended for {@link Attribute} sub classes, and is
      * normally not needed by class generators or adapters.</i>
-     *
-     * @param name name of the invoked method.
-     * @param desc descriptor of the invoke method.
-     * @param bsm the bootstrap method.
-     * @param bsmArgs the bootstrap method constant arguments.
-     *
-     * @return the index of a new or already existing invokedynamic
-     *         reference item.
-     */
-    public int newInvokeDynamic(
-        final String name,
-        final String desc,
-        final Handle bsm,
-        final Object... bsmArgs)
-    {
+     * 
+     * @param name
+     *            name of the invoked method.
+     * @param desc
+     *            descriptor of the invoke method.
+     * @param bsm
+     *            the bootstrap method.
+     * @param bsmArgs
+     *            the bootstrap method constant arguments.
+     * 
+     * @return the index of a new or already existing invokedynamic reference
+     *         item.
+     */
+    public int newInvokeDynamic(final String name, final String desc,
+            final Handle bsm, final Object... bsmArgs) {
         return newInvokeDynamicItem(name, desc, bsm, bsmArgs).index;
     }
 
     /**
      * Adds a field reference to the constant pool of the class being build.
      * Does nothing if the constant pool already contains a similar item.
-     *
-     * @param owner the internal name of the field's owner class.
-     * @param name the field's name.
-     * @param desc the field's descriptor.
+     * 
+     * @param owner
+     *            the internal name of the field's owner class.
+     * @param name
+     *            the field's name.
+     * @param desc
+     *            the field's descriptor.
      * @return a new or already existing field reference item.
      */
-    Item newFieldItem(final String owner, final String name, final String desc)
-    {
+    Item newFieldItem(final String owner, final String name, final String desc) {
         key3.set(FIELD, owner, name, desc);
         Item result = get(key3);
         if (result == null) {
@@ -1293,33 +1371,35 @@ public class ClassWriter extends ClassVisitor {
      * Does nothing if the constant pool already contains a similar item.
      * <i>This method is intended for {@link Attribute} sub classes, and is
      * normally not needed by class generators or adapters.</i>
-     *
-     * @param owner the internal name of the field's owner class.
-     * @param name the field's name.
-     * @param desc the field's descriptor.
+     * 
+     * @param owner
+     *            the internal name of the field's owner class.
+     * @param name
+     *            the field's name.
+     * @param desc
+     *            the field's descriptor.
      * @return the index of a new or already existing field reference item.
      */
-    public int newField(final String owner, final String name, final String desc)
-    {
+    public int newField(final String owner, final String name, final String desc) {
         return newFieldItem(owner, name, desc).index;
     }
 
     /**
      * Adds a method reference to the constant pool of the class being build.
      * Does nothing if the constant pool already contains a similar item.
-     *
-     * @param owner the internal name of the method's owner class.
-     * @param name the method's name.
-     * @param desc the method's descriptor.
-     * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
+     * 
+     * @param owner
+     *            the internal name of the method's owner class.
+     * @param name
+     *            the method's name.
+     * @param desc
+     *            the method's descriptor.
+     * @param itf
+     *            <tt>true</tt> if <tt>owner</tt> is an interface.
      * @return a new or already existing method reference item.
      */
-    Item newMethodItem(
-        final String owner,
-        final String name,
-        final String desc,
-        final boolean itf)
-    {
+    Item newMethodItem(final String owner, final String name,
+            final String desc, final boolean itf) {
         int type = itf ? IMETH : METH;
         key3.set(type, owner, name, desc);
         Item result = get(key3);
@@ -1336,27 +1416,28 @@ public class ClassWriter extends ClassVisitor {
      * Does nothing if the constant pool already contains a similar item.
      * <i>This method is intended for {@link Attribute} sub classes, and is
      * normally not needed by class generators or adapters.</i>
-     *
-     * @param owner the internal name of the method's owner class.
-     * @param name the method's name.
-     * @param desc the method's descriptor.
-     * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
+     * 
+     * @param owner
+     *            the internal name of the method's owner class.
+     * @param name
+     *            the method's name.
+     * @param desc
+     *            the method's descriptor.
+     * @param itf
+     *            <tt>true</tt> if <tt>owner</tt> is an interface.
      * @return the index of a new or already existing method reference item.
      */
-    public int newMethod(
-        final String owner,
-        final String name,
-        final String desc,
-        final boolean itf)
-    {
+    public int newMethod(final String owner, final String name,
+            final String desc, final boolean itf) {
         return newMethodItem(owner, name, desc, itf).index;
     }
 
     /**
      * Adds an integer to the constant pool of the class being build. Does
      * nothing if the constant pool already contains a similar item.
-     *
-     * @param value the int value.
+     * 
+     * @param value
+     *            the int value.
      * @return a new or already existing int item.
      */
     Item newInteger(final int value) {
@@ -1373,8 +1454,9 @@ public class ClassWriter extends ClassVisitor {
     /**
      * Adds a float to the constant pool of the class being build. Does nothing
      * if the constant pool already contains a similar item.
-     *
-     * @param value the float value.
+     * 
+     * @param value
+     *            the float value.
      * @return a new or already existing float item.
      */
     Item newFloat(final float value) {
@@ -1391,8 +1473,9 @@ public class ClassWriter extends ClassVisitor {
     /**
      * Adds a long to the constant pool of the class being build. Does nothing
      * if the constant pool already contains a similar item.
-     *
-     * @param value the long value.
+     * 
+     * @param value
+     *            the long value.
      * @return a new or already existing long item.
      */
     Item newLong(final long value) {
@@ -1410,8 +1493,9 @@ public class ClassWriter extends ClassVisitor {
     /**
      * Adds a double to the constant pool of the class being build. Does nothing
      * if the constant pool already contains a similar item.
-     *
-     * @param value the double value.
+     * 
+     * @param value
+     *            the double value.
      * @return a new or already existing double item.
      */
     Item newDouble(final double value) {
@@ -1429,8 +1513,9 @@ public class ClassWriter extends ClassVisitor {
     /**
      * Adds a string to the constant pool of the class being build. Does nothing
      * if the constant pool already contains a similar item.
-     *
-     * @param value the String value.
+     * 
+     * @param value
+     *            the String value.
      * @return a new or already existing string item.
      */
     private Item newString(final String value) {
@@ -1449,9 +1534,11 @@ public class ClassWriter extends ClassVisitor {
      * nothing if the constant pool already contains a similar item. <i>This
      * method is intended for {@link Attribute} sub classes, and is normally not
      * needed by class generators or adapters.</i>
-     *
-     * @param name a name.
-     * @param desc a type descriptor.
+     * 
+     * @param name
+     *            a name.
+     * @param desc
+     *            a type descriptor.
      * @return the index of a new or already existing name and type item.
      */
     public int newNameType(final String name, final String desc) {
@@ -1461,9 +1548,11 @@ public class ClassWriter extends ClassVisitor {
     /**
      * Adds a name and type to the constant pool of the class being build. Does
      * nothing if the constant pool already contains a similar item.
-     *
-     * @param name a name.
-     * @param desc a type descriptor.
+     * 
+     * @param name
+     *            a name.
+     * @param desc
+     *            a type descriptor.
      * @return a new or already existing name and type item.
      */
     Item newNameTypeItem(final String name, final String desc) {
@@ -1480,8 +1569,9 @@ public class ClassWriter extends ClassVisitor {
     /**
      * Adds the given internal name to {@link #typeTable} and returns its index.
      * Does nothing if the type table already contains this internal name.
-     *
-     * @param type the internal name to be added to the type table.
+     * 
+     * @param type
+     *            the internal name to be added to the type table.
      * @return the index of this internal name in the type table.
      */
     int addType(final String type) {
@@ -1497,10 +1587,12 @@ public class ClassWriter extends ClassVisitor {
      * Adds the given "uninitialized" type to {@link #typeTable} and returns its
      * index. This method is used for UNINITIALIZED types, made of an internal
      * name and a bytecode offset.
-     *
-     * @param type the internal name to be added to the type table.
-     * @param offset the bytecode offset of the NEW instruction that created
-     *        this UNINITIALIZED type value.
+     * 
+     * @param type
+     *            the internal name to be added to the type table.
+     * @param offset
+     *            the bytecode offset of the NEW instruction that created this
+     *            UNINITIALIZED type value.
      * @return the index of this internal name in the type table.
      */
     int addUninitializedType(final String type, final int offset) {
@@ -1517,8 +1609,9 @@ public class ClassWriter extends ClassVisitor {
 
     /**
      * Adds the given Item to {@link #typeTable}.
-     *
-     * @param item the value to be added to the type table.
+     * 
+     * @param item
+     *            the value to be added to the type table.
      * @return the added Item, which a new Item instance with the same value as
      *         the given Item.
      */
@@ -1543,9 +1636,11 @@ public class ClassWriter extends ClassVisitor {
      * method calls {@link #getCommonSuperClass} and caches the result in the
      * {@link #items} hash table to speedup future calls with the same
      * parameters.
-     *
-     * @param type1 index of an internal name in {@link #typeTable}.
-     * @param type2 index of an internal name in {@link #typeTable}.
+     * 
+     * @param type1
+     *            index of an internal name in {@link #typeTable}.
+     * @param type2
+     *            index of an internal name in {@link #typeTable}.
      * @return the index of the common super type of the two given types.
      */
     int getMergedType(final int type1, final int type2) {
@@ -1565,20 +1660,21 @@ public class ClassWriter extends ClassVisitor {
 
     /**
      * Returns the common super type of the two given types. The default
-     * implementation of this method <i>loads<i> the two given classes and uses
+     * implementation of this method <i>loads</i> the two given classes and uses
      * the java.lang.Class methods to find the common super class. It can be
      * overridden to compute this common super type in other ways, in particular
      * without actually loading any class, or to take into account the class
      * that is currently being generated by this ClassWriter, which can of
      * course not be loaded since it is under construction.
-     *
-     * @param type1 the internal name of a class.
-     * @param type2 the internal name of another class.
+     * 
+     * @param type1
+     *            the internal name of a class.
+     * @param type2
+     *            the internal name of another class.
      * @return the internal name of the common super class of the two given
      *         classes.
      */
-    protected String getCommonSuperClass(final String type1, final String type2)
-    {
+    protected String getCommonSuperClass(final String type1, final String type2) {
         Class<?> c, d;
         ClassLoader classLoader = getClass().getClassLoader();
         try {
@@ -1606,8 +1702,9 @@ public class ClassWriter extends ClassVisitor {
     /**
      * Returns the constant pool's hash table item which is equal to the given
      * item.
-     *
-     * @param key a constant pool item.
+     * 
+     * @param key
+     *            a constant pool item.
      * @return the constant pool's hash table item which is equal to the given
      *         item, or <tt>null</tt> if there is no such item.
      */
@@ -1622,8 +1719,9 @@ public class ClassWriter extends ClassVisitor {
     /**
      * Puts the given item in the constant pool's hash table. The hash table
      * <i>must</i> not already contains this item.
-     *
-     * @param i the item to be added to the constant pool's hash table.
+     * 
+     * @param i
+     *            the item to be added to the constant pool's hash table.
      */
     private void put(final Item i) {
         if (index + typeCount > threshold) {
@@ -1650,10 +1748,13 @@ public class ClassWriter extends ClassVisitor {
 
     /**
      * Puts one byte and two shorts into the constant pool.
-     *
-     * @param b a byte.
-     * @param s1 a short.
-     * @param s2 another short.
+     * 
+     * @param b
+     *            a byte.
+     * @param s1
+     *            a short.
+     * @param s2
+     *            another short.
      */
     private void put122(final int b, final int s1, final int s2) {
         pool.put12(b, s1).putShort(s2);
@@ -1661,10 +1762,13 @@ public class ClassWriter extends ClassVisitor {
 
     /**
      * Puts two bytes and one short into the constant pool.
-     *
-     * @param b1 a byte.
-     * @param b2 another byte.
-     * @param s a short.
+     * 
+     * @param b1
+     *            a byte.
+     * @param b2
+     *            another byte.
+     * @param s
+     *            a short.
      */
     private void put112(final int b1, final int b2, final int s) {
         pool.put11(b1, b2).putShort(s);

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java
new file mode 100644
index 0000000..27983d6
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java
@@ -0,0 +1,145 @@
+/***
+ * 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;
+
+/**
+ * Information about a class being parsed in a {@link ClassReader}.
+ * 
+ * @author Eric Bruneton
+ */
+class Context {
+
+    /**
+     * Prototypes of the attributes that must be parsed for this class.
+     */
+    Attribute[] attrs;
+
+    /**
+     * The {@link ClassReader} option flags for the parsing of this class.
+     */
+    int flags;
+
+    /**
+     * The buffer used to read strings.
+     */
+    char[] buffer;
+
+    /**
+     * The start index of each bootstrap method.
+     */
+    int[] bootstrapMethods;
+
+    /**
+     * The access flags of the method currently being parsed.
+     */
+    int access;
+
+    /**
+     * The name of the method currently being parsed.
+     */
+    String name;
+
+    /**
+     * The descriptor of the method currently being parsed.
+     */
+    String desc;
+
+    /**
+     * The label objects, indexed by bytecode offset, of the method currently
+     * being parsed (only bytecode offsets for which a label is needed have a
+     * non null associated Label object).
+     */
+    Label[] labels;
+
+    /**
+     * The target of the type annotation currently being parsed.
+     */
+    int typeRef;
+
+    /**
+     * The path of the type annotation currently being parsed.
+     */
+    TypePath typePath;
+
+    /**
+     * The offset of the latest stack map frame that has been parsed.
+     */
+    int offset;
+
+    /**
+     * The labels corresponding to the start of the local variable ranges in the
+     * local variable type annotation currently being parsed.
+     */
+    Label[] start;
+
+    /**
+     * The labels corresponding to the end of the local variable ranges in the
+     * local variable type annotation currently being parsed.
+     */
+    Label[] end;
+
+    /**
+     * The local variable indices for each local variable range in the local
+     * variable type annotation currently being parsed.
+     */
+    int[] index;
+
+    /**
+     * The encoding of the latest stack map frame that has been parsed.
+     */
+    int mode;
+
+    /**
+     * The number of locals in the latest stack map frame that has been parsed.
+     */
+    int localCount;
+
+    /**
+     * The number locals in the latest stack map frame that has been parsed,
+     * minus the number of locals in the previous frame.
+     */
+    int localDiff;
+
+    /**
+     * The local values of the latest stack map frame that has been parsed.
+     */
+    Object[] local;
+
+    /**
+     * The stack size of the latest stack map frame that has been parsed.
+     */
+    int stackCount;
+
+    /**
+     * The stack values of the latest stack map frame that has been parsed.
+     */
+    Object[] stack;
+}
\ 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/Edge.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java
index 80222bc..9347888 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
 
 /**
  * An edge in the control flow graph of a method body. See {@link Label Label}.
- *
+ * 
  * @author Eric Bruneton
  */
 class Edge {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
index 32c23d1..107af8f 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
@@ -30,17 +30,17 @@
 package org.apache.tapestry5.internal.plastic.asm;
 
 /**
- * A visitor to visit a Java field. The methods of this class must be called
- * in the following order: ( <tt>visitAnnotation</tt> |
- * <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
- *
+ * A visitor to visit a Java field. The methods of this class must be called in
+ * the following order: ( <tt>visitAnnotation</tt> |
+ * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
+ * 
  * @author Eric Bruneton
  */
 public abstract class FieldVisitor {
 
     /**
      * The ASM API version implemented by this visitor. The value of this field
-     * must be one of {@link Opcodes#ASM4}.
+     * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
      */
     protected final int api;
 
@@ -52,9 +52,10 @@ public abstract class FieldVisitor {
 
     /**
      * Constructs a new {@link FieldVisitor}.
-     *
-     * @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 FieldVisitor(final int api) {
         this(api, null);
@@ -62,25 +63,29 @@ public abstract class FieldVisitor {
 
     /**
      * Constructs a new {@link FieldVisitor}.
-     *
-     * @param api the ASM API version implemented by this visitor. Must be one
-     *        of {@link Opcodes#ASM4}.
-     * @param fv the field visitor to which this visitor must delegate method
-     *        calls. May be null.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param fv
+     *            the field visitor to which this visitor must delegate method
+     *            calls. May be null.
      */
     public FieldVisitor(final int api, final FieldVisitor fv) {
-        /*if (api != Opcodes.ASM4) {
+        if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
             throw new IllegalArgumentException();
-        }*/
+        }
         this.api = api;
         this.fv = fv;
     }
 
     /**
      * Visits an annotation of the field.
-     *
-     * @param desc the class descriptor of the annotation class.
-     * @param visible <tt>true</tt> if the annotation is visible at runtime.
+     * 
+     * @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.
      */
@@ -92,9 +97,39 @@ public abstract class FieldVisitor {
     }
 
     /**
+     * Visits an annotation on the type of the field.
+     * 
+     * @param typeRef
+     *            a reference to the annotated type. The sort of this type
+     *            reference must be {@link TypeReference#FIELD FIELD}. 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.
+     * @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.
+     */
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        if (api < Opcodes.ASM5) {
+            throw new RuntimeException();
+        }
+        if (fv != null) {
+            return fv.visitTypeAnnotation(typeRef, typePath, desc, visible);
+        }
+        return null;
+    }
+
+    /**
      * Visits a non standard attribute of the field.
-     *
-     * @param attr an attribute.
+     * 
+     * @param attr
+     *            an attribute.
      */
     public void visitAttribute(Attribute attr) {
         if (fv != null) {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
index b61105a..4a5f406 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
 
 /**
  * An {@link FieldVisitor} that generates Java fields in bytecode form.
- *
+ * 
  * @author Eric Bruneton
  */
 final class FieldWriter extends FieldVisitor {
@@ -81,6 +81,17 @@ final class FieldWriter extends FieldVisitor {
     private AnnotationWriter ianns;
 
     /**
+     * The runtime visible type annotations of this field. May be <tt>null</tt>.
+     */
+    private AnnotationWriter tanns;
+
+    /**
+     * The runtime invisible type annotations of this field. May be
+     * <tt>null</tt>.
+     */
+    private AnnotationWriter itanns;
+
+    /**
      * The non standard attributes of this field. May be <tt>null</tt>.
      */
     private Attribute attrs;
@@ -91,23 +102,23 @@ final class FieldWriter extends FieldVisitor {
 
     /**
      * Constructs a new {@link FieldWriter}.
-     *
-     * @param cw the class writer to which this field must be added.
-     * @param access the field's access flags (see {@link Opcodes}).
-     * @param name the field's name.
-     * @param desc the field's descriptor (see {@link Type}).
-     * @param signature the field's signature. May be <tt>null</tt>.
-     * @param value the field's constant value. May be <tt>null</tt>.
+     * 
+     * @param cw
+     *            the class writer to which this field must be added.
+     * @param access
+     *            the field's access flags (see {@link Opcodes}).
+     * @param name
+     *            the field's name.
+     * @param desc
+     *            the field's descriptor (see {@link Type}).
+     * @param signature
+     *            the field's signature. May be <tt>null</tt>.
+     * @param value
+     *            the field's constant value. May be <tt>null</tt>.
      */
-    FieldWriter(
-        final ClassWriter cw,
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final Object value)
-    {
-        super(Opcodes.ASM4);
+    FieldWriter(final ClassWriter cw, final int access, final String name,
+            final String desc, final String signature, final Object value) {
+        super(Opcodes.ASM5);
         if (cw.firstField == null) {
             cw.firstField = this;
         } else {
@@ -131,10 +142,8 @@ final class FieldWriter extends FieldVisitor {
     // ------------------------------------------------------------------------
 
     @Override
-    public AnnotationVisitor visitAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
         if (!ClassReader.ANNOTATIONS) {
             return null;
         }
@@ -153,6 +162,29 @@ final class FieldWriter extends FieldVisitor {
     }
 
     @Override
+    public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        if (!ClassReader.ANNOTATIONS) {
+            return null;
+        }
+        ByteVector bv = new ByteVector();
+        // write target_type and target_info
+        AnnotationWriter.putTarget(typeRef, typePath, bv);
+        // write type, and reserve space for values count
+        bv.putShort(cw.newUTF8(desc)).putShort(0);
+        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+                bv.length - 2);
+        if (visible) {
+            aw.next = tanns;
+            tanns = aw;
+        } else {
+            aw.next = itanns;
+            itanns = aw;
+        }
+        return aw;
+    }
+
+    @Override
     public void visitAttribute(final Attribute attr) {
         attr.next = attrs;
         attrs = attr;
@@ -168,7 +200,7 @@ final class FieldWriter extends FieldVisitor {
 
     /**
      * Returns the size of this field.
-     *
+     * 
      * @return the size of this field.
      */
     int getSize() {
@@ -177,11 +209,12 @@ final class FieldWriter extends FieldVisitor {
             cw.newUTF8("ConstantValue");
             size += 8;
         }
-        if ((access & Opcodes.ACC_SYNTHETIC) != 0
-                && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
-        {
-            cw.newUTF8("Synthetic");
-            size += 6;
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            if ((cw.version & 0xFFFF) < Opcodes.V1_5
+                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+                cw.newUTF8("Synthetic");
+                size += 6;
+            }
         }
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             cw.newUTF8("Deprecated");
@@ -199,6 +232,14 @@ final class FieldWriter extends FieldVisitor {
             cw.newUTF8("RuntimeInvisibleAnnotations");
             size += 8 + ianns.getSize();
         }
+        if (ClassReader.ANNOTATIONS && tanns != null) {
+            cw.newUTF8("RuntimeVisibleTypeAnnotations");
+            size += 8 + tanns.getSize();
+        }
+        if (ClassReader.ANNOTATIONS && itanns != null) {
+            cw.newUTF8("RuntimeInvisibleTypeAnnotations");
+            size += 8 + itanns.getSize();
+        }
         if (attrs != null) {
             size += attrs.getSize(cw, null, 0, -1, -1);
         }
@@ -207,22 +248,24 @@ final class FieldWriter extends FieldVisitor {
 
     /**
      * Puts the content of this field into the given byte vector.
-     *
-     * @param out where the content of this field must be put.
+     * 
+     * @param out
+     *            where the content of this field must be put.
      */
     void put(final ByteVector out) {
-        int mask = Opcodes.ACC_DEPRECATED
-                | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
-                | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC));
+        final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
+        int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+                | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
         out.putShort(access & ~mask).putShort(name).putShort(desc);
         int attributeCount = 0;
         if (value != 0) {
             ++attributeCount;
         }
-        if ((access & Opcodes.ACC_SYNTHETIC) != 0
-                && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
-        {
-            ++attributeCount;
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            if ((cw.version & 0xFFFF) < Opcodes.V1_5
+                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+                ++attributeCount;
+            }
         }
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             ++attributeCount;
@@ -236,6 +279,12 @@ final class FieldWriter extends FieldVisitor {
         if (ClassReader.ANNOTATIONS && ianns != null) {
             ++attributeCount;
         }
+        if (ClassReader.ANNOTATIONS && tanns != null) {
+            ++attributeCount;
+        }
+        if (ClassReader.ANNOTATIONS && itanns != null) {
+            ++attributeCount;
+        }
         if (attrs != null) {
             attributeCount += attrs.getCount();
         }
@@ -244,10 +293,11 @@ final class FieldWriter extends FieldVisitor {
             out.putShort(cw.newUTF8("ConstantValue"));
             out.putInt(2).putShort(value);
         }
-        if ((access & Opcodes.ACC_SYNTHETIC) != 0
-                && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
-        {
-            out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            if ((cw.version & 0xFFFF) < Opcodes.V1_5
+                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+                out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+            }
         }
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             out.putShort(cw.newUTF8("Deprecated")).putInt(0);
@@ -264,6 +314,14 @@ final class FieldWriter extends FieldVisitor {
             out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
             ianns.put(out);
         }
+        if (ClassReader.ANNOTATIONS && tanns != null) {
+            out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
+            tanns.put(out);
+        }
+        if (ClassReader.ANNOTATIONS && itanns != null) {
+            out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
+            itanns.put(out);
+        }
         if (attrs != null) {
             attrs.put(cw, null, 0, -1, -1, out);
         }


[07/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceInterpreter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceInterpreter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceInterpreter.java
new file mode 100644
index 0000000..284fbef
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceInterpreter.java
@@ -0,0 +1,198 @@
+/***
+ * 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.HashSet;
+import java.util.List;
+import java.util.Set;
+
+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.FieldInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.InvokeDynamicInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LdcInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodInsnNode;
+
+/**
+ * An {@link Interpreter} for {@link SourceValue} values.
+ * 
+ * @author Eric Bruneton
+ */
+public class SourceInterpreter extends Interpreter<SourceValue> implements
+        Opcodes {
+
+    public SourceInterpreter() {
+        super(ASM5);
+    }
+
+    protected SourceInterpreter(final int api) {
+        super(api);
+    }
+
+    @Override
+    public SourceValue newValue(final Type type) {
+        if (type == Type.VOID_TYPE) {
+            return null;
+        }
+        return new SourceValue(type == null ? 1 : type.getSize());
+    }
+
+    @Override
+    public SourceValue newOperation(final AbstractInsnNode insn) {
+        int size;
+        switch (insn.getOpcode()) {
+        case LCONST_0:
+        case LCONST_1:
+        case DCONST_0:
+        case DCONST_1:
+            size = 2;
+            break;
+        case LDC:
+            Object cst = ((LdcInsnNode) insn).cst;
+            size = cst instanceof Long || cst instanceof Double ? 2 : 1;
+            break;
+        case GETSTATIC:
+            size = Type.getType(((FieldInsnNode) insn).desc).getSize();
+            break;
+        default:
+            size = 1;
+        }
+        return new SourceValue(size, insn);
+    }
+
+    @Override
+    public SourceValue copyOperation(final AbstractInsnNode insn,
+            final SourceValue value) {
+        return new SourceValue(value.getSize(), insn);
+    }
+
+    @Override
+    public SourceValue unaryOperation(final AbstractInsnNode insn,
+            final SourceValue value) {
+        int size;
+        switch (insn.getOpcode()) {
+        case LNEG:
+        case DNEG:
+        case I2L:
+        case I2D:
+        case L2D:
+        case F2L:
+        case F2D:
+        case D2L:
+            size = 2;
+            break;
+        case GETFIELD:
+            size = Type.getType(((FieldInsnNode) insn).desc).getSize();
+            break;
+        default:
+            size = 1;
+        }
+        return new SourceValue(size, insn);
+    }
+
+    @Override
+    public SourceValue binaryOperation(final AbstractInsnNode insn,
+            final SourceValue value1, final SourceValue value2) {
+        int size;
+        switch (insn.getOpcode()) {
+        case LALOAD:
+        case DALOAD:
+        case LADD:
+        case DADD:
+        case LSUB:
+        case DSUB:
+        case LMUL:
+        case DMUL:
+        case LDIV:
+        case DDIV:
+        case LREM:
+        case DREM:
+        case LSHL:
+        case LSHR:
+        case LUSHR:
+        case LAND:
+        case LOR:
+        case LXOR:
+            size = 2;
+            break;
+        default:
+            size = 1;
+        }
+        return new SourceValue(size, insn);
+    }
+
+    @Override
+    public SourceValue ternaryOperation(final AbstractInsnNode insn,
+            final SourceValue value1, final SourceValue value2,
+            final SourceValue value3) {
+        return new SourceValue(1, insn);
+    }
+
+    @Override
+    public SourceValue naryOperation(final AbstractInsnNode insn,
+            final List<? extends SourceValue> values) {
+        int size;
+        int opcode = insn.getOpcode();
+        if (opcode == MULTIANEWARRAY) {
+            size = 1;
+        } else {
+            String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc
+                    : ((MethodInsnNode) insn).desc;
+            size = Type.getReturnType(desc).getSize();
+        }
+        return new SourceValue(size, insn);
+    }
+
+    @Override
+    public void returnOperation(final AbstractInsnNode insn,
+            final SourceValue value, final SourceValue expected) {
+    }
+
+    @Override
+    public SourceValue merge(final SourceValue d, final SourceValue w) {
+        if (d.insns instanceof SmallSet && w.insns instanceof SmallSet) {
+            Set<AbstractInsnNode> s = ((SmallSet<AbstractInsnNode>) d.insns)
+                    .union((SmallSet<AbstractInsnNode>) w.insns);
+            if (s == d.insns && d.size == w.size) {
+                return d;
+            } else {
+                return new SourceValue(Math.min(d.size, w.size), s);
+            }
+        }
+        if (d.size != w.size || !d.insns.containsAll(w.insns)) {
+            HashSet<AbstractInsnNode> s = new HashSet<AbstractInsnNode>();
+            s.addAll(d.insns);
+            s.addAll(w.insns);
+            return new SourceValue(Math.min(d.size, w.size), s);
+        }
+        return d;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceValue.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceValue.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceValue.java
new file mode 100644
index 0000000..0cb2f50
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceValue.java
@@ -0,0 +1,97 @@
+/***
+ * 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.Set;
+
+import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
+
+/**
+ * A {@link Value} that is represented by its type in a two types type system.
+ * This type system distinguishes the ONEWORD and TWOWORDS types.
+ * 
+ * @author Eric Bruneton
+ */
+public class SourceValue implements Value {
+
+    /**
+     * The size of this value.
+     */
+    public final int size;
+
+    /**
+     * The instructions that can produce this value. For example, for the Java
+     * code below, the instructions that can produce the value of <tt>i</tt> at
+     * line 5 are the txo ISTORE instructions at line 1 and 3:
+     * 
+     * <pre>
+     * 1: i = 0;
+     * 2: if (...) {
+     * 3:   i = 1;
+     * 4: }
+     * 5: return i;
+     * </pre>
+     * 
+     * This field is a set of {@link AbstractInsnNode} objects.
+     */
+    public final Set<AbstractInsnNode> insns;
+
+    public SourceValue(final int size) {
+        this(size, SmallSet.<AbstractInsnNode> emptySet());
+    }
+
+    public SourceValue(final int size, final AbstractInsnNode insn) {
+        this.size = size;
+        this.insns = new SmallSet<AbstractInsnNode>(insn, null);
+    }
+
+    public SourceValue(final int size, final Set<AbstractInsnNode> insns) {
+        this.size = size;
+        this.insns = insns;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    @Override
+    public boolean equals(final Object value) {
+        if (!(value instanceof SourceValue)) {
+            return false;
+        }
+        SourceValue v = (SourceValue) value;
+        return size == v.size && insns.equals(v.insns);
+    }
+
+    @Override
+    public int hashCode() {
+        return insns.hashCode();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Subroutine.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Subroutine.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Subroutine.java
new file mode 100644
index 0000000..2032d59
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Subroutine.java
@@ -0,0 +1,90 @@
+/***
+ * 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.List;
+
+import org.apache.tapestry5.internal.plastic.asm.tree.JumpInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LabelNode;
+
+/**
+ * A method subroutine (corresponds to a JSR instruction).
+ * 
+ * @author Eric Bruneton
+ */
+class Subroutine {
+
+    LabelNode start;
+
+    boolean[] access;
+
+    List<JumpInsnNode> callers;
+
+    private Subroutine() {
+    }
+
+    Subroutine(final LabelNode start, final int maxLocals,
+            final JumpInsnNode caller) {
+        this.start = start;
+        this.access = new boolean[maxLocals];
+        this.callers = new ArrayList<JumpInsnNode>();
+        callers.add(caller);
+    }
+
+    public Subroutine copy() {
+        Subroutine result = new Subroutine();
+        result.start = start;
+        result.access = new boolean[access.length];
+        System.arraycopy(access, 0, result.access, 0, access.length);
+        result.callers = new ArrayList<JumpInsnNode>(callers);
+        return result;
+    }
+
+    public boolean merge(final Subroutine subroutine) throws AnalyzerException {
+        boolean changes = false;
+        for (int i = 0; i < access.length; ++i) {
+            if (subroutine.access[i] && !access[i]) {
+                access[i] = true;
+                changes = true;
+            }
+        }
+        if (subroutine.start == start) {
+            for (int i = 0; i < subroutine.callers.size(); ++i) {
+                JumpInsnNode caller = subroutine.callers.get(i);
+                if (!callers.contains(caller)) {
+                    callers.add(caller);
+                    changes = true;
+                }
+            }
+        }
+        return changes;
+    }
+}
\ 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/Value.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Value.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Value.java
new file mode 100644
index 0000000..b0d657c
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Value.java
@@ -0,0 +1,45 @@
+/***
+ * 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;
+
+/**
+ * An immutable symbolic value for semantic interpretation of bytecode.
+ * 
+ * @author Eric Bruneton
+ */
+public interface Value {
+
+    /**
+     * Returns the size of this value in words.
+     * 
+     * @return either 1 or 2.
+     */
+    int getSize();
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/package.html
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/package.html b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/package.html
new file mode 100644
index 0000000..228da02
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/package.html
@@ -0,0 +1,67 @@
+<html>
+<!--
+ * 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.
+-->
+<body>
+
+<p>
+Provides a framework for static code analysis based on the asm.tree package.
+</p>
+
+<p>
+Basic usage:
+</p>
+
+<pre>
+ClassReader cr = new ClassReader(bytecode);
+ClassNode cn = new ClassNode();
+cr.accept(cn, ClassReader.SKIP_DEBUG);
+
+List methods = cn.methods;
+for (int i = 0; i < methods.size(); ++i) {
+    MethodNode method = (MethodNode) methods.get(i);
+    if (method.instructions.size() > 0) {
+        Analyzer a = new Analyzer(new BasicInterpreter());
+        a.analyze(cn.name, method);
+        Frame[] frames = a.getFrames();
+        // Elements of the frames arrray now contains info for each instruction
+        // from the analyzed method. BasicInterpreter creates BasicValue, that
+        // is using simplified type system that distinguishes the UNINITIALZED,
+        // INT, FLOAT, LONG, DOUBLE, REFERENCE and RETURNADDRESS types.
+        ...
+    }
+}
+</pre>
+
+<p>
+@since ASM 1.4.3
+</p>
+
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java
index e1fec58..f8b0b0d 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java
@@ -29,25 +29,28 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.util;
 
-import org.apache.tapestry5.internal.plastic.asm.Label;
-
 import java.util.Map;
 
+import org.apache.tapestry5.internal.plastic.asm.Label;
+
 /**
  * An {@link org.apache.tapestry5.internal.plastic.asm.Attribute Attribute} that can print the ASM code
  * to create an equivalent attribute.
- *
+ * 
  * @author Eugene Kuleshov
  */
 public interface ASMifiable {
 
     /**
      * Prints the ASM code to create an attribute equal to this attribute.
-     *
-     * @param buf a buffer used for printing Java code.
-     * @param varName name of the variable in a printed code used to store
-     *        attribute instance.
-     * @param labelNames map of label instances to their names.
+     * 
+     * @param buf
+     *            a buffer used for printing Java code.
+     * @param varName
+     *            name of the variable in a printed code used to store attribute
+     *            instance.
+     * @param labelNames
+     *            map of label instances to their names.
      */
     void asmify(StringBuffer buf, String varName, Map<Label, String> labelNames);
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java
new file mode 100644
index 0000000..34829b0
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java
@@ -0,0 +1,1285 @@
+/***
+ * 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.util;
+
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+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 {@link Printer} that prints the ASM code to generate the classes if visits.
+ * 
+ * @author Eric Bruneton
+ */
+public class ASMifier extends Printer {
+
+    /**
+     * The name of the visitor variable in the produced code.
+     */
+    protected final String name;
+
+    /**
+     * Identifier of the annotation visitor variable in the produced code.
+     */
+    protected final int id;
+
+    /**
+     * The label names. This map associates String values to Label keys. It is
+     * used only in ASMifierMethodVisitor.
+     */
+    protected Map<Label, String> labelNames;
+
+    /**
+     * Pseudo access flag used to distinguish class access flags.
+     */
+    private static final int ACCESS_CLASS = 262144;
+
+    /**
+     * Pseudo access flag used to distinguish field access flags.
+     */
+    private static final int ACCESS_FIELD = 524288;
+
+    /**
+     * Pseudo access flag used to distinguish inner class flags.
+     */
+    private static final int ACCESS_INNER = 1048576;
+
+    /**
+     * Constructs a new {@link ASMifier}. <i>Subclasses must not use this
+     * constructor</i>. Instead, they must use the
+     * {@link #ASMifier(int, String, int)} version.
+     * 
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public ASMifier() {
+        this(Opcodes.ASM5, "cw", 0);
+        if (getClass() != ASMifier.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Constructs a new {@link ASMifier}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this class. Must be one of
+     *            {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param name
+     *            the name of the visitor variable in the produced code.
+     * @param id
+     *            identifier of the annotation visitor variable in the produced
+     *            code.
+     */
+    protected ASMifier(final int api, final String name, final int id) {
+        super(api);
+        this.name = name;
+        this.id = id;
+    }
+
+    /**
+     * Prints the ASM source code to generate the given class to the standard
+     * output.
+     * <p>
+     * Usage: ASMifier [-debug] &lt;binary class name or class file name&gt;
+     * 
+     * @param args
+     *            the command line arguments.
+     * 
+     * @throws Exception
+     *             if the class cannot be found, or if an IO exception occurs.
+     */
+    public static void main(final String[] args) throws Exception {
+        int i = 0;
+        int flags = ClassReader.SKIP_DEBUG;
+
+        boolean ok = true;
+        if (args.length < 1 || args.length > 2) {
+            ok = false;
+        }
+        if (ok && "-debug".equals(args[0])) {
+            i = 1;
+            flags = 0;
+            if (args.length != 2) {
+                ok = false;
+            }
+        }
+        if (!ok) {
+            System.err
+                    .println("Prints the ASM code to generate the given class.");
+            System.err.println("Usage: ASMifier [-debug] "
+                    + "<fully qualified class name or class file name>");
+            return;
+        }
+        ClassReader cr;
+        if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1
+                || args[i].indexOf('/') > -1) {
+            cr = new ClassReader(new FileInputStream(args[i]));
+        } else {
+            cr = new ClassReader(args[i]);
+        }
+        cr.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(
+                System.out)), flags);
+    }
+
+    // ------------------------------------------------------------------------
+    // Classes
+    // ------------------------------------------------------------------------
+
+    @Override
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
+        String simpleName;
+        int n = name.lastIndexOf('/');
+        if (n == -1) {
+            simpleName = name;
+        } else {
+            text.add("package asm." + name.substring(0, n).replace('/', '.')
+                    + ";\n");
+            simpleName = name.substring(n + 1);
+        }
+        text.add("import java.util.*;\n");
+        text.add("import org.objectweb.asm.*;\n");
+        text.add("import org.objectweb.asm.attrs.*;\n");
+        text.add("public class " + simpleName + "Dump implements Opcodes {\n\n");
+        text.add("public static byte[] dump () throws Exception {\n\n");
+        text.add("ClassWriter cw = new ClassWriter(0);\n");
+        text.add("FieldVisitor fv;\n");
+        text.add("MethodVisitor mv;\n");
+        text.add("AnnotationVisitor av0;\n\n");
+
+        buf.setLength(0);
+        buf.append("cw.visit(");
+        switch (version) {
+        case Opcodes.V1_1:
+            buf.append("V1_1");
+            break;
+        case Opcodes.V1_2:
+            buf.append("V1_2");
+            break;
+        case Opcodes.V1_3:
+            buf.append("V1_3");
+            break;
+        case Opcodes.V1_4:
+            buf.append("V1_4");
+            break;
+        case Opcodes.V1_5:
+            buf.append("V1_5");
+            break;
+        case Opcodes.V1_6:
+            buf.append("V1_6");
+            break;
+        case Opcodes.V1_7:
+            buf.append("V1_7");
+            break;
+        default:
+            buf.append(version);
+            break;
+        }
+        buf.append(", ");
+        appendAccess(access | ACCESS_CLASS);
+        buf.append(", ");
+        appendConstant(name);
+        buf.append(", ");
+        appendConstant(signature);
+        buf.append(", ");
+        appendConstant(superName);
+        buf.append(", ");
+        if (interfaces != null && interfaces.length > 0) {
+            buf.append("new String[] {");
+            for (int i = 0; i < interfaces.length; ++i) {
+                buf.append(i == 0 ? " " : ", ");
+                appendConstant(interfaces[i]);
+            }
+            buf.append(" }");
+        } else {
+            buf.append("null");
+        }
+        buf.append(");\n\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitSource(final String file, final String debug) {
+        buf.setLength(0);
+        buf.append("cw.visitSource(");
+        appendConstant(file);
+        buf.append(", ");
+        appendConstant(debug);
+        buf.append(");\n\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitOuterClass(final String owner, final String name,
+            final String desc) {
+        buf.setLength(0);
+        buf.append("cw.visitOuterClass(");
+        appendConstant(owner);
+        buf.append(", ");
+        appendConstant(name);
+        buf.append(", ");
+        appendConstant(desc);
+        buf.append(");\n\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public ASMifier visitClassAnnotation(final String desc,
+            final boolean visible) {
+        return visitAnnotation(desc, visible);
+    }
+
+    @Override
+    public ASMifier visitClassTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        return visitTypeAnnotation(typeRef, typePath, desc, visible);
+    }
+
+    @Override
+    public void visitClassAttribute(final Attribute attr) {
+        visitAttribute(attr);
+    }
+
+    @Override
+    public void visitInnerClass(final String name, final String outerName,
+            final String innerName, final int access) {
+        buf.setLength(0);
+        buf.append("cw.visitInnerClass(");
+        appendConstant(name);
+        buf.append(", ");
+        appendConstant(outerName);
+        buf.append(", ");
+        appendConstant(innerName);
+        buf.append(", ");
+        appendAccess(access | ACCESS_INNER);
+        buf.append(");\n\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public ASMifier visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
+        buf.setLength(0);
+        buf.append("{\n");
+        buf.append("fv = cw.visitField(");
+        appendAccess(access | ACCESS_FIELD);
+        buf.append(", ");
+        appendConstant(name);
+        buf.append(", ");
+        appendConstant(desc);
+        buf.append(", ");
+        appendConstant(signature);
+        buf.append(", ");
+        appendConstant(value);
+        buf.append(");\n");
+        text.add(buf.toString());
+        ASMifier a = createASMifier("fv", 0);
+        text.add(a.getText());
+        text.add("}\n");
+        return a;
+    }
+
+    @Override
+    public ASMifier visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        buf.setLength(0);
+        buf.append("{\n");
+        buf.append("mv = cw.visitMethod(");
+        appendAccess(access);
+        buf.append(", ");
+        appendConstant(name);
+        buf.append(", ");
+        appendConstant(desc);
+        buf.append(", ");
+        appendConstant(signature);
+        buf.append(", ");
+        if (exceptions != null && exceptions.length > 0) {
+            buf.append("new String[] {");
+            for (int i = 0; i < exceptions.length; ++i) {
+                buf.append(i == 0 ? " " : ", ");
+                appendConstant(exceptions[i]);
+            }
+            buf.append(" }");
+        } else {
+            buf.append("null");
+        }
+        buf.append(");\n");
+        text.add(buf.toString());
+        ASMifier a = createASMifier("mv", 0);
+        text.add(a.getText());
+        text.add("}\n");
+        return a;
+    }
+
+    @Override
+    public void visitClassEnd() {
+        text.add("cw.visitEnd();\n\n");
+        text.add("return cw.toByteArray();\n");
+        text.add("}\n");
+        text.add("}\n");
+    }
+
+    // ------------------------------------------------------------------------
+    // Annotations
+    // ------------------------------------------------------------------------
+
+    @Override
+    public void visit(final String name, final Object value) {
+        buf.setLength(0);
+        buf.append("av").append(id).append(".visit(");
+        appendConstant(buf, name);
+        buf.append(", ");
+        appendConstant(buf, value);
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitEnum(final String name, final String desc,
+            final String value) {
+        buf.setLength(0);
+        buf.append("av").append(id).append(".visitEnum(");
+        appendConstant(buf, name);
+        buf.append(", ");
+        appendConstant(buf, desc);
+        buf.append(", ");
+        appendConstant(buf, value);
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public ASMifier visitAnnotation(final String name, final String desc) {
+        buf.setLength(0);
+        buf.append("{\n");
+        buf.append("AnnotationVisitor av").append(id + 1).append(" = av");
+        buf.append(id).append(".visitAnnotation(");
+        appendConstant(buf, name);
+        buf.append(", ");
+        appendConstant(buf, desc);
+        buf.append(");\n");
+        text.add(buf.toString());
+        ASMifier a = createASMifier("av", id + 1);
+        text.add(a.getText());
+        text.add("}\n");
+        return a;
+    }
+
+    @Override
+    public ASMifier visitArray(final String name) {
+        buf.setLength(0);
+        buf.append("{\n");
+        buf.append("AnnotationVisitor av").append(id + 1).append(" = av");
+        buf.append(id).append(".visitArray(");
+        appendConstant(buf, name);
+        buf.append(");\n");
+        text.add(buf.toString());
+        ASMifier a = createASMifier("av", id + 1);
+        text.add(a.getText());
+        text.add("}\n");
+        return a;
+    }
+
+    @Override
+    public void visitAnnotationEnd() {
+        buf.setLength(0);
+        buf.append("av").append(id).append(".visitEnd();\n");
+        text.add(buf.toString());
+    }
+
+    // ------------------------------------------------------------------------
+    // Fields
+    // ------------------------------------------------------------------------
+
+    @Override
+    public ASMifier visitFieldAnnotation(final String desc,
+            final boolean visible) {
+        return visitAnnotation(desc, visible);
+    }
+
+    @Override
+    public ASMifier visitFieldTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        return visitTypeAnnotation(typeRef, typePath, desc, visible);
+    }
+
+    @Override
+    public void visitFieldAttribute(final Attribute attr) {
+        visitAttribute(attr);
+    }
+
+    @Override
+    public void visitFieldEnd() {
+        buf.setLength(0);
+        buf.append(name).append(".visitEnd();\n");
+        text.add(buf.toString());
+    }
+
+    // ------------------------------------------------------------------------
+    // Methods
+    // ------------------------------------------------------------------------
+
+    @Override
+    public void visitParameter(String parameterName, int access) {
+        buf.setLength(0);
+        buf.append(name).append(".visitParameter(");
+        appendString(buf, parameterName);
+        buf.append(", ");
+        appendAccess(access);
+        text.add(buf.append(");\n").toString());
+    }
+
+    @Override
+    public ASMifier visitAnnotationDefault() {
+        buf.setLength(0);
+        buf.append("{\n").append("av0 = ").append(name)
+                .append(".visitAnnotationDefault();\n");
+        text.add(buf.toString());
+        ASMifier a = createASMifier("av", 0);
+        text.add(a.getText());
+        text.add("}\n");
+        return a;
+    }
+
+    @Override
+    public ASMifier visitMethodAnnotation(final String desc,
+            final boolean visible) {
+        return visitAnnotation(desc, visible);
+    }
+
+    @Override
+    public ASMifier visitMethodTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        return visitTypeAnnotation(typeRef, typePath, desc, visible);
+    }
+
+    @Override
+    public ASMifier visitParameterAnnotation(final int parameter,
+            final String desc, final boolean visible) {
+        buf.setLength(0);
+        buf.append("{\n").append("av0 = ").append(name)
+                .append(".visitParameterAnnotation(").append(parameter)
+                .append(", ");
+        appendConstant(desc);
+        buf.append(", ").append(visible).append(");\n");
+        text.add(buf.toString());
+        ASMifier a = createASMifier("av", 0);
+        text.add(a.getText());
+        text.add("}\n");
+        return a;
+    }
+
+    @Override
+    public void visitMethodAttribute(final Attribute attr) {
+        visitAttribute(attr);
+    }
+
+    @Override
+    public void visitCode() {
+        text.add(name + ".visitCode();\n");
+    }
+
+    @Override
+    public void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack) {
+        buf.setLength(0);
+        switch (type) {
+        case Opcodes.F_NEW:
+        case Opcodes.F_FULL:
+            declareFrameTypes(nLocal, local);
+            declareFrameTypes(nStack, stack);
+            if (type == Opcodes.F_NEW) {
+                buf.append(name).append(".visitFrame(Opcodes.F_NEW, ");
+            } else {
+                buf.append(name).append(".visitFrame(Opcodes.F_FULL, ");
+            }
+            buf.append(nLocal).append(", new Object[] {");
+            appendFrameTypes(nLocal, local);
+            buf.append("}, ").append(nStack).append(", new Object[] {");
+            appendFrameTypes(nStack, stack);
+            buf.append('}');
+            break;
+        case Opcodes.F_APPEND:
+            declareFrameTypes(nLocal, local);
+            buf.append(name).append(".visitFrame(Opcodes.F_APPEND,")
+                    .append(nLocal).append(", new Object[] {");
+            appendFrameTypes(nLocal, local);
+            buf.append("}, 0, null");
+            break;
+        case Opcodes.F_CHOP:
+            buf.append(name).append(".visitFrame(Opcodes.F_CHOP,")
+                    .append(nLocal).append(", null, 0, null");
+            break;
+        case Opcodes.F_SAME:
+            buf.append(name).append(
+                    ".visitFrame(Opcodes.F_SAME, 0, null, 0, null");
+            break;
+        case Opcodes.F_SAME1:
+            declareFrameTypes(1, stack);
+            buf.append(name).append(
+                    ".visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {");
+            appendFrameTypes(1, stack);
+            buf.append('}');
+            break;
+        }
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitInsn(final int opcode) {
+        buf.setLength(0);
+        buf.append(name).append(".visitInsn(").append(OPCODES[opcode])
+                .append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitIntInsn(final int opcode, final int operand) {
+        buf.setLength(0);
+        buf.append(name)
+                .append(".visitIntInsn(")
+                .append(OPCODES[opcode])
+                .append(", ")
+                .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer
+                        .toString(operand)).append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitVarInsn(final int opcode, final int var) {
+        buf.setLength(0);
+        buf.append(name).append(".visitVarInsn(").append(OPCODES[opcode])
+                .append(", ").append(var).append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitTypeInsn(final int opcode, final String type) {
+        buf.setLength(0);
+        buf.append(name).append(".visitTypeInsn(").append(OPCODES[opcode])
+                .append(", ");
+        appendConstant(type);
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitFieldInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        buf.setLength(0);
+        buf.append(this.name).append(".visitFieldInsn(")
+                .append(OPCODES[opcode]).append(", ");
+        appendConstant(owner);
+        buf.append(", ");
+        appendConstant(name);
+        buf.append(", ");
+        appendConstant(desc);
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Deprecated
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (api >= Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc,
+                opcode == Opcodes.INVOKEINTERFACE);
+    }
+
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    private void doVisitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        buf.setLength(0);
+        buf.append(this.name).append(".visitMethodInsn(")
+                .append(OPCODES[opcode]).append(", ");
+        appendConstant(owner);
+        buf.append(", ");
+        appendConstant(name);
+        buf.append(", ");
+        appendConstant(desc);
+        buf.append(", ");
+        buf.append(itf ? "true" : "false");
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        buf.setLength(0);
+        buf.append(this.name).append(".visitInvokeDynamicInsn(");
+        appendConstant(name);
+        buf.append(", ");
+        appendConstant(desc);
+        buf.append(", ");
+        appendConstant(bsm);
+        buf.append(", new Object[]{");
+        for (int i = 0; i < bsmArgs.length; ++i) {
+            appendConstant(bsmArgs[i]);
+            if (i != bsmArgs.length - 1) {
+                buf.append(", ");
+            }
+        }
+        buf.append("});\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitJumpInsn(final int opcode, final Label label) {
+        buf.setLength(0);
+        declareLabel(label);
+        buf.append(name).append(".visitJumpInsn(").append(OPCODES[opcode])
+                .append(", ");
+        appendLabel(label);
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitLabel(final Label label) {
+        buf.setLength(0);
+        declareLabel(label);
+        buf.append(name).append(".visitLabel(");
+        appendLabel(label);
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitLdcInsn(final Object cst) {
+        buf.setLength(0);
+        buf.append(name).append(".visitLdcInsn(");
+        appendConstant(cst);
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitIincInsn(final int var, final int increment) {
+        buf.setLength(0);
+        buf.append(name).append(".visitIincInsn(").append(var).append(", ")
+                .append(increment).append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels) {
+        buf.setLength(0);
+        for (int i = 0; i < labels.length; ++i) {
+            declareLabel(labels[i]);
+        }
+        declareLabel(dflt);
+
+        buf.append(name).append(".visitTableSwitchInsn(").append(min)
+                .append(", ").append(max).append(", ");
+        appendLabel(dflt);
+        buf.append(", new Label[] {");
+        for (int i = 0; i < labels.length; ++i) {
+            buf.append(i == 0 ? " " : ", ");
+            appendLabel(labels[i]);
+        }
+        buf.append(" });\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
+        buf.setLength(0);
+        for (int i = 0; i < labels.length; ++i) {
+            declareLabel(labels[i]);
+        }
+        declareLabel(dflt);
+
+        buf.append(name).append(".visitLookupSwitchInsn(");
+        appendLabel(dflt);
+        buf.append(", new int[] {");
+        for (int i = 0; i < keys.length; ++i) {
+            buf.append(i == 0 ? " " : ", ").append(keys[i]);
+        }
+        buf.append(" }, new Label[] {");
+        for (int i = 0; i < labels.length; ++i) {
+            buf.append(i == 0 ? " " : ", ");
+            appendLabel(labels[i]);
+        }
+        buf.append(" });\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitMultiANewArrayInsn(final String desc, final int dims) {
+        buf.setLength(0);
+        buf.append(name).append(".visitMultiANewArrayInsn(");
+        appendConstant(desc);
+        buf.append(", ").append(dims).append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public ASMifier visitInsnAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        return visitTypeAnnotation("visitInsnAnnotation", typeRef, typePath,
+                desc, visible);
+    }
+
+    @Override
+    public void visitTryCatchBlock(final Label start, final Label end,
+            final Label handler, final String type) {
+        buf.setLength(0);
+        declareLabel(start);
+        declareLabel(end);
+        declareLabel(handler);
+        buf.append(name).append(".visitTryCatchBlock(");
+        appendLabel(start);
+        buf.append(", ");
+        appendLabel(end);
+        buf.append(", ");
+        appendLabel(handler);
+        buf.append(", ");
+        appendConstant(type);
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public ASMifier visitTryCatchAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        return visitTypeAnnotation("visitTryCatchAnnotation", typeRef,
+                typePath, desc, visible);
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
+        buf.setLength(0);
+        buf.append(this.name).append(".visitLocalVariable(");
+        appendConstant(name);
+        buf.append(", ");
+        appendConstant(desc);
+        buf.append(", ");
+        appendConstant(signature);
+        buf.append(", ");
+        appendLabel(start);
+        buf.append(", ");
+        appendLabel(end);
+        buf.append(", ").append(index).append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public Printer visitLocalVariableAnnotation(int typeRef, TypePath typePath,
+            Label[] start, Label[] end, int[] index, String desc,
+            boolean visible) {
+        buf.setLength(0);
+        buf.append("{\n").append("av0 = ").append(name)
+                .append(".visitLocalVariableAnnotation(");
+        buf.append(typeRef);
+        buf.append(", TypePath.fromString(\"").append(typePath).append("\"), ");
+        buf.append("new Label[] {");
+        for (int i = 0; i < start.length; ++i) {
+            buf.append(i == 0 ? " " : ", ");
+            appendLabel(start[i]);
+        }
+        buf.append(" }, new Label[] {");
+        for (int i = 0; i < end.length; ++i) {
+            buf.append(i == 0 ? " " : ", ");
+            appendLabel(end[i]);
+        }
+        buf.append(" }, new int[] {");
+        for (int i = 0; i < index.length; ++i) {
+            buf.append(i == 0 ? " " : ", ").append(index[i]);
+        }
+        buf.append(" }, ");
+        appendConstant(desc);
+        buf.append(", ").append(visible).append(");\n");
+        text.add(buf.toString());
+        ASMifier a = createASMifier("av", 0);
+        text.add(a.getText());
+        text.add("}\n");
+        return a;
+    }
+
+    @Override
+    public void visitLineNumber(final int line, final Label start) {
+        buf.setLength(0);
+        buf.append(name).append(".visitLineNumber(").append(line).append(", ");
+        appendLabel(start);
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitMaxs(final int maxStack, final int maxLocals) {
+        buf.setLength(0);
+        buf.append(name).append(".visitMaxs(").append(maxStack).append(", ")
+                .append(maxLocals).append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitMethodEnd() {
+        buf.setLength(0);
+        buf.append(name).append(".visitEnd();\n");
+        text.add(buf.toString());
+    }
+
+    // ------------------------------------------------------------------------
+    // Common methods
+    // ------------------------------------------------------------------------
+
+    public ASMifier visitAnnotation(final String desc, final boolean visible) {
+        buf.setLength(0);
+        buf.append("{\n").append("av0 = ").append(name)
+                .append(".visitAnnotation(");
+        appendConstant(desc);
+        buf.append(", ").append(visible).append(");\n");
+        text.add(buf.toString());
+        ASMifier a = createASMifier("av", 0);
+        text.add(a.getText());
+        text.add("}\n");
+        return a;
+    }
+
+    public ASMifier visitTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        return visitTypeAnnotation("visitTypeAnnotation", typeRef, typePath,
+                desc, visible);
+    }
+
+    public ASMifier visitTypeAnnotation(final String method, final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        buf.setLength(0);
+        buf.append("{\n").append("av0 = ").append(name).append(".")
+                .append(method).append("(");
+        buf.append(typeRef);
+        buf.append(", TypePath.fromString(\"").append(typePath).append("\"), ");
+        appendConstant(desc);
+        buf.append(", ").append(visible).append(");\n");
+        text.add(buf.toString());
+        ASMifier a = createASMifier("av", 0);
+        text.add(a.getText());
+        text.add("}\n");
+        return a;
+    }
+
+    public void visitAttribute(final Attribute attr) {
+        buf.setLength(0);
+        buf.append("// ATTRIBUTE ").append(attr.type).append('\n');
+        if (attr instanceof ASMifiable) {
+            if (labelNames == null) {
+                labelNames = new HashMap<Label, String>();
+            }
+            buf.append("{\n");
+            ((ASMifiable) attr).asmify(buf, "attr", labelNames);
+            buf.append(name).append(".visitAttribute(attr);\n");
+            buf.append("}\n");
+        }
+        text.add(buf.toString());
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods
+    // ------------------------------------------------------------------------
+
+    protected ASMifier createASMifier(final String name, final int id) {
+        return new ASMifier(Opcodes.ASM5, name, id);
+    }
+
+    /**
+     * Appends a string representation of the given access modifiers to
+     * {@link #buf buf}.
+     * 
+     * @param access
+     *            some access modifiers.
+     */
+    void appendAccess(final int access) {
+        boolean first = true;
+        if ((access & Opcodes.ACC_PUBLIC) != 0) {
+            buf.append("ACC_PUBLIC");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_PRIVATE) != 0) {
+            buf.append("ACC_PRIVATE");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_PROTECTED) != 0) {
+            buf.append("ACC_PROTECTED");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_FINAL) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_FINAL");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_STATIC) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_STATIC");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            if ((access & ACCESS_CLASS) == 0) {
+                buf.append("ACC_SYNCHRONIZED");
+            } else {
+                buf.append("ACC_SUPER");
+            }
+            first = false;
+        }
+        if ((access & Opcodes.ACC_VOLATILE) != 0
+                && (access & ACCESS_FIELD) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_VOLATILE");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_BRIDGE) != 0 && (access & ACCESS_CLASS) == 0
+                && (access & ACCESS_FIELD) == 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_BRIDGE");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_VARARGS) != 0 && (access & ACCESS_CLASS) == 0
+                && (access & ACCESS_FIELD) == 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_VARARGS");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_TRANSIENT) != 0
+                && (access & ACCESS_FIELD) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_TRANSIENT");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_NATIVE) != 0 && (access & ACCESS_CLASS) == 0
+                && (access & ACCESS_FIELD) == 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_NATIVE");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_ENUM) != 0
+                && ((access & ACCESS_CLASS) != 0
+                        || (access & ACCESS_FIELD) != 0 || (access & ACCESS_INNER) != 0)) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_ENUM");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_ANNOTATION) != 0
+                && ((access & ACCESS_CLASS) != 0 || (access & ACCESS_INNER) != 0)) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_ANNOTATION");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_ABSTRACT");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_INTERFACE) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_INTERFACE");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_STRICT) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_STRICT");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_SYNTHETIC");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_DEPRECATED");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_MANDATED) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_MANDATED");
+            first = false;
+        }
+        if (first) {
+            buf.append('0');
+        }
+    }
+
+    /**
+     * Appends a string representation of the given constant to the given
+     * buffer.
+     * 
+     * @param cst
+     *            an {@link Integer}, {@link Float}, {@link Long},
+     *            {@link Double} or {@link String} object. May be <tt>null</tt>.
+     */
+    protected void appendConstant(final Object cst) {
+        appendConstant(buf, cst);
+    }
+
+    /**
+     * Appends a string representation of the given constant to the given
+     * buffer.
+     * 
+     * @param buf
+     *            a string buffer.
+     * @param cst
+     *            an {@link Integer}, {@link Float}, {@link Long},
+     *            {@link Double} or {@link String} object. May be <tt>null</tt>.
+     */
+    static void appendConstant(final StringBuffer buf, final Object cst) {
+        if (cst == null) {
+            buf.append("null");
+        } else if (cst instanceof String) {
+            appendString(buf, (String) cst);
+        } else if (cst instanceof Type) {
+            buf.append("Type.getType(\"");
+            buf.append(((Type) cst).getDescriptor());
+            buf.append("\")");
+        } else if (cst instanceof Handle) {
+            buf.append("new Handle(");
+            Handle h = (Handle) cst;
+            buf.append("Opcodes.").append(HANDLE_TAG[h.getTag()])
+                    .append(", \"");
+            buf.append(h.getOwner()).append("\", \"");
+            buf.append(h.getName()).append("\", \"");
+            buf.append(h.getDesc()).append("\")");
+        } else if (cst instanceof Byte) {
+            buf.append("new Byte((byte)").append(cst).append(')');
+        } else if (cst instanceof Boolean) {
+            buf.append(((Boolean) cst).booleanValue() ? "Boolean.TRUE"
+                    : "Boolean.FALSE");
+        } else if (cst instanceof Short) {
+            buf.append("new Short((short)").append(cst).append(')');
+        } else if (cst instanceof Character) {
+            int c = ((Character) cst).charValue();
+            buf.append("new Character((char)").append(c).append(')');
+        } else if (cst instanceof Integer) {
+            buf.append("new Integer(").append(cst).append(')');
+        } else if (cst instanceof Float) {
+            buf.append("new Float(\"").append(cst).append("\")");
+        } else if (cst instanceof Long) {
+            buf.append("new Long(").append(cst).append("L)");
+        } else if (cst instanceof Double) {
+            buf.append("new Double(\"").append(cst).append("\")");
+        } else if (cst instanceof byte[]) {
+            byte[] v = (byte[]) cst;
+            buf.append("new byte[] {");
+            for (int i = 0; i < v.length; i++) {
+                buf.append(i == 0 ? "" : ",").append(v[i]);
+            }
+            buf.append('}');
+        } else if (cst instanceof boolean[]) {
+            boolean[] v = (boolean[]) cst;
+            buf.append("new boolean[] {");
+            for (int i = 0; i < v.length; i++) {
+                buf.append(i == 0 ? "" : ",").append(v[i]);
+            }
+            buf.append('}');
+        } else if (cst instanceof short[]) {
+            short[] v = (short[]) cst;
+            buf.append("new short[] {");
+            for (int i = 0; i < v.length; i++) {
+                buf.append(i == 0 ? "" : ",").append("(short)").append(v[i]);
+            }
+            buf.append('}');
+        } else if (cst instanceof char[]) {
+            char[] v = (char[]) cst;
+            buf.append("new char[] {");
+            for (int i = 0; i < v.length; i++) {
+                buf.append(i == 0 ? "" : ",").append("(char)")
+                        .append((int) v[i]);
+            }
+            buf.append('}');
+        } else if (cst instanceof int[]) {
+            int[] v = (int[]) cst;
+            buf.append("new int[] {");
+            for (int i = 0; i < v.length; i++) {
+                buf.append(i == 0 ? "" : ",").append(v[i]);
+            }
+            buf.append('}');
+        } else if (cst instanceof long[]) {
+            long[] v = (long[]) cst;
+            buf.append("new long[] {");
+            for (int i = 0; i < v.length; i++) {
+                buf.append(i == 0 ? "" : ",").append(v[i]).append('L');
+            }
+            buf.append('}');
+        } else if (cst instanceof float[]) {
+            float[] v = (float[]) cst;
+            buf.append("new float[] {");
+            for (int i = 0; i < v.length; i++) {
+                buf.append(i == 0 ? "" : ",").append(v[i]).append('f');
+            }
+            buf.append('}');
+        } else if (cst instanceof double[]) {
+            double[] v = (double[]) cst;
+            buf.append("new double[] {");
+            for (int i = 0; i < v.length; i++) {
+                buf.append(i == 0 ? "" : ",").append(v[i]).append('d');
+            }
+            buf.append('}');
+        }
+    }
+
+    private void declareFrameTypes(final int n, final Object[] o) {
+        for (int i = 0; i < n; ++i) {
+            if (o[i] instanceof Label) {
+                declareLabel((Label) o[i]);
+            }
+        }
+    }
+
+    private void appendFrameTypes(final int n, final Object[] o) {
+        for (int i = 0; i < n; ++i) {
+            if (i > 0) {
+                buf.append(", ");
+            }
+            if (o[i] instanceof String) {
+                appendConstant(o[i]);
+            } else if (o[i] instanceof Integer) {
+                switch (((Integer) o[i]).intValue()) {
+                case 0:
+                    buf.append("Opcodes.TOP");
+                    break;
+                case 1:
+                    buf.append("Opcodes.INTEGER");
+                    break;
+                case 2:
+                    buf.append("Opcodes.FLOAT");
+                    break;
+                case 3:
+                    buf.append("Opcodes.DOUBLE");
+                    break;
+                case 4:
+                    buf.append("Opcodes.LONG");
+                    break;
+                case 5:
+                    buf.append("Opcodes.NULL");
+                    break;
+                case 6:
+                    buf.append("Opcodes.UNINITIALIZED_THIS");
+                    break;
+                }
+            } else {
+                appendLabel((Label) o[i]);
+            }
+        }
+    }
+
+    /**
+     * Appends a declaration of the given label to {@link #buf buf}. This
+     * declaration is of the form "Label lXXX = new Label();". Does nothing if
+     * the given label has already been declared.
+     * 
+     * @param l
+     *            a label.
+     */
+    protected void declareLabel(final Label l) {
+        if (labelNames == null) {
+            labelNames = new HashMap<Label, String>();
+        }
+        String name = labelNames.get(l);
+        if (name == null) {
+            name = "l" + labelNames.size();
+            labelNames.put(l, name);
+            buf.append("Label ").append(name).append(" = new Label();\n");
+        }
+    }
+
+    /**
+     * Appends the name of the given label to {@link #buf buf}. The given label
+     * <i>must</i> already have a name. One way to ensure this is to always call
+     * {@link #declareLabel declared} before calling this method.
+     * 
+     * @param l
+     *            a label.
+     */
+    protected void appendLabel(final Label l) {
+        buf.append(labelNames.get(l));
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckAnnotationAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckAnnotationAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckAnnotationAdapter.java
new file mode 100644
index 0000000..56580d1
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckAnnotationAdapter.java
@@ -0,0 +1,136 @@
+/***
+ * 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.util;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * An {@link AnnotationVisitor} that checks that its methods are properly used.
+ * 
+ * @author Eric Bruneton
+ */
+public class CheckAnnotationAdapter extends AnnotationVisitor {
+
+    private final boolean named;
+
+    private boolean end;
+
+    public CheckAnnotationAdapter(final AnnotationVisitor av) {
+        this(av, true);
+    }
+
+    CheckAnnotationAdapter(final AnnotationVisitor av, final boolean named) {
+        super(Opcodes.ASM5, av);
+        this.named = named;
+    }
+
+    @Override
+    public void visit(final String name, final Object value) {
+        checkEnd();
+        checkName(name);
+        if (!(value instanceof Byte || value instanceof Boolean
+                || value instanceof Character || value instanceof Short
+                || value instanceof Integer || value instanceof Long
+                || value instanceof Float || value instanceof Double
+                || value instanceof String || value instanceof Type
+                || value instanceof byte[] || value instanceof boolean[]
+                || value instanceof char[] || value instanceof short[]
+                || value instanceof int[] || value instanceof long[]
+                || value instanceof float[] || value instanceof double[])) {
+            throw new IllegalArgumentException("Invalid annotation value");
+        }
+        if (value instanceof Type) {
+            int sort = ((Type) value).getSort();
+            if (sort == Type.METHOD) {
+                throw new IllegalArgumentException("Invalid annotation value");
+            }
+        }
+        if (av != null) {
+            av.visit(name, value);
+        }
+    }
+
+    @Override
+    public void visitEnum(final String name, final String desc,
+            final String value) {
+        checkEnd();
+        checkName(name);
+        CheckMethodAdapter.checkDesc(desc, false);
+        if (value == null) {
+            throw new IllegalArgumentException("Invalid enum value");
+        }
+        if (av != null) {
+            av.visitEnum(name, desc, value);
+        }
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String name,
+            final String desc) {
+        checkEnd();
+        checkName(name);
+        CheckMethodAdapter.checkDesc(desc, false);
+        return new CheckAnnotationAdapter(av == null ? null
+                : av.visitAnnotation(name, desc));
+    }
+
+    @Override
+    public AnnotationVisitor visitArray(final String name) {
+        checkEnd();
+        checkName(name);
+        return new CheckAnnotationAdapter(av == null ? null
+                : av.visitArray(name), false);
+    }
+
+    @Override
+    public void visitEnd() {
+        checkEnd();
+        end = true;
+        if (av != null) {
+            av.visitEnd();
+        }
+    }
+
+    private void checkEnd() {
+        if (end) {
+            throw new IllegalStateException(
+                    "Cannot call a visit method after visitEnd has been called");
+        }
+    }
+
+    private void checkName(final String name) {
+        if (named && name == null) {
+            throw new IllegalArgumentException(
+                    "Annotation value name must not be null");
+        }
+    }
+}


[16/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
new file mode 100644
index 0000000..c256825
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
@@ -0,0 +1,947 @@
+/***
+ * 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.commons;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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;
+
+/**
+ * A {@link MethodVisitor} that keeps track of stack map frame changes between
+ * {@link #visitFrame(int, int, Object[], int, Object[]) visitFrame} calls. This
+ * adapter must be used with the
+ * {@link org.apache.tapestry5.internal.plastic.asm.ClassReader#EXPAND_FRAMES} option. Each
+ * visit<i>X</i> instruction delegates to the next visitor in the chain, if any,
+ * and then simulates the effect of this instruction on the stack map frame,
+ * represented by {@link #locals} and {@link #stack}. The next visitor in the
+ * chain can get the state of the stack map frame <i>before</i> each instruction
+ * by reading the value of these fields in its visit<i>X</i> methods (this
+ * requires a reference to the AnalyzerAdapter that is before it in the chain).
+ * If this adapter is used with a class that does not contain stack map table
+ * attributes (i.e., pre Java 6 classes) then this adapter may not be able to
+ * compute the stack map frame for each instruction. In this case no exception
+ * is thrown but the {@link #locals} and {@link #stack} fields will be null for
+ * these instructions.
+ * 
+ * @author Eric Bruneton
+ */
+public class AnalyzerAdapter extends MethodVisitor {
+
+    /**
+     * <code>List</code> of the local variable slots for current execution
+     * frame. Primitive types are represented by {@link Opcodes#TOP},
+     * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+     * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
+     * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by
+     * two elements, the second one being TOP). Reference types are represented
+     * by String objects (representing internal names), and uninitialized types
+     * by Label objects (this label designates the NEW instruction that created
+     * this uninitialized value). This field is <tt>null</tt> for unreachable
+     * instructions.
+     */
+    public List<Object> locals;
+
+    /**
+     * <code>List</code> of the operand stack slots for current execution frame.
+     * Primitive types are represented by {@link Opcodes#TOP},
+     * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+     * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
+     * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by
+     * two elements, the second one being TOP). Reference types are represented
+     * by String objects (representing internal names), and uninitialized types
+     * by Label objects (this label designates the NEW instruction that created
+     * this uninitialized value). This field is <tt>null</tt> for unreachable
+     * instructions.
+     */
+    public List<Object> stack;
+
+    /**
+     * The labels that designate the next instruction to be visited. May be
+     * <tt>null</tt>.
+     */
+    private List<Label> labels;
+
+    /**
+     * Information about uninitialized types in the current execution frame.
+     * This map associates internal names to Label objects. Each label
+     * designates a NEW instruction that created the currently uninitialized
+     * types, and the associated internal name represents the NEW operand, i.e.
+     * the final, initialized type value.
+     */
+    public Map<Object, Object> uninitializedTypes;
+
+    /**
+     * The maximum stack size of this method.
+     */
+    private int maxStack;
+
+    /**
+     * The maximum number of local variables of this method.
+     */
+    private int maxLocals;
+
+    /**
+     * The owner's class name.
+     */
+    private String owner;
+
+    /**
+     * Creates a new {@link AnalyzerAdapter}. <i>Subclasses must not use this
+     * constructor</i>. Instead, they must use the
+     * {@link #AnalyzerAdapter(int, String, int, String, String, MethodVisitor)}
+     * version.
+     * 
+     * @param owner
+     *            the owner's class name.
+     * @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}).
+     * @param mv
+     *            the method visitor to which this adapter delegates calls. May
+     *            be <tt>null</tt>.
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public AnalyzerAdapter(final String owner, final int access,
+            final String name, final String desc, final MethodVisitor mv) {
+        this(Opcodes.ASM5, owner, access, name, desc, mv);
+        if (getClass() != AnalyzerAdapter.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Creates a new {@link AnalyzerAdapter}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param owner
+     *            the owner's class name.
+     * @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}).
+     * @param mv
+     *            the method visitor to which this adapter delegates calls. May
+     *            be <tt>null</tt>.
+     */
+    protected AnalyzerAdapter(final int api, final String owner,
+            final int access, final String name, final String desc,
+            final MethodVisitor mv) {
+        super(api, mv);
+        this.owner = owner;
+        locals = new ArrayList<Object>();
+        stack = new ArrayList<Object>();
+        uninitializedTypes = new HashMap<Object, Object>();
+
+        if ((access & Opcodes.ACC_STATIC) == 0) {
+            if ("<init>".equals(name)) {
+                locals.add(Opcodes.UNINITIALIZED_THIS);
+            } else {
+                locals.add(owner);
+            }
+        }
+        Type[] types = Type.getArgumentTypes(desc);
+        for (int i = 0; i < types.length; ++i) {
+            Type type = types[i];
+            switch (type.getSort()) {
+            case Type.BOOLEAN:
+            case Type.CHAR:
+            case Type.BYTE:
+            case Type.SHORT:
+            case Type.INT:
+                locals.add(Opcodes.INTEGER);
+                break;
+            case Type.FLOAT:
+                locals.add(Opcodes.FLOAT);
+                break;
+            case Type.LONG:
+                locals.add(Opcodes.LONG);
+                locals.add(Opcodes.TOP);
+                break;
+            case Type.DOUBLE:
+                locals.add(Opcodes.DOUBLE);
+                locals.add(Opcodes.TOP);
+                break;
+            case Type.ARRAY:
+                locals.add(types[i].getDescriptor());
+                break;
+            // case Type.OBJECT:
+            default:
+                locals.add(types[i].getInternalName());
+            }
+        }
+        maxLocals = locals.size();
+    }
+
+    @Override
+    public void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack) {
+        if (type != Opcodes.F_NEW) { // uncompressed frame
+            throw new IllegalStateException(
+                    "ClassReader.accept() should be called with EXPAND_FRAMES flag");
+        }
+
+        if (mv != null) {
+            mv.visitFrame(type, nLocal, local, nStack, stack);
+        }
+
+        if (this.locals != null) {
+            this.locals.clear();
+            this.stack.clear();
+        } else {
+            this.locals = new ArrayList<Object>();
+            this.stack = new ArrayList<Object>();
+        }
+        visitFrameTypes(nLocal, local, this.locals);
+        visitFrameTypes(nStack, stack, this.stack);
+        maxStack = Math.max(maxStack, this.stack.size());
+    }
+
+    private static void visitFrameTypes(final int n, final Object[] types,
+            final List<Object> result) {
+        for (int i = 0; i < n; ++i) {
+            Object type = types[i];
+            result.add(type);
+            if (type == Opcodes.LONG || type == Opcodes.DOUBLE) {
+                result.add(Opcodes.TOP);
+            }
+        }
+    }
+
+    @Override
+    public void visitInsn(final int opcode) {
+        if (mv != null) {
+            mv.visitInsn(opcode);
+        }
+        execute(opcode, 0, null);
+        if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
+                || opcode == Opcodes.ATHROW) {
+            this.locals = null;
+            this.stack = null;
+        }
+    }
+
+    @Override
+    public void visitIntInsn(final int opcode, final int operand) {
+        if (mv != null) {
+            mv.visitIntInsn(opcode, operand);
+        }
+        execute(opcode, operand, null);
+    }
+
+    @Override
+    public void visitVarInsn(final int opcode, final int var) {
+        if (mv != null) {
+            mv.visitVarInsn(opcode, var);
+        }
+        execute(opcode, var, null);
+    }
+
+    @Override
+    public void visitTypeInsn(final int opcode, final String type) {
+        if (opcode == Opcodes.NEW) {
+            if (labels == null) {
+                Label l = new Label();
+                labels = new ArrayList<Label>(3);
+                labels.add(l);
+                if (mv != null) {
+                    mv.visitLabel(l);
+                }
+            }
+            for (int i = 0; i < labels.size(); ++i) {
+                uninitializedTypes.put(labels.get(i), type);
+            }
+        }
+        if (mv != null) {
+            mv.visitTypeInsn(opcode, type);
+        }
+        execute(opcode, 0, type);
+    }
+
+    @Override
+    public void visitFieldInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (mv != null) {
+            mv.visitFieldInsn(opcode, owner, name, desc);
+        }
+        execute(opcode, 0, desc);
+    }
+
+    @Deprecated
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (api >= Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc,
+                opcode == Opcodes.INVOKEINTERFACE);
+    }
+
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    private void doVisitMethodInsn(int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (mv != null) {
+            mv.visitMethodInsn(opcode, owner, name, desc, itf);
+        }
+        if (this.locals == null) {
+            labels = null;
+            return;
+        }
+        pop(desc);
+        if (opcode != Opcodes.INVOKESTATIC) {
+            Object t = pop();
+            if (opcode == Opcodes.INVOKESPECIAL && name.charAt(0) == '<') {
+                Object u;
+                if (t == Opcodes.UNINITIALIZED_THIS) {
+                    u = this.owner;
+                } else {
+                    u = uninitializedTypes.get(t);
+                }
+                for (int i = 0; i < locals.size(); ++i) {
+                    if (locals.get(i) == t) {
+                        locals.set(i, u);
+                    }
+                }
+                for (int i = 0; i < stack.size(); ++i) {
+                    if (stack.get(i) == t) {
+                        stack.set(i, u);
+                    }
+                }
+            }
+        }
+        pushDesc(desc);
+        labels = null;
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        if (mv != null) {
+            mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+        }
+        if (this.locals == null) {
+            labels = null;
+            return;
+        }
+        pop(desc);
+        pushDesc(desc);
+        labels = null;
+    }
+
+    @Override
+    public void visitJumpInsn(final int opcode, final Label label) {
+        if (mv != null) {
+            mv.visitJumpInsn(opcode, label);
+        }
+        execute(opcode, 0, null);
+        if (opcode == Opcodes.GOTO) {
+            this.locals = null;
+            this.stack = null;
+        }
+    }
+
+    @Override
+    public void visitLabel(final Label label) {
+        if (mv != null) {
+            mv.visitLabel(label);
+        }
+        if (labels == null) {
+            labels = new ArrayList<Label>(3);
+        }
+        labels.add(label);
+    }
+
+    @Override
+    public void visitLdcInsn(final Object cst) {
+        if (mv != null) {
+            mv.visitLdcInsn(cst);
+        }
+        if (this.locals == null) {
+            labels = null;
+            return;
+        }
+        if (cst instanceof Integer) {
+            push(Opcodes.INTEGER);
+        } else if (cst instanceof Long) {
+            push(Opcodes.LONG);
+            push(Opcodes.TOP);
+        } else if (cst instanceof Float) {
+            push(Opcodes.FLOAT);
+        } else if (cst instanceof Double) {
+            push(Opcodes.DOUBLE);
+            push(Opcodes.TOP);
+        } else if (cst instanceof String) {
+            push("java/lang/String");
+        } else if (cst instanceof Type) {
+            int sort = ((Type) cst).getSort();
+            if (sort == Type.OBJECT || sort == Type.ARRAY) {
+                push("java/lang/Class");
+            } else if (sort == Type.METHOD) {
+                push("java/lang/invoke/MethodType");
+            } else {
+                throw new IllegalArgumentException();
+            }
+        } else if (cst instanceof Handle) {
+            push("java/lang/invoke/MethodHandle");
+        } else {
+            throw new IllegalArgumentException();
+        }
+        labels = null;
+    }
+
+    @Override
+    public void visitIincInsn(final int var, final int increment) {
+        if (mv != null) {
+            mv.visitIincInsn(var, increment);
+        }
+        execute(Opcodes.IINC, var, null);
+    }
+
+    @Override
+    public void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels) {
+        if (mv != null) {
+            mv.visitTableSwitchInsn(min, max, dflt, labels);
+        }
+        execute(Opcodes.TABLESWITCH, 0, null);
+        this.locals = null;
+        this.stack = null;
+    }
+
+    @Override
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
+        if (mv != null) {
+            mv.visitLookupSwitchInsn(dflt, keys, labels);
+        }
+        execute(Opcodes.LOOKUPSWITCH, 0, null);
+        this.locals = null;
+        this.stack = null;
+    }
+
+    @Override
+    public void visitMultiANewArrayInsn(final String desc, final int dims) {
+        if (mv != null) {
+            mv.visitMultiANewArrayInsn(desc, dims);
+        }
+        execute(Opcodes.MULTIANEWARRAY, dims, desc);
+    }
+
+    @Override
+    public void visitMaxs(final int maxStack, final int maxLocals) {
+        if (mv != null) {
+            this.maxStack = Math.max(this.maxStack, maxStack);
+            this.maxLocals = Math.max(this.maxLocals, maxLocals);
+            mv.visitMaxs(this.maxStack, this.maxLocals);
+        }
+    }
+
+    // ------------------------------------------------------------------------
+
+    private Object get(final int local) {
+        maxLocals = Math.max(maxLocals, local + 1);
+        return local < locals.size() ? locals.get(local) : Opcodes.TOP;
+    }
+
+    private void set(final int local, final Object type) {
+        maxLocals = Math.max(maxLocals, local + 1);
+        while (local >= locals.size()) {
+            locals.add(Opcodes.TOP);
+        }
+        locals.set(local, type);
+    }
+
+    private void push(final Object type) {
+        stack.add(type);
+        maxStack = Math.max(maxStack, stack.size());
+    }
+
+    private void pushDesc(final String desc) {
+        int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
+        switch (desc.charAt(index)) {
+        case 'V':
+            return;
+        case 'Z':
+        case 'C':
+        case 'B':
+        case 'S':
+        case 'I':
+            push(Opcodes.INTEGER);
+            return;
+        case 'F':
+            push(Opcodes.FLOAT);
+            return;
+        case 'J':
+            push(Opcodes.LONG);
+            push(Opcodes.TOP);
+            return;
+        case 'D':
+            push(Opcodes.DOUBLE);
+            push(Opcodes.TOP);
+            return;
+        case '[':
+            if (index == 0) {
+                push(desc);
+            } else {
+                push(desc.substring(index, desc.length()));
+            }
+            break;
+        // case 'L':
+        default:
+            if (index == 0) {
+                push(desc.substring(1, desc.length() - 1));
+            } else {
+                push(desc.substring(index + 1, desc.length() - 1));
+            }
+        }
+    }
+
+    private Object pop() {
+        return stack.remove(stack.size() - 1);
+    }
+
+    private void pop(final int n) {
+        int size = stack.size();
+        int end = size - n;
+        for (int i = size - 1; i >= end; --i) {
+            stack.remove(i);
+        }
+    }
+
+    private void pop(final String desc) {
+        char c = desc.charAt(0);
+        if (c == '(') {
+            int n = 0;
+            Type[] types = Type.getArgumentTypes(desc);
+            for (int i = 0; i < types.length; ++i) {
+                n += types[i].getSize();
+            }
+            pop(n);
+        } else if (c == 'J' || c == 'D') {
+            pop(2);
+        } else {
+            pop(1);
+        }
+    }
+
+    private void execute(final int opcode, final int iarg, final String sarg) {
+        if (this.locals == null) {
+            labels = null;
+            return;
+        }
+        Object t1, t2, t3, t4;
+        switch (opcode) {
+        case Opcodes.NOP:
+        case Opcodes.INEG:
+        case Opcodes.LNEG:
+        case Opcodes.FNEG:
+        case Opcodes.DNEG:
+        case Opcodes.I2B:
+        case Opcodes.I2C:
+        case Opcodes.I2S:
+        case Opcodes.GOTO:
+        case Opcodes.RETURN:
+            break;
+        case Opcodes.ACONST_NULL:
+            push(Opcodes.NULL);
+            break;
+        case Opcodes.ICONST_M1:
+        case Opcodes.ICONST_0:
+        case Opcodes.ICONST_1:
+        case Opcodes.ICONST_2:
+        case Opcodes.ICONST_3:
+        case Opcodes.ICONST_4:
+        case Opcodes.ICONST_5:
+        case Opcodes.BIPUSH:
+        case Opcodes.SIPUSH:
+            push(Opcodes.INTEGER);
+            break;
+        case Opcodes.LCONST_0:
+        case Opcodes.LCONST_1:
+            push(Opcodes.LONG);
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.FCONST_0:
+        case Opcodes.FCONST_1:
+        case Opcodes.FCONST_2:
+            push(Opcodes.FLOAT);
+            break;
+        case Opcodes.DCONST_0:
+        case Opcodes.DCONST_1:
+            push(Opcodes.DOUBLE);
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.ILOAD:
+        case Opcodes.FLOAD:
+        case Opcodes.ALOAD:
+            push(get(iarg));
+            break;
+        case Opcodes.LLOAD:
+        case Opcodes.DLOAD:
+            push(get(iarg));
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.IALOAD:
+        case Opcodes.BALOAD:
+        case Opcodes.CALOAD:
+        case Opcodes.SALOAD:
+            pop(2);
+            push(Opcodes.INTEGER);
+            break;
+        case Opcodes.LALOAD:
+        case Opcodes.D2L:
+            pop(2);
+            push(Opcodes.LONG);
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.FALOAD:
+            pop(2);
+            push(Opcodes.FLOAT);
+            break;
+        case Opcodes.DALOAD:
+        case Opcodes.L2D:
+            pop(2);
+            push(Opcodes.DOUBLE);
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.AALOAD:
+            pop(1);
+            t1 = pop();
+            if (t1 instanceof String) {
+                pushDesc(((String) t1).substring(1));
+            } else {
+                push("java/lang/Object");
+            }
+            break;
+        case Opcodes.ISTORE:
+        case Opcodes.FSTORE:
+        case Opcodes.ASTORE:
+            t1 = pop();
+            set(iarg, t1);
+            if (iarg > 0) {
+                t2 = get(iarg - 1);
+                if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) {
+                    set(iarg - 1, Opcodes.TOP);
+                }
+            }
+            break;
+        case Opcodes.LSTORE:
+        case Opcodes.DSTORE:
+            pop(1);
+            t1 = pop();
+            set(iarg, t1);
+            set(iarg + 1, Opcodes.TOP);
+            if (iarg > 0) {
+                t2 = get(iarg - 1);
+                if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) {
+                    set(iarg - 1, Opcodes.TOP);
+                }
+            }
+            break;
+        case Opcodes.IASTORE:
+        case Opcodes.BASTORE:
+        case Opcodes.CASTORE:
+        case Opcodes.SASTORE:
+        case Opcodes.FASTORE:
+        case Opcodes.AASTORE:
+            pop(3);
+            break;
+        case Opcodes.LASTORE:
+        case Opcodes.DASTORE:
+            pop(4);
+            break;
+        case Opcodes.POP:
+        case Opcodes.IFEQ:
+        case Opcodes.IFNE:
+        case Opcodes.IFLT:
+        case Opcodes.IFGE:
+        case Opcodes.IFGT:
+        case Opcodes.IFLE:
+        case Opcodes.IRETURN:
+        case Opcodes.FRETURN:
+        case Opcodes.ARETURN:
+        case Opcodes.TABLESWITCH:
+        case Opcodes.LOOKUPSWITCH:
+        case Opcodes.ATHROW:
+        case Opcodes.MONITORENTER:
+        case Opcodes.MONITOREXIT:
+        case Opcodes.IFNULL:
+        case Opcodes.IFNONNULL:
+            pop(1);
+            break;
+        case Opcodes.POP2:
+        case Opcodes.IF_ICMPEQ:
+        case Opcodes.IF_ICMPNE:
+        case Opcodes.IF_ICMPLT:
+        case Opcodes.IF_ICMPGE:
+        case Opcodes.IF_ICMPGT:
+        case Opcodes.IF_ICMPLE:
+        case Opcodes.IF_ACMPEQ:
+        case Opcodes.IF_ACMPNE:
+        case Opcodes.LRETURN:
+        case Opcodes.DRETURN:
+            pop(2);
+            break;
+        case Opcodes.DUP:
+            t1 = pop();
+            push(t1);
+            push(t1);
+            break;
+        case Opcodes.DUP_X1:
+            t1 = pop();
+            t2 = pop();
+            push(t1);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.DUP_X2:
+            t1 = pop();
+            t2 = pop();
+            t3 = pop();
+            push(t1);
+            push(t3);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.DUP2:
+            t1 = pop();
+            t2 = pop();
+            push(t2);
+            push(t1);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.DUP2_X1:
+            t1 = pop();
+            t2 = pop();
+            t3 = pop();
+            push(t2);
+            push(t1);
+            push(t3);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.DUP2_X2:
+            t1 = pop();
+            t2 = pop();
+            t3 = pop();
+            t4 = pop();
+            push(t2);
+            push(t1);
+            push(t4);
+            push(t3);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.SWAP:
+            t1 = pop();
+            t2 = pop();
+            push(t1);
+            push(t2);
+            break;
+        case Opcodes.IADD:
+        case Opcodes.ISUB:
+        case Opcodes.IMUL:
+        case Opcodes.IDIV:
+        case Opcodes.IREM:
+        case Opcodes.IAND:
+        case Opcodes.IOR:
+        case Opcodes.IXOR:
+        case Opcodes.ISHL:
+        case Opcodes.ISHR:
+        case Opcodes.IUSHR:
+        case Opcodes.L2I:
+        case Opcodes.D2I:
+        case Opcodes.FCMPL:
+        case Opcodes.FCMPG:
+            pop(2);
+            push(Opcodes.INTEGER);
+            break;
+        case Opcodes.LADD:
+        case Opcodes.LSUB:
+        case Opcodes.LMUL:
+        case Opcodes.LDIV:
+        case Opcodes.LREM:
+        case Opcodes.LAND:
+        case Opcodes.LOR:
+        case Opcodes.LXOR:
+            pop(4);
+            push(Opcodes.LONG);
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.FADD:
+        case Opcodes.FSUB:
+        case Opcodes.FMUL:
+        case Opcodes.FDIV:
+        case Opcodes.FREM:
+        case Opcodes.L2F:
+        case Opcodes.D2F:
+            pop(2);
+            push(Opcodes.FLOAT);
+            break;
+        case Opcodes.DADD:
+        case Opcodes.DSUB:
+        case Opcodes.DMUL:
+        case Opcodes.DDIV:
+        case Opcodes.DREM:
+            pop(4);
+            push(Opcodes.DOUBLE);
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.LSHL:
+        case Opcodes.LSHR:
+        case Opcodes.LUSHR:
+            pop(3);
+            push(Opcodes.LONG);
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.IINC:
+            set(iarg, Opcodes.INTEGER);
+            break;
+        case Opcodes.I2L:
+        case Opcodes.F2L:
+            pop(1);
+            push(Opcodes.LONG);
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.I2F:
+            pop(1);
+            push(Opcodes.FLOAT);
+            break;
+        case Opcodes.I2D:
+        case Opcodes.F2D:
+            pop(1);
+            push(Opcodes.DOUBLE);
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.F2I:
+        case Opcodes.ARRAYLENGTH:
+        case Opcodes.INSTANCEOF:
+            pop(1);
+            push(Opcodes.INTEGER);
+            break;
+        case Opcodes.LCMP:
+        case Opcodes.DCMPL:
+        case Opcodes.DCMPG:
+            pop(4);
+            push(Opcodes.INTEGER);
+            break;
+        case Opcodes.JSR:
+        case Opcodes.RET:
+            throw new RuntimeException("JSR/RET are not supported");
+        case Opcodes.GETSTATIC:
+            pushDesc(sarg);
+            break;
+        case Opcodes.PUTSTATIC:
+            pop(sarg);
+            break;
+        case Opcodes.GETFIELD:
+            pop(1);
+            pushDesc(sarg);
+            break;
+        case Opcodes.PUTFIELD:
+            pop(sarg);
+            pop();
+            break;
+        case Opcodes.NEW:
+            push(labels.get(0));
+            break;
+        case Opcodes.NEWARRAY:
+            pop();
+            switch (iarg) {
+            case Opcodes.T_BOOLEAN:
+                pushDesc("[Z");
+                break;
+            case Opcodes.T_CHAR:
+                pushDesc("[C");
+                break;
+            case Opcodes.T_BYTE:
+                pushDesc("[B");
+                break;
+            case Opcodes.T_SHORT:
+                pushDesc("[S");
+                break;
+            case Opcodes.T_INT:
+                pushDesc("[I");
+                break;
+            case Opcodes.T_FLOAT:
+                pushDesc("[F");
+                break;
+            case Opcodes.T_DOUBLE:
+                pushDesc("[D");
+                break;
+            // case Opcodes.T_LONG:
+            default:
+                pushDesc("[J");
+                break;
+            }
+            break;
+        case Opcodes.ANEWARRAY:
+            pop();
+            pushDesc("[" + Type.getObjectType(sarg));
+            break;
+        case Opcodes.CHECKCAST:
+            pop();
+            pushDesc(Type.getObjectType(sarg).getDescriptor());
+            break;
+        // case Opcodes.MULTIANEWARRAY:
+        default:
+            pop(iarg);
+            pushDesc(sarg);
+            break;
+        }
+        labels = null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java
new file mode 100644
index 0000000..d146a36
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java
@@ -0,0 +1,238 @@
+/***
+ * 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.commons;
+
+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;
+
+/**
+ * A {@link MethodVisitor} that can be used to approximate method size.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class CodeSizeEvaluator extends MethodVisitor implements Opcodes {
+
+    private int minSize;
+
+    private int maxSize;
+
+    public CodeSizeEvaluator(final MethodVisitor mv) {
+        this(Opcodes.ASM5, mv);
+    }
+
+    protected CodeSizeEvaluator(final int api, final MethodVisitor mv) {
+        super(api, mv);
+    }
+
+    public int getMinSize() {
+        return this.minSize;
+    }
+
+    public int getMaxSize() {
+        return this.maxSize;
+    }
+
+    @Override
+    public void visitInsn(final int opcode) {
+        minSize += 1;
+        maxSize += 1;
+        if (mv != null) {
+            mv.visitInsn(opcode);
+        }
+    }
+
+    @Override
+    public void visitIntInsn(final int opcode, final int operand) {
+        if (opcode == SIPUSH) {
+            minSize += 3;
+            maxSize += 3;
+        } else {
+            minSize += 2;
+            maxSize += 2;
+        }
+        if (mv != null) {
+            mv.visitIntInsn(opcode, operand);
+        }
+    }
+
+    @Override
+    public void visitVarInsn(final int opcode, final int var) {
+        if (var < 4 && opcode != RET) {
+            minSize += 1;
+            maxSize += 1;
+        } else if (var >= 256) {
+            minSize += 4;
+            maxSize += 4;
+        } else {
+            minSize += 2;
+            maxSize += 2;
+        }
+        if (mv != null) {
+            mv.visitVarInsn(opcode, var);
+        }
+    }
+
+    @Override
+    public void visitTypeInsn(final int opcode, final String type) {
+        minSize += 3;
+        maxSize += 3;
+        if (mv != null) {
+            mv.visitTypeInsn(opcode, type);
+        }
+    }
+
+    @Override
+    public void visitFieldInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        minSize += 3;
+        maxSize += 3;
+        if (mv != null) {
+            mv.visitFieldInsn(opcode, owner, name, desc);
+        }
+    }
+
+    @Deprecated
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (api >= Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc,
+                opcode == Opcodes.INVOKEINTERFACE);
+    }
+
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    private void doVisitMethodInsn(int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (opcode == INVOKEINTERFACE) {
+            minSize += 5;
+            maxSize += 5;
+        } else {
+            minSize += 3;
+            maxSize += 3;
+        }
+        if (mv != null) {
+            mv.visitMethodInsn(opcode, owner, name, desc, itf);
+        }
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        minSize += 5;
+        maxSize += 5;
+        if (mv != null) {
+            mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+        }
+    }
+
+    @Override
+    public void visitJumpInsn(final int opcode, final Label label) {
+        minSize += 3;
+        if (opcode == GOTO || opcode == JSR) {
+            maxSize += 5;
+        } else {
+            maxSize += 8;
+        }
+        if (mv != null) {
+            mv.visitJumpInsn(opcode, label);
+        }
+    }
+
+    @Override
+    public void visitLdcInsn(final Object cst) {
+        if (cst instanceof Long || cst instanceof Double) {
+            minSize += 3;
+            maxSize += 3;
+        } else {
+            minSize += 2;
+            maxSize += 3;
+        }
+        if (mv != null) {
+            mv.visitLdcInsn(cst);
+        }
+    }
+
+    @Override
+    public void visitIincInsn(final int var, final int increment) {
+        if (var > 255 || increment > 127 || increment < -128) {
+            minSize += 6;
+            maxSize += 6;
+        } else {
+            minSize += 3;
+            maxSize += 3;
+        }
+        if (mv != null) {
+            mv.visitIincInsn(var, increment);
+        }
+    }
+
+    @Override
+    public void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels) {
+        minSize += 13 + labels.length * 4;
+        maxSize += 16 + labels.length * 4;
+        if (mv != null) {
+            mv.visitTableSwitchInsn(min, max, dflt, labels);
+        }
+    }
+
+    @Override
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
+        minSize += 9 + keys.length * 8;
+        maxSize += 12 + keys.length * 8;
+        if (mv != null) {
+            mv.visitLookupSwitchInsn(dflt, keys, labels);
+        }
+    }
+
+    @Override
+    public void visitMultiANewArrayInsn(final String desc, final int dims) {
+        minSize += 4;
+        maxSize += 4;
+        if (mv != null) {
+            mv.visitMultiANewArrayInsn(desc, dims);
+        }
+    }
+}


[22/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
index 4801b61..4b9c65e 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
@@ -37,7 +37,7 @@ import java.io.InputStream;
  * This class parses a byte array conforming to the Java class file format and
  * calls the appropriate visit methods of a given class visitor for each field,
  * method and bytecode instruction encountered.
- *
+ * 
  * @author Eric Bruneton
  * @author Eugene Kuleshov
  */
@@ -112,9 +112,8 @@ public class ClassReader {
     public final byte[] b;
 
     /**
-     * The start index of each constant pool item in {@link #b b}, plus one.
-     * The one byte offset skips the constant pool item tag that indicates its
-     * type.
+     * The start index of each constant pool item in {@link #b b}, plus one. The
+     * one byte offset skips the constant pool item tag that indicates its type.
      */
     private final int[] items;
 
@@ -146,8 +145,9 @@ public class ClassReader {
 
     /**
      * Constructs a new {@link ClassReader} object.
-     *
-     * @param b the bytecode of the class to be read.
+     * 
+     * @param b
+     *            the bytecode of the class to be read.
      */
     public ClassReader(final byte[] b) {
         this(b, 0, b.length);
@@ -155,15 +155,18 @@ public class ClassReader {
 
     /**
      * Constructs a new {@link ClassReader} object.
-     *
-     * @param b the bytecode of the class to be read.
-     * @param off the start offset of the class data.
-     * @param len the length of the class data.
+     * 
+     * @param b
+     *            the bytecode of the class to be read.
+     * @param off
+     *            the start offset of the class data.
+     * @param len
+     *            the length of the class data.
      */
     public ClassReader(final byte[] b, final int off, final int len) {
         this.b = b;
         // checks the class version
-        if (readShort(6) > Opcodes.V1_7) {
+        if (readShort(off + 6) > Opcodes.V1_8) {
             throw new IllegalArgumentException();
         }
         // parses the constant pool
@@ -176,35 +179,35 @@ public class ClassReader {
             items[i] = index + 1;
             int size;
             switch (b[index]) {
-                case ClassWriter.FIELD:
-                case ClassWriter.METH:
-                case ClassWriter.IMETH:
-                case ClassWriter.INT:
-                case ClassWriter.FLOAT:
-                case ClassWriter.NAME_TYPE:
-                case ClassWriter.INDY:
-                    size = 5;
-                    break;
-                case ClassWriter.LONG:
-                case ClassWriter.DOUBLE:
-                    size = 9;
-                    ++i;
-                    break;
-                case ClassWriter.UTF8:
-                    size = 3 + readUnsignedShort(index + 1);
-                    if (size > max) {
-                        max = size;
-                    }
-                    break;
-                case ClassWriter.HANDLE:
-                    size = 4;
-                    break;
-                // case ClassWriter.CLASS:
-                // case ClassWriter.STR:
-                // case ClassWriter.MTYPE
-                default:
-                    size = 3;
-                    break;
+            case ClassWriter.FIELD:
+            case ClassWriter.METH:
+            case ClassWriter.IMETH:
+            case ClassWriter.INT:
+            case ClassWriter.FLOAT:
+            case ClassWriter.NAME_TYPE:
+            case ClassWriter.INDY:
+                size = 5;
+                break;
+            case ClassWriter.LONG:
+            case ClassWriter.DOUBLE:
+                size = 9;
+                ++i;
+                break;
+            case ClassWriter.UTF8:
+                size = 3 + readUnsignedShort(index + 1);
+                if (size > max) {
+                    max = size;
+                }
+                break;
+            case ClassWriter.HANDLE:
+                size = 4;
+                break;
+            // case ClassWriter.CLASS:
+            // case ClassWriter.STR:
+            // case ClassWriter.MTYPE
+            default:
+                size = 3;
+                break;
             }
             index += size;
         }
@@ -217,9 +220,9 @@ public class ClassReader {
      * Returns the class's access flags (see {@link Opcodes}). This value may
      * not reflect Deprecated and Synthetic flags when bytecode is before 1.5
      * and those flags are represented by attributes.
-     *
+     * 
      * @return the class access flags
-     *
+     * 
      * @see ClassVisitor#visit(int, int, String, String, String, String[])
      */
     public int getAccess() {
@@ -229,9 +232,9 @@ public class ClassReader {
     /**
      * Returns the internal name of the class (see
      * {@link Type#getInternalName() getInternalName}).
-     *
+     * 
      * @return the internal class name
-     *
+     * 
      * @see ClassVisitor#visit(int, int, String, String, String, String[])
      */
     public String getClassName() {
@@ -242,24 +245,23 @@ public class ClassReader {
      * Returns the internal of name of the super class (see
      * {@link Type#getInternalName() getInternalName}). For interfaces, the
      * super class is {@link Object}.
-     *
+     * 
      * @return the internal name of super class, or <tt>null</tt> for
      *         {@link Object} class.
-     *
+     * 
      * @see ClassVisitor#visit(int, int, String, String, String, String[])
      */
     public String getSuperName() {
-        int n = items[readUnsignedShort(header + 4)];
-        return n == 0 ? null : readUTF8(n, new char[maxStringLength]);
+        return readClass(header + 4, new char[maxStringLength]);
     }
 
     /**
      * Returns the internal names of the class's interfaces (see
      * {@link Type#getInternalName() getInternalName}).
-     *
+     * 
      * @return the array of internal names for all implemented interfaces or
      *         <tt>null</tt>.
-     *
+     * 
      * @see ClassVisitor#visit(int, int, String, String, String, String[])
      */
     public String[] getInterfaces() {
@@ -279,8 +281,9 @@ public class ClassReader {
     /**
      * Copies the constant pool data into the given {@link ClassWriter}. Should
      * be called before the {@link #accept(ClassVisitor,int)} method.
-     *
-     * @param classWriter the {@link ClassWriter} to copy constant pool into.
+     * 
+     * @param classWriter
+     *            the {@link ClassWriter} to copy constant pool into.
      */
     void copyPool(final ClassWriter classWriter) {
         char[] buf = new char[maxStringLength];
@@ -292,82 +295,63 @@ public class ClassReader {
             Item item = new Item(i);
             int nameType;
             switch (tag) {
-                case ClassWriter.FIELD:
-                case ClassWriter.METH:
-                case ClassWriter.IMETH:
-                    nameType = items[readUnsignedShort(index + 2)];
-                    item.set(tag,
-                            readClass(index, buf),
-                            readUTF8(nameType, buf),
-                            readUTF8(nameType + 2, buf));
-                    break;
-
-                case ClassWriter.INT:
-                    item.set(readInt(index));
-                    break;
-
-                case ClassWriter.FLOAT:
-                    item.set(Float.intBitsToFloat(readInt(index)));
-                    break;
-
-                case ClassWriter.NAME_TYPE:
-                    item.set(tag,
-                            readUTF8(index, buf),
-                            readUTF8(index + 2, buf),
-                            null);
-                    break;
-
-                case ClassWriter.LONG:
-                    item.set(readLong(index));
-                    ++i;
-                    break;
-
-                case ClassWriter.DOUBLE:
-                    item.set(Double.longBitsToDouble(readLong(index)));
-                    ++i;
-                    break;
-
-                case ClassWriter.UTF8: {
-                    String s = strings[i];
-                    if (s == null) {
-                        index = items[i];
-                        s = strings[i] = readUTF(index + 2,
-                                readUnsignedShort(index),
-                                buf);
-                    }
-                    item.set(tag, s, null, null);
+            case ClassWriter.FIELD:
+            case ClassWriter.METH:
+            case ClassWriter.IMETH:
+                nameType = items[readUnsignedShort(index + 2)];
+                item.set(tag, readClass(index, buf), readUTF8(nameType, buf),
+                        readUTF8(nameType + 2, buf));
+                break;
+            case ClassWriter.INT:
+                item.set(readInt(index));
+                break;
+            case ClassWriter.FLOAT:
+                item.set(Float.intBitsToFloat(readInt(index)));
+                break;
+            case ClassWriter.NAME_TYPE:
+                item.set(tag, readUTF8(index, buf), readUTF8(index + 2, buf),
+                        null);
+                break;
+            case ClassWriter.LONG:
+                item.set(readLong(index));
+                ++i;
+                break;
+            case ClassWriter.DOUBLE:
+                item.set(Double.longBitsToDouble(readLong(index)));
+                ++i;
+                break;
+            case ClassWriter.UTF8: {
+                String s = strings[i];
+                if (s == null) {
+                    index = items[i];
+                    s = strings[i] = readUTF(index + 2,
+                            readUnsignedShort(index), buf);
                 }
-                    break;
-
-                case ClassWriter.HANDLE: {
-                    int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
-                    nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
-                    item.set(ClassWriter.HANDLE_BASE + readByte(index),
-                            readClass(fieldOrMethodRef, buf),
-                            readUTF8(nameType, buf),
-                            readUTF8(nameType + 2, buf));
-
+                item.set(tag, s, null, null);
+                break;
+            }
+            case ClassWriter.HANDLE: {
+                int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
+                nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
+                item.set(ClassWriter.HANDLE_BASE + readByte(index),
+                        readClass(fieldOrMethodRef, buf),
+                        readUTF8(nameType, buf), readUTF8(nameType + 2, buf));
+                break;
+            }
+            case ClassWriter.INDY:
+                if (classWriter.bootstrapMethods == null) {
+                    copyBootstrapMethods(classWriter, items2, buf);
                 }
-                    break;
-
-
-                case ClassWriter.INDY:
-                    if (classWriter.bootstrapMethods == null) {
-                        copyBootstrapMethods(classWriter, items2, buf);
-                    }
-                    nameType = items[readUnsignedShort(index + 2)];
-                    item.set(readUTF8(nameType, buf),
-                            readUTF8(nameType + 2, buf),
-                            readUnsignedShort(index));
-                    break;
-
-
-                // case ClassWriter.STR:
-                // case ClassWriter.CLASS:
-                // case ClassWriter.MTYPE
-                default:
-                    item.set(tag, readUTF8(index, buf), null, null);
-                    break;
+                nameType = items[readUnsignedShort(index + 2)];
+                item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf),
+                        readUnsignedShort(index));
+                break;
+            // case ClassWriter.STR:
+            // case ClassWriter.CLASS:
+            // case ClassWriter.MTYPE
+            default:
+                item.set(tag, readUTF8(index, buf), null, null);
+                break;
             }
 
             int index2 = item.hashCode % items2.length;
@@ -382,77 +366,59 @@ public class ClassReader {
         classWriter.index = ll;
     }
 
-    private void copyBootstrapMethods(ClassWriter classWriter, Item[] items2, char[] buf) {
-        int i, j, k, u, v;
-
-        // skip class header
-        v = header;
-        v += 8 + (readUnsignedShort(v + 6) << 1);
-
-        // skips fields and methods
-        i = readUnsignedShort(v);
-        v += 2;
-        for (; i > 0; --i) {
-            j = readUnsignedShort(v + 6);
-            v += 8;
-            for (; j > 0; --j) {
-                v += 6 + readInt(v + 2);
+    /**
+     * Copies the bootstrap method data into the given {@link ClassWriter}.
+     * Should be called before the {@link #accept(ClassVisitor,int)} method.
+     * 
+     * @param classWriter
+     *            the {@link ClassWriter} to copy bootstrap methods into.
+     */
+    private void copyBootstrapMethods(final ClassWriter classWriter,
+            final Item[] items, final char[] c) {
+        // finds the "BootstrapMethods" attribute
+        int u = getAttributes();
+        boolean found = false;
+        for (int i = readUnsignedShort(u); i > 0; --i) {
+            String attrName = readUTF8(u + 2, c);
+            if ("BootstrapMethods".equals(attrName)) {
+                found = true;
+                break;
             }
+            u += 6 + readInt(u + 4);
         }
-        i = readUnsignedShort(v);
-        v += 2;
-        for (; i > 0; --i) {
-            j = readUnsignedShort(v + 6);
-            v += 8;
-            for (; j > 0; --j) {
-                v += 6 + readInt(v + 2);
-            }
+        if (!found) {
+            return;
         }
-
-        // read class attributes
-        i = readUnsignedShort(v);
-        v += 2;
-        for (; i > 0; --i) {
-            String attrName = readUTF8(v, buf);
-            int size = readInt(v + 2);
-            if ("BootstrapMethods".equals(attrName)) {
-                int boostrapMethodCount = readUnsignedShort(v + 6);
-                int x = v + 8;
-                for (j = 0; j < boostrapMethodCount; j++) {
-                    int hashCode = readConst(readUnsignedShort(x), buf).hashCode();
-                    k = readUnsignedShort(x + 2);
-                    u = x + 4;
-                    for(; k > 0; --k) {
-                        hashCode ^= readConst(readUnsignedShort(u), buf).hashCode();
-                        u += 2;
-                    }
-                    Item item = new Item(j);
-                    item.set(x - v - 8, hashCode & 0x7FFFFFFF);
-
-                    int index2 = item.hashCode % items2.length;
-                    item.next = items2[index2];
-                    items2[index2] = item;
-
-                    x = u;
-                }
-
-                classWriter.bootstrapMethodsCount = boostrapMethodCount;
-                ByteVector bootstrapMethods = new ByteVector(size + 62);
-                bootstrapMethods.putByteArray(b, v + 8, size - 2);
-                classWriter.bootstrapMethods = bootstrapMethods;
-                return;
+        // copies the bootstrap methods in the class writer
+        int boostrapMethodCount = readUnsignedShort(u + 8);
+        for (int j = 0, v = u + 10; j < boostrapMethodCount; j++) {
+            int position = v - u - 10;
+            int hashCode = readConst(readUnsignedShort(v), c).hashCode();
+            for (int k = readUnsignedShort(v + 2); k > 0; --k) {
+                hashCode ^= readConst(readUnsignedShort(v + 4), c).hashCode();
+                v += 2;
             }
-            v += 6 + size;
+            v += 4;
+            Item item = new Item(j);
+            item.set(position, hashCode & 0x7FFFFFFF);
+            int index = item.hashCode % items.length;
+            item.next = items[index];
+            items[index] = item;
         }
-
-        // we are in trouble !!!
+        int attrSize = readInt(u + 4);
+        ByteVector bootstrapMethods = new ByteVector(attrSize + 62);
+        bootstrapMethods.putByteArray(b, u + 10, attrSize - 2);
+        classWriter.bootstrapMethodsCount = boostrapMethodCount;
+        classWriter.bootstrapMethods = bootstrapMethods;
     }
 
     /**
      * Constructs a new {@link ClassReader} object.
-     *
-     * @param is an input stream from which to read the class.
-     * @throws IOException if a problem occurs during reading.
+     * 
+     * @param is
+     *            an input stream from which to read the class.
+     * @throws IOException
+     *             if a problem occurs during reading.
      */
     public ClassReader(final InputStream is) throws IOException {
         this(readClass(is, false));
@@ -460,26 +426,31 @@ public class ClassReader {
 
     /**
      * Constructs a new {@link ClassReader} object.
-     *
-     * @param name the binary qualified name of the class to be read.
-     * @throws IOException if an exception occurs during reading.
+     * 
+     * @param name
+     *            the binary qualified name of the class to be read.
+     * @throws IOException
+     *             if an exception occurs during reading.
      */
     public ClassReader(final String name) throws IOException {
-        this(readClass(ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
-                + ".class"), true));
+        this(readClass(
+                ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
+                        + ".class"), true));
     }
 
     /**
      * Reads the bytecode of a class.
-     *
-     * @param is an input stream from which to read the class.
-     * @param close true to close the input stream after reading.
+     * 
+     * @param is
+     *            an input stream from which to read the class.
+     * @param close
+     *            true to close the input stream after reading.
      * @return the bytecode read from the given input stream.
-     * @throws IOException if a problem occurs during reading.
+     * @throws IOException
+     *             if a problem occurs during reading.
      */
     private static byte[] readClass(final InputStream is, boolean close)
-            throws IOException
-    {
+            throws IOException {
         if (is == null) {
             throw new IOException("Class not found");
         }
@@ -520,14 +491,16 @@ public class ClassReader {
     // ------------------------------------------------------------------------
 
     /**
-     * Makes the given visitor visit the Java class of this {@link ClassReader}.
-     * This class is the one specified in the constructor (see
+     * Makes the given visitor visit the Java class of this {@link ClassReader}
+     * . This class is the one specified in the constructor (see
      * {@link #ClassReader(byte[]) ClassReader}).
-     *
-     * @param classVisitor the visitor that must visit this class.
-     * @param flags option flags that can be used to modify the default behavior
-     *        of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
-     *        {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+     * 
+     * @param classVisitor
+     *            the visitor that must visit this class.
+     * @param flags
+     *            option flags that can be used to modify the default behavior
+     *            of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}
+     *            , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
      */
     public void accept(final ClassVisitor classVisitor, final int flags) {
         accept(classVisitor, new Attribute[0], flags);
@@ -537,1118 +510,1220 @@ public class ClassReader {
      * Makes the given visitor visit the Java class of this {@link ClassReader}.
      * This class is the one specified in the constructor (see
      * {@link #ClassReader(byte[]) ClassReader}).
-     *
-     * @param classVisitor the visitor that must visit this class.
-     * @param attrs prototypes of the attributes that must be parsed during the
-     *        visit of the class. Any attribute whose type is not equal to the
-     *        type of one the prototypes will not be parsed: its byte array
-     *        value will be passed unchanged to the ClassWriter. <i>This may
-     *        corrupt it if this value contains references to the constant pool,
-     *        or has syntactic or semantic links with a class element that has
-     *        been transformed by a class adapter between the reader and the
-     *        writer</i>.
-     * @param flags option flags that can be used to modify the default behavior
-     *        of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
-     *        {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+     * 
+     * @param classVisitor
+     *            the visitor that must visit this class.
+     * @param attrs
+     *            prototypes of the attributes that must be parsed during the
+     *            visit of the class. Any attribute whose type is not equal to
+     *            the type of one the prototypes will not be parsed: its byte
+     *            array value will be passed unchanged to the ClassWriter.
+     *            <i>This may corrupt it if this value contains references to
+     *            the constant pool, or has syntactic or semantic links with a
+     *            class element that has been transformed by a class adapter
+     *            between the reader and the writer</i>.
+     * @param flags
+     *            option flags that can be used to modify the default behavior
+     *            of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}
+     *            , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
      */
-    public void accept(
-        final ClassVisitor classVisitor,
-        final Attribute[] attrs,
-        final int flags)
-    {
-        byte[] b = this.b; // the bytecode array
+    public void accept(final ClassVisitor classVisitor,
+            final Attribute[] attrs, final int flags) {
+        int u = header; // current offset in the class file
         char[] c = new char[maxStringLength]; // buffer used to read strings
-        int i, j, k; // loop variables
-        int u, v, w; // indexes in b
-        Attribute attr;
-
-        int access;
-        String name;
-        String desc;
-        String attrName;
-        String signature;
-        int anns = 0;
-        int ianns = 0;
-        Attribute cattrs = null;
-
-        // visits the header
-        u = header;
-        access = readUnsignedShort(u);
-        name = readClass(u + 2, c);
-        v = items[readUnsignedShort(u + 4)];
-        String superClassName = v == 0 ? null : readUTF8(v, c);
-        String[] implementedItfs = new String[readUnsignedShort(u + 6)];
-        w = 0;
+
+        Context context = new Context();
+        context.attrs = attrs;
+        context.flags = flags;
+        context.buffer = c;
+
+        // reads the class declaration
+        int access = readUnsignedShort(u);
+        String name = readClass(u + 2, c);
+        String superClass = readClass(u + 4, c);
+        String[] interfaces = new String[readUnsignedShort(u + 6)];
         u += 8;
-        for (i = 0; i < implementedItfs.length; ++i) {
-            implementedItfs[i] = readClass(u, c);
+        for (int i = 0; i < interfaces.length; ++i) {
+            interfaces[i] = readClass(u, c);
             u += 2;
         }
 
-        boolean skipCode = (flags & SKIP_CODE) != 0;
-        boolean skipDebug = (flags & SKIP_DEBUG) != 0;
-        boolean unzip = (flags & EXPAND_FRAMES) != 0;
-
-        // skips fields and methods
-        v = u;
-        i = readUnsignedShort(v);
-        v += 2;
-        for (; i > 0; --i) {
-            j = readUnsignedShort(v + 6);
-            v += 8;
-            for (; j > 0; --j) {
-                v += 6 + readInt(v + 2);
-            }
-        }
-        i = readUnsignedShort(v);
-        v += 2;
-        for (; i > 0; --i) {
-            j = readUnsignedShort(v + 6);
-            v += 8;
-            for (; j > 0; --j) {
-                v += 6 + readInt(v + 2);
-            }
-        }
-        // reads the class's attributes
-        signature = null;
+        // reads the class attributes
+        String signature = null;
         String sourceFile = null;
         String sourceDebug = null;
         String enclosingOwner = null;
         String enclosingName = null;
         String enclosingDesc = null;
-        int[] bootstrapMethods = null;  // start indexed of the bsms
-
-        i = readUnsignedShort(v);
-        v += 2;
-        for (; i > 0; --i) {
-            attrName = readUTF8(v, c);
+        int anns = 0;
+        int ianns = 0;
+        int tanns = 0;
+        int itanns = 0;
+        int innerClasses = 0;
+        Attribute attributes = null;
+
+        u = getAttributes();
+        for (int i = readUnsignedShort(u); i > 0; --i) {
+            String attrName = readUTF8(u + 2, c);
             // tests are sorted in decreasing frequency order
             // (based on frequencies observed on typical classes)
             if ("SourceFile".equals(attrName)) {
-                sourceFile = readUTF8(v + 6, c);
+                sourceFile = readUTF8(u + 8, c);
             } else if ("InnerClasses".equals(attrName)) {
-                w = v + 6;
+                innerClasses = u + 8;
             } else if ("EnclosingMethod".equals(attrName)) {
-                enclosingOwner = readClass(v + 6, c);
-                int item = readUnsignedShort(v + 8);
+                enclosingOwner = readClass(u + 8, c);
+                int item = readUnsignedShort(u + 10);
                 if (item != 0) {
                     enclosingName = readUTF8(items[item], c);
                     enclosingDesc = readUTF8(items[item] + 2, c);
                 }
             } else if (SIGNATURES && "Signature".equals(attrName)) {
-                signature = readUTF8(v + 6, c);
-            } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
-                anns = v + 6;
+                signature = readUTF8(u + 8, c);
+            } else if (ANNOTATIONS
+                    && "RuntimeVisibleAnnotations".equals(attrName)) {
+                anns = u + 8;
+            } else if (ANNOTATIONS
+                    && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+                tanns = u + 8;
             } else if ("Deprecated".equals(attrName)) {
                 access |= Opcodes.ACC_DEPRECATED;
             } else if ("Synthetic".equals(attrName)) {
-                access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+                access |= Opcodes.ACC_SYNTHETIC
+                        | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
             } else if ("SourceDebugExtension".equals(attrName)) {
-                int len = readInt(v + 2);
-                sourceDebug = readUTF(v + 6, len, new char[len]);
-            } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
-                ianns = v + 6;
+                int len = readInt(u + 4);
+                sourceDebug = readUTF(u + 8, len, new char[len]);
+            } else if (ANNOTATIONS
+                    && "RuntimeInvisibleAnnotations".equals(attrName)) {
+                ianns = u + 8;
+            } else if (ANNOTATIONS
+                    && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+                itanns = u + 8;
             } else if ("BootstrapMethods".equals(attrName)) {
-                int boostrapMethodCount = readUnsignedShort(v + 6);
-                bootstrapMethods = new int[boostrapMethodCount];
-                int x = v + 8;
-                for (j = 0; j < boostrapMethodCount; j++) {
-                    bootstrapMethods[j] = x;
-                    x += 2 + readUnsignedShort(x + 2) << 1;
+                int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
+                for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
+                    bootstrapMethods[j] = v;
+                    v += 2 + readUnsignedShort(v + 2) << 1;
                 }
+                context.bootstrapMethods = bootstrapMethods;
             } else {
-                attr = readAttribute(attrs,
-                        attrName,
-                        v + 6,
-                        readInt(v + 2),
-                        c,
-                        -1,
-                        null);
+                Attribute attr = readAttribute(attrs, attrName, u + 8,
+                        readInt(u + 4), c, -1, null);
                 if (attr != null) {
-                    attr.next = cattrs;
-                    cattrs = attr;
+                    attr.next = attributes;
+                    attributes = attr;
                 }
             }
-            v += 6 + readInt(v + 2);
-        }
-        // calls the visit method
-        classVisitor.visit(readInt(4),
-                access,
-                name,
-                signature,
-                superClassName,
-                implementedItfs);
-
-        // calls the visitSource method
-        if (!skipDebug && (sourceFile != null || sourceDebug != null)) {
+            u += 6 + readInt(u + 4);
+        }
+
+        // visits the class declaration
+        classVisitor.visit(readInt(items[1] - 7), access, name, signature,
+                superClass, interfaces);
+
+        // visits the source and debug info
+        if ((flags & SKIP_DEBUG) == 0
+                && (sourceFile != null || sourceDebug != null)) {
             classVisitor.visitSource(sourceFile, sourceDebug);
         }
 
-        // calls the visitOuterClass method
+        // visits the outer class
         if (enclosingOwner != null) {
-            classVisitor.visitOuterClass(enclosingOwner,
-                    enclosingName,
+            classVisitor.visitOuterClass(enclosingOwner, enclosingName,
                     enclosingDesc);
         }
 
-        // visits the class annotations
-        if (ANNOTATIONS) {
-            for (i = 1; i >= 0; --i) {
-                v = i == 0 ? ianns : anns;
-                if (v != 0) {
-                    j = readUnsignedShort(v);
-                    v += 2;
-                    for (; j > 0; --j) {
-                        v = readAnnotationValues(v + 2,
-                                c,
-                                true,
-                                classVisitor.visitAnnotation(readUTF8(v, c), i != 0));
-                    }
-                }
+        // visits the class annotations and type annotations
+        if (ANNOTATIONS && anns != 0) {
+            for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
+                v = readAnnotationValues(v + 2, c, true,
+                        classVisitor.visitAnnotation(readUTF8(v, c), true));
+            }
+        }
+        if (ANNOTATIONS && ianns != 0) {
+            for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
+                v = readAnnotationValues(v + 2, c, true,
+                        classVisitor.visitAnnotation(readUTF8(v, c), false));
+            }
+        }
+        if (ANNOTATIONS && tanns != 0) {
+            for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
+                v = readAnnotationTarget(context, v);
+                v = readAnnotationValues(v + 2, c, true,
+                        classVisitor.visitTypeAnnotation(context.typeRef,
+                                context.typePath, readUTF8(v, c), true));
+            }
+        }
+        if (ANNOTATIONS && itanns != 0) {
+            for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
+                v = readAnnotationTarget(context, v);
+                v = readAnnotationValues(v + 2, c, true,
+                        classVisitor.visitTypeAnnotation(context.typeRef,
+                                context.typePath, readUTF8(v, c), false));
             }
         }
 
-        // visits the class attributes
-        while (cattrs != null) {
-            attr = cattrs.next;
-            cattrs.next = null;
-            classVisitor.visitAttribute(cattrs);
-            cattrs = attr;
+        // visits the attributes
+        while (attributes != null) {
+            Attribute attr = attributes.next;
+            attributes.next = null;
+            classVisitor.visitAttribute(attributes);
+            attributes = attr;
         }
 
-        // calls the visitInnerClass method
-        if (w != 0) {
-            i = readUnsignedShort(w);
-            w += 2;
-            for (; i > 0; --i) {
-                classVisitor.visitInnerClass(readUnsignedShort(w) == 0
-                        ? null
-                        : readClass(w, c), readUnsignedShort(w + 2) == 0
-                        ? null
-                        : readClass(w + 2, c), readUnsignedShort(w + 4) == 0
-                        ? null
-                        : readUTF8(w + 4, c), readUnsignedShort(w + 6));
-                w += 8;
+        // visits the inner classes
+        if (innerClasses != 0) {
+            int v = innerClasses + 2;
+            for (int i = readUnsignedShort(innerClasses); i > 0; --i) {
+                classVisitor.visitInnerClass(readClass(v, c),
+                        readClass(v + 2, c), readUTF8(v + 4, c),
+                        readUnsignedShort(v + 6));
+                v += 8;
             }
         }
 
-        // visits the fields
-        i = readUnsignedShort(u);
+        // visits the fields and methods
+        u = header + 10 + 2 * interfaces.length;
+        for (int i = readUnsignedShort(u - 2); i > 0; --i) {
+            u = readField(classVisitor, context, u);
+        }
         u += 2;
-        for (; i > 0; --i) {
-            access = readUnsignedShort(u);
-            name = readUTF8(u + 2, c);
-            desc = readUTF8(u + 4, c);
-            // visits the field's attributes and looks for a ConstantValue
-            // attribute
-            int fieldValueItem = 0;
-            signature = null;
-            anns = 0;
-            ianns = 0;
-            cattrs = null;
-
-            j = readUnsignedShort(u + 6);
-            u += 8;
-            for (; j > 0; --j) {
-                attrName = readUTF8(u, c);
-                // tests are sorted in decreasing frequency order
-                // (based on frequencies observed on typical classes)
-                if ("ConstantValue".equals(attrName)) {
-                    fieldValueItem = readUnsignedShort(u + 6);
-                } else if (SIGNATURES && "Signature".equals(attrName)) {
-                    signature = readUTF8(u + 6, c);
-                } else if ("Deprecated".equals(attrName)) {
-                    access |= Opcodes.ACC_DEPRECATED;
-                } else if ("Synthetic".equals(attrName)) {
-                    access |= Opcodes.ACC_SYNTHETIC  | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
-                } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
-                    anns = u + 6;
-                } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
-                    ianns = u + 6;
-                } else {
-                    attr = readAttribute(attrs,
-                            attrName,
-                            u + 6,
-                            readInt(u + 2),
-                            c,
-                            -1,
-                            null);
-                    if (attr != null) {
-                        attr.next = cattrs;
-                        cattrs = attr;
-                    }
+        for (int i = readUnsignedShort(u - 2); i > 0; --i) {
+            u = readMethod(classVisitor, context, u);
+        }
+
+        // visits the end of the class
+        classVisitor.visitEnd();
+    }
+
+    /**
+     * Reads a field and makes the given visitor visit it.
+     * 
+     * @param classVisitor
+     *            the visitor that must visit the field.
+     * @param context
+     *            information about the class being parsed.
+     * @param u
+     *            the start offset of the field in the class file.
+     * @return the offset of the first byte following the field in the class.
+     */
+    private int readField(final ClassVisitor classVisitor,
+            final Context context, int u) {
+        // reads the field declaration
+        char[] c = context.buffer;
+        int access = readUnsignedShort(u);
+        String name = readUTF8(u + 2, c);
+        String desc = readUTF8(u + 4, c);
+        u += 6;
+
+        // reads the field attributes
+        String signature = null;
+        int anns = 0;
+        int ianns = 0;
+        int tanns = 0;
+        int itanns = 0;
+        Object value = null;
+        Attribute attributes = null;
+
+        for (int i = readUnsignedShort(u); i > 0; --i) {
+            String attrName = readUTF8(u + 2, c);
+            // tests are sorted in decreasing frequency order
+            // (based on frequencies observed on typical classes)
+            if ("ConstantValue".equals(attrName)) {
+                int item = readUnsignedShort(u + 8);
+                value = item == 0 ? null : readConst(item, c);
+            } else if (SIGNATURES && "Signature".equals(attrName)) {
+                signature = readUTF8(u + 8, c);
+            } else if ("Deprecated".equals(attrName)) {
+                access |= Opcodes.ACC_DEPRECATED;
+            } else if ("Synthetic".equals(attrName)) {
+                access |= Opcodes.ACC_SYNTHETIC
+                        | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+            } else if (ANNOTATIONS
+                    && "RuntimeVisibleAnnotations".equals(attrName)) {
+                anns = u + 8;
+            } else if (ANNOTATIONS
+                    && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+                tanns = u + 8;
+            } else if (ANNOTATIONS
+                    && "RuntimeInvisibleAnnotations".equals(attrName)) {
+                ianns = u + 8;
+            } else if (ANNOTATIONS
+                    && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+                itanns = u + 8;
+            } else {
+                Attribute attr = readAttribute(context.attrs, attrName, u + 8,
+                        readInt(u + 4), c, -1, null);
+                if (attr != null) {
+                    attr.next = attributes;
+                    attributes = attr;
                 }
-                u += 6 + readInt(u + 2);
             }
-            // visits the field
-            FieldVisitor fv = classVisitor.visitField(access,
-                    name,
-                    desc,
-                    signature,
-                    fieldValueItem == 0 ? null : readConst(fieldValueItem, c));
-            // visits the field annotations and attributes
-            if (fv != null) {
-                if (ANNOTATIONS) {
-                    for (j = 1; j >= 0; --j) {
-                        v = j == 0 ? ianns : anns;
-                        if (v != 0) {
-                            k = readUnsignedShort(v);
-                            v += 2;
-                            for (; k > 0; --k) {
-                                v = readAnnotationValues(v + 2,
-                                        c,
-                                        true,
-                                        fv.visitAnnotation(readUTF8(v, c), j != 0));
-                            }
-                        }
-                    }
-                }
-                while (cattrs != null) {
-                    attr = cattrs.next;
-                    cattrs.next = null;
-                    fv.visitAttribute(cattrs);
-                    cattrs = attr;
-                }
-                fv.visitEnd();
+            u += 6 + readInt(u + 4);
+        }
+        u += 2;
+
+        // visits the field declaration
+        FieldVisitor fv = classVisitor.visitField(access, name, desc,
+                signature, value);
+        if (fv == null) {
+            return u;
+        }
+
+        // visits the field annotations and type annotations
+        if (ANNOTATIONS && anns != 0) {
+            for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
+                v = readAnnotationValues(v + 2, c, true,
+                        fv.visitAnnotation(readUTF8(v, c), true));
+            }
+        }
+        if (ANNOTATIONS && ianns != 0) {
+            for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
+                v = readAnnotationValues(v + 2, c, true,
+                        fv.visitAnnotation(readUTF8(v, c), false));
+            }
+        }
+        if (ANNOTATIONS && tanns != 0) {
+            for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
+                v = readAnnotationTarget(context, v);
+                v = readAnnotationValues(v + 2, c, true,
+                        fv.visitTypeAnnotation(context.typeRef,
+                                context.typePath, readUTF8(v, c), true));
+            }
+        }
+        if (ANNOTATIONS && itanns != 0) {
+            for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
+                v = readAnnotationTarget(context, v);
+                v = readAnnotationValues(v + 2, c, true,
+                        fv.visitTypeAnnotation(context.typeRef,
+                                context.typePath, readUTF8(v, c), false));
             }
         }
 
-        // visits the methods
-        i = readUnsignedShort(u);
-        u += 2;
-        for (; i > 0; --i) {
-            int u0 = u + 6;
-            access = readUnsignedShort(u);
-            name = readUTF8(u + 2, c);
-            desc = readUTF8(u + 4, c);
-            signature = null;
-            anns = 0;
-            ianns = 0;
-            int dann = 0;
-            int mpanns = 0;
-            int impanns = 0;
-            cattrs = null;
-            v = 0;
-            w = 0;
-
-            // looks for Code and Exceptions attributes
-            j = readUnsignedShort(u + 6);
-            u += 8;
-            for (; j > 0; --j) {
-                attrName = readUTF8(u, c);
-                int attrSize = readInt(u + 2);
-                u += 6;
-                // tests are sorted in decreasing frequency order
-                // (based on frequencies observed on typical classes)
-                if ("Code".equals(attrName)) {
-                    if (!skipCode) {
-                        v = u;
-                    }
-                } else if ("Exceptions".equals(attrName)) {
-                    w = u;
-                } else if (SIGNATURES && "Signature".equals(attrName)) {
-                    signature = readUTF8(u, c);
-                } else if ("Deprecated".equals(attrName)) {
-                    access |= Opcodes.ACC_DEPRECATED;
-                } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
-                    anns = u;
-                } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
-                    dann = u;
-                } else if ("Synthetic".equals(attrName)) {
-                    access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
-                } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
-                    ianns = u;
-                } else if (ANNOTATIONS && "RuntimeVisibleParameterAnnotations".equals(attrName))
-                {
-                    mpanns = u;
-                } else if (ANNOTATIONS && "RuntimeInvisibleParameterAnnotations".equals(attrName))
-                {
-                    impanns = u;
-                } else {
-                    attr = readAttribute(attrs,
-                            attrName,
-                            u,
-                            attrSize,
-                            c,
-                            -1,
-                            null);
-                    if (attr != null) {
-                        attr.next = cattrs;
-                        cattrs = attr;
-                    }
+        // visits the field attributes
+        while (attributes != null) {
+            Attribute attr = attributes.next;
+            attributes.next = null;
+            fv.visitAttribute(attributes);
+            attributes = attr;
+        }
+
+        // visits the end of the field
+        fv.visitEnd();
+
+        return u;
+    }
+
+    /**
+     * Reads a method and makes the given visitor visit it.
+     * 
+     * @param classVisitor
+     *            the visitor that must visit the method.
+     * @param context
+     *            information about the class being parsed.
+     * @param u
+     *            the start offset of the method in the class file.
+     * @return the offset of the first byte following the method in the class.
+     */
+    private int readMethod(final ClassVisitor classVisitor,
+            final Context context, int u) {
+        // reads the method declaration
+        char[] c = context.buffer;
+        context.access = readUnsignedShort(u);
+        context.name = readUTF8(u + 2, c);
+        context.desc = readUTF8(u + 4, c);
+        u += 6;
+
+        // reads the method attributes
+        int code = 0;
+        int exception = 0;
+        String[] exceptions = null;
+        String signature = null;
+        int methodParameters = 0;
+        int anns = 0;
+        int ianns = 0;
+        int tanns = 0;
+        int itanns = 0;
+        int dann = 0;
+        int mpanns = 0;
+        int impanns = 0;
+        int firstAttribute = u;
+        Attribute attributes = null;
+
+        for (int i = readUnsignedShort(u); i > 0; --i) {
+            String attrName = readUTF8(u + 2, c);
+            // tests are sorted in decreasing frequency order
+            // (based on frequencies observed on typical classes)
+            if ("Code".equals(attrName)) {
+                if ((context.flags & SKIP_CODE) == 0) {
+                    code = u + 8;
                 }
-                u += attrSize;
-            }
-            // reads declared exceptions
-            String[] exceptions;
-            if (w == 0) {
-                exceptions = null;
+            } else if ("Exceptions".equals(attrName)) {
+                exceptions = new String[readUnsignedShort(u + 8)];
+                exception = u + 10;
+                for (int j = 0; j < exceptions.length; ++j) {
+                    exceptions[j] = readClass(exception, c);
+                    exception += 2;
+                }
+            } else if (SIGNATURES && "Signature".equals(attrName)) {
+                signature = readUTF8(u + 8, c);
+            } else if ("Deprecated".equals(attrName)) {
+                context.access |= Opcodes.ACC_DEPRECATED;
+            } else if (ANNOTATIONS
+                    && "RuntimeVisibleAnnotations".equals(attrName)) {
+                anns = u + 8;
+            } else if (ANNOTATIONS
+                    && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+                tanns = u + 8;
+            } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
+                dann = u + 8;
+            } else if ("Synthetic".equals(attrName)) {
+                context.access |= Opcodes.ACC_SYNTHETIC
+                        | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+            } else if (ANNOTATIONS
+                    && "RuntimeInvisibleAnnotations".equals(attrName)) {
+                ianns = u + 8;
+            } else if (ANNOTATIONS
+                    && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+                itanns = u + 8;
+            } else if (ANNOTATIONS
+                    && "RuntimeVisibleParameterAnnotations".equals(attrName)) {
+                mpanns = u + 8;
+            } else if (ANNOTATIONS
+                    && "RuntimeInvisibleParameterAnnotations".equals(attrName)) {
+                impanns = u + 8;
+            } else if ("MethodParameters".equals(attrName)) {
+                methodParameters = u + 8;
             } else {
-                exceptions = new String[readUnsignedShort(w)];
-                w += 2;
-                for (j = 0; j < exceptions.length; ++j) {
-                    exceptions[j] = readClass(w, c);
-                    w += 2;
+                Attribute attr = readAttribute(context.attrs, attrName, u + 8,
+                        readInt(u + 4), c, -1, null);
+                if (attr != null) {
+                    attr.next = attributes;
+                    attributes = attr;
                 }
             }
+            u += 6 + readInt(u + 4);
+        }
+        u += 2;
 
-            // visits the method's code, if any
-            MethodVisitor mv = classVisitor.visitMethod(access,
-                    name,
-                    desc,
-                    signature,
-                    exceptions);
+        // visits the method declaration
+        MethodVisitor mv = classVisitor.visitMethod(context.access,
+                context.name, context.desc, signature, exceptions);
+        if (mv == null) {
+            return u;
+        }
 
-            if (mv != null) {
-                /*
-                 * if the returned MethodVisitor is in fact a MethodWriter, it
-                 * means there is no method adapter between the reader and the
-                 * writer. If, in addition, the writer's constant pool was
-                 * copied from this reader (mw.cw.cr == this), and the signature
-                 * and exceptions of the method have not been changed, then it
-                 * is possible to skip all visit events and just copy the
-                 * original code of the method to the writer (the access, name
-                 * and descriptor can have been changed, this is not important
-                 * since they are not copied as is from the reader).
-                 */
-                if (WRITER && mv instanceof MethodWriter) {
-                    MethodWriter mw = (MethodWriter) mv;
-                    if (mw.cw.cr == this) {
-                        if (signature == mw.signature) {
-                            boolean sameExceptions = false;
-                            if (exceptions == null) {
-                                sameExceptions = mw.exceptionCount == 0;
-                            } else {
-                                if (exceptions.length == mw.exceptionCount) {
-                                    sameExceptions = true;
-                                    for (j = exceptions.length - 1; j >= 0; --j)
-                                    {
-                                        w -= 2;
-                                        if (mw.exceptions[j] != readUnsignedShort(w))
-                                        {
-                                            sameExceptions = false;
-                                            break;
-                                        }
-                                    }
-                                }
-                            }
-                            if (sameExceptions) {
-                                /*
-                                 * we do not copy directly the code into
-                                 * MethodWriter to save a byte array copy
-                                 * operation. The real copy will be done in
-                                 * ClassWriter.toByteArray().
-                                 */
-                                mw.classReaderOffset = u0;
-                                mw.classReaderLength = u - u0;
-                                continue;
-                            }
+        /*
+         * if the returned MethodVisitor is in fact a MethodWriter, it means
+         * there is no method adapter between the reader and the writer. If, in
+         * addition, the writer's constant pool was copied from this reader
+         * (mw.cw.cr == this), and the signature and exceptions of the method
+         * have not been changed, then it is possible to skip all visit events
+         * and just copy the original code of the method to the writer (the
+         * access, name and descriptor can have been changed, this is not
+         * important since they are not copied as is from the reader).
+         */
+        if (WRITER && mv instanceof MethodWriter) {
+            MethodWriter mw = (MethodWriter) mv;
+            if (mw.cw.cr == this && signature == mw.signature) {
+                boolean sameExceptions = false;
+                if (exceptions == null) {
+                    sameExceptions = mw.exceptionCount == 0;
+                } else if (exceptions.length == mw.exceptionCount) {
+                    sameExceptions = true;
+                    for (int j = exceptions.length - 1; j >= 0; --j) {
+                        exception -= 2;
+                        if (mw.exceptions[j] != readUnsignedShort(exception)) {
+                            sameExceptions = false;
+                            break;
                         }
                     }
                 }
-
-                if (ANNOTATIONS && dann != 0) {
-                    AnnotationVisitor dv = mv.visitAnnotationDefault();
-                    readAnnotationValue(dann, c, null, dv);
-                    if (dv != null) {
-                        dv.visitEnd();
-                    }
-                }
-                if (ANNOTATIONS) {
-                    for (j = 1; j >= 0; --j) {
-                        w = j == 0 ? ianns : anns;
-                        if (w != 0) {
-                            k = readUnsignedShort(w);
-                            w += 2;
-                            for (; k > 0; --k) {
-                                w = readAnnotationValues(w + 2,
-                                        c,
-                                        true,
-                                        mv.visitAnnotation(readUTF8(w, c), j != 0));
-                            }
-                        }
-                    }
+                if (sameExceptions) {
+                    /*
+                     * we do not copy directly the code into MethodWriter to
+                     * save a byte array copy operation. The real copy will be
+                     * done in ClassWriter.toByteArray().
+                     */
+                    mw.classReaderOffset = firstAttribute;
+                    mw.classReaderLength = u - firstAttribute;
+                    return u;
                 }
-                if (ANNOTATIONS && mpanns != 0) {
-                    readParameterAnnotations(mpanns, desc, c, true, mv);
+            }
+        }
+
+        // visit the method parameters
+        if (methodParameters != 0) {
+            for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) {
+                mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2));
+            }
+        }
+
+        // visits the method annotations
+        if (ANNOTATIONS && dann != 0) {
+            AnnotationVisitor dv = mv.visitAnnotationDefault();
+            readAnnotationValue(dann, c, null, dv);
+            if (dv != null) {
+                dv.visitEnd();
+            }
+        }
+        if (ANNOTATIONS && anns != 0) {
+            for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
+                v = readAnnotationValues(v + 2, c, true,
+                        mv.visitAnnotation(readUTF8(v, c), true));
+            }
+        }
+        if (ANNOTATIONS && ianns != 0) {
+            for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
+                v = readAnnotationValues(v + 2, c, true,
+                        mv.visitAnnotation(readUTF8(v, c), false));
+            }
+        }
+        if (ANNOTATIONS && tanns != 0) {
+            for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
+                v = readAnnotationTarget(context, v);
+                v = readAnnotationValues(v + 2, c, true,
+                        mv.visitTypeAnnotation(context.typeRef,
+                                context.typePath, readUTF8(v, c), true));
+            }
+        }
+        if (ANNOTATIONS && itanns != 0) {
+            for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
+                v = readAnnotationTarget(context, v);
+                v = readAnnotationValues(v + 2, c, true,
+                        mv.visitTypeAnnotation(context.typeRef,
+                                context.typePath, readUTF8(v, c), false));
+            }
+        }
+        if (ANNOTATIONS && mpanns != 0) {
+            readParameterAnnotations(mv, context, mpanns, true);
+        }
+        if (ANNOTATIONS && impanns != 0) {
+            readParameterAnnotations(mv, context, impanns, false);
+        }
+
+        // visits the method attributes
+        while (attributes != null) {
+            Attribute attr = attributes.next;
+            attributes.next = null;
+            mv.visitAttribute(attributes);
+            attributes = attr;
+        }
+
+        // visits the method code
+        if (code != 0) {
+            mv.visitCode();
+            readCode(mv, context, code);
+        }
+
+        // visits the end of the method
+        mv.visitEnd();
+
+        return u;
+    }
+
+    /**
+     * Reads the bytecode of a method and makes the given visitor visit it.
+     * 
+     * @param mv
+     *            the visitor that must visit the method's code.
+     * @param context
+     *            information about the class being parsed.
+     * @param u
+     *            the start offset of the code attribute in the class file.
+     */
+    private void readCode(final MethodVisitor mv, final Context context, int u) {
+        // reads the header
+        byte[] b = this.b;
+        char[] c = context.buffer;
+        int maxStack = readUnsignedShort(u);
+        int maxLocals = readUnsignedShort(u + 2);
+        int codeLength = readInt(u + 4);
+        u += 8;
+
+        // reads the bytecode to find the labels
+        int codeStart = u;
+        int codeEnd = u + codeLength;
+        Label[] labels = context.labels = new Label[codeLength + 2];
+        readLabel(codeLength + 1, labels);
+        while (u < codeEnd) {
+            int offset = u - codeStart;
+            int opcode = b[u] & 0xFF;
+            switch (ClassWriter.TYPE[opcode]) {
+            case ClassWriter.NOARG_INSN:
+            case ClassWriter.IMPLVAR_INSN:
+                u += 1;
+                break;
+            case ClassWriter.LABEL_INSN:
+                readLabel(offset + readShort(u + 1), labels);
+                u += 3;
+                break;
+            case ClassWriter.LABELW_INSN:
+                readLabel(offset + readInt(u + 1), labels);
+                u += 5;
+                break;
+            case ClassWriter.WIDE_INSN:
+                opcode = b[u + 1] & 0xFF;
+                if (opcode == Opcodes.IINC) {
+                    u += 6;
+                } else {
+                    u += 4;
                 }
-                if (ANNOTATIONS && impanns != 0) {
-                    readParameterAnnotations(impanns, desc, c, false, mv);
+                break;
+            case ClassWriter.TABL_INSN:
+                // skips 0 to 3 padding bytes
+                u = u + 4 - (offset & 3);
+                // reads instruction
+                readLabel(offset + readInt(u), labels);
+                for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) {
+                    readLabel(offset + readInt(u + 12), labels);
+                    u += 4;
                 }
-                while (cattrs != null) {
-                    attr = cattrs.next;
-                    cattrs.next = null;
-                    mv.visitAttribute(cattrs);
-                    cattrs = attr;
+                u += 12;
+                break;
+            case ClassWriter.LOOK_INSN:
+                // skips 0 to 3 padding bytes
+                u = u + 4 - (offset & 3);
+                // reads instruction
+                readLabel(offset + readInt(u), labels);
+                for (int i = readInt(u + 4); i > 0; --i) {
+                    readLabel(offset + readInt(u + 12), labels);
+                    u += 8;
                 }
+                u += 8;
+                break;
+            case ClassWriter.VAR_INSN:
+            case ClassWriter.SBYTE_INSN:
+            case ClassWriter.LDC_INSN:
+                u += 2;
+                break;
+            case ClassWriter.SHORT_INSN:
+            case ClassWriter.LDCW_INSN:
+            case ClassWriter.FIELDORMETH_INSN:
+            case ClassWriter.TYPE_INSN:
+            case ClassWriter.IINC_INSN:
+                u += 3;
+                break;
+            case ClassWriter.ITFMETH_INSN:
+            case ClassWriter.INDYMETH_INSN:
+                u += 5;
+                break;
+            // case MANA_INSN:
+            default:
+                u += 4;
+                break;
             }
+        }
 
-            if (mv != null && v != 0) {
-                int maxStack = readUnsignedShort(v);
-                int maxLocals = readUnsignedShort(v + 2);
-                int codeLength = readInt(v + 4);
-                v += 8;
+        // reads the try catch entries to find the labels, and also visits them
+        for (int i = readUnsignedShort(u); i > 0; --i) {
+            Label start = readLabel(readUnsignedShort(u + 2), labels);
+            Label end = readLabel(readUnsignedShort(u + 4), labels);
+            Label handler = readLabel(readUnsignedShort(u + 6), labels);
+            String type = readUTF8(items[readUnsignedShort(u + 8)], c);
+            mv.visitTryCatchBlock(start, end, handler, type);
+            u += 8;
+        }
+        u += 2;
 
-                int codeStart = v;
-                int codeEnd = v + codeLength;
-
-                mv.visitCode();
-
-                // 1st phase: finds the labels
-                int label;
-                Label[] labels = new Label[codeLength + 2];
-                readLabel(codeLength + 1, labels);
-                while (v < codeEnd) {
-                    w = v - codeStart;
-                    int opcode = b[v] & 0xFF;
-                    switch (ClassWriter.TYPE[opcode]) {
-                        case ClassWriter.NOARG_INSN:
-                        case ClassWriter.IMPLVAR_INSN:
-                            v += 1;
-                            break;
-                        case ClassWriter.LABEL_INSN:
-                            readLabel(w + readShort(v + 1), labels);
-                            v += 3;
-                            break;
-                        case ClassWriter.LABELW_INSN:
-                            readLabel(w + readInt(v + 1), labels);
-                            v += 5;
-                            break;
-                        case ClassWriter.WIDE_INSN:
-                            opcode = b[v + 1] & 0xFF;
-                            if (opcode == Opcodes.IINC) {
-                                v += 6;
-                            } else {
-                                v += 4;
-                            }
-                            break;
-                        case ClassWriter.TABL_INSN:
-                            // skips 0 to 3 padding bytes*
-                            v = v + 4 - (w & 3);
-                            // reads instruction
-                            readLabel(w + readInt(v), labels);
-                            j = readInt(v + 8) - readInt(v + 4) + 1;
-                            v += 12;
-                            for (; j > 0; --j) {
-                                readLabel(w + readInt(v), labels);
-                                v += 4;
-                            }
-                            break;
-                        case ClassWriter.LOOK_INSN:
-                            // skips 0 to 3 padding bytes*
-                            v = v + 4 - (w & 3);
-                            // reads instruction
-                            readLabel(w + readInt(v), labels);
-                            j = readInt(v + 4);
-                            v += 8;
-                            for (; j > 0; --j) {
-                                readLabel(w + readInt(v + 4), labels);
-                                v += 8;
-                            }
-                            break;
-                        case ClassWriter.VAR_INSN:
-                        case ClassWriter.SBYTE_INSN:
-                        case ClassWriter.LDC_INSN:
-                            v += 2;
-                            break;
-                        case ClassWriter.SHORT_INSN:
-                        case ClassWriter.LDCW_INSN:
-                        case ClassWriter.FIELDORMETH_INSN:
-                        case ClassWriter.TYPE_INSN:
-                        case ClassWriter.IINC_INSN:
-                            v += 3;
-                            break;
-                        case ClassWriter.ITFMETH_INSN:
-                        case ClassWriter.INDYMETH_INSN:
-                            v += 5;
-                            break;
-                        // case MANA_INSN:
-                        default:
-                            v += 4;
-                            break;
-                    }
-                }
-                // parses the try catch entries
-                j = readUnsignedShort(v);
-                v += 2;
-                for (; j > 0; --j) {
-                    Label start = readLabel(readUnsignedShort(v), labels);
-                    Label end = readLabel(readUnsignedShort(v + 2), labels);
-                    Label handler = readLabel(readUnsignedShort(v + 4), labels);
-                    int type = readUnsignedShort(v + 6);
-                    if (type == 0) {
-                        mv.visitTryCatchBlock(start, end, handler, null);
-                    } else {
-                        mv.visitTryCatchBlock(start,
-                                end,
-                                handler,
-                                readUTF8(items[type], c));
-                    }
-                    v += 8;
-                }
-                // parses the local variable, line number tables, and code
-                // attributes
-                int varTable = 0;
-                int varTypeTable = 0;
-                int stackMap = 0;
-                int stackMapSize = 0;
-                int frameCount = 0;
-                int frameMode = 0;
-                int frameOffset = 0;
-                int frameLocalCount = 0;
-                int frameLocalDiff = 0;
-                int frameStackCount = 0;
-                Object[] frameLocal = null;
-                Object[] frameStack = null;
-                boolean zip = true;
-                cattrs = null;
-                j = readUnsignedShort(v);
-                v += 2;
-                for (; j > 0; --j) {
-                    attrName = readUTF8(v, c);
-                    if ("LocalVariableTable".equals(attrName)) {
-                        if (!skipDebug) {
-                            varTable = v + 6;
-                            k = readUnsignedShort(v + 6);
-                            w = v + 8;
-                            for (; k > 0; --k) {
-                                label = readUnsignedShort(w);
-                                if (labels[label] == null) {
-                                    readLabel(label, labels).status |= Label.DEBUG;
-                                }
-                                label += readUnsignedShort(w + 2);
-                                if (labels[label] == null) {
-                                    readLabel(label, labels).status |= Label.DEBUG;
-                                }
-                                w += 10;
-                            }
-                        }
-                    } else if ("LocalVariableTypeTable".equals(attrName)) {
-                        varTypeTable = v + 6;
-                    } else if ("LineNumberTable".equals(attrName)) {
-                        if (!skipDebug) {
-                            k = readUnsignedShort(v + 6);
-                            w = v + 8;
-                            for (; k > 0; --k) {
-                                label = readUnsignedShort(w);
-                                if (labels[label] == null) {
-                                    readLabel(label, labels).status |= Label.DEBUG;
-                                }
-                                labels[label].line = readUnsignedShort(w + 2);
-                                w += 4;
-                            }
-                        }
-                    } else if (FRAMES && "StackMapTable".equals(attrName)) {
-                        if ((flags & SKIP_FRAMES) == 0) {
-                            stackMap = v + 8;
-                            stackMapSize = readInt(v + 2);
-                            frameCount = readUnsignedShort(v + 6);
+        // reads the code attributes
+        int[] tanns = null; // start index of each visible type annotation
+        int[] itanns = null; // start index of each invisible type annotation
+        int tann = 0; // current index in tanns array
+        int itann = 0; // current index in itanns array
+        int ntoff = -1; // next visible type annotation code offset
+        int nitoff = -1; // next invisible type annotation code offset
+        int varTable = 0;
+        int varTypeTable = 0;
+        boolean zip = true;
+        boolean unzip = (context.flags & EXPAND_FRAMES) != 0;
+        int stackMap = 0;
+        int stackMapSize = 0;
+        int frameCount = 0;
+        Context frame = null;
+        Attribute attributes = null;
+
+        for (int i = readUnsignedShort(u); i > 0; --i) {
+            String attrName = readUTF8(u + 2, c);
+            if ("LocalVariableTable".equals(attrName)) {
+                if ((context.flags & SKIP_DEBUG) == 0) {
+                    varTable = u + 8;
+                    for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
+                        int label = readUnsignedShort(v + 10);
+                        if (labels[label] == null) {
+                            readLabel(label, labels).status |= Label.DEBUG;
                         }
-                        /*
-                         * here we do not extract the labels corresponding to
-                         * the attribute content. This would require a full
-                         * parsing of the attribute, which would need to be
-                         * repeated in the second phase (see below). Instead the
-                         * content of the attribute is read one frame at a time
-                         * (i.e. after a frame has been visited, the next frame
-                         * is read), and the labels it contains are also
-                         * extracted one frame at a time. Thanks to the ordering
-                         * of frames, having only a "one frame lookahead" is not
-                         * a problem, i.e. it is not possible to see an offset
-                         * smaller than the offset of the current insn and for
-                         * which no Label exist.
-                         */
-                        /*
-                         * This is not true for UNINITIALIZED type offsets. We
-                         * solve this by parsing the stack map table without a
-                         * full decoding (see below).
-                         */
-                    } else if (FRAMES && "StackMap".equals(attrName)) {
-                        if ((flags & SKIP_FRAMES) == 0) {
-                            stackMap = v + 8;
-                            stackMapSize = readInt(v + 2);
-                            frameCount = readUnsignedShort(v + 6);
-                            zip = false;
-                        }
-                        /*
-                         * IMPORTANT! here we assume that the frames are
-                         * ordered, as in the StackMapTable attribute, although
-                         * this is not guaranteed by the attribute format.
-                         */
-                    } else {
-                        for (k = 0; k < attrs.length; ++k) {
-                            if (attrs[k].type.equals(attrName)) {
-                                attr = attrs[k].read(this,
-                                        v + 6,
-                                        readInt(v + 2),
-                                        c,
-                                        codeStart - 8,
-                                        labels);
-                                if (attr != null) {
-                                    attr.next = cattrs;
-                                    cattrs = attr;
-                                }
-                            }
+                        label += readUnsignedShort(v + 12);
+                        if (labels[label] == null) {
+                            readLabel(label, labels).status |= Label.DEBUG;
                         }
+                        v += 10;
                     }
-                    v += 6 + readInt(v + 2);
                 }
-
-                // 2nd phase: visits each instruction
-                if (FRAMES && stackMap != 0) {
-                    // creates the very first (implicit) frame from the method
-                    // descriptor
-                    frameLocal = new Object[maxLocals];
-                    frameStack = new Object[maxStack];
-                    if (unzip) {
-                        int local = 0;
-                        if ((access & Opcodes.ACC_STATIC) == 0) {
-                            if ("<init>".equals(name)) {
-                                frameLocal[local++] = Opcodes.UNINITIALIZED_THIS;
-                            } else {
-                                frameLocal[local++] = readClass(header + 2, c);
-                            }
-                        }
-                        j = 1;
-                        loop: while (true) {
-                            k = j;
-                            switch (desc.charAt(j++)) {
-                                case 'Z':
-                                case 'C':
-                                case 'B':
-                                case 'S':
-                                case 'I':
-                                    frameLocal[local++] = Opcodes.INTEGER;
-                                    break;
-                                case 'F':
-                                    frameLocal[local++] = Opcodes.FLOAT;
-                                    break;
-                                case 'J':
-                                    frameLocal[local++] = Opcodes.LONG;
-                                    break;
-                                case 'D':
-                                    frameLocal[local++] = Opcodes.DOUBLE;
-                                    break;
-                                case '[':
-                                    while (desc.charAt(j) == '[') {
-                                        ++j;
-                                    }
-                                    if (desc.charAt(j) == 'L') {
-                                        ++j;
-                                        while (desc.charAt(j) != ';') {
-                                            ++j;
-                                        }
-                                    }
-                                    frameLocal[local++] = desc.substring(k, ++j);
-                                    break;
-                                case 'L':
-                                    while (desc.charAt(j) != ';') {
-                                        ++j;
-                                    }
-                                    frameLocal[local++] = desc.substring(k + 1,
-                                            j++);
-                                    break;
-                                default:
-                                    break loop;
-                            }
+            } else if ("LocalVariableTypeTable".equals(attrName)) {
+                varTypeTable = u + 8;
+            } else if ("LineNumberTable".equals(attrName)) {
+                if ((context.flags & SKIP_DEBUG) == 0) {
+                    for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
+                        int label = readUnsignedShort(v + 10);
+                        if (labels[label] == null) {
+                            readLabel(label, labels).status |= Label.DEBUG;
                         }
-                        frameLocalCount = local;
+                        labels[label].line = readUnsignedShort(v + 12);
+                        v += 4;
                     }
-                    /*
-                     * for the first explicit frame the offset is not
-                     * offset_delta + 1 but only offset_delta; setting the
-                     * implicit frame offset to -1 allow the use of the
-                     * "offset_delta + 1" rule in all cases
-                     */
-                    frameOffset = -1;
-                    /*
-                     * Finds labels for UNINITIALIZED frame types. Instead of
-                     * decoding each element of the stack map table, we look
-                     * for 3 consecutive bytes that "look like" an UNINITIALIZED
-                     * type (tag 8, offset within code bounds, NEW instruction
-                     * at this offset). We may find false positives (i.e. not
-                     * real UNINITIALIZED types), but this should be rare, and
-                     * the only consequence will be the creation of an unneeded
-                     * label. This is better than creating a label for each NEW
-                     * instruction, and faster than fully decoding the whole
-                     * stack map table.
-                     */
-                    for (j = stackMap; j < stackMap + stackMapSize - 2; ++j) {
-                        if (b[j] == 8) { // UNINITIALIZED FRAME TYPE
-                            k = readUnsignedShort(j + 1);
-                            if (k >= 0 && k < codeLength) { // potential offset
-                                if ((b[codeStart + k] & 0xFF) == Opcodes.NEW) { // NEW at this offset
-                                    readLabel(k, labels);
-                                }
-                            }
+                }
+            } else if (ANNOTATIONS
+                    && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+                tanns = readTypeAnnotations(mv, context, u + 8, true);
+                ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1
+                        : readUnsignedShort(tanns[0] + 1);
+            } else if (ANNOTATIONS
+                    && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+                itanns = readTypeAnnotations(mv, context, u + 8, false);
+                nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1
+                        : readUnsignedShort(itanns[0] + 1);
+            } else if (FRAMES && "StackMapTable".equals(attrName)) {
+                if ((context.flags & SKIP_FRAMES) == 0) {
+                    stackMap = u + 10;
+                    stackMapSize = readInt(u + 4);
+                    frameCount = readUnsignedShort(u + 8);
+                }
+                /*
+                 * here we do not extract the labels corresponding to the
+                 * attribute content. This would require a full parsing of the
+                 * attribute, which would need to be repeated in the second
+                 * phase (see below). Instead the content of the attribute is
+                 * read one frame at a time (i.e. after a frame has been
+                 * visited, the next frame is read), and the labels it contains
+                 * are also extracted one frame at a time. Thanks to the
+                 * ordering of frames, having only a "one frame lookahead" is
+                 * not a problem, i.e. it is not possible to see an offset
+                 * smaller than the offset of the current insn and for which no
+                 * Label exist.
+                 */
+                /*
+                 * This is not true for UNINITIALIZED type offsets. We solve
+                 * this by parsing the stack map table without a full decoding
+                 * (see below).
+                 */
+            } else if (FRAMES && "StackMap".equals(attrName)) {
+                if ((context.flags & SKIP_FRAMES) == 0) {
+                    zip = false;
+                    stackMap = u + 10;
+                    stackMapSize = readInt(u + 4);
+                    frameCount = readUnsignedShort(u + 8);
+                }
+                /*
+                 * IMPORTANT! here we assume that the frames are ordered, as in
+                 * the StackMapTable attribute, although this is not guaranteed
+                 * by the attribute format.
+                 */
+            } else {
+                for (int j = 0; j < context.attrs.length; ++j) {
+                    if (context.attrs[j].type.equals(attrName)) {
+                        Attribute attr = context.attrs[j].read(this, u + 8,
+                                readInt(u + 4), c, codeStart - 8, labels);
+                        if (attr != null) {
+                            attr.next = attributes;
+                            attributes = attr;
                         }
                     }
                 }
-                v = codeStart;
-                Label l;
-                while (v < codeEnd) {
-                    w = v - codeStart;
-
-                    l = labels[w];
-                    if (l != null) {
-                        mv.visitLabel(l);
-                        if (!skipDebug && l.line > 0) {
-                            mv.visitLineNumber(l.line, l);
+            }
+            u += 6 + readInt(u + 4);
+        }
+        u += 2;
+
+        // generates the first (implicit) stack map frame
+        if (FRAMES && stackMap != 0) {
+            /*
+             * for the first explicit frame the offset is not offset_delta + 1
+             * but only offset_delta; setting the implicit frame offset to -1
+             * allow the use of the "offset_delta + 1" rule in all cases
+             */
+            frame = context;
+            frame.offset = -1;
+            frame.mode = 0;
+            frame.localCount = 0;
+            frame.localDiff = 0;
+            frame.stackCount = 0;
+            frame.local = new Object[maxLocals];
+            frame.stack = new Object[maxStack];
+            if (unzip) {
+                getImplicitFrame(context);
+            }
+            /*
+             * Finds labels for UNINITIALIZED frame types. Instead of decoding
+             * each element of the stack map table, we look for 3 consecutive
+             * bytes that "look like" an UNINITIALIZED type (tag 8, offset
+             * within code bounds, NEW instruction at this offset). We may find
+             * false positives (i.e. not real UNINITIALIZED types), but this
+             * should be rare, and the only consequence will be the creation of
+             * an unneeded label. This is better than creating a label for each
+             * NEW instruction, and faster than fully decoding the whole stack
+             * map table.
+             */
+            for (int i = stackMap; i < stackMap + stackMapSize - 2; ++i) {
+                if (b[i] == 8) { // UNINITIALIZED FRAME TYPE
+                    int v = readUnsignedShort(i + 1);
+                    if (v >= 0 && v < codeLength) {
+                        if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) {
+                            readLabel(v, labels);
                         }
                     }
+                }
+            }
+        }
 
-                    while (FRAMES && frameLocal != null
-                            && (frameOffset == w || frameOffset == -1))
-                    {
-                        // if there is a frame for this offset,
-                        // makes the visitor visit it,
-                        // and reads the next frame if there is one.
-                        if (!zip || unzip) {
-                            mv.visitFrame(Opcodes.F_NEW,
-                                    frameLocalCount,
-                                    frameLocal,
-                                    frameStackCount,
-                                    frameStack);
-                        } else if (frameOffset != -1) {
-                            mv.visitFrame(frameMode,
-                                    frameLocalDiff,
-                                    frameLocal,
-                                    frameStackCount,
-                                    frameStack);
-                        }
+        // visits the instructions
+        u = codeStart;
+        while (u < codeEnd) {
+            int offset = u - codeStart;
+
+            // visits the label and line number for this offset, if any
+            Label l = labels[offset];
+            if (l != null) {
+                mv.visitLabel(l);
+                if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) {
+                    mv.visitLineNumber(l.line, l);
+                }
+            }
 
-                        if (frameCount > 0) {
-                            int tag, delta, n;
-                            if (zip) {
-                                tag = b[stackMap++] & 0xFF;
-                            } else {
-                                tag = MethodWriter.FULL_FRAME;
-                                frameOffset = -1;
-                            }
-                            frameLocalDiff = 0;
-                            if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME)
-                            {
-                                delta = tag;
-                                frameMode = Opcodes.F_SAME;
-                                frameStackCount = 0;
-                            } else if (tag < MethodWriter.RESERVED) {
-                                delta = tag
-                                        - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME;
-                                stackMap = readFrameType(frameStack,
-                                        0,
-                                        stackMap,
-                                        c,
-                                        labels);
-                                frameMode = Opcodes.F_SAME1;
-                                frameStackCount = 1;
-                            } else {
-                                delta = readUnsignedShort(stackMap);
-                                stackMap += 2;
-                                if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
-                                {
-                                    stackMap = readFrameType(frameStack,
-                                            0,
-                                            stackMap,
-                                            c,
-                                            labels);
-                                    frameMode = Opcodes.F_SAME1;
-                                    frameStackCount = 1;
-                                } else if (tag >= MethodWriter.CHOP_FRAME
-                                        && tag < MethodWriter.SAME_FRAME_EXTENDED)
-                                {
-                                    frameMode = Opcodes.F_CHOP;
-                                    frameLocalDiff = MethodWriter.SAME_FRAME_EXTENDED
-                                            - tag;
-                                    frameLocalCount -= frameLocalDiff;
-                                    frameStackCount = 0;
-                                } else if (tag == MethodWriter.SAME_FRAME_EXTENDED)
-                                {
-                                    frameMode = Opcodes.F_SAME;
-                                    frameStackCount = 0;
-                                } else if (tag < MethodWriter.FULL_FRAME) {
-                                    j = unzip ? 

<TRUNCATED>

[18/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/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 70b26b8..3128ff6 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
@@ -33,7 +33,7 @@ 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
  */
@@ -42,7 +42,7 @@ class MethodWriter extends MethodVisitor {
     /**
      * Pseudo access flag used to denote constructors.
      */
-    static final int ACC_CONSTRUCTOR = 262144;
+    static final int ACC_CONSTRUCTOR = 0x80000;
 
     /**
      * Frame has exactly the same locals as the previous stack map frame and
@@ -96,7 +96,7 @@ class MethodWriter extends 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,14 +104,14 @@ class MethodWriter extends 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;
@@ -192,6 +192,18 @@ class MethodWriter extends MethodVisitor {
     private AnnotationWriter ianns;
 
     /**
+     * The runtime visible type annotations of this method. May be <tt>null</tt>
+     * .
+     */
+    private AnnotationWriter tanns;
+
+    /**
+     * The runtime invisible type annotations of this method. May be
+     * <tt>null</tt>.
+     */
+    private AnnotationWriter itanns;
+
+    /**
      * The runtime visible parameter annotations of this method. May be
      * <tt>null</tt>.
      */
@@ -229,7 +241,7 @@ class MethodWriter extends MethodVisitor {
     private int maxLocals;
 
     /**
-     *  Number of local variables in the current stack map frame.
+     * Number of local variables in the current stack map frame.
      */
     private int currentLocals;
 
@@ -251,17 +263,12 @@ class MethodWriter extends MethodVisitor {
 
     /**
      * The last frame that was written in the StackMapTable attribute.
-     *
+     * 
      * @see #frame
      */
     private int[] previousFrame;
 
     /**
-     * Index of the next element to be added in {@link #frame}.
-     */
-    private int frameIndex;
-
-    /**
      * The current stack map frame. The first element contains the offset of the
      * instruction to which the frame corresponds, the second element is the
      * number of locals and the third one is the number of stack elements. The
@@ -288,6 +295,16 @@ class MethodWriter extends MethodVisitor {
     private Handler lastHandler;
 
     /**
+     * Number of entries in the MethodParameters attribute.
+     */
+    private int methodParametersCount;
+
+    /**
+     * The MethodParameters attribute.
+     */
+    private ByteVector methodParameters;
+
+    /**
      * Number of entries in the LocalVariableTable attribute.
      */
     private int localVarCount;
@@ -318,6 +335,21 @@ class MethodWriter extends MethodVisitor {
     private ByteVector lineNumber;
 
     /**
+     * The start offset of the last visited instruction.
+     */
+    private int lastCodeOffset;
+
+    /**
+     * The runtime visible type annotations of the code. May be <tt>null</tt>.
+     */
+    private AnnotationWriter ctanns;
+
+    /**
+     * The runtime invisible type annotations of the code. May be <tt>null</tt>.
+     */
+    private AnnotationWriter ictanns;
+
+    /**
      * The non standard attributes of the method's code.
      */
     private Attribute cattrs;
@@ -346,7 +378,7 @@ class MethodWriter extends MethodVisitor {
 
     /**
      * Indicates what must be automatically computed.
-     *
+     * 
      * @see #FRAMES
      * @see #MAXS
      * @see #NOTHING
@@ -357,7 +389,8 @@ class MethodWriter extends MethodVisitor {
      * A list of labels. This list is the list of basic blocks in the method,
      * i.e. a list of Label objects linked to each other by their
      * {@link Label#successor} field, in the order they are visited by
-     * {@link MethodVisitor#visitLabel}, and starting with the first basic block.
+     * {@link MethodVisitor#visitLabel}, and starting with the first basic
+     * block.
      */
     private Label labels;
 
@@ -395,30 +428,32 @@ class MethodWriter extends 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.
-     * @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 exceptions. May be
-     *        <tt>null</tt>.
-     * @param computeMaxs <tt>true</tt> if the maximum stack size and number
-     *        of local variables must be automatically computed.
-     * @param computeFrames <tt>true</tt> if the stack map tables must be
-     *        recomputed from scratch.
-     */
-    MethodWriter(
-        final ClassWriter cw,
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final String[] exceptions,
-        final boolean computeMaxs,
-        final boolean computeFrames)
-    {
-        super(Opcodes.ASM4);
+     * 
+     * @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.
+     * @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 exceptions. May be
+     *            <tt>null</tt>.
+     * @param computeMaxs
+     *            <tt>true</tt> if the maximum stack size and number of local
+     *            variables must be automatically computed.
+     * @param computeFrames
+     *            <tt>true</tt> if the stack map tables must be recomputed from
+     *            scratch.
+     */
+    MethodWriter(final ClassWriter cw, final int access, final String name,
+            final String desc, final String signature,
+            final String[] exceptions, final boolean computeMaxs,
+            final boolean computeFrames) {
+        super(Opcodes.ASM5);
         if (cw.firstMethod == null) {
             cw.firstMethod = this;
         } else {
@@ -427,6 +462,9 @@ class MethodWriter extends MethodVisitor {
         cw.lastMethod = this;
         this.cw = cw;
         this.access = access;
+        if ("<init>".equals(name)) {
+            this.access |= ACC_CONSTRUCTOR;
+        }
         this.name = cw.newUTF8(name);
         this.desc = cw.newUTF8(desc);
         this.descriptor = desc;
@@ -442,9 +480,6 @@ class MethodWriter extends MethodVisitor {
         }
         this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING);
         if (computeMaxs || computeFrames) {
-            if (computeFrames && "<init>".equals(name)) {
-                this.access |= ACC_CONSTRUCTOR;
-            }
             // updates maxLocals
             int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2;
             if ((access & Opcodes.ACC_STATIC) != 0) {
@@ -464,6 +499,16 @@ class MethodWriter extends MethodVisitor {
     // ------------------------------------------------------------------------
 
     @Override
+    public void visitParameter(String name, int access) {
+        if (methodParameters == null) {
+            methodParameters = new ByteVector();
+        }
+        ++methodParametersCount;
+        methodParameters.putShort((name == null) ? 0 : cw.newUTF8(name))
+                .putShort(access);
+    }
+
+    @Override
     public AnnotationVisitor visitAnnotationDefault() {
         if (!ClassReader.ANNOTATIONS) {
             return null;
@@ -473,10 +518,8 @@ class MethodWriter extends MethodVisitor {
     }
 
     @Override
-    public AnnotationVisitor visitAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
         if (!ClassReader.ANNOTATIONS) {
             return null;
         }
@@ -495,11 +538,31 @@ class MethodWriter extends MethodVisitor {
     }
 
     @Override
-    public AnnotationVisitor visitParameterAnnotation(
-        final int parameter,
-        final String desc,
-        final boolean visible)
-    {
+    public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        if (!ClassReader.ANNOTATIONS) {
+            return null;
+        }
+        ByteVector bv = new ByteVector();
+        // write target_type and target_info
+        AnnotationWriter.putTarget(typeRef, typePath, bv);
+        // write type, and reserve space for values count
+        bv.putShort(cw.newUTF8(desc)).putShort(0);
+        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+                bv.length - 2);
+        if (visible) {
+            aw.next = tanns;
+            tanns = aw;
+        } else {
+            aw.next = itanns;
+            itanns = aw;
+        }
+        return aw;
+    }
+
+    @Override
+    public AnnotationVisitor visitParameterAnnotation(final int parameter,
+            final String desc, final boolean visible) {
         if (!ClassReader.ANNOTATIONS) {
             return null;
         }
@@ -545,20 +608,18 @@ class MethodWriter extends MethodVisitor {
     }
 
     @Override
-    public void visitFrame(
-        final int type,
-        final int nLocal,
-        final Object[] local,
-        final int nStack,
-        final Object[] stack)
-    {
+    public void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack) {
         if (!ClassReader.FRAMES || compute == FRAMES) {
             return;
         }
 
         if (type == Opcodes.F_NEW) {
+            if (previousFrame == null) {
+                visitImplicitFirstFrame();
+            }
             currentLocals = nLocal;
-            startFrame(code.length, nLocal, nStack);
+            int frameIndex = startFrame(code.length, nLocal, nStack);
             for (int i = 0; i < nLocal; ++i) {
                 if (local[i] instanceof String) {
                     frame[frameIndex++] = Frame.OBJECT
@@ -601,48 +662,44 @@ class MethodWriter extends MethodVisitor {
             }
 
             switch (type) {
-                case Opcodes.F_FULL:
-                    currentLocals = nLocal;
-                    stackMap.putByte(FULL_FRAME)
-                            .putShort(delta)
-                            .putShort(nLocal);
-                    for (int i = 0; i < nLocal; ++i) {
-                        writeFrameType(local[i]);
-                    }
-                    stackMap.putShort(nStack);
-                    for (int i = 0; i < nStack; ++i) {
-                        writeFrameType(stack[i]);
-                    }
-                    break;
-                case Opcodes.F_APPEND:
-                    currentLocals += nLocal;
-                    stackMap.putByte(SAME_FRAME_EXTENDED + nLocal)
-                            .putShort(delta);
-                    for (int i = 0; i < nLocal; ++i) {
-                        writeFrameType(local[i]);
-                    }
-                    break;
-                case Opcodes.F_CHOP:
-                    currentLocals -= nLocal;
-                    stackMap.putByte(SAME_FRAME_EXTENDED - nLocal)
+            case Opcodes.F_FULL:
+                currentLocals = nLocal;
+                stackMap.putByte(FULL_FRAME).putShort(delta).putShort(nLocal);
+                for (int i = 0; i < nLocal; ++i) {
+                    writeFrameType(local[i]);
+                }
+                stackMap.putShort(nStack);
+                for (int i = 0; i < nStack; ++i) {
+                    writeFrameType(stack[i]);
+                }
+                break;
+            case Opcodes.F_APPEND:
+                currentLocals += nLocal;
+                stackMap.putByte(SAME_FRAME_EXTENDED + nLocal).putShort(delta);
+                for (int i = 0; i < nLocal; ++i) {
+                    writeFrameType(local[i]);
+                }
+                break;
+            case Opcodes.F_CHOP:
+                currentLocals -= nLocal;
+                stackMap.putByte(SAME_FRAME_EXTENDED - nLocal).putShort(delta);
+                break;
+            case Opcodes.F_SAME:
+                if (delta < 64) {
+                    stackMap.putByte(delta);
+                } else {
+                    stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
+                }
+                break;
+            case Opcodes.F_SAME1:
+                if (delta < 64) {
+                    stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
+                } else {
+                    stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
                             .putShort(delta);
-                    break;
-                case Opcodes.F_SAME:
-                    if (delta < 64) {
-                        stackMap.putByte(delta);
-                    } else {
-                        stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
-                    }
-                    break;
-                case Opcodes.F_SAME1:
-                    if (delta < 64) {
-                        stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
-                    } else {
-                        stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
-                                .putShort(delta);
-                    }
-                    writeFrameType(stack[0]);
-                    break;
+                }
+                writeFrameType(stack[0]);
+                break;
             }
 
             previousFrameOffset = code.length;
@@ -655,6 +712,7 @@ class MethodWriter extends MethodVisitor {
 
     @Override
     public void visitInsn(final int opcode) {
+        lastCodeOffset = code.length;
         // adds the instruction to the bytecode of the method
         code.putByte(opcode);
         // update currentBlock
@@ -672,8 +730,7 @@ class MethodWriter extends MethodVisitor {
             }
             // if opcode == ATHROW or xRETURN, ends current block (no successor)
             if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
-                    || opcode == Opcodes.ATHROW)
-            {
+                    || opcode == Opcodes.ATHROW) {
                 noSuccessor();
             }
         }
@@ -681,6 +738,7 @@ class MethodWriter extends MethodVisitor {
 
     @Override
     public void visitIntInsn(final int opcode, final int operand) {
+        lastCodeOffset = code.length;
         // Label currentBlock = this.currentBlock;
         if (currentBlock != null) {
             if (compute == FRAMES) {
@@ -705,6 +763,7 @@ class MethodWriter extends MethodVisitor {
 
     @Override
     public void visitVarInsn(final int opcode, final int var) {
+        lastCodeOffset = code.length;
         // Label currentBlock = this.currentBlock;
         if (currentBlock != null) {
             if (compute == FRAMES) {
@@ -731,8 +790,7 @@ class MethodWriter extends MethodVisitor {
             // updates max locals
             int n;
             if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD
-                    || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE)
-            {
+                    || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) {
                 n = var + 2;
             } else {
                 n = var + 1;
@@ -764,6 +822,7 @@ class MethodWriter extends MethodVisitor {
 
     @Override
     public void visitTypeInsn(final int opcode, final String type) {
+        lastCodeOffset = code.length;
         Item i = cw.newClassItem(type);
         // Label currentBlock = this.currentBlock;
         if (currentBlock != null) {
@@ -784,12 +843,9 @@ class MethodWriter 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) {
+        lastCodeOffset = code.length;
         Item i = cw.newFieldItem(owner, name, desc);
         // Label currentBlock = this.currentBlock;
         if (currentBlock != null) {
@@ -800,19 +856,19 @@ class MethodWriter extends MethodVisitor {
                 // computes the stack size variation
                 char c = desc.charAt(0);
                 switch (opcode) {
-                    case Opcodes.GETSTATIC:
-                        size = stackSize + (c == 'D' || c == 'J' ? 2 : 1);
-                        break;
-                    case Opcodes.PUTSTATIC:
-                        size = stackSize + (c == 'D' || c == 'J' ? -2 : -1);
-                        break;
-                    case Opcodes.GETFIELD:
-                        size = stackSize + (c == 'D' || c == 'J' ? 1 : 0);
-                        break;
-                    // case Constants.PUTFIELD:
-                    default:
-                        size = stackSize + (c == 'D' || c == 'J' ? -3 : -2);
-                        break;
+                case Opcodes.GETSTATIC:
+                    size = stackSize + (c == 'D' || c == 'J' ? 2 : 1);
+                    break;
+                case Opcodes.PUTSTATIC:
+                    size = stackSize + (c == 'D' || c == 'J' ? -2 : -1);
+                    break;
+                case Opcodes.GETFIELD:
+                    size = stackSize + (c == 'D' || c == 'J' ? 1 : 0);
+                    break;
+                // case Constants.PUTFIELD:
+                default:
+                    size = stackSize + (c == 'D' || c == 'J' ? -3 : -2);
+                    break;
                 }
                 // updates current and max stack sizes
                 if (size > maxStackSize) {
@@ -826,13 +882,9 @@ class MethodWriter extends MethodVisitor {
     }
 
     @Override
-    public void visitMethodInsn(
-        final int opcode,
-        final String owner,
-        final String name,
-        final String desc)
-    {
-        boolean itf = opcode == Opcodes.INVOKEINTERFACE;
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        lastCodeOffset = code.length;
         Item i = cw.newMethodItem(owner, name, desc, itf);
         int argSize = i.intVal;
         // Label currentBlock = this.currentBlock;
@@ -870,7 +922,7 @@ class MethodWriter extends MethodVisitor {
             }
         }
         // adds the instruction to the bytecode of the method
-        if (itf) {
+        if (opcode == Opcodes.INVOKEINTERFACE) {
             if (argSize == 0) {
                 argSize = Type.getArgumentsAndReturnSizes(desc);
                 i.intVal = argSize;
@@ -882,12 +934,9 @@ class MethodWriter extends MethodVisitor {
     }
 
     @Override
-    public void visitInvokeDynamicInsn(
-        final String name,
-        final String desc,
-        final Handle bsm,
-        final Object... bsmArgs)
-    {
+    public void visitInvokeDynamicInsn(final String name, final String desc,
+            final Handle bsm, final Object... bsmArgs) {
+        lastCodeOffset = code.length;
         Item i = cw.newInvokeDynamicItem(name, desc, bsm, bsmArgs);
         int argSize = i.intVal;
         // Label currentBlock = this.currentBlock;
@@ -927,6 +976,7 @@ class MethodWriter extends MethodVisitor {
 
     @Override
     public void visitJumpInsn(final int opcode, final Label label) {
+        lastCodeOffset = code.length;
         Label nextInsn = null;
         // Label currentBlock = this.currentBlock;
         if (currentBlock != null) {
@@ -967,8 +1017,7 @@ class MethodWriter extends MethodVisitor {
         }
         // adds the instruction to the bytecode of the method
         if ((label.status & Label.RESOLVED) != 0
-                && label.position - code.length < Short.MIN_VALUE)
-        {
+                && label.position - code.length < Short.MIN_VALUE) {
             /*
              * case of a backward jump with an offset < -32768. In this case we
              * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx
@@ -986,8 +1035,7 @@ class MethodWriter extends MethodVisitor {
                 if (nextInsn != null) {
                     nextInsn.status |= Label.TARGET;
                 }
-                code.putByte(opcode <= 166
-                        ? ((opcode + 1) ^ 1) - 1
+                code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
                         : opcode ^ 1);
                 code.putShort(8); // jump offset
                 code.putByte(200); // GOTO_W
@@ -1074,6 +1122,7 @@ class MethodWriter extends MethodVisitor {
 
     @Override
     public void visitLdcInsn(final Object cst) {
+        lastCodeOffset = code.length;
         Item i = cw.newConstItem(cst);
         // Label currentBlock = this.currentBlock;
         if (currentBlock != null) {
@@ -1082,8 +1131,7 @@ class MethodWriter extends MethodVisitor {
             } else {
                 int size;
                 // computes the stack size variation
-                if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE)
-                {
+                if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {
                     size = stackSize + 2;
                 } else {
                     size = stackSize + 1;
@@ -1108,6 +1156,7 @@ class MethodWriter extends MethodVisitor {
 
     @Override
     public void visitIincInsn(final int var, final int increment) {
+        lastCodeOffset = code.length;
         if (currentBlock != null) {
             if (compute == FRAMES) {
                 currentBlock.frame.execute(Opcodes.IINC, var, null, null);
@@ -1122,8 +1171,7 @@ class MethodWriter extends MethodVisitor {
         }
         // adds the instruction to the bytecode of the method
         if ((var > 255) || (increment > 127) || (increment < -128)) {
-            code.putByte(196 /* WIDE */)
-                    .put12(Opcodes.IINC, var)
+            code.putByte(196 /* WIDE */).put12(Opcodes.IINC, var)
                     .putShort(increment);
         } else {
             code.putByte(Opcodes.IINC).put11(var, increment);
@@ -1131,12 +1179,9 @@ class MethodWriter extends MethodVisitor {
     }
 
     @Override
-    public void visitTableSwitchInsn(
-        final int min,
-        final int max,
-        final Label dflt,
-        final Label... labels)
-    {
+    public void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels) {
+        lastCodeOffset = code.length;
         // adds the instruction to the bytecode of the method
         int source = code.length;
         code.putByte(Opcodes.TABLESWITCH);
@@ -1151,11 +1196,9 @@ class MethodWriter extends MethodVisitor {
     }
 
     @Override
-    public void visitLookupSwitchInsn(
-        final Label dflt,
-        final int[] keys,
-        final Label[] labels)
-    {
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
+        lastCodeOffset = code.length;
         // adds the instruction to the bytecode of the method
         int source = code.length;
         code.putByte(Opcodes.LOOKUPSWITCH);
@@ -1198,6 +1241,7 @@ class MethodWriter extends MethodVisitor {
 
     @Override
     public void visitMultiANewArrayInsn(final String desc, final int dims) {
+        lastCodeOffset = code.length;
         Item i = cw.newClassItem(desc);
         // Label currentBlock = this.currentBlock;
         if (currentBlock != null) {
@@ -1214,12 +1258,32 @@ class MethodWriter 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) {
+        if (!ClassReader.ANNOTATIONS) {
+            return null;
+        }
+        ByteVector bv = new ByteVector();
+        // write target_type and target_info
+        typeRef = (typeRef & 0xFF0000FF) | (lastCodeOffset << 8);
+        AnnotationWriter.putTarget(typeRef, typePath, bv);
+        // write type, and reserve space for values count
+        bv.putShort(cw.newUTF8(desc)).putShort(0);
+        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+                bv.length - 2);
+        if (visible) {
+            aw.next = ctanns;
+            ctanns = aw;
+        } else {
+            aw.next = ictanns;
+            ictanns = aw;
+        }
+        return aw;
+    }
+
+    @Override
+    public void visitTryCatchBlock(final Label start, final Label end,
+            final Label handler, final String type) {
         ++handlerCount;
         Handler h = new Handler();
         h.start = start;
@@ -1236,14 +1300,32 @@ class MethodWriter extends MethodVisitor {
     }
 
     @Override
-    public void visitLocalVariable(
-        final String name,
-        final String desc,
-        final String signature,
-        final Label start,
-        final Label end,
-        final int index)
-    {
+    public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        if (!ClassReader.ANNOTATIONS) {
+            return null;
+        }
+        ByteVector bv = new ByteVector();
+        // write target_type and target_info
+        AnnotationWriter.putTarget(typeRef, typePath, bv);
+        // write type, and reserve space for values count
+        bv.putShort(cw.newUTF8(desc)).putShort(0);
+        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+                bv.length - 2);
+        if (visible) {
+            aw.next = ctanns;
+            ctanns = aw;
+        } else {
+            aw.next = ictanns;
+            ictanns = aw;
+        }
+        return aw;
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
         if (signature != null) {
             if (localVarType == null) {
                 localVarType = new ByteVector();
@@ -1251,8 +1333,7 @@ class MethodWriter extends MethodVisitor {
             ++localVarTypeCount;
             localVarType.putShort(start.position)
                     .putShort(end.position - start.position)
-                    .putShort(cw.newUTF8(name))
-                    .putShort(cw.newUTF8(signature))
+                    .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(signature))
                     .putShort(index);
         }
         if (localVar == null) {
@@ -1261,8 +1342,7 @@ class MethodWriter extends MethodVisitor {
         ++localVarCount;
         localVar.putShort(start.position)
                 .putShort(end.position - start.position)
-                .putShort(cw.newUTF8(name))
-                .putShort(cw.newUTF8(desc))
+                .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(desc))
                 .putShort(index);
         if (compute != NOTHING) {
             // updates max locals
@@ -1275,6 +1355,41 @@ class MethodWriter extends MethodVisitor {
     }
 
     @Override
+    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+            TypePath typePath, Label[] start, Label[] end, int[] index,
+            String desc, boolean visible) {
+        if (!ClassReader.ANNOTATIONS) {
+            return null;
+        }
+        ByteVector bv = new ByteVector();
+        // write target_type and target_info
+        bv.putByte(typeRef >>> 24).putShort(start.length);
+        for (int i = 0; i < start.length; ++i) {
+            bv.putShort(start[i].position)
+                    .putShort(end[i].position - start[i].position)
+                    .putShort(index[i]);
+        }
+        if (typePath == null) {
+            bv.putByte(0);
+        } else {
+            int length = typePath.b[typePath.offset] * 2 + 1;
+            bv.putByteArray(typePath.b, typePath.offset, length);
+        }
+        // write type, and reserve space for values count
+        bv.putShort(cw.newUTF8(desc)).putShort(0);
+        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+                bv.length - 2);
+        if (visible) {
+            aw.next = ctanns;
+            ctanns = aw;
+        } else {
+            aw.next = ictanns;
+            ictanns = aw;
+        }
+        return aw;
+    }
+
+    @Override
     public void visitLineNumber(final int line, final Label start) {
         if (lineNumber == null) {
             lineNumber = new ByteVector();
@@ -1286,6 +1401,14 @@ class MethodWriter extends MethodVisitor {
 
     @Override
     public void visitMaxs(final int maxStack, final int maxLocals) {
+        if (resize) {
+            // replaces the temporary jump opcodes introduced by Label.resolve.
+            if (ClassReader.RESIZE) {
+                resizeInstructions();
+            } else {
+                throw new RuntimeException("Method code too large!");
+            }
+        }
         if (ClassReader.FRAMES && compute == FRAMES) {
             // completes the control flow graph with exception handler blocks
             Handler handler = firstHandler;
@@ -1294,8 +1417,7 @@ class MethodWriter extends MethodVisitor {
                 Label h = handler.handler.getFirst();
                 Label e = handler.end.getFirst();
                 // computes the kind of the edges to 'h'
-                String t = handler.desc == null
-                        ? "java/lang/Throwable"
+                String t = handler.desc == null ? "java/lang/Throwable"
                         : handler.desc;
                 int kind = Frame.OBJECT | cw.addType(t);
                 // h is an exception handler
@@ -1382,11 +1504,12 @@ class MethodWriter extends MethodVisitor {
                         }
                         code.data[end] = (byte) Opcodes.ATHROW;
                         // emits a frame for this unreachable block
-                        startFrame(start, 0, 1);
-                        frame[frameIndex++] = Frame.OBJECT
+                        int frameIndex = startFrame(start, 0, 1);
+                        frame[frameIndex] = Frame.OBJECT
                                 | cw.addType("java/lang/Throwable");
                         endFrame();
-                        // removes the start-end range from the exception handlers
+                        // removes the start-end range from the exception
+                        // handlers
                         firstHandler = Handler.remove(firstHandler, l, k);
                     }
                 }
@@ -1534,9 +1657,11 @@ class MethodWriter extends 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.
+     * 
+     * @param info
+     *            information about the control flow edge to be added.
+     * @param successor
+     *            the successor block to be added to the current block.
      */
     private void addSuccessor(final int info, final Label successor) {
         // creates and initializes an Edge object...
@@ -1572,8 +1697,9 @@ class MethodWriter extends MethodVisitor {
 
     /**
      * Visits a frame that has been computed from scratch.
-     *
-     * @param f the frame that must be visited.
+     * 
+     * @param f
+     *            the frame that must be visited.
      */
     private void visitFrame(final Frame f) {
         int i, t;
@@ -1606,7 +1732,7 @@ class MethodWriter extends MethodVisitor {
             }
         }
         // visits the frame and its content
-        startFrame(f.owner.position, nLocal, nStack);
+        int frameIndex = startFrame(f.owner.position, nLocal, nStack);
         for (i = 0; nLocal > 0; ++i, --nLocal) {
             t = locals[i];
             frame[frameIndex++] = t;
@@ -1625,15 +1751,78 @@ class MethodWriter extends MethodVisitor {
     }
 
     /**
+     * Visit the implicit first frame of this method.
+     */
+    private void visitImplicitFirstFrame() {
+        // There can be at most descriptor.length() + 1 locals
+        int frameIndex = startFrame(0, descriptor.length() + 1, 0);
+        if ((access & Opcodes.ACC_STATIC) == 0) {
+            if ((access & ACC_CONSTRUCTOR) == 0) {
+                frame[frameIndex++] = Frame.OBJECT | cw.addType(cw.thisName);
+            } else {
+                frame[frameIndex++] = 6; // Opcodes.UNINITIALIZED_THIS;
+            }
+        }
+        int i = 1;
+        loop: while (true) {
+            int j = i;
+            switch (descriptor.charAt(i++)) {
+            case 'Z':
+            case 'C':
+            case 'B':
+            case 'S':
+            case 'I':
+                frame[frameIndex++] = 1; // Opcodes.INTEGER;
+                break;
+            case 'F':
+                frame[frameIndex++] = 2; // Opcodes.FLOAT;
+                break;
+            case 'J':
+                frame[frameIndex++] = 4; // Opcodes.LONG;
+                break;
+            case 'D':
+                frame[frameIndex++] = 3; // Opcodes.DOUBLE;
+                break;
+            case '[':
+                while (descriptor.charAt(i) == '[') {
+                    ++i;
+                }
+                if (descriptor.charAt(i) == 'L') {
+                    ++i;
+                    while (descriptor.charAt(i) != ';') {
+                        ++i;
+                    }
+                }
+                frame[frameIndex++] = Frame.OBJECT
+                        | cw.addType(descriptor.substring(j, ++i));
+                break;
+            case 'L':
+                while (descriptor.charAt(i) != ';') {
+                    ++i;
+                }
+                frame[frameIndex++] = Frame.OBJECT
+                        | cw.addType(descriptor.substring(j + 1, i++));
+                break;
+            default:
+                break loop;
+            }
+        }
+        frame[1] = frameIndex - 3;
+        endFrame();
+    }
+
+    /**
      * 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.
-     * @param nStack the number of stack elements in the frame.
-     */
-    private void startFrame(final int offset, final int nLocal, final int nStack)
-    {
+     * 
+     * @param offset
+     *            the offset of the instruction to which the frame corresponds.
+     * @param nLocal
+     *            the number of local variables in the frame.
+     * @param nStack
+     *            the number of stack elements in the frame.
+     * @return the index of the next element to be written in this frame.
+     */
+    private int startFrame(final int offset, final int nLocal, final int nStack) {
         int n = 3 + nLocal + nStack;
         if (frame == null || frame.length < n) {
             frame = new int[n];
@@ -1641,7 +1830,7 @@ class MethodWriter extends MethodVisitor {
         frame[0] = offset;
         frame[1] = nLocal;
         frame[2] = nStack;
-        frameIndex = 3;
+        return 3;
     }
 
     /**
@@ -1686,24 +1875,23 @@ class MethodWriter extends MethodVisitor {
         if (cstackSize == 0) {
             k = clocalsSize - localsSize;
             switch (k) {
-                case -3:
-                case -2:
-                case -1:
-                    type = CHOP_FRAME;
-                    localsSize = clocalsSize;
-                    break;
-                case 0:
-                    type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED;
-                    break;
-                case 1:
-                case 2:
-                case 3:
-                    type = APPEND_FRAME;
-                    break;
+            case -3:
+            case -2:
+            case -1:
+                type = CHOP_FRAME;
+                localsSize = clocalsSize;
+                break;
+            case 0:
+                type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED;
+                break;
+            case 1:
+            case 2:
+            case 3:
+                type = APPEND_FRAME;
+                break;
             }
         } else if (clocalsSize == localsSize && cstackSize == 1) {
-            type = delta < 63
-                    ? SAME_LOCALS_1_STACK_ITEM_FRAME
+            type = delta < 63 ? SAME_LOCALS_1_STACK_ITEM_FRAME
                     : SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;
         }
         if (type != FULL_FRAME) {
@@ -1718,36 +1906,34 @@ class MethodWriter extends MethodVisitor {
             }
         }
         switch (type) {
-            case SAME_FRAME:
-                stackMap.putByte(delta);
-                break;
-            case SAME_LOCALS_1_STACK_ITEM_FRAME:
-                stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
-                writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
-                break;
-            case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:
-                stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
-                        .putShort(delta);
-                writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
-                break;
-            case SAME_FRAME_EXTENDED:
-                stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
-                break;
-            case CHOP_FRAME:
-                stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
-                break;
-            case APPEND_FRAME:
-                stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
-                writeFrameTypes(3 + localsSize, 3 + clocalsSize);
-                break;
-            // case FULL_FRAME:
-            default:
-                stackMap.putByte(FULL_FRAME)
-                        .putShort(delta)
-                        .putShort(clocalsSize);
-                writeFrameTypes(3, 3 + clocalsSize);
-                stackMap.putShort(cstackSize);
-                writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);
+        case SAME_FRAME:
+            stackMap.putByte(delta);
+            break;
+        case SAME_LOCALS_1_STACK_ITEM_FRAME:
+            stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
+            writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
+            break;
+        case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:
+            stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED).putShort(
+                    delta);
+            writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
+            break;
+        case SAME_FRAME_EXTENDED:
+            stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
+            break;
+        case CHOP_FRAME:
+            stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
+            break;
+        case APPEND_FRAME:
+            stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
+            writeFrameTypes(3 + localsSize, 3 + clocalsSize);
+            break;
+        // case FULL_FRAME:
+        default:
+            stackMap.putByte(FULL_FRAME).putShort(delta).putShort(clocalsSize);
+            writeFrameTypes(3, 3 + clocalsSize);
+            stackMap.putShort(cstackSize);
+            writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);
         }
     }
 
@@ -1756,9 +1942,11 @@ class MethodWriter extends 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).
+     * 
+     * @param start
+     *            index of the first type in {@link #frame} to write.
+     * @param end
+     *            index of last type in {@link #frame} to write (exclusive).
      */
     private void writeFrameTypes(final int start, final int end) {
         for (int i = start; i < end; ++i) {
@@ -1767,15 +1955,15 @@ class MethodWriter extends MethodVisitor {
             if (d == 0) {
                 int v = t & Frame.BASE_VALUE;
                 switch (t & Frame.BASE_KIND) {
-                    case Frame.OBJECT:
-                        stackMap.putByte(7)
-                                .putShort(cw.newClass(cw.typeTable[v].strVal1));
-                        break;
-                    case Frame.UNINITIALIZED:
-                        stackMap.putByte(8).putShort(cw.typeTable[v].intVal);
-                        break;
-                    default:
-                        stackMap.putByte(v);
+                case Frame.OBJECT:
+                    stackMap.putByte(7).putShort(
+                            cw.newClass(cw.typeTable[v].strVal1));
+                    break;
+                case Frame.UNINITIALIZED:
+                    stackMap.putByte(8).putShort(cw.typeTable[v].intVal);
+                    break;
+                default:
+                    stackMap.putByte(v);
                 }
             } else {
                 StringBuffer buf = new StringBuffer();
@@ -1789,29 +1977,29 @@ class MethodWriter extends MethodVisitor {
                     buf.append(';');
                 } else {
                     switch (t & 0xF) {
-                        case 1:
-                            buf.append('I');
-                            break;
-                        case 2:
-                            buf.append('F');
-                            break;
-                        case 3:
-                            buf.append('D');
-                            break;
-                        case 9:
-                            buf.append('Z');
-                            break;
-                        case 10:
-                            buf.append('B');
-                            break;
-                        case 11:
-                            buf.append('C');
-                            break;
-                        case 12:
-                            buf.append('S');
-                            break;
-                        default:
-                            buf.append('J');
+                    case 1:
+                        buf.append('I');
+                        break;
+                    case 2:
+                        buf.append('F');
+                        break;
+                    case 3:
+                        buf.append('D');
+                        break;
+                    case 9:
+                        buf.append('Z');
+                        break;
+                    case 10:
+                        buf.append('B');
+                        break;
+                    case 11:
+                        buf.append('C');
+                        break;
+                    case 12:
+                        buf.append('S');
+                        break;
+                    default:
+                        buf.append('J');
                     }
                 }
                 stackMap.putByte(7).putShort(cw.newClass(buf.toString()));
@@ -1835,21 +2023,13 @@ class MethodWriter extends MethodVisitor {
 
     /**
      * Returns the size of the bytecode of this method.
-     *
+     * 
      * @return the size of the bytecode of this method.
      */
     final int getSize() {
         if (classReaderOffset != 0) {
             return 6 + classReaderLength;
         }
-        if (resize) {
-            // replaces the temporary jump opcodes introduced by Label.resolve.
-            if (ClassReader.RESIZE) {
-                resizeInstructions();
-            } else {
-                throw new RuntimeException("Method code too large!");
-            }
-        }
         int size = 8;
         if (code.length > 0) {
             if (code.length > 65536) {
@@ -1874,11 +2054,16 @@ class MethodWriter extends MethodVisitor {
                 cw.newUTF8(zip ? "StackMapTable" : "StackMap");
                 size += 8 + stackMap.length;
             }
+            if (ClassReader.ANNOTATIONS && ctanns != null) {
+                cw.newUTF8("RuntimeVisibleTypeAnnotations");
+                size += 8 + ctanns.getSize();
+            }
+            if (ClassReader.ANNOTATIONS && ictanns != null) {
+                cw.newUTF8("RuntimeInvisibleTypeAnnotations");
+                size += 8 + ictanns.getSize();
+            }
             if (cattrs != null) {
-                size += cattrs.getSize(cw,
-                        code.data,
-                        code.length,
-                        maxStack,
+                size += cattrs.getSize(cw, code.data, code.length, maxStack,
                         maxLocals);
             }
         }
@@ -1886,11 +2071,12 @@ class MethodWriter extends MethodVisitor {
             cw.newUTF8("Exceptions");
             size += 8 + 2 * exceptionCount;
         }
-        if ((access & Opcodes.ACC_SYNTHETIC) != 0
-                && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
-        {
-            cw.newUTF8("Synthetic");
-            size += 6;
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            if ((cw.version & 0xFFFF) < Opcodes.V1_5
+                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+                cw.newUTF8("Synthetic");
+                size += 6;
+            }
         }
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             cw.newUTF8("Deprecated");
@@ -1901,6 +2087,10 @@ class MethodWriter extends MethodVisitor {
             cw.newUTF8(signature);
             size += 8;
         }
+        if (methodParameters != null) {
+            cw.newUTF8("MethodParameters");
+            size += 7 + methodParameters.length;
+        }
         if (ClassReader.ANNOTATIONS && annd != null) {
             cw.newUTF8("AnnotationDefault");
             size += 6 + annd.length;
@@ -1913,6 +2103,14 @@ class MethodWriter extends MethodVisitor {
             cw.newUTF8("RuntimeInvisibleAnnotations");
             size += 8 + ianns.getSize();
         }
+        if (ClassReader.ANNOTATIONS && tanns != null) {
+            cw.newUTF8("RuntimeVisibleTypeAnnotations");
+            size += 8 + tanns.getSize();
+        }
+        if (ClassReader.ANNOTATIONS && itanns != null) {
+            cw.newUTF8("RuntimeInvisibleTypeAnnotations");
+            size += 8 + itanns.getSize();
+        }
         if (ClassReader.ANNOTATIONS && panns != null) {
             cw.newUTF8("RuntimeVisibleParameterAnnotations");
             size += 7 + 2 * (panns.length - synthetics);
@@ -1935,14 +2133,16 @@ class MethodWriter extends 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.
+     * 
+     * @param out
+     *            the byte vector into which the bytecode of this method must be
+     *            copied.
      */
     final void put(final ByteVector out) {
-        int mask = Opcodes.ACC_DEPRECATED
+        final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
+        int mask = ACC_CONSTRUCTOR | Opcodes.ACC_DEPRECATED
                 | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
-                | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC));
+                | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
         out.putShort(access & ~mask).putShort(name).putShort(desc);
         if (classReaderOffset != 0) {
             out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength);
@@ -1955,10 +2155,11 @@ class MethodWriter extends MethodVisitor {
         if (exceptionCount > 0) {
             ++attributeCount;
         }
-        if ((access & Opcodes.ACC_SYNTHETIC) != 0
-                && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
-        {
-            ++attributeCount;
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            if ((cw.version & 0xFFFF) < Opcodes.V1_5
+                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+                ++attributeCount;
+            }
         }
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             ++attributeCount;
@@ -1966,6 +2167,9 @@ class MethodWriter extends MethodVisitor {
         if (ClassReader.SIGNATURES && signature != null) {
             ++attributeCount;
         }
+        if (methodParameters != null) {
+            ++attributeCount;
+        }
         if (ClassReader.ANNOTATIONS && annd != null) {
             ++attributeCount;
         }
@@ -1975,6 +2179,12 @@ class MethodWriter extends MethodVisitor {
         if (ClassReader.ANNOTATIONS && ianns != null) {
             ++attributeCount;
         }
+        if (ClassReader.ANNOTATIONS && tanns != null) {
+            ++attributeCount;
+        }
+        if (ClassReader.ANNOTATIONS && itanns != null) {
+            ++attributeCount;
+        }
         if (ClassReader.ANNOTATIONS && panns != null) {
             ++attributeCount;
         }
@@ -1999,11 +2209,14 @@ class MethodWriter extends MethodVisitor {
             if (stackMap != null) {
                 size += 8 + stackMap.length;
             }
+            if (ClassReader.ANNOTATIONS && ctanns != null) {
+                size += 8 + ctanns.getSize();
+            }
+            if (ClassReader.ANNOTATIONS && ictanns != null) {
+                size += 8 + ictanns.getSize();
+            }
             if (cattrs != null) {
-                size += cattrs.getSize(cw,
-                        code.data,
-                        code.length,
-                        maxStack,
+                size += cattrs.getSize(cw, code.data, code.length, maxStack,
                         maxLocals);
             }
             out.putShort(cw.newUTF8("Code")).putInt(size);
@@ -2013,10 +2226,8 @@ class MethodWriter extends MethodVisitor {
             if (handlerCount > 0) {
                 Handler h = firstHandler;
                 while (h != null) {
-                    out.putShort(h.start.position)
-                            .putShort(h.end.position)
-                            .putShort(h.handler.position)
-                            .putShort(h.type);
+                    out.putShort(h.start.position).putShort(h.end.position)
+                            .putShort(h.handler.position).putShort(h.type);
                     h = h.next;
                 }
             }
@@ -2033,6 +2244,12 @@ class MethodWriter extends MethodVisitor {
             if (stackMap != null) {
                 ++attributeCount;
             }
+            if (ClassReader.ANNOTATIONS && ctanns != null) {
+                ++attributeCount;
+            }
+            if (ClassReader.ANNOTATIONS && ictanns != null) {
+                ++attributeCount;
+            }
             if (cattrs != null) {
                 attributeCount += cattrs.getCount();
             }
@@ -2058,31 +2275,45 @@ class MethodWriter extends MethodVisitor {
                 out.putInt(stackMap.length + 2).putShort(frameCount);
                 out.putByteArray(stackMap.data, 0, stackMap.length);
             }
+            if (ClassReader.ANNOTATIONS && ctanns != null) {
+                out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
+                ctanns.put(out);
+            }
+            if (ClassReader.ANNOTATIONS && ictanns != null) {
+                out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
+                ictanns.put(out);
+            }
             if (cattrs != null) {
                 cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out);
             }
         }
         if (exceptionCount > 0) {
-            out.putShort(cw.newUTF8("Exceptions"))
-                    .putInt(2 * exceptionCount + 2);
+            out.putShort(cw.newUTF8("Exceptions")).putInt(
+                    2 * exceptionCount + 2);
             out.putShort(exceptionCount);
             for (int i = 0; i < exceptionCount; ++i) {
                 out.putShort(exceptions[i]);
             }
         }
-        if ((access & Opcodes.ACC_SYNTHETIC) != 0
-                && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
-        {
-            out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            if ((cw.version & 0xFFFF) < Opcodes.V1_5
+                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+                out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+            }
         }
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             out.putShort(cw.newUTF8("Deprecated")).putInt(0);
         }
         if (ClassReader.SIGNATURES && signature != null) {
-            out.putShort(cw.newUTF8("Signature"))
-                    .putInt(2)
+            out.putShort(cw.newUTF8("Signature")).putInt(2)
                     .putShort(cw.newUTF8(signature));
         }
+        if (methodParameters != null) {
+            out.putShort(cw.newUTF8("MethodParameters"));
+            out.putInt(methodParameters.length + 1).putByte(
+                    methodParametersCount);
+            out.putByteArray(methodParameters.data, 0, methodParameters.length);
+        }
         if (ClassReader.ANNOTATIONS && annd != null) {
             out.putShort(cw.newUTF8("AnnotationDefault"));
             out.putInt(annd.length);
@@ -2096,6 +2327,14 @@ class MethodWriter extends MethodVisitor {
             out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
             ianns.put(out);
         }
+        if (ClassReader.ANNOTATIONS && tanns != null) {
+            out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
+            tanns.put(out);
+        }
+        if (ClassReader.ANNOTATIONS && itanns != null) {
+            out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
+            itanns.put(out);
+        }
         if (ClassReader.ANNOTATIONS && panns != null) {
             out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations"));
             AnnotationWriter.put(panns, synthetics, out);
@@ -2123,10 +2362,12 @@ class MethodWriter extends MethodVisitor {
      * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W
      * 32765. This, in turn, may require to increase the size of another jump
      * instruction, and so on... All these operations are handled automatically
-     * by this method. <p> <i>This method must be called after all the method
-     * that is being built has been visited</i>. In particular, the
-     * {@link Label Label} objects used to construct the method are no longer
-     * valid after this method has been called.
+     * by this method.
+     * <p>
+     * <i>This method must be called after all the method that is being built
+     * has been visited</i>. In particular, the {@link Label Label} objects used
+     * to construct the method are no longer valid after this method has been
+     * called.
      */
     private void resizeInstructions() {
         byte[] b = code.data; // bytecode of the method
@@ -2138,17 +2379,17 @@ class MethodWriter extends 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
@@ -2176,158 +2417,14 @@ class MethodWriter extends MethodVisitor {
                 int insert = 0; // bytes to be added after this instruction
 
                 switch (ClassWriter.TYPE[opcode]) {
-                    case ClassWriter.NOARG_INSN:
-                    case ClassWriter.IMPLVAR_INSN:
-                        u += 1;
-                        break;
-                    case ClassWriter.LABEL_INSN:
-                        if (opcode > 201) {
-                            // converts temporary opcodes 202 to 217, 218 and
-                            // 219 to IFEQ ... JSR (inclusive), IFNULL and
-                            // IFNONNULL
-                            opcode = opcode < 218 ? opcode - 49 : opcode - 20;
-                            label = u + readUnsignedShort(b, u + 1);
-                        } else {
-                            label = u + readShort(b, u + 1);
-                        }
-                        newOffset = getNewOffset(allIndexes, allSizes, u, label);
-                        if (newOffset < Short.MIN_VALUE
-                                || newOffset > Short.MAX_VALUE)
-                        {
-                            if (!resize[u]) {
-                                if (opcode == Opcodes.GOTO
-                                        || opcode == Opcodes.JSR)
-                                {
-                                    // two additional bytes will be required to
-                                    // replace this GOTO or JSR instruction with
-                                    // a GOTO_W or a JSR_W
-                                    insert = 2;
-                                } else {
-                                    // five additional bytes will be required to
-                                    // replace this IFxxx <l> instruction with
-                                    // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx
-                                    // is the "opposite" opcode of IFxxx (i.e.,
-                                    // IFNE for IFEQ) and where <l'> designates
-                                    // the instruction just after the GOTO_W.
-                                    insert = 5;
-                                }
-                                resize[u] = true;
-                            }
-                        }
-                        u += 3;
-                        break;
-                    case ClassWriter.LABELW_INSN:
-                        u += 5;
-                        break;
-                    case ClassWriter.TABL_INSN:
-                        if (state == 1) {
-                            // true number of bytes to be added (or removed)
-                            // from this instruction = (future number of padding
-                            // bytes - current number of padding byte) -
-                            // previously over estimated variation =
-                            // = ((3 - newOffset%4) - (3 - u%4)) - u%4
-                            // = (-newOffset%4 + u%4) - u%4
-                            // = -(newOffset & 3)
-                            newOffset = getNewOffset(allIndexes, allSizes, 0, u);
-                            insert = -(newOffset & 3);
-                        } else if (!resize[u]) {
-                            // over estimation of the number of bytes to be
-                            // added to this instruction = 3 - current number
-                            // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3
-                            insert = u & 3;
-                            resize[u] = true;
-                        }
-                        // skips instruction
-                        u = u + 4 - (u & 3);
-                        u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12;
-                        break;
-                    case ClassWriter.LOOK_INSN:
-                        if (state == 1) {
-                            // like TABL_INSN
-                            newOffset = getNewOffset(allIndexes, allSizes, 0, u);
-                            insert = -(newOffset & 3);
-                        } else if (!resize[u]) {
-                            // like TABL_INSN
-                            insert = u & 3;
-                            resize[u] = true;
-                        }
-                        // skips instruction
-                        u = u + 4 - (u & 3);
-                        u += 8 * readInt(b, u + 4) + 8;
-                        break;
-                    case ClassWriter.WIDE_INSN:
-                        opcode = b[u + 1] & 0xFF;
-                        if (opcode == Opcodes.IINC) {
-                            u += 6;
-                        } else {
-                            u += 4;
-                        }
-                        break;
-                    case ClassWriter.VAR_INSN:
-                    case ClassWriter.SBYTE_INSN:
-                    case ClassWriter.LDC_INSN:
-                        u += 2;
-                        break;
-                    case ClassWriter.SHORT_INSN:
-                    case ClassWriter.LDCW_INSN:
-                    case ClassWriter.FIELDORMETH_INSN:
-                    case ClassWriter.TYPE_INSN:
-                    case ClassWriter.IINC_INSN:
-                        u += 3;
-                        break;
-                    case ClassWriter.ITFMETH_INSN:
-                    case ClassWriter.INDYMETH_INSN:
-                        u += 5;
-                        break;
-                    // case ClassWriter.MANA_INSN:
-                    default:
-                        u += 4;
-                        break;
-                }
-                if (insert != 0) {
-                    // adds a new (u, insert) entry in the allIndexes and
-                    // allSizes arrays
-                    int[] newIndexes = new int[allIndexes.length + 1];
-                    int[] newSizes = new int[allSizes.length + 1];
-                    System.arraycopy(allIndexes,
-                            0,
-                            newIndexes,
-                            0,
-                            allIndexes.length);
-                    System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length);
-                    newIndexes[allIndexes.length] = u;
-                    newSizes[allSizes.length] = insert;
-                    allIndexes = newIndexes;
-                    allSizes = newSizes;
-                    if (insert > 0) {
-                        state = 3;
-                    }
-                }
-            }
-            if (state < 3) {
-                --state;
-            }
-        } while (state != 0);
-
-        // 2nd step:
-        // copies the bytecode of the method into a new bytevector, updates the
-        // offsets, and inserts (or removes) bytes as requested.
-
-        ByteVector newCode = new ByteVector(code.length);
-
-        u = 0;
-        while (u < code.length) {
-            int opcode = b[u] & 0xFF;
-            switch (ClassWriter.TYPE[opcode]) {
                 case ClassWriter.NOARG_INSN:
                 case ClassWriter.IMPLVAR_INSN:
-                    newCode.putByte(opcode);
                     u += 1;
                     break;
                 case ClassWriter.LABEL_INSN:
                     if (opcode > 201) {
-                        // changes temporary opcodes 202 to 217 (inclusive), 218
-                        // and 219 to IFEQ ... JSR (inclusive), IFNULL and
+                        // converts temporary opcodes 202 to 217, 218 and
+                        // 219 to IFEQ ... JSR (inclusive), IFNULL and
                         // IFNONNULL
                         opcode = opcode < 218 ? opcode - 49 : opcode - 20;
                         label = u + readUnsignedShort(b, u + 1);
@@ -2335,100 +2432,78 @@ class MethodWriter extends MethodVisitor {
                         label = u + readShort(b, u + 1);
                     }
                     newOffset = getNewOffset(allIndexes, allSizes, u, label);
-                    if (resize[u]) {
-                        // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
-                        // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is
-                        // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
-                        // and where <l'> designates the instruction just after
-                        // the GOTO_W.
-                        if (opcode == Opcodes.GOTO) {
-                            newCode.putByte(200); // GOTO_W
-                        } else if (opcode == Opcodes.JSR) {
-                            newCode.putByte(201); // JSR_W
-                        } else {
-                            newCode.putByte(opcode <= 166
-                                    ? ((opcode + 1) ^ 1) - 1
-                                    : opcode ^ 1);
-                            newCode.putShort(8); // jump offset
-                            newCode.putByte(200); // GOTO_W
-                            // newOffset now computed from start of GOTO_W
-                            newOffset -= 3;
+                    if (newOffset < Short.MIN_VALUE
+                            || newOffset > Short.MAX_VALUE) {
+                        if (!resize[u]) {
+                            if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
+                                // two additional bytes will be required to
+                                // replace this GOTO or JSR instruction with
+                                // a GOTO_W or a JSR_W
+                                insert = 2;
+                            } else {
+                                // five additional bytes will be required to
+                                // replace this IFxxx <l> instruction with
+                                // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx
+                                // is the "opposite" opcode of IFxxx (i.e.,
+                                // IFNE for IFEQ) and where <l'> designates
+                                // the instruction just after the GOTO_W.
+                                insert = 5;
+                            }
+                            resize[u] = true;
                         }
-                        newCode.putInt(newOffset);
-                    } else {
-                        newCode.putByte(opcode);
-                        newCode.putShort(newOffset);
                     }
                     u += 3;
                     break;
                 case ClassWriter.LABELW_INSN:
-                    label = u + readInt(b, u + 1);
-                    newOffset = getNewOffset(allIndexes, allSizes, u, label);
-                    newCode.putByte(opcode);
-                    newCode.putInt(newOffset);
                     u += 5;
                     break;
                 case ClassWriter.TABL_INSN:
-                    // skips 0 to 3 padding bytes
-                    v = u;
-                    u = u + 4 - (v & 3);
-                    // reads and copies instruction
-                    newCode.putByte(Opcodes.TABLESWITCH);
-                    newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
-                    label = v + readInt(b, u);
-                    u += 4;
-                    newOffset = getNewOffset(allIndexes, allSizes, v, label);
-                    newCode.putInt(newOffset);
-                    j = readInt(b, u);
-                    u += 4;
-                    newCode.putInt(j);
-                    j = readInt(b, u) - j + 1;
-                    u += 4;
-                    newCode.putInt(readInt(b, u - 4));
-                    for (; j > 0; --j) {
-                        label = v + readInt(b, u);
-                        u += 4;
-                        newOffset = getNewOffset(allIndexes, allSizes, v, label);
-                        newCode.putInt(newOffset);
+                    if (state == 1) {
+                        // true number of bytes to be added (or removed)
+                        // from this instruction = (future number of padding
+                        // bytes - current number of padding byte) -
+                        // previously over estimated variation =
+                        // = ((3 - newOffset%4) - (3 - u%4)) - u%4
+                        // = (-newOffset%4 + u%4) - u%4
+                        // = -(newOffset & 3)
+                        newOffset = getNewOffset(allIndexes, allSizes, 0, u);
+                        insert = -(newOffset & 3);
+                    } else if (!resize[u]) {
+                        // over estimation of the number of bytes to be
+                        // added to this instruction = 3 - current number
+                        // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3
+                        insert = u & 3;
+                        resize[u] = true;
                     }
+                    // skips instruction
+                    u = u + 4 - (u & 3);
+                    u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12;
                     break;
                 case ClassWriter.LOOK_INSN:
-                    // skips 0 to 3 padding bytes
-                    v = u;
-                    u = u + 4 - (v & 3);
-                    // reads and copies instruction
-                    newCode.putByte(Opcodes.LOOKUPSWITCH);
-                    newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
-                    label = v + readInt(b, u);
-                    u += 4;
-                    newOffset = getNewOffset(allIndexes, allSizes, v, label);
-                    newCode.putInt(newOffset);
-                    j = readInt(b, u);
-                    u += 4;
-                    newCode.putInt(j);
-                    for (; j > 0; --j) {
-                        newCode.putInt(readInt(b, u));
-                        u += 4;
-                        label = v + readInt(b, u);
-                        u += 4;
-                        newOffset = getNewOffset(allIndexes, allSizes, v, label);
-                        newCode.putInt(newOffset);
+                    if (state == 1) {
+                        // like TABL_INSN
+                        newOffset = getNewOffset(allIndexes, allSizes, 0, u);
+                        insert = -(newOffset & 3);
+                    } else if (!resize[u]) {
+                        // like TABL_INSN
+                        insert = u & 3;
+                        resize[u] = true;
                     }
+                    // skips instruction
+                    u = u + 4 - (u & 3);
+                    u += 8 * readInt(b, u + 4) + 8;
                     break;
                 case ClassWriter.WIDE_INSN:
                     opcode = b[u + 1] & 0xFF;
                     if (opcode == Opcodes.IINC) {
-                        newCode.putByteArray(b, u, 6);
                         u += 6;
                     } else {
-                        newCode.putByteArray(b, u, 4);
                         u += 4;
                     }
                     break;
                 case ClassWriter.VAR_INSN:
                 case ClassWriter.SBYTE_INSN:
                 case ClassWriter.LDC_INSN:
-                    newCode.putByteArray(b, u, 2);
                     u += 2;
                     break;
                 case ClassWriter.SHORT_INSN:
@@ -2436,66 +2511,225 @@ class MethodWriter extends MethodVisitor {
                 case ClassWriter.FIELDORMETH_INSN:
                 case ClassWriter.TYPE_INSN:
                 case ClassWriter.IINC_INSN:
-                    newCode.putByteArray(b, u, 3);
                     u += 3;
                     break;
                 case ClassWriter.ITFMETH_INSN:
                 case ClassWriter.INDYMETH_INSN:
-                    newCode.putByteArray(b, u, 5);
                     u += 5;
                     break;
-                // case MANA_INSN:
+                // case ClassWriter.MANA_INSN:
                 default:
-                    newCode.putByteArray(b, u, 4);
                     u += 4;
                     break;
+                }
+                if (insert != 0) {
+                    // adds a new (u, insert) entry in the allIndexes and
+                    // allSizes arrays
+                    int[] newIndexes = new int[allIndexes.length + 1];
+                    int[] newSizes = new int[allSizes.length + 1];
+                    System.arraycopy(allIndexes, 0, newIndexes, 0,
+                            allIndexes.length);
+                    System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length);
+                    newIndexes[allIndexes.length] = u;
+                    newSizes[allSizes.length] = insert;
+                    allIndexes = newIndexes;
+                    allSizes = newSizes;
+                    if (insert > 0) {
+                        state = 3;
+                    }
+                }
             }
-        }
+            if (state < 3) {
+                --state;
+            }
+        } while (state != 0);
 
-        // recomputes the stack map frames
-        if (frameCount > 0) {
-            if (compute == FRAMES) {
-                frameCount = 0;
-                stackMap = null;
-                previousFrame = null;
-                frame = null;
-                Frame f = new Frame();
-                f.owner = labels;
-                Type[] args = Type.getArgumentTypes(descriptor);
-                f.initInputFrame(cw, access, args, maxLocals);
-                visitFrame(f);
-                Label l = labels;
-                while (l != null) {
-                    /*
-                     * here we need the original label position. getNewOffset
-                     * must therefore never have been called for this label.
-                     */
-                    u = l.position - 3;
-                    if ((l.status & Label.STORE) != 0 || (u >= 0 && resize[u]))
-                    {
-                        getNewOffset(allIndexes, allSizes, l);
-                        // TODO update offsets in UNINITIALIZED values
-                        visitFrame(l.frame);
+        // 2nd step:
+        // copies the bytecode of the method into a new bytevector, updates the
+        // offsets, and inserts (or removes) bytes as requested.
+
+        ByteVector newCode = new ByteVector(code.length);
+
+        u = 0;
+        while (u < code.length) {
+            int opcode = b[u] & 0xFF;
+            switch (ClassWriter.TYPE[opcode]) {
+            case ClassWriter.NOARG_INSN:
+            case ClassWriter.IMPLVAR_INSN:
+                newCode.putByte(opcode);
+                u += 1;
+                break;
+            case ClassWriter.LABEL_INSN:
+                if (opcode > 201) {
+                    // changes temporary opcodes 202 to 217 (inclusive), 218
+                    // and 219 to IFEQ ... JSR (inclusive), IFNULL and
+                    // IFNONNULL
+                    opcode = opcode < 218 ? opcode - 49 : opcode - 20;
+                    label = u + readUnsignedShort(b, u + 1);
+                } else {
+                    label = u + readShort(b, u + 1);
+                }
+                newOffset = getNewOffset(allIndexes, allSizes, u, label);
+                if (resize[u]) {
+                    // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
+                    // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is
+                    // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
+                    // and where <l'> designates the instruction just after
+                    // the GOTO_W.
+                    if (opcode == Opcodes.GOTO) {
+                        newCode.putByte(200); // GOTO_W
+                    } else if (opcode == Opcodes.JSR) {
+                        newCode.putByte(201); // JSR_W
+                    } else {
+                        newCode.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
+                                : opcode ^ 1);
+                        newCode.putShort(8); // jump offset
+                        newCode.putByte(200); // GOTO_W
+                        // newOffset now computed from start of GOTO_W
+                        newOffset -= 3;
                     }
-                    l = l.successor;
+                    newCode.putInt(newOffset);
+                } else {
+                    newCode.putByte(opcode);
+                    newCode.putShort(newOffset);
                 }
-            } else {
+                u += 3;
+                break;
+            case ClassWriter.LABELW_INSN:
+                label = u + readInt(b, u + 1);
+                newOffset = getNewOffset(allIndexes, allSizes, u, label);
+                newCode.putByte(opcode);
+                newCode.putInt(newOffset);
+                u += 5;
+                break;
+            case ClassWriter.TABL_INSN:
+                // skips 0 to 3 padding bytes
+                v = u;
+                u = u + 4 - (v & 3);
+                // reads and copies instruction
+                newCode.putByte(Opcodes.TABLESWITCH);
+                newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
+                label = v + readInt(b, u);
+                u += 4;
+                newOffset = getNewOffset(allIndexes, allSizes, v, label);
+                newCode.putInt(newOffset);
+                j = readInt(b, u);
+                u += 4;
+                newCode.putInt(j);
+                j = readInt(b, u) - j + 1;
+                u += 4;
+                newCode.putInt(readInt(b, u - 4));
+                for (; j > 0; --j) {
+                    label = v + readInt(b, u);
+                    u += 4;
+                    newOffset = getNewOffset(allIndexes, allSizes, v, label);
+                    newCode.putInt(newOffset);
+                }
+                break;
+            case ClassWriter.LOOK_INSN:
+                // skips 0 to 3 padding bytes
+                v = u;
+                u = u + 4 - (v & 3);
+                // reads and copies instruction
+                newCode.putByte(Opcodes.LOOKUPSWITCH);
+                newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
+                label = v + readInt(b, u);
+                u += 4;
+                newOffset = getNewOffset(allIndexes, allSizes, v, label);
+                newCode.putInt(newOffset);
+                j = readInt(b, u);
+                u += 4;
+                newCode.putInt(j);
+                for (; j > 0; --j) {
+                    newCode.putInt(readInt(b, u));
+                    u += 4;
+                    label = v + readInt(b, u);
+                    u += 4;
+                    newOffset = getNewOffset(allIndexes, allSizes, v, label);
+                    newCode.putInt(newOffset);
+                }
+                break;
+            case ClassWriter.WIDE_INSN:
+                opcode = b[u + 1] & 0xFF;
+                if (opcode == Opcodes.IINC) {
+                    newCode.putByteArray(b, u, 6);
+                    u += 6;
+                } else {
+                    newCode.putByteArray(b, u, 4);
+                    u += 4;
+                }
+                break;
+            case ClassWriter.VAR_INSN:
+            case ClassWriter.SBYTE_INSN:
+            case ClassWriter.LDC_INSN:
+                newCode.putByteArray(b, u, 2);
+                u += 2;
+                break;
+            case ClassWriter.SHORT_INSN:
+            case ClassWriter.LDCW_INSN:
+            case ClassWriter.FIELDORMETH_INSN:
+            case ClassWriter.TYPE_INSN:
+            case ClassWriter.IINC_INSN:
+                newCode.putByteArray(b, u, 3);
+                u += 3;
+                break;
+            case ClassWriter.ITFMETH_INSN:
+            case ClassWriter.INDYMETH_INSN:
+                newCode.putByteArray(b, u, 5);
+                u += 5;
+                break;
+            // case MANA_INSN:
+            default:
+                newCode.putByteArray(b, u, 4);
+                u += 4;
+                break;
+            }
+        }
+
+        // updates the stack map frame labels
+        if (compute == FRAMES) {
+            Label l = labels;
+            while (l != null) {
                 /*
-                 * Resizing an existing stack map frame table is really hard.
-                 * Not only the table must be parsed to update the offets, but
-                 * new frames may be needed for jump instructions that were
-                 * inserted by this method. And updating the offsets or
-                 * inserting frames can change the format of the following
-                 * frames, in case of packed frames. In practice the whole table
-                 * must be recomputed. For this the frames are marked as
-                 * potentially invalid. This will cause the whole class to be
-                 * reread and rewritten with the COMPUTE_FRAMES option (see the
-                 * ClassWriter.toByteArray method). This is not very efficient
-                 * but is much easier and requires much less code than any other
-                 * method I can think of.
+                 * Detects the labels that are just after an IF instruction that
+                 * has been resized with the IFNOT GOTO_W pattern. These labels
+                 * are now the target of a jump instruction (the IFNOT
+                 * instruction). Note that we need the original label position
+                 * here. getNewOffset must therefore never have been called for
+                 * this label.
                  */
-                cw.invalidFrames = true;
+                u = l.position - 3;
+                if (u >= 0 && resize[u]) {
+                    l.status |= Label.TARGET;
+                }
+                getNewOffset(allIndexes, allSizes, l);
+                l = l.successor;
+            }
+            // Update the offsets in the uninitialized types
+            for (i = 0; i < cw.typeTable.length; ++i) {
+                Item item = cw.typeTable[i];
+                if (item != null && item.type == ClassWriter.TYPE_UNINIT) {
+                    item.intVal = getNewOffset(allIndexes, allSizes, 0,
+                            item.intVal);
+                }
             }
+            // The stack map frames are not serialized yet, so we don't need
+            // to update them. They will be serialized in visitMaxs.
+        } else if (frameCount > 0) {
+            /*
+             * Resizing an existing stack map frame table is really hard. Not
+             * only the table must be parsed to update the offets, but new
+             * frames may be needed for jump instructions that were inserted by
+             * this method. And updating the offsets or inserting frames can
+             * change the format of the following frames, in case of packed
+             * frames. In practice the whole table must be recomputed. For this
+             * the frames are marked as potentially invalid. This will cause the
+             * whole class to be reread and rewritten with the COMPUTE_FRAMES
+             * option (see the ClassWriter.toByteArray method). This is not very
+             * efficient but is much easier and requires much less code than any
+             * other method I can think of.
+             */
+            cw.invalidFrames = true;
         }
         // updates the exception handler block labels
         Handler h = firstHandler;
@@ -2528,10 +2762,11 @@ class MethodWriter extends MethodVisitor {
             b = lineNumber.data;
             u = 0;
             while (u < lineNumber.length) {
-                writeShort(b, u, getNewOffset(allIndexes,
-                        allSizes,
-                        0,
-                        readUnsignedShort(b, u)));
+                writeShort(
+                        b,
+                        u,
+                        getNewOffset(allIndexes, allSizes, 0,
+                                readUnsignedShort(b, u)));
                 u += 4;
             }
         }
@@ -2553,9 +2788,11 @@ class MethodWriter extends 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.
+     * 
+     * @param b
+     *            a byte array.
+     * @param index
+     *            the start index of the value to be read.
      * @return the read value.
      */
     static int readUnsignedShort(final byte[] b, final int index) {
@@ -2564,9 +2801,11 @@ class MethodWriter extends 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.
+     * 
+     * @param b
+     *            a byte array.
+     * @param index
+     *            the start index of the value to be read.
      * @return the read value.
      */
     static short readShort(final byte[] b, final int index) {
@@ -2575,9 +2814,11 @@ class MethodWriter extends 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.
+     * 
+     * @param b
+     *            a byte array.
+     * @param index
+     *            the start index of the value to be read.
      * @return the read value.
      */
     static int readInt(final byte[] b, final int index) {
@@ -2587,10 +2828,13 @@ class MethodWriter extends 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.
+     * 
+     * @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.
      */
     static void writeShort(final byte[] b, final int index, final int s) {
         b[index] = (byte) (s >>> 8);
@@ -2598,32 +2842,34 @@ class MethodWriter extends MethodVisitor {
     }
 
     /**
-     * Computes the future value of a bytecode offset. <p> Note: it is possible
-     * 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').
-     *


<TRUNCATED>

[06/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java
new file mode 100644
index 0000000..294fd46
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java
@@ -0,0 +1,1009 @@
+/***
+ * 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.util;
+
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+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;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+import org.apache.tapestry5.internal.plastic.asm.tree.ClassNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.Analyzer;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicValue;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.Frame;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.SimpleVerifier;
+
+/**
+ * A {@link ClassVisitor} that checks that its methods are properly used. More
+ * precisely this class adapter checks each method call individually, based
+ * <i>only</i> on its arguments, but does <i>not</i> check the <i>sequence</i>
+ * of method calls. For example, the invalid sequence
+ * <tt>visitField(ACC_PUBLIC, "i", "I", null)</tt> <tt>visitField(ACC_PUBLIC,
+ * "i", "D", null)</tt> will <i>not</i> be detected by this class adapter.
+ * 
+ * <p>
+ * <code>CheckClassAdapter</code> can be also used to verify bytecode
+ * transformations in order to make sure transformed bytecode is sane. For
+ * example:
+ * 
+ * <pre>
+ *   InputStream is = ...; // get bytes for the source class
+ *   ClassReader cr = new ClassReader(is);
+ *   ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
+ *   ClassVisitor cv = new <b>MyClassAdapter</b>(new CheckClassAdapter(cw));
+ *   cr.accept(cv, 0);
+ * 
+ *   StringWriter sw = new StringWriter();
+ *   PrintWriter pw = new PrintWriter(sw);
+ *   CheckClassAdapter.verify(new ClassReader(cw.toByteArray()), false, pw);
+ *   assertTrue(sw.toString(), sw.toString().length()==0);
+ * </pre>
+ * 
+ * Above code runs transformed bytecode trough the
+ * <code>CheckClassAdapter</code>. It won't be exactly the same verification as
+ * JVM does, but it run data flow analysis for the code of each method and
+ * checks that expectations are met for each method instruction.
+ * 
+ * <p>
+ * If method bytecode has errors, assertion text will show the erroneous
+ * instruction number and dump of the failed method with information about
+ * locals and stack slot for each instruction. For example (format is -
+ * insnNumber locals : stack):
+ * 
+ * <pre>
+ * org.objectweb.asm.tree.analysis.AnalyzerException: Error at instruction 71: Expected I, but found .
+ *   at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:289)
+ *   at org.objectweb.asm.util.CheckClassAdapter.verify(CheckClassAdapter.java:135)
+ * ...
+ * remove()V
+ * 00000 LinkedBlockingQueue$Itr . . . . . . . .  :
+ *   ICONST_0
+ * 00001 LinkedBlockingQueue$Itr . . . . . . . .  : I
+ *   ISTORE 2
+ * 00001 LinkedBlockingQueue$Itr <b>.</b> I . . . . . .  :
+ * ...
+ * 
+ * 00071 LinkedBlockingQueue$Itr <b>.</b> I . . . . . .  :
+ *   ILOAD 1
+ * 00072 <b>?</b>
+ *   INVOKESPECIAL java/lang/Integer.&lt;init&gt; (I)V
+ * ...
+ * </pre>
+ * 
+ * In the above output you can see that variable 1 loaded by
+ * <code>ILOAD 1</code> instruction at position <code>00071</code> is not
+ * initialized. You can also see that at the beginning of the method (code
+ * inserted by the transformation) variable 2 is initialized.
+ * 
+ * <p>
+ * Note that when used like that, <code>CheckClassAdapter.verify()</code> can
+ * trigger additional class loading, because it is using
+ * <code>SimpleVerifier</code>.
+ * 
+ * @author Eric Bruneton
+ */
+public class CheckClassAdapter extends ClassVisitor {
+
+    /**
+     * The class version number.
+     */
+    private int version;
+
+    /**
+     * <tt>true</tt> if the visit method has been called.
+     */
+    private boolean start;
+
+    /**
+     * <tt>true</tt> if the visitSource method has been called.
+     */
+    private boolean source;
+
+    /**
+     * <tt>true</tt> if the visitOuterClass method has been called.
+     */
+    private boolean outer;
+
+    /**
+     * <tt>true</tt> if the visitEnd method has been called.
+     */
+    private boolean end;
+
+    /**
+     * The already visited labels. This map associate Integer values to Label
+     * keys.
+     */
+    private Map<Label, Integer> labels;
+
+    /**
+     * <tt>true</tt> if the method code must be checked with a BasicVerifier.
+     */
+    private boolean checkDataFlow;
+
+    /**
+     * Checks a given class.
+     * <p>
+     * Usage: CheckClassAdapter &lt;binary class name or class file name&gt;
+     * 
+     * @param args
+     *            the command line arguments.
+     * 
+     * @throws Exception
+     *             if the class cannot be found, or if an IO exception occurs.
+     */
+    public static void main(final String[] args) throws Exception {
+        if (args.length != 1) {
+            System.err.println("Verifies the given class.");
+            System.err.println("Usage: CheckClassAdapter "
+                    + "<fully qualified class name or class file name>");
+            return;
+        }
+        ClassReader cr;
+        if (args[0].endsWith(".class")) {
+            cr = new ClassReader(new FileInputStream(args[0]));
+        } else {
+            cr = new ClassReader(args[0]);
+        }
+
+        verify(cr, false, new PrintWriter(System.err));
+    }
+
+    /**
+     * Checks a given class.
+     * 
+     * @param cr
+     *            a <code>ClassReader</code> that contains bytecode for the
+     *            analysis.
+     * @param loader
+     *            a <code>ClassLoader</code> which will be used to load
+     *            referenced classes. This is useful if you are verifiying
+     *            multiple interdependent classes.
+     * @param dump
+     *            true if bytecode should be printed out not only when errors
+     *            are found.
+     * @param pw
+     *            write where results going to be printed
+     */
+    public static void verify(final ClassReader cr, final ClassLoader loader,
+            final boolean dump, final PrintWriter pw) {
+        ClassNode cn = new ClassNode();
+        cr.accept(new CheckClassAdapter(cn, false), ClassReader.SKIP_DEBUG);
+
+        Type syperType = cn.superName == null ? null : Type
+                .getObjectType(cn.superName);
+        List<MethodNode> methods = cn.methods;
+
+        List<Type> interfaces = new ArrayList<Type>();
+        for (Iterator<String> i = cn.interfaces.iterator(); i.hasNext();) {
+            interfaces.add(Type.getObjectType(i.next()));
+        }
+
+        for (int i = 0; i < methods.size(); ++i) {
+            MethodNode method = methods.get(i);
+            SimpleVerifier verifier = new SimpleVerifier(
+                    Type.getObjectType(cn.name), syperType, interfaces,
+                    (cn.access & Opcodes.ACC_INTERFACE) != 0);
+            Analyzer<BasicValue> a = new Analyzer<BasicValue>(verifier);
+            if (loader != null) {
+                verifier.setClassLoader(loader);
+            }
+            try {
+                a.analyze(cn.name, method);
+                if (!dump) {
+                    continue;
+                }
+            } catch (Exception e) {
+                e.printStackTrace(pw);
+            }
+            printAnalyzerResult(method, a, pw);
+        }
+        pw.flush();
+    }
+
+    /**
+     * Checks a given class
+     * 
+     * @param cr
+     *            a <code>ClassReader</code> that contains bytecode for the
+     *            analysis.
+     * @param dump
+     *            true if bytecode should be printed out not only when errors
+     *            are found.
+     * @param pw
+     *            write where results going to be printed
+     */
+    public static void verify(final ClassReader cr, final boolean dump,
+            final PrintWriter pw) {
+        verify(cr, null, dump, pw);
+    }
+
+    static void printAnalyzerResult(MethodNode method, Analyzer<BasicValue> a,
+            final PrintWriter pw) {
+        Frame<BasicValue>[] frames = a.getFrames();
+        Textifier t = new Textifier();
+        TraceMethodVisitor mv = new TraceMethodVisitor(t);
+
+        pw.println(method.name + method.desc);
+        for (int j = 0; j < method.instructions.size(); ++j) {
+            method.instructions.get(j).accept(mv);
+
+            StringBuffer s = new StringBuffer();
+            Frame<BasicValue> f = frames[j];
+            if (f == null) {
+                s.append('?');
+            } else {
+                for (int k = 0; k < f.getLocals(); ++k) {
+                    s.append(getShortName(f.getLocal(k).toString()))
+                            .append(' ');
+                }
+                s.append(" : ");
+                for (int k = 0; k < f.getStackSize(); ++k) {
+                    s.append(getShortName(f.getStack(k).toString()))
+                            .append(' ');
+                }
+            }
+            while (s.length() < method.maxStack + method.maxLocals + 1) {
+                s.append(' ');
+            }
+            pw.print(Integer.toString(j + 100000).substring(1));
+            pw.print(" " + s + " : " + t.text.get(t.text.size() - 1));
+        }
+        for (int j = 0; j < method.tryCatchBlocks.size(); ++j) {
+            method.tryCatchBlocks.get(j).accept(mv);
+            pw.print(" " + t.text.get(t.text.size() - 1));
+        }
+        pw.println();
+    }
+
+    private static String getShortName(final String name) {
+        int n = name.lastIndexOf('/');
+        int k = name.length();
+        if (name.charAt(k - 1) == ';') {
+            k--;
+        }
+        return n == -1 ? name : name.substring(n + 1, k);
+    }
+
+    /**
+     * Constructs a new {@link CheckClassAdapter}. <i>Subclasses must not use
+     * this constructor</i>. Instead, they must use the
+     * {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version.
+     * 
+     * @param cv
+     *            the class visitor to which this adapter must delegate calls.
+     */
+    public CheckClassAdapter(final ClassVisitor cv) {
+        this(cv, true);
+    }
+
+    /**
+     * Constructs a new {@link CheckClassAdapter}. <i>Subclasses must not use
+     * this constructor</i>. Instead, they must use the
+     * {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version.
+     * 
+     * @param cv
+     *            the class visitor to which this adapter must delegate calls.
+     * @param checkDataFlow
+     *            <tt>true</tt> to perform basic data flow checks, or
+     *            <tt>false</tt> to not perform any data flow check (see
+     *            {@link CheckMethodAdapter}). This option requires valid
+     *            maxLocals and maxStack values.
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public CheckClassAdapter(final ClassVisitor cv, final boolean checkDataFlow) {
+        this(Opcodes.ASM5, cv, checkDataFlow);
+        if (getClass() != CheckClassAdapter.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Constructs a new {@link CheckClassAdapter}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param cv
+     *            the class visitor to which this adapter must delegate calls.
+     * @param checkDataFlow
+     *            <tt>true</tt> to perform basic data flow checks, or
+     *            <tt>false</tt> to not perform any data flow check (see
+     *            {@link CheckMethodAdapter}). This option requires valid
+     *            maxLocals and maxStack values.
+     */
+    protected CheckClassAdapter(final int api, final ClassVisitor cv,
+            final boolean checkDataFlow) {
+        super(api, cv);
+        this.labels = new HashMap<Label, Integer>();
+        this.checkDataFlow = checkDataFlow;
+    }
+
+    // ------------------------------------------------------------------------
+    // Implementation of the ClassVisitor interface
+    // ------------------------------------------------------------------------
+
+    @Override
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
+        if (start) {
+            throw new IllegalStateException("visit must be called only once");
+        }
+        start = true;
+        checkState();
+        checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL
+                + Opcodes.ACC_SUPER + Opcodes.ACC_INTERFACE
+                + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
+                + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM
+                + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+        if (name == null || !name.endsWith("package-info")) {
+            CheckMethodAdapter.checkInternalName(name, "class name");
+        }
+        if ("java/lang/Object".equals(name)) {
+            if (superName != null) {
+                throw new IllegalArgumentException(
+                        "The super class name of the Object class must be 'null'");
+            }
+        } else {
+            CheckMethodAdapter.checkInternalName(superName, "super class name");
+        }
+        if (signature != null) {
+            checkClassSignature(signature);
+        }
+        if ((access & Opcodes.ACC_INTERFACE) != 0) {
+            if (!"java/lang/Object".equals(superName)) {
+                throw new IllegalArgumentException(
+                        "The super class name of interfaces must be 'java/lang/Object'");
+            }
+        }
+        if (interfaces != null) {
+            for (int i = 0; i < interfaces.length; ++i) {
+                CheckMethodAdapter.checkInternalName(interfaces[i],
+                        "interface name at index " + i);
+            }
+        }
+        this.version = version;
+        super.visit(version, access, name, signature, superName, interfaces);
+    }
+
+    @Override
+    public void visitSource(final String file, final String debug) {
+        checkState();
+        if (source) {
+            throw new IllegalStateException(
+                    "visitSource can be called only once.");
+        }
+        source = true;
+        super.visitSource(file, debug);
+    }
+
+    @Override
+    public void visitOuterClass(final String owner, final String name,
+            final String desc) {
+        checkState();
+        if (outer) {
+            throw new IllegalStateException(
+                    "visitOuterClass can be called only once.");
+        }
+        outer = true;
+        if (owner == null) {
+            throw new IllegalArgumentException("Illegal outer class owner");
+        }
+        if (desc != null) {
+            CheckMethodAdapter.checkMethodDesc(desc);
+        }
+        super.visitOuterClass(owner, name, desc);
+    }
+
+    @Override
+    public void visitInnerClass(final String name, final String outerName,
+            final String innerName, final int access) {
+        checkState();
+        CheckMethodAdapter.checkInternalName(name, "class name");
+        if (outerName != null) {
+            CheckMethodAdapter.checkInternalName(outerName, "outer class name");
+        }
+        if (innerName != null) {
+            int start = 0;
+            while (start < innerName.length()
+                    && Character.isDigit(innerName.charAt(start))) {
+                start++;
+            }
+            if (start == 0 || start < innerName.length()) {
+                CheckMethodAdapter.checkIdentifier(innerName, start, -1,
+                        "inner class name");
+            }
+        }
+        checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+                + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+                + Opcodes.ACC_FINAL + Opcodes.ACC_INTERFACE
+                + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
+                + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM);
+        super.visitInnerClass(name, outerName, innerName, access);
+    }
+
+    @Override
+    public FieldVisitor visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
+        checkState();
+        checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+                + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+                + Opcodes.ACC_FINAL + Opcodes.ACC_VOLATILE
+                + Opcodes.ACC_TRANSIENT + Opcodes.ACC_SYNTHETIC
+                + Opcodes.ACC_ENUM + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+        CheckMethodAdapter.checkUnqualifiedName(version, name, "field name");
+        CheckMethodAdapter.checkDesc(desc, false);
+        if (signature != null) {
+            checkFieldSignature(signature);
+        }
+        if (value != null) {
+            CheckMethodAdapter.checkConstant(value);
+        }
+        FieldVisitor av = super
+                .visitField(access, name, desc, signature, value);
+        return new CheckFieldAdapter(av);
+    }
+
+    @Override
+    public MethodVisitor visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        checkState();
+        checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+                + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+                + Opcodes.ACC_FINAL + Opcodes.ACC_SYNCHRONIZED
+                + Opcodes.ACC_BRIDGE + Opcodes.ACC_VARARGS + Opcodes.ACC_NATIVE
+                + Opcodes.ACC_ABSTRACT + Opcodes.ACC_STRICT
+                + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+        if (!"<init>".equals(name) && !"<clinit>".equals(name)) {
+            CheckMethodAdapter.checkMethodIdentifier(version, name,
+                    "method name");
+        }
+        CheckMethodAdapter.checkMethodDesc(desc);
+        if (signature != null) {
+            checkMethodSignature(signature);
+        }
+        if (exceptions != null) {
+            for (int i = 0; i < exceptions.length; ++i) {
+                CheckMethodAdapter.checkInternalName(exceptions[i],
+                        "exception name at index " + i);
+            }
+        }
+        CheckMethodAdapter cma;
+        if (checkDataFlow) {
+            cma = new CheckMethodAdapter(access, name, desc, super.visitMethod(
+                    access, name, desc, signature, exceptions), labels);
+        } else {
+            cma = new CheckMethodAdapter(super.visitMethod(access, name, desc,
+                    signature, exceptions), labels);
+        }
+        cma.version = version;
+        return cma;
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        checkState();
+        CheckMethodAdapter.checkDesc(desc, false);
+        return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        checkState();
+        int sort = typeRef >>> 24;
+        if (sort != TypeReference.CLASS_TYPE_PARAMETER
+                && sort != TypeReference.CLASS_TYPE_PARAMETER_BOUND
+                && sort != TypeReference.CLASS_EXTENDS) {
+            throw new IllegalArgumentException("Invalid type reference sort 0x"
+                    + Integer.toHexString(sort));
+        }
+        checkTypeRefAndPath(typeRef, typePath);
+        CheckMethodAdapter.checkDesc(desc, false);
+        return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef,
+                typePath, desc, visible));
+    }
+
+    @Override
+    public void visitAttribute(final Attribute attr) {
+        checkState();
+        if (attr == null) {
+            throw new IllegalArgumentException(
+                    "Invalid attribute (must not be null)");
+        }
+        super.visitAttribute(attr);
+    }
+
+    @Override
+    public void visitEnd() {
+        checkState();
+        end = true;
+        super.visitEnd();
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Checks that the visit method has been called and that visitEnd has not
+     * been called.
+     */
+    private void checkState() {
+        if (!start) {
+            throw new IllegalStateException(
+                    "Cannot visit member before visit has been called.");
+        }
+        if (end) {
+            throw new IllegalStateException(
+                    "Cannot visit member after visitEnd has been called.");
+        }
+    }
+
+    /**
+     * Checks that the given access flags do not contain invalid flags. This
+     * method also checks that mutually incompatible flags are not set
+     * simultaneously.
+     * 
+     * @param access
+     *            the access flags to be checked
+     * @param possibleAccess
+     *            the valid access flags.
+     */
+    static void checkAccess(final int access, final int possibleAccess) {
+        if ((access & ~possibleAccess) != 0) {
+            throw new IllegalArgumentException("Invalid access flags: "
+                    + access);
+        }
+        int pub = (access & Opcodes.ACC_PUBLIC) == 0 ? 0 : 1;
+        int pri = (access & Opcodes.ACC_PRIVATE) == 0 ? 0 : 1;
+        int pro = (access & Opcodes.ACC_PROTECTED) == 0 ? 0 : 1;
+        if (pub + pri + pro > 1) {
+            throw new IllegalArgumentException(
+                    "public private and protected are mutually exclusive: "
+                            + access);
+        }
+        int fin = (access & Opcodes.ACC_FINAL) == 0 ? 0 : 1;
+        int abs = (access & Opcodes.ACC_ABSTRACT) == 0 ? 0 : 1;
+        if (fin + abs > 1) {
+            throw new IllegalArgumentException(
+                    "final and abstract are mutually exclusive: " + access);
+        }
+    }
+
+    /**
+     * Checks a class signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     */
+    public static void checkClassSignature(final String signature) {
+        // ClassSignature:
+        // FormalTypeParameters? ClassTypeSignature ClassTypeSignature*
+
+        int pos = 0;
+        if (getChar(signature, 0) == '<') {
+            pos = checkFormalTypeParameters(signature, pos);
+        }
+        pos = checkClassTypeSignature(signature, pos);
+        while (getChar(signature, pos) == 'L') {
+            pos = checkClassTypeSignature(signature, pos);
+        }
+        if (pos != signature.length()) {
+            throw new IllegalArgumentException(signature + ": error at index "
+                    + pos);
+        }
+    }
+
+    /**
+     * Checks a method signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     */
+    public static void checkMethodSignature(final String signature) {
+        // MethodTypeSignature:
+        // FormalTypeParameters? ( TypeSignature* ) ( TypeSignature | V ) (
+        // ^ClassTypeSignature | ^TypeVariableSignature )*
+
+        int pos = 0;
+        if (getChar(signature, 0) == '<') {
+            pos = checkFormalTypeParameters(signature, pos);
+        }
+        pos = checkChar('(', signature, pos);
+        while ("ZCBSIFJDL[T".indexOf(getChar(signature, pos)) != -1) {
+            pos = checkTypeSignature(signature, pos);
+        }
+        pos = checkChar(')', signature, pos);
+        if (getChar(signature, pos) == 'V') {
+            ++pos;
+        } else {
+            pos = checkTypeSignature(signature, pos);
+        }
+        while (getChar(signature, pos) == '^') {
+            ++pos;
+            if (getChar(signature, pos) == 'L') {
+                pos = checkClassTypeSignature(signature, pos);
+            } else {
+                pos = checkTypeVariableSignature(signature, pos);
+            }
+        }
+        if (pos != signature.length()) {
+            throw new IllegalArgumentException(signature + ": error at index "
+                    + pos);
+        }
+    }
+
+    /**
+     * Checks a field signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     */
+    public static void checkFieldSignature(final String signature) {
+        int pos = checkFieldTypeSignature(signature, 0);
+        if (pos != signature.length()) {
+            throw new IllegalArgumentException(signature + ": error at index "
+                    + pos);
+        }
+    }
+
+    /**
+     * Checks the reference to a type in a type annotation.
+     * 
+     * @param typeRef
+     *            a reference to an annotated type.
+     * @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.
+     */
+    static void checkTypeRefAndPath(int typeRef, TypePath typePath) {
+        int mask = 0;
+        switch (typeRef >>> 24) {
+        case TypeReference.CLASS_TYPE_PARAMETER:
+        case TypeReference.METHOD_TYPE_PARAMETER:
+        case TypeReference.METHOD_FORMAL_PARAMETER:
+            mask = 0xFFFF0000;
+            break;
+        case TypeReference.FIELD:
+        case TypeReference.METHOD_RETURN:
+        case TypeReference.METHOD_RECEIVER:
+        case TypeReference.LOCAL_VARIABLE:
+        case TypeReference.RESOURCE_VARIABLE:
+        case TypeReference.INSTANCEOF:
+        case TypeReference.NEW:
+        case TypeReference.CONSTRUCTOR_REFERENCE:
+        case TypeReference.METHOD_REFERENCE:
+            mask = 0xFF000000;
+            break;
+        case TypeReference.CLASS_EXTENDS:
+        case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
+        case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
+        case TypeReference.THROWS:
+        case TypeReference.EXCEPTION_PARAMETER:
+            mask = 0xFFFFFF00;
+            break;
+        case TypeReference.CAST:
+        case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
+        case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT:
+        case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
+        case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT:
+            mask = 0xFF0000FF;
+            break;
+        default:
+            throw new IllegalArgumentException("Invalid type reference sort 0x"
+                    + Integer.toHexString(typeRef >>> 24));
+        }
+        if ((typeRef & ~mask) != 0) {
+            throw new IllegalArgumentException("Invalid type reference 0x"
+                    + Integer.toHexString(typeRef));
+        }
+        if (typePath != null) {
+            for (int i = 0; i < typePath.getLength(); ++i) {
+                int step = typePath.getStep(i);
+                if (step != TypePath.ARRAY_ELEMENT
+                        && step != TypePath.INNER_TYPE
+                        && step != TypePath.TYPE_ARGUMENT
+                        && step != TypePath.WILDCARD_BOUND) {
+                    throw new IllegalArgumentException(
+                            "Invalid type path step " + i + " in " + typePath);
+                }
+                if (step != TypePath.TYPE_ARGUMENT
+                        && typePath.getStepArgument(i) != 0) {
+                    throw new IllegalArgumentException(
+                            "Invalid type path step argument for step " + i
+                                    + " in " + typePath);
+                }
+            }
+        }
+    }
+
+    /**
+     * Checks the formal type parameters of a class or method signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkFormalTypeParameters(final String signature, int pos) {
+        // FormalTypeParameters:
+        // < FormalTypeParameter+ >
+
+        pos = checkChar('<', signature, pos);
+        pos = checkFormalTypeParameter(signature, pos);
+        while (getChar(signature, pos) != '>') {
+            pos = checkFormalTypeParameter(signature, pos);
+        }
+        return pos + 1;
+    }
+
+    /**
+     * Checks a formal type parameter of a class or method signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkFormalTypeParameter(final String signature, int pos) {
+        // FormalTypeParameter:
+        // Identifier : FieldTypeSignature? (: FieldTypeSignature)*
+
+        pos = checkIdentifier(signature, pos);
+        pos = checkChar(':', signature, pos);
+        if ("L[T".indexOf(getChar(signature, pos)) != -1) {
+            pos = checkFieldTypeSignature(signature, pos);
+        }
+        while (getChar(signature, pos) == ':') {
+            pos = checkFieldTypeSignature(signature, pos + 1);
+        }
+        return pos;
+    }
+
+    /**
+     * Checks a field type signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkFieldTypeSignature(final String signature, int pos) {
+        // FieldTypeSignature:
+        // ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature
+        //
+        // ArrayTypeSignature:
+        // [ TypeSignature
+
+        switch (getChar(signature, pos)) {
+        case 'L':
+            return checkClassTypeSignature(signature, pos);
+        case '[':
+            return checkTypeSignature(signature, pos + 1);
+        default:
+            return checkTypeVariableSignature(signature, pos);
+        }
+    }
+
+    /**
+     * Checks a class type signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkClassTypeSignature(final String signature, int pos) {
+        // ClassTypeSignature:
+        // L Identifier ( / Identifier )* TypeArguments? ( . Identifier
+        // TypeArguments? )* ;
+
+        pos = checkChar('L', signature, pos);
+        pos = checkIdentifier(signature, pos);
+        while (getChar(signature, pos) == '/') {
+            pos = checkIdentifier(signature, pos + 1);
+        }
+        if (getChar(signature, pos) == '<') {
+            pos = checkTypeArguments(signature, pos);
+        }
+        while (getChar(signature, pos) == '.') {
+            pos = checkIdentifier(signature, pos + 1);
+            if (getChar(signature, pos) == '<') {
+                pos = checkTypeArguments(signature, pos);
+            }
+        }
+        return checkChar(';', signature, pos);
+    }
+
+    /**
+     * Checks the type arguments in a class type signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkTypeArguments(final String signature, int pos) {
+        // TypeArguments:
+        // < TypeArgument+ >
+
+        pos = checkChar('<', signature, pos);
+        pos = checkTypeArgument(signature, pos);
+        while (getChar(signature, pos) != '>') {
+            pos = checkTypeArgument(signature, pos);
+        }
+        return pos + 1;
+    }
+
+    /**
+     * Checks a type argument in a class type signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkTypeArgument(final String signature, int pos) {
+        // TypeArgument:
+        // * | ( ( + | - )? FieldTypeSignature )
+
+        char c = getChar(signature, pos);
+        if (c == '*') {
+            return pos + 1;
+        } else if (c == '+' || c == '-') {
+            pos++;
+        }
+        return checkFieldTypeSignature(signature, pos);
+    }
+
+    /**
+     * Checks a type variable signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkTypeVariableSignature(final String signature,
+            int pos) {
+        // TypeVariableSignature:
+        // T Identifier ;
+
+        pos = checkChar('T', signature, pos);
+        pos = checkIdentifier(signature, pos);
+        return checkChar(';', signature, pos);
+    }
+
+    /**
+     * Checks a type signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkTypeSignature(final String signature, int pos) {
+        // TypeSignature:
+        // Z | C | B | S | I | F | J | D | FieldTypeSignature
+
+        switch (getChar(signature, pos)) {
+        case 'Z':
+        case 'C':
+        case 'B':
+        case 'S':
+        case 'I':
+        case 'F':
+        case 'J':
+        case 'D':
+            return pos + 1;
+        default:
+            return checkFieldTypeSignature(signature, pos);
+        }
+    }
+
+    /**
+     * Checks an identifier.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkIdentifier(final String signature, int pos) {
+        if (!Character.isJavaIdentifierStart(getChar(signature, pos))) {
+            throw new IllegalArgumentException(signature
+                    + ": identifier expected at index " + pos);
+        }
+        ++pos;
+        while (Character.isJavaIdentifierPart(getChar(signature, pos))) {
+            ++pos;
+        }
+        return pos;
+    }
+
+    /**
+     * Checks a single character.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkChar(final char c, final String signature, int pos) {
+        if (getChar(signature, pos) == c) {
+            return pos + 1;
+        }
+        throw new IllegalArgumentException(signature + ": '" + c
+                + "' expected at index " + pos);
+    }
+
+    /**
+     * Returns the signature car at the given index.
+     * 
+     * @param signature
+     *            a signature.
+     * @param pos
+     *            an index in signature.
+     * @return the character at the given index, or 0 if there is no such
+     *         character.
+     */
+    private static char getChar(final String signature, int pos) {
+        return pos < signature.length() ? signature.charAt(pos) : (char) 0;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java
new file mode 100644
index 0000000..753025b
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java
@@ -0,0 +1,122 @@
+/***
+ * 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.util;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+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 {@link FieldVisitor} that checks that its methods are properly used.
+ */
+public class CheckFieldAdapter extends FieldVisitor {
+
+    private boolean end;
+
+    /**
+     * Constructs a new {@link CheckFieldAdapter}. <i>Subclasses must not use
+     * this constructor</i>. Instead, they must use the
+     * {@link #CheckFieldAdapter(int, FieldVisitor)} version.
+     * 
+     * @param fv
+     *            the field visitor to which this adapter must delegate calls.
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public CheckFieldAdapter(final FieldVisitor fv) {
+        this(Opcodes.ASM5, fv);
+        if (getClass() != CheckFieldAdapter.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Constructs a new {@link CheckFieldAdapter}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param fv
+     *            the field visitor to which this adapter must delegate calls.
+     */
+    protected CheckFieldAdapter(final int api, final FieldVisitor fv) {
+        super(api, fv);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        checkEnd();
+        CheckMethodAdapter.checkDesc(desc, false);
+        return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        checkEnd();
+        int sort = typeRef >>> 24;
+        if (sort != TypeReference.FIELD) {
+            throw new IllegalArgumentException("Invalid type reference sort 0x"
+                    + Integer.toHexString(sort));
+        }
+        CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+        CheckMethodAdapter.checkDesc(desc, false);
+        return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef,
+                typePath, desc, visible));
+    }
+
+    @Override
+    public void visitAttribute(final Attribute attr) {
+        checkEnd();
+        if (attr == null) {
+            throw new IllegalArgumentException(
+                    "Invalid attribute (must not be null)");
+        }
+        super.visitAttribute(attr);
+    }
+
+    @Override
+    public void visitEnd() {
+        checkEnd();
+        end = true;
+        super.visitEnd();
+    }
+
+    private void checkEnd() {
+        if (end) {
+            throw new IllegalStateException(
+                    "Cannot call a visit method after visitEnd has been called");
+        }
+    }
+}


[02/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java
new file mode 100644
index 0000000..6d5715c
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java
@@ -0,0 +1,1044 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * 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.xml;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.Templates;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.ClassWriter;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/**
+ * Processor is a command line tool that can be used for bytecode waving
+ * directed by XSL transformation.
+ * <p>
+ * In order to use a concrete XSLT engine, system property
+ * <tt>javax.xml.transform.TransformerFactory</tt> must be set to one of the
+ * following values.
+ * 
+ * <blockquote>
+ * <table border="1" cellspacing="0" cellpadding="3">
+ * <tr>
+ * <td>jd.xslt</td>
+ * <td>jd.xml.xslt.trax.TransformerFactoryImpl</td>
+ * </tr>
+ * 
+ * <tr>
+ * <td>Saxon</td>
+ * <td>net.sf.saxon.TransformerFactoryImpl</td>
+ * </tr>
+ * 
+ * <tr>
+ * <td>Caucho</td>
+ * <td>com.caucho.xsl.Xsl</td>
+ * </tr>
+ * 
+ * <tr>
+ * <td>Xalan interpeter</td>
+ * <td>org.apache.xalan.processor.TransformerFactory</td>
+ * </tr>
+ * 
+ * <tr>
+ * <td>Xalan xsltc</td>
+ * <td>org.apache.xalan.xsltc.trax.TransformerFactoryImpl</td>
+ * </tr>
+ * </table>
+ * </blockquote>
+ * 
+ * @author Eugene Kuleshov
+ */
+public class Processor {
+
+    public static final int BYTECODE = 1;
+
+    public static final int MULTI_XML = 2;
+
+    public static final int SINGLE_XML = 3;
+
+    private static final String SINGLE_XML_NAME = "classes.xml";
+
+    private final int inRepresentation;
+
+    private final int outRepresentation;
+
+    private final InputStream input;
+
+    private final OutputStream output;
+
+    private final Source xslt;
+
+    private int n = 0;
+
+    public Processor(final int inRepresenation, final int outRepresentation,
+            final InputStream input, final OutputStream output,
+            final Source xslt) {
+        this.inRepresentation = inRepresenation;
+        this.outRepresentation = outRepresentation;
+        this.input = input;
+        this.output = output;
+        this.xslt = xslt;
+    }
+
+    public int process() throws TransformerException, IOException, SAXException {
+        ZipInputStream zis = new ZipInputStream(input);
+        final ZipOutputStream zos = new ZipOutputStream(output);
+        final OutputStreamWriter osw = new OutputStreamWriter(zos);
+
+        Thread.currentThread().setContextClassLoader(
+                getClass().getClassLoader());
+
+        TransformerFactory tf = TransformerFactory.newInstance();
+        if (!tf.getFeature(SAXSource.FEATURE)
+                || !tf.getFeature(SAXResult.FEATURE)) {
+            return 0;
+        }
+
+        SAXTransformerFactory saxtf = (SAXTransformerFactory) tf;
+        Templates templates = null;
+        if (xslt != null) {
+            templates = saxtf.newTemplates(xslt);
+        }
+
+        // configuring outHandlerFactory
+        // ///////////////////////////////////////////////////////
+
+        EntryElement entryElement = getEntryElement(zos);
+
+        ContentHandler outDocHandler = null;
+        switch (outRepresentation) {
+        case BYTECODE:
+            outDocHandler = new OutputSlicingHandler(
+                    new ASMContentHandlerFactory(zos), entryElement, false);
+            break;
+
+        case MULTI_XML:
+            outDocHandler = new OutputSlicingHandler(new SAXWriterFactory(osw,
+                    true), entryElement, true);
+            break;
+
+        case SINGLE_XML:
+            ZipEntry outputEntry = new ZipEntry(SINGLE_XML_NAME);
+            zos.putNextEntry(outputEntry);
+            outDocHandler = new SAXWriter(osw, false);
+            break;
+
+        }
+
+        // configuring inputDocHandlerFactory
+        // /////////////////////////////////////////////////
+        ContentHandler inDocHandler;
+        if (templates == null) {
+            inDocHandler = outDocHandler;
+        } else {
+            inDocHandler = new InputSlicingHandler("class", outDocHandler,
+                    new TransformerHandlerFactory(saxtf, templates,
+                            outDocHandler));
+        }
+        ContentHandlerFactory inDocHandlerFactory = new SubdocumentHandlerFactory(
+                inDocHandler);
+
+        if (inDocHandler != null && inRepresentation != SINGLE_XML) {
+            inDocHandler.startDocument();
+            inDocHandler.startElement("", "classes", "classes",
+                    new AttributesImpl());
+        }
+
+        int i = 0;
+        ZipEntry ze;
+        while ((ze = zis.getNextEntry()) != null) {
+            update(ze.getName(), n++);
+            if (isClassEntry(ze)) {
+                processEntry(zis, ze, inDocHandlerFactory);
+            } else {
+                OutputStream os = entryElement.openEntry(getName(ze));
+                copyEntry(zis, os);
+                entryElement.closeEntry();
+            }
+
+            i++;
+        }
+
+        if (inDocHandler != null && inRepresentation != SINGLE_XML) {
+            inDocHandler.endElement("", "classes", "classes");
+            inDocHandler.endDocument();
+        }
+
+        if (outRepresentation == SINGLE_XML) {
+            zos.closeEntry();
+        }
+        zos.flush();
+        zos.close();
+
+        return i;
+    }
+
+    private void copyEntry(final InputStream is, final OutputStream os)
+            throws IOException {
+        if (outRepresentation == SINGLE_XML) {
+            return;
+        }
+
+        byte[] buff = new byte[2048];
+        int i;
+        while ((i = is.read(buff)) != -1) {
+            os.write(buff, 0, i);
+        }
+    }
+
+    private boolean isClassEntry(final ZipEntry ze) {
+        String name = ze.getName();
+        return inRepresentation == SINGLE_XML && name.equals(SINGLE_XML_NAME)
+                || name.endsWith(".class") || name.endsWith(".class.xml");
+    }
+
+    private void processEntry(final ZipInputStream zis, final ZipEntry ze,
+            final ContentHandlerFactory handlerFactory) {
+        ContentHandler handler = handlerFactory.createContentHandler();
+        try {
+
+            // if (CODE2ASM.equals(command)) { // read bytecode and process it
+            // // with TraceClassVisitor
+            // ClassReader cr = new ClassReader(readEntry(zis, ze));
+            // cr.accept(new TraceClassVisitor(null, new PrintWriter(os)),
+            // false);
+            // }
+
+            boolean singleInputDocument = inRepresentation == SINGLE_XML;
+            if (inRepresentation == BYTECODE) { // read bytecode and process it
+                // with handler
+                ClassReader cr = new ClassReader(readEntry(zis, ze));
+                cr.accept(new SAXClassAdapter(handler, singleInputDocument), 0);
+
+            } else { // read XML and process it with handler
+                XMLReader reader = XMLReaderFactory.createXMLReader();
+                reader.setContentHandler(handler);
+                reader.parse(new InputSource(
+                        singleInputDocument ? (InputStream) new ProtectedInputStream(
+                                zis) : new ByteArrayInputStream(readEntry(zis,
+                                ze))));
+
+            }
+        } catch (Exception ex) {
+            update(ze.getName(), 0);
+            update(ex, 0);
+        }
+    }
+
+    private EntryElement getEntryElement(final ZipOutputStream zos) {
+        if (outRepresentation == SINGLE_XML) {
+            return new SingleDocElement(zos);
+        }
+        return new ZipEntryElement(zos);
+    }
+
+    // private ContentHandlerFactory getHandlerFactory(
+    // OutputStream os,
+    // SAXTransformerFactory saxtf,
+    // Templates templates)
+    // {
+    // ContentHandlerFactory factory = null;
+    // if (templates == null) {
+    // if (outputRepresentation == BYTECODE) { // factory used to write
+    // // bytecode
+    // factory = new ASMContentHandlerFactory(os, computeMax);
+    // } else { // factory used to write XML
+    // factory = new SAXWriterFactory(os, true);
+    // }
+    // } else {
+    // if (outputRepresentation == BYTECODE) { // factory used to transform
+    // // and then write bytecode
+    // factory = new ASMTransformerHandlerFactory(saxtf,
+    // templates,
+    // os,
+    // computeMax);
+    // } else { // factory used to transformand then write XML
+    // factory = new TransformerHandlerFactory(saxtf,
+    // templates,
+    // os,
+    // outputRepresentation == SINGLE_XML);
+    // }
+    // }
+    // return factory;
+    // }
+
+    private String getName(final ZipEntry ze) {
+        String name = ze.getName();
+        if (isClassEntry(ze)) {
+            if (inRepresentation != BYTECODE && outRepresentation == BYTECODE) {
+                name = name.substring(0, name.length() - 4); // .class.xml to
+                // .class
+            } else if (inRepresentation == BYTECODE
+                    && outRepresentation != BYTECODE) {
+                name += ".xml"; // .class to .class.xml
+            }
+            // } else if( CODE2ASM.equals( command)) {
+            // name = name.substring( 0, name.length()-6).concat( ".asm");
+        }
+        return name;
+    }
+
+    private static byte[] readEntry(final InputStream zis, final ZipEntry ze)
+            throws IOException {
+        long size = ze.getSize();
+        if (size > -1) {
+            byte[] buff = new byte[(int) size];
+            int k = 0;
+            int n;
+            while ((n = zis.read(buff, k, buff.length - k)) > 0) {
+                k += n;
+            }
+            return buff;
+        }
+
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        byte[] buff = new byte[4096];
+        int i;
+        while ((i = zis.read(buff)) != -1) {
+            bos.write(buff, 0, i);
+        }
+        return bos.toByteArray();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
+     */
+    protected void update(final Object arg, final int n) {
+        if (arg instanceof Throwable) {
+            ((Throwable) arg).printStackTrace();
+        } else {
+            if (n % 100 == 0) {
+                System.err.println(n + " " + arg);
+            }
+        }
+    }
+
+    public static void main(final String[] args) throws Exception {
+        if (args.length < 2) {
+            showUsage();
+            return;
+        }
+
+        int inRepresentation = getRepresentation(args[0]);
+        int outRepresentation = getRepresentation(args[1]);
+
+        InputStream is = System.in;
+        OutputStream os = new BufferedOutputStream(System.out);
+
+        Source xslt = null;
+        // boolean computeMax = true;
+
+        for (int i = 2; i < args.length; i++) {
+            if ("-in".equals(args[i])) {
+                is = new FileInputStream(args[++i]);
+
+            } else if ("-out".equals(args[i])) {
+                os = new BufferedOutputStream(new FileOutputStream(args[++i]));
+
+            } else if ("-xslt".equals(args[i])) {
+                xslt = new StreamSource(new FileInputStream(args[++i]));
+
+                // } else if( "-computemax".equals( args[ i].toLowerCase())) {
+                // computeMax = true;
+
+            } else {
+                showUsage();
+                return;
+
+            }
+        }
+
+        if (inRepresentation == 0 || outRepresentation == 0) {
+            showUsage();
+            return;
+        }
+
+        Processor m = new Processor(inRepresentation, outRepresentation, is,
+                os, xslt);
+
+        long l1 = System.currentTimeMillis();
+        int n = m.process();
+        long l2 = System.currentTimeMillis();
+        System.err.println(n);
+        System.err.println((l2 - l1) + "ms  " + 1000f * n / (l2 - l1)
+                + " resources/sec");
+    }
+
+    private static int getRepresentation(final String s) {
+        if ("code".equals(s)) {
+            return BYTECODE;
+        } else if ("xml".equals(s)) {
+            return MULTI_XML;
+        } else if ("singlexml".equals(s)) {
+            return SINGLE_XML;
+        }
+        return 0;
+    }
+
+    private static void showUsage() {
+        System.err
+                .println("Usage: Main <in format> <out format> [-in <input jar>] [-out <output jar>] [-xslt <xslt fiel>]");
+        System.err
+                .println("  when -in or -out is omitted sysin and sysout would be used");
+        System.err
+                .println("  <in format> and <out format> - code | xml | singlexml");
+    }
+
+    /**
+     * IputStream wrapper class used to protect input streams from being closed
+     * by some stupid XML parsers.
+     */
+    private static final class ProtectedInputStream extends InputStream {
+        private final InputStream is;
+
+        ProtectedInputStream(final InputStream is) {
+            this.is = is;
+        }
+
+        @Override
+        public final void close() throws IOException {
+        }
+
+        @Override
+        public final int read() throws IOException {
+            return is.read();
+        }
+
+        @Override
+        public final int read(final byte[] b, final int off, final int len)
+                throws IOException {
+            return is.read(b, off, len);
+        }
+
+        @Override
+        public final int available() throws IOException {
+            return is.available();
+        }
+    }
+
+    /**
+     * A {@link ContentHandlerFactory ContentHandlerFactory} is used to create
+     * {@link org.xml.sax.ContentHandler ContentHandler} instances for concrete
+     * context.
+     */
+    private static interface ContentHandlerFactory {
+
+        /**
+         * Creates an instance of the content handler.
+         * 
+         * @return content handler
+         */
+        ContentHandler createContentHandler();
+
+    }
+
+    /**
+     * SAXWriterFactory
+     */
+    private static final class SAXWriterFactory implements
+            ContentHandlerFactory {
+        private final Writer w;
+
+        private final boolean optimizeEmptyElements;
+
+        SAXWriterFactory(final Writer w, final boolean optimizeEmptyElements) {
+            this.w = w;
+            this.optimizeEmptyElements = optimizeEmptyElements;
+        }
+
+        public final ContentHandler createContentHandler() {
+            return new SAXWriter(w, optimizeEmptyElements);
+        }
+
+    }
+
+    /**
+     * ASMContentHandlerFactory
+     */
+    private static final class ASMContentHandlerFactory implements
+            ContentHandlerFactory {
+        final OutputStream os;
+
+        ASMContentHandlerFactory(final OutputStream os) {
+            this.os = os;
+        }
+
+        public final ContentHandler createContentHandler() {
+            final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+            return new ASMContentHandler(cw) {
+                @Override
+                public void endDocument() throws SAXException {
+                    try {
+                        os.write(cw.toByteArray());
+                    } catch (IOException e) {
+                        throw new SAXException(e);
+                    }
+                }
+            };
+        }
+
+    }
+
+    /**
+     * TransformerHandlerFactory
+     */
+    private static final class TransformerHandlerFactory implements
+            ContentHandlerFactory {
+        private SAXTransformerFactory saxtf;
+
+        private final Templates templates;
+
+        private ContentHandler outputHandler;
+
+        TransformerHandlerFactory(final SAXTransformerFactory saxtf,
+                final Templates templates, final ContentHandler outputHandler) {
+            this.saxtf = saxtf;
+            this.templates = templates;
+            this.outputHandler = outputHandler;
+        }
+
+        public final ContentHandler createContentHandler() {
+            try {
+                TransformerHandler handler = saxtf
+                        .newTransformerHandler(templates);
+                handler.setResult(new SAXResult(outputHandler));
+                return handler;
+            } catch (TransformerConfigurationException ex) {
+                throw new RuntimeException(ex.toString());
+            }
+        }
+    }
+
+    /**
+     * SubdocumentHandlerFactory
+     */
+    private static final class SubdocumentHandlerFactory implements
+            ContentHandlerFactory {
+        private final ContentHandler subdocumentHandler;
+
+        SubdocumentHandlerFactory(final ContentHandler subdocumentHandler) {
+            this.subdocumentHandler = subdocumentHandler;
+        }
+
+        public final ContentHandler createContentHandler() {
+            return subdocumentHandler;
+        }
+
+    }
+
+    /**
+     * A {@link org.xml.sax.ContentHandler ContentHandler} and
+     * {@link org.xml.sax.ext.LexicalHandler LexicalHandler} that serializes XML
+     * from SAX 2.0 events into {@link java.io.Writer Writer}.
+     * 
+     * <i><blockquote> This implementation does not support namespaces, entity
+     * definitions (uncluding DTD), CDATA and text elements. </blockquote></i>
+     */
+    private static final class SAXWriter extends DefaultHandler implements
+            LexicalHandler {
+        private static final char[] OFF = "                                                                                                        "
+                .toCharArray();
+
+        private Writer w;
+
+        private final boolean optimizeEmptyElements;
+
+        private boolean openElement = false;
+
+        private int ident = 0;
+
+        /**
+         * Creates <code>SAXWriter</code>.
+         * 
+         * @param w
+         *            writer
+         * @param optimizeEmptyElements
+         *            if set to <code>true</code>, short XML syntax will be used
+         *            for empty elements
+         */
+        SAXWriter(final Writer w, final boolean optimizeEmptyElements) {
+            this.w = w;
+            this.optimizeEmptyElements = optimizeEmptyElements;
+        }
+
+        @Override
+        public final void startElement(final String ns, final String localName,
+                final String qName, final Attributes atts) throws SAXException {
+            try {
+                closeElement();
+
+                writeIdent();
+                w.write('<' + qName);
+                if (atts != null && atts.getLength() > 0) {
+                    writeAttributes(atts);
+                }
+
+                if (optimizeEmptyElements) {
+                    openElement = true;
+                } else {
+                    w.write(">\n");
+                }
+                ident += 2;
+
+            } catch (IOException ex) {
+                throw new SAXException(ex);
+
+            }
+        }
+
+        @Override
+        public final void endElement(final String ns, final String localName,
+                final String qName) throws SAXException {
+            ident -= 2;
+            try {
+                if (openElement) {
+                    w.write("/>\n");
+                    openElement = false;
+                } else {
+                    writeIdent();
+                    w.write("</" + qName + ">\n");
+                }
+
+            } catch (IOException ex) {
+                throw new SAXException(ex);
+
+            }
+        }
+
+        @Override
+        public final void endDocument() throws SAXException {
+            try {
+                w.flush();
+
+            } catch (IOException ex) {
+                throw new SAXException(ex);
+
+            }
+        }
+
+        public final void comment(final char[] ch, final int off, final int len)
+                throws SAXException {
+            try {
+                closeElement();
+
+                writeIdent();
+                w.write("<!-- ");
+                w.write(ch, off, len);
+                w.write(" -->\n");
+
+            } catch (IOException ex) {
+                throw new SAXException(ex);
+
+            }
+        }
+
+        public final void startDTD(final String arg0, final String arg1,
+                final String arg2) throws SAXException {
+        }
+
+        public final void endDTD() throws SAXException {
+        }
+
+        public final void startEntity(final String arg0) throws SAXException {
+        }
+
+        public final void endEntity(final String arg0) throws SAXException {
+        }
+
+        public final void startCDATA() throws SAXException {
+        }
+
+        public final void endCDATA() throws SAXException {
+        }
+
+        private final void writeAttributes(final Attributes atts)
+                throws IOException {
+            StringBuffer sb = new StringBuffer();
+            int len = atts.getLength();
+            for (int i = 0; i < len; i++) {
+                sb.append(' ').append(atts.getLocalName(i)).append("=\"")
+                        .append(esc(atts.getValue(i))).append('\"');
+            }
+            w.write(sb.toString());
+        }
+
+        /**
+         * Encode string with escaping.
+         * 
+         * @param str
+         *            string to encode.
+         * @return encoded string
+         */
+        private static final String esc(final String str) {
+            StringBuffer sb = new StringBuffer(str.length());
+            for (int i = 0; i < str.length(); i++) {
+                char ch = str.charAt(i);
+                switch (ch) {
+                case '&':
+                    sb.append("&amp;");
+                    break;
+
+                case '<':
+                    sb.append("&lt;");
+                    break;
+
+                case '>':
+                    sb.append("&gt;");
+                    break;
+
+                case '\"':
+                    sb.append("&quot;");
+                    break;
+
+                default:
+                    if (ch > 0x7f) {
+                        sb.append("&#").append(Integer.toString(ch))
+                                .append(';');
+                    } else {
+                        sb.append(ch);
+                    }
+
+                }
+            }
+            return sb.toString();
+        }
+
+        private final void writeIdent() throws IOException {
+            int n = ident;
+            while (n > 0) {
+                if (n > OFF.length) {
+                    w.write(OFF);
+                    n -= OFF.length;
+                } else {
+                    w.write(OFF, 0, n);
+                    n = 0;
+                }
+            }
+        }
+
+        private final void closeElement() throws IOException {
+            if (openElement) {
+                w.write(">\n");
+            }
+            openElement = false;
+        }
+
+    }
+
+    /**
+     * A {@link org.xml.sax.ContentHandler ContentHandler} that splits XML
+     * documents into smaller chunks. Each chunk is processed by the nested
+     * {@link org.xml.sax.ContentHandler ContentHandler} obtained from
+     * {@link java.net.ContentHandlerFactory ContentHandlerFactory}. This is
+     * useful for running XSLT engine against large XML document that will
+     * hardly fit into the memory all together.
+     * <p>
+     * TODO use complete path for subdocumentRoot
+     */
+    private static final class InputSlicingHandler extends DefaultHandler {
+        private String subdocumentRoot;
+
+        private final ContentHandler rootHandler;
+
+        private ContentHandlerFactory subdocumentHandlerFactory;
+
+        private boolean subdocument = false;
+
+        private ContentHandler subdocumentHandler;
+
+        /**
+         * Constructs a new {@link InputSlicingHandler SubdocumentHandler}
+         * object.
+         * 
+         * @param subdocumentRoot
+         *            name/path to the root element of the subdocument
+         * @param rootHandler
+         *            content handler for the entire document (subdocument
+         *            envelope).
+         * @param subdocumentHandlerFactory
+         *            a {@link ContentHandlerFactory ContentHandlerFactory} used
+         *            to create {@link ContentHandler ContentHandler} instances
+         *            for subdocuments.
+         */
+        InputSlicingHandler(final String subdocumentRoot,
+                final ContentHandler rootHandler,
+                final ContentHandlerFactory subdocumentHandlerFactory) {
+            this.subdocumentRoot = subdocumentRoot;
+            this.rootHandler = rootHandler;
+            this.subdocumentHandlerFactory = subdocumentHandlerFactory;
+        }
+
+        @Override
+        public final void startElement(final String namespaceURI,
+                final String localName, final String qName,
+                final Attributes list) throws SAXException {
+            if (subdocument) {
+                subdocumentHandler.startElement(namespaceURI, localName, qName,
+                        list);
+            } else if (localName.equals(subdocumentRoot)) {
+                subdocumentHandler = subdocumentHandlerFactory
+                        .createContentHandler();
+                subdocumentHandler.startDocument();
+                subdocumentHandler.startElement(namespaceURI, localName, qName,
+                        list);
+                subdocument = true;
+            } else if (rootHandler != null) {
+                rootHandler.startElement(namespaceURI, localName, qName, list);
+            }
+        }
+
+        @Override
+        public final void endElement(final String namespaceURI,
+                final String localName, final String qName) throws SAXException {
+            if (subdocument) {
+                subdocumentHandler.endElement(namespaceURI, localName, qName);
+                if (localName.equals(subdocumentRoot)) {
+                    subdocumentHandler.endDocument();
+                    subdocument = false;
+                }
+            } else if (rootHandler != null) {
+                rootHandler.endElement(namespaceURI, localName, qName);
+            }
+        }
+
+        @Override
+        public final void startDocument() throws SAXException {
+            if (rootHandler != null) {
+                rootHandler.startDocument();
+            }
+        }
+
+        @Override
+        public final void endDocument() throws SAXException {
+            if (rootHandler != null) {
+                rootHandler.endDocument();
+
+            }
+        }
+
+        @Override
+        public final void characters(final char[] buff, final int offset,
+                final int size) throws SAXException {
+            if (subdocument) {
+                subdocumentHandler.characters(buff, offset, size);
+            } else if (rootHandler != null) {
+                rootHandler.characters(buff, offset, size);
+            }
+        }
+
+    }
+
+    /**
+     * A {@link org.xml.sax.ContentHandler ContentHandler} that splits XML
+     * documents into smaller chunks. Each chunk is processed by the nested
+     * {@link org.xml.sax.ContentHandler ContentHandler} obtained from
+     * {@link java.net.ContentHandlerFactory ContentHandlerFactory}. This is
+     * useful for running XSLT engine against large XML document that will
+     * hardly fit into the memory all together.
+     * 
+     * <p>
+     * TODO use complete path for subdocumentRoot
+     */
+    private static final class OutputSlicingHandler extends DefaultHandler {
+        private final String subdocumentRoot;
+
+        private ContentHandlerFactory subdocumentHandlerFactory;
+
+        private final EntryElement entryElement;
+
+        private boolean isXml;
+
+        private boolean subdocument = false;
+
+        private ContentHandler subdocumentHandler;
+
+        /**
+         * Constructs a new {@link OutputSlicingHandler SubdocumentHandler}
+         * object.
+         * 
+         * @param subdocumentHandlerFactory
+         *            a {@link ContentHandlerFactory ContentHandlerFactory} used
+         *            to create {@link ContentHandler ContentHandler} instances
+         *            for subdocuments.
+         * @param entryElement
+         *            TODO.
+         * @param isXml
+         *            TODO.
+         */
+        OutputSlicingHandler(
+                final ContentHandlerFactory subdocumentHandlerFactory,
+                final EntryElement entryElement, final boolean isXml) {
+            this.subdocumentRoot = "class";
+            this.subdocumentHandlerFactory = subdocumentHandlerFactory;
+            this.entryElement = entryElement;
+            this.isXml = isXml;
+        }
+
+        @Override
+        public final void startElement(final String namespaceURI,
+                final String localName, final String qName,
+                final Attributes list) throws SAXException {
+            if (subdocument) {
+                subdocumentHandler.startElement(namespaceURI, localName, qName,
+                        list);
+            } else if (localName.equals(subdocumentRoot)) {
+                String name = list.getValue("name");
+                if (name == null || name.length() == 0) {
+                    throw new SAXException(
+                            "Class element without name attribute.");
+                }
+                try {
+                    entryElement.openEntry(isXml ? name + ".class.xml" : name
+                            + ".class");
+                } catch (IOException ex) {
+                    throw new SAXException(ex.toString(), ex);
+                }
+                subdocumentHandler = subdocumentHandlerFactory
+                        .createContentHandler();
+                subdocumentHandler.startDocument();
+                subdocumentHandler.startElement(namespaceURI, localName, qName,
+                        list);
+                subdocument = true;
+            }
+        }
+
+        @Override
+        public final void endElement(final String namespaceURI,
+                final String localName, final String qName) throws SAXException {
+            if (subdocument) {
+                subdocumentHandler.endElement(namespaceURI, localName, qName);
+                if (localName.equals(subdocumentRoot)) {
+                    subdocumentHandler.endDocument();
+                    subdocument = false;
+                    try {
+                        entryElement.closeEntry();
+                    } catch (IOException ex) {
+                        throw new SAXException(ex.toString(), ex);
+                    }
+                }
+            }
+        }
+
+        @Override
+        public final void startDocument() throws SAXException {
+        }
+
+        @Override
+        public final void endDocument() throws SAXException {
+        }
+
+        @Override
+        public final void characters(final char[] buff, final int offset,
+                final int size) throws SAXException {
+            if (subdocument) {
+                subdocumentHandler.characters(buff, offset, size);
+            }
+        }
+
+    }
+
+    private static interface EntryElement {
+
+        OutputStream openEntry(String name) throws IOException;
+
+        void closeEntry() throws IOException;
+
+    }
+
+    private static final class SingleDocElement implements EntryElement {
+        private final OutputStream os;
+
+        SingleDocElement(final OutputStream os) {
+            this.os = os;
+        }
+
+        public OutputStream openEntry(final String name) throws IOException {
+            return os;
+        }
+
+        public void closeEntry() throws IOException {
+            os.flush();
+        }
+
+    }
+
+    private static final class ZipEntryElement implements EntryElement {
+        private ZipOutputStream zos;
+
+        ZipEntryElement(final ZipOutputStream zos) {
+            this.zos = zos;
+        }
+
+        public OutputStream openEntry(final String name) throws IOException {
+            ZipEntry entry = new ZipEntry(name);
+            zos.putNextEntry(entry);
+            return zos;
+        }
+
+        public void closeEntry() throws IOException {
+            zos.flush();
+            zos.closeEntry();
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java
new file mode 100644
index 0000000..2f49c24
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java
@@ -0,0 +1,89 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * 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.xml;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * SAXAdapter
+ * 
+ * @author Eugene Kuleshov
+ */
+public class SAXAdapter {
+
+    private final ContentHandler h;
+
+    protected SAXAdapter(final ContentHandler h) {
+        this.h = h;
+    }
+
+    protected ContentHandler getContentHandler() {
+        return h;
+    }
+
+    protected void addDocumentStart() {
+        try {
+            h.startDocument();
+        } catch (SAXException ex) {
+            throw new RuntimeException(ex.getMessage(), ex.getException());
+        }
+    }
+
+    protected void addDocumentEnd() {
+        try {
+            h.endDocument();
+        } catch (SAXException ex) {
+            throw new RuntimeException(ex.getMessage(), ex.getException());
+        }
+    }
+
+    protected final void addStart(final String name, final Attributes attrs) {
+        try {
+            h.startElement("", name, name, attrs);
+        } catch (SAXException ex) {
+            throw new RuntimeException(ex.getMessage(), ex.getException());
+        }
+    }
+
+    protected final void addEnd(final String name) {
+        try {
+            h.endElement("", name, name);
+        } catch (SAXException ex) {
+            throw new RuntimeException(ex.getMessage(), ex.getException());
+        }
+    }
+
+    protected final void addElement(final String name, final Attributes attrs) {
+        addStart(name, attrs);
+        addEnd(name);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java
new file mode 100644
index 0000000..491c57e
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java
@@ -0,0 +1,242 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * 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.xml;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * SAXAnnotationAdapter
+ * 
+ * @author Eugene Kuleshov
+ */
+public final class SAXAnnotationAdapter extends AnnotationVisitor {
+
+    SAXAdapter sa;
+
+    private final String elementName;
+
+    public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
+            final int visible, final String name, final String desc) {
+        this(Opcodes.ASM5, sa, elementName, visible, desc, name, -1, -1, null,
+                null, null, null);
+    }
+
+    public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
+            final int visible, final int parameter, final String desc) {
+        this(Opcodes.ASM5, sa, elementName, visible, desc, null, parameter, -1,
+                null, null, null, null);
+    }
+
+    public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
+            final int visible, final String name, final String desc,
+            final int typeRef, final TypePath typePath) {
+        this(Opcodes.ASM5, sa, elementName, visible, desc, name, -1, typeRef,
+                typePath, null, null, null);
+    }
+
+    public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
+            final int visible, final String name, final String desc,
+            int typeRef, TypePath typePath, final String[] start,
+            final String[] end, final int[] index) {
+        this(Opcodes.ASM5, sa, elementName, visible, desc, name, -1, typeRef,
+                typePath, start, end, index);
+    }
+
+    protected SAXAnnotationAdapter(final int api, final SAXAdapter sa,
+            final String elementName, final int visible, final String desc,
+            final String name, final int parameter) {
+        this(api, sa, elementName, visible, desc, name, parameter, -1, null,
+                null, null, null);
+    }
+
+    protected SAXAnnotationAdapter(final int api, final SAXAdapter sa,
+            final String elementName, final int visible, final String desc,
+            final String name, final int parameter, final int typeRef,
+            final TypePath typePath, final String[] start, final String[] end,
+            final int[] index) {
+        super(api);
+        this.sa = sa;
+        this.elementName = elementName;
+
+        AttributesImpl att = new AttributesImpl();
+        if (name != null) {
+            att.addAttribute("", "name", "name", "", name);
+        }
+        if (visible != 0) {
+            att.addAttribute("", "visible", "visible", "", visible > 0 ? "true"
+                    : "false");
+        }
+        if (parameter != -1) {
+            att.addAttribute("", "parameter", "parameter", "",
+                    Integer.toString(parameter));
+        }
+        if (desc != null) {
+            att.addAttribute("", "desc", "desc", "", desc);
+        }
+        if (typeRef != -1) {
+            att.addAttribute("", "typeRef", "typeRef", "",
+                    Integer.toString(typeRef));
+        }
+        if (typePath != null) {
+            att.addAttribute("", "typePath", "typePath", "",
+                    typePath.toString());
+        }
+        if (start != null) {
+            StringBuffer value = new StringBuffer(start[0]);
+            for (int i = 1; i < start.length; ++i) {
+                value.append(" ").append(start[i]);
+            }
+            att.addAttribute("", "start", "start", "", value.toString());
+        }
+        if (end != null) {
+            StringBuffer value = new StringBuffer(end[0]);
+            for (int i = 1; i < end.length; ++i) {
+                value.append(" ").append(end[i]);
+            }
+            att.addAttribute("", "end", "end", "", value.toString());
+        }
+        if (index != null) {
+            StringBuffer value = new StringBuffer();
+            value.append(index[0]);
+            for (int i = 1; i < index.length; ++i) {
+                value.append(" ").append(index[i]);
+            }
+            att.addAttribute("", "index", "index", "", value.toString());
+        }
+
+        sa.addStart(elementName, att);
+    }
+
+    @Override
+    public void visit(final String name, final Object value) {
+        Class<?> c = value.getClass();
+        if (c.isArray()) {
+            AnnotationVisitor av = visitArray(name);
+            if (value instanceof byte[]) {
+                byte[] b = (byte[]) value;
+                for (int i = 0; i < b.length; i++) {
+                    av.visit(null, new Byte(b[i]));
+                }
+
+            } else if (value instanceof char[]) {
+                char[] b = (char[]) value;
+                for (int i = 0; i < b.length; i++) {
+                    av.visit(null, new Character(b[i]));
+                }
+
+            } else if (value instanceof short[]) {
+                short[] b = (short[]) value;
+                for (int i = 0; i < b.length; i++) {
+                    av.visit(null, new Short(b[i]));
+                }
+
+            } else if (value instanceof boolean[]) {
+                boolean[] b = (boolean[]) value;
+                for (int i = 0; i < b.length; i++) {
+                    av.visit(null, Boolean.valueOf(b[i]));
+                }
+
+            } else if (value instanceof int[]) {
+                int[] b = (int[]) value;
+                for (int i = 0; i < b.length; i++) {
+                    av.visit(null, new Integer(b[i]));
+                }
+
+            } else if (value instanceof long[]) {
+                long[] b = (long[]) value;
+                for (int i = 0; i < b.length; i++) {
+                    av.visit(null, new Long(b[i]));
+                }
+
+            } else if (value instanceof float[]) {
+                float[] b = (float[]) value;
+                for (int i = 0; i < b.length; i++) {
+                    av.visit(null, new Float(b[i]));
+                }
+
+            } else if (value instanceof double[]) {
+                double[] b = (double[]) value;
+                for (int i = 0; i < b.length; i++) {
+                    av.visit(null, new Double(b[i]));
+                }
+
+            }
+            av.visitEnd();
+        } else {
+            addValueElement("annotationValue", name, Type.getDescriptor(c),
+                    value.toString());
+        }
+    }
+
+    @Override
+    public void visitEnum(final String name, final String desc,
+            final String value) {
+        addValueElement("annotationValueEnum", name, desc, value);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String name,
+            final String desc) {
+        return new SAXAnnotationAdapter(sa, "annotationValueAnnotation", 0,
+                name, desc);
+    }
+
+    @Override
+    public AnnotationVisitor visitArray(final String name) {
+        return new SAXAnnotationAdapter(sa, "annotationValueArray", 0, name,
+                null);
+    }
+
+    @Override
+    public void visitEnd() {
+        sa.addEnd(elementName);
+    }
+
+    private void addValueElement(final String element, final String name,
+            final String desc, final String value) {
+        AttributesImpl att = new AttributesImpl();
+        if (name != null) {
+            att.addAttribute("", "name", "name", "", name);
+        }
+        if (desc != null) {
+            att.addAttribute("", "desc", "desc", "", desc);
+        }
+        if (value != null) {
+            att.addAttribute("", "value", "value", "",
+                    SAXClassAdapter.encode(value));
+        }
+
+        sa.addElement(element, att);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java
new file mode 100644
index 0000000..dc4cb66
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java
@@ -0,0 +1,335 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * 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.xml;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * A {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor ClassVisitor} that generates SAX 2.0
+ * events from the visited class. It can feed any kind of
+ * {@link org.xml.sax.ContentHandler ContentHandler}, e.g. XML serializer, XSLT
+ * or XQuery engines.
+ * 
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.Processor
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.ASMContentHandler
+ * 
+ * @author Eugene Kuleshov
+ */
+public final class SAXClassAdapter extends ClassVisitor {
+
+    SAXAdapter sa;
+
+    private final boolean singleDocument;
+
+    /**
+     * Pseudo access flag used to distinguish class access flags.
+     */
+    private static final int ACCESS_CLASS = 262144;
+
+    /**
+     * Pseudo access flag used to distinguish field access flags.
+     */
+    private static final int ACCESS_FIELD = 524288;
+
+    /**
+     * Pseudo access flag used to distinguish inner class flags.
+     */
+    private static final int ACCESS_INNER = 1048576;
+
+    /**
+     * Constructs a new {@link SAXClassAdapter SAXClassAdapter} object.
+     * 
+     * @param h
+     *            content handler that will be used to send SAX 2.0 events.
+     * @param singleDocument
+     *            if <tt>true</tt> adapter will not produce
+     *            {@link ContentHandler#startDocument() startDocument()} and
+     *            {@link ContentHandler#endDocument() endDocument()} events.
+     */
+    public SAXClassAdapter(final ContentHandler h, boolean singleDocument) {
+        super(Opcodes.ASM5);
+        this.sa = new SAXAdapter(h);
+        this.singleDocument = singleDocument;
+        if (!singleDocument) {
+            sa.addDocumentStart();
+        }
+    }
+
+    @Override
+    public void visitSource(final String source, final String debug) {
+        AttributesImpl att = new AttributesImpl();
+        if (source != null) {
+            att.addAttribute("", "file", "file", "", encode(source));
+        }
+        if (debug != null) {
+            att.addAttribute("", "debug", "debug", "", encode(debug));
+        }
+
+        sa.addElement("source", att);
+    }
+
+    @Override
+    public void visitOuterClass(final String owner, final String name,
+            final String desc) {
+        AttributesImpl att = new AttributesImpl();
+        att.addAttribute("", "owner", "owner", "", owner);
+        if (name != null) {
+            att.addAttribute("", "name", "name", "", name);
+        }
+        if (desc != null) {
+            att.addAttribute("", "desc", "desc", "", desc);
+        }
+
+        sa.addElement("outerclass", att);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        return new SAXAnnotationAdapter(sa, "annotation", visible ? 1 : -1,
+                null, desc);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        return new SAXAnnotationAdapter(sa, "typeAnnotation", visible ? 1 : -1,
+                null, desc, typeRef, typePath);
+    }
+
+    @Override
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
+        StringBuffer sb = new StringBuffer();
+        appendAccess(access | ACCESS_CLASS, sb);
+
+        AttributesImpl att = new AttributesImpl();
+        att.addAttribute("", "access", "access", "", sb.toString());
+        if (name != null) {
+            att.addAttribute("", "name", "name", "", name);
+        }
+        if (signature != null) {
+            att.addAttribute("", "signature", "signature", "",
+                    encode(signature));
+        }
+        if (superName != null) {
+            att.addAttribute("", "parent", "parent", "", superName);
+        }
+        att.addAttribute("", "major", "major", "",
+                Integer.toString(version & 0xFFFF));
+        att.addAttribute("", "minor", "minor", "",
+                Integer.toString(version >>> 16));
+        sa.addStart("class", att);
+
+        sa.addStart("interfaces", new AttributesImpl());
+        if (interfaces != null && interfaces.length > 0) {
+            for (int i = 0; i < interfaces.length; i++) {
+                AttributesImpl att2 = new AttributesImpl();
+                att2.addAttribute("", "name", "name", "", interfaces[i]);
+                sa.addElement("interface", att2);
+            }
+        }
+        sa.addEnd("interfaces");
+    }
+
+    @Override
+    public FieldVisitor visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
+        StringBuffer sb = new StringBuffer();
+        appendAccess(access | ACCESS_FIELD, sb);
+
+        AttributesImpl att = new AttributesImpl();
+        att.addAttribute("", "access", "access", "", sb.toString());
+        att.addAttribute("", "name", "name", "", name);
+        att.addAttribute("", "desc", "desc", "", desc);
+        if (signature != null) {
+            att.addAttribute("", "signature", "signature", "",
+                    encode(signature));
+        }
+        if (value != null) {
+            att.addAttribute("", "value", "value", "", encode(value.toString()));
+        }
+
+        return new SAXFieldAdapter(sa, att);
+    }
+
+    @Override
+    public MethodVisitor visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        StringBuffer sb = new StringBuffer();
+        appendAccess(access, sb);
+
+        AttributesImpl att = new AttributesImpl();
+        att.addAttribute("", "access", "access", "", sb.toString());
+        att.addAttribute("", "name", "name", "", name);
+        att.addAttribute("", "desc", "desc", "", desc);
+        if (signature != null) {
+            att.addAttribute("", "signature", "signature", "", signature);
+        }
+        sa.addStart("method", att);
+
+        sa.addStart("exceptions", new AttributesImpl());
+        if (exceptions != null && exceptions.length > 0) {
+            for (int i = 0; i < exceptions.length; i++) {
+                AttributesImpl att2 = new AttributesImpl();
+                att2.addAttribute("", "name", "name", "", exceptions[i]);
+                sa.addElement("exception", att2);
+            }
+        }
+        sa.addEnd("exceptions");
+
+        return new SAXCodeAdapter(sa, access);
+    }
+
+    @Override
+    public final void visitInnerClass(final String name,
+            final String outerName, final String innerName, final int access) {
+        StringBuffer sb = new StringBuffer();
+        appendAccess(access | ACCESS_INNER, sb);
+
+        AttributesImpl att = new AttributesImpl();
+        att.addAttribute("", "access", "access", "", sb.toString());
+        if (name != null) {
+            att.addAttribute("", "name", "name", "", name);
+        }
+        if (outerName != null) {
+            att.addAttribute("", "outerName", "outerName", "", outerName);
+        }
+        if (innerName != null) {
+            att.addAttribute("", "innerName", "innerName", "", innerName);
+        }
+        sa.addElement("innerclass", att);
+    }
+
+    @Override
+    public final void visitEnd() {
+        sa.addEnd("class");
+        if (!singleDocument) {
+            sa.addDocumentEnd();
+        }
+    }
+
+    static final String encode(final String s) {
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0; i < s.length(); i++) {
+            char c = s.charAt(i);
+            if (c == '\\') {
+                sb.append("\\\\");
+            } else if (c < 0x20 || c > 0x7f) {
+                sb.append("\\u");
+                if (c < 0x10) {
+                    sb.append("000");
+                } else if (c < 0x100) {
+                    sb.append("00");
+                } else if (c < 0x1000) {
+                    sb.append('0');
+                }
+                sb.append(Integer.toString(c, 16));
+            } else {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    static void appendAccess(final int access, final StringBuffer sb) {
+        if ((access & Opcodes.ACC_PUBLIC) != 0) {
+            sb.append("public ");
+        }
+        if ((access & Opcodes.ACC_PRIVATE) != 0) {
+            sb.append("private ");
+        }
+        if ((access & Opcodes.ACC_PROTECTED) != 0) {
+            sb.append("protected ");
+        }
+        if ((access & Opcodes.ACC_FINAL) != 0) {
+            sb.append("final ");
+        }
+        if ((access & Opcodes.ACC_STATIC) != 0) {
+            sb.append("static ");
+        }
+        if ((access & Opcodes.ACC_SUPER) != 0) {
+            if ((access & ACCESS_CLASS) == 0) {
+                sb.append("synchronized ");
+            } else {
+                sb.append("super ");
+            }
+        }
+        if ((access & Opcodes.ACC_VOLATILE) != 0) {
+            if ((access & ACCESS_FIELD) == 0) {
+                sb.append("bridge ");
+            } else {
+                sb.append("volatile ");
+            }
+        }
+        if ((access & Opcodes.ACC_TRANSIENT) != 0) {
+            if ((access & ACCESS_FIELD) == 0) {
+                sb.append("varargs ");
+            } else {
+                sb.append("transient ");
+            }
+        }
+        if ((access & Opcodes.ACC_NATIVE) != 0) {
+            sb.append("native ");
+        }
+        if ((access & Opcodes.ACC_STRICT) != 0) {
+            sb.append("strict ");
+        }
+        if ((access & Opcodes.ACC_INTERFACE) != 0) {
+            sb.append("interface ");
+        }
+        if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+            sb.append("abstract ");
+        }
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            sb.append("synthetic ");
+        }
+        if ((access & Opcodes.ACC_ANNOTATION) != 0) {
+            sb.append("annotation ");
+        }
+        if ((access & Opcodes.ACC_ENUM) != 0) {
+            sb.append("enum ");
+        }
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            sb.append("deprecated ");
+        }
+        if ((access & Opcodes.ACC_MANDATED) != 0) {
+            sb.append("mandated ");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java
new file mode 100644
index 0000000..3ed0a49
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java
@@ -0,0 +1,415 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * 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.xml;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+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;
+import org.apache.tapestry5.internal.plastic.asm.util.Printer;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * A {@link MethodVisitor} that generates SAX 2.0 events from the visited
+ * method.
+ * 
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.SAXClassAdapter
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.Processor
+ * 
+ * @author Eugene Kuleshov
+ */
+public final class SAXCodeAdapter extends MethodVisitor {
+
+    static final String[] TYPES = { "top", "int", "float", "double", "long",
+            "null", "uninitializedThis" };
+
+    SAXAdapter sa;
+
+    int access;
+
+    private final Map<Label, String> labelNames;
+
+    /**
+     * Constructs a new {@link SAXCodeAdapter SAXCodeAdapter} object.
+     * 
+     * @param sa
+     *            content handler that will be used to send SAX 2.0 events.
+     */
+    public SAXCodeAdapter(final SAXAdapter sa, final int access) {
+        super(Opcodes.ASM5);
+        this.sa = sa;
+        this.access = access;
+        this.labelNames = new HashMap<Label, String>();
+    }
+
+    @Override
+    public void visitParameter(String name, int access) {
+        AttributesImpl attrs = new AttributesImpl();
+        if (name != null) {
+            attrs.addAttribute("", "name", "name", "", name);
+        }
+        StringBuffer sb = new StringBuffer();
+        SAXClassAdapter.appendAccess(access, sb);
+        attrs.addAttribute("", "access", "access", "", sb.toString());
+        sa.addElement("parameter", attrs);
+    }
+
+    @Override
+    public final void visitCode() {
+        if ((access & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE | Opcodes.ACC_NATIVE)) == 0) {
+            sa.addStart("code", new AttributesImpl());
+        }
+    }
+
+    @Override
+    public void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack) {
+        AttributesImpl attrs = new AttributesImpl();
+        switch (type) {
+        case Opcodes.F_NEW:
+        case Opcodes.F_FULL:
+            if (type == Opcodes.F_NEW) {
+                attrs.addAttribute("", "type", "type", "", "NEW");
+            } else {
+                attrs.addAttribute("", "type", "type", "", "FULL");
+            }
+            sa.addStart("frame", attrs);
+            appendFrameTypes(true, nLocal, local);
+            appendFrameTypes(false, nStack, stack);
+            break;
+        case Opcodes.F_APPEND:
+            attrs.addAttribute("", "type", "type", "", "APPEND");
+            sa.addStart("frame", attrs);
+            appendFrameTypes(true, nLocal, local);
+            break;
+        case Opcodes.F_CHOP:
+            attrs.addAttribute("", "type", "type", "", "CHOP");
+            attrs.addAttribute("", "count", "count", "",
+                    Integer.toString(nLocal));
+            sa.addStart("frame", attrs);
+            break;
+        case Opcodes.F_SAME:
+            attrs.addAttribute("", "type", "type", "", "SAME");
+            sa.addStart("frame", attrs);
+            break;
+        case Opcodes.F_SAME1:
+            attrs.addAttribute("", "type", "type", "", "SAME1");
+            sa.addStart("frame", attrs);
+            appendFrameTypes(false, 1, stack);
+            break;
+        }
+        sa.addEnd("frame");
+    }
+
+    private void appendFrameTypes(final boolean local, final int n,
+            final Object[] types) {
+        for (int i = 0; i < n; ++i) {
+            Object type = types[i];
+            AttributesImpl attrs = new AttributesImpl();
+            if (type instanceof String) {
+                attrs.addAttribute("", "type", "type", "", (String) type);
+            } else if (type instanceof Integer) {
+                attrs.addAttribute("", "type", "type", "",
+                        TYPES[((Integer) type).intValue()]);
+            } else {
+                attrs.addAttribute("", "type", "type", "", "uninitialized");
+                attrs.addAttribute("", "label", "label", "",
+                        getLabel((Label) type));
+            }
+            sa.addElement(local ? "local" : "stack", attrs);
+        }
+    }
+
+    @Override
+    public final void visitInsn(final int opcode) {
+        sa.addElement(Printer.OPCODES[opcode], new AttributesImpl());
+    }
+
+    @Override
+    public final void visitIntInsn(final int opcode, final int operand) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "value", "value", "", Integer.toString(operand));
+        sa.addElement(Printer.OPCODES[opcode], attrs);
+    }
+
+    @Override
+    public final void visitVarInsn(final int opcode, final int var) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "var", "var", "", Integer.toString(var));
+        sa.addElement(Printer.OPCODES[opcode], attrs);
+    }
+
+    @Override
+    public final void visitTypeInsn(final int opcode, final String type) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "desc", "desc", "", type);
+        sa.addElement(Printer.OPCODES[opcode], attrs);
+    }
+
+    @Override
+    public final void visitFieldInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "owner", "owner", "", owner);
+        attrs.addAttribute("", "name", "name", "", name);
+        attrs.addAttribute("", "desc", "desc", "", desc);
+        sa.addElement(Printer.OPCODES[opcode], attrs);
+    }
+
+    @Override
+    public final void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "owner", "owner", "", owner);
+        attrs.addAttribute("", "name", "name", "", name);
+        attrs.addAttribute("", "desc", "desc", "", desc);
+        attrs.addAttribute("", "itf", "itf", "", itf ? "true" : "false");
+        sa.addElement(Printer.OPCODES[opcode], attrs);
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "name", "name", "", name);
+        attrs.addAttribute("", "desc", "desc", "", desc);
+        attrs.addAttribute("", "bsm", "bsm", "",
+                SAXClassAdapter.encode(bsm.toString()));
+        sa.addStart("INVOKEDYNAMIC", attrs);
+        for (int i = 0; i < bsmArgs.length; i++) {
+            sa.addElement("bsmArg", getConstantAttribute(bsmArgs[i]));
+        }
+        sa.addEnd("INVOKEDYNAMIC");
+    }
+
+    @Override
+    public final void visitJumpInsn(final int opcode, final Label label) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "label", "label", "", getLabel(label));
+        sa.addElement(Printer.OPCODES[opcode], attrs);
+    }
+
+    @Override
+    public final void visitLabel(final Label label) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "name", "name", "", getLabel(label));
+        sa.addElement("Label", attrs);
+    }
+
+    @Override
+    public final void visitLdcInsn(final Object cst) {
+        sa.addElement(Printer.OPCODES[Opcodes.LDC], getConstantAttribute(cst));
+    }
+
+    private static AttributesImpl getConstantAttribute(final Object cst) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "cst", "cst", "",
+                SAXClassAdapter.encode(cst.toString()));
+        attrs.addAttribute("", "desc", "desc", "",
+                Type.getDescriptor(cst.getClass()));
+        return attrs;
+    }
+
+    @Override
+    public final void visitIincInsn(final int var, final int increment) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "var", "var", "", Integer.toString(var));
+        attrs.addAttribute("", "inc", "inc", "", Integer.toString(increment));
+        sa.addElement(Printer.OPCODES[Opcodes.IINC], attrs);
+    }
+
+    @Override
+    public final void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "min", "min", "", Integer.toString(min));
+        attrs.addAttribute("", "max", "max", "", Integer.toString(max));
+        attrs.addAttribute("", "dflt", "dflt", "", getLabel(dflt));
+        String o = Printer.OPCODES[Opcodes.TABLESWITCH];
+        sa.addStart(o, attrs);
+        for (int i = 0; i < labels.length; i++) {
+            AttributesImpl att2 = new AttributesImpl();
+            att2.addAttribute("", "name", "name", "", getLabel(labels[i]));
+            sa.addElement("label", att2);
+        }
+        sa.addEnd(o);
+    }
+
+    @Override
+    public final void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
+        AttributesImpl att = new AttributesImpl();
+        att.addAttribute("", "dflt", "dflt", "", getLabel(dflt));
+        String o = Printer.OPCODES[Opcodes.LOOKUPSWITCH];
+        sa.addStart(o, att);
+        for (int i = 0; i < labels.length; i++) {
+            AttributesImpl att2 = new AttributesImpl();
+            att2.addAttribute("", "name", "name", "", getLabel(labels[i]));
+            att2.addAttribute("", "key", "key", "", Integer.toString(keys[i]));
+            sa.addElement("label", att2);
+        }
+        sa.addEnd(o);
+    }
+
+    @Override
+    public final void visitMultiANewArrayInsn(final String desc, final int dims) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "desc", "desc", "", desc);
+        attrs.addAttribute("", "dims", "dims", "", Integer.toString(dims));
+        sa.addElement(Printer.OPCODES[Opcodes.MULTIANEWARRAY], attrs);
+    }
+
+    @Override
+    public final void visitTryCatchBlock(final Label start, final Label end,
+            final Label handler, final String type) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "start", "start", "", getLabel(start));
+        attrs.addAttribute("", "end", "end", "", getLabel(end));
+        attrs.addAttribute("", "handler", "handler", "", getLabel(handler));
+        if (type != null) {
+            attrs.addAttribute("", "type", "type", "", type);
+        }
+        sa.addElement("TryCatch", attrs);
+    }
+
+    @Override
+    public final void visitMaxs(final int maxStack, final int maxLocals) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "maxStack", "maxStack", "",
+                Integer.toString(maxStack));
+        attrs.addAttribute("", "maxLocals", "maxLocals", "",
+                Integer.toString(maxLocals));
+        sa.addElement("Max", attrs);
+
+        sa.addEnd("code");
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "name", "name", "", name);
+        attrs.addAttribute("", "desc", "desc", "", desc);
+        if (signature != null) {
+            attrs.addAttribute("", "signature", "signature", "",
+                    SAXClassAdapter.encode(signature));
+        }
+        attrs.addAttribute("", "start", "start", "", getLabel(start));
+        attrs.addAttribute("", "end", "end", "", getLabel(end));
+        attrs.addAttribute("", "var", "var", "", Integer.toString(index));
+        sa.addElement("LocalVar", attrs);
+    }
+
+    @Override
+    public final void visitLineNumber(final int line, final Label start) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "line", "line", "", Integer.toString(line));
+        attrs.addAttribute("", "start", "start", "", getLabel(start));
+        sa.addElement("LineNumber", attrs);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotationDefault() {
+        return new SAXAnnotationAdapter(sa, "annotationDefault", 0, null, null);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        return new SAXAnnotationAdapter(sa, "annotation", visible ? 1 : -1,
+                null, desc);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        return new SAXAnnotationAdapter(sa, "typeAnnotation", visible ? 1 : -1,
+                null, desc, typeRef, typePath);
+    }
+
+    @Override
+    public AnnotationVisitor visitParameterAnnotation(final int parameter,
+            final String desc, final boolean visible) {
+        return new SAXAnnotationAdapter(sa, "parameterAnnotation", visible ? 1
+                : -1, parameter, desc);
+    }
+
+    @Override
+    public AnnotationVisitor visitInsnAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        return new SAXAnnotationAdapter(sa, "insnAnnotation", visible ? 1 : -1,
+                null, desc, typeRef, typePath);
+    }
+
+    @Override
+    public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        return new SAXAnnotationAdapter(sa, "tryCatchAnnotation", visible ? 1
+                : -1, null, desc, typeRef, typePath);
+    }
+
+    @Override
+    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+            TypePath typePath, Label[] start, Label[] end, int[] index,
+            String desc, boolean visible) {
+        String[] s = new String[start.length];
+        String[] e = new String[end.length];
+        for (int i = 0; i < s.length; ++i) {
+            s[i] = getLabel(start[i]);
+        }
+        for (int i = 0; i < e.length; ++i) {
+            e[i] = getLabel(end[i]);
+        }
+        return new SAXAnnotationAdapter(sa, "localVariableAnnotation",
+                visible ? 1 : -1, null, desc, typeRef, typePath, s, e, index);
+    }
+
+    @Override
+    public void visitEnd() {
+        sa.addEnd("method");
+    }
+
+    private final String getLabel(final Label label) {
+        String name = labelNames.get(label);
+        if (name == null) {
+            name = Integer.toString(labelNames.size());
+            labelNames.put(label, name);
+        }
+        return name;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java
new file mode 100644
index 0000000..4fbc2a5
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java
@@ -0,0 +1,71 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * 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.xml;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.xml.sax.Attributes;
+
+/**
+ * SAXFieldAdapter
+ * 
+ * @author Eugene Kuleshov
+ */
+public final class SAXFieldAdapter extends FieldVisitor {
+
+    SAXAdapter sa;
+
+    public SAXFieldAdapter(final SAXAdapter sa, final Attributes att) {
+        super(Opcodes.ASM5);
+        this.sa = sa;
+        sa.addStart("field", att);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        return new SAXAnnotationAdapter(sa, "annotation", visible ? 1 : -1,
+                null, desc);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        return new SAXAnnotationAdapter(sa, "typeAnnotation", visible ? 1 : -1,
+                null, desc, typeRef, typePath);
+    }
+
+    @Override
+    public void visitEnd() {
+        sa.addEnd("field");
+    }
+}


[04/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
index c74a17f..a849298 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
@@ -29,18 +29,19 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.util;
 
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.tapestry5.internal.plastic.asm.Attribute;
 import org.apache.tapestry5.internal.plastic.asm.Handle;
 import org.apache.tapestry5.internal.plastic.asm.Label;
 import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
 
 /**
  * An abstract converter from visit events to text.
- *
+ * 
  * @author Eric Bruneton
  */
 public abstract class Printer {
@@ -103,8 +104,8 @@ public abstract class Printer {
         }
 
         s = "H_GETFIELD,H_GETSTATIC,H_PUTFIELD,H_PUTSTATIC,"
-          + "H_INVOKEVIRTUAL,H_INVOKESTATIC,H_INVOKESPECIAL,"
-          + "H_NEWINVOKESPECIAL,H_INVOKEINTERFACE,";
+                + "H_INVOKEVIRTUAL,H_INVOKESTATIC,H_INVOKESPECIAL,"
+                + "H_NEWINVOKESPECIAL,H_INVOKEINTERFACE,";
         HANDLE_TAG = new String[10];
         j = 0;
         i = 1;
@@ -116,7 +117,7 @@ public abstract class Printer {
 
     /**
      * The ASM API version implemented by this class. The value of this field
-     * must be one of {@link Opcodes#ASM4}.
+     * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
      */
     protected final int api;
 
@@ -149,81 +150,67 @@ public abstract class Printer {
     }
 
     /**
-     * Class header.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visit}.
+     * Class header. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visit}.
      */
-    public abstract void visit(
-        final int version,
-        final int access,
-        final String name,
-        final String signature,
-        final String superName,
-        final String[] interfaces);
+    public abstract void visit(final int version, final int access,
+            final String name, final String signature, final String superName,
+            final String[] interfaces);
 
     /**
-     * Class source.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitSource}.
+     * Class source. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitSource}.
      */
     public abstract void visitSource(final String file, final String debug);
 
     /**
-     * Class outer class.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitOuterClass}.
+     * Class outer class. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitOuterClass}.
      */
-    public abstract void visitOuterClass(
-        final String owner,
-        final String name,
-        final String desc);
+    public abstract void visitOuterClass(final String owner, final String name,
+            final String desc);
 
     /**
-     * Class annotation.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitAnnotation}.
+     * Class annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitAnnotation}.
      */
-    public abstract Printer visitClassAnnotation(
-        final String desc,
-        final boolean visible);
+    public abstract Printer visitClassAnnotation(final String desc,
+            final boolean visible);
 
     /**
-     * Class attribute.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitAttribute}.
+     * Class type annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitTypeAnnotation}.
+     */
+    public Printer visitClassTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        throw new RuntimeException("Must be overriden");
+    }
+
+    /**
+     * Class attribute. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitAttribute}.
      */
     public abstract void visitClassAttribute(final Attribute attr);
 
     /**
-     * Class inner name.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitInnerClass}.
+     * Class inner name. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitInnerClass}.
      */
-    public abstract void visitInnerClass(
-        final String name,
-        final String outerName,
-        final String innerName,
-        final int access);
+    public abstract void visitInnerClass(final String name,
+            final String outerName, final String innerName, final int access);
 
     /**
-     * Class field.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitField}.
+     * Class field. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitField}.
      */
-    public abstract Printer visitField(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final Object value);
+    public abstract Printer visitField(final int access, final String name,
+            final String desc, final String signature, final Object value);
 
     /**
-     * Class method.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitMethod}.
+     * Class method. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitMethod}.
      */
-    public abstract Printer visitMethod(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final String[] exceptions);
+    public abstract Printer visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions);
 
     /**
-     * Class end.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitEnd}.
+     * Class end. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitEnd}.
      */
     public abstract void visitClassEnd();
 
@@ -232,37 +219,31 @@ public abstract class Printer {
     // ------------------------------------------------------------------------
 
     /**
-     * Annotation value.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visit}.
+     * Annotation value. See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visit}.
      */
     public abstract void visit(final String name, final Object value);
 
     /**
-     * Annotation enum value.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitEnum}.
+     * Annotation enum value. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitEnum}.
      */
-    public abstract void visitEnum(
-        final String name,
-        final String desc,
-        final String value);
+    public abstract void visitEnum(final String name, final String desc,
+            final String value);
 
     /**
-     * Nested annotation value.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitAnnotation}.
+     * Nested annotation value. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitAnnotation}.
      */
-    public abstract Printer visitAnnotation(
-        final String name,
-        final String desc);
+    public abstract Printer visitAnnotation(final String name, final String desc);
 
     /**
-     * Annotation array value.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitArray}.
+     * Annotation array value. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitArray}.
      */
     public abstract Printer visitArray(final String name);
 
     /**
-     * Annotation end.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitEnd}.
+     * Annotation end. See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitEnd}.
      */
     public abstract void visitAnnotationEnd();
 
@@ -271,22 +252,29 @@ public abstract class Printer {
     // ------------------------------------------------------------------------
 
     /**
-     * Field annotation.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitAnnotation}.
+     * Field annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitAnnotation}.
+     */
+    public abstract Printer visitFieldAnnotation(final String desc,
+            final boolean visible);
+
+    /**
+     * Field type annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitTypeAnnotation}.
      */
-    public abstract Printer visitFieldAnnotation(
-        final String desc,
-        final boolean visible);
+    public Printer visitFieldTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        throw new RuntimeException("Must be overriden");
+    }
 
     /**
-     * Field attribute.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitAttribute}.
+     * Field attribute. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitAttribute}.
      */
     public abstract void visitFieldAttribute(final Attribute attr);
 
     /**
-     * Field end.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitEnd}.
+     * Field end. See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitEnd}.
      */
     public abstract void visitFieldEnd();
 
@@ -295,199 +283,237 @@ public abstract class Printer {
     // ------------------------------------------------------------------------
 
     /**
-     * Method default annotation.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAnnotationDefault}.
+     * Method parameter. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitParameter(String, int)}.
+     */
+    public void visitParameter(String name, int access) {
+        throw new RuntimeException("Must be overriden");
+    }
+
+    /**
+     * Method default annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAnnotationDefault}.
      */
     public abstract Printer visitAnnotationDefault();
 
     /**
-     * Method annotation.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAnnotation}.
+     * Method annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAnnotation}.
      */
-    public abstract Printer visitMethodAnnotation(
-        final String desc,
-        final boolean visible);
+    public abstract Printer visitMethodAnnotation(final String desc,
+            final boolean visible);
 
     /**
-     * Method parameter annotation.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitParameterAnnotation}.
+     * Method type annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTypeAnnotation}.
      */
-    public abstract Printer visitParameterAnnotation(
-        final int parameter,
-        final String desc,
-        final boolean visible);
+    public Printer visitMethodTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        throw new RuntimeException("Must be overriden");
+    }
 
     /**
-     * Method attribute.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAttribute}.
+     * Method parameter annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitParameterAnnotation}.
+     */
+    public abstract Printer visitParameterAnnotation(final int parameter,
+            final String desc, final boolean visible);
+
+    /**
+     * Method attribute. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAttribute}.
      */
     public abstract void visitMethodAttribute(final Attribute attr);
 
     /**
-     * Method start.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitCode}.
+     * Method start. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitCode}.
      */
     public abstract void visitCode();
 
     /**
-     * Method stack frame.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFrame}.
+     * Method stack frame. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFrame}.
      */
-    public abstract void visitFrame(
-        final int type,
-        final int nLocal,
-        final Object[] local,
-        final int nStack,
-        final Object[] stack);
+    public abstract void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInsn}.
+     * Method instruction. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInsn}
+     * .
      */
     public abstract void visitInsn(final int opcode);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitIntInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitIntInsn}.
      */
     public abstract void visitIntInsn(final int opcode, final int operand);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitVarInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitVarInsn}.
      */
     public abstract void visitVarInsn(final int opcode, final int var);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTypeInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTypeInsn}.
      */
     public abstract void visitTypeInsn(final int opcode, final String type);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFieldInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFieldInsn}.
      */
-    public abstract void visitFieldInsn(
-        final int opcode,
-        final String owner,
-        final String name,
-        final String desc);
+    public abstract void visitFieldInsn(final int opcode, final String owner,
+            final String name, final String desc);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMethodInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMethodInsn}.
      */
-    public abstract void visitMethodInsn(
-        final int opcode,
-        final String owner,
-        final String name,
-        final String desc);
+    @Deprecated
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (api >= Opcodes.ASM5) {
+            boolean itf = opcode == Opcodes.INVOKEINTERFACE;
+            visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
+        throw new RuntimeException("Must be overriden");
+    }
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInvokeDynamicInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMethodInsn}.
      */
-    public abstract void visitInvokeDynamicInsn(
-        String name,
-        String desc,
-        Handle bsm,
-        Object... bsmArgs);
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            if (itf != (opcode == Opcodes.INVOKEINTERFACE)) {
+                throw new IllegalArgumentException(
+                        "INVOKESPECIAL/STATIC on interfaces require ASM 5");
+            }
+            visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        throw new RuntimeException("Must be overriden");
+    }
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitJumpInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInvokeDynamicInsn}.
+     */
+    public abstract void visitInvokeDynamicInsn(String name, String desc,
+            Handle bsm, Object... bsmArgs);
+
+    /**
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitJumpInsn}.
      */
     public abstract void visitJumpInsn(final int opcode, final Label label);
 
     /**
-     * Method label.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLabel}.
+     * Method label. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLabel}.
      */
     public abstract void visitLabel(final Label label);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLdcInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLdcInsn}.
      */
     public abstract void visitLdcInsn(final Object cst);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitIincInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitIincInsn}.
      */
     public abstract void visitIincInsn(final int var, final int increment);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTableSwitchInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTableSwitchInsn}.
+     */
+    public abstract void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels);
+
+    /**
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLookupSwitchInsn}.
      */
-    public abstract void visitTableSwitchInsn(
-        final int min,
-        final int max,
-        final Label dflt,
-        final Label... labels);
+    public abstract void visitLookupSwitchInsn(final Label dflt,
+            final int[] keys, final Label[] labels);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLookupSwitchInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMultiANewArrayInsn}.
      */
-    public abstract void visitLookupSwitchInsn(
-        final Label dflt,
-        final int[] keys,
-        final Label[] labels);
+    public abstract void visitMultiANewArrayInsn(final String desc,
+            final int dims);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMultiANewArrayInsn}.
+     * Instruction type annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInsnAnnotation}.
      */
-    public abstract void visitMultiANewArrayInsn(
-        final String desc,
-        final int dims);
+    public Printer visitInsnAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        throw new RuntimeException("Must be overriden");
+    }
 
     /**
-     * Method exception handler.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTryCatchBlock}.
+     * Method exception handler. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTryCatchBlock}.
      */
-    public abstract void visitTryCatchBlock(
-        final Label start,
-        final Label end,
-        final Label handler,
-        final String type);
+    public abstract void visitTryCatchBlock(final Label start, final Label end,
+            final Label handler, final String type);
 
     /**
-     * Method debug info.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLocalVariable}.
+     * Try catch block type annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTryCatchAnnotation}.
      */
-    public abstract void visitLocalVariable(
-        final String name,
-        final String desc,
-        final String signature,
-        final Label start,
-        final Label end,
-        final int index);
+    public Printer visitTryCatchAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        throw new RuntimeException("Must be overriden");
+    }
+
+    /**
+     * Method debug info. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLocalVariable}.
+     */
+    public abstract void visitLocalVariable(final String name,
+            final String desc, final String signature, final Label start,
+            final Label end, final int index);
+
+    /**
+     * Local variable type annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTryCatchAnnotation}.
+     */
+    public Printer visitLocalVariableAnnotation(final int typeRef,
+            final TypePath typePath, final Label[] start, final Label[] end,
+            final int[] index, final String desc, final boolean visible) {
+        throw new RuntimeException("Must be overriden");
+    }
 
     /**
-     * Method debug info.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLineNumber}.
+     * Method debug info. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLineNumber}.
      */
     public abstract void visitLineNumber(final int line, final Label start);
 
     /**
-     * Method max stack and max locals.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMaxs}.
+     * Method max stack and max locals. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMaxs}.
      */
     public abstract void visitMaxs(final int maxStack, final int maxLocals);
 
     /**
-     * Method end.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitEnd}.
+     * Method end. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitEnd}.
      */
     public abstract void visitMethodEnd();
 
     /**
      * Returns the text constructed by this visitor.
-     *
+     * 
      * @return the text constructed by this visitor.
      */
     public List<Object> getText() {
@@ -496,8 +522,9 @@ public abstract class Printer {
 
     /**
      * Prints the text constructed by this visitor.
-     *
-     * @param pw the print writer to be used.
+     * 
+     * @param pw
+     *            the print writer to be used.
      */
     public void print(final PrintWriter pw) {
         printList(pw, text);
@@ -505,9 +532,11 @@ public abstract class Printer {
 
     /**
      * Appends a quoted string to a given buffer.
-     *
-     * @param buf the buffer where the string must be added.
-     * @param s the string to be added.
+     * 
+     * @param buf
+     *            the buffer where the string must be added.
+     * @param s
+     *            the string to be added.
      */
     public static void appendString(final StringBuffer buf, final String s) {
         buf.append('\"');
@@ -540,10 +569,12 @@ public abstract class Printer {
 
     /**
      * Prints the given string tree.
-     *
-     * @param pw the writer to be used to print the tree.
-     * @param l a string tree, i.e., a string list that can contain other string
-     *        lists, and so on recursively.
+     * 
+     * @param pw
+     *            the writer to be used to print the tree.
+     * @param l
+     *            a string tree, i.e., a string list that can contain other
+     *            string lists, and so on recursively.
      */
     static void printList(final PrintWriter pw, final List<?> l) {
         for (int i = 0; i < l.size(); ++i) {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
index 81156fc..dfa5e41 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
@@ -29,26 +29,28 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.util;
 
-import org.apache.tapestry5.internal.plastic.asm.Label;
-
 import java.util.Map;
 
+import org.apache.tapestry5.internal.plastic.asm.Label;
+
 /**
  * An {@link org.apache.tapestry5.internal.plastic.asm.Attribute Attribute} that can print a readable
  * representation of itself.
- *
+ * 
  * Implementations should construct readable output from an attribute data
  * structure. Such representation could be used in unit test assertions.
- *
+ * 
  * @author Eugene Kuleshov
  */
 public interface Textifiable {
 
     /**
      * Build a human readable representation of this attribute.
-     *
-     * @param buf a buffer used for printing Java code.
-     * @param labelNames map of label instances to their names.
+     * 
+     * @param buf
+     *            a buffer used for printing Java code.
+     * @param labelNames
+     *            map of label instances to their names.
      */
     void textify(StringBuffer buf, Map<Label, String> labelNames);
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java
index 3598080..854fe7c 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java
@@ -29,14 +29,21 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.util;
 
-import org.apache.tapestry5.internal.plastic.asm.*;
-import org.apache.tapestry5.internal.plastic.asm.signature.SignatureReader;
-
 import java.io.FileInputStream;
 import java.io.PrintWriter;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureReader;
+
 /**
  * A {@link Printer} that prints a disassembled view of the classes it visits.
  *
@@ -130,36 +137,49 @@ public class Textifier extends Printer {
      */
     protected Map<Label, String> labelNames;
 
+    /**
+     * Class access flags
+     */
+    private int access;
+
     private int valueNumber = 0;
 
     /**
      * Constructs a new {@link Textifier}. <i>Subclasses must not use this
      * constructor</i>. Instead, they must use the {@link #Textifier(int)}
      * version.
+     *
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
      */
     public Textifier() {
-        this(Opcodes.ASM4);
+        this(Opcodes.ASM5);
+        if (getClass() != Textifier.class) {
+            throw new IllegalStateException();
+        }
     }
 
     /**
      * Constructs a new {@link Textifier}.
      *
-     * @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}.
      */
     protected Textifier(final int api) {
         super(api);
     }
 
     /**
-     * Prints a disassembled view of the given class to the standard output. <p>
-     * Usage: Textifier [-debug] &lt;binary class name or class
-     * file name &gt;
+     * Prints a disassembled view of the given class to the standard output.
+     * <p>
+     * Usage: Textifier [-debug] &lt;binary class name or class file name &gt;
      *
-     * @param args the command line arguments.
+     * @param args
+     *            the command line arguments.
      *
-     * @throws Exception if the class cannot be found, or if an IO exception
-     *         occurs.
+     * @throws Exception
+     *             if the class cannot be found, or if an IO exception occurs.
      */
     public static void main(final String[] args) throws Exception {
         int i = 0;
@@ -177,21 +197,20 @@ public class Textifier extends Printer {
             }
         }
         if (!ok) {
-            System.err.println("Prints a disassembled view of the given class.");
+            System.err
+                    .println("Prints a disassembled view of the given class.");
             System.err.println("Usage: Textifier [-debug] "
                     + "<fully qualified class name or class file name>");
             return;
         }
         ClassReader cr;
         if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1
-                || args[i].indexOf('/') > -1)
-        {
+                || args[i].indexOf('/') > -1) {
             cr = new ClassReader(new FileInputStream(args[i]));
         } else {
             cr = new ClassReader(args[i]);
         }
-        cr.accept(new TraceClassVisitor(new PrintWriter(System.out)),
-                flags);
+        cr.accept(new TraceClassVisitor(new PrintWriter(System.out)), flags);
     }
 
     // ------------------------------------------------------------------------
@@ -199,38 +218,28 @@ public class Textifier extends Printer {
     // ------------------------------------------------------------------------
 
     @Override
-    public void visit(
-        final int version,
-        final int access,
-        final String name,
-        final String signature,
-        final String superName,
-        final String[] interfaces)
-    {
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
+        this.access = access;
         int major = version & 0xFFFF;
         int minor = version >>> 16;
         buf.setLength(0);
-        buf.append("// class version ")
-                .append(major)
-                .append('.')
-                .append(minor)
-                .append(" (")
-                .append(version)
-                .append(")\n");
+        buf.append("// class version ").append(major).append('.').append(minor)
+                .append(" (").append(version).append(")\n");
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             buf.append("// DEPRECATED\n");
         }
-        buf.append("// access flags 0x").append(Integer.toHexString(access).toUpperCase()).append('\n');
+        buf.append("// access flags 0x")
+                .append(Integer.toHexString(access).toUpperCase()).append('\n');
 
         appendDescriptor(CLASS_SIGNATURE, signature);
         if (signature != null) {
             TraceSignatureVisitor sv = new TraceSignatureVisitor(access);
             SignatureReader r = new SignatureReader(signature);
             r.accept(sv);
-            buf.append("// declaration: ")
-                    .append(name)
-                    .append(sv.getDeclaration())
-                    .append('\n');
+            buf.append("// declaration: ").append(name)
+                    .append(sv.getDeclaration()).append('\n');
         }
 
         appendAccess(access & ~Opcodes.ACC_SUPER);
@@ -264,15 +273,11 @@ public class Textifier extends Printer {
     public void visitSource(final String file, final String debug) {
         buf.setLength(0);
         if (file != null) {
-            buf.append(tab)
-                    .append("// compiled from: ")
-                    .append(file)
+            buf.append(tab).append("// compiled from: ").append(file)
                     .append('\n');
         }
         if (debug != null) {
-            buf.append(tab)
-                    .append("// debug info: ")
-                    .append(debug)
+            buf.append(tab).append("// debug info: ").append(debug)
                     .append('\n');
         }
         if (buf.length() > 0) {
@@ -281,11 +286,8 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public void visitOuterClass(
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    public void visitOuterClass(final String owner, final String name,
+            final String desc) {
         buf.setLength(0);
         buf.append(tab).append("OUTERCLASS ");
         appendDescriptor(INTERNAL_NAME, owner);
@@ -299,30 +301,33 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public Textifier visitClassAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public Textifier visitClassAnnotation(final String desc,
+            final boolean visible) {
         text.add("\n");
         return visitAnnotation(desc, visible);
     }
 
     @Override
+    public Printer visitClassTypeAnnotation(int typeRef, TypePath typePath,
+            String desc, boolean visible) {
+        text.add("\n");
+        return visitTypeAnnotation(typeRef, typePath, desc, visible);
+    }
+
+    @Override
     public void visitClassAttribute(final Attribute attr) {
         text.add("\n");
         visitAttribute(attr);
     }
 
     @Override
-    public void visitInnerClass(
-        final String name,
-        final String outerName,
-        final String innerName,
-        final int access)
-    {
+    public void visitInnerClass(final String name, final String outerName,
+            final String innerName, final int access) {
         buf.setLength(0);
         buf.append(tab).append("// access flags 0x");
-        buf.append(Integer.toHexString(access & ~Opcodes.ACC_SUPER).toUpperCase()).append('\n');
+        buf.append(
+                Integer.toHexString(access & ~Opcodes.ACC_SUPER).toUpperCase())
+                .append('\n');
         buf.append(tab);
         appendAccess(access);
         buf.append("INNERCLASS ");
@@ -336,19 +341,15 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public Textifier visitField(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final Object value)
-    {
+    public Textifier visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
         buf.setLength(0);
         buf.append('\n');
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             buf.append(tab).append("// DEPRECATED\n");
         }
-        buf.append(tab).append("// access flags 0x").append(Integer.toHexString(access).toUpperCase()).append('\n');
+        buf.append(tab).append("// access flags 0x")
+                .append(Integer.toHexString(access).toUpperCase()).append('\n');
         if (signature != null) {
             buf.append(tab);
             appendDescriptor(FIELD_SIGNATURE, signature);
@@ -356,10 +357,8 @@ public class Textifier extends Printer {
             TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
             SignatureReader r = new SignatureReader(signature);
             r.acceptType(sv);
-            buf.append(tab)
-                    .append("// declaration: ")
-                    .append(sv.getDeclaration())
-                    .append('\n');
+            buf.append(tab).append("// declaration: ")
+                    .append(sv.getDeclaration()).append('\n');
         }
 
         buf.append(tab);
@@ -385,19 +384,15 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public Textifier visitMethod(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final String[] exceptions)
-    {
+    public Textifier visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
         buf.setLength(0);
         buf.append('\n');
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             buf.append(tab).append("// DEPRECATED\n");
         }
-        buf.append(tab).append("// access flags 0x").append(Integer.toHexString(access).toUpperCase()).append('\n');
+        buf.append(tab).append("// access flags 0x")
+                .append(Integer.toHexString(access).toUpperCase()).append('\n');
 
         if (signature != null) {
             buf.append(tab);
@@ -410,12 +405,8 @@ public class Textifier extends Printer {
             String genericReturn = v.getReturnType();
             String genericExceptions = v.getExceptions();
 
-            buf.append(tab)
-                    .append("// declaration: ")
-                    .append(genericReturn)
-                    .append(' ')
-                    .append(name)
-                    .append(genericDecl);
+            buf.append(tab).append("// declaration: ").append(genericReturn)
+                    .append(' ').append(name).append(genericDecl);
             if (genericExceptions != null) {
                 buf.append(" throws ").append(genericExceptions);
             }
@@ -433,6 +424,11 @@ public class Textifier extends Printer {
         if ((access & Opcodes.ACC_BRIDGE) != 0) {
             buf.append("bridge ");
         }
+        if ((this.access & Opcodes.ACC_INTERFACE) != 0
+                && (access & Opcodes.ACC_ABSTRACT) == 0
+                && (access & Opcodes.ACC_STATIC) == 0) {
+            buf.append("default ");
+        }
 
         buf.append(name);
         appendDescriptor(METHOD_DESCRIPTOR, desc);
@@ -588,11 +584,8 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public void visitEnum(
-        final String name,
-        final String desc,
-        final String value)
-    {
+    public void visitEnum(final String name, final String desc,
+            final String value) {
         buf.setLength(0);
         appendComa(valueNumber++);
         if (name != null) {
@@ -604,10 +597,7 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public Textifier visitAnnotation(
-        final String name,
-        final String desc)
-    {
+    public Textifier visitAnnotation(final String name, final String desc) {
         buf.setLength(0);
         appendComa(valueNumber++);
         if (name != null) {
@@ -624,9 +614,7 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public Textifier visitArray(
-        final String name)
-    {
+    public Textifier visitArray(final String name) {
         buf.setLength(0);
         appendComa(valueNumber++);
         if (name != null) {
@@ -649,14 +637,18 @@ public class Textifier extends Printer {
     // ------------------------------------------------------------------------
 
     @Override
-    public Textifier visitFieldAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public Textifier visitFieldAnnotation(final String desc,
+            final boolean visible) {
         return visitAnnotation(desc, visible);
     }
 
     @Override
+    public Printer visitFieldTypeAnnotation(int typeRef, TypePath typePath,
+            String desc, boolean visible) {
+        return visitTypeAnnotation(typeRef, typePath, desc, visible);
+    }
+
+    @Override
     public void visitFieldAttribute(final Attribute attr) {
         visitAttribute(attr);
     }
@@ -670,6 +662,16 @@ public class Textifier extends Printer {
     // ------------------------------------------------------------------------
 
     @Override
+    public void visitParameter(final String name, final int access) {
+        buf.setLength(0);
+        buf.append(tab2).append("// parameter ");
+        appendAccess(access);
+        buf.append(' ').append((name == null) ? "<no name>" : name)
+                .append('\n');
+        text.add(buf.toString());
+    }
+
+    @Override
     public Textifier visitAnnotationDefault() {
         text.add(tab2 + "default=");
         Textifier t = createTextifier();
@@ -679,19 +681,20 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public Textifier visitMethodAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public Textifier visitMethodAnnotation(final String desc,
+            final boolean visible) {
         return visitAnnotation(desc, visible);
     }
 
     @Override
-    public Textifier visitParameterAnnotation(
-        final int parameter,
-        final String desc,
-        final boolean visible)
-    {
+    public Printer visitMethodTypeAnnotation(int typeRef, TypePath typePath,
+            String desc, boolean visible) {
+        return visitTypeAnnotation(typeRef, typePath, desc, visible);
+    }
+
+    @Override
+    public Textifier visitParameterAnnotation(final int parameter,
+            final String desc, final boolean visible) {
         buf.setLength(0);
         buf.append(tab2).append('@');
         appendDescriptor(FIELD_DESCRIPTOR, desc);
@@ -725,40 +728,35 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public void visitFrame(
-        final int type,
-        final int nLocal,
-        final Object[] local,
-        final int nStack,
-        final Object[] stack)
-    {
+    public void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack) {
         buf.setLength(0);
         buf.append(ltab);
         buf.append("FRAME ");
         switch (type) {
-            case Opcodes.F_NEW:
-            case Opcodes.F_FULL:
-                buf.append("FULL [");
-                appendFrameTypes(nLocal, local);
-                buf.append("] [");
-                appendFrameTypes(nStack, stack);
-                buf.append(']');
-                break;
-            case Opcodes.F_APPEND:
-                buf.append("APPEND [");
-                appendFrameTypes(nLocal, local);
-                buf.append(']');
-                break;
-            case Opcodes.F_CHOP:
-                buf.append("CHOP ").append(nLocal);
-                break;
-            case Opcodes.F_SAME:
-                buf.append("SAME");
-                break;
-            case Opcodes.F_SAME1:
-                buf.append("SAME1 ");
-                appendFrameTypes(1, stack);
-                break;
+        case Opcodes.F_NEW:
+        case Opcodes.F_FULL:
+            buf.append("FULL [");
+            appendFrameTypes(nLocal, local);
+            buf.append("] [");
+            appendFrameTypes(nStack, stack);
+            buf.append(']');
+            break;
+        case Opcodes.F_APPEND:
+            buf.append("APPEND [");
+            appendFrameTypes(nLocal, local);
+            buf.append(']');
+            break;
+        case Opcodes.F_CHOP:
+            buf.append("CHOP ").append(nLocal);
+            break;
+        case Opcodes.F_SAME:
+            buf.append("SAME");
+            break;
+        case Opcodes.F_SAME1:
+            buf.append("SAME1 ");
+            appendFrameTypes(1, stack);
+            break;
         }
         buf.append('\n');
         text.add(buf.toString());
@@ -777,20 +775,15 @@ public class Textifier extends Printer {
         buf.append(tab2)
                 .append(OPCODES[opcode])
                 .append(' ')
-                .append(opcode == Opcodes.NEWARRAY
-                        ? TYPES[operand]
-                        : Integer.toString(operand))
-                .append('\n');
+                .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer
+                        .toString(operand)).append('\n');
         text.add(buf.toString());
     }
 
     @Override
     public void visitVarInsn(final int opcode, final int var) {
         buf.setLength(0);
-        buf.append(tab2)
-                .append(OPCODES[opcode])
-                .append(' ')
-                .append(var)
+        buf.append(tab2).append(OPCODES[opcode]).append(' ').append(var)
                 .append('\n');
         text.add(buf.toString());
     }
@@ -805,12 +798,8 @@ public class Textifier extends Printer {
     }
 
     @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) {
         buf.setLength(0);
         buf.append(tab2).append(OPCODES[opcode]).append(' ');
         appendDescriptor(INTERNAL_NAME, owner);
@@ -820,13 +809,30 @@ public class Textifier extends Printer {
         text.add(buf.toString());
     }
 
+    @Deprecated
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (api >= Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc,
+                opcode == Opcodes.INVOKEINTERFACE);
+    }
+
     @Override
-    public void visitMethodInsn(
-        final int opcode,
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    private void doVisitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
         buf.setLength(0);
         buf.append(tab2).append(OPCODES[opcode]).append(' ');
         appendDescriptor(INTERNAL_NAME, owner);
@@ -837,37 +843,42 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public void visitInvokeDynamicInsn(
-        String name,
-        String desc,
-        Handle bsm,
-        Object... bsmArgs)
-    {
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
         buf.setLength(0);
         buf.append(tab2).append("INVOKEDYNAMIC").append(' ');
         buf.append(name);
         appendDescriptor(METHOD_DESCRIPTOR, desc);
         buf.append(" [");
+        buf.append('\n');
+        buf.append(tab3);
         appendHandle(bsm);
+        buf.append('\n');
         buf.append(tab3).append("// arguments:");
-        if(bsmArgs.length == 0) {
+        if (bsmArgs.length == 0) {
             buf.append(" none");
         } else {
-            buf.append('\n').append(tab3);
-            for(int i = 0; i < bsmArgs.length; i++) {
+            buf.append('\n');
+            for (int i = 0; i < bsmArgs.length; i++) {
+                buf.append(tab3);
                 Object cst = bsmArgs[i];
                 if (cst instanceof String) {
                     Printer.appendString(buf, (String) cst);
                 } else if (cst instanceof Type) {
-                    buf.append(((Type) cst).getDescriptor()).append(".class");
+                    Type type = (Type) cst;
+                    if(type.getSort() == Type.METHOD){
+                        appendDescriptor(METHOD_DESCRIPTOR, type.getDescriptor());
+                    } else {
+                        buf.append(type.getDescriptor()).append(".class");
+                    }
                 } else if (cst instanceof Handle) {
                     appendHandle((Handle) cst);
                 } else {
                     buf.append(cst);
                 }
-                buf.append(", ");
+                buf.append(", \n");
             }
-            buf.setLength(buf.length() - 2);
+            buf.setLength(buf.length() - 3);
         }
         buf.append('\n');
         buf.append(tab2).append("]\n");
@@ -910,22 +921,14 @@ public class Textifier extends Printer {
     @Override
     public void visitIincInsn(final int var, final int increment) {
         buf.setLength(0);
-        buf.append(tab2)
-                .append("IINC ")
-                .append(var)
-                .append(' ')
-                .append(increment)
-                .append('\n');
+        buf.append(tab2).append("IINC ").append(var).append(' ')
+                .append(increment).append('\n');
         text.add(buf.toString());
     }
 
     @Override
-    public void visitTableSwitchInsn(
-        final int min,
-        final int max,
-        final Label dflt,
-        final Label... labels)
-    {
+    public void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels) {
         buf.setLength(0);
         buf.append(tab2).append("TABLESWITCH\n");
         for (int i = 0; i < labels.length; ++i) {
@@ -940,11 +943,8 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public void visitLookupSwitchInsn(
-        final Label dflt,
-        final int[] keys,
-        final Label[] labels)
-    {
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
         buf.setLength(0);
         buf.append(tab2).append("LOOKUPSWITCH\n");
         for (int i = 0; i < labels.length; ++i) {
@@ -968,12 +968,14 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public void visitTryCatchBlock(
-        final Label start,
-        final Label end,
-        final Label handler,
-        final String type)
-    {
+    public Printer visitInsnAnnotation(int typeRef, TypePath typePath,
+            String desc, boolean visible) {
+        return visitTypeAnnotation(typeRef, typePath, desc, visible);
+    }
+
+    @Override
+    public void visitTryCatchBlock(final Label start, final Label end,
+            final Label handler, final String type) {
         buf.setLength(0);
         buf.append(tab2).append("TRYCATCHBLOCK ");
         appendLabel(start);
@@ -988,14 +990,28 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public void visitLocalVariable(
-        final String name,
-        final String desc,
-        final String signature,
-        final Label start,
-        final Label end,
-        final int index)
-    {
+    public Printer visitTryCatchAnnotation(int typeRef, TypePath typePath,
+            String desc, boolean visible) {
+        buf.setLength(0);
+        buf.append(tab2).append("TRYCATCHBLOCK @");
+        appendDescriptor(FIELD_DESCRIPTOR, desc);
+        buf.append('(');
+        text.add(buf.toString());
+        Textifier t = createTextifier();
+        text.add(t.getText());
+        buf.setLength(0);
+        buf.append(") : ");
+        appendTypeReference(typeRef);
+        buf.append(", ").append(typePath);
+        buf.append(visible ? "\n" : " // invisible\n");
+        text.add(buf.toString());
+        return t;
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
         buf.setLength(0);
         buf.append(tab2).append("LOCALVARIABLE ").append(name).append(' ');
         appendDescriptor(FIELD_DESCRIPTOR, desc);
@@ -1012,12 +1028,37 @@ public class Textifier extends Printer {
             TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
             SignatureReader r = new SignatureReader(signature);
             r.acceptType(sv);
-            buf.append(tab2)
-                    .append("// declaration: ")
-                    .append(sv.getDeclaration())
-                    .append('\n');
+            buf.append(tab2).append("// declaration: ")
+                    .append(sv.getDeclaration()).append('\n');
+        }
+        text.add(buf.toString());
+    }
+
+    @Override
+    public Printer visitLocalVariableAnnotation(int typeRef, TypePath typePath,
+            Label[] start, Label[] end, int[] index, String desc,
+            boolean visible) {
+        buf.setLength(0);
+        buf.append(tab2).append("LOCALVARIABLE @");
+        appendDescriptor(FIELD_DESCRIPTOR, desc);
+        buf.append('(');
+        text.add(buf.toString());
+        Textifier t = createTextifier();
+        text.add(t.getText());
+        buf.setLength(0);
+        buf.append(") : ");
+        appendTypeReference(typeRef);
+        buf.append(", ").append(typePath);
+        for (int i = 0; i < start.length; ++i) {
+            buf.append(" [ ");
+            appendLabel(start[i]);
+            buf.append(" - ");
+            appendLabel(end[i]);
+            buf.append(" - ").append(index[i]).append(" ]");
         }
+        buf.append(visible ? "\n" : " // invisible\n");
         text.add(buf.toString());
+        return t;
     }
 
     @Override
@@ -1051,14 +1092,13 @@ public class Textifier extends Printer {
     /**
      * Prints a disassembled view of the given annotation.
      *
-     * @param desc the class descriptor of the annotation class.
-     * @param visible <tt>true</tt> if the annotation is visible at runtime.
+     * @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.
      */
-    public Textifier visitAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public Textifier visitAnnotation(final String desc, final boolean visible) {
         buf.setLength(0);
         buf.append(tab).append('@');
         appendDescriptor(FIELD_DESCRIPTOR, desc);
@@ -1071,9 +1111,43 @@ public class Textifier extends Printer {
     }
 
     /**
+     * Prints a disassembled view of the given type annotation.
+     *
+     * @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.
+     * @param visible
+     *            <tt>true</tt> if the annotation is visible at runtime.
+     * @return a visitor to visit the annotation values.
+     */
+    public Textifier visitTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        buf.setLength(0);
+        buf.append(tab).append('@');
+        appendDescriptor(FIELD_DESCRIPTOR, desc);
+        buf.append('(');
+        text.add(buf.toString());
+        Textifier t = createTextifier();
+        text.add(t.getText());
+        buf.setLength(0);
+        buf.append(") : ");
+        appendTypeReference(typeRef);
+        buf.append(", ").append(typePath);
+        buf.append(visible ? "\n" : " // invisible\n");
+        text.add(buf.toString());
+        return t;
+    }
+
+    /**
      * Prints a disassembled view of the given attribute.
      *
-     * @param attr an attribute.
+     * @param attr
+     *            an attribute.
      */
     public void visitAttribute(final Attribute attr) {
         buf.setLength(0);
@@ -1106,15 +1180,16 @@ public class Textifier extends Printer {
      * Appends an internal name, a type descriptor or a type signature to
      * {@link #buf buf}.
      *
-     * @param type indicates if desc is an internal name, a field descriptor, a
-     *        method descriptor, a class signature, ...
-     * @param desc an internal name, type descriptor, or type signature. May be
-     *        <tt>null</tt>.
+     * @param type
+     *            indicates if desc is an internal name, a field descriptor, a
+     *            method descriptor, a class signature, ...
+     * @param desc
+     *            an internal name, type descriptor, or type signature. May be
+     *            <tt>null</tt>.
      */
     protected void appendDescriptor(final int type, final String desc) {
         if (type == CLASS_SIGNATURE || type == FIELD_SIGNATURE
-                || type == METHOD_SIGNATURE)
-        {
+                || type == METHOD_SIGNATURE) {
             if (desc != null) {
                 buf.append("// signature ").append(desc).append('\n');
             }
@@ -1127,7 +1202,8 @@ public class Textifier extends Printer {
      * Appends the name of the given label to {@link #buf buf}. Creates a new
      * label name if the given label does not yet have one.
      *
-     * @param l a label.
+     * @param l
+     *            a label.
      */
     protected void appendLabel(final Label l) {
         if (labelNames == null) {
@@ -1144,56 +1220,68 @@ public class Textifier extends Printer {
     /**
      * Appends the information about the given handle to {@link #buf buf}.
      *
-     * @param h a handle, non null.
+     * @param h
+     *            a handle, non null.
      */
     protected void appendHandle(final Handle h) {
-        buf.append('\n').append(tab3);
         int tag = h.getTag();
-        buf.append("// handle kind 0x").append(Integer.toHexString(tag)).append(" : ");
+        buf.append("// handle kind 0x").append(Integer.toHexString(tag))
+                .append(" : ");
+        boolean isMethodHandle = false;
         switch (tag) {
-            case Opcodes.H_GETFIELD:
-                buf.append("GETFIELD");
-                break;
-            case Opcodes.H_GETSTATIC:
-                buf.append("GETSTATIC");
-                break;
-            case Opcodes.H_PUTFIELD:
-                buf.append("PUTFIELD");
-                break;
-            case Opcodes.H_PUTSTATIC:
-                buf.append("PUTSTATIC");
-                break;
-            case Opcodes.H_INVOKEINTERFACE:
-                buf.append("INVOKEINTERFACE");
-                break;
-            case Opcodes.H_INVOKESPECIAL:
-                buf.append("INVOKESPECIAL");
-                break;
-            case Opcodes.H_INVOKESTATIC:
-                buf.append("INVOKESTATIC");
-                break;
-            case Opcodes.H_INVOKEVIRTUAL:
-                buf.append("INVOKEVIRTUAL");
-                break;
-            case Opcodes.H_NEWINVOKESPECIAL:
-                buf.append("NEWINVOKESPECIAL");
-                break;
+        case Opcodes.H_GETFIELD:
+            buf.append("GETFIELD");
+            break;
+        case Opcodes.H_GETSTATIC:
+            buf.append("GETSTATIC");
+            break;
+        case Opcodes.H_PUTFIELD:
+            buf.append("PUTFIELD");
+            break;
+        case Opcodes.H_PUTSTATIC:
+            buf.append("PUTSTATIC");
+            break;
+        case Opcodes.H_INVOKEINTERFACE:
+            buf.append("INVOKEINTERFACE");
+            isMethodHandle = true;
+            break;
+        case Opcodes.H_INVOKESPECIAL:
+            buf.append("INVOKESPECIAL");
+            isMethodHandle = true;
+            break;
+        case Opcodes.H_INVOKESTATIC:
+            buf.append("INVOKESTATIC");
+            isMethodHandle = true;
+            break;
+        case Opcodes.H_INVOKEVIRTUAL:
+            buf.append("INVOKEVIRTUAL");
+            isMethodHandle = true;
+            break;
+        case Opcodes.H_NEWINVOKESPECIAL:
+            buf.append("NEWINVOKESPECIAL");
+            isMethodHandle = true;
+            break;
         }
         buf.append('\n');
         buf.append(tab3);
         appendDescriptor(INTERNAL_NAME, h.getOwner());
         buf.append('.');
         buf.append(h.getName());
-        buf.append('(');
+        if(!isMethodHandle){
+            buf.append('(');
+        }
         appendDescriptor(HANDLE_DESCRIPTOR, h.getDesc());
-        buf.append(')').append('\n');
+        if(!isMethodHandle){
+            buf.append(')');
+        }
     }
 
     /**
-     * Appends a string representation of the given access modifiers to {@link
-     * #buf buf}.
+     * Appends a string representation of the given access modifiers to
+     * {@link #buf buf}.
      *
-     * @param access some access modifiers.
+     * @param access
+     *            some access modifiers.
      */
     private void appendAccess(final int access) {
         if ((access & Opcodes.ACC_PUBLIC) != 0) {
@@ -1226,6 +1314,12 @@ public class Textifier extends Printer {
         if ((access & Opcodes.ACC_STRICT) != 0) {
             buf.append("strictfp ");
         }
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            buf.append("synthetic ");
+        }
+        if ((access & Opcodes.ACC_MANDATED) != 0) {
+            buf.append("mandated ");
+        }
         if ((access & Opcodes.ACC_ENUM) != 0) {
             buf.append("enum ");
         }
@@ -1237,6 +1331,90 @@ public class Textifier extends Printer {
         }
     }
 
+    private void appendTypeReference(final int typeRef) {
+        TypeReference ref = new TypeReference(typeRef);
+        switch (ref.getSort()) {
+        case TypeReference.CLASS_TYPE_PARAMETER:
+            buf.append("CLASS_TYPE_PARAMETER ").append(
+                    ref.getTypeParameterIndex());
+            break;
+        case TypeReference.METHOD_TYPE_PARAMETER:
+            buf.append("METHOD_TYPE_PARAMETER ").append(
+                    ref.getTypeParameterIndex());
+            break;
+        case TypeReference.CLASS_EXTENDS:
+            buf.append("CLASS_EXTENDS ").append(ref.getSuperTypeIndex());
+            break;
+        case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
+            buf.append("CLASS_TYPE_PARAMETER_BOUND ")
+                    .append(ref.getTypeParameterIndex()).append(", ")
+                    .append(ref.getTypeParameterBoundIndex());
+            break;
+        case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
+            buf.append("METHOD_TYPE_PARAMETER_BOUND ")
+                    .append(ref.getTypeParameterIndex()).append(", ")
+                    .append(ref.getTypeParameterBoundIndex());
+            break;
+        case TypeReference.FIELD:
+            buf.append("FIELD");
+            break;
+        case TypeReference.METHOD_RETURN:
+            buf.append("METHOD_RETURN");
+            break;
+        case TypeReference.METHOD_RECEIVER:
+            buf.append("METHOD_RECEIVER");
+            break;
+        case TypeReference.METHOD_FORMAL_PARAMETER:
+            buf.append("METHOD_FORMAL_PARAMETER ").append(
+                    ref.getFormalParameterIndex());
+            break;
+        case TypeReference.THROWS:
+            buf.append("THROWS ").append(ref.getExceptionIndex());
+            break;
+        case TypeReference.LOCAL_VARIABLE:
+            buf.append("LOCAL_VARIABLE");
+            break;
+        case TypeReference.RESOURCE_VARIABLE:
+            buf.append("RESOURCE_VARIABLE");
+            break;
+        case TypeReference.EXCEPTION_PARAMETER:
+            buf.append("EXCEPTION_PARAMETER ").append(
+                    ref.getTryCatchBlockIndex());
+            break;
+        case TypeReference.INSTANCEOF:
+            buf.append("INSTANCEOF");
+            break;
+        case TypeReference.NEW:
+            buf.append("NEW");
+            break;
+        case TypeReference.CONSTRUCTOR_REFERENCE:
+            buf.append("CONSTRUCTOR_REFERENCE");
+            break;
+        case TypeReference.METHOD_REFERENCE:
+            buf.append("METHOD_REFERENCE");
+            break;
+        case TypeReference.CAST:
+            buf.append("CAST ").append(ref.getTypeArgumentIndex());
+            break;
+        case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
+            buf.append("CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT ").append(
+                    ref.getTypeArgumentIndex());
+            break;
+        case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT:
+            buf.append("METHOD_INVOCATION_TYPE_ARGUMENT ").append(
+                    ref.getTypeArgumentIndex());
+            break;
+        case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
+            buf.append("CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT ").append(
+                    ref.getTypeArgumentIndex());
+            break;
+        case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT:
+            buf.append("METHOD_REFERENCE_TYPE_ARGUMENT ").append(
+                    ref.getTypeArgumentIndex());
+            break;
+        }
+    }
+
     private void appendFrameTypes(final int n, final Object[] o) {
         for (int i = 0; i < n; ++i) {
             if (i > 0) {
@@ -1251,27 +1429,27 @@ public class Textifier extends Printer {
                 }
             } else if (o[i] instanceof Integer) {
                 switch (((Integer) o[i]).intValue()) {
-                    case 0:
-                        appendDescriptor(FIELD_DESCRIPTOR, "T");
-                        break;
-                    case 1:
-                        appendDescriptor(FIELD_DESCRIPTOR, "I");
-                        break;
-                    case 2:
-                        appendDescriptor(FIELD_DESCRIPTOR, "F");
-                        break;
-                    case 3:
-                        appendDescriptor(FIELD_DESCRIPTOR, "D");
-                        break;
-                    case 4:
-                        appendDescriptor(FIELD_DESCRIPTOR, "J");
-                        break;
-                    case 5:
-                        appendDescriptor(FIELD_DESCRIPTOR, "N");
-                        break;
-                    case 6:
-                        appendDescriptor(FIELD_DESCRIPTOR, "U");
-                        break;
+                case 0:
+                    appendDescriptor(FIELD_DESCRIPTOR, "T");
+                    break;
+                case 1:
+                    appendDescriptor(FIELD_DESCRIPTOR, "I");
+                    break;
+                case 2:
+                    appendDescriptor(FIELD_DESCRIPTOR, "F");
+                    break;
+                case 3:
+                    appendDescriptor(FIELD_DESCRIPTOR, "D");
+                    break;
+                case 4:
+                    appendDescriptor(FIELD_DESCRIPTOR, "J");
+                    break;
+                case 5:
+                    appendDescriptor(FIELD_DESCRIPTOR, "N");
+                    break;
+                case 6:
+                    appendDescriptor(FIELD_DESCRIPTOR, "U");
+                    break;
                 }
             } else {
                 appendLabel((Label) o[i]);

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
index 84b9750..3af500a 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
@@ -33,13 +33,12 @@ import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
 import org.apache.tapestry5.internal.plastic.asm.Opcodes;
 
 /**
- * An {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor} that prints the annotations it visits with a
+ * An {@link AnnotationVisitor} that prints the annotations it visits with a
  * {@link Printer}.
- *
+ * 
  * @author Eric Bruneton
  */
-public final class TraceAnnotationVisitor extends AnnotationVisitor
-{
+public final class TraceAnnotationVisitor extends AnnotationVisitor {
 
     private final Printer p;
 
@@ -48,7 +47,7 @@ public final class TraceAnnotationVisitor extends AnnotationVisitor
     }
 
     public TraceAnnotationVisitor(final AnnotationVisitor av, final Printer p) {
-        super(Opcodes.ASM4, av);
+        super(Opcodes.ASM5, av);
         this.p = p;
     }
 
@@ -59,33 +58,26 @@ public final class TraceAnnotationVisitor extends AnnotationVisitor
     }
 
     @Override
-    public void visitEnum(
-        final String name,
-        final String desc,
-        final String value)
-    {
+    public void visitEnum(final String name, final String desc,
+            final String value) {
         p.visitEnum(name, desc, value);
         super.visitEnum(name, desc, value);
     }
 
     @Override
-    public AnnotationVisitor visitAnnotation(
-        final String name,
-        final String desc)
-    {
+    public AnnotationVisitor visitAnnotation(final String name,
+            final String desc) {
         Printer p = this.p.visitAnnotation(name, desc);
-        AnnotationVisitor av = this.av == null
-                ? null
-                : this.av.visitAnnotation(name, desc);
+        AnnotationVisitor av = this.av == null ? null : this.av
+                .visitAnnotation(name, desc);
         return new TraceAnnotationVisitor(av, p);
     }
 
     @Override
     public AnnotationVisitor visitArray(final String name) {
         Printer p = this.p.visitArray(name);
-        AnnotationVisitor av = this.av == null
-                ? null
-                : this.av.visitArray(name);
+        AnnotationVisitor av = this.av == null ? null : this.av
+                .visitArray(name);
         return new TraceAnnotationVisitor(av, p);
     }
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java
index ae06852..7c6a775 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.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,18 +29,28 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.util;
 
-import org.apache.tapestry5.internal.plastic.asm.*;
-
 import java.io.PrintWriter;
 
+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.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
 /**
  * A {@link ClassVisitor} that prints the classes it visits with a
  * {@link Printer}. This class visitor can be used in the middle of a class
  * visitor chain to trace the class that is visited at a given point in this
- * chain. This may be useful for debugging purposes. <p> The trace printed when
- * visiting the <tt>Hello</tt> class is the following: <p> <blockquote>
+ * chain. This may be useful for debugging purposes.
+ * <p>
+ * The trace printed when visiting the <tt>Hello</tt> class is the following:
+ * <p>
+ * <blockquote>
  * 
- * <pre> // class version 49.0 (49) // access flags 0x21 public class Hello {
+ * <pre>
+ * // class version 49.0 (49) // access flags 0x21 public class Hello {
  * 
  * // compiled from: Hello.java
  * 
@@ -51,14 +60,21 @@ import java.io.PrintWriter;
  * // access flags 0x9 public static main ([Ljava/lang/String;)V GETSTATIC
  * java/lang/System out Ljava/io/PrintStream; LDC &quot;hello&quot;
  * INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V RETURN
- * MAXSTACK = 2 MAXLOCALS = 1 } </pre>
+ * MAXSTACK = 2 MAXLOCALS = 1 }
+ * </pre>
  * 
- * </blockquote> where <tt>Hello</tt> is defined by: <p> <blockquote>
+ * </blockquote> where <tt>Hello</tt> is defined by:
+ * <p>
+ * <blockquote>
  * 
- * <pre> public class Hello {
+ * <pre>
+ * public class Hello {
  * 
- * public static void main(String[] args) {
- * System.out.println(&quot;hello&quot;); } } </pre>
+ *     public static void main(String[] args) {
+ *         System.out.println(&quot;hello&quot;);
+ *     }
+ * }
+ * </pre>
  * 
  * </blockquote>
  * 
@@ -80,7 +96,8 @@ public final class TraceClassVisitor extends ClassVisitor {
     /**
      * Constructs a new {@link TraceClassVisitor}.
      * 
-     * @param pw the print writer to be used to print the class.
+     * @param pw
+     *            the print writer to be used to print the class.
      */
     public TraceClassVisitor(final PrintWriter pw) {
         this(null, pw);
@@ -89,9 +106,11 @@ public final class TraceClassVisitor extends ClassVisitor {
     /**
      * Constructs a new {@link TraceClassVisitor}.
      * 
-     * @param cv the {@link ClassVisitor} to which this visitor delegates calls.
-     *        May be <tt>null</tt>.
-     * @param pw the print writer to be used to print the class.
+     * @param cv
+     *            the {@link ClassVisitor} to which this visitor delegates
+     *            calls. May be <tt>null</tt>.
+     * @param pw
+     *            the print writer to be used to print the class.
      */
     public TraceClassVisitor(final ClassVisitor cv, final PrintWriter pw) {
         this(cv, new Textifier(), pw);
@@ -100,32 +119,27 @@ public final class TraceClassVisitor extends ClassVisitor {
     /**
      * Constructs a new {@link TraceClassVisitor}.
      * 
-     * @param cv the {@link ClassVisitor} to which this visitor delegates calls.
-     *        May be <tt>null</tt>.
-     * @param p the object that actually converts visit events into text.
-     * @param pw the print writer to be used to print the class. May be null if
-     *        you simply want to use the result via
-     *        {@link Printer#getText()}, instead of printing it.
+     * @param cv
+     *            the {@link ClassVisitor} to which this visitor delegates
+     *            calls. May be <tt>null</tt>.
+     * @param p
+     *            the object that actually converts visit events into text.
+     * @param pw
+     *            the print writer to be used to print the class. May be null if
+     *            you simply want to use the result via
+     *            {@link Printer#getText()}, instead of printing it.
      */
-    public TraceClassVisitor(
-        final ClassVisitor cv,
-        final Printer p,
-        final PrintWriter pw)
-    {
-        super(Opcodes.ASM4, cv);
+    public TraceClassVisitor(final ClassVisitor cv, final Printer p,
+            final PrintWriter pw) {
+        super(Opcodes.ASM5, cv);
         this.pw = pw;
         this.p = p;
     }
 
     @Override
-    public void visit(
-        final int version,
-        final int access,
-        final String name,
-        final String signature,
-        final String superName,
-        final String[] interfaces)
-    {
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
         p.visit(version, access, name, signature, superName, interfaces);
         super.visit(version, access, name, signature, superName, interfaces);
     }
@@ -137,20 +151,15 @@ public final class TraceClassVisitor extends ClassVisitor {
     }
 
     @Override
-    public void visitOuterClass(
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    public void visitOuterClass(final String owner, final String name,
+            final String desc) {
         p.visitOuterClass(owner, name, desc);
         super.visitOuterClass(owner, name, desc);
     }
 
     @Override
-    public AnnotationVisitor visitAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
         Printer p = this.p.visitClassAnnotation(desc, visible);
         AnnotationVisitor av = cv == null ? null : cv.visitAnnotation(desc,
                 visible);
@@ -158,61 +167,44 @@ public final class TraceClassVisitor extends ClassVisitor {
     }
 
     @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        Printer p = this.p.visitClassTypeAnnotation(typeRef, typePath, desc,
+                visible);
+        AnnotationVisitor av = cv == null ? null : cv.visitTypeAnnotation(
+                typeRef, typePath, desc, visible);
+        return new TraceAnnotationVisitor(av, p);
+    }
+
+    @Override
     public void visitAttribute(final Attribute attr) {
         p.visitClassAttribute(attr);
         super.visitAttribute(attr);
     }
 
     @Override
-    public void visitInnerClass(
-        final String name,
-        final String outerName,
-        final String innerName,
-        final int access)
-    {
+    public void visitInnerClass(final String name, final String outerName,
+            final String innerName, final int access) {
         p.visitInnerClass(name, outerName, innerName, access);
         super.visitInnerClass(name, outerName, innerName, access);
     }
 
     @Override
-    public FieldVisitor visitField(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final Object value)
-    {
-        Printer p = this.p.visitField(access,
-                name,
-                desc,
-                signature,
-                value);
-        FieldVisitor fv = cv == null ? null : cv.visitField(access,
-                name,
-                desc,
-                signature,
-                value);
+    public FieldVisitor visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
+        Printer p = this.p.visitField(access, name, desc, signature, value);
+        FieldVisitor fv = cv == null ? null : cv.visitField(access, name, desc,
+                signature, value);
         return new TraceFieldVisitor(fv, p);
     }
 
     @Override
-    public MethodVisitor visitMethod(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final String[] exceptions)
-    {
-        Printer p = this.p.visitMethod(access,
-                name,
-                desc,
-                signature,
-                exceptions);
-        MethodVisitor mv = cv == null ? null : cv.visitMethod(access,
-                name,
-                desc,
-                signature,
+    public MethodVisitor visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        Printer p = this.p.visitMethod(access, name, desc, signature,
                 exceptions);
+        MethodVisitor mv = cv == null ? null : cv.visitMethod(access, name,
+                desc, signature, exceptions);
         return new TraceMethodVisitor(mv, p);
     }
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java
index d75b04b..3fed39e 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.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
@@ -34,15 +33,15 @@ import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
 import org.apache.tapestry5.internal.plastic.asm.Attribute;
 import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
 import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
 
 /**
- * A {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor} that prints the fields it visits with a
+ * A {@link FieldVisitor} that prints the fields it visits with a
  * {@link Printer}.
  * 
  * @author Eric Bruneton
  */
-public final class TraceFieldVisitor extends FieldVisitor
-{
+public final class TraceFieldVisitor extends FieldVisitor {
 
     public final Printer p;
 
@@ -51,15 +50,13 @@ public final class TraceFieldVisitor extends FieldVisitor
     }
 
     public TraceFieldVisitor(final FieldVisitor fv, final Printer p) {
-        super(Opcodes.ASM4, fv);
+        super(Opcodes.ASM5, fv);
         this.p = p;
     }
-        
+
     @Override
-    public AnnotationVisitor visitAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
         Printer p = this.p.visitFieldAnnotation(desc, visible);
         AnnotationVisitor av = fv == null ? null : fv.visitAnnotation(desc,
                 visible);
@@ -67,6 +64,16 @@ public final class TraceFieldVisitor extends FieldVisitor
     }
 
     @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        Printer p = this.p.visitFieldTypeAnnotation(typeRef, typePath, desc,
+                visible);
+        AnnotationVisitor av = fv == null ? null : fv.visitTypeAnnotation(
+                typeRef, typePath, desc, visible);
+        return new TraceAnnotationVisitor(av, p);
+    }
+
+    @Override
     public void visitAttribute(final Attribute attr) {
         p.visitFieldAttribute(attr);
         super.visitAttribute(attr);


[03/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java
index 0d7fe3f..859a8d1 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.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,12 +29,18 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.util;
 
-import org.apache.tapestry5.internal.plastic.asm.*;
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+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.TypePath;
 
 /**
  * A {@link MethodVisitor} that prints the methods it visits with a
  * {@link Printer}.
- *
+ * 
  * @author Eric Bruneton
  */
 public final class TraceMethodVisitor extends MethodVisitor {
@@ -47,15 +52,19 @@ public final class TraceMethodVisitor extends MethodVisitor {
     }
 
     public TraceMethodVisitor(final MethodVisitor mv, final Printer p) {
-        super(Opcodes.ASM4, mv);
+        super(Opcodes.ASM5, mv);
         this.p = p;
     }
 
     @Override
-    public AnnotationVisitor visitAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public void visitParameter(String name, int access) {
+        p.visitParameter(name, access);
+        super.visitParameter(name, access);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
         Printer p = this.p.visitMethodAnnotation(desc, visible);
         AnnotationVisitor av = mv == null ? null : mv.visitAnnotation(desc,
                 visible);
@@ -63,6 +72,16 @@ public final class TraceMethodVisitor extends MethodVisitor {
     }
 
     @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        Printer p = this.p.visitMethodTypeAnnotation(typeRef, typePath, desc,
+                visible);
+        AnnotationVisitor av = mv == null ? null : mv.visitTypeAnnotation(
+                typeRef, typePath, desc, visible);
+        return new TraceAnnotationVisitor(av, p);
+    }
+
+    @Override
     public void visitAttribute(final Attribute attr) {
         p.visitMethodAttribute(attr);
         super.visitAttribute(attr);
@@ -76,17 +95,11 @@ public final class TraceMethodVisitor extends MethodVisitor {
     }
 
     @Override
-    public AnnotationVisitor visitParameterAnnotation(
-        final int parameter,
-        final String desc,
-        final boolean visible)
-    {
-        Printer p = this.p.visitParameterAnnotation(parameter,
-                desc,
-                visible);
-        AnnotationVisitor av = mv == null
-                ? null
-                : mv.visitParameterAnnotation(parameter, desc, visible);
+    public AnnotationVisitor visitParameterAnnotation(final int parameter,
+            final String desc, final boolean visible) {
+        Printer p = this.p.visitParameterAnnotation(parameter, desc, visible);
+        AnnotationVisitor av = mv == null ? null : mv.visitParameterAnnotation(
+                parameter, desc, visible);
         return new TraceAnnotationVisitor(av, p);
     }
 
@@ -97,13 +110,8 @@ public final class TraceMethodVisitor extends MethodVisitor {
     }
 
     @Override
-    public void visitFrame(
-        final int type,
-        final int nLocal,
-        final Object[] local,
-        final int nStack,
-        final Object[] stack)
-    {
+    public void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack) {
         p.visitFrame(type, nLocal, local, nStack, stack);
         super.visitFrame(type, nLocal, local, nStack, stack);
     }
@@ -133,34 +141,42 @@ public final class TraceMethodVisitor 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) {
         p.visitFieldInsn(opcode, owner, name, desc);
         super.visitFieldInsn(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;
+        }
         p.visitMethodInsn(opcode, owner, name, desc);
-        super.visitMethodInsn(opcode, owner, name, desc);
+        if (mv != null) {
+            mv.visitMethodInsn(opcode, owner, name, desc);
+        }
+    }
+
+    @Override
+    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;
+        }
+        p.visitMethodInsn(opcode, owner, name, desc, itf);
+        if (mv != null) {
+            mv.visitMethodInsn(opcode, owner, name, desc, itf);
+        }
     }
 
     @Override
-    public void visitInvokeDynamicInsn(
-        String name,
-        String desc,
-        Handle bsm,
-        Object... bsmArgs)
-    {
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
         p.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
         super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
     }
@@ -190,22 +206,15 @@ public final class TraceMethodVisitor extends MethodVisitor {
     }
 
     @Override
-    public void visitTableSwitchInsn(
-        final int min,
-        final int max,
-        final Label dflt,
-        final Label... labels)
-    {
+    public void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels) {
         p.visitTableSwitchInsn(min, max, dflt, labels);
         super.visitTableSwitchInsn(min, max, dflt, labels);
     }
 
     @Override
-    public void visitLookupSwitchInsn(
-        final Label dflt,
-        final int[] keys,
-        final Label[] labels)
-    {
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
         p.visitLookupSwitchInsn(dflt, keys, labels);
         super.visitLookupSwitchInsn(dflt, keys, labels);
     }
@@ -217,30 +226,53 @@ public final class TraceMethodVisitor 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) {
+        Printer p = this.p
+                .visitInsnAnnotation(typeRef, typePath, desc, visible);
+        AnnotationVisitor av = mv == null ? null : mv.visitInsnAnnotation(
+                typeRef, typePath, desc, visible);
+        return new TraceAnnotationVisitor(av, p);
+    }
+
+    @Override
+    public void visitTryCatchBlock(final Label start, final Label end,
+            final Label handler, final String type) {
         p.visitTryCatchBlock(start, end, handler, type);
         super.visitTryCatchBlock(start, end, handler, type);
     }
 
     @Override
-    public void visitLocalVariable(
-        final String name,
-        final String desc,
-        final String signature,
-        final Label start,
-        final Label end,
-        final int index)
-    {
+    public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        Printer p = this.p.visitTryCatchAnnotation(typeRef, typePath, desc,
+                visible);
+        AnnotationVisitor av = mv == null ? null : mv.visitTryCatchAnnotation(
+                typeRef, typePath, desc, visible);
+        return new TraceAnnotationVisitor(av, p);
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
         p.visitLocalVariable(name, desc, signature, start, end, index);
         super.visitLocalVariable(name, desc, signature, start, end, index);
     }
 
     @Override
+    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+            TypePath typePath, Label[] start, Label[] end, int[] index,
+            String desc, boolean visible) {
+        Printer p = this.p.visitLocalVariableAnnotation(typeRef, typePath,
+                start, end, index, desc, visible);
+        AnnotationVisitor av = mv == null ? null : mv
+                .visitLocalVariableAnnotation(typeRef, typePath, start, end,
+                        index, desc, visible);
+        return new TraceAnnotationVisitor(av, p);
+    }
+
+    @Override
     public void visitLineNumber(final int line, final Label start) {
         p.visitLineNumber(line, start);
         super.visitLineNumber(line, start);

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
index 3b0a178..1e2c9a3 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
@@ -33,14 +33,13 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
 import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
 
 /**
- * A {@link org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor} that prints a disassembled view of the signature
+ * A {@link SignatureVisitor} that prints a disassembled view of the signature
  * it visits.
- *
+ * 
  * @author Eugene Kuleshov
  * @author Eric Bruneton
  */
-public final class TraceSignatureVisitor extends SignatureVisitor
-{
+public final class TraceSignatureVisitor extends SignatureVisitor {
 
     private final StringBuffer declaration;
 
@@ -76,13 +75,13 @@ public final class TraceSignatureVisitor extends SignatureVisitor
     private String separator = "";
 
     public TraceSignatureVisitor(final int access) {
-        super(Opcodes.ASM4);
+        super(Opcodes.ASM5);
         isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
         this.declaration = new StringBuffer();
     }
 
     private TraceSignatureVisitor(final StringBuffer buf) {
-        super(Opcodes.ASM4);
+        super(Opcodes.ASM5);
         this.declaration = buf;
     }
 
@@ -118,8 +117,7 @@ public final class TraceSignatureVisitor extends SignatureVisitor
 
     @Override
     public SignatureVisitor visitInterface() {
-        separator = seenInterface ? ", " : isInterface
-                ? " extends "
+        separator = seenInterface ? ", " : isInterface ? " extends "
                 : " implements ";
         seenInterface = true;
         startType();
@@ -166,34 +164,34 @@ public final class TraceSignatureVisitor extends SignatureVisitor
     @Override
     public void visitBaseType(final char descriptor) {
         switch (descriptor) {
-            case 'V':
-                declaration.append("void");
-                break;
-            case 'B':
-                declaration.append("byte");
-                break;
-            case 'J':
-                declaration.append("long");
-                break;
-            case 'Z':
-                declaration.append("boolean");
-                break;
-            case 'I':
-                declaration.append("int");
-                break;
-            case 'S':
-                declaration.append("short");
-                break;
-            case 'C':
-                declaration.append("char");
-                break;
-            case 'F':
-                declaration.append("float");
-                break;
-            // case 'D':
-            default:
-                declaration.append("double");
-                break;
+        case 'V':
+            declaration.append("void");
+            break;
+        case 'B':
+            declaration.append("byte");
+            break;
+        case 'J':
+            declaration.append("long");
+            break;
+        case 'Z':
+            declaration.append("boolean");
+            break;
+        case 'I':
+            declaration.append("int");
+            break;
+        case 'S':
+            declaration.append("short");
+            break;
+        case 'C':
+            declaration.append("char");
+            break;
+        case 'F':
+            declaration.append("float");
+            break;
+        // case 'D':
+        default:
+            declaration.append("double");
+            break;
         }
         endType();
     }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java
new file mode 100644
index 0000000..88dab5e
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java
@@ -0,0 +1,1453 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * 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.xml;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+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;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * A {@link org.xml.sax.ContentHandler ContentHandler} that transforms XML
+ * document into Java class file. This class can be feeded by any kind of SAX
+ * 2.0 event producers, e.g. XML parser, XSLT or XPath engines, or custom code.
+ * 
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.SAXClassAdapter
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.Processor
+ * 
+ * @author Eugene Kuleshov
+ */
+public class ASMContentHandler extends DefaultHandler implements Opcodes {
+
+    /**
+     * Stack of the intermediate processing contexts.
+     */
+    private final ArrayList<Object> stack = new ArrayList<Object>();
+
+    /**
+     * Complete name of the current element.
+     */
+    String match = "";
+
+    /**
+     * Current instance of the {@link ClassVisitor ClassVisitor} used to visit
+     * classfile bytecode.
+     */
+    protected ClassVisitor cv;
+
+    /**
+     * Map of the active {@link Label Label} instances for current method.
+     */
+    protected Map<Object, Label> labels;
+
+    private static final String BASE = "class";
+
+    private final RuleSet RULES = new RuleSet();
+    {
+        RULES.add(BASE, new ClassRule());
+        RULES.add(BASE + "/interfaces/interface", new InterfaceRule());
+        RULES.add(BASE + "/interfaces", new InterfacesRule());
+        RULES.add(BASE + "/outerclass", new OuterClassRule());
+        RULES.add(BASE + "/innerclass", new InnerClassRule());
+        RULES.add(BASE + "/source", new SourceRule());
+        RULES.add(BASE + "/field", new FieldRule());
+
+        RULES.add(BASE + "/method", new MethodRule());
+        RULES.add(BASE + "/method/exceptions/exception", new ExceptionRule());
+        RULES.add(BASE + "/method/exceptions", new ExceptionsRule());
+
+        RULES.add(BASE + "/method/parameter", new MethodParameterRule());
+        RULES.add(BASE + "/method/annotationDefault",
+                new AnnotationDefaultRule());
+
+        RULES.add(BASE + "/method/code/*", new OpcodesRule()); // opcodes
+
+        RULES.add(BASE + "/method/code/frame", new FrameRule());
+        RULES.add(BASE + "/method/code/frame/local", new FrameTypeRule());
+        RULES.add(BASE + "/method/code/frame/stack", new FrameTypeRule());
+
+        RULES.add(BASE + "/method/code/TABLESWITCH", new TableSwitchRule());
+        RULES.add(BASE + "/method/code/TABLESWITCH/label",
+                new TableSwitchLabelRule());
+        RULES.add(BASE + "/method/code/LOOKUPSWITCH", new LookupSwitchRule());
+        RULES.add(BASE + "/method/code/LOOKUPSWITCH/label",
+                new LookupSwitchLabelRule());
+
+        RULES.add(BASE + "/method/code/INVOKEDYNAMIC", new InvokeDynamicRule());
+        RULES.add(BASE + "/method/code/INVOKEDYNAMIC/bsmArg",
+                new InvokeDynamicBsmArgumentsRule());
+
+        RULES.add(BASE + "/method/code/Label", new LabelRule());
+        RULES.add(BASE + "/method/code/TryCatch", new TryCatchRule());
+        RULES.add(BASE + "/method/code/LineNumber", new LineNumberRule());
+        RULES.add(BASE + "/method/code/LocalVar", new LocalVarRule());
+        RULES.add(BASE + "/method/code/Max", new MaxRule());
+
+        RULES.add("*/annotation", new AnnotationRule());
+        RULES.add("*/typeAnnotation", new TypeAnnotationRule());
+        RULES.add("*/parameterAnnotation", new AnnotationParameterRule());
+        RULES.add("*/insnAnnotation", new InsnAnnotationRule());
+        RULES.add("*/tryCatchAnnotation", new TryCatchAnnotationRule());
+        RULES.add("*/localVariableAnnotation",
+                new LocalVariableAnnotationRule());
+        RULES.add("*/annotationValue", new AnnotationValueRule());
+        RULES.add("*/annotationValueAnnotation",
+                new AnnotationValueAnnotationRule());
+        RULES.add("*/annotationValueEnum", new AnnotationValueEnumRule());
+        RULES.add("*/annotationValueArray", new AnnotationValueArrayRule());
+    }
+
+    private static interface OpcodeGroup {
+        public static final int INSN = 0;
+        public static final int INSN_INT = 1;
+        public static final int INSN_VAR = 2;
+        public static final int INSN_TYPE = 3;
+        public static final int INSN_FIELD = 4;
+        public static final int INSN_METHOD = 5;
+        public static final int INSN_JUMP = 6;
+        public static final int INSN_LDC = 7;
+        public static final int INSN_IINC = 8;
+        public static final int INSN_MULTIANEWARRAY = 9;
+    }
+
+    /**
+     * Map of the opcode names to opcode and opcode group
+     */
+    static final HashMap<String, Opcode> OPCODES = new HashMap<String, Opcode>();
+    static {
+        addOpcode("NOP", NOP, OpcodeGroup.INSN);
+        addOpcode("ACONST_NULL", ACONST_NULL, OpcodeGroup.INSN);
+        addOpcode("ICONST_M1", ICONST_M1, OpcodeGroup.INSN);
+        addOpcode("ICONST_0", ICONST_0, OpcodeGroup.INSN);
+        addOpcode("ICONST_1", ICONST_1, OpcodeGroup.INSN);
+        addOpcode("ICONST_2", ICONST_2, OpcodeGroup.INSN);
+        addOpcode("ICONST_3", ICONST_3, OpcodeGroup.INSN);
+        addOpcode("ICONST_4", ICONST_4, OpcodeGroup.INSN);
+        addOpcode("ICONST_5", ICONST_5, OpcodeGroup.INSN);
+        addOpcode("LCONST_0", LCONST_0, OpcodeGroup.INSN);
+        addOpcode("LCONST_1", LCONST_1, OpcodeGroup.INSN);
+        addOpcode("FCONST_0", FCONST_0, OpcodeGroup.INSN);
+        addOpcode("FCONST_1", FCONST_1, OpcodeGroup.INSN);
+        addOpcode("FCONST_2", FCONST_2, OpcodeGroup.INSN);
+        addOpcode("DCONST_0", DCONST_0, OpcodeGroup.INSN);
+        addOpcode("DCONST_1", DCONST_1, OpcodeGroup.INSN);
+        addOpcode("BIPUSH", BIPUSH, OpcodeGroup.INSN_INT);
+        addOpcode("SIPUSH", SIPUSH, OpcodeGroup.INSN_INT);
+        addOpcode("LDC", LDC, OpcodeGroup.INSN_LDC);
+        addOpcode("ILOAD", ILOAD, OpcodeGroup.INSN_VAR);
+        addOpcode("LLOAD", LLOAD, OpcodeGroup.INSN_VAR);
+        addOpcode("FLOAD", FLOAD, OpcodeGroup.INSN_VAR);
+        addOpcode("DLOAD", DLOAD, OpcodeGroup.INSN_VAR);
+        addOpcode("ALOAD", ALOAD, OpcodeGroup.INSN_VAR);
+        addOpcode("IALOAD", IALOAD, OpcodeGroup.INSN);
+        addOpcode("LALOAD", LALOAD, OpcodeGroup.INSN);
+        addOpcode("FALOAD", FALOAD, OpcodeGroup.INSN);
+        addOpcode("DALOAD", DALOAD, OpcodeGroup.INSN);
+        addOpcode("AALOAD", AALOAD, OpcodeGroup.INSN);
+        addOpcode("BALOAD", BALOAD, OpcodeGroup.INSN);
+        addOpcode("CALOAD", CALOAD, OpcodeGroup.INSN);
+        addOpcode("SALOAD", SALOAD, OpcodeGroup.INSN);
+        addOpcode("ISTORE", ISTORE, OpcodeGroup.INSN_VAR);
+        addOpcode("LSTORE", LSTORE, OpcodeGroup.INSN_VAR);
+        addOpcode("FSTORE", FSTORE, OpcodeGroup.INSN_VAR);
+        addOpcode("DSTORE", DSTORE, OpcodeGroup.INSN_VAR);
+        addOpcode("ASTORE", ASTORE, OpcodeGroup.INSN_VAR);
+        addOpcode("IASTORE", IASTORE, OpcodeGroup.INSN);
+        addOpcode("LASTORE", LASTORE, OpcodeGroup.INSN);
+        addOpcode("FASTORE", FASTORE, OpcodeGroup.INSN);
+        addOpcode("DASTORE", DASTORE, OpcodeGroup.INSN);
+        addOpcode("AASTORE", AASTORE, OpcodeGroup.INSN);
+        addOpcode("BASTORE", BASTORE, OpcodeGroup.INSN);
+        addOpcode("CASTORE", CASTORE, OpcodeGroup.INSN);
+        addOpcode("SASTORE", SASTORE, OpcodeGroup.INSN);
+        addOpcode("POP", POP, OpcodeGroup.INSN);
+        addOpcode("POP2", POP2, OpcodeGroup.INSN);
+        addOpcode("DUP", DUP, OpcodeGroup.INSN);
+        addOpcode("DUP_X1", DUP_X1, OpcodeGroup.INSN);
+        addOpcode("DUP_X2", DUP_X2, OpcodeGroup.INSN);
+        addOpcode("DUP2", DUP2, OpcodeGroup.INSN);
+        addOpcode("DUP2_X1", DUP2_X1, OpcodeGroup.INSN);
+        addOpcode("DUP2_X2", DUP2_X2, OpcodeGroup.INSN);
+        addOpcode("SWAP", SWAP, OpcodeGroup.INSN);
+        addOpcode("IADD", IADD, OpcodeGroup.INSN);
+        addOpcode("LADD", LADD, OpcodeGroup.INSN);
+        addOpcode("FADD", FADD, OpcodeGroup.INSN);
+        addOpcode("DADD", DADD, OpcodeGroup.INSN);
+        addOpcode("ISUB", ISUB, OpcodeGroup.INSN);
+        addOpcode("LSUB", LSUB, OpcodeGroup.INSN);
+        addOpcode("FSUB", FSUB, OpcodeGroup.INSN);
+        addOpcode("DSUB", DSUB, OpcodeGroup.INSN);
+        addOpcode("IMUL", IMUL, OpcodeGroup.INSN);
+        addOpcode("LMUL", LMUL, OpcodeGroup.INSN);
+        addOpcode("FMUL", FMUL, OpcodeGroup.INSN);
+        addOpcode("DMUL", DMUL, OpcodeGroup.INSN);
+        addOpcode("IDIV", IDIV, OpcodeGroup.INSN);
+        addOpcode("LDIV", LDIV, OpcodeGroup.INSN);
+        addOpcode("FDIV", FDIV, OpcodeGroup.INSN);
+        addOpcode("DDIV", DDIV, OpcodeGroup.INSN);
+        addOpcode("IREM", IREM, OpcodeGroup.INSN);
+        addOpcode("LREM", LREM, OpcodeGroup.INSN);
+        addOpcode("FREM", FREM, OpcodeGroup.INSN);
+        addOpcode("DREM", DREM, OpcodeGroup.INSN);
+        addOpcode("INEG", INEG, OpcodeGroup.INSN);
+        addOpcode("LNEG", LNEG, OpcodeGroup.INSN);
+        addOpcode("FNEG", FNEG, OpcodeGroup.INSN);
+        addOpcode("DNEG", DNEG, OpcodeGroup.INSN);
+        addOpcode("ISHL", ISHL, OpcodeGroup.INSN);
+        addOpcode("LSHL", LSHL, OpcodeGroup.INSN);
+        addOpcode("ISHR", ISHR, OpcodeGroup.INSN);
+        addOpcode("LSHR", LSHR, OpcodeGroup.INSN);
+        addOpcode("IUSHR", IUSHR, OpcodeGroup.INSN);
+        addOpcode("LUSHR", LUSHR, OpcodeGroup.INSN);
+        addOpcode("IAND", IAND, OpcodeGroup.INSN);
+        addOpcode("LAND", LAND, OpcodeGroup.INSN);
+        addOpcode("IOR", IOR, OpcodeGroup.INSN);
+        addOpcode("LOR", LOR, OpcodeGroup.INSN);
+        addOpcode("IXOR", IXOR, OpcodeGroup.INSN);
+        addOpcode("LXOR", LXOR, OpcodeGroup.INSN);
+        addOpcode("IINC", IINC, OpcodeGroup.INSN_IINC);
+        addOpcode("I2L", I2L, OpcodeGroup.INSN);
+        addOpcode("I2F", I2F, OpcodeGroup.INSN);
+        addOpcode("I2D", I2D, OpcodeGroup.INSN);
+        addOpcode("L2I", L2I, OpcodeGroup.INSN);
+        addOpcode("L2F", L2F, OpcodeGroup.INSN);
+        addOpcode("L2D", L2D, OpcodeGroup.INSN);
+        addOpcode("F2I", F2I, OpcodeGroup.INSN);
+        addOpcode("F2L", F2L, OpcodeGroup.INSN);
+        addOpcode("F2D", F2D, OpcodeGroup.INSN);
+        addOpcode("D2I", D2I, OpcodeGroup.INSN);
+        addOpcode("D2L", D2L, OpcodeGroup.INSN);
+        addOpcode("D2F", D2F, OpcodeGroup.INSN);
+        addOpcode("I2B", I2B, OpcodeGroup.INSN);
+        addOpcode("I2C", I2C, OpcodeGroup.INSN);
+        addOpcode("I2S", I2S, OpcodeGroup.INSN);
+        addOpcode("LCMP", LCMP, OpcodeGroup.INSN);
+        addOpcode("FCMPL", FCMPL, OpcodeGroup.INSN);
+        addOpcode("FCMPG", FCMPG, OpcodeGroup.INSN);
+        addOpcode("DCMPL", DCMPL, OpcodeGroup.INSN);
+        addOpcode("DCMPG", DCMPG, OpcodeGroup.INSN);
+        addOpcode("IFEQ", IFEQ, OpcodeGroup.INSN_JUMP);
+        addOpcode("IFNE", IFNE, OpcodeGroup.INSN_JUMP);
+        addOpcode("IFLT", IFLT, OpcodeGroup.INSN_JUMP);
+        addOpcode("IFGE", IFGE, OpcodeGroup.INSN_JUMP);
+        addOpcode("IFGT", IFGT, OpcodeGroup.INSN_JUMP);
+        addOpcode("IFLE", IFLE, OpcodeGroup.INSN_JUMP);
+        addOpcode("IF_ICMPEQ", IF_ICMPEQ, OpcodeGroup.INSN_JUMP);
+        addOpcode("IF_ICMPNE", IF_ICMPNE, OpcodeGroup.INSN_JUMP);
+        addOpcode("IF_ICMPLT", IF_ICMPLT, OpcodeGroup.INSN_JUMP);
+        addOpcode("IF_ICMPGE", IF_ICMPGE, OpcodeGroup.INSN_JUMP);
+        addOpcode("IF_ICMPGT", IF_ICMPGT, OpcodeGroup.INSN_JUMP);
+        addOpcode("IF_ICMPLE", IF_ICMPLE, OpcodeGroup.INSN_JUMP);
+        addOpcode("IF_ACMPEQ", IF_ACMPEQ, OpcodeGroup.INSN_JUMP);
+        addOpcode("IF_ACMPNE", IF_ACMPNE, OpcodeGroup.INSN_JUMP);
+        addOpcode("GOTO", GOTO, OpcodeGroup.INSN_JUMP);
+        addOpcode("JSR", JSR, OpcodeGroup.INSN_JUMP);
+        addOpcode("RET", RET, OpcodeGroup.INSN_VAR);
+        addOpcode("IRETURN", IRETURN, OpcodeGroup.INSN);
+        addOpcode("LRETURN", LRETURN, OpcodeGroup.INSN);
+        addOpcode("FRETURN", FRETURN, OpcodeGroup.INSN);
+        addOpcode("DRETURN", DRETURN, OpcodeGroup.INSN);
+        addOpcode("ARETURN", ARETURN, OpcodeGroup.INSN);
+        addOpcode("RETURN", RETURN, OpcodeGroup.INSN);
+        addOpcode("GETSTATIC", GETSTATIC, OpcodeGroup.INSN_FIELD);
+        addOpcode("PUTSTATIC", PUTSTATIC, OpcodeGroup.INSN_FIELD);
+        addOpcode("GETFIELD", GETFIELD, OpcodeGroup.INSN_FIELD);
+        addOpcode("PUTFIELD", PUTFIELD, OpcodeGroup.INSN_FIELD);
+        addOpcode("INVOKEVIRTUAL", INVOKEVIRTUAL, OpcodeGroup.INSN_METHOD);
+        addOpcode("INVOKESPECIAL", INVOKESPECIAL, OpcodeGroup.INSN_METHOD);
+        addOpcode("INVOKESTATIC", INVOKESTATIC, OpcodeGroup.INSN_METHOD);
+        addOpcode("INVOKEINTERFACE", INVOKEINTERFACE, OpcodeGroup.INSN_METHOD);
+        addOpcode("NEW", NEW, OpcodeGroup.INSN_TYPE);
+        addOpcode("NEWARRAY", NEWARRAY, OpcodeGroup.INSN_INT);
+        addOpcode("ANEWARRAY", ANEWARRAY, OpcodeGroup.INSN_TYPE);
+        addOpcode("ARRAYLENGTH", ARRAYLENGTH, OpcodeGroup.INSN);
+        addOpcode("ATHROW", ATHROW, OpcodeGroup.INSN);
+        addOpcode("CHECKCAST", CHECKCAST, OpcodeGroup.INSN_TYPE);
+        addOpcode("INSTANCEOF", INSTANCEOF, OpcodeGroup.INSN_TYPE);
+        addOpcode("MONITORENTER", MONITORENTER, OpcodeGroup.INSN);
+        addOpcode("MONITOREXIT", MONITOREXIT, OpcodeGroup.INSN);
+        addOpcode("MULTIANEWARRAY", MULTIANEWARRAY,
+                OpcodeGroup.INSN_MULTIANEWARRAY);
+        addOpcode("IFNULL", IFNULL, OpcodeGroup.INSN_JUMP);
+        addOpcode("IFNONNULL", IFNONNULL, OpcodeGroup.INSN_JUMP);
+    }
+
+    private static void addOpcode(String operStr, int oper, int group) {
+        OPCODES.put(operStr, new Opcode(oper, group));
+    }
+
+    static final HashMap<String, Integer> TYPES = new HashMap<String, Integer>();
+    static {
+        String[] types = SAXCodeAdapter.TYPES;
+        for (int i = 0; i < types.length; i++) {
+            TYPES.put(types[i], new Integer(i));
+        }
+    }
+
+    /**
+     * Constructs a new {@link ASMContentHandler ASMContentHandler} object.
+     * 
+     * @param cv
+     *            class visitor that will be called to reconstruct the classfile
+     *            using the XML stream.
+     */
+    public ASMContentHandler(final ClassVisitor cv) {
+        this.cv = cv;
+    }
+
+    /**
+     * Process notification of the start of an XML element being reached.
+     * 
+     * @param ns
+     *            - The Namespace URI, or the empty string if the element has no
+     *            Namespace URI or if Namespace processing is not being
+     *            performed.
+     * @param lName
+     *            - The local name (without prefix), or the empty string if
+     *            Namespace processing is not being performed.
+     * @param qName
+     *            - The qualified name (with prefix), or the empty string if
+     *            qualified names are not available.
+     * @param list
+     *            - The attributes attached to the element. If there are no
+     *            attributes, it shall be an empty Attributes object.
+     * @exception SAXException
+     *                if a parsing error is to be reported
+     */
+    @Override
+    public final void startElement(final String ns, final String lName,
+            final String qName, final Attributes list) throws SAXException {
+        // the actual element name is either in lName or qName, depending
+        // on whether the parser is namespace aware
+        String name = lName == null || lName.length() == 0 ? qName : lName;
+
+        // Compute the current matching rule
+        StringBuffer sb = new StringBuffer(match);
+        if (match.length() > 0) {
+            sb.append('/');
+        }
+        sb.append(name);
+        match = sb.toString();
+
+        // Fire "begin" events for all relevant rules
+        Rule r = (Rule) RULES.match(match);
+        if (r != null) {
+            r.begin(name, list);
+        }
+    }
+
+    /**
+     * Process notification of the end of an XML element being reached.
+     * 
+     * @param ns
+     *            - The Namespace URI, or the empty string if the element has no
+     *            Namespace URI or if Namespace processing is not being
+     *            performed.
+     * @param lName
+     *            - The local name (without prefix), or the empty string if
+     *            Namespace processing is not being performed.
+     * @param qName
+     *            - The qualified XML 1.0 name (with prefix), or the empty
+     *            string if qualified names are not available.
+     * 
+     * @exception SAXException
+     *                if a parsing error is to be reported
+     */
+    @Override
+    public final void endElement(final String ns, final String lName,
+            final String qName) throws SAXException {
+        // the actual element name is either in lName or qName, depending
+        // on whether the parser is namespace aware
+        String name = lName == null || lName.length() == 0 ? qName : lName;
+
+        // Fire "end" events for all relevant rules in reverse order
+        Rule r = (Rule) RULES.match(match);
+        if (r != null) {
+            r.end(name);
+        }
+
+        // Recover the previous match expression
+        int slash = match.lastIndexOf('/');
+        if (slash >= 0) {
+            match = match.substring(0, slash);
+        } else {
+            match = "";
+        }
+    }
+
+    /**
+     * Return the top object on the stack without removing it. If there are no
+     * objects on the stack, return <code>null</code>.
+     * 
+     * @return the top object on the stack without removing it.
+     */
+    final Object peek() {
+        int size = stack.size();
+        return size == 0 ? null : stack.get(size - 1);
+    }
+
+    /**
+     * Pop the top object off of the stack, and return it. If there are no
+     * objects on the stack, return <code>null</code>.
+     * 
+     * @return the top object off of the stack.
+     */
+    final Object pop() {
+        int size = stack.size();
+        return size == 0 ? null : stack.remove(size - 1);
+    }
+
+    /**
+     * Push a new object onto the top of the object stack.
+     * 
+     * @param object
+     *            The new object
+     */
+    final void push(final Object object) {
+        stack.add(object);
+    }
+
+    static final class RuleSet {
+
+        private final HashMap<String, Object> rules = new HashMap<String, Object>();
+
+        private final ArrayList<String> lpatterns = new ArrayList<String>();
+
+        private final ArrayList<String> rpatterns = new ArrayList<String>();
+
+        public void add(final String path, final Object rule) {
+            String pattern = path;
+            if (path.startsWith("*/")) {
+                pattern = path.substring(1);
+                lpatterns.add(pattern);
+            } else if (path.endsWith("/*")) {
+                pattern = path.substring(0, path.length() - 1);
+                rpatterns.add(pattern);
+            }
+            rules.put(pattern, rule);
+        }
+
+        public Object match(final String path) {
+            if (rules.containsKey(path)) {
+                return rules.get(path);
+            }
+
+            int n = path.lastIndexOf('/');
+            for (Iterator<String> it = lpatterns.iterator(); it.hasNext();) {
+                String pattern = it.next();
+                if (path.substring(n).endsWith(pattern)) {
+                    return rules.get(pattern);
+                }
+            }
+
+            for (Iterator<String> it = rpatterns.iterator(); it.hasNext();) {
+                String pattern = it.next();
+                if (path.startsWith(pattern)) {
+                    return rules.get(pattern);
+                }
+            }
+
+            return null;
+        }
+    }
+
+    /**
+     * Rule
+     */
+    protected abstract class Rule {
+
+        public void begin(final String name, final Attributes attrs)
+                throws SAXException {
+        }
+
+        public void end(final String name) {
+        }
+
+        protected final Object getValue(final String desc, final String val)
+                throws SAXException {
+            Object value = null;
+            if (val != null) {
+                if ("Ljava/lang/String;".equals(desc)) {
+                    value = decode(val);
+                } else if ("Ljava/lang/Integer;".equals(desc)
+                        || "I".equals(desc) || "S".equals(desc)
+                        || "B".equals(desc) || "C".equals(desc)
+                        || "Z".equals(desc)) {
+                    value = new Integer(val);
+
+                } else if ("Ljava/lang/Short;".equals(desc)) {
+                    value = new Short(val);
+
+                } else if ("Ljava/lang/Byte;".equals(desc)) {
+                    value = new Byte(val);
+
+                } else if ("Ljava/lang/Character;".equals(desc)) {
+                    value = new Character(decode(val).charAt(0));
+
+                } else if ("Ljava/lang/Boolean;".equals(desc)) {
+                    value = Boolean.valueOf(val);
+
+                } else if ("Ljava/lang/Long;".equals(desc) || "J".equals(desc)) {
+                    value = new Long(val);
+                } else if ("Ljava/lang/Float;".equals(desc) || "F".equals(desc)) {
+                    value = new Float(val);
+                } else if ("Ljava/lang/Double;".equals(desc)
+                        || "D".equals(desc)) {
+                    value = new Double(val);
+                } else if (Type.getDescriptor(Type.class).equals(desc)) {
+                    value = Type.getType(val);
+
+                } else if (Type.getDescriptor(Handle.class).equals(desc)) {
+                    value = decodeHandle(val);
+
+                } else {
+                    // TODO use of default toString().
+                    throw new SAXException("Invalid value:" + val + " desc:"
+                            + desc + " ctx:" + this);
+                }
+            }
+            return value;
+        }
+
+        Handle decodeHandle(final String val) throws SAXException {
+            try {
+                int dotIndex = val.indexOf('.');
+                int descIndex = val.indexOf('(', dotIndex + 1);
+                int tagIndex = val.lastIndexOf('(');
+
+                int tag = Integer.parseInt(val.substring(tagIndex + 1,
+                        val.length() - 1));
+                String owner = val.substring(0, dotIndex);
+                String name = val.substring(dotIndex + 1, descIndex);
+                String desc = val.substring(descIndex, tagIndex - 1);
+                return new Handle(tag, owner, name, desc);
+
+            } catch (RuntimeException e) {
+                throw new SAXException("Malformed handle " + val, e);
+            }
+        }
+
+        private final String decode(final String val) throws SAXException {
+            StringBuffer sb = new StringBuffer(val.length());
+            try {
+                int n = 0;
+                while (n < val.length()) {
+                    char c = val.charAt(n);
+                    if (c == '\\') {
+                        n++;
+                        c = val.charAt(n);
+                        if (c == '\\') {
+                            sb.append('\\');
+                        } else {
+                            n++; // skip 'u'
+                            sb.append((char) Integer.parseInt(
+                                    val.substring(n, n + 4), 16));
+                            n += 3;
+                        }
+                    } else {
+                        sb.append(c);
+                    }
+                    n++;
+                }
+
+            } catch (RuntimeException ex) {
+                throw new SAXException(ex);
+            }
+            return sb.toString();
+        }
+
+        protected final Label getLabel(final Object label) {
+            Label lbl = labels.get(label);
+            if (lbl == null) {
+                lbl = new Label();
+                labels.put(label, lbl);
+            }
+            return lbl;
+        }
+
+        // TODO verify move to stack
+        protected final MethodVisitor getCodeVisitor() {
+            return (MethodVisitor) peek();
+        }
+
+        protected final int getAccess(final String s) {
+            int access = 0;
+            if (s.indexOf("public") != -1) {
+                access |= ACC_PUBLIC;
+            }
+            if (s.indexOf("private") != -1) {
+                access |= ACC_PRIVATE;
+            }
+            if (s.indexOf("protected") != -1) {
+                access |= ACC_PROTECTED;
+            }
+            if (s.indexOf("static") != -1) {
+                access |= ACC_STATIC;
+            }
+            if (s.indexOf("final") != -1) {
+                access |= ACC_FINAL;
+            }
+            if (s.indexOf("super") != -1) {
+                access |= ACC_SUPER;
+            }
+            if (s.indexOf("synchronized") != -1) {
+                access |= ACC_SYNCHRONIZED;
+            }
+            if (s.indexOf("volatile") != -1) {
+                access |= ACC_VOLATILE;
+            }
+            if (s.indexOf("bridge") != -1) {
+                access |= ACC_BRIDGE;
+            }
+            if (s.indexOf("varargs") != -1) {
+                access |= ACC_VARARGS;
+            }
+            if (s.indexOf("transient") != -1) {
+                access |= ACC_TRANSIENT;
+            }
+            if (s.indexOf("native") != -1) {
+                access |= ACC_NATIVE;
+            }
+            if (s.indexOf("interface") != -1) {
+                access |= ACC_INTERFACE;
+            }
+            if (s.indexOf("abstract") != -1) {
+                access |= ACC_ABSTRACT;
+            }
+            if (s.indexOf("strict") != -1) {
+                access |= ACC_STRICT;
+            }
+            if (s.indexOf("synthetic") != -1) {
+                access |= ACC_SYNTHETIC;
+            }
+            if (s.indexOf("annotation") != -1) {
+                access |= ACC_ANNOTATION;
+            }
+            if (s.indexOf("enum") != -1) {
+                access |= ACC_ENUM;
+            }
+            if (s.indexOf("deprecated") != -1) {
+                access |= ACC_DEPRECATED;
+            }
+            if (s.indexOf("mandated") != -1) {
+                access |= ACC_MANDATED;
+            }
+            return access;
+        }
+    }
+
+    /**
+     * ClassRule
+     */
+    final class ClassRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            int major = Integer.parseInt(attrs.getValue("major"));
+            int minor = Integer.parseInt(attrs.getValue("minor"));
+            HashMap<String, Object> vals = new HashMap<String, Object>();
+            vals.put("version", new Integer(minor << 16 | major));
+            vals.put("access", attrs.getValue("access"));
+            vals.put("name", attrs.getValue("name"));
+            vals.put("parent", attrs.getValue("parent"));
+            vals.put("source", attrs.getValue("source"));
+            vals.put("signature", attrs.getValue("signature"));
+            vals.put("interfaces", new ArrayList<String>());
+            push(vals);
+            // values will be extracted in InterfacesRule.end();
+        }
+    }
+
+    final class SourceRule extends Rule {
+
+        @Override
+        public void begin(final String name, final Attributes attrs) {
+            String file = attrs.getValue("file");
+            String debug = attrs.getValue("debug");
+            cv.visitSource(file, debug);
+        }
+    }
+
+    /**
+     * InterfaceRule
+     */
+    final class InterfaceRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            ((ArrayList<String>) ((HashMap<?, ?>) peek()).get("interfaces"))
+                    .add(attrs.getValue("name"));
+        }
+    }
+
+    /**
+     * InterfacesRule
+     */
+    final class InterfacesRule extends Rule {
+
+        @Override
+        public final void end(final String element) {
+            HashMap<?, ?> vals = (HashMap<?, ?>) pop();
+            int version = ((Integer) vals.get("version")).intValue();
+            int access = getAccess((String) vals.get("access"));
+            String name = (String) vals.get("name");
+            String signature = (String) vals.get("signature");
+            String parent = (String) vals.get("parent");
+            ArrayList<?> infs = (ArrayList<?>) vals.get("interfaces");
+            String[] interfaces = infs.toArray(new String[infs.size()]);
+            cv.visit(version, access, name, signature, parent, interfaces);
+            push(cv);
+        }
+    }
+
+    /**
+     * OuterClassRule
+     */
+    final class OuterClassRule extends Rule {
+
+        @Override
+        public final void begin(final String element, final Attributes attrs) {
+            String owner = attrs.getValue("owner");
+            String name = attrs.getValue("name");
+            String desc = attrs.getValue("desc");
+            cv.visitOuterClass(owner, name, desc);
+        }
+    }
+
+    /**
+     * InnerClassRule
+     */
+    final class InnerClassRule extends Rule {
+
+        @Override
+        public final void begin(final String element, final Attributes attrs) {
+            int access = getAccess(attrs.getValue("access"));
+            String name = attrs.getValue("name");
+            String outerName = attrs.getValue("outerName");
+            String innerName = attrs.getValue("innerName");
+            cv.visitInnerClass(name, outerName, innerName, access);
+        }
+    }
+
+    /**
+     * FieldRule
+     */
+    final class FieldRule extends Rule {
+
+        @Override
+        public final void begin(final String element, final Attributes attrs)
+                throws SAXException {
+            int access = getAccess(attrs.getValue("access"));
+            String name = attrs.getValue("name");
+            String signature = attrs.getValue("signature");
+            String desc = attrs.getValue("desc");
+            Object value = getValue(desc, attrs.getValue("value"));
+            push(cv.visitField(access, name, desc, signature, value));
+        }
+
+        @Override
+        public void end(final String name) {
+            ((FieldVisitor) pop()).visitEnd();
+        }
+    }
+
+    /**
+     * MethodRule
+     */
+    final class MethodRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            labels = new HashMap<Object, Label>();
+            HashMap<String, Object> vals = new HashMap<String, Object>();
+            vals.put("access", attrs.getValue("access"));
+            vals.put("name", attrs.getValue("name"));
+            vals.put("desc", attrs.getValue("desc"));
+            vals.put("signature", attrs.getValue("signature"));
+            vals.put("exceptions", new ArrayList<String>());
+            push(vals);
+            // values will be extracted in ExceptionsRule.end();
+        }
+
+        @Override
+        public final void end(final String name) {
+            ((MethodVisitor) pop()).visitEnd();
+            labels = null;
+        }
+    }
+
+    /**
+     * ExceptionRule
+     */
+    final class ExceptionRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            ((ArrayList<String>) ((HashMap<?, ?>) peek()).get("exceptions"))
+                    .add(attrs.getValue("name"));
+        }
+    }
+
+    /**
+     * ExceptionsRule
+     */
+    final class ExceptionsRule extends Rule {
+
+        @Override
+        public final void end(final String element) {
+            HashMap<?, ?> vals = (HashMap<?, ?>) pop();
+            int access = getAccess((String) vals.get("access"));
+            String name = (String) vals.get("name");
+            String desc = (String) vals.get("desc");
+            String signature = (String) vals.get("signature");
+            ArrayList<?> excs = (ArrayList<?>) vals.get("exceptions");
+            String[] exceptions = excs.toArray(new String[excs.size()]);
+
+            push(cv.visitMethod(access, name, desc, signature, exceptions));
+        }
+    }
+
+    /**
+     * MethodParameterRule
+     */
+    final class MethodParameterRule extends Rule {
+        @Override
+        public void begin(final String nm, final Attributes attrs) {
+            String name = attrs.getValue("name");
+            int access = getAccess(attrs.getValue("access"));
+            getCodeVisitor().visitParameter(name, access);
+        }
+    }
+
+    /**
+     * TableSwitchRule
+     */
+    final class TableSwitchRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            HashMap<String, Object> vals = new HashMap<String, Object>();
+            vals.put("min", attrs.getValue("min"));
+            vals.put("max", attrs.getValue("max"));
+            vals.put("dflt", attrs.getValue("dflt"));
+            vals.put("labels", new ArrayList<String>());
+            push(vals);
+        }
+
+        @Override
+        public final void end(final String name) {
+            HashMap<?, ?> vals = (HashMap<?, ?>) pop();
+            int min = Integer.parseInt((String) vals.get("min"));
+            int max = Integer.parseInt((String) vals.get("max"));
+            Label dflt = getLabel(vals.get("dflt"));
+            ArrayList<?> lbls = (ArrayList<?>) vals.get("labels");
+            Label[] labels = lbls.toArray(new Label[lbls.size()]);
+            getCodeVisitor().visitTableSwitchInsn(min, max, dflt, labels);
+        }
+    }
+
+    /**
+     * TableSwitchLabelRule
+     */
+    final class TableSwitchLabelRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            ((ArrayList<Label>) ((HashMap<?, ?>) peek()).get("labels"))
+                    .add(getLabel(attrs.getValue("name")));
+        }
+    }
+
+    /**
+     * LookupSwitchRule
+     */
+    final class LookupSwitchRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            HashMap<String, Object> vals = new HashMap<String, Object>();
+            vals.put("dflt", attrs.getValue("dflt"));
+            vals.put("labels", new ArrayList<Label>());
+            vals.put("keys", new ArrayList<String>());
+            push(vals);
+        }
+
+        @Override
+        public final void end(final String name) {
+            HashMap<?, ?> vals = (HashMap<?, ?>) pop();
+            Label dflt = getLabel(vals.get("dflt"));
+            ArrayList<String> keyList = (ArrayList<String>) vals.get("keys");
+            ArrayList<?> lbls = (ArrayList<?>) vals.get("labels");
+            Label[] labels = lbls.toArray(new Label[lbls.size()]);
+            int[] keys = new int[keyList.size()];
+            for (int i = 0; i < keys.length; i++) {
+                keys[i] = Integer.parseInt(keyList.get(i));
+            }
+            getCodeVisitor().visitLookupSwitchInsn(dflt, keys, labels);
+        }
+    }
+
+    /**
+     * LookupSwitchLabelRule
+     */
+    final class LookupSwitchLabelRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            HashMap<?, ?> vals = (HashMap<?, ?>) peek();
+            ((ArrayList<Label>) vals.get("labels")).add(getLabel(attrs
+                    .getValue("name")));
+            ((ArrayList<String>) vals.get("keys")).add(attrs.getValue("key"));
+        }
+    }
+
+    /**
+     * FrameRule
+     */
+    final class FrameRule extends Rule {
+
+        @Override
+        public void begin(final String name, final Attributes attrs) {
+            HashMap<String, Object> typeLists = new HashMap<String, Object>();
+            typeLists.put("local", new ArrayList<Object>());
+            typeLists.put("stack", new ArrayList<Object>());
+            push(attrs.getValue("type"));
+            push(attrs.getValue("count") == null ? "0" : attrs
+                    .getValue("count"));
+            push(typeLists);
+        }
+
+        @Override
+        public void end(final String name) {
+            HashMap<?, ?> typeLists = (HashMap<?, ?>) pop();
+            ArrayList<?> locals = (ArrayList<?>) typeLists.get("local");
+            int nLocal = locals.size();
+            Object[] local = locals.toArray();
+            ArrayList<?> stacks = (ArrayList<?>) typeLists.get("stack");
+            int nStack = stacks.size();
+            Object[] stack = stacks.toArray();
+            String count = (String) pop();
+            String type = (String) pop();
+            if ("NEW".equals(type)) {
+                getCodeVisitor()
+                        .visitFrame(F_NEW, nLocal, local, nStack, stack);
+            } else if ("FULL".equals(type)) {
+                getCodeVisitor().visitFrame(F_FULL, nLocal, local, nStack,
+                        stack);
+            } else if ("APPEND".equals(type)) {
+                getCodeVisitor().visitFrame(F_APPEND, nLocal, local, 0, null);
+            } else if ("CHOP".equals(type)) {
+                getCodeVisitor().visitFrame(F_CHOP, Integer.parseInt(count),
+                        null, 0, null);
+            } else if ("SAME".equals(type)) {
+                getCodeVisitor().visitFrame(F_SAME, 0, null, 0, null);
+            } else if ("SAME1".equals(type)) {
+                getCodeVisitor().visitFrame(F_SAME1, 0, null, nStack, stack);
+            }
+        }
+    }
+
+    final class FrameTypeRule extends Rule {
+
+        @Override
+        public void begin(final String name, final Attributes attrs) {
+            ArrayList<Object> types = (ArrayList<Object>) ((HashMap<?, ?>) peek())
+                    .get(name);
+            String type = attrs.getValue("type");
+            if ("uninitialized".equals(type)) {
+                types.add(getLabel(attrs.getValue("label")));
+            } else {
+                Integer t = TYPES.get(type);
+                if (t == null) {
+                    types.add(type);
+                } else {
+                    types.add(t);
+                }
+            }
+        }
+    }
+
+    /**
+     * LabelRule
+     */
+    final class LabelRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            getCodeVisitor().visitLabel(getLabel(attrs.getValue("name")));
+        }
+    }
+
+    /**
+     * TryCatchRule
+     */
+    final class TryCatchRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            Label start = getLabel(attrs.getValue("start"));
+            Label end = getLabel(attrs.getValue("end"));
+            Label handler = getLabel(attrs.getValue("handler"));
+            String type = attrs.getValue("type");
+            getCodeVisitor().visitTryCatchBlock(start, end, handler, type);
+        }
+    }
+
+    /**
+     * LineNumberRule
+     */
+    final class LineNumberRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            int line = Integer.parseInt(attrs.getValue("line"));
+            Label start = getLabel(attrs.getValue("start"));
+            getCodeVisitor().visitLineNumber(line, start);
+        }
+    }
+
+    /**
+     * LocalVarRule
+     */
+    final class LocalVarRule extends Rule {
+
+        @Override
+        public final void begin(final String element, final Attributes attrs) {
+            String name = attrs.getValue("name");
+            String desc = attrs.getValue("desc");
+            String signature = attrs.getValue("signature");
+            Label start = getLabel(attrs.getValue("start"));
+            Label end = getLabel(attrs.getValue("end"));
+            int var = Integer.parseInt(attrs.getValue("var"));
+            getCodeVisitor().visitLocalVariable(name, desc, signature, start,
+                    end, var);
+        }
+    }
+
+    /**
+     * InvokeDynamicRule
+     */
+    final class InvokeDynamicRule extends Rule {
+        @Override
+        public final void begin(final String element, final Attributes attrs)
+                throws SAXException {
+            push(attrs.getValue("name"));
+            push(attrs.getValue("desc"));
+            push(decodeHandle(attrs.getValue("bsm")));
+            push(new ArrayList<Object>());
+        }
+
+        @Override
+        public final void end(final String element) {
+            ArrayList<?> bsmArgs = (ArrayList<?>) pop();
+            Handle bsm = (Handle) pop();
+            String desc = (String) pop();
+            String name = (String) pop();
+            getCodeVisitor().visitInvokeDynamicInsn(name, desc, bsm,
+                    bsmArgs.toArray());
+        }
+    }
+
+    /**
+     * InvokeDynamicBsmArgumentsRule
+     */
+    final class InvokeDynamicBsmArgumentsRule extends Rule {
+        @Override
+        public final void begin(final String element, final Attributes attrs)
+                throws SAXException {
+            ArrayList<Object> bsmArgs = (ArrayList<Object>) peek();
+            bsmArgs.add(getValue(attrs.getValue("desc"), attrs.getValue("cst")));
+        }
+    }
+
+    /**
+     * OpcodesRule
+     */
+    final class OpcodesRule extends Rule {
+
+        // public boolean match( String match, String element) {
+        // return match.startsWith( path) && OPCODES.containsKey( element);
+        // }
+
+        @Override
+        public final void begin(final String element, final Attributes attrs)
+                throws SAXException {
+            Opcode o = OPCODES.get(element);
+            if (o == null) {
+                throw new SAXException("Invalid element: " + element + " at "
+                        + match);
+            }
+
+            switch (o.type) {
+            case OpcodeGroup.INSN:
+                getCodeVisitor().visitInsn(o.opcode);
+                break;
+
+            case OpcodeGroup.INSN_FIELD:
+                getCodeVisitor().visitFieldInsn(o.opcode,
+                        attrs.getValue("owner"), attrs.getValue("name"),
+                        attrs.getValue("desc"));
+                break;
+
+            case OpcodeGroup.INSN_INT:
+                getCodeVisitor().visitIntInsn(o.opcode,
+                        Integer.parseInt(attrs.getValue("value")));
+                break;
+
+            case OpcodeGroup.INSN_JUMP:
+                getCodeVisitor().visitJumpInsn(o.opcode,
+                        getLabel(attrs.getValue("label")));
+                break;
+
+            case OpcodeGroup.INSN_METHOD:
+                getCodeVisitor().visitMethodInsn(o.opcode,
+                        attrs.getValue("owner"), attrs.getValue("name"),
+                        attrs.getValue("desc"),
+                        attrs.getValue("itf").equals("true"));
+                break;
+
+            case OpcodeGroup.INSN_TYPE:
+                getCodeVisitor()
+                        .visitTypeInsn(o.opcode, attrs.getValue("desc"));
+                break;
+
+            case OpcodeGroup.INSN_VAR:
+                getCodeVisitor().visitVarInsn(o.opcode,
+                        Integer.parseInt(attrs.getValue("var")));
+                break;
+
+            case OpcodeGroup.INSN_IINC:
+                getCodeVisitor().visitIincInsn(
+                        Integer.parseInt(attrs.getValue("var")),
+                        Integer.parseInt(attrs.getValue("inc")));
+                break;
+
+            case OpcodeGroup.INSN_LDC:
+                getCodeVisitor()
+                        .visitLdcInsn(
+                                getValue(attrs.getValue("desc"),
+                                        attrs.getValue("cst")));
+                break;
+
+            case OpcodeGroup.INSN_MULTIANEWARRAY:
+                getCodeVisitor().visitMultiANewArrayInsn(
+                        attrs.getValue("desc"),
+                        Integer.parseInt(attrs.getValue("dims")));
+                break;
+
+            default:
+                throw new Error("Internal error");
+
+            }
+        }
+    }
+
+    /**
+     * MaxRule
+     */
+    final class MaxRule extends Rule {
+
+        @Override
+        public final void begin(final String element, final Attributes attrs) {
+            int maxStack = Integer.parseInt(attrs.getValue("maxStack"));
+            int maxLocals = Integer.parseInt(attrs.getValue("maxLocals"));
+            getCodeVisitor().visitMaxs(maxStack, maxLocals);
+        }
+    }
+
+    final class AnnotationRule extends Rule {
+
+        @Override
+        public void begin(final String name, final Attributes attrs) {
+            String desc = attrs.getValue("desc");
+            boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+                    .booleanValue();
+
+            Object v = peek();
+            if (v instanceof ClassVisitor) {
+                push(((ClassVisitor) v).visitAnnotation(desc, visible));
+            } else if (v instanceof FieldVisitor) {
+                push(((FieldVisitor) v).visitAnnotation(desc, visible));
+            } else if (v instanceof MethodVisitor) {
+                push(((MethodVisitor) v).visitAnnotation(desc, visible));
+            }
+        }
+
+        @Override
+        public void end(final String name) {
+            AnnotationVisitor av = (AnnotationVisitor) pop();
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+    }
+
+    final class TypeAnnotationRule extends Rule {
+
+        @Override
+        public void begin(final String name, final Attributes attrs) {
+            String desc = attrs.getValue("desc");
+            boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+                    .booleanValue();
+            int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
+            TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
+
+            Object v = peek();
+            if (v instanceof ClassVisitor) {
+                push(((ClassVisitor) v).visitTypeAnnotation(typeRef, typePath,
+                        desc, visible));
+            } else if (v instanceof FieldVisitor) {
+                push(((FieldVisitor) v).visitTypeAnnotation(typeRef, typePath,
+                        desc, visible));
+            } else if (v instanceof MethodVisitor) {
+                push(((MethodVisitor) v).visitTypeAnnotation(typeRef, typePath,
+                        desc, visible));
+            }
+        }
+
+        @Override
+        public void end(final String name) {
+            AnnotationVisitor av = (AnnotationVisitor) pop();
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+    }
+
+    final class AnnotationParameterRule extends Rule {
+
+        @Override
+        public void begin(final String name, final Attributes attrs) {
+            int parameter = Integer.parseInt(attrs.getValue("parameter"));
+            String desc = attrs.getValue("desc");
+            boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+                    .booleanValue();
+
+            push(((MethodVisitor) peek()).visitParameterAnnotation(parameter,
+                    desc, visible));
+        }
+
+        @Override
+        public void end(final String name) {
+            AnnotationVisitor av = (AnnotationVisitor) pop();
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+    }
+
+    final class InsnAnnotationRule extends Rule {
+
+        @Override
+        public void begin(final String name, final Attributes attrs) {
+            String desc = attrs.getValue("desc");
+            boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+                    .booleanValue();
+            int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
+            TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
+            push(((MethodVisitor) peek()).visitInsnAnnotation(typeRef,
+                    typePath, desc, visible));
+        }
+
+        @Override
+        public void end(final String name) {
+            AnnotationVisitor av = (AnnotationVisitor) pop();
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+    }
+
+    final class TryCatchAnnotationRule extends Rule {
+
+        @Override
+        public void begin(final String name, final Attributes attrs) {
+            String desc = attrs.getValue("desc");
+            boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+                    .booleanValue();
+            int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
+            TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
+            push(((MethodVisitor) peek()).visitTryCatchAnnotation(typeRef,
+                    typePath, desc, visible));
+        }
+
+        @Override
+        public void end(final String name) {
+            AnnotationVisitor av = (AnnotationVisitor) pop();
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+    }
+
+    final class LocalVariableAnnotationRule extends Rule {
+
+        @Override
+        public void begin(final String name, final Attributes attrs) {
+            String desc = attrs.getValue("desc");
+            boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+                    .booleanValue();
+            int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
+            TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
+            String[] s = attrs.getValue("start").split(" ");
+            Label[] start = new Label[s.length];
+            for (int i = 0; i < start.length; ++i) {
+                start[i] = getLabel(s[i]);
+            }
+            String[] e = attrs.getValue("end").split(" ");
+            Label[] end = new Label[e.length];
+            for (int i = 0; i < end.length; ++i) {
+                end[i] = getLabel(e[i]);
+            }
+            String[] v = attrs.getValue("index").split(" ");
+            int[] index = new int[v.length];
+            for (int i = 0; i < index.length; ++i) {
+                index[i] = Integer.parseInt(v[i]);
+            }
+            push(((MethodVisitor) peek()).visitLocalVariableAnnotation(typeRef,
+                    typePath, start, end, index, desc, visible));
+        }
+
+        @Override
+        public void end(final String name) {
+            AnnotationVisitor av = (AnnotationVisitor) pop();
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+    }
+
+    final class AnnotationValueRule extends Rule {
+
+        @Override
+        public void begin(final String nm, final Attributes attrs)
+                throws SAXException {
+            AnnotationVisitor av = (AnnotationVisitor) peek();
+            if (av != null) {
+                av.visit(
+                        attrs.getValue("name"),
+                        getValue(attrs.getValue("desc"),
+                                attrs.getValue("value")));
+            }
+        }
+    }
+
+    final class AnnotationValueEnumRule extends Rule {
+
+        @Override
+        public void begin(final String nm, final Attributes attrs) {
+            AnnotationVisitor av = (AnnotationVisitor) peek();
+            if (av != null) {
+                av.visitEnum(attrs.getValue("name"), attrs.getValue("desc"),
+                        attrs.getValue("value"));
+            }
+        }
+    }
+
+    final class AnnotationValueAnnotationRule extends Rule {
+
+        @Override
+        public void begin(final String nm, final Attributes attrs) {
+            AnnotationVisitor av = (AnnotationVisitor) peek();
+            push(av == null ? null : av.visitAnnotation(attrs.getValue("name"),
+                    attrs.getValue("desc")));
+        }
+
+        @Override
+        public void end(final String name) {
+            AnnotationVisitor av = (AnnotationVisitor) pop();
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+    }
+
+    final class AnnotationValueArrayRule extends Rule {
+
+        @Override
+        public void begin(final String nm, final Attributes attrs) {
+            AnnotationVisitor av = (AnnotationVisitor) peek();
+            push(av == null ? null : av.visitArray(attrs.getValue("name")));
+        }
+
+        @Override
+        public void end(final String name) {
+            AnnotationVisitor av = (AnnotationVisitor) pop();
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+    }
+
+    final class AnnotationDefaultRule extends Rule {
+
+        @Override
+        public void begin(final String nm, final Attributes attrs) {
+            MethodVisitor av = (MethodVisitor) peek();
+            push(av == null ? null : av.visitAnnotationDefault());
+        }
+
+        @Override
+        public void end(final String name) {
+            AnnotationVisitor av = (AnnotationVisitor) pop();
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+    }
+
+    /**
+     * Opcode
+     */
+    static final class Opcode {
+
+        public final int opcode;
+
+        public final int type;
+
+        Opcode(final int opcode, final int type) {
+            this.opcode = opcode;
+            this.type = type;
+        }
+    }
+}


[11/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-frames.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-frames.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-frames.properties
new file mode 100644
index 0000000..ecf580f
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-frames.properties
@@ -0,0 +1,62 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+org/objectweb/asm/Frame/remove=true
+
+# field mappings
+
+org/objectweb/asm/ClassWriter.typeCount=-
+org/objectweb/asm/ClassWriter.typeTable=-
+
+org/objectweb/asm/Label.frame=-
+
+org/objectweb/asm/MethodWriter.frameCount=-
+org/objectweb/asm/MethodWriter.stackMap=-
+org/objectweb/asm/MethodWriter.previousFrameOffset=-
+org/objectweb/asm/MethodWriter.previousFrame=-
+org/objectweb/asm/MethodWriter.frameIndex=-
+org/objectweb/asm/MethodWriter.frame=-
+
+# method mappings
+
+org/objectweb/asm/ClassReader.readFrameType([Ljava/lang/Object;II[C[Lorg/objectweb/asm/Label;)I=-
+
+org/objectweb/asm/ClassWriter.addType(Ljava/lang/String;)I=-
+org/objectweb/asm/ClassWriter.addUninitializedType(Ljava/lang/String;I)I=-
+org/objectweb/asm/ClassWriter.addType(Lorg/objectweb/asm/Item;)Lorg/objectweb/asm/Item;=-
+org/objectweb/asm/ClassWriter.getMergedType(II)I=-
+
+org/objectweb/asm/MethodWriter.startFrame(III)V=-
+org/objectweb/asm/MethodWriter.endFrame()V=-
+org/objectweb/asm/MethodWriter.writeFrame()V=-
+org/objectweb/asm/MethodWriter.writeFrameTypes(II)V=-
+org/objectweb/asm/MethodWriter.writeFrameType(Ljava/lang/Object;)V=-

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-resize.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-resize.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-resize.properties
new file mode 100644
index 0000000..97f7e34
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-resize.properties
@@ -0,0 +1,37 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+# field mappings
+
+# method mappings
+
+org/objectweb/asm/MethodWriter.resizeInstructions()V=-
\ 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/optimizer/shrink-signatures.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-signatures.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-signatures.properties
new file mode 100644
index 0000000..6a48623
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-signatures.properties
@@ -0,0 +1,43 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+org/objectweb/asm/signature/SignatureReader/remove=true
+org/objectweb/asm/signature/SignatureVisitor/remove=true
+org/objectweb/asm/signature/SignatureWriter/remove=true
+
+# field mappings
+
+org/objectweb/asm/ClassWriter.signature=-
+
+org/objectweb/asm/FieldWriter.signature=-
+
+org/objectweb/asm/MethodWriter.signature=-

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-writer.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-writer.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-writer.properties
new file mode 100644
index 0000000..1c83ca2
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-writer.properties
@@ -0,0 +1,66 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+org/objectweb/asm/AnnotationWriter/remove=true
+org/objectweb/asm/ByteVector/remove=true
+org/objectweb/asm/ClassWriter/remove=true
+org/objectweb/asm/Edge/remove=true
+org/objectweb/asm/FieldWriter/remove=true
+org/objectweb/asm/Frame/remove=true
+org/objectweb/asm/Handler/remove=true
+org/objectweb/asm/Item/remove=true
+org/objectweb/asm/MethodWriter/remove=true
+
+# field mappings
+
+org/objectweb/asm/Label.position=-
+org/objectweb/asm/Label.referenceCount=-
+org/objectweb/asm/Label.srcAndRefPositions=-
+org/objectweb/asm/Label.inputStackTop=-
+org/objectweb/asm/Label.outputStackMax=-
+org/objectweb/asm/Label.frame=-
+org/objectweb/asm/Label.successor=-
+org/objectweb/asm/Label.successors=-
+org/objectweb/asm/Label.next=-
+
+# method mappings
+
+org/objectweb/asm/ClassReader.copyPool(Lorg/objectweb/asm/ClassWriter;)V=-
+
+org/objectweb/asm/Label.addReference(II)V=-
+org/objectweb/asm/Label.put(Lorg/objectweb/asm/MethodWriter;Lorg/objectweb/asm/ByteVector;IZ)V=-
+org/objectweb/asm/Label.resolve(Lorg/objectweb/asm/MethodWriter;I[B)Z=-
+org/objectweb/asm/Label.getFirst()Lorg/objectweb/asm/Label;=-
+org/objectweb/asm/Label.inSubroutine(J)Z=-
+org/objectweb/asm/Label.inSameSubroutine(Lorg/objectweb/asm/Label;)Z=-
+org/objectweb/asm/Label.addToSubroutine(JI)V=-
+org/objectweb/asm/Label.visitSubroutine(Lorg/objectweb/asm/Label;JI)V=-

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink.properties
new file mode 100644
index 0000000..6b2a41f
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink.properties
@@ -0,0 +1,380 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+#org/objectweb/asm/Edge=org/objectweb/asm/a
+#org/objectweb/asm/Item=org/objectweb/asm/b
+#org/objectweb/asm/FieldWriter=org/objectweb/asm/c
+#org/objectweb/asm/MethodWriter=org/objectweb/asm/d
+#org/objectweb/asm/AnnotationWriter=org/objectweb/asm/e
+#org/objectweb/asm/Context=org/objectweb/asm/f
+
+java/lang/StringBuilder=java/lang/StringBuffer
+
+
+# field mappings
+
+org/objectweb/asm/AnnotationWriter.cw=a
+org/objectweb/asm/AnnotationWriter.size=b
+org/objectweb/asm/AnnotationWriter.named=c
+org/objectweb/asm/AnnotationWriter.bv=d
+org/objectweb/asm/AnnotationWriter.parent=e
+org/objectweb/asm/AnnotationWriter.offset=f
+org/objectweb/asm/AnnotationWriter.next=g
+org/objectweb/asm/AnnotationWriter.prev=h
+
+org/objectweb/asm/Attribute.next=a
+org/objectweb/asm/Attribute.value=b
+
+org/objectweb/asm/ByteVector.data=a
+org/objectweb/asm/ByteVector.length=b
+
+org/objectweb/asm/ClassReader.items=a
+org/objectweb/asm/ClassReader.strings=c
+org/objectweb/asm/ClassReader.maxStringLength=d
+#org/objectweb/asm/ClassReader.header=e
+
+org/objectweb/asm/Context.attrs=a
+org/objectweb/asm/Context.flags=b
+org/objectweb/asm/Context.buffer=c
+org/objectweb/asm/Context.bootstrapMethods=d
+org/objectweb/asm/Context.access=e
+org/objectweb/asm/Context.name=f
+org/objectweb/asm/Context.desc=g
+org/objectweb/asm/Context.labels=h
+org/objectweb/asm/Context.typeRef=i
+org/objectweb/asm/Context.typePath=j
+org/objectweb/asm/Context.offset=k
+org/objectweb/asm/Context.start=l
+org/objectweb/asm/Context.end=m
+org/objectweb/asm/Context.index=n
+org/objectweb/asm/Context.offset=o
+org/objectweb/asm/Context.mode=p
+org/objectweb/asm/Context.localCount=q
+org/objectweb/asm/Context.localDiff=r
+org/objectweb/asm/Context.local=s
+org/objectweb/asm/Context.stackCount=t
+org/objectweb/asm/Context.stack=u
+
+org/objectweb/asm/ClassWriter.TYPE=a
+org/objectweb/asm/ClassWriter.version=b
+org/objectweb/asm/ClassWriter.index=c
+org/objectweb/asm/ClassWriter.pool=d
+org/objectweb/asm/ClassWriter.items=e
+org/objectweb/asm/ClassWriter.threshold=f
+org/objectweb/asm/ClassWriter.key=g
+org/objectweb/asm/ClassWriter.key2=h
+org/objectweb/asm/ClassWriter.key3=i
+org/objectweb/asm/ClassWriter.key4=j
+org/objectweb/asm/ClassWriter.access=k
+org/objectweb/asm/ClassWriter.name=l
+org/objectweb/asm/ClassWriter.signature=m
+org/objectweb/asm/ClassWriter.superName=n
+org/objectweb/asm/ClassWriter.interfaceCount=o
+org/objectweb/asm/ClassWriter.interfaces=p
+org/objectweb/asm/ClassWriter.sourceFile=q
+org/objectweb/asm/ClassWriter.sourceDebug=r
+org/objectweb/asm/ClassWriter.enclosingMethodOwner=s
+org/objectweb/asm/ClassWriter.enclosingMethod=t
+org/objectweb/asm/ClassWriter.anns=u
+org/objectweb/asm/ClassWriter.ianns=v
+org/objectweb/asm/ClassWriter.tanns=N
+org/objectweb/asm/ClassWriter.itanns=O
+org/objectweb/asm/ClassWriter.attrs=w
+org/objectweb/asm/ClassWriter.innerClassesCount=x
+org/objectweb/asm/ClassWriter.innerClasses=y
+org/objectweb/asm/ClassWriter.bootstrapMethodsCount=z
+org/objectweb/asm/ClassWriter.bootstrapMethods=A
+org/objectweb/asm/ClassWriter.firstField=B
+org/objectweb/asm/ClassWriter.lastField=C
+org/objectweb/asm/ClassWriter.firstMethod=D
+org/objectweb/asm/ClassWriter.lastMethod=E
+org/objectweb/asm/ClassWriter.computeMaxs=F
+org/objectweb/asm/ClassWriter.typeCount=G
+org/objectweb/asm/ClassWriter.typeTable=H
+org/objectweb/asm/ClassWriter.thisName=I
+org/objectweb/asm/ClassWriter.computeFrames=J
+org/objectweb/asm/ClassWriter.computeMaxs=K
+org/objectweb/asm/ClassWriter.invalidFrames=L
+org/objectweb/asm/ClassWriter.cr=M
+    
+org/objectweb/asm/Edge.info=a
+org/objectweb/asm/Edge.successor=b
+org/objectweb/asm/Edge.next=c
+
+org/objectweb/asm/Handler.start=a
+org/objectweb/asm/Handler.end=b
+org/objectweb/asm/Handler.handler=c
+org/objectweb/asm/Handler.desc=d
+org/objectweb/asm/Handler.type=e
+org/objectweb/asm/Handler.next=f
+
+org/objectweb/asm/FieldWriter.cw=b
+org/objectweb/asm/FieldWriter.access=c
+org/objectweb/asm/FieldWriter.name=d
+org/objectweb/asm/FieldWriter.desc=e
+org/objectweb/asm/FieldWriter.signature=f
+org/objectweb/asm/FieldWriter.value=g
+org/objectweb/asm/FieldWriter.anns=h
+org/objectweb/asm/FieldWriter.ianns=i
+org/objectweb/asm/FieldWriter.tanns=k
+org/objectweb/asm/FieldWriter.itanns=l
+org/objectweb/asm/FieldWriter.attrs=j
+
+org/objectweb/asm/Item.index=a
+org/objectweb/asm/Item.type=b
+org/objectweb/asm/Item.intVal=c
+org/objectweb/asm/Item.longVal=d
+org/objectweb/asm/Item.strVal1=g
+org/objectweb/asm/Item.strVal2=h
+org/objectweb/asm/Item.strVal3=i
+org/objectweb/asm/Item.hashCode=j
+org/objectweb/asm/Item.next=k
+
+org/objectweb/asm/Label.status=a
+org/objectweb/asm/Label.line=b
+org/objectweb/asm/Label.position=c
+org/objectweb/asm/Label.referenceCount=d
+org/objectweb/asm/Label.srcAndRefPositions=e
+org/objectweb/asm/Label.inputStackTop=f
+org/objectweb/asm/Label.outputStackMax=g
+org/objectweb/asm/Label.frame=h
+org/objectweb/asm/Label.successor=i
+org/objectweb/asm/Label.successors=j
+org/objectweb/asm/Label.next=k
+
+org/objectweb/asm/Frame.SIZE=a
+org/objectweb/asm/Frame.owner=b
+org/objectweb/asm/Frame.inputLocals=c
+org/objectweb/asm/Frame.inputStack=d
+org/objectweb/asm/Frame.outputLocals=e
+org/objectweb/asm/Frame.outputStack=f
+org/objectweb/asm/Frame.outputStackTop=g
+org/objectweb/asm/Frame.initializationCount=h
+org/objectweb/asm/Frame.initializations=i
+
+org/objectweb/asm/MethodWriter.cw=b
+org/objectweb/asm/MethodWriter.access=c
+org/objectweb/asm/MethodWriter.name=d
+org/objectweb/asm/MethodWriter.desc=e
+org/objectweb/asm/MethodWriter.descriptor=f
+org/objectweb/asm/MethodWriter.signature=g
+org/objectweb/asm/MethodWriter.classReaderOffset=h
+org/objectweb/asm/MethodWriter.classReaderLength=i
+org/objectweb/asm/MethodWriter.exceptionCount=j
+org/objectweb/asm/MethodWriter.exceptions=k
+org/objectweb/asm/MethodWriter.annd=l
+org/objectweb/asm/MethodWriter.anns=m
+org/objectweb/asm/MethodWriter.ianns=n
+org/objectweb/asm/MethodWriter.tanns=U
+org/objectweb/asm/MethodWriter.itanns=V
+org/objectweb/asm/MethodWriter.panns=o
+org/objectweb/asm/MethodWriter.ipanns=p
+org/objectweb/asm/MethodWriter.attrs=q
+org/objectweb/asm/MethodWriter.code=r
+org/objectweb/asm/MethodWriter.maxStack=s
+org/objectweb/asm/MethodWriter.maxLocals=t
+org/objectweb/asm/MethodWriter.currentLocals=T
+org/objectweb/asm/MethodWriter.frameCount=u
+org/objectweb/asm/MethodWriter.stackMap=v
+org/objectweb/asm/MethodWriter.previousFrameOffset=w
+org/objectweb/asm/MethodWriter.previousFrame=x
+#org/objectweb/asm/MethodWriter.frameIndex=y
+org/objectweb/asm/MethodWriter.frame=z
+org/objectweb/asm/MethodWriter.handlerCount=A
+org/objectweb/asm/MethodWriter.firstHandler=B
+org/objectweb/asm/MethodWriter.lastHandler=C
+org/objectweb/asm/MethodWriter.methodParametersCount=Z
+org/objectweb/asm/MethodWriter.methodParameters=$
+org/objectweb/asm/MethodWriter.localVarCount=D
+org/objectweb/asm/MethodWriter.localVar=E
+org/objectweb/asm/MethodWriter.localVarTypeCount=F
+org/objectweb/asm/MethodWriter.localVarType=G
+org/objectweb/asm/MethodWriter.lineNumberCount=H
+org/objectweb/asm/MethodWriter.lineNumber=I
+org/objectweb/asm/MethodWriter.lastCodeOffset=Y
+org/objectweb/asm/MethodWriter.ctanns=W
+org/objectweb/asm/MethodWriter.ictanns=X
+org/objectweb/asm/MethodWriter.cattrs=J
+org/objectweb/asm/MethodWriter.resize=K
+org/objectweb/asm/MethodWriter.subroutines=L
+org/objectweb/asm/MethodWriter.compute=M
+org/objectweb/asm/MethodWriter.labels=N
+org/objectweb/asm/MethodWriter.previousBlock=O
+org/objectweb/asm/MethodWriter.currentBlock=P
+org/objectweb/asm/MethodWriter.stackSize=Q
+org/objectweb/asm/MethodWriter.maxStackSize=R
+org/objectweb/asm/MethodWriter.synthetics=S
+
+org/objectweb/asm/Type.sort=a
+org/objectweb/asm/Type.buf=b
+org/objectweb/asm/Type.off=c
+org/objectweb/asm/Type.len=d
+
+org/objectweb/asm/TypeReference.value=a
+
+org/objectweb/asm/TypePath.b=a
+org/objectweb/asm/TypePath.offset=b
+
+org/objectweb/asm/Handle.tag=a
+org/objectweb/asm/Handle.owner=b
+org/objectweb/asm/Handle.name=c
+org/objectweb/asm/Handle.desc=d
+
+org/objectweb/asm/signature/SignatureReader.signature=a
+
+org/objectweb/asm/signature/SignatureWriter.buf=a
+org/objectweb/asm/signature/SignatureWriter.hasFormals=b
+org/objectweb/asm/signature/SignatureWriter.hasParameters=c
+org/objectweb/asm/signature/SignatureWriter.argumentStack=d
+
+# method mappings
+
+org/objectweb/asm/AnnotationWriter.getSize()I=a
+org/objectweb/asm/AnnotationWriter.put([Lorg/objectweb/asm/AnnotationWriter;ILorg/objectweb/asm/ByteVector;)V=a
+org/objectweb/asm/AnnotationWriter.put(Lorg/objectweb/asm/ByteVector;)V=a
+org/objectweb/asm/AnnotationWriter.putTarget(ILorg/objectweb/asm/TypePath;Lorg/objectweb/asm/ByteVector;)V=a
+
+org/objectweb/asm/Attribute.getCount()I=a
+org/objectweb/asm/Attribute.getSize(Lorg/objectweb/asm/ClassWriter;[BIII)I=a
+org/objectweb/asm/Attribute.put(Lorg/objectweb/asm/ClassWriter;[BIIILorg/objectweb/asm/ByteVector;)V=a
+
+org/objectweb/asm/ByteVector.enlarge(I)V=a
+org/objectweb/asm/ByteVector.put11(II)Lorg/objectweb/asm/ByteVector;=a
+org/objectweb/asm/ByteVector.put12(II)Lorg/objectweb/asm/ByteVector;=b
+
+org/objectweb/asm/ClassReader.copyPool(Lorg/objectweb/asm/ClassWriter;)V=a
+org/objectweb/asm/ClassReader.copyBootstrapMethods(Lorg/objectweb/asm/ClassWriter;[Lorg/objectweb/asm/Item;[C)V=a
+org/objectweb/asm/ClassReader.readField(Lorg/objectweb/asm/ClassVisitor;Lorg/objectweb/asm/Context;I)I=a
+org/objectweb/asm/ClassReader.readMethod(Lorg/objectweb/asm/ClassVisitor;Lorg/objectweb/asm/Context;I)I=b
+org/objectweb/asm/ClassReader.readCode(Lorg/objectweb/asm/MethodVisitor;Lorg/objectweb/asm/Context;I)V=a
+org/objectweb/asm/ClassReader.readTypeAnnotations(Lorg/objectweb/asm/MethodVisitor;Lorg/objectweb/asm/Context;IZ)[I=a
+org/objectweb/asm/ClassReader.readAnnotationTarget(Lorg/objectweb/asm/Context;I)I=a
+org/objectweb/asm/ClassReader.readAnnotationValues(I[CZLorg/objectweb/asm/AnnotationVisitor;)I=a
+org/objectweb/asm/ClassReader.readAnnotationValue(I[CLjava/lang/String;Lorg/objectweb/asm/AnnotationVisitor;)I=a
+org/objectweb/asm/ClassReader.getAttributes()I=a
+org/objectweb/asm/ClassReader.readAttribute([Lorg/objectweb/asm/Attribute;Ljava/lang/String;II[CI[Lorg/objectweb/asm/Label;)Lorg/objectweb/asm/Attribute;=a
+org/objectweb/asm/ClassReader.readClass(Ljava/io/InputStream;Z)[B=a
+org/objectweb/asm/ClassReader.readParameterAnnotations(Lorg/objectweb/asm/MethodVisitor;Lorg/objectweb/asm/Context;IZ)V=b
+org/objectweb/asm/ClassReader.readUTF(II[C)Ljava/lang/String;=a
+org/objectweb/asm/ClassReader.getImplicitFrame(Lorg/objectweb/asm/Context;)V=a
+org/objectweb/asm/ClassReader.readFrame(IZZLorg/objectweb/asm/Context;)I=a
+org/objectweb/asm/ClassReader.readFrameType([Ljava/lang/Object;II[C[Lorg/objectweb/asm/Label;)I=a
+
+org/objectweb/asm/ClassWriter.get(Lorg/objectweb/asm/Item;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newClassItem(Ljava/lang/String;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newConstItem(Ljava/lang/Object;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newDouble(D)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newFloat(F)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newInteger(I)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newLong(J)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newMethodItem(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newString(Ljava/lang/String;)Lorg/objectweb/asm/Item;=b
+org/objectweb/asm/ClassWriter.put122(III)V=a
+org/objectweb/asm/ClassWriter.put112(III)V=b
+org/objectweb/asm/ClassWriter.put(Lorg/objectweb/asm/Item;)V=b
+org/objectweb/asm/ClassWriter.newFieldItem(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.addType(Ljava/lang/String;)I=c
+org/objectweb/asm/ClassWriter.addUninitializedType(Ljava/lang/String;I)I=a
+org/objectweb/asm/ClassWriter.addType(Lorg/objectweb/asm/Item;)Lorg/objectweb/asm/Item;=c
+org/objectweb/asm/ClassWriter.getMergedType(II)I=a
+org/objectweb/asm/ClassWriter.newNameTypeItem(Ljava/lang/String;Ljava/lang/String;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newMethodTypeItem(Ljava/lang/String;)Lorg/objectweb/asm/Item;=c
+org/objectweb/asm/ClassWriter.newHandleItem(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newInvokeDynamicItem(Ljava/lang/String;Ljava/lang/String;Lorg/objectweb/asm/Handle;[Ljava/lang/Object;)Lorg/objectweb/asm/Item;=a
+
+org/objectweb/asm/FieldWriter.getSize()I=a
+org/objectweb/asm/FieldWriter.put(Lorg/objectweb/asm/ByteVector;)V=a
+
+org/objectweb/asm/Item.isEqualTo(Lorg/objectweb/asm/Item;)Z=a
+org/objectweb/asm/Item.set(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V=a
+org/objectweb/asm/Item.set(D)V=a
+org/objectweb/asm/Item.set(F)V=a
+org/objectweb/asm/Item.set(I)V=a
+org/objectweb/asm/Item.set(J)V=a
+org/objectweb/asm/Item.set(Ljava/lang/String;Ljava/lang/String;I)V=a
+org/objectweb/asm/Item.set(II)V=a
+
+org/objectweb/asm/Label.addReference(II)V=a
+org/objectweb/asm/Label.put(Lorg/objectweb/asm/MethodWriter;Lorg/objectweb/asm/ByteVector;IZ)V=a
+org/objectweb/asm/Label.resolve(Lorg/objectweb/asm/MethodWriter;I[B)Z=a
+org/objectweb/asm/Label.getFirst()Lorg/objectweb/asm/Label;=a
+org/objectweb/asm/Label.inSubroutine(J)Z=a
+org/objectweb/asm/Label.inSameSubroutine(Lorg/objectweb/asm/Label;)Z=a
+org/objectweb/asm/Label.addToSubroutine(JI)V=a
+org/objectweb/asm/Label.visitSubroutine(Lorg/objectweb/asm/Label;JI)V=b
+
+org/objectweb/asm/Frame.get(I)I=a
+org/objectweb/asm/Frame.set(II)V=a
+org/objectweb/asm/Frame.push(I)V=b
+org/objectweb/asm/Frame.push(Lorg/objectweb/asm/ClassWriter;Ljava/lang/String;)V=a
+org/objectweb/asm/Frame.type(Lorg/objectweb/asm/ClassWriter;Ljava/lang/String;)I=b
+org/objectweb/asm/Frame.pop()I=a
+org/objectweb/asm/Frame.pop(Ljava/lang/String;)V=a
+org/objectweb/asm/Frame.pop(I)V=c
+org/objectweb/asm/Frame.init(I)V=d
+org/objectweb/asm/Frame.init(Lorg/objectweb/asm/ClassWriter;I)I=a
+org/objectweb/asm/Frame.initInputFrame(Lorg/objectweb/asm/ClassWriter;I[Lorg/objectweb/asm/Type;I)V=a
+org/objectweb/asm/Frame.execute(IILorg/objectweb/asm/ClassWriter;Lorg/objectweb/asm/Item;)V=a
+org/objectweb/asm/Frame.merge(Lorg/objectweb/asm/ClassWriter;Lorg/objectweb/asm/Frame;I)Z=a
+org/objectweb/asm/Frame.merge(Lorg/objectweb/asm/ClassWriter;I[II)Z=a
+
+org/objectweb/asm/Handler.remove(Lorg/objectweb/asm/Handler;Lorg/objectweb/asm/Label;Lorg/objectweb/asm/Label;)Lorg/objectweb/asm/Handler;=a
+
+org/objectweb/asm/MethodWriter.visitSwitchInsn(Lorg/objectweb/asm/Label;[Lorg/objectweb/asm/Label;)V=a
+org/objectweb/asm/MethodWriter.addSuccessor(ILorg/objectweb/asm/Label;)V=a
+org/objectweb/asm/MethodWriter.getNewOffset([I[III)I=a
+org/objectweb/asm/MethodWriter.getSize()I=a
+org/objectweb/asm/MethodWriter.put(Lorg/objectweb/asm/ByteVector;)V=a
+org/objectweb/asm/MethodWriter.readInt([BI)I=a
+org/objectweb/asm/MethodWriter.readShort([BI)S=b
+org/objectweb/asm/MethodWriter.readUnsignedShort([BI)I=c
+org/objectweb/asm/MethodWriter.writeShort([BII)V=a
+org/objectweb/asm/MethodWriter.visitFrame(Lorg/objectweb/asm/Frame;)V=b
+org/objectweb/asm/MethodWriter.visitImplicitFirstFrame()V=f
+org/objectweb/asm/MethodWriter.startFrame(III)I=a
+org/objectweb/asm/MethodWriter.endFrame()V=b
+org/objectweb/asm/MethodWriter.writeFrame()V=c
+org/objectweb/asm/MethodWriter.resizeInstructions()V=d
+org/objectweb/asm/MethodWriter.noSuccessor()V=e
+org/objectweb/asm/MethodWriter.writeFrameTypes(II)V=a
+org/objectweb/asm/MethodWriter.writeFrameType(Ljava/lang/Object;)V=a
+org/objectweb/asm/MethodWriter.getNewOffset([I[ILorg/objectweb/asm/Label;)V=a
+
+org/objectweb/asm/Type.getType([CI)Lorg/objectweb/asm/Type;=a
+org/objectweb/asm/Type.getDescriptor(Ljava/lang/StringBuffer;)V=a
+org/objectweb/asm/Type.getDescriptor(Ljava/lang/StringBuffer;Ljava/lang/Class;)V=a
+
+org/objectweb/asm/signature/SignatureReader.parseType(Ljava/lang/String;ILorg/objectweb/asm/signature/SignatureVisitor;)I=a
+
+org/objectweb/asm/signature/SignatureWriter.endFormals()V=a
+org/objectweb/asm/signature/SignatureWriter.endArguments()V=b
+     
\ 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/signature/SignatureReader.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java
index b72fde6..b5b2c45 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java
@@ -32,7 +32,7 @@ package org.apache.tapestry5.internal.plastic.asm.signature;
 /**
  * A type signature parser to make a signature visitor visit an existing
  * signature.
- *
+ * 
  * @author Thomas Hallgren
  * @author Eric Bruneton
  */
@@ -45,9 +45,10 @@ public class SignatureReader {
 
     /**
      * Constructs a {@link SignatureReader} for the given signature.
-     *
-     * @param signature A <i>ClassSignature</i>, <i>MethodTypeSignature</i>,
-     *        or <i>FieldTypeSignature</i>.
+     * 
+     * @param signature
+     *            A <i>ClassSignature</i>, <i>MethodTypeSignature</i>, or
+     *            <i>FieldTypeSignature</i>.
      */
     public SignatureReader(final String signature) {
         this.signature = signature;
@@ -58,15 +59,15 @@ public class SignatureReader {
      * {@link SignatureReader}. This signature is the one specified in the
      * constructor (see {@link #SignatureReader(String) SignatureReader}). This
      * method is intended to be called on a {@link SignatureReader} that was
-     * created using a <i>ClassSignature</i> (such as the
+     * created using a <i>ClassSignature</i> (such as the <code>signature</code>
+     * parameter of the {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visit
+     * ClassVisitor.visit} method) or a <i>MethodTypeSignature</i> (such as the
      * <code>signature</code> parameter of the
-     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visit ClassVisitor.visit} method)
-     * or a <i>MethodTypeSignature</i> (such as the <code>signature</code>
-     * parameter of the
-     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitMethod ClassVisitor.visitMethod}
-     * method).
-     *
-     * @param v the visitor that must visit this signature.
+     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitMethod
+     * ClassVisitor.visitMethod} method).
+     * 
+     * @param v
+     *            the visitor that must visit this signature.
      */
     public void accept(final SignatureVisitor v) {
         String signature = this.signature;
@@ -118,12 +119,12 @@ public class SignatureReader {
      * method is intended to be called on a {@link SignatureReader} that was
      * created using a <i>FieldTypeSignature</i>, such as the
      * <code>signature</code> parameter of the
-     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitField
-     * ClassVisitor.visitField} or {@link
-     * org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLocalVariable
+     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitField ClassVisitor.visitField}
+     * or {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLocalVariable
      * MethodVisitor.visitLocalVariable} methods.
-     *
-     * @param v the visitor that must visit this signature.
+     * 
+     * @param v
+     *            the visitor that must visit this signature.
      */
     public void acceptType(final SignatureVisitor v) {
         parseType(this.signature, 0, v);
@@ -131,99 +132,97 @@ public class SignatureReader {
 
     /**
      * Parses a field type signature and makes the given visitor visit it.
-     *
-     * @param signature a string containing the signature that must be parsed.
-     * @param pos index of the first character of the signature to parsed.
-     * @param v the visitor that must visit this signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be parsed.
+     * @param pos
+     *            index of the first character of the signature to parsed.
+     * @param v
+     *            the visitor that must visit this signature.
      * @return the index of the first character after the parsed signature.
      */
-    private static int parseType(
-        final String signature,
-        int pos,
-        final SignatureVisitor v)
-    {
+    private static int parseType(final String signature, int pos,
+            final SignatureVisitor v) {
         char c;
         int start, end;
         boolean visited, inner;
         String name;
 
         switch (c = signature.charAt(pos++)) {
-            case 'Z':
-            case 'C':
-            case 'B':
-            case 'S':
-            case 'I':
-            case 'F':
-            case 'J':
-            case 'D':
-            case 'V':
-                v.visitBaseType(c);
-                return pos;
+        case 'Z':
+        case 'C':
+        case 'B':
+        case 'S':
+        case 'I':
+        case 'F':
+        case 'J':
+        case 'D':
+        case 'V':
+            v.visitBaseType(c);
+            return pos;
 
-            case '[':
-                return parseType(signature, pos, v.visitArrayType());
+        case '[':
+            return parseType(signature, pos, v.visitArrayType());
 
-            case 'T':
-                end = signature.indexOf(';', pos);
-                v.visitTypeVariable(signature.substring(pos, end));
-                return end + 1;
+        case 'T':
+            end = signature.indexOf(';', pos);
+            v.visitTypeVariable(signature.substring(pos, end));
+            return end + 1;
 
-            default: // case 'L':
-                start = pos;
-                visited = false;
-                inner = false;
-                for (;;) {
-                    switch (c = signature.charAt(pos++)) {
-                        case '.':
-                        case ';':
-                            if (!visited) {
-                                name = signature.substring(start, pos - 1);
-                                if (inner) {
-                                    v.visitInnerClassType(name);
-                                } else {
-                                    v.visitClassType(name);
-                                }
-                            }
-                            if (c == ';') {
-                                v.visitEnd();
-                                return pos;
-                            }
-                            start = pos;
-                            visited = false;
-                            inner = true;
-                            break;
+        default: // case 'L':
+            start = pos;
+            visited = false;
+            inner = false;
+            for (;;) {
+                switch (c = signature.charAt(pos++)) {
+                case '.':
+                case ';':
+                    if (!visited) {
+                        name = signature.substring(start, pos - 1);
+                        if (inner) {
+                            v.visitInnerClassType(name);
+                        } else {
+                            v.visitClassType(name);
+                        }
+                    }
+                    if (c == ';') {
+                        v.visitEnd();
+                        return pos;
+                    }
+                    start = pos;
+                    visited = false;
+                    inner = true;
+                    break;
 
-                        case '<':
-                            name = signature.substring(start, pos - 1);
-                            if (inner) {
-                                v.visitInnerClassType(name);
-                            } else {
-                                v.visitClassType(name);
-                            }
-                            visited = true;
-                            top: for (;;) {
-                                switch (c = signature.charAt(pos)) {
-                                    case '>':
-                                        break top;
-                                    case '*':
-                                        ++pos;
-                                        v.visitTypeArgument();
-                                        break;
-                                    case '+':
-                                    case '-':
-                                        pos = parseType(signature,
-                                                pos + 1,
-                                                v.visitTypeArgument(c));
-                                        break;
-                                    default:
-                                        pos = parseType(signature,
-                                                pos,
-                                                v.visitTypeArgument('='));
-                                        break;
-                                }
-                            }
+                case '<':
+                    name = signature.substring(start, pos - 1);
+                    if (inner) {
+                        v.visitInnerClassType(name);
+                    } else {
+                        v.visitClassType(name);
+                    }
+                    visited = true;
+                    top: for (;;) {
+                        switch (c = signature.charAt(pos)) {
+                        case '>':
+                            break top;
+                        case '*':
+                            ++pos;
+                            v.visitTypeArgument();
+                            break;
+                        case '+':
+                        case '-':
+                            pos = parseType(signature, pos + 1,
+                                    v.visitTypeArgument(c));
+                            break;
+                        default:
+                            pos = parseType(signature, pos,
+                                    v.visitTypeArgument('='));
+                            break;
+                        }
                     }
                 }
+            }
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
index 14e9ccb..941980f 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
@@ -35,22 +35,22 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
  * A visitor to visit a generic signature. The methods of this interface must be
  * called in one of the three following orders (the last one is the only valid
  * order for a {@link SignatureVisitor} that is returned by a method of this
- * interface): <ul> <li><i>ClassSignature</i> = (
- * <tt>visitFormalTypeParameter</tt>
- *   <tt>visitClassBound</tt>?
- * <tt>visitInterfaceBound</tt>* )* ( <tt>visitSuperClass</tt>
- *   <tt>visitInterface</tt>* )</li>
+ * interface):
+ * <ul>
+ * <li><i>ClassSignature</i> = ( <tt>visitFormalTypeParameter</tt>
+ * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* (
+ * <tt>visitSuperClass</tt> <tt>visitInterface</tt>* )</li>
  * <li><i>MethodSignature</i> = ( <tt>visitFormalTypeParameter</tt>
- *   <tt>visitClassBound</tt>?
- * <tt>visitInterfaceBound</tt>* )* ( <tt>visitParameterType</tt>*
- * <tt>visitReturnType</tt>
- *   <tt>visitExceptionType</tt>* )</li> <li><i>TypeSignature</i> =
- * <tt>visitBaseType</tt> | <tt>visitTypeVariable</tt> |
- * <tt>visitArrayType</tt> | (
+ * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* (
+ * <tt>visitParameterType</tt>* <tt>visitReturnType</tt>
+ * <tt>visitExceptionType</tt>* )</li>
+ * <li><i>TypeSignature</i> = <tt>visitBaseType</tt> |
+ * <tt>visitTypeVariable</tt> | <tt>visitArrayType</tt> | (
  * <tt>visitClassType</tt> <tt>visitTypeArgument</tt>* (
- * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )*
- * <tt>visitEnd</tt> ) )</li> </ul>
- *
+ * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )* <tt>visitEnd</tt>
+ * ) )</li>
+ * </ul>
+ * 
  * @author Thomas Hallgren
  * @author Eric Bruneton
  */
@@ -73,31 +73,36 @@ public abstract class SignatureVisitor {
 
     /**
      * The ASM API version implemented by this visitor. The value of this field
-     * must be one of {@link Opcodes#ASM4}.
+     * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
      */
     protected final int api;
 
     /**
      * Constructs a new {@link SignatureVisitor}.
-     *
-     * @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 SignatureVisitor(final int api) {
+        if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
+            throw new IllegalArgumentException();
+        }
         this.api = api;
     }
 
     /**
      * Visits a formal type parameter.
-     *
-     * @param name the name of the formal parameter.
+     * 
+     * @param name
+     *            the name of the formal parameter.
      */
     public void visitFormalTypeParameter(String name) {
     }
 
     /**
      * Visits the class bound of the last visited formal type parameter.
-     *
+     * 
      * @return a non null visitor to visit the signature of the class bound.
      */
     public SignatureVisitor visitClassBound() {
@@ -106,7 +111,7 @@ public abstract class SignatureVisitor {
 
     /**
      * Visits an interface bound of the last visited formal type parameter.
-     *
+     * 
      * @return a non null visitor to visit the signature of the interface bound.
      */
     public SignatureVisitor visitInterfaceBound() {
@@ -115,7 +120,7 @@ public abstract class SignatureVisitor {
 
     /**
      * Visits the type of the super class.
-     *
+     * 
      * @return a non null visitor to visit the signature of the super class
      *         type.
      */
@@ -125,7 +130,7 @@ public abstract class SignatureVisitor {
 
     /**
      * Visits the type of an interface implemented by the class.
-     *
+     * 
      * @return a non null visitor to visit the signature of the interface type.
      */
     public SignatureVisitor visitInterface() {
@@ -134,7 +139,7 @@ public abstract class SignatureVisitor {
 
     /**
      * Visits the type of a method parameter.
-     *
+     * 
      * @return a non null visitor to visit the signature of the parameter type.
      */
     public SignatureVisitor visitParameterType() {
@@ -143,7 +148,7 @@ public abstract class SignatureVisitor {
 
     /**
      * Visits the return type of the method.
-     *
+     * 
      * @return a non null visitor to visit the signature of the return type.
      */
     public SignatureVisitor visitReturnType() {
@@ -152,7 +157,7 @@ public abstract class SignatureVisitor {
 
     /**
      * Visits the type of a method exception.
-     *
+     * 
      * @return a non null visitor to visit the signature of the exception type.
      */
     public SignatureVisitor visitExceptionType() {
@@ -161,24 +166,26 @@ public abstract class SignatureVisitor {
 
     /**
      * Visits a signature corresponding to a primitive type.
-     *
-     * @param descriptor the descriptor of the primitive type, or 'V' for
-     *        <tt>void</tt>.
+     * 
+     * @param descriptor
+     *            the descriptor of the primitive type, or 'V' for <tt>void</tt>
+     *            .
      */
     public void visitBaseType(char descriptor) {
     }
 
     /**
      * Visits a signature corresponding to a type variable.
-     *
-     * @param name the name of the type variable.
+     * 
+     * @param name
+     *            the name of the type variable.
      */
     public void visitTypeVariable(String name) {
     }
 
     /**
      * Visits a signature corresponding to an array type.
-     *
+     * 
      * @return a non null visitor to visit the signature of the array element
      *         type.
      */
@@ -189,16 +196,18 @@ public abstract class SignatureVisitor {
     /**
      * Starts the visit of a signature corresponding to a class or interface
      * type.
-     *
-     * @param name the internal name of the class or interface.
+     * 
+     * @param name
+     *            the internal name of the class or interface.
      */
     public void visitClassType(String name) {
     }
 
     /**
      * Visits an inner class.
-     *
-     * @param name the local name of the inner class in its enclosing class.
+     * 
+     * @param name
+     *            the local name of the inner class in its enclosing class.
      */
     public void visitInnerClassType(String name) {
     }
@@ -212,8 +221,9 @@ public abstract class SignatureVisitor {
 
     /**
      * Visits a type argument of the last visited class or inner class type.
-     *
-     * @param wildcard '+', '-' or '='.
+     * 
+     * @param wildcard
+     *            '+', '-' or '='.
      * @return a non null visitor to visit the signature of the type argument.
      */
     public SignatureVisitor visitTypeArgument(char wildcard) {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
index 841fdad..d1e6bac 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
@@ -33,7 +33,7 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
 
 /**
  * A signature visitor that generates signatures in string format.
- *
+ * 
  * @author Thomas Hallgren
  * @author Eric Bruneton
  */
@@ -66,7 +66,7 @@ public class SignatureWriter extends SignatureVisitor {
      * Constructs a new {@link SignatureWriter} object.
      */
     public SignatureWriter() {
-        super(Opcodes.ASM4);
+        super(Opcodes.ASM5);
     }
 
     // ------------------------------------------------------------------------
@@ -193,7 +193,7 @@ public class SignatureWriter extends SignatureVisitor {
 
     /**
      * Returns the signature that was built by this signature writer.
-     *
+     * 
      * @return the signature that was built by this signature writer.
      */
     @Override

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
index 32dc008..a6a01d6 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
@@ -29,15 +29,16 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
 /**
  * A node that represents a bytecode instruction. <i>An instruction can appear
  * at most once in at most one {@link InsnList} at a time</i>.
- *
+ * 
  * @author Eric Bruneton
  */
 public abstract class AbstractInsnNode {
@@ -128,6 +129,28 @@ public abstract class AbstractInsnNode {
     protected int opcode;
 
     /**
+     * The runtime visible type annotations of this instruction. This field is
+     * only used for real instructions (i.e. not for labels, frames, or line
+     * number nodes). 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 instruction. This field is
+     * only used for real instructions (i.e. not for labels, frames, or line
+     * number nodes). 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;
+
+    /**
      * Previous instruction in the list to which this instruction belongs.
      */
     AbstractInsnNode prev;
@@ -147,8 +170,9 @@ public abstract class AbstractInsnNode {
 
     /**
      * Constructs a new {@link AbstractInsnNode}.
-     *
-     * @param opcode the opcode of the instruction to be constructed.
+     * 
+     * @param opcode
+     *            the opcode of the instruction to be constructed.
      */
     protected AbstractInsnNode(final int opcode) {
         this.opcode = opcode;
@@ -157,7 +181,7 @@ public abstract class AbstractInsnNode {
 
     /**
      * Returns the opcode of this instruction.
-     *
+     * 
      * @return the opcode of this instruction.
      */
     public int getOpcode() {
@@ -166,7 +190,7 @@ public abstract class AbstractInsnNode {
 
     /**
      * Returns the type of this instruction.
-     *
+     * 
      * @return the type of this instruction, i.e. one the constants defined in
      *         this class.
      */
@@ -175,7 +199,7 @@ public abstract class AbstractInsnNode {
     /**
      * Returns the previous instruction in the list to which this instruction
      * belongs, if any.
-     *
+     * 
      * @return the previous instruction in the list to which this instruction
      *         belongs, if any. May be <tt>null</tt>.
      */
@@ -186,7 +210,7 @@ public abstract class AbstractInsnNode {
     /**
      * Returns the next instruction in the list to which this instruction
      * belongs, if any.
-     *
+     * 
      * @return the next instruction in the list to which this instruction
      *         belongs, if any. May be <tt>null</tt>.
      */
@@ -196,43 +220,107 @@ public abstract class AbstractInsnNode {
 
     /**
      * Makes the given code visitor visit this instruction.
-     *
-     * @param cv a code visitor.
+     * 
+     * @param cv
+     *            a code visitor.
      */
     public abstract void accept(final MethodVisitor cv);
 
     /**
+     * Makes the given visitor visit the annotations of this instruction.
+     * 
+     * @param mv
+     *            a method visitor.
+     */
+    protected final void acceptAnnotations(final MethodVisitor mv) {
+        int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations
+                .size();
+        for (int i = 0; i < n; ++i) {
+            TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+            an.accept(mv.visitInsnAnnotation(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.visitInsnAnnotation(an.typeRef, an.typePath, an.desc,
+                    false));
+        }
+    }
+
+    /**
      * Returns a copy of this instruction.
-     *
-     * @param labels a map from LabelNodes to cloned LabelNodes.
+     * 
+     * @param labels
+     *            a map from LabelNodes to cloned LabelNodes.
      * @return a copy of this instruction. The returned instruction does not
      *         belong to any {@link InsnList}.
      */
-    public abstract AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels);
+    public abstract AbstractInsnNode clone(
+            final Map<LabelNode, LabelNode> labels);
 
     /**
      * Returns the clone of the given label.
-     *
-     * @param label a label.
-     * @param map a map from LabelNodes to cloned LabelNodes.
+     * 
+     * @param label
+     *            a label.
+     * @param map
+     *            a map from LabelNodes to cloned LabelNodes.
      * @return the clone of the given label.
      */
-    static LabelNode clone(final LabelNode label, final Map<LabelNode, LabelNode> map) {
+    static LabelNode clone(final LabelNode label,
+            final Map<LabelNode, LabelNode> map) {
         return map.get(label);
     }
 
     /**
      * Returns the clones of the given labels.
-     *
-     * @param labels a list of labels.
-     * @param map a map from LabelNodes to cloned LabelNodes.
+     * 
+     * @param labels
+     *            a list of labels.
+     * @param map
+     *            a map from LabelNodes to cloned LabelNodes.
      * @return the clones of the given labels.
      */
-    static LabelNode[] clone(final List<LabelNode> labels, final Map<LabelNode, LabelNode> map) {
+    static LabelNode[] clone(final List<LabelNode> labels,
+            final Map<LabelNode, LabelNode> map) {
         LabelNode[] clones = new LabelNode[labels.size()];
         for (int i = 0; i < clones.length; ++i) {
             clones[i] = map.get(labels.get(i));
         }
         return clones;
     }
+
+    /**
+     * Clones the annotations of the given instruction into this instruction.
+     * 
+     * @param insn
+     *            the source instruction.
+     * @return this instruction.
+     */
+    protected final AbstractInsnNode cloneAnnotations(
+            final AbstractInsnNode insn) {
+        if (insn.visibleTypeAnnotations != null) {
+            this.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>();
+            for (int i = 0; i < insn.visibleTypeAnnotations.size(); ++i) {
+                TypeAnnotationNode src = insn.visibleTypeAnnotations.get(i);
+                TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef,
+                        src.typePath, src.desc);
+                src.accept(ann);
+                this.visibleTypeAnnotations.add(ann);
+            }
+        }
+        if (insn.invisibleTypeAnnotations != null) {
+            this.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>();
+            for (int i = 0; i < insn.invisibleTypeAnnotations.size(); ++i) {
+                TypeAnnotationNode src = insn.invisibleTypeAnnotations.get(i);
+                TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef,
+                        src.typePath, src.desc);
+                src.accept(ann);
+                this.invisibleTypeAnnotations.add(ann);
+            }
+        }
+        return this;
+    }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
index 2fe5b77..9d07669 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
@@ -29,19 +29,18 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
-import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
 /**
  * A node that represents an annotationn.
  *
  * @author Eric Bruneton
  */
-public class AnnotationNode extends AnnotationVisitor
-{
+public class AnnotationNode extends AnnotationVisitor {
 
     /**
      * The class descriptor of the annotation class.
@@ -56,8 +55,8 @@ public class AnnotationNode extends AnnotationVisitor
      * {@link Double}, {@link String} or {@link org.apache.tapestry5.internal.plastic.asm.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. The list may be <tt>null</tt> if there is no name
-     * value pair.
+     * preceding types. The list may be <tt>null</tt> if there is no name value
+     * pair.
      */
     public List<Object> values;
 
@@ -66,18 +65,26 @@ public class AnnotationNode extends AnnotationVisitor
      * constructor</i>. Instead, they must use the
      * {@link #AnnotationNode(int, String)} version.
      *
-     * @param desc the class descriptor of the annotation class.
+     * @param desc
+     *            the class descriptor of the annotation class.
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
      */
     public AnnotationNode(final String desc) {
-        this(Opcodes.ASM4, desc);
+        this(Opcodes.ASM5, desc);
+        if (getClass() != AnnotationNode.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}.
-     * @param desc the class descriptor of the annotation class.
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param desc
+     *            the class descriptor of the annotation class.
      */
     public AnnotationNode(final int api, final String desc) {
         super(api);
@@ -87,10 +94,11 @@ public class AnnotationNode extends AnnotationVisitor
     /**
      * Constructs a new {@link AnnotationNode} to visit an array value.
      *
-     * @param values where the visited values must be stored.
+     * @param values
+     *            where the visited values must be stored.
      */
     AnnotationNode(final List<Object> values) {
-        super(Opcodes.ASM4);
+        super(Opcodes.ASM5);
         this.values = values;
     }
 
@@ -110,11 +118,8 @@ public class AnnotationNode extends AnnotationVisitor
     }
 
     @Override
-    public void visitEnum(
-        final String name,
-        final String desc,
-        final String value)
-    {
+    public void visitEnum(final String name, final String desc,
+            final String value) {
         if (values == null) {
             values = new ArrayList<Object>(this.desc != null ? 2 : 1);
         }
@@ -125,10 +130,8 @@ public class AnnotationNode extends AnnotationVisitor
     }
 
     @Override
-    public AnnotationVisitor visitAnnotation(
-        final String name,
-        final String desc)
-    {
+    public AnnotationVisitor visitAnnotation(final String name,
+            final String desc) {
         if (values == null) {
             values = new ArrayList<Object>(this.desc != null ? 2 : 1);
         }
@@ -167,7 +170,9 @@ public class AnnotationNode extends AnnotationVisitor
      * 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
@@ -176,7 +181,8 @@ public class AnnotationNode extends AnnotationVisitor
     /**
      * Makes the given visitor visit this annotation.
      *
-     * @param av an annotation visitor. Maybe <tt>null</tt>.
+     * @param av
+     *            an annotation visitor. Maybe <tt>null</tt>.
      */
     public void accept(final AnnotationVisitor av) {
         if (av != null) {
@@ -194,15 +200,15 @@ public class AnnotationNode extends AnnotationVisitor
     /**
      * Makes the given visitor visit a given annotation value.
      *
-     * @param av an annotation visitor. Maybe <tt>null</tt>.
-     * @param name the value name.
-     * @param value the actual value.
+     * @param av
+     *            an annotation visitor. Maybe <tt>null</tt>.
+     * @param name
+     *            the value name.
+     * @param value
+     *            the actual value.
      */
-    static void accept(
-        final AnnotationVisitor av,
-        final String name,
-        final Object value)
-    {
+    public static void accept(final AnnotationVisitor av, final String name,
+            final Object value) {
         if (av != null) {
             if (value instanceof String[]) {
                 String[] typeconst = (String[]) value;

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
index 7bda1ab..0bdcc54 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
@@ -29,15 +29,21 @@
  */
 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.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
 /**
  * A node that represents a class.
- *
+ * 
  * @author Eric Bruneton
  */
 public class ClassNode extends ClassVisitor {
@@ -60,15 +66,15 @@ public class ClassNode extends ClassVisitor {
     public String name;
 
     /**
-     * The signature of the class. Mayt be <tt>null</tt>.
+     * The signature of the class. May be <tt>null</tt>.
      */
     public String signature;
 
     /**
      * The internal of name of the super class (see
      * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). For
-     * interfaces, the super class is {@link Object}. May be <tt>null</tt>,
-     * but only for the {@link Object} class.
+     * interfaces, the super class is {@link Object}. May be <tt>null</tt>, but
+     * only for the {@link Object} class.
      */
     public String superName;
 
@@ -86,7 +92,7 @@ public class ClassNode extends ClassVisitor {
     public String sourceFile;
 
     /**
-     * Debug information to compute the correspondance between source and
+     * Debug information to compute the correspondence between source and
      * compiled elements of the class. May be <tt>null</tt>.
      */
     public String sourceDebug;
@@ -104,16 +110,16 @@ public class ClassNode extends ClassVisitor {
     public String outerMethod;
 
     /**
-     * The descriptor of the method that contains the class, or <tt>null</tt>
-     * if the class is not enclosed in a method.
+     * The descriptor of the method that contains the class, or <tt>null</tt> if
+     * the class is not enclosed in a method.
      */
     public String outerMethodDesc;
 
     /**
      * The runtime visible annotations of this class. 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;
@@ -121,41 +127,59 @@ public class ClassNode extends ClassVisitor {
     /**
      * The runtime invisible annotations of this class. 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 class. 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 class. 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 class. This list is a list of
      * {@link Attribute} objects. May be <tt>null</tt>.
-     *
-     * @associates Attribute
+     * 
+     * @associates org.objectweb.asm.Attribute
      */
     public List<Attribute> attrs;
 
     /**
      * Informations about the inner classes of this class. This list is a list
      * of {@link InnerClassNode} objects.
-     *
-     * @associates InnerClassNode
+     * 
+     * @associates org.objectweb.asm.tree.InnerClassNode
      */
     public List<InnerClassNode> innerClasses;
 
     /**
      * The fields of this class. This list is a list of {@link FieldNode}
      * objects.
-     *
-     * @associates FieldNode
+     * 
+     * @associates org.objectweb.asm.tree.FieldNode
      */
     public List<FieldNode> fields;
 
     /**
      * The methods of this class. This list is a list of {@link MethodNode}
      * objects.
-     *
-     * @associates MethodNode
+     * 
+     * @associates org.objectweb.asm.tree.MethodNode
      */
     public List<MethodNode> methods;
 
@@ -163,16 +187,23 @@ public class ClassNode extends ClassVisitor {
      * Constructs a new {@link ClassNode}. <i>Subclasses must not use this
      * constructor</i>. Instead, they must use the {@link #ClassNode(int)}
      * version.
+     * 
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
      */
     public ClassNode() {
-        this(Opcodes.ASM4);
+        this(Opcodes.ASM5);
+        if (getClass() != ClassNode.class) {
+            throw new IllegalStateException();
+        }
     }
 
     /**
      * Constructs a new {@link ClassNode}.
-     *
-     * @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 ClassNode(final int api) {
         super(api);
@@ -187,14 +218,9 @@ public class ClassNode extends ClassVisitor {
     // ------------------------------------------------------------------------
 
     @Override
-    public void visit(
-        final int version,
-        final int access,
-        final String name,
-        final String signature,
-        final String superName,
-        final String[] interfaces)
-    {
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
         this.version = version;
         this.access = access;
         this.name = name;
@@ -212,21 +238,16 @@ public class ClassNode extends ClassVisitor {
     }
 
     @Override
-    public void visitOuterClass(
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    public void visitOuterClass(final String owner, final String name,
+            final String desc) {
         outerClass = owner;
         outerMethod = name;
         outerMethodDesc = desc;
     }
 
     @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) {
@@ -243,6 +264,24 @@ public class ClassNode extends ClassVisitor {
     }
 
     @Override
+    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 void visitAttribute(final Attribute attr) {
         if (attrs == null) {
             attrs = new ArrayList<Attribute>(1);
@@ -251,44 +290,25 @@ public class ClassNode extends ClassVisitor {
     }
 
     @Override
-    public void visitInnerClass(
-        final String name,
-        final String outerName,
-        final String innerName,
-        final int access)
-    {
-        InnerClassNode icn = new InnerClassNode(name,
-                outerName,
-                innerName,
+    public void visitInnerClass(final String name, final String outerName,
+            final String innerName, final int access) {
+        InnerClassNode icn = new InnerClassNode(name, outerName, innerName,
                 access);
         innerClasses.add(icn);
     }
 
     @Override
-    public FieldVisitor visitField(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final Object value)
-    {
+    public FieldVisitor visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
         FieldNode fn = new FieldNode(access, name, desc, signature, value);
         fields.add(fn);
         return fn;
     }
 
     @Override
-    public MethodVisitor visitMethod(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final String[] exceptions)
-    {
-        MethodNode mn = new MethodNode(access,
-                name,
-                desc,
-                signature,
+    public MethodVisitor visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        MethodNode mn = new MethodNode(access, name, desc, signature,
                 exceptions);
         methods.add(mn);
         return mn;
@@ -307,17 +327,35 @@ public class ClassNode extends ClassVisitor {
      * 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();
+            }
+            for (FieldNode f : fields) {
+                f.check(api);
+            }
+            for (MethodNode m : methods) {
+                m.check(api);
+            }
+        }
     }
 
     /**
      * Makes the given class visitor visit this class.
-     *
-     * @param cv a class visitor.
+     * 
+     * @param cv
+     *            a class visitor.
      */
     public void accept(final ClassVisitor cv) {
         // visits header
@@ -344,6 +382,19 @@ public class ClassNode extends ClassVisitor {
             AnnotationNode an = invisibleAnnotations.get(i);
             an.accept(cv.visitAnnotation(an.desc, false));
         }
+        n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
+        for (i = 0; i < n; ++i) {
+            TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+            an.accept(cv.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(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+                    false));
+        }
         n = attrs == null ? 0 : attrs.size();
         for (i = 0; i < n; ++i) {
             cv.visitAttribute(attrs.get(i));

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java
index 265fb1e..848d05d 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.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 field instruction. A field instruction is an
  * instruction that loads or stores the value of a field of an object.
- *
+ * 
  * @author Eric Bruneton
  */
 public class FieldInsnNode extends AbstractInsnNode {
@@ -59,20 +59,21 @@ public class FieldInsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link FieldInsnNode}.
-     *
-     * @param opcode the opcode of the type instruction to be constructed. This
-     *        opcode must be GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
-     * @param owner the internal name of the field's owner class (see
-     *        {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}).
-     * @param name the field's name.
-     * @param desc the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+     * 
+     * @param opcode
+     *            the opcode of the type instruction to be constructed. This
+     *            opcode must be GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
+     * @param owner
+     *            the internal name of the field's owner class (see
+     *            {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+     *            getInternalName}).
+     * @param name
+     *            the field's name.
+     * @param desc
+     *            the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
      */
-    public FieldInsnNode(
-        final int opcode,
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    public FieldInsnNode(final int opcode, final String owner,
+            final String name, final String desc) {
         super(opcode);
         this.owner = owner;
         this.name = name;
@@ -81,9 +82,10 @@ public class FieldInsnNode extends AbstractInsnNode {
 
     /**
      * Sets the opcode of this instruction.
-     *
-     * @param opcode the new instruction opcode. This opcode must be GETSTATIC,
-     *        PUTSTATIC, GETFIELD or PUTFIELD.
+     * 
+     * @param opcode
+     *            the new instruction opcode. This opcode must be GETSTATIC,
+     *            PUTSTATIC, GETFIELD or PUTFIELD.
      */
     public void setOpcode(final int opcode) {
         this.opcode = opcode;
@@ -95,12 +97,14 @@ public class FieldInsnNode extends AbstractInsnNode {
     }
 
     @Override
-    public void accept(final MethodVisitor cv) {
-        cv.visitFieldInsn(opcode, owner, name, desc);
+    public void accept(final MethodVisitor mv) {
+        mv.visitFieldInsn(opcode, owner, name, desc);
+        acceptAnnotations(mv);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new FieldInsnNode(opcode, owner, name, desc);
+        return new FieldInsnNode(opcode, owner, name, desc)
+                .cloneAnnotations(this);
     }
 }


[13/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java
new file mode 100644
index 0000000..bffd20e
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java
@@ -0,0 +1,223 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureReader;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureWriter;
+
+/**
+ * A class responsible for remapping types and names. Subclasses can override
+ * the following methods:
+ * 
+ * <ul>
+ * <li>{@link #map(String)} - map type</li>
+ * <li>{@link #mapFieldName(String, String, String)} - map field name</li>
+ * <li>{@link #mapMethodName(String, String, String)} - map method name</li>
+ * </ul>
+ * 
+ * @author Eugene Kuleshov
+ */
+public abstract class Remapper {
+
+    public String mapDesc(String desc) {
+        Type t = Type.getType(desc);
+        switch (t.getSort()) {
+        case Type.ARRAY:
+            String s = mapDesc(t.getElementType().getDescriptor());
+            for (int i = 0; i < t.getDimensions(); ++i) {
+                s = '[' + s;
+            }
+            return s;
+        case Type.OBJECT:
+            String newType = map(t.getInternalName());
+            if (newType != null) {
+                return 'L' + newType + ';';
+            }
+        }
+        return desc;
+    }
+
+    private Type mapType(Type t) {
+        switch (t.getSort()) {
+        case Type.ARRAY:
+            String s = mapDesc(t.getElementType().getDescriptor());
+            for (int i = 0; i < t.getDimensions(); ++i) {
+                s = '[' + s;
+            }
+            return Type.getType(s);
+        case Type.OBJECT:
+            s = map(t.getInternalName());
+            return s != null ? Type.getObjectType(s) : t;
+        case Type.METHOD:
+            return Type.getMethodType(mapMethodDesc(t.getDescriptor()));
+        }
+        return t;
+    }
+
+    public String mapType(String type) {
+        if (type == null) {
+            return null;
+        }
+        return mapType(Type.getObjectType(type)).getInternalName();
+    }
+
+    public String[] mapTypes(String[] types) {
+        String[] newTypes = null;
+        boolean needMapping = false;
+        for (int i = 0; i < types.length; i++) {
+            String type = types[i];
+            String newType = map(type);
+            if (newType != null && newTypes == null) {
+                newTypes = new String[types.length];
+                if (i > 0) {
+                    System.arraycopy(types, 0, newTypes, 0, i);
+                }
+                needMapping = true;
+            }
+            if (needMapping) {
+                newTypes[i] = newType == null ? type : newType;
+            }
+        }
+        return needMapping ? newTypes : types;
+    }
+
+    public String mapMethodDesc(String desc) {
+        if ("()V".equals(desc)) {
+            return desc;
+        }
+
+        Type[] args = Type.getArgumentTypes(desc);
+        StringBuffer s = new StringBuffer("(");
+        for (int i = 0; i < args.length; i++) {
+            s.append(mapDesc(args[i].getDescriptor()));
+        }
+        Type returnType = Type.getReturnType(desc);
+        if (returnType == Type.VOID_TYPE) {
+            s.append(")V");
+            return s.toString();
+        }
+        s.append(')').append(mapDesc(returnType.getDescriptor()));
+        return s.toString();
+    }
+
+    public Object mapValue(Object value) {
+        if (value instanceof Type) {
+            return mapType((Type) value);
+        }
+        if (value instanceof Handle) {
+            Handle h = (Handle) value;
+            return new Handle(h.getTag(), mapType(h.getOwner()), mapMethodName(
+                    h.getOwner(), h.getName(), h.getDesc()),
+                    mapMethodDesc(h.getDesc()));
+        }
+        return value;
+    }
+
+    /**
+     * 
+     * @param typeSignature
+     *            true if signature is a FieldTypeSignature, such as the
+     *            signature parameter of the ClassVisitor.visitField or
+     *            MethodVisitor.visitLocalVariable methods
+     */
+    public String mapSignature(String signature, boolean typeSignature) {
+        if (signature == null) {
+            return null;
+        }
+        SignatureReader r = new SignatureReader(signature);
+        SignatureWriter w = new SignatureWriter();
+        SignatureVisitor a = createRemappingSignatureAdapter(w);
+        if (typeSignature) {
+            r.acceptType(a);
+        } else {
+            r.accept(a);
+        }
+        return w.toString();
+    }
+
+    protected SignatureVisitor createRemappingSignatureAdapter(
+            SignatureVisitor v) {
+        return new RemappingSignatureAdapter(v, this);
+    }
+
+    /**
+     * Map method name to the new name. Subclasses can override.
+     * 
+     * @param owner
+     *            owner of the method.
+     * @param name
+     *            name of the method.
+     * @param desc
+     *            descriptor of the method.
+     * @return new name of the method
+     */
+    public String mapMethodName(String owner, String name, String desc) {
+        return name;
+    }
+
+    /**
+     * Map invokedynamic method name to the new name. Subclasses can override.
+     * 
+     * @param name
+     *            name of the invokedynamic.
+     * @param desc
+     *            descriptor of the invokedynamic.
+     * @return new invokdynamic name.
+     */
+    public String mapInvokeDynamicMethodName(String name, String desc) {
+        return name;
+    }
+
+    /**
+     * Map field name to the new name. Subclasses can override.
+     * 
+     * @param owner
+     *            owner of the field.
+     * @param name
+     *            name of the field
+     * @param desc
+     *            descriptor of the field
+     * @return new name of the field.
+     */
+    public String mapFieldName(String owner, String name, String desc) {
+        return name;
+    }
+
+    /**
+     * Map type name to the new name. Subclasses can override.
+     */
+    public String map(String typeName) {
+        return typeName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java
new file mode 100644
index 0000000..2f253dd
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java
@@ -0,0 +1,79 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
+/**
+ * An {@link AnnotationVisitor} adapter for type remapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingAnnotationAdapter extends AnnotationVisitor {
+
+    protected final Remapper remapper;
+
+    public RemappingAnnotationAdapter(final AnnotationVisitor av,
+            final Remapper remapper) {
+        this(Opcodes.ASM5, av, remapper);
+    }
+
+    protected RemappingAnnotationAdapter(final int api,
+            final AnnotationVisitor av, final Remapper remapper) {
+        super(api, av);
+        this.remapper = remapper;
+    }
+
+    @Override
+    public void visit(String name, Object value) {
+        av.visit(name, remapper.mapValue(value));
+    }
+
+    @Override
+    public void visitEnum(String name, String desc, String value) {
+        av.visitEnum(name, remapper.mapDesc(desc), value);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(String name, String desc) {
+        AnnotationVisitor v = av.visitAnnotation(name, remapper.mapDesc(desc));
+        return v == null ? null : (v == av ? this
+                : new RemappingAnnotationAdapter(v, remapper));
+    }
+
+    @Override
+    public AnnotationVisitor visitArray(String name) {
+        AnnotationVisitor v = av.visitArray(name);
+        return v == null ? null : (v == av ? this
+                : new RemappingAnnotationAdapter(v, remapper));
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java
new file mode 100644
index 0000000..7dbae24
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java
@@ -0,0 +1,135 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A {@link ClassVisitor} for type remapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingClassAdapter extends ClassVisitor {
+
+    protected final Remapper remapper;
+
+    protected String className;
+
+    public RemappingClassAdapter(final ClassVisitor cv, final Remapper remapper) {
+        this(Opcodes.ASM5, cv, remapper);
+    }
+
+    protected RemappingClassAdapter(final int api, final ClassVisitor cv,
+            final Remapper remapper) {
+        super(api, cv);
+        this.remapper = remapper;
+    }
+
+    @Override
+    public void visit(int version, int access, String name, String signature,
+            String superName, String[] interfaces) {
+        this.className = name;
+        super.visit(version, access, remapper.mapType(name), remapper
+                .mapSignature(signature, false), remapper.mapType(superName),
+                interfaces == null ? null : remapper.mapTypes(interfaces));
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
+                visible);
+        return av == null ? null : createRemappingAnnotationAdapter(av);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
+                remapper.mapDesc(desc), visible);
+        return av == null ? null : createRemappingAnnotationAdapter(av);
+    }
+
+    @Override
+    public FieldVisitor visitField(int access, String name, String desc,
+            String signature, Object value) {
+        FieldVisitor fv = super.visitField(access,
+                remapper.mapFieldName(className, name, desc),
+                remapper.mapDesc(desc), remapper.mapSignature(signature, true),
+                remapper.mapValue(value));
+        return fv == null ? null : createRemappingFieldAdapter(fv);
+    }
+
+    @Override
+    public MethodVisitor visitMethod(int access, String name, String desc,
+            String signature, String[] exceptions) {
+        String newDesc = remapper.mapMethodDesc(desc);
+        MethodVisitor mv = super.visitMethod(access, remapper.mapMethodName(
+                className, name, desc), newDesc, remapper.mapSignature(
+                signature, false),
+                exceptions == null ? null : remapper.mapTypes(exceptions));
+        return mv == null ? null : createRemappingMethodAdapter(access,
+                newDesc, mv);
+    }
+
+    @Override
+    public void visitInnerClass(String name, String outerName,
+            String innerName, int access) {
+        // TODO should innerName be changed?
+        super.visitInnerClass(remapper.mapType(name), outerName == null ? null
+                : remapper.mapType(outerName), innerName, access);
+    }
+
+    @Override
+    public void visitOuterClass(String owner, String name, String desc) {
+        super.visitOuterClass(remapper.mapType(owner), name == null ? null
+                : remapper.mapMethodName(owner, name, desc),
+                desc == null ? null : remapper.mapMethodDesc(desc));
+    }
+
+    protected FieldVisitor createRemappingFieldAdapter(FieldVisitor fv) {
+        return new RemappingFieldAdapter(fv, remapper);
+    }
+
+    protected MethodVisitor createRemappingMethodAdapter(int access,
+            String newDesc, MethodVisitor mv) {
+        return new RemappingMethodAdapter(access, newDesc, mv, remapper);
+    }
+
+    protected AnnotationVisitor createRemappingAnnotationAdapter(
+            AnnotationVisitor av) {
+        return new RemappingAnnotationAdapter(av, remapper);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java
new file mode 100644
index 0000000..8a8420d
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java
@@ -0,0 +1,71 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A {@link FieldVisitor} adapter for type remapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingFieldAdapter extends FieldVisitor {
+
+    private final Remapper remapper;
+
+    public RemappingFieldAdapter(final FieldVisitor fv, final Remapper remapper) {
+        this(Opcodes.ASM5, fv, remapper);
+    }
+
+    protected RemappingFieldAdapter(final int api, final FieldVisitor fv,
+            final Remapper remapper) {
+        super(api, fv);
+        this.remapper = remapper;
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        AnnotationVisitor av = fv.visitAnnotation(remapper.mapDesc(desc),
+                visible);
+        return av == null ? null : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
+                remapper.mapDesc(desc), visible);
+        return av == null ? null : new RemappingAnnotationAdapter(av, remapper);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java
new file mode 100644
index 0000000..1dec924
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java
@@ -0,0 +1,224 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+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.TypePath;
+
+/**
+ * A {@link LocalVariablesSorter} for type mapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingMethodAdapter extends LocalVariablesSorter {
+
+    protected final Remapper remapper;
+
+    public RemappingMethodAdapter(final int access, final String desc,
+            final MethodVisitor mv, final Remapper remapper) {
+        this(Opcodes.ASM5, access, desc, mv, remapper);
+    }
+
+    protected RemappingMethodAdapter(final int api, final int access,
+            final String desc, final MethodVisitor mv, final Remapper remapper) {
+        super(api, access, desc, mv);
+        this.remapper = remapper;
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotationDefault() {
+        AnnotationVisitor av = super.visitAnnotationDefault();
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
+                visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
+                remapper.mapDesc(desc), visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public AnnotationVisitor visitParameterAnnotation(int parameter,
+            String desc, boolean visible) {
+        AnnotationVisitor av = super.visitParameterAnnotation(parameter,
+                remapper.mapDesc(desc), visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public void visitFrame(int type, int nLocal, Object[] local, int nStack,
+            Object[] stack) {
+        super.visitFrame(type, nLocal, remapEntries(nLocal, local), nStack,
+                remapEntries(nStack, stack));
+    }
+
+    private Object[] remapEntries(int n, Object[] entries) {
+        for (int i = 0; i < n; i++) {
+            if (entries[i] instanceof String) {
+                Object[] newEntries = new Object[n];
+                if (i > 0) {
+                    System.arraycopy(entries, 0, newEntries, 0, i);
+                }
+                do {
+                    Object t = entries[i];
+                    newEntries[i++] = t instanceof String ? remapper
+                            .mapType((String) t) : t;
+                } while (i < n);
+                return newEntries;
+            }
+        }
+        return entries;
+    }
+
+    @Override
+    public void visitFieldInsn(int opcode, String owner, String name,
+            String desc) {
+        super.visitFieldInsn(opcode, remapper.mapType(owner),
+                remapper.mapFieldName(owner, name, desc),
+                remapper.mapDesc(desc));
+    }
+
+    @Deprecated
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (api >= Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc,
+                opcode == Opcodes.INVOKEINTERFACE);
+    }
+
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    private void doVisitMethodInsn(int opcode, String owner, String name,
+            String desc, boolean itf) {
+        // Calling super.visitMethodInsn requires to call the correct version
+        // depending on this.api (otherwise infinite loops can occur). To
+        // simplify and to make it easier to automatically remove the backward
+        // compatibility code, we inline the code of the overridden method here.
+        // IMPORTANT: THIS ASSUMES THAT visitMethodInsn IS NOT OVERRIDDEN IN
+        // LocalVariableSorter.
+        if (mv != null) {
+            mv.visitMethodInsn(opcode, remapper.mapType(owner),
+                    remapper.mapMethodName(owner, name, desc),
+                    remapper.mapMethodDesc(desc), itf);
+        }
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        for (int i = 0; i < bsmArgs.length; i++) {
+            bsmArgs[i] = remapper.mapValue(bsmArgs[i]);
+        }
+        super.visitInvokeDynamicInsn(
+                remapper.mapInvokeDynamicMethodName(name, desc),
+                remapper.mapMethodDesc(desc), (Handle) remapper.mapValue(bsm),
+                bsmArgs);
+    }
+
+    @Override
+    public void visitTypeInsn(int opcode, String type) {
+        super.visitTypeInsn(opcode, remapper.mapType(type));
+    }
+
+    @Override
+    public void visitLdcInsn(Object cst) {
+        super.visitLdcInsn(remapper.mapValue(cst));
+    }
+
+    @Override
+    public void visitMultiANewArrayInsn(String desc, int dims) {
+        super.visitMultiANewArrayInsn(remapper.mapDesc(desc), dims);
+    }
+
+    @Override
+    public AnnotationVisitor visitInsnAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        AnnotationVisitor av = super.visitInsnAnnotation(typeRef, typePath,
+                remapper.mapDesc(desc), visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public void visitTryCatchBlock(Label start, Label end, Label handler,
+            String type) {
+        super.visitTryCatchBlock(start, end, handler, type == null ? null
+                : remapper.mapType(type));
+    }
+
+    @Override
+    public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        AnnotationVisitor av = super.visitTryCatchAnnotation(typeRef, typePath,
+                remapper.mapDesc(desc), visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public void visitLocalVariable(String name, String desc, String signature,
+            Label start, Label end, int index) {
+        super.visitLocalVariable(name, remapper.mapDesc(desc),
+                remapper.mapSignature(signature, true), start, end, index);
+    }
+
+    @Override
+    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+            TypePath typePath, Label[] start, Label[] end, int[] index,
+            String desc, boolean visible) {
+        AnnotationVisitor av = super.visitLocalVariableAnnotation(typeRef,
+                typePath, start, end, index, remapper.mapDesc(desc), visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java
new file mode 100644
index 0000000..ff608a4
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java
@@ -0,0 +1,155 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
+
+/**
+ * A {@link SignatureVisitor} adapter for type mapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingSignatureAdapter extends SignatureVisitor {
+
+    private final SignatureVisitor v;
+
+    private final Remapper remapper;
+
+    private String className;
+
+    public RemappingSignatureAdapter(final SignatureVisitor v,
+            final Remapper remapper) {
+        this(Opcodes.ASM5, v, remapper);
+    }
+
+    protected RemappingSignatureAdapter(final int api,
+            final SignatureVisitor v, final Remapper remapper) {
+        super(api);
+        this.v = v;
+        this.remapper = remapper;
+    }
+
+    @Override
+    public void visitClassType(String name) {
+        className = name;
+        v.visitClassType(remapper.mapType(name));
+    }
+
+    @Override
+    public void visitInnerClassType(String name) {
+        String remappedOuter = remapper.mapType(className) + '$';
+        className = className + '$' + name;
+        String remappedName = remapper.mapType(className);
+        int index = remappedName.startsWith(remappedOuter) ? remappedOuter
+                .length() : remappedName.lastIndexOf('$') + 1;
+        v.visitInnerClassType(remappedName.substring(index));
+    }
+
+    @Override
+    public void visitFormalTypeParameter(String name) {
+        v.visitFormalTypeParameter(name);
+    }
+
+    @Override
+    public void visitTypeVariable(String name) {
+        v.visitTypeVariable(name);
+    }
+
+    @Override
+    public SignatureVisitor visitArrayType() {
+        v.visitArrayType();
+        return this;
+    }
+
+    @Override
+    public void visitBaseType(char descriptor) {
+        v.visitBaseType(descriptor);
+    }
+
+    @Override
+    public SignatureVisitor visitClassBound() {
+        v.visitClassBound();
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitExceptionType() {
+        v.visitExceptionType();
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitInterface() {
+        v.visitInterface();
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitInterfaceBound() {
+        v.visitInterfaceBound();
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitParameterType() {
+        v.visitParameterType();
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitReturnType() {
+        v.visitReturnType();
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitSuperclass() {
+        v.visitSuperclass();
+        return this;
+    }
+
+    @Override
+    public void visitTypeArgument() {
+        v.visitTypeArgument();
+    }
+
+    @Override
+    public SignatureVisitor visitTypeArgument(char wildcard) {
+        v.visitTypeArgument(wildcard);
+        return this;
+    }
+
+    @Override
+    public void visitEnd() {
+        v.visitEnd();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
new file mode 100644
index 0000000..04dcc9b
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
@@ -0,0 +1,540 @@
+/***
+ * 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.commons;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
+/**
+ * A {@link ClassVisitor} that adds a serial version unique identifier to a
+ * class if missing. Here is typical usage of this class:
+ * 
+ * <pre>
+ *   ClassWriter cw = new ClassWriter(...);
+ *   ClassVisitor sv = new SerialVersionUIDAdder(cw);
+ *   ClassVisitor ca = new MyClassAdapter(sv);
+ *   new ClassReader(orginalClass).accept(ca, false);
+ * </pre>
+ * 
+ * The SVUID algorithm can be found <a href=
+ * "http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html"
+ * >http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html</a>:
+ * 
+ * <pre>
+ * The serialVersionUID is computed using the signature of a stream of bytes
+ * that reflect the class definition. The National Institute of Standards and
+ * Technology (NIST) Secure Hash Algorithm (SHA-1) is used to compute a
+ * signature for the stream. The first two 32-bit quantities are used to form a
+ * 64-bit hash. A java.lang.DataOutputStream is used to convert primitive data
+ * types to a sequence of bytes. The values input to the stream are defined by
+ * the Java Virtual Machine (VM) specification for classes.
+ * 
+ * The sequence of items in the stream is as follows:
+ * 
+ * 1. The class name written using UTF encoding.
+ * 2. The class modifiers written as a 32-bit integer.
+ * 3. The name of each interface sorted by name written using UTF encoding.
+ * 4. For each field of the class sorted by field name (except private static
+ * and private transient fields):
+ * 1. The name of the field in UTF encoding.
+ * 2. The modifiers of the field written as a 32-bit integer.
+ * 3. The descriptor of the field in UTF encoding
+ * 5. If a class initializer exists, write out the following:
+ * 1. The name of the method, &lt;clinit&gt;, in UTF encoding.
+ * 2. The modifier of the method, java.lang.reflect.Modifier.STATIC,
+ * written as a 32-bit integer.
+ * 3. The descriptor of the method, ()V, in UTF encoding.
+ * 6. For each non-private constructor sorted by method name and signature:
+ * 1. The name of the method, &lt;init&gt;, in UTF encoding.
+ * 2. The modifiers of the method written as a 32-bit integer.
+ * 3. The descriptor of the method in UTF encoding.
+ * 7. For each non-private method sorted by method name and signature:
+ * 1. The name of the method in UTF encoding.
+ * 2. The modifiers of the method written as a 32-bit integer.
+ * 3. The descriptor of the method in UTF encoding.
+ * 8. The SHA-1 algorithm is executed on the stream of bytes produced by
+ * DataOutputStream and produces five 32-bit values sha[0..4].
+ * 
+ * 9. The hash value is assembled from the first and second 32-bit values of
+ * the SHA-1 message digest. If the result of the message digest, the five
+ * 32-bit words H0 H1 H2 H3 H4, is in an array of five int values named
+ * sha, the hash value would be computed as follows:
+ * 
+ * long hash = ((sha[0] &gt;&gt;&gt; 24) &amp; 0xFF) |
+ * ((sha[0] &gt;&gt;&gt; 16) &amp; 0xFF) &lt;&lt; 8 |
+ * ((sha[0] &gt;&gt;&gt; 8) &amp; 0xFF) &lt;&lt; 16 |
+ * ((sha[0] &gt;&gt;&gt; 0) &amp; 0xFF) &lt;&lt; 24 |
+ * ((sha[1] &gt;&gt;&gt; 24) &amp; 0xFF) &lt;&lt; 32 |
+ * ((sha[1] &gt;&gt;&gt; 16) &amp; 0xFF) &lt;&lt; 40 |
+ * ((sha[1] &gt;&gt;&gt; 8) &amp; 0xFF) &lt;&lt; 48 |
+ * ((sha[1] &gt;&gt;&gt; 0) &amp; 0xFF) &lt;&lt; 56;
+ * </pre>
+ * 
+ * @author Rajendra Inamdar, Vishal Vishnoi
+ */
+public class SerialVersionUIDAdder extends ClassVisitor {
+
+    /**
+     * Flag that indicates if we need to compute SVUID.
+     */
+    private boolean computeSVUID;
+
+    /**
+     * Set to true if the class already has SVUID.
+     */
+    private boolean hasSVUID;
+
+    /**
+     * Classes access flags.
+     */
+    private int access;
+
+    /**
+     * Internal name of the class
+     */
+    private String name;
+
+    /**
+     * Interfaces implemented by the class.
+     */
+    private String[] interfaces;
+
+    /**
+     * Collection of fields. (except private static and private transient
+     * fields)
+     */
+    private Collection<Item> svuidFields;
+
+    /**
+     * Set to true if the class has static initializer.
+     */
+    private boolean hasStaticInitializer;
+
+    /**
+     * Collection of non-private constructors.
+     */
+    private Collection<Item> svuidConstructors;
+
+    /**
+     * Collection of non-private methods.
+     */
+    private Collection<Item> svuidMethods;
+
+    /**
+     * Creates a new {@link SerialVersionUIDAdder}. <i>Subclasses must not use
+     * this constructor</i>. Instead, they must use the
+     * {@link #SerialVersionUIDAdder(int, ClassVisitor)} version.
+     * 
+     * @param cv
+     *            a {@link ClassVisitor} to which this visitor will delegate
+     *            calls.
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public SerialVersionUIDAdder(final ClassVisitor cv) {
+        this(Opcodes.ASM5, cv);
+        if (getClass() != SerialVersionUIDAdder.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Creates a new {@link SerialVersionUIDAdder}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param cv
+     *            a {@link ClassVisitor} to which this visitor will delegate
+     *            calls.
+     */
+    protected SerialVersionUIDAdder(final int api, final ClassVisitor cv) {
+        super(api, cv);
+        svuidFields = new ArrayList<Item>();
+        svuidConstructors = new ArrayList<Item>();
+        svuidMethods = new ArrayList<Item>();
+    }
+
+    // ------------------------------------------------------------------------
+    // Overridden methods
+    // ------------------------------------------------------------------------
+
+    /*
+     * Visit class header and get class name, access , and interfaces
+     * information (step 1,2, and 3) for SVUID computation.
+     */
+    @Override
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
+        computeSVUID = (access & Opcodes.ACC_INTERFACE) == 0;
+
+        if (computeSVUID) {
+            this.name = name;
+            this.access = access;
+            this.interfaces = new String[interfaces.length];
+            System.arraycopy(interfaces, 0, this.interfaces, 0,
+                    interfaces.length);
+        }
+
+        super.visit(version, access, name, signature, superName, interfaces);
+    }
+
+    /*
+     * Visit the methods and get constructor and method information (step 5 and
+     * 7). Also determine if there is a class initializer (step 6).
+     */
+    @Override
+    public MethodVisitor visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        if (computeSVUID) {
+            if ("<clinit>".equals(name)) {
+                hasStaticInitializer = true;
+            }
+            /*
+             * Remembers non private constructors and methods for SVUID
+             * computation For constructor and method modifiers, only the
+             * ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
+             * ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT and ACC_STRICT flags
+             * are used.
+             */
+            int mods = access
+                    & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE
+                            | Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
+                            | Opcodes.ACC_FINAL | Opcodes.ACC_SYNCHRONIZED
+                            | Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_STRICT);
+
+            // all non private methods
+            if ((access & Opcodes.ACC_PRIVATE) == 0) {
+                if ("<init>".equals(name)) {
+                    svuidConstructors.add(new Item(name, mods, desc));
+                } else if (!"<clinit>".equals(name)) {
+                    svuidMethods.add(new Item(name, mods, desc));
+                }
+            }
+        }
+
+        return super.visitMethod(access, name, desc, signature, exceptions);
+    }
+
+    /*
+     * Gets class field information for step 4 of the algorithm. Also determines
+     * if the class already has a SVUID.
+     */
+    @Override
+    public FieldVisitor visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
+        if (computeSVUID) {
+            if ("serialVersionUID".equals(name)) {
+                // since the class already has SVUID, we won't be computing it.
+                computeSVUID = false;
+                hasSVUID = true;
+            }
+            /*
+             * Remember field for SVUID computation For field modifiers, only
+             * the ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC,
+             * ACC_FINAL, ACC_VOLATILE, and ACC_TRANSIENT flags are used when
+             * computing serialVersionUID values.
+             */
+            if ((access & Opcodes.ACC_PRIVATE) == 0
+                    || (access & (Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT)) == 0) {
+                int mods = access
+                        & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE
+                                | Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
+                                | Opcodes.ACC_FINAL | Opcodes.ACC_VOLATILE | Opcodes.ACC_TRANSIENT);
+                svuidFields.add(new Item(name, mods, desc));
+            }
+        }
+
+        return super.visitField(access, name, desc, signature, value);
+    }
+
+    /**
+     * Handle a bizarre special case. Nested classes (static classes declared
+     * inside another class) that are protected have their access bit set to
+     * public in their class files to deal with some odd reflection situation.
+     * Our SVUID computation must do as the JVM does and ignore access bits in
+     * the class file in favor of the access bits InnerClass attribute.
+     */
+    @Override
+    public void visitInnerClass(final String aname, final String outerName,
+            final String innerName, final int attr_access) {
+        if ((name != null) && name.equals(aname)) {
+            this.access = attr_access;
+        }
+        super.visitInnerClass(aname, outerName, innerName, attr_access);
+    }
+
+    /*
+     * Add the SVUID if class doesn't have one
+     */
+    @Override
+    public void visitEnd() {
+        // compute SVUID and add it to the class
+        if (computeSVUID && !hasSVUID) {
+            try {
+                addSVUID(computeSVUID());
+            } catch (Throwable e) {
+                throw new RuntimeException("Error while computing SVUID for "
+                        + name, e);
+            }
+        }
+
+        super.visitEnd();
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns true if the class already has a SVUID field. The result of this
+     * method is only valid when visitEnd is or has been called.
+     * 
+     * @return true if the class already has a SVUID field.
+     */
+    public boolean hasSVUID() {
+        return hasSVUID;
+    }
+
+    protected void addSVUID(long svuid) {
+        FieldVisitor fv = super.visitField(Opcodes.ACC_FINAL
+                + Opcodes.ACC_STATIC, "serialVersionUID", "J", null, new Long(
+                svuid));
+        if (fv != null) {
+            fv.visitEnd();
+        }
+    }
+
+    /**
+     * Computes and returns the value of SVUID.
+     * 
+     * @return Returns the serial version UID
+     * @throws IOException
+     *             if an I/O error occurs
+     */
+    protected long computeSVUID() throws IOException {
+        ByteArrayOutputStream bos;
+        DataOutputStream dos = null;
+        long svuid = 0;
+
+        try {
+            bos = new ByteArrayOutputStream();
+            dos = new DataOutputStream(bos);
+
+            /*
+             * 1. The class name written using UTF encoding.
+             */
+            dos.writeUTF(name.replace('/', '.'));
+
+            /*
+             * 2. The class modifiers written as a 32-bit integer.
+             */
+            dos.writeInt(access
+                    & (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL
+                            | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT));
+
+            /*
+             * 3. The name of each interface sorted by name written using UTF
+             * encoding.
+             */
+            Arrays.sort(interfaces);
+            for (int i = 0; i < interfaces.length; i++) {
+                dos.writeUTF(interfaces[i].replace('/', '.'));
+            }
+
+            /*
+             * 4. For each field of the class sorted by field name (except
+             * private static and private transient fields):
+             * 
+             * 1. The name of the field in UTF encoding. 2. The modifiers of the
+             * field written as a 32-bit integer. 3. The descriptor of the field
+             * in UTF encoding
+             * 
+             * Note that field signatures are not dot separated. Method and
+             * constructor signatures are dot separated. Go figure...
+             */
+            writeItems(svuidFields, dos, false);
+
+            /*
+             * 5. If a class initializer exists, write out the following: 1. The
+             * name of the method, <clinit>, in UTF encoding. 2. The modifier of
+             * the method, java.lang.reflect.Modifier.STATIC, written as a
+             * 32-bit integer. 3. The descriptor of the method, ()V, in UTF
+             * encoding.
+             */
+            if (hasStaticInitializer) {
+                dos.writeUTF("<clinit>");
+                dos.writeInt(Opcodes.ACC_STATIC);
+                dos.writeUTF("()V");
+            } // if..
+
+            /*
+             * 6. For each non-private constructor sorted by method name and
+             * signature: 1. The name of the method, <init>, in UTF encoding. 2.
+             * The modifiers of the method written as a 32-bit integer. 3. The
+             * descriptor of the method in UTF encoding.
+             */
+            writeItems(svuidConstructors, dos, true);
+
+            /*
+             * 7. For each non-private method sorted by method name and
+             * signature: 1. The name of the method in UTF encoding. 2. The
+             * modifiers of the method written as a 32-bit integer. 3. The
+             * descriptor of the method in UTF encoding.
+             */
+            writeItems(svuidMethods, dos, true);
+
+            dos.flush();
+
+            /*
+             * 8. The SHA-1 algorithm is executed on the stream of bytes
+             * produced by DataOutputStream and produces five 32-bit values
+             * sha[0..4].
+             */
+            byte[] hashBytes = computeSHAdigest(bos.toByteArray());
+
+            /*
+             * 9. The hash value is assembled from the first and second 32-bit
+             * values of the SHA-1 message digest. If the result of the message
+             * digest, the five 32-bit words H0 H1 H2 H3 H4, is in an array of
+             * five int values named sha, the hash value would be computed as
+             * follows:
+             * 
+             * long hash = ((sha[0] >>> 24) & 0xFF) | ((sha[0] >>> 16) & 0xFF)
+             * << 8 | ((sha[0] >>> 8) & 0xFF) << 16 | ((sha[0] >>> 0) & 0xFF) <<
+             * 24 | ((sha[1] >>> 24) & 0xFF) << 32 | ((sha[1] >>> 16) & 0xFF) <<
+             * 40 | ((sha[1] >>> 8) & 0xFF) << 48 | ((sha[1] >>> 0) & 0xFF) <<
+             * 56;
+             */
+            for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
+                svuid = (svuid << 8) | (hashBytes[i] & 0xFF);
+            }
+        } finally {
+            // close the stream (if open)
+            if (dos != null) {
+                dos.close();
+            }
+        }
+
+        return svuid;
+    }
+
+    /**
+     * Returns the SHA-1 message digest of the given value.
+     * 
+     * @param value
+     *            the value whose SHA message digest must be computed.
+     * @return the SHA-1 message digest of the given value.
+     */
+    protected byte[] computeSHAdigest(final byte[] value) {
+        try {
+            return MessageDigest.getInstance("SHA").digest(value);
+        } catch (Exception e) {
+            throw new UnsupportedOperationException(e.toString());
+        }
+    }
+
+    /**
+     * Sorts the items in the collection and writes it to the data output stream
+     * 
+     * @param itemCollection
+     *            collection of items
+     * @param dos
+     *            a <code>DataOutputStream</code> value
+     * @param dotted
+     *            a <code>boolean</code> value
+     * @exception IOException
+     *                if an error occurs
+     */
+    private static void writeItems(final Collection<Item> itemCollection,
+            final DataOutput dos, final boolean dotted) throws IOException {
+        int size = itemCollection.size();
+        Item[] items = itemCollection.toArray(new Item[size]);
+        Arrays.sort(items);
+        for (int i = 0; i < size; i++) {
+            dos.writeUTF(items[i].name);
+            dos.writeInt(items[i].access);
+            dos.writeUTF(dotted ? items[i].desc.replace('/', '.')
+                    : items[i].desc);
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Inner classes
+    // ------------------------------------------------------------------------
+
+    private static class Item implements Comparable<Item> {
+
+        final String name;
+
+        final int access;
+
+        final String desc;
+
+        Item(final String name, final int access, final String desc) {
+            this.name = name;
+            this.access = access;
+            this.desc = desc;
+        }
+
+        public int compareTo(final Item other) {
+            int retVal = name.compareTo(other.name);
+            if (retVal == 0) {
+                retVal = desc.compareTo(other.desc);
+            }
+            return retVal;
+        }
+
+        @Override
+        public boolean equals(final Object o) {
+            if (o instanceof Item) {
+                return compareTo((Item) o) == 0;
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return (name + desc).hashCode();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java
new file mode 100644
index 0000000..25b594d
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java
@@ -0,0 +1,69 @@
+/***
+ * 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.commons;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * A {@link Remapper} using a {@link Map} to define its mapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class SimpleRemapper extends Remapper {
+
+    private final Map<String, String> mapping;
+
+    public SimpleRemapper(Map<String, String> mapping) {
+        this.mapping = mapping;
+    }
+
+    public SimpleRemapper(String oldName, String newName) {
+        this.mapping = Collections.singletonMap(oldName, newName);
+    }
+
+    @Override
+    public String mapMethodName(String owner, String name, String desc) {
+        String s = map(owner + '.' + name + desc);
+        return s == null ? name : s;
+    }
+
+    @Override
+    public String mapFieldName(String owner, String name, String desc) {
+        String s = map(owner + '.' + name);
+        return s == null ? name : s;
+    }
+
+    @Override
+    public String map(String key) {
+        return mapping.get(key);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.java
new file mode 100644
index 0000000..8291c66
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.java
@@ -0,0 +1,97 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
+/**
+ * A {@link ClassVisitor} that merges clinit methods into a single one.
+ * 
+ * @author Eric Bruneton
+ */
+public class StaticInitMerger extends ClassVisitor {
+
+    private String name;
+
+    private MethodVisitor clinit;
+
+    private final String prefix;
+
+    private int counter;
+
+    public StaticInitMerger(final String prefix, final ClassVisitor cv) {
+        this(Opcodes.ASM5, prefix, cv);
+    }
+
+    protected StaticInitMerger(final int api, final String prefix,
+            final ClassVisitor cv) {
+        super(api, cv);
+        this.prefix = prefix;
+    }
+
+    @Override
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
+        cv.visit(version, access, name, signature, superName, interfaces);
+        this.name = name;
+    }
+
+    @Override
+    public MethodVisitor visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        MethodVisitor mv;
+        if ("<clinit>".equals(name)) {
+            int a = Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC;
+            String n = prefix + counter++;
+            mv = cv.visitMethod(a, n, desc, signature, exceptions);
+
+            if (clinit == null) {
+                clinit = cv.visitMethod(a, name, desc, null, null);
+            }
+            clinit.visitMethodInsn(Opcodes.INVOKESTATIC, this.name, n, desc,
+                    false);
+        } else {
+            mv = cv.visitMethod(access, name, desc, signature, exceptions);
+        }
+        return mv;
+    }
+
+    @Override
+    public void visitEnd() {
+        if (clinit != null) {
+            clinit.visitInsn(Opcodes.RETURN);
+            clinit.visitMaxs(0, 0);
+        }
+        cv.visitEnd();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java
new file mode 100644
index 0000000..322d7bb
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java
@@ -0,0 +1,57 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.Label;
+
+/**
+ * A code generator for switch statements.
+ * 
+ * @author Juozas Baliuka
+ * @author Chris Nokleberg
+ * @author Eric Bruneton
+ */
+public interface TableSwitchGenerator {
+
+    /**
+     * Generates the code for a switch case.
+     * 
+     * @param key
+     *            the switch case key.
+     * @param end
+     *            a label that corresponds to the end of the switch statement.
+     */
+    void generateCase(int key, Label end);
+
+    /**
+     * Generates the code for the default switch case.
+     */
+    void generateDefault();
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java
new file mode 100644
index 0000000..4b4641a
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java
@@ -0,0 +1,96 @@
+/***
+ * 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.commons;
+
+import java.util.Collections;
+import java.util.Comparator;
+
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TryCatchBlockNode;
+
+/**
+ * A {@link MethodVisitor} adapter to sort the exception handlers. The handlers
+ * are sorted in a method innermost-to-outermost. This allows the programmer to
+ * add handlers without worrying about ordering them correctly with respect to
+ * existing, in-code handlers.
+ * 
+ * Behavior is only defined for properly-nested handlers. If any "try" blocks
+ * overlap (something that isn't possible in Java code) then this may not do
+ * what you want. In fact, this adapter just sorts by the length of the "try"
+ * block, taking advantage of the fact that a given try block must be larger
+ * than any block it contains).
+ * 
+ * @author Adrian Sampson
+ */
+public class TryCatchBlockSorter extends MethodNode {
+
+    public TryCatchBlockSorter(final MethodVisitor mv, final int access,
+            final String name, final String desc, final String signature,
+            final String[] exceptions) {
+        this(Opcodes.ASM5, mv, access, name, desc, signature, exceptions);
+    }
+
+    protected TryCatchBlockSorter(final int api, final MethodVisitor mv,
+            final int access, final String name, final String desc,
+            final String signature, final String[] exceptions) {
+        super(api, access, name, desc, signature, exceptions);
+        this.mv = mv;
+    }
+
+    @Override
+    public void visitEnd() {
+        // Compares TryCatchBlockNodes by the length of their "try" block.
+        Comparator<TryCatchBlockNode> comp = new Comparator<TryCatchBlockNode>() {
+
+            public int compare(TryCatchBlockNode t1, TryCatchBlockNode t2) {
+                int len1 = blockLength(t1);
+                int len2 = blockLength(t2);
+                return len1 - len2;
+            }
+
+            private int blockLength(TryCatchBlockNode block) {
+                int startidx = instructions.indexOf(block.start);
+                int endidx = instructions.indexOf(block.end);
+                return endidx - startidx;
+            }
+        };
+        Collections.sort(tryCatchBlocks, comp);
+        // Updates the 'target' of each try catch block annotation.
+        for (int i = 0; i < tryCatchBlocks.size(); ++i) {
+            tryCatchBlocks.get(i).updateIndex(i);
+        }
+        if (mv != null) {
+            accept(mv);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/package.html
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/package.html b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/package.html
new file mode 100644
index 0000000..4ce0db8
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/package.html
@@ -0,0 +1,48 @@
+<html>
+<!--
+ * 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.
+-->
+<body>
+Provides some useful class and method adapters. <i>The preferred way of using
+these adapters is by chaining them together and to custom adapters (instead of
+inheriting from them)</i>. Indeed this approach provides more combination
+possibilities than inheritance. For instance, suppose you want to implement an
+adapter MyAdapter than needs sorted local variables and intermediate stack map
+frame values taking into account the local variables sort. By using inheritance,
+this would require MyAdapter to extend AnalyzerAdapter, itself extending
+LocalVariablesSorter. But AnalyzerAdapter is not a subclass of
+LocalVariablesSorter, so this is not possible. On the contrary, by using
+delegation, you can make LocalVariablesSorter delegate to AnalyzerAdapter,
+itself delegating to MyAdapter. In this case AnalyzerAdapter computes
+intermediate frames based on the output of LocalVariablesSorter, and MyAdapter
+can add new locals by calling the newLocal method on LocalVariablesSorter, and
+can get the stack map frame state before each instruction by reading the locals
+and stack fields in AnalyzerAdapter (this requires references from MyAdapter
+back to LocalVariablesSorter and AnalyzerAdapter).
+</body>
\ 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/optimizer/AnnotationConstantsCollector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/AnnotationConstantsCollector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/AnnotationConstantsCollector.java
new file mode 100644
index 0000000..84aff49
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/AnnotationConstantsCollector.java
@@ -0,0 +1,147 @@
+/***
+ * 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.optimizer;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * An {@link AnnotationVisitor} that collects the {@link Constant}s of the
+ * annotations it visits.
+ * 
+ * @author Eric Bruneton
+ */
+public class AnnotationConstantsCollector extends AnnotationVisitor {
+
+    private final ConstantPool cp;
+
+    public AnnotationConstantsCollector(final AnnotationVisitor av,
+            final ConstantPool cp) {
+        super(Opcodes.ASM5, av);
+        this.cp = cp;
+    }
+
+    @Override
+    public void visit(final String name, final Object value) {
+        if (name != null) {
+            cp.newUTF8(name);
+        }
+        if (value instanceof Byte) {
+            cp.newInteger(((Byte) value).byteValue());
+        } else if (value instanceof Boolean) {
+            cp.newInteger(((Boolean) value).booleanValue() ? 1 : 0);
+        } else if (value instanceof Character) {
+            cp.newInteger(((Character) value).charValue());
+        } else if (value instanceof Short) {
+            cp.newInteger(((Short) value).shortValue());
+        } else if (value instanceof Type) {
+            cp.newUTF8(((Type) value).getDescriptor());
+        } else if (value instanceof byte[]) {
+            byte[] v = (byte[]) value;
+            for (int i = 0; i < v.length; i++) {
+                cp.newInteger(v[i]);
+            }
+        } else if (value instanceof boolean[]) {
+            boolean[] v = (boolean[]) value;
+            for (int i = 0; i < v.length; i++) {
+                cp.newInteger(v[i] ? 1 : 0);
+            }
+        } else if (value instanceof short[]) {
+            short[] v = (short[]) value;
+            for (int i = 0; i < v.length; i++) {
+                cp.newInteger(v[i]);
+            }
+        } else if (value instanceof char[]) {
+            char[] v = (char[]) value;
+            for (int i = 0; i < v.length; i++) {
+                cp.newInteger(v[i]);
+            }
+        } else if (value instanceof int[]) {
+            int[] v = (int[]) value;
+            for (int i = 0; i < v.length; i++) {
+                cp.newInteger(v[i]);
+            }
+        } else if (value instanceof long[]) {
+            long[] v = (long[]) value;
+            for (int i = 0; i < v.length; i++) {
+                cp.newLong(v[i]);
+            }
+        } else if (value instanceof float[]) {
+            float[] v = (float[]) value;
+            for (int i = 0; i < v.length; i++) {
+                cp.newFloat(v[i]);
+            }
+        } else if (value instanceof double[]) {
+            double[] v = (double[]) value;
+            for (int i = 0; i < v.length; i++) {
+                cp.newDouble(v[i]);
+            }
+        } else {
+            cp.newConst(value);
+        }
+        av.visit(name, value);
+    }
+
+    @Override
+    public void visitEnum(final String name, final String desc,
+            final String value) {
+        if (name != null) {
+            cp.newUTF8(name);
+        }
+        cp.newUTF8(desc);
+        cp.newUTF8(value);
+        av.visitEnum(name, desc, value);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String name,
+            final String desc) {
+        if (name != null) {
+            cp.newUTF8(name);
+        }
+        cp.newUTF8(desc);
+        return new AnnotationConstantsCollector(av.visitAnnotation(name, desc),
+                cp);
+    }
+
+    @Override
+    public AnnotationVisitor visitArray(final String name) {
+        if (name != null) {
+            cp.newUTF8(name);
+        }
+        return new AnnotationConstantsCollector(av.visitArray(name), cp);
+    }
+
+    @Override
+    public void visitEnd() {
+        av.visitEnd();
+    }
+}


[12/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassConstantsCollector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassConstantsCollector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassConstantsCollector.java
new file mode 100644
index 0000000..b907322
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassConstantsCollector.java
@@ -0,0 +1,198 @@
+/***
+ * 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.optimizer;
+
+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.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A {@link ClassVisitor} that collects the {@link Constant}s of the classes it
+ * visits.
+ * 
+ * @author Eric Bruneton
+ */
+public class ClassConstantsCollector extends ClassVisitor {
+
+    private final ConstantPool cp;
+
+    public ClassConstantsCollector(final ClassVisitor cv, final ConstantPool cp) {
+        super(Opcodes.ASM5, cv);
+        this.cp = cp;
+    }
+
+    @Override
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            cp.newUTF8("Deprecated");
+        }
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            cp.newUTF8("Synthetic");
+        }
+        cp.newClass(name);
+        if (signature != null) {
+            cp.newUTF8("Signature");
+            cp.newUTF8(signature);
+        }
+        if (superName != null) {
+            cp.newClass(superName);
+        }
+        if (interfaces != null) {
+            for (int i = 0; i < interfaces.length; ++i) {
+                cp.newClass(interfaces[i]);
+            }
+        }
+        cv.visit(version, access, name, signature, superName, interfaces);
+    }
+
+    @Override
+    public void visitSource(final String source, final String debug) {
+        if (source != null) {
+            cp.newUTF8("SourceFile");
+            cp.newUTF8(source);
+        }
+        if (debug != null) {
+            cp.newUTF8("SourceDebugExtension");
+        }
+        cv.visitSource(source, debug);
+    }
+
+    @Override
+    public void visitOuterClass(final String owner, final String name,
+            final String desc) {
+        cp.newUTF8("EnclosingMethod");
+        cp.newClass(owner);
+        if (name != null && desc != null) {
+            cp.newNameType(name, desc);
+        }
+        cv.visitOuterClass(owner, name, desc);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleAnnotations");
+        }
+        return new AnnotationConstantsCollector(cv.visitAnnotation(desc,
+                visible), cp);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleTypeAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+        }
+        return new AnnotationConstantsCollector(cv.visitAnnotation(desc,
+                visible), cp);
+    }
+
+    @Override
+    public void visitAttribute(final Attribute attr) {
+        // can do nothing
+        cv.visitAttribute(attr);
+    }
+
+    @Override
+    public void visitInnerClass(final String name, final String outerName,
+            final String innerName, final int access) {
+        cp.newUTF8("InnerClasses");
+        if (name != null) {
+            cp.newClass(name);
+        }
+        if (outerName != null) {
+            cp.newClass(outerName);
+        }
+        if (innerName != null) {
+            cp.newUTF8(innerName);
+        }
+        cv.visitInnerClass(name, outerName, innerName, access);
+    }
+
+    @Override
+    public FieldVisitor visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            cp.newUTF8("Synthetic");
+        }
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            cp.newUTF8("Deprecated");
+        }
+        cp.newUTF8(name);
+        cp.newUTF8(desc);
+        if (signature != null) {
+            cp.newUTF8("Signature");
+            cp.newUTF8(signature);
+        }
+        if (value != null) {
+            cp.newConst(value);
+        }
+        return new FieldConstantsCollector(cv.visitField(access, name, desc,
+                signature, value), cp);
+    }
+
+    @Override
+    public MethodVisitor visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            cp.newUTF8("Synthetic");
+        }
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            cp.newUTF8("Deprecated");
+        }
+        cp.newUTF8(name);
+        cp.newUTF8(desc);
+        if (signature != null) {
+            cp.newUTF8("Signature");
+            cp.newUTF8(signature);
+        }
+        if (exceptions != null) {
+            cp.newUTF8("Exceptions");
+            for (int i = 0; i < exceptions.length; ++i) {
+                cp.newClass(exceptions[i]);
+            }
+        }
+        return new MethodConstantsCollector(cv.visitMethod(access, name, desc,
+                signature, exceptions), cp);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java
new file mode 100644
index 0000000..f4a7a22
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java
@@ -0,0 +1,260 @@
+/***
+ * 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.optimizer;
+
+import java.util.ArrayList;
+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.FieldVisitor;
+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.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.commons.Remapper;
+import org.apache.tapestry5.internal.plastic.asm.commons.RemappingClassAdapter;
+
+/**
+ * A {@link ClassVisitor} that renames fields and methods, and removes debug
+ * info.
+ * 
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class ClassOptimizer extends RemappingClassAdapter {
+
+    private String pkgName;
+    String clsName;
+
+    boolean isInterface = false;
+    boolean hasClinitMethod = false;
+    List<String> syntheticClassFields = new ArrayList<String>();
+
+    public ClassOptimizer(final ClassVisitor cv, final Remapper remapper) {
+        super(Opcodes.ASM5, cv, remapper);
+    }
+
+    FieldVisitor syntheticFieldVisitor(final int access, final String name,
+            final String desc) {
+        return super.visitField(access, name, desc, null, null);
+    }
+
+    // ------------------------------------------------------------------------
+    // Overridden methods
+    // ------------------------------------------------------------------------
+
+    @Override
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
+        super.visit(Opcodes.V1_2, access, name, null, superName, interfaces);
+        int index = name.lastIndexOf('/');
+        if (index > 0) {
+            pkgName = name.substring(0, index);
+        } else {
+            pkgName = "";
+        }
+        clsName = name;
+        isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
+    }
+
+    @Override
+    public void visitSource(final String source, final String debug) {
+        // remove debug info
+    }
+
+    @Override
+    public void visitOuterClass(final String owner, final String name,
+            final String desc) {
+        // remove debug info
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        // remove annotations
+        return null;
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        // remove annotations
+        return null;
+    }
+
+    @Override
+    public void visitAttribute(final Attribute attr) {
+        // remove non standard attributes
+    }
+
+    @Override
+    public void visitInnerClass(final String name, final String outerName,
+            final String innerName, final int access) {
+        // remove debug info
+    }
+
+    @Override
+    public FieldVisitor visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
+        String s = remapper.mapFieldName(className, name, desc);
+        if ("-".equals(s)) {
+            return null;
+        }
+        if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
+            if ((access & Opcodes.ACC_FINAL) != 0
+                    && (access & Opcodes.ACC_STATIC) != 0 && desc.length() == 1) {
+                return null;
+            }
+            if ("org/objectweb/asm".equals(pkgName) && s.equals(name)) {
+                System.out.println("INFO: " + clsName + "." + s
+                        + " could be renamed");
+            }
+            super.visitField(access, name, desc, null, value);
+        } else {
+            if (!s.equals(name)) {
+                throw new RuntimeException("The public or protected field "
+                        + className + '.' + name + " must not be renamed.");
+            }
+            super.visitField(access, name, desc, null, value);
+        }
+        return null; // remove debug info
+    }
+
+    @Override
+    public MethodVisitor visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        String s = remapper.mapMethodName(className, name, desc);
+        if ("-".equals(s)) {
+            return null;
+        }
+        if (name.equals("<clinit>") && !isInterface) {
+            hasClinitMethod = true;
+            MethodVisitor mv = super.visitMethod(access, name, desc, null,
+                    exceptions);
+            return new MethodVisitor(Opcodes.ASM5, mv) {
+                @Override
+                public void visitCode() {
+                    super.visitCode();
+                    mv.visitMethodInsn(Opcodes.INVOKESTATIC, clsName,
+                            "_clinit_", "()V", false);
+                }
+            };
+        }
+
+        if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
+            if ("org/objectweb/asm".equals(pkgName) && !name.startsWith("<")
+                    && s.equals(name)) {
+                System.out.println("INFO: " + clsName + "." + s
+                        + " could be renamed");
+            }
+            return super.visitMethod(access, name, desc, null, exceptions);
+        } else {
+            if (!s.equals(name)) {
+                throw new RuntimeException("The public or protected method "
+                        + className + '.' + name + desc
+                        + " must not be renamed.");
+            }
+            return super.visitMethod(access, name, desc, null, exceptions);
+        }
+    }
+
+    @Override
+    protected MethodVisitor createRemappingMethodAdapter(int access,
+            String newDesc, MethodVisitor mv) {
+        return new MethodOptimizer(this, access, newDesc, mv, remapper);
+    }
+
+    @Override
+    public void visitEnd() {
+        if (syntheticClassFields.isEmpty()) {
+            if (hasClinitMethod) {
+                MethodVisitor mv = cv.visitMethod(Opcodes.ACC_STATIC
+                        | Opcodes.ACC_SYNTHETIC, "_clinit_", "()V", null, null);
+                mv.visitCode();
+                mv.visitInsn(Opcodes.RETURN);
+                mv.visitMaxs(0, 0);
+                mv.visitEnd();
+            }
+        } else {
+            MethodVisitor mv = cv.visitMethod(Opcodes.ACC_STATIC
+                    | Opcodes.ACC_SYNTHETIC, "class$",
+                    "(Ljava/lang/String;)Ljava/lang/Class;", null, null);
+            mv.visitCode();
+            Label l0 = new Label();
+            Label l1 = new Label();
+            Label l2 = new Label();
+            mv.visitTryCatchBlock(l0, l1, l2,
+                    "java/lang/ClassNotFoundException");
+            mv.visitLabel(l0);
+            mv.visitVarInsn(Opcodes.ALOAD, 0);
+            mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class",
+                    "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false);
+            mv.visitLabel(l1);
+            mv.visitInsn(Opcodes.ARETURN);
+            mv.visitLabel(l2);
+            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
+                    "java/lang/ClassNotFoundException", "getMessage",
+                    "()Ljava/lang/String;", false);
+            mv.visitVarInsn(Opcodes.ASTORE, 1);
+            mv.visitTypeInsn(Opcodes.NEW, "java/lang/NoClassDefFoundError");
+            mv.visitInsn(Opcodes.DUP);
+            mv.visitVarInsn(Opcodes.ALOAD, 1);
+            mv.visitMethodInsn(Opcodes.INVOKESPECIAL,
+                    "java/lang/NoClassDefFoundError", "<init>",
+                    "(Ljava/lang/String;)V", false);
+            mv.visitInsn(Opcodes.ATHROW);
+            mv.visitMaxs(3, 2);
+            mv.visitEnd();
+
+            if (hasClinitMethod) {
+                mv = cv.visitMethod(Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE,
+                        "_clinit_", "()V", null, null);
+            } else {
+                mv = cv.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V",
+                        null, null);
+            }
+            for (String ldcName : syntheticClassFields) {
+                String fieldName = "class$" + ldcName.replace('/', '$');
+                mv.visitLdcInsn(ldcName.replace('/', '.'));
+                mv.visitMethodInsn(Opcodes.INVOKESTATIC, clsName, "class$",
+                        "(Ljava/lang/String;)Ljava/lang/Class;", false);
+                mv.visitFieldInsn(Opcodes.PUTSTATIC, clsName, fieldName,
+                        "Ljava/lang/Class;");
+            }
+            mv.visitInsn(Opcodes.RETURN);
+            mv.visitMaxs(1, 0);
+            mv.visitEnd();
+        }
+        super.visitEnd();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Constant.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Constant.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Constant.java
new file mode 100644
index 0000000..9c1f306
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Constant.java
@@ -0,0 +1,323 @@
+/***
+ * 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.optimizer;
+
+import java.util.Arrays;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassWriter;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+
+/**
+ * A constant pool item.
+ * 
+ * @author Eric Bruneton
+ */
+class Constant {
+
+    /**
+     * Type of this constant pool item. A single class is used to represent all
+     * constant pool item types, in order to minimize the bytecode size of this
+     * package. The value of this field is I, J, F, D, S, s, C, T, G, M, N, y,
+     * t, [h..p] (for Constant Integer, Long, Float, Double, STR, UTF8, Class,
+     * NameType, Fieldref, Methodref, InterfaceMethodref, InvokeDynamic,
+     * MethodType and MethodHandle constant pool items respectively).
+     * 
+     * The 9 variable of MethodHandle constants are stored between h and p.
+     */
+    char type;
+
+    /**
+     * Value of this item, for an integer item.
+     */
+    int intVal;
+
+    /**
+     * Value of this item, for a long item.
+     */
+    long longVal;
+
+    /**
+     * Value of this item, for a float item.
+     */
+    float floatVal;
+
+    /**
+     * Value of this item, for a double item.
+     */
+    double doubleVal;
+
+    /**
+     * First part of the value of this item, for items that do not hold a
+     * primitive value.
+     */
+    String strVal1;
+
+    /**
+     * Second part of the value of this item, for items that do not hold a
+     * primitive value.
+     */
+    String strVal2;
+
+    /**
+     * Third part of the value of this item, for items that do not hold a
+     * primitive value.
+     */
+    Object objVal3;
+
+    /**
+     * InvokeDynamic's constant values.
+     */
+    Object[] objVals;
+
+    /**
+     * The hash code value of this constant pool item.
+     */
+    int hashCode;
+
+    Constant() {
+    }
+
+    Constant(final Constant i) {
+        type = i.type;
+        intVal = i.intVal;
+        longVal = i.longVal;
+        floatVal = i.floatVal;
+        doubleVal = i.doubleVal;
+        strVal1 = i.strVal1;
+        strVal2 = i.strVal2;
+        objVal3 = i.objVal3;
+        objVals = i.objVals;
+        hashCode = i.hashCode;
+    }
+
+    /**
+     * Sets this item to an integer item.
+     * 
+     * @param intVal
+     *            the value of this item.
+     */
+    void set(final int intVal) {
+        this.type = 'I';
+        this.intVal = intVal;
+        this.hashCode = 0x7FFFFFFF & (type + intVal);
+    }
+
+    /**
+     * Sets this item to a long item.
+     * 
+     * @param longVal
+     *            the value of this item.
+     */
+    void set(final long longVal) {
+        this.type = 'J';
+        this.longVal = longVal;
+        this.hashCode = 0x7FFFFFFF & (type + (int) longVal);
+    }
+
+    /**
+     * Sets this item to a float item.
+     * 
+     * @param floatVal
+     *            the value of this item.
+     */
+    void set(final float floatVal) {
+        this.type = 'F';
+        this.floatVal = floatVal;
+        this.hashCode = 0x7FFFFFFF & (type + (int) floatVal);
+    }
+
+    /**
+     * Sets this item to a double item.
+     * 
+     * @param doubleVal
+     *            the value of this item.
+     */
+    void set(final double doubleVal) {
+        this.type = 'D';
+        this.doubleVal = doubleVal;
+        this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal);
+    }
+
+    /**
+     * Sets this item to an item that do not hold a primitive value.
+     * 
+     * @param type
+     *            the type of this item.
+     * @param strVal1
+     *            first part of the value of this item.
+     * @param strVal2
+     *            second part of the value of this item.
+     * @param strVal3
+     *            third part of the value of this item.
+     */
+    void set(final char type, final String strVal1, final String strVal2,
+            final String strVal3) {
+        this.type = type;
+        this.strVal1 = strVal1;
+        this.strVal2 = strVal2;
+        this.objVal3 = strVal3;
+        switch (type) {
+        case 's':
+        case 'S':
+        case 'C':
+        case 't':
+            hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
+            return;
+        case 'T':
+            hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+                    * strVal2.hashCode());
+            return;
+            // case 'G':
+            // case 'M':
+            // case 'N':
+            // case 'h' ... 'p':
+        default:
+            hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+                    * strVal2.hashCode() * strVal3.hashCode());
+        }
+    }
+
+    /**
+     * Set this item to an InvokeDynamic item.
+     * 
+     * @param name
+     *            invokedynamic's name.
+     * @param desc
+     *            invokedynamic's descriptor.
+     * @param bsm
+     *            bootstrap method.
+     * @param bsmArgs
+     *            bootstrap method constant arguments.
+     */
+    void set(final String name, final String desc, final Handle bsm,
+            final Object[] bsmArgs) {
+        this.type = 'y';
+        this.strVal1 = name;
+        this.strVal2 = desc;
+        this.objVal3 = bsm;
+        this.objVals = bsmArgs;
+
+        int hashCode = 'y' + name.hashCode() * desc.hashCode() * bsm.hashCode();
+        for (int i = 0; i < bsmArgs.length; i++) {
+            hashCode *= bsmArgs[i].hashCode();
+        }
+        this.hashCode = 0x7FFFFFFF & hashCode;
+    }
+
+    void write(final ClassWriter cw) {
+        switch (type) {
+        case 'I':
+            cw.newConst(new Integer(intVal));
+            break;
+        case 'J':
+            cw.newConst(new Long(longVal));
+            break;
+        case 'F':
+            cw.newConst(new Float(floatVal));
+            break;
+        case 'D':
+            cw.newConst(new Double(doubleVal));
+            break;
+        case 'S':
+            cw.newConst(strVal1);
+            break;
+        case 's':
+            cw.newUTF8(strVal1);
+            break;
+        case 'C':
+            cw.newClass(strVal1);
+            break;
+        case 'T':
+            cw.newNameType(strVal1, strVal2);
+            break;
+        case 'G':
+            cw.newField(strVal1, strVal2, (String) objVal3);
+            break;
+        case 'M':
+            cw.newMethod(strVal1, strVal2, (String) objVal3, false);
+            break;
+        case 'N':
+            cw.newMethod(strVal1, strVal2, (String) objVal3, true);
+            break;
+        case 'y':
+            cw.newInvokeDynamic(strVal1, strVal2, (Handle) objVal3, objVals);
+            break;
+        case 't':
+            cw.newMethodType(strVal1);
+            break;
+        default: // 'h' ... 'p': handle
+            cw.newHandle(type - 'h' + 1, strVal1, strVal2, (String) objVal3);
+        }
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (!(o instanceof Constant)) {
+            return false;
+        }
+        Constant c = (Constant) o;
+        if (c.type == type) {
+            switch (type) {
+            case 'I':
+                return c.intVal == intVal;
+            case 'J':
+                return c.longVal == longVal;
+            case 'F':
+                return Float.compare(c.floatVal, floatVal) == 0;
+            case 'D':
+                return Double.compare(c.doubleVal, doubleVal) == 0;
+            case 's':
+            case 'S':
+            case 'C':
+            case 't':
+                return c.strVal1.equals(strVal1);
+            case 'T':
+                return c.strVal1.equals(strVal1) && c.strVal2.equals(strVal2);
+            case 'y':
+                return c.strVal1.equals(strVal1) && c.strVal2.equals(strVal2)
+                        && c.objVal3.equals(objVal3)
+                        && Arrays.equals(c.objVals, objVals);
+                // case 'G':
+                // case 'M':
+                // case 'N':
+                // case 'h' ... 'p':
+            default:
+                return c.strVal1.equals(strVal1) && c.strVal2.equals(strVal2)
+                        && c.objVal3.equals(objVal3);
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return hashCode;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ConstantPool.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ConstantPool.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ConstantPool.java
new file mode 100644
index 0000000..1901387
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ConstantPool.java
@@ -0,0 +1,249 @@
+/***
+ * 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.optimizer;
+
+import java.util.HashMap;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A constant pool.
+ * 
+ * @author Eric Bruneton
+ */
+public class ConstantPool extends HashMap<Constant, Constant> {
+
+    private final Constant key1 = new Constant();
+
+    private final Constant key2 = new Constant();
+
+    private final Constant key3 = new Constant();
+
+    private final Constant key4 = new Constant();
+
+    private final Constant key5 = new Constant();
+
+    public Constant newInteger(final int value) {
+        key1.set(value);
+        Constant result = get(key1);
+        if (result == null) {
+            result = new Constant(key1);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newFloat(final float value) {
+        key1.set(value);
+        Constant result = get(key1);
+        if (result == null) {
+            result = new Constant(key1);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newLong(final long value) {
+        key1.set(value);
+        Constant result = get(key1);
+        if (result == null) {
+            result = new Constant(key1);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newDouble(final double value) {
+        key1.set(value);
+        Constant result = get(key1);
+        if (result == null) {
+            result = new Constant(key1);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newUTF8(final String value) {
+        key1.set('s', value, null, null);
+        Constant result = get(key1);
+        if (result == null) {
+            result = new Constant(key1);
+            put(result);
+        }
+        return result;
+    }
+
+    private Constant newString(final String value) {
+        key2.set('S', value, null, null);
+        Constant result = get(key2);
+        if (result == null) {
+            newUTF8(value);
+            result = new Constant(key2);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newClass(final String value) {
+        key2.set('C', value, null, null);
+        Constant result = get(key2);
+        if (result == null) {
+            newUTF8(value);
+            result = new Constant(key2);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newMethodType(final String methodDescriptor) {
+        key2.set('t', methodDescriptor, null, null);
+        Constant result = get(key2);
+        if (result == null) {
+            newUTF8(methodDescriptor);
+            result = new Constant(key2);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newHandle(final int tag, final String owner,
+            final String name, final String desc) {
+        key4.set((char) ('h' - 1 + tag), owner, name, desc);
+        Constant result = get(key4);
+        if (result == null) {
+            if (tag <= Opcodes.H_PUTSTATIC) {
+                newField(owner, name, desc);
+            } else {
+                newMethod(owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE);
+            }
+            result = new Constant(key4);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newConst(final Object cst) {
+        if (cst instanceof Integer) {
+            int val = ((Integer) cst).intValue();
+            return newInteger(val);
+        } else if (cst instanceof Float) {
+            float val = ((Float) cst).floatValue();
+            return newFloat(val);
+        } else if (cst instanceof Long) {
+            long val = ((Long) cst).longValue();
+            return newLong(val);
+        } else if (cst instanceof Double) {
+            double val = ((Double) cst).doubleValue();
+            return newDouble(val);
+        } else if (cst instanceof String) {
+            return newString((String) cst);
+        } else if (cst instanceof Type) {
+            Type t = (Type) cst;
+            int s = t.getSort();
+            if (s == Type.OBJECT) {
+                return newClass(t.getInternalName());
+            } else if (s == Type.METHOD) {
+                return newMethodType(t.getDescriptor());
+            } else { // s == primitive type or array
+                return newClass(t.getDescriptor());
+            }
+        } else if (cst instanceof Handle) {
+            Handle h = (Handle) cst;
+            return newHandle(h.getTag(), h.getOwner(), h.getName(), h.getDesc());
+        } else {
+            throw new IllegalArgumentException("value " + cst);
+        }
+    }
+
+    public Constant newField(final String owner, final String name,
+            final String desc) {
+        key3.set('G', owner, name, desc);
+        Constant result = get(key3);
+        if (result == null) {
+            newClass(owner);
+            newNameType(name, desc);
+            result = new Constant(key3);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newMethod(final String owner, final String name,
+            final String desc, final boolean itf) {
+        key3.set(itf ? 'N' : 'M', owner, name, desc);
+        Constant result = get(key3);
+        if (result == null) {
+            newClass(owner);
+            newNameType(name, desc);
+            result = new Constant(key3);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newInvokeDynamic(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        key5.set(name, desc, bsm, bsmArgs);
+        Constant result = get(key5);
+        if (result == null) {
+            newNameType(name, desc);
+            newHandle(bsm.getTag(), bsm.getOwner(), bsm.getName(),
+                    bsm.getDesc());
+            for (int i = 0; i < bsmArgs.length; i++) {
+                newConst(bsmArgs[i]);
+            }
+            result = new Constant(key5);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newNameType(final String name, final String desc) {
+        key2.set('T', name, desc, null);
+        Constant result = get(key2);
+        if (result == null) {
+            newUTF8(name);
+            newUTF8(desc);
+            result = new Constant(key2);
+            put(result);
+        }
+        return result;
+    }
+
+    private Constant get(final Constant key) {
+        return get((Object) key);
+    }
+
+    private void put(final Constant cst) {
+        put(cst, cst);
+    }
+}
\ 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/optimizer/FieldConstantsCollector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/FieldConstantsCollector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/FieldConstantsCollector.java
new file mode 100644
index 0000000..63ca654
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/FieldConstantsCollector.java
@@ -0,0 +1,89 @@
+/***
+ * 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.optimizer;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A {@link FieldVisitor} that collects the {@link Constant}s of the fields it
+ * visits.
+ * 
+ * @author Eric Bruneton
+ */
+public class FieldConstantsCollector extends FieldVisitor {
+
+    private final ConstantPool cp;
+
+    public FieldConstantsCollector(final FieldVisitor fv, final ConstantPool cp) {
+        super(Opcodes.ASM5, fv);
+        this.cp = cp;
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleAnnotations");
+        }
+        return new AnnotationConstantsCollector(fv.visitAnnotation(desc,
+                visible), cp);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleTypeAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+        }
+        return new AnnotationConstantsCollector(fv.visitAnnotation(desc,
+                visible), cp);
+    }
+
+    @Override
+    public void visitAttribute(final Attribute attr) {
+        // can do nothing
+        fv.visitAttribute(attr);
+    }
+
+    @Override
+    public void visitEnd() {
+        fv.visitEnd();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/JarOptimizer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/JarOptimizer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/JarOptimizer.java
new file mode 100644
index 0000000..e7d93cf
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/JarOptimizer.java
@@ -0,0 +1,235 @@
+/***
+ * 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.optimizer;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
+/**
+ * A Jar file optimizer.
+ * 
+ * @author Eric Bruneton
+ */
+public class JarOptimizer {
+
+    static final Set<String> API = new HashSet<String>();
+    static final Map<String, String> HIERARCHY = new HashMap<String, String>();
+    static boolean nodebug = false;
+
+    public static void main(final String[] args) throws IOException {
+        File f = new File(args[0]);
+        InputStream is = new GZIPInputStream(new FileInputStream(f));
+        BufferedReader lnr = new LineNumberReader(new InputStreamReader(is));
+        while (true) {
+            String line = lnr.readLine();
+            if (line != null) {
+                if (line.startsWith("class")) {
+                    String c = line.substring(6, line.lastIndexOf(' '));
+                    String sc = line.substring(line.lastIndexOf(' ') + 1);
+                    HIERARCHY.put(c, sc);
+                } else {
+                    API.add(line);
+                }
+            } else {
+                break;
+            }
+        }
+
+        int argIndex = 1;
+        if (args[argIndex].equals("-nodebug")) {
+            nodebug = true;
+            argIndex++;
+        }
+
+        optimize(new File(args[argIndex]));
+    }
+
+    static void optimize(final File f) throws IOException {
+        if (nodebug && f.getName().contains("debug")) {
+            return;
+        }
+
+        if (f.isDirectory()) {
+            File[] files = f.listFiles();
+            for (int i = 0; i < files.length; ++i) {
+                optimize(files[i]);
+            }
+        } else if (f.getName().endsWith(".jar")) {
+            File g = new File(f.getParentFile(), f.getName() + ".new");
+            ZipFile zf = new ZipFile(f);
+            ZipOutputStream out = new ZipOutputStream(new FileOutputStream(g));
+            Enumeration<? extends ZipEntry> e = zf.entries();
+            byte[] buf = new byte[10000];
+            while (e.hasMoreElements()) {
+                ZipEntry ze = e.nextElement();
+                if (ze.isDirectory()) {
+                    out.putNextEntry(ze);
+                    continue;
+                }
+                out.putNextEntry(ze);
+                if (ze.getName().endsWith(".class")) {
+                    ClassReader cr = new ClassReader(zf.getInputStream(ze));
+                    // cr.accept(new ClassDump(), 0);
+                    cr.accept(new ClassVerifier(), 0);
+                }
+                InputStream is = zf.getInputStream(ze);
+                int n;
+                do {
+                    n = is.read(buf, 0, buf.length);
+                    if (n != -1) {
+                        out.write(buf, 0, n);
+                    }
+                } while (n != -1);
+                out.closeEntry();
+            }
+            out.close();
+            zf.close();
+            if (!f.delete()) {
+                throw new IOException("Cannot delete file " + f);
+            }
+            if (!g.renameTo(f)) {
+                throw new IOException("Cannot rename file " + g);
+            }
+        }
+    }
+
+    static class ClassDump extends ClassVisitor {
+
+        String owner;
+
+        public ClassDump() {
+            super(Opcodes.ASM5);
+        }
+
+        @Override
+        public void visit(final int version, final int access,
+                final String name, final String signature,
+                final String superName, final String[] interfaces) {
+            owner = name;
+            if (owner.startsWith("java/")) {
+                System.out.println("class " + name + ' ' + superName);
+            }
+        }
+
+        @Override
+        public FieldVisitor visitField(final int access, final String name,
+                final String desc, final String signature, final Object value) {
+            if (owner.startsWith("java/")) {
+                System.out.println(owner + ' ' + name);
+            }
+            return null;
+        }
+
+        @Override
+        public MethodVisitor visitMethod(final int access, final String name,
+                final String desc, final String signature,
+                final String[] exceptions) {
+            if (owner.startsWith("java/")) {
+                System.out.println(owner + ' ' + name + desc);
+            }
+            return null;
+        }
+    }
+
+    static class ClassVerifier extends ClassVisitor {
+
+        String owner;
+
+        String method;
+
+        public ClassVerifier() {
+            super(Opcodes.ASM5);
+        }
+
+        @Override
+        public void visit(final int version, final int access,
+                final String name, final String signature,
+                final String superName, final String[] interfaces) {
+            owner = name;
+        }
+
+        @Override
+        public MethodVisitor visitMethod(final int access, final String name,
+                final String desc, final String signature,
+                final String[] exceptions) {
+            method = name + desc;
+            return new MethodVisitor(Opcodes.ASM5) {
+                @Override
+                public void visitFieldInsn(final int opcode,
+                        final String owner, final String name, final String desc) {
+                    check(owner, name);
+                }
+
+                @Override
+                public void visitMethodInsn(final int opcode,
+                        final String owner, final String name,
+                        final String desc, final boolean itf) {
+                    check(owner, name + desc);
+                }
+            };
+        }
+
+        void check(String owner, String member) {
+            if (owner.startsWith("java/")) {
+                String o = owner;
+                while (o != null) {
+                    if (API.contains(o + ' ' + member)) {
+                        return;
+                    }
+                    o = HIERARCHY.get(o);
+                }
+                System.out.println("WARNING: " + owner + ' ' + member
+                        + " called in " + this.owner + ' ' + method
+                        + " is not defined in JDK 1.3 API");
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodConstantsCollector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodConstantsCollector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodConstantsCollector.java
new file mode 100644
index 0000000..54b3519
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodConstantsCollector.java
@@ -0,0 +1,224 @@
+/***
+ * 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.optimizer;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+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.TypePath;
+
+/**
+ * An {@link MethodVisitor} that collects the {@link Constant}s of the methods
+ * it visits.
+ * 
+ * @author Eric Bruneton
+ */
+public class MethodConstantsCollector extends MethodVisitor {
+
+    private final ConstantPool cp;
+
+    public MethodConstantsCollector(final MethodVisitor mv,
+            final ConstantPool cp) {
+        super(Opcodes.ASM5, mv);
+        this.cp = cp;
+    }
+
+    @Override
+    public void visitParameter(String name, int access) {
+        cp.newUTF8("MethodParameters");
+        if (name != null) {
+            cp.newUTF8(name);
+        }
+        mv.visitParameter(name, access);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotationDefault() {
+        cp.newUTF8("AnnotationDefault");
+        return new AnnotationConstantsCollector(mv.visitAnnotationDefault(), cp);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleAnnotations");
+        }
+        return new AnnotationConstantsCollector(mv.visitAnnotation(desc,
+                visible), cp);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleTypeAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+        }
+        return new AnnotationConstantsCollector(mv.visitAnnotation(desc,
+                visible), cp);
+    }
+
+    @Override
+    public AnnotationVisitor visitParameterAnnotation(final int parameter,
+            final String desc, final boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleParameterAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleParameterAnnotations");
+        }
+        return new AnnotationConstantsCollector(mv.visitParameterAnnotation(
+                parameter, desc, visible), cp);
+    }
+
+    @Override
+    public void visitTypeInsn(final int opcode, final String type) {
+        cp.newClass(type);
+        mv.visitTypeInsn(opcode, type);
+    }
+
+    @Override
+    public void visitFieldInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        cp.newField(owner, name, desc);
+        mv.visitFieldInsn(opcode, owner, name, desc);
+    }
+
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        cp.newMethod(owner, name, desc, itf);
+        mv.visitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        cp.newInvokeDynamic(name, desc, bsm, bsmArgs);
+        mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+    }
+
+    @Override
+    public void visitLdcInsn(final Object cst) {
+        cp.newConst(cst);
+        mv.visitLdcInsn(cst);
+    }
+
+    @Override
+    public void visitMultiANewArrayInsn(final String desc, final int dims) {
+        cp.newClass(desc);
+        mv.visitMultiANewArrayInsn(desc, dims);
+    }
+
+    @Override
+    public AnnotationVisitor visitInsnAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleTypeAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+        }
+        return new AnnotationConstantsCollector(mv.visitInsnAnnotation(typeRef,
+                typePath, desc, visible), cp);
+    }
+
+    @Override
+    public void visitTryCatchBlock(final Label start, final Label end,
+            final Label handler, final String type) {
+        if (type != null) {
+            cp.newClass(type);
+        }
+        mv.visitTryCatchBlock(start, end, handler, type);
+    }
+
+    @Override
+    public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleTypeAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+        }
+        return new AnnotationConstantsCollector(mv.visitTryCatchAnnotation(
+                typeRef, typePath, desc, visible), cp);
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
+        if (signature != null) {
+            cp.newUTF8("LocalVariableTypeTable");
+            cp.newUTF8(name);
+            cp.newUTF8(signature);
+        }
+        cp.newUTF8("LocalVariableTable");
+        cp.newUTF8(name);
+        cp.newUTF8(desc);
+        mv.visitLocalVariable(name, desc, signature, start, end, index);
+    }
+
+    @Override
+    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+            TypePath typePath, Label[] start, Label[] end, int[] index,
+            String desc, boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleTypeAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+        }
+        return new AnnotationConstantsCollector(
+                mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
+                        index, desc, visible), cp);
+    }
+
+    @Override
+    public void visitLineNumber(final int line, final Label start) {
+        cp.newUTF8("LineNumberTable");
+        mv.visitLineNumber(line, start);
+    }
+
+    @Override
+    public void visitMaxs(final int maxStack, final int maxLocals) {
+        cp.newUTF8("Code");
+        mv.visitMaxs(maxStack, maxLocals);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.java
new file mode 100644
index 0000000..adad6b4
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.java
@@ -0,0 +1,136 @@
+/***
+ * 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.optimizer;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+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;
+import org.apache.tapestry5.internal.plastic.asm.commons.Remapper;
+import org.apache.tapestry5.internal.plastic.asm.commons.RemappingMethodAdapter;
+
+/**
+ * A {@link MethodVisitor} that renames fields and methods, and removes debug
+ * info.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class MethodOptimizer extends RemappingMethodAdapter implements Opcodes {
+
+    private final ClassOptimizer classOptimizer;
+
+    public MethodOptimizer(ClassOptimizer classOptimizer, int access,
+            String desc, MethodVisitor mv, Remapper remapper) {
+        super(Opcodes.ASM5, access, desc, mv, remapper);
+        this.classOptimizer = classOptimizer;
+    }
+
+    // ------------------------------------------------------------------------
+    // Overridden methods
+    // ------------------------------------------------------------------------
+
+    @Override
+    public void visitParameter(String name, int access) {
+        // remove parameter info
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotationDefault() {
+        // remove annotations
+        return null;
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        // remove annotations
+        return null;
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        return null;
+    }
+
+    @Override
+    public AnnotationVisitor visitParameterAnnotation(final int parameter,
+            final String desc, final boolean visible) {
+        // remove annotations
+        return null;
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
+        // remove debug info
+    }
+
+    @Override
+    public void visitLineNumber(final int line, final Label start) {
+        // remove debug info
+    }
+
+    @Override
+    public void visitFrame(int type, int local, Object[] local2, int stack,
+            Object[] stack2) {
+        // remove frame info
+    }
+
+    @Override
+    public void visitAttribute(Attribute attr) {
+        // remove non standard attributes
+    }
+
+    @Override
+    public void visitLdcInsn(Object cst) {
+        if (!(cst instanceof Type)) {
+            super.visitLdcInsn(cst);
+            return;
+        }
+
+        // transform Foo.class for 1.2 compatibility
+        String ldcName = ((Type) cst).getInternalName();
+        String fieldName = "class$" + ldcName.replace('/', '$');
+        if (!classOptimizer.syntheticClassFields.contains(ldcName)) {
+            classOptimizer.syntheticClassFields.add(ldcName);
+            FieldVisitor fv = classOptimizer.syntheticFieldVisitor(ACC_STATIC
+                    | ACC_SYNTHETIC, fieldName, "Ljava/lang/Class;");
+            fv.visitEnd();
+        }
+
+        String clsName = classOptimizer.clsName;
+        mv.visitFieldInsn(GETSTATIC, clsName, fieldName, "Ljava/lang/Class;");
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/NameMapping.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/NameMapping.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/NameMapping.java
new file mode 100644
index 0000000..70d74f7
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/NameMapping.java
@@ -0,0 +1,114 @@
+/***
+ * 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.optimizer;
+
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A MAPPING from names to names, used to rename classes, fields and methods.
+ * 
+ * @author Eric Bruneton
+ */
+public class NameMapping {
+
+    public final Properties mapping;
+
+    public final Set<Object> unused;
+
+    public NameMapping(final String file) throws IOException {
+        mapping = new Properties();
+        InputStream is = null;
+        try {
+            is = new BufferedInputStream(new FileInputStream(file));
+            mapping.load(is);
+            unused = new HashSet<Object>(mapping.keySet());
+        } finally {
+            if (is != null) {
+                is.close();
+            }
+        }
+    }
+
+    public String map(final String name) {
+        String s = (String) mapping.get(name);
+        if (s == null) {
+            int p = name.indexOf('.');
+            if (p == -1) {
+                s = name;
+            } else {
+                int q = name.indexOf('(');
+                if (q == -1) {
+                    s = name.substring(p + 1);
+                } else {
+                    s = name.substring(p + 1, q);
+                }
+            }
+        } else {
+            unused.remove(name);
+        }
+        return s;
+    }
+
+    public String fix(final String desc) {
+        if (desc.startsWith("(")) {
+            Type[] arguments = Type.getArgumentTypes(desc);
+            Type result = Type.getReturnType(desc);
+            for (int i = 0; i < arguments.length; ++i) {
+                arguments[i] = fix(arguments[i]);
+            }
+            result = fix(result);
+            return Type.getMethodDescriptor(result, arguments);
+        } else {
+            return fix(Type.getType(desc)).getDescriptor();
+        }
+    }
+
+    private Type fix(final Type t) {
+        if (t.getSort() == Type.OBJECT) {
+            return Type.getObjectType(map(t.getInternalName()));
+        } else if (t.getSort() == Type.ARRAY) {
+            String s = fix(t.getElementType()).getDescriptor();
+            for (int i = 0; i < t.getDimensions(); ++i) {
+                s = '[' + s;
+            }
+            return Type.getType(s);
+        } else {
+            return t;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Shrinker.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Shrinker.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Shrinker.java
new file mode 100644
index 0000000..e20cf5c
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Shrinker.java
@@ -0,0 +1,283 @@
+/***
+ * 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.optimizer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.ClassWriter;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.commons.Remapper;
+import org.apache.tapestry5.internal.plastic.asm.commons.SimpleRemapper;
+
+/**
+ * A class file shrinker utility.
+ * 
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class Shrinker {
+
+    static final HashMap<String, String> MAPPING = new HashMap<String, String>();
+
+    public static void main(final String[] args) throws IOException {
+        Properties properties = new Properties();
+        int n = args.length - 1;
+        for (int i = 0; i < n - 1; ++i) {
+            properties.load(new FileInputStream(args[i]));
+        }
+
+        for (Map.Entry<Object, Object> entry : properties.entrySet()) {
+            MAPPING.put((String) entry.getKey(), (String) entry.getValue());
+        }
+
+        final Set<String> unused = new HashSet<String>(MAPPING.keySet());
+
+        File f = new File(args[n - 1]);
+        File d = new File(args[n]);
+
+        optimize(f, d, new SimpleRemapper(MAPPING) {
+            @Override
+            public String map(String key) {
+                String s = super.map(key);
+                if (s != null) {
+                    unused.remove(key);
+                }
+                return s;
+            }
+        });
+
+        Iterator<String> i = unused.iterator();
+        while (i.hasNext()) {
+            String s = i.next();
+            if (!s.endsWith("/remove")) {
+                System.out.println("INFO: unused mapping " + s);
+            }
+        }
+    }
+
+    static void optimize(final File f, final File d, final Remapper remapper)
+            throws IOException {
+        if (f.isDirectory()) {
+            File[] files = f.listFiles();
+            for (int i = 0; i < files.length; ++i) {
+                optimize(files[i], d, remapper);
+            }
+        } else if (f.getName().endsWith(".class")) {
+            ConstantPool cp = new ConstantPool();
+            ClassReader cr = new ClassReader(new FileInputStream(f));
+            ClassWriter cw = new ClassWriter(0);
+            ClassConstantsCollector ccc = new ClassConstantsCollector(cw, cp);
+            ClassOptimizer co = new ClassOptimizer(ccc, remapper);
+            cr.accept(co, ClassReader.SKIP_DEBUG);
+
+            Set<Constant> constants = new TreeSet<Constant>(
+                    new ConstantComparator());
+            constants.addAll(cp.values());
+
+            cr = new ClassReader(cw.toByteArray());
+            cw = new ClassWriter(0);
+            Iterator<Constant> i = constants.iterator();
+            while (i.hasNext()) {
+                Constant c = i.next();
+                c.write(cw);
+            }
+            cr.accept(cw, ClassReader.SKIP_DEBUG);
+
+            if (MAPPING.get(cr.getClassName() + "/remove") != null) {
+                return;
+            }
+            String n = remapper.mapType(cr.getClassName());
+            File g = new File(d, n + ".class");
+            if (!g.exists() || g.lastModified() < f.lastModified()) {
+                if (!g.getParentFile().exists() && !g.getParentFile().mkdirs()) {
+                    throw new IOException("Cannot create directory "
+                            + g.getParentFile());
+                }
+                OutputStream os = new FileOutputStream(g);
+                try {
+                    os.write(cw.toByteArray());
+                } finally {
+                    os.close();
+                }
+            }
+        }
+    }
+
+    static class ConstantComparator implements Comparator<Constant> {
+
+        public int compare(final Constant c1, final Constant c2) {
+            int d = getSort(c1) - getSort(c2);
+            if (d == 0) {
+                switch (c1.type) {
+                case 'I':
+                    return new Integer(c1.intVal).compareTo(new Integer(
+                            c2.intVal));
+                case 'J':
+                    return new Long(c1.longVal).compareTo(new Long(c2.longVal));
+                case 'F':
+                    return new Float(c1.floatVal).compareTo(new Float(
+                            c2.floatVal));
+                case 'D':
+                    return new Double(c1.doubleVal).compareTo(new Double(
+                            c2.doubleVal));
+                case 's':
+                case 'S':
+                case 'C':
+                case 't':
+                    return c1.strVal1.compareTo(c2.strVal1);
+                case 'T':
+                    d = c1.strVal1.compareTo(c2.strVal1);
+                    if (d == 0) {
+                        d = c1.strVal2.compareTo(c2.strVal2);
+                    }
+                    break;
+                case 'y':
+                    d = c1.strVal1.compareTo(c2.strVal1);
+                    if (d == 0) {
+                        d = c1.strVal2.compareTo(c2.strVal2);
+                        if (d == 0) {
+                            Handle bsm1 = (Handle) c1.objVal3;
+                            Handle bsm2 = (Handle) c2.objVal3;
+                            d = compareHandle(bsm1, bsm2);
+                            if (d == 0) {
+                                d = compareObjects(c1.objVals, c2.objVals);
+                            }
+                        }
+                    }
+                    break;
+
+                default:
+                    d = c1.strVal1.compareTo(c2.strVal1);
+                    if (d == 0) {
+                        d = c1.strVal2.compareTo(c2.strVal2);
+                        if (d == 0) {
+                            d = ((String) c1.objVal3)
+                                    .compareTo((String) c2.objVal3);
+                        }
+                    }
+                }
+            }
+            return d;
+        }
+
+        private static int compareHandle(Handle h1, Handle h2) {
+            int d = h1.getTag() - h2.getTag();
+            if (d == 0) {
+                d = h1.getOwner().compareTo(h2.getOwner());
+                if (d == 0) {
+                    d = h1.getName().compareTo(h2.getName());
+                    if (d == 0) {
+                        d = h1.getDesc().compareTo(h2.getDesc());
+                    }
+                }
+            }
+            return d;
+        }
+
+        private static int compareType(Type mtype1, Type mtype2) {
+            return mtype1.getDescriptor().compareTo(mtype2.getDescriptor());
+        }
+
+        private static int compareObjects(Object[] objVals1, Object[] objVals2) {
+            int length = objVals1.length;
+            int d = length - objVals2.length;
+            if (d == 0) {
+                for (int i = 0; i < length; i++) {
+                    Object objVal1 = objVals1[i];
+                    Object objVal2 = objVals2[i];
+                    d = objVal1.getClass().getName()
+                            .compareTo(objVal2.getClass().getName());
+                    if (d == 0) {
+                        if (objVal1 instanceof Type) {
+                            d = compareType((Type) objVal1, (Type) objVal2);
+                        } else if (objVal1 instanceof Handle) {
+                            d = compareHandle((Handle) objVal1,
+                                    (Handle) objVal2);
+                        } else {
+                            d = ((Comparable) objVal1).compareTo(objVal2);
+                        }
+                    }
+
+                    if (d != 0) {
+                        return d;
+                    }
+                }
+            }
+            return 0;
+        }
+
+        private static int getSort(final Constant c) {
+            switch (c.type) {
+            case 'I':
+                return 0;
+            case 'J':
+                return 1;
+            case 'F':
+                return 2;
+            case 'D':
+                return 3;
+            case 's':
+                return 4;
+            case 'S':
+                return 5;
+            case 'C':
+                return 6;
+            case 'T':
+                return 7;
+            case 'G':
+                return 8;
+            case 'M':
+                return 9;
+            case 'N':
+                return 10;
+            case 'y':
+                return 11;
+            case 't':
+                return 12;
+            default:
+                return 100 + c.type - 'h';
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.2.2_017.txt.gz
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.2.2_017.txt.gz b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.2.2_017.txt.gz
new file mode 100644
index 0000000..39cdf9d
Binary files /dev/null and b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.2.2_017.txt.gz differ

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.3.1_19.txt.gz
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.3.1_19.txt.gz b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.3.1_19.txt.gz
new file mode 100644
index 0000000..a3c7aa6
Binary files /dev/null and b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.3.1_19.txt.gz differ

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-annotations.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-annotations.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-annotations.properties
new file mode 100644
index 0000000..03fec2e
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-annotations.properties
@@ -0,0 +1,53 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+org/objectweb/asm/AnnotationWriter/remove=true
+
+# field mappings
+
+org/objectweb/asm/ClassWriter.anns=-
+org/objectweb/asm/ClassWriter.ianns=-
+
+org/objectweb/asm/FieldWriter.anns=-
+org/objectweb/asm/FieldWriter.ianns=-
+
+org/objectweb/asm/MethodWriter.annd=-
+org/objectweb/asm/MethodWriter.anns=-
+org/objectweb/asm/MethodWriter.ianns=-
+org/objectweb/asm/MethodWriter.panns=-
+org/objectweb/asm/MethodWriter.ipanns=-
+
+# method mappings
+
+org/objectweb/asm/ClassReader.readAnnotationValue(I[CLjava/lang/String;Lorg/objectweb/asm/AnnotationVisitor;)I=-
+org/objectweb/asm/ClassReader.readAnnotationValues(I[CZLorg/objectweb/asm/AnnotationVisitor;)I=-
+org/objectweb/asm/ClassReader.readParameterAnnotations(I[CZLorg/objectweb/asm/MethodVisitor;)V=-


[17/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/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 ac7c671..d899c5e 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
@@ -37,7 +37,7 @@ 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
  */
@@ -46,6 +46,7 @@ public interface Opcodes {
     // ASM API versions
 
     int ASM4 = 4 << 16 | 0 << 8 | 0;
+    int ASM5 = 5 << 16 | 0 << 8 | 0;
 
     // versions
 
@@ -56,6 +57,7 @@ public interface Opcodes {
     int V1_5 = 0 << 16 | 49;
     int V1_6 = 0 << 16 | 50;
     int V1_7 = 0 << 16 | 51;
+    int V1_8 = 0 << 16 | 52;
 
     // access flags
 
@@ -63,7 +65,7 @@ public interface Opcodes {
     int ACC_PRIVATE = 0x0002; // class, field, method
     int ACC_PROTECTED = 0x0004; // class, field, method
     int ACC_STATIC = 0x0008; // field, method
-    int ACC_FINAL = 0x0010; // class, field, method
+    int ACC_FINAL = 0x0010; // class, field, method, parameter
     int ACC_SUPER = 0x0020; // class
     int ACC_SYNCHRONIZED = 0x0020; // method
     int ACC_VOLATILE = 0x0040; // field
@@ -74,9 +76,10 @@ public interface Opcodes {
     int ACC_INTERFACE = 0x0200; // class
     int ACC_ABSTRACT = 0x0400; // class, method
     int ACC_STRICT = 0x0800; // method
-    int ACC_SYNTHETIC = 0x1000; // class, field, method
+    int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter
     int ACC_ANNOTATION = 0x2000; // class
     int ACC_ENUM = 0x4000; // class(?) field inner
+    int ACC_MANDATED = 0x8000; // parameter
 
     // ASM specific pseudo access flags
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/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 6011aa4..0b526a0 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
@@ -35,7 +35,7 @@ import java.lang.reflect.Method;
 /**
  * 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
  */
@@ -189,14 +189,17 @@ 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.
-     * @param len the length of this descriptor.
-     */
-    private Type(final int sort, final char[] buf, final int off, final int len)
-    {
+     * 
+     * @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.
+     * @param len
+     *            the length of this descriptor.
+     */
+    private Type(final int sort, final char[] buf, final int off, final int len) {
         this.sort = sort;
         this.buf = buf;
         this.off = off;
@@ -205,8 +208,9 @@ public class Type {
 
     /**
      * Returns the Java type corresponding to the given type descriptor.
-     *
-     * @param typeDescriptor a field or method 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) {
@@ -215,8 +219,9 @@ public class Type {
 
     /**
      * Returns the Java type corresponding to the given internal name.
-     *
-     * @param internalName an internal name.
+     * 
+     * @param internalName
+     *            an internal name.
      * @return the Java type corresponding to the given internal name.
      */
     public static Type getObjectType(final String internalName) {
@@ -227,8 +232,9 @@ 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.
+     * 
+     * @param methodDescriptor
+     *            a method descriptor.
      * @return the Java type corresponding to the given method descriptor.
      */
     public static Type getMethodType(final String methodDescriptor) {
@@ -238,19 +244,24 @@ public class Type {
     /**
      * 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.
+     * 
+     * @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) {
+    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.
+     * 
+     * @param c
+     *            a class.
      * @return the Java type corresponding to the given class.
      */
     public static Type getType(final Class<?> c) {
@@ -281,8 +292,9 @@ public class Type {
 
     /**
      * Returns the Java method type corresponding to the given constructor.
-     *
-     * @param c a {@link Constructor Constructor} object.
+     * 
+     * @param c
+     *            a {@link Constructor Constructor} object.
      * @return the Java method type corresponding to the given constructor.
      */
     public static Type getType(final Constructor<?> c) {
@@ -291,8 +303,9 @@ public class Type {
 
     /**
      * Returns the Java method type corresponding to the given method.
-     *
-     * @param m a {@link Method Method} object.
+     * 
+     * @param m
+     *            a {@link Method Method} object.
      * @return the Java method type corresponding to the given method.
      */
     public static Type getType(final Method m) {
@@ -302,8 +315,9 @@ public class Type {
     /**
      * Returns the Java types corresponding to the argument types of the given
      * method descriptor.
-     *
-     * @param methodDescriptor a method descriptor.
+     * 
+     * @param methodDescriptor
+     *            a method descriptor.
      * @return the Java types corresponding to the argument types of the given
      *         method descriptor.
      */
@@ -337,8 +351,9 @@ public class Type {
     /**
      * Returns the Java types corresponding to the argument types of the given
      * method.
-     *
-     * @param method a method.
+     * 
+     * @param method
+     *            a method.
      * @return the Java types corresponding to the argument types of the given
      *         method.
      */
@@ -354,8 +369,9 @@ public class Type {
     /**
      * Returns the Java type corresponding to the return type of the given
      * method descriptor.
-     *
-     * @param methodDescriptor a method descriptor.
+     * 
+     * @param methodDescriptor
+     *            a method descriptor.
      * @return the Java type corresponding to the return type of the given
      *         method descriptor.
      */
@@ -367,8 +383,9 @@ public class Type {
     /**
      * Returns the Java type corresponding to the return type of the given
      * method.
-     *
-     * @param method a method.
+     * 
+     * @param method
+     *            a method.
      * @return the Java type corresponding to the return type of the given
      *         method.
      */
@@ -378,13 +395,14 @@ public class Type {
 
     /**
      * Computes the size of the arguments and of the return value of a method.
-     *
-     * @param desc the descriptor 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
      *         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>).
+     *         <tt>(argSize &lt;&lt; 2) | retSize</tt> (argSize is therefore equal to
+     *         <tt>i &gt;&gt; 2</tt>, and retSize to <tt>i &amp; 0x03</tt>).
      */
     public static int getArgumentsAndReturnSizes(final String desc) {
         int n = 1;
@@ -418,53 +436,55 @@ public class Type {
      * 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.
+     * 
+     * @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.
      */
     private static Type getType(final char[] buf, final int off) {
         int len;
         switch (buf[off]) {
-            case 'V':
-                return VOID_TYPE;
-            case 'Z':
-                return BOOLEAN_TYPE;
-            case 'C':
-                return CHAR_TYPE;
-            case 'B':
-                return BYTE_TYPE;
-            case 'S':
-                return SHORT_TYPE;
-            case 'I':
-                return INT_TYPE;
-            case 'F':
-                return FLOAT_TYPE;
-            case 'J':
-                return LONG_TYPE;
-            case 'D':
-                return DOUBLE_TYPE;
-            case '[':
-                len = 1;
-                while (buf[off + len] == '[') {
-                    ++len;
-                }
-                if (buf[off + len] == 'L') {
-                    ++len;
-                    while (buf[off + len] != ';') {
-                        ++len;
-                    }
-                }
-                return new Type(ARRAY, buf, off, len + 1);
-            case 'L':
-                len = 1;
+        case 'V':
+            return VOID_TYPE;
+        case 'Z':
+            return BOOLEAN_TYPE;
+        case 'C':
+            return CHAR_TYPE;
+        case 'B':
+            return BYTE_TYPE;
+        case 'S':
+            return SHORT_TYPE;
+        case 'I':
+            return INT_TYPE;
+        case 'F':
+            return FLOAT_TYPE;
+        case 'J':
+            return LONG_TYPE;
+        case 'D':
+            return DOUBLE_TYPE;
+        case '[':
+            len = 1;
+            while (buf[off + len] == '[') {
+                ++len;
+            }
+            if (buf[off + len] == 'L') {
+                ++len;
                 while (buf[off + len] != ';') {
                     ++len;
                 }
-                return new Type(OBJECT, buf, off + 1, len - 1);
+            }
+            return new Type(ARRAY, buf, off, len + 1);
+        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);
+        default:
+            return new Type(METHOD, buf, off, buf.length - off);
         }
     }
 
@@ -474,12 +494,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},
-     *         {@link #OBJECT OBJECT} or {@link #METHOD METHOD}.
+     * 
+     * @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}, {@link #OBJECT OBJECT} or {@link #METHOD
+     *         METHOD}.
      */
     public int getSort() {
         return sort;
@@ -488,7 +508,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() {
@@ -502,7 +522,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() {
@@ -512,39 +532,39 @@ public class 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) {
-            case VOID:
-                return "void";
-            case BOOLEAN:
-                return "boolean";
-            case CHAR:
-                return "char";
-            case BYTE:
-                return "byte";
-            case SHORT:
-                return "short";
-            case INT:
-                return "int";
-            case FLOAT:
-                return "float";
-            case LONG:
-                return "long";
-            case DOUBLE:
-                return "double";
-            case ARRAY:
-                StringBuffer b = new StringBuffer(getElementType().getClassName());
-                for (int i = getDimensions(); i > 0; --i) {
-                    b.append("[]");
-                }
-                return b.toString();
-            case OBJECT:
-                return new String(buf, off, len).replace('/', '.');
-            default:
-                return null;
+        case VOID:
+            return "void";
+        case BOOLEAN:
+            return "boolean";
+        case CHAR:
+            return "char";
+        case BYTE:
+            return "byte";
+        case SHORT:
+            return "short";
+        case INT:
+            return "int";
+        case FLOAT:
+            return "float";
+        case LONG:
+            return "long";
+        case DOUBLE:
+            return "double";
+        case ARRAY:
+            StringBuffer b = new StringBuffer(getElementType().getClassName());
+            for (int i = getDimensions(); i > 0; --i) {
+                b.append("[]");
+            }
+            return b.toString();
+        case OBJECT:
+            return new String(buf, off, len).replace('/', '.');
+        default:
+            return null;
         }
     }
 
@@ -553,7 +573,7 @@ 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() {
@@ -563,7 +583,7 @@ public class Type {
     /**
      * 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() {
@@ -573,7 +593,7 @@ public class Type {
     /**
      * 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() {
@@ -583,12 +603,13 @@ public class Type {
     /**
      * 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>).
+     *         packed into a single
+     *         int i = <tt>(argSize &lt;&lt; 2) | retSize</tt>
+     *         (argSize is therefore equal to <tt>i &gt;&gt; 2</tt>,
+     *         and retSize to <tt>i &amp; 0x03</tt>).
      */
     public int getArgumentsAndReturnSizes() {
         return getArgumentsAndReturnSizes(getDescriptor());
@@ -600,7 +621,7 @@ public class Type {
 
     /**
      * Returns the descriptor corresponding to this Java type.
-     *
+     * 
      * @return the descriptor corresponding to this Java type.
      */
     public String getDescriptor() {
@@ -612,16 +633,16 @@ 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.
+     * 
+     * @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
      *         types.
      */
-    public static String getMethodDescriptor(
-        final Type returnType,
-        final Type... argumentTypes)
-    {
+    public static String getMethodDescriptor(final Type returnType,
+            final Type... argumentTypes) {
         StringBuffer buf = new StringBuffer();
         buf.append('(');
         for (int i = 0; i < argumentTypes.length; ++i) {
@@ -635,12 +656,14 @@ 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.
+     * 
+     * @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)
+            // descriptor is in byte 3 of 'off' for primitive types (buf ==
+            // null)
             buf.append((char) ((off & 0xFF000000) >>> 24));
         } else if (sort == OBJECT) {
             buf.append('L');
@@ -660,8 +683,9 @@ 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.
+     * 
+     * @param c
+     *            an object or array class.
      * @return the internal name of the given class.
      */
     public static String getInternalName(final Class<?> c) {
@@ -670,8 +694,9 @@ public class Type {
 
     /**
      * Returns the descriptor corresponding to the given Java type.
-     *
-     * @param c an object class, a primitive class or an array class.
+     * 
+     * @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) {
@@ -682,8 +707,9 @@ public class Type {
 
     /**
      * Returns the descriptor corresponding to the given constructor.
-     *
-     * @param c a {@link Constructor Constructor} object.
+     * 
+     * @param c
+     *            a {@link Constructor Constructor} object.
      * @return the descriptor of the given constructor.
      */
     public static String getConstructorDescriptor(final Constructor<?> c) {
@@ -698,8 +724,9 @@ public class Type {
 
     /**
      * Returns the descriptor corresponding to the given method.
-     *
-     * @param m a {@link Method Method} object.
+     * 
+     * @param m
+     *            a {@link Method Method} object.
      * @return the descriptor of the given method.
      */
     public static String getMethodDescriptor(final Method m) {
@@ -716,9 +743,11 @@ 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.
+     * 
+     * @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;
@@ -770,7 +799,7 @@ public class 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.
      */
@@ -782,10 +811,11 @@ public class 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.
+     * 
+     * @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.
      * @return an opcode that is similar to the given opcode, but adapted to
      *         this Java type. For example, if this type is <tt>float</tt> and
      *         <tt>opcode</tt> is IRETURN, this method returns FRETURN.
@@ -808,8 +838,9 @@ public class Type {
 
     /**
      * Tests if the given object is equal to this type.
-     *
-     * @param o the object to be compared 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
@@ -839,7 +870,7 @@ public class Type {
 
     /**
      * Returns a hash code value for this type.
-     *
+     * 
      * @return a hash code value for this type.
      */
     @Override
@@ -855,7 +886,7 @@ public class Type {
 
     /**
      * Returns a string representation of this type.
-     *
+     * 
      * @return the descriptor of this type.
      */
     @Override

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java
new file mode 100644
index 0000000..b772d59
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java
@@ -0,0 +1,193 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2013 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;
+
+/**
+ * The path to a type argument, wildcard bound, array element type, or static
+ * inner type within an enclosing type.
+ * 
+ * @author Eric Bruneton
+ */
+public class TypePath {
+
+    /**
+     * A type path step that steps into the element type of an array type. See
+     * {@link #getStep getStep}.
+     */
+    public final static int ARRAY_ELEMENT = 0;
+
+    /**
+     * A type path step that steps into the nested type of a class type. See
+     * {@link #getStep getStep}.
+     */
+    public final static int INNER_TYPE = 1;
+
+    /**
+     * A type path step that steps into the bound of a wildcard type. See
+     * {@link #getStep getStep}.
+     */
+    public final static int WILDCARD_BOUND = 2;
+
+    /**
+     * A type path step that steps into a type argument of a generic type. See
+     * {@link #getStep getStep}.
+     */
+    public final static int TYPE_ARGUMENT = 3;
+
+    /**
+     * The byte array where the path is stored, in Java class file format.
+     */
+    byte[] b;
+
+    /**
+     * The offset of the first byte of the type path in 'b'.
+     */
+    int offset;
+
+    /**
+     * Creates a new type path.
+     * 
+     * @param b
+     *            the byte array containing the type path in Java class file
+     *            format.
+     * @param offset
+     *            the offset of the first byte of the type path in 'b'.
+     */
+    TypePath(byte[] b, int offset) {
+        this.b = b;
+        this.offset = offset;
+    }
+
+    /**
+     * Returns the length of this path.
+     * 
+     * @return the length of this path.
+     */
+    public int getLength() {
+        return b[offset];
+    }
+
+    /**
+     * Returns the value of the given step of this path.
+     * 
+     * @param index
+     *            an index between 0 and {@link #getLength()}, exclusive.
+     * @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE
+     *         INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or
+     *         {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
+     */
+    public int getStep(int index) {
+        return b[offset + 2 * index + 1];
+    }
+
+    /**
+     * Returns the index of the type argument that the given step is stepping
+     * into. This method should only be used for steps whose value is
+     * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
+     * 
+     * @param index
+     *            an index between 0 and {@link #getLength()}, exclusive.
+     * @return the index of the type argument that the given step is stepping
+     *         into.
+     */
+    public int getStepArgument(int index) {
+        return b[offset + 2 * index + 2];
+    }
+
+    /**
+     * Converts a type path in string form, in the format used by
+     * {@link #toString()}, into a TypePath object.
+     * 
+     * @param typePath
+     *            a type path in string form, in the format used by
+     *            {@link #toString()}. May be null or empty.
+     * @return the corresponding TypePath object, or null if the path is empty.
+     */
+    public static TypePath fromString(final String typePath) {
+        if (typePath == null || typePath.length() == 0) {
+            return null;
+        }
+        int n = typePath.length();
+        ByteVector out = new ByteVector(n);
+        out.putByte(0);
+        for (int i = 0; i < n;) {
+            char c = typePath.charAt(i++);
+            if (c == '[') {
+                out.put11(ARRAY_ELEMENT, 0);
+            } else if (c == '.') {
+                out.put11(INNER_TYPE, 0);
+            } else if (c == '*') {
+                out.put11(WILDCARD_BOUND, 0);
+            } else if (c >= '0' && c <= '9') {
+                int typeArg = c - '0';
+                while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') {
+                    typeArg = typeArg * 10 + c - '0';
+                    i += 1;
+                }
+                out.put11(TYPE_ARGUMENT, typeArg);
+            }
+        }
+        out.data[0] = (byte) (out.length / 2);
+        return new TypePath(out.data, 0);
+    }
+
+    /**
+     * Returns a string representation of this type path. {@link #ARRAY_ELEMENT
+     * ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE
+     * INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps
+     * with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type
+     * argument index in decimal form.
+     */
+    @Override
+    public String toString() {
+        int length = getLength();
+        StringBuilder result = new StringBuilder(length * 2);
+        for (int i = 0; i < length; ++i) {
+            switch (getStep(i)) {
+            case ARRAY_ELEMENT:
+                result.append('[');
+                break;
+            case INNER_TYPE:
+                result.append('.');
+                break;
+            case WILDCARD_BOUND:
+                result.append('*');
+                break;
+            case TYPE_ARGUMENT:
+                result.append(getStepArgument(i));
+                break;
+            default:
+                result.append('_');
+            }
+        }
+        return result.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java
new file mode 100644
index 0000000..d518864
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java
@@ -0,0 +1,452 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2013 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;
+
+/**
+ * A reference to a type appearing in a class, field or method declaration, or
+ * on an instruction. Such a reference designates the part of the class where
+ * the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws'
+ * clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable
+ * declaration, etc).
+ * 
+ * @author Eric Bruneton
+ */
+public class TypeReference {
+
+    /**
+     * The sort of type references that target a type parameter of a generic
+     * class. See {@link #getSort getSort}.
+     */
+    public final static int CLASS_TYPE_PARAMETER = 0x00;
+
+    /**
+     * The sort of type references that target a type parameter of a generic
+     * method. See {@link #getSort getSort}.
+     */
+    public final static int METHOD_TYPE_PARAMETER = 0x01;
+
+    /**
+     * The sort of type references that target the super class of a class or one
+     * of the interfaces it implements. See {@link #getSort getSort}.
+     */
+    public final static int CLASS_EXTENDS = 0x10;
+
+    /**
+     * The sort of type references that target a bound of a type parameter of a
+     * generic class. See {@link #getSort getSort}.
+     */
+    public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11;
+
+    /**
+     * The sort of type references that target a bound of a type parameter of a
+     * generic method. See {@link #getSort getSort}.
+     */
+    public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12;
+
+    /**
+     * The sort of type references that target the type of a field. See
+     * {@link #getSort getSort}.
+     */
+    public final static int FIELD = 0x13;
+
+    /**
+     * The sort of type references that target the return type of a method. See
+     * {@link #getSort getSort}.
+     */
+    public final static int METHOD_RETURN = 0x14;
+
+    /**
+     * The sort of type references that target the receiver type of a method.
+     * See {@link #getSort getSort}.
+     */
+    public final static int METHOD_RECEIVER = 0x15;
+
+    /**
+     * The sort of type references that target the type of a formal parameter of
+     * a method. See {@link #getSort getSort}.
+     */
+    public final static int METHOD_FORMAL_PARAMETER = 0x16;
+
+    /**
+     * The sort of type references that target the type of an exception declared
+     * in the throws clause of a method. See {@link #getSort getSort}.
+     */
+    public final static int THROWS = 0x17;
+
+    /**
+     * The sort of type references that target the type of a local variable in a
+     * method. See {@link #getSort getSort}.
+     */
+    public final static int LOCAL_VARIABLE = 0x40;
+
+    /**
+     * The sort of type references that target the type of a resource variable
+     * in a method. See {@link #getSort getSort}.
+     */
+    public final static int RESOURCE_VARIABLE = 0x41;
+
+    /**
+     * The sort of type references that target the type of the exception of a
+     * 'catch' clause in a method. See {@link #getSort getSort}.
+     */
+    public final static int EXCEPTION_PARAMETER = 0x42;
+
+    /**
+     * The sort of type references that target the type declared in an
+     * 'instanceof' instruction. See {@link #getSort getSort}.
+     */
+    public final static int INSTANCEOF = 0x43;
+
+    /**
+     * The sort of type references that target the type of the object created by
+     * a 'new' instruction. See {@link #getSort getSort}.
+     */
+    public final static int NEW = 0x44;
+
+    /**
+     * The sort of type references that target the receiver type of a
+     * constructor reference. See {@link #getSort getSort}.
+     */
+    public final static int CONSTRUCTOR_REFERENCE = 0x45;
+
+    /**
+     * The sort of type references that target the receiver type of a method
+     * reference. See {@link #getSort getSort}.
+     */
+    public final static int METHOD_REFERENCE = 0x46;
+
+    /**
+     * The sort of type references that target the type declared in an explicit
+     * or implicit cast instruction. See {@link #getSort getSort}.
+     */
+    public final static int CAST = 0x47;
+
+    /**
+     * The sort of type references that target a type parameter of a generic
+     * constructor in a constructor call. See {@link #getSort getSort}.
+     */
+    public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
+
+    /**
+     * The sort of type references that target a type parameter of a generic
+     * method in a method call. See {@link #getSort getSort}.
+     */
+    public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
+
+    /**
+     * The sort of type references that target a type parameter of a generic
+     * constructor in a constructor reference. See {@link #getSort getSort}.
+     */
+    public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
+
+    /**
+     * The sort of type references that target a type parameter of a generic
+     * method in a method reference. See {@link #getSort getSort}.
+     */
+    public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
+
+    /**
+     * The type reference value in Java class file format.
+     */
+    private int value;
+
+    /**
+     * Creates a new TypeReference.
+     * 
+     * @param typeRef
+     *            the int encoded value of the type reference, as received in a
+     *            visit method related to type annotations, like
+     *            visitTypeAnnotation.
+     */
+    public TypeReference(int typeRef) {
+        this.value = typeRef;
+    }
+
+    /**
+     * Returns a type reference of the given sort.
+     * 
+     * @param sort
+     *            {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
+     *            {@link #METHOD_RECEIVER METHOD_RECEIVER},
+     *            {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
+     *            {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
+     *            {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
+     *            {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or
+     *            {@link #METHOD_REFERENCE METHOD_REFERENCE}.
+     * @return a type reference of the given sort.
+     */
+    public static TypeReference newTypeReference(int sort) {
+        return new TypeReference(sort << 24);
+    }
+
+    /**
+     * Returns a reference to a type parameter of a generic class or method.
+     * 
+     * @param sort
+     *            {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
+     *            {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
+     * @param paramIndex
+     *            the type parameter index.
+     * @return a reference to the given generic class or method type parameter.
+     */
+    public static TypeReference newTypeParameterReference(int sort,
+            int paramIndex) {
+        return new TypeReference((sort << 24) | (paramIndex << 16));
+    }
+
+    /**
+     * Returns a reference to a type parameter bound of a generic class or
+     * method.
+     * 
+     * @param sort
+     *            {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
+     *            {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
+     * @param paramIndex
+     *            the type parameter index.
+     * @param boundIndex
+     *            the type bound index within the above type parameters.
+     * @return a reference to the given generic class or method type parameter
+     *         bound.
+     */
+    public static TypeReference newTypeParameterBoundReference(int sort,
+            int paramIndex, int boundIndex) {
+        return new TypeReference((sort << 24) | (paramIndex << 16)
+                | (boundIndex << 8));
+    }
+
+    /**
+     * Returns a reference to the super class or to an interface of the
+     * 'implements' clause of a class.
+     * 
+     * @param itfIndex
+     *            the index of an interface in the 'implements' clause of a
+     *            class, or -1 to reference the super class of the class.
+     * @return a reference to the given super type of a class.
+     */
+    public static TypeReference newSuperTypeReference(int itfIndex) {
+        itfIndex &= 0xFFFF;
+        return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8));
+    }
+
+    /**
+     * Returns a reference to the type of a formal parameter of a method.
+     * 
+     * @param paramIndex
+     *            the formal parameter index.
+     * 
+     * @return a reference to the type of the given method formal parameter.
+     */
+    public static TypeReference newFormalParameterReference(int paramIndex) {
+        return new TypeReference((METHOD_FORMAL_PARAMETER << 24)
+                | (paramIndex << 16));
+    }
+
+    /**
+     * Returns a reference to the type of an exception, in a 'throws' clause of
+     * a method.
+     * 
+     * @param exceptionIndex
+     *            the index of an exception in a 'throws' clause of a method.
+     * 
+     * @return a reference to the type of the given exception.
+     */
+    public static TypeReference newExceptionReference(int exceptionIndex) {
+        return new TypeReference((THROWS << 24) | (exceptionIndex << 8));
+    }
+
+    /**
+     * Returns a reference to the type of the exception declared in a 'catch'
+     * clause of a method.
+     * 
+     * @param tryCatchBlockIndex
+     *            the index of a try catch block (using the order in which they
+     *            are visited with visitTryCatchBlock).
+     * 
+     * @return a reference to the type of the given exception.
+     */
+    public static TypeReference newTryCatchReference(int tryCatchBlockIndex) {
+        return new TypeReference((EXCEPTION_PARAMETER << 24)
+                | (tryCatchBlockIndex << 8));
+    }
+
+    /**
+     * Returns a reference to the type of a type argument in a constructor or
+     * method call or reference.
+     * 
+     * @param sort
+     *            {@link #CAST CAST},
+     *            {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+     *            CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+     *            {@link #METHOD_INVOCATION_TYPE_ARGUMENT
+     *            METHOD_INVOCATION_TYPE_ARGUMENT},
+     *            {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+     *            CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+     *            {@link #METHOD_REFERENCE_TYPE_ARGUMENT
+     *            METHOD_REFERENCE_TYPE_ARGUMENT}.
+     * @param argIndex
+     *            the type argument index.
+     * 
+     * @return a reference to the type of the given type argument.
+     */
+    public static TypeReference newTypeArgumentReference(int sort, int argIndex) {
+        return new TypeReference((sort << 24) | argIndex);
+    }
+
+    /**
+     * Returns the sort of this type reference.
+     * 
+     * @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
+     *         {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
+     *         {@link #CLASS_EXTENDS CLASS_EXTENDS},
+     *         {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND},
+     *         {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND},
+     *         {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
+     *         {@link #METHOD_RECEIVER METHOD_RECEIVER},
+     *         {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER},
+     *         {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
+     *         {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
+     *         {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER},
+     *         {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
+     *         {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE},
+     *         {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST},
+     *         {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+     *         CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+     *         {@link #METHOD_INVOCATION_TYPE_ARGUMENT
+     *         METHOD_INVOCATION_TYPE_ARGUMENT},
+     *         {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+     *         CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+     *         {@link #METHOD_REFERENCE_TYPE_ARGUMENT
+     *         METHOD_REFERENCE_TYPE_ARGUMENT}.
+     */
+    public int getSort() {
+        return value >>> 24;
+    }
+
+    /**
+     * Returns the index of the type parameter referenced by this type
+     * reference. This method must only be used for type references whose sort
+     * is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
+     * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
+     * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
+     * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
+     * 
+     * @return a type parameter index.
+     */
+    public int getTypeParameterIndex() {
+        return (value & 0x00FF0000) >> 16;
+    }
+
+    /**
+     * Returns the index of the type parameter bound, within the type parameter
+     * {@link #getTypeParameterIndex}, referenced by this type reference. This
+     * method must only be used for type references whose sort is
+     * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
+     * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
+     * 
+     * @return a type parameter bound index.
+     */
+    public int getTypeParameterBoundIndex() {
+        return (value & 0x0000FF00) >> 8;
+    }
+
+    /**
+     * Returns the index of the "super type" of a class that is referenced by
+     * this type reference. This method must only be used for type references
+     * whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}.
+     * 
+     * @return the index of an interface in the 'implements' clause of a class,
+     *         or -1 if this type reference references the type of the super
+     *         class.
+     */
+    public int getSuperTypeIndex() {
+        return (short) ((value & 0x00FFFF00) >> 8);
+    }
+
+    /**
+     * Returns the index of the formal parameter whose type is referenced by
+     * this type reference. This method must only be used for type references
+     * whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}.
+     * 
+     * @return a formal parameter index.
+     */
+    public int getFormalParameterIndex() {
+        return (value & 0x00FF0000) >> 16;
+    }
+
+    /**
+     * Returns the index of the exception, in a 'throws' clause of a method,
+     * whose type is referenced by this type reference. This method must only be
+     * used for type references whose sort is {@link #THROWS THROWS}.
+     * 
+     * @return the index of an exception in the 'throws' clause of a method.
+     */
+    public int getExceptionIndex() {
+        return (value & 0x00FFFF00) >> 8;
+    }
+
+    /**
+     * Returns the index of the try catch block (using the order in which they
+     * are visited with visitTryCatchBlock), whose 'catch' type is referenced by
+     * this type reference. This method must only be used for type references
+     * whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} .
+     * 
+     * @return the index of an exception in the 'throws' clause of a method.
+     */
+    public int getTryCatchBlockIndex() {
+        return (value & 0x00FFFF00) >> 8;
+    }
+
+    /**
+     * Returns the index of the type argument referenced by this type reference.
+     * This method must only be used for type references whose sort is
+     * {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+     * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+     * {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT},
+     * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+     * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+     * {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}.
+     * 
+     * @return a type parameter index.
+     */
+    public int getTypeArgumentIndex() {
+        return value & 0xFF;
+    }
+
+    /**
+     * Returns the int encoded value of this type reference, suitable for use in
+     * visit methods related to type annotations, like visitTypeAnnotation.
+     * 
+     * @return the int encoded value of this type reference.
+     */
+    public int getValue() {
+        return value;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/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
new file mode 100644
index 0000000..a53995b
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java
@@ -0,0 +1,646 @@
+/***
+ * 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.commons;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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;
+
+/**
+ * A {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor} 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<Object> stackFrame;
+
+    private Map<Label, List<Object>> branches;
+
+    /**
+     * Creates a new {@link AdviceAdapter}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @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 int api, final MethodVisitor mv,
+            final int access, final String name, final String desc) {
+        super(api, mv, access, name, desc);
+        methodAccess = access;
+        methodDesc = desc;
+        constructor = "<init>".equals(name);
+    }
+
+    @Override
+    public void visitCode() {
+        mv.visitCode();
+        if (constructor) {
+            stackFrame = new ArrayList<Object>();
+            branches = new HashMap<Label, List<Object>>();
+        } else {
+            superInitialized = true;
+            onMethodEnter();
+        }
+    }
+
+    @Override
+    public void visitLabel(final Label label) {
+        mv.visitLabel(label);
+        if (constructor && branches != null) {
+            List<Object> frame = branches.get(label);
+            if (frame != null) {
+                stackFrame = frame;
+                branches.remove(label);
+            }
+        }
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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;
+            }
+        }
+    }
+
+    @Override
+    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);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void visitIntInsn(final int opcode, final int operand) {
+        mv.visitIntInsn(opcode, operand);
+        if (constructor && opcode != NEWARRAY) {
+            pushValue(OTHER);
+        }
+    }
+
+    @Override
+    public void visitLdcInsn(final Object cst) {
+        mv.visitLdcInsn(cst);
+        if (constructor) {
+            pushValue(OTHER);
+            if (cst instanceof Double || cst instanceof Long) {
+                pushValue(OTHER);
+            }
+        }
+    }
+
+    @Override
+    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);
+        }
+    }
+
+    @Override
+    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);
+        }
+    }
+
+    @Deprecated
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (api >= Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc,
+                opcode == Opcodes.INVOKEINTERFACE);
+    }
+
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    private void doVisitMethodInsn(int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        mv.visitMethodInsn(opcode, owner, name, desc, itf);
+        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:
+            // 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);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+        if (constructor) {
+            Type[] types = Type.getArgumentTypes(desc);
+            for (int i = 0; i < types.length; i++) {
+                popValue();
+                if (types[i].getSize() == 2) {
+                    popValue();
+                }
+            }
+
+            Type returnType = Type.getReturnType(desc);
+            if (returnType != Type.VOID_TYPE) {
+                pushValue(OTHER);
+                if (returnType.getSize() == 2) {
+                    pushValue(OTHER);
+                }
+            }
+        }
+    }
+
+    @Override
+    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);
+        }
+    }
+
+    @Override
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
+        mv.visitLookupSwitchInsn(dflt, keys, labels);
+        if (constructor) {
+            popValue();
+            addBranches(dflt, labels);
+        }
+    }
+
+    @Override
+    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);
+        }
+    }
+
+    @Override
+    public void visitTryCatchBlock(Label start, Label end, Label handler,
+            String type) {
+        super.visitTryCatchBlock(start, end, handler, type);
+        if (constructor && !branches.containsKey(handler)) {
+            List<Object> stackFrame = new ArrayList<Object>();
+            stackFrame.add(OTHER);
+            branches.put(handler, stackFrame);
+        }
+    }
+
+    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<Object>(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
+}


[21/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
index dced23c..8c8e29b 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
@@ -30,19 +30,20 @@
 package org.apache.tapestry5.internal.plastic.asm;
 
 /**
- * A visitor to visit a Java class. The methods of this class must be called
- * in the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
+ * A visitor to visit a Java class. The methods of this class must be called in
+ * the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
  * <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
- * <tt>visitAttribute</tt> )* ( <tt>visitInnerClass</tt> |
- * <tt>visitField</tt> | <tt>visitMethod</tt> )* <tt>visitEnd</tt>.
- *
+ * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (
+ * <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )*
+ * <tt>visitEnd</tt>.
+ * 
  * @author Eric Bruneton
  */
 public abstract class ClassVisitor {
 
     /**
      * The ASM API version implemented by this visitor. The value of this field
-     * must be one of {@link Opcodes#ASM4}.
+     * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
      */
     protected final int api;
 
@@ -54,9 +55,10 @@ public abstract class ClassVisitor {
 
     /**
      * Constructs a new {@link ClassVisitor}.
-     *
-     * @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 ClassVisitor(final int api) {
         this(api, null);
@@ -64,47 +66,49 @@ public abstract class ClassVisitor {
 
     /**
      * Constructs a new {@link ClassVisitor}.
-     *
-     * @param api the ASM API version implemented by this visitor. Must be one
-     *        of {@link Opcodes#ASM4}.
-     * @param cv the class visitor to which this visitor must delegate method
-     *        calls. May be null.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param cv
+     *            the class visitor to which this visitor must delegate method
+     *            calls. May be null.
      */
     public ClassVisitor(final int api, final ClassVisitor cv) {
-        /*if (api != Opcodes.ASM4) {
+        if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
             throw new IllegalArgumentException();
-        }*/
+        }
         this.api = api;
         this.cv = cv;
     }
 
     /**
      * Visits the header of the class.
-     *
-     * @param version the class version.
-     * @param access the class's access flags (see {@link Opcodes}). This
-     *        parameter also indicates if the class is deprecated.
-     * @param name the internal name of the class (see
-     *        {@link Type#getInternalName() getInternalName}).
-     * @param signature the signature of this class. May be <tt>null</tt> if
-     *        the class is not a generic one, and does not extend or implement
-     *        generic classes or interfaces.
-     * @param superName the internal of name of the super class (see
-     *        {@link Type#getInternalName() getInternalName}). For interfaces,
-     *        the super class is {@link Object}. May be <tt>null</tt>, but
-     *        only for the {@link Object} class.
-     * @param interfaces the internal names of the class's interfaces (see
-     *        {@link Type#getInternalName() getInternalName}). May be
-     *        <tt>null</tt>.
+     * 
+     * @param version
+     *            the class version.
+     * @param access
+     *            the class's access flags (see {@link Opcodes}). This parameter
+     *            also indicates if the class is deprecated.
+     * @param name
+     *            the internal name of the class (see
+     *            {@link Type#getInternalName() getInternalName}).
+     * @param signature
+     *            the signature of this class. May be <tt>null</tt> if the class
+     *            is not a generic one, and does not extend or implement generic
+     *            classes or interfaces.
+     * @param superName
+     *            the internal of name of the super class (see
+     *            {@link Type#getInternalName() getInternalName}). For
+     *            interfaces, the super class is {@link Object}. May be
+     *            <tt>null</tt>, but only for the {@link Object} class.
+     * @param interfaces
+     *            the internal names of the class's interfaces (see
+     *            {@link Type#getInternalName() getInternalName}). May be
+     *            <tt>null</tt>.
      */
-    public void visit(
-        int version,
-        int access,
-        String name,
-        String signature,
-        String superName,
-        String[] interfaces)
-    {
+    public void visit(int version, int access, String name, String signature,
+            String superName, String[] interfaces) {
         if (cv != null) {
             cv.visit(version, access, name, signature, superName, interfaces);
         }
@@ -112,12 +116,14 @@ public abstract class ClassVisitor {
 
     /**
      * Visits the source of the class.
-     *
-     * @param source the name of the source file from which the class was
-     *        compiled. May be <tt>null</tt>.
-     * @param debug additional debug information to compute the correspondance
-     *        between source and compiled elements of the class. May be
-     *        <tt>null</tt>.
+     * 
+     * @param source
+     *            the name of the source file from which the class was compiled.
+     *            May be <tt>null</tt>.
+     * @param debug
+     *            additional debug information to compute the correspondance
+     *            between source and compiled elements of the class. May be
+     *            <tt>null</tt>.
      */
     public void visitSource(String source, String debug) {
         if (cv != null) {
@@ -128,26 +134,31 @@ public abstract class ClassVisitor {
     /**
      * Visits the enclosing class of the class. This method must be called only
      * if the class has an enclosing class.
-     *
-     * @param owner internal name of the enclosing class of the class.
-     * @param name the name of the method that contains the class, or
-     *        <tt>null</tt> if the class is not enclosed in a method of its
-     *        enclosing class.
-     * @param desc the descriptor of the method that contains the class, or
-     *        <tt>null</tt> if the class is not enclosed in a method of its
-     *        enclosing class.
+     * 
+     * @param owner
+     *            internal name of the enclosing class of the class.
+     * @param name
+     *            the name of the method that contains the class, or
+     *            <tt>null</tt> if the class is not enclosed in a method of its
+     *            enclosing class.
+     * @param desc
+     *            the descriptor of the method that contains the class, or
+     *            <tt>null</tt> if the class is not enclosed in a method of its
+     *            enclosing class.
      */
     public void visitOuterClass(String owner, String name, String desc) {
-        if (cv != null)  {
+        if (cv != null) {
             cv.visitOuterClass(owner, name, desc);
         }
     }
 
     /**
      * Visits an annotation of the class.
-     *
-     * @param desc the class descriptor of the annotation class.
-     * @param visible <tt>true</tt> if the annotation is visible at runtime.
+     * 
+     * @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.
      */
@@ -159,9 +170,43 @@ public abstract class ClassVisitor {
     }
 
     /**
+     * Visits an annotation on a type in the class signature.
+     * 
+     * @param typeRef
+     *            a reference to the annotated type. The sort of this type
+     *            reference must be {@link TypeReference#CLASS_TYPE_PARAMETER
+     *            CLASS_TYPE_PARAMETER},
+     *            {@link TypeReference#CLASS_TYPE_PARAMETER_BOUND
+     *            CLASS_TYPE_PARAMETER_BOUND} or
+     *            {@link TypeReference#CLASS_EXTENDS CLASS_EXTENDS}. 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.
+     * @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.
+     */
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        if (api < Opcodes.ASM5) {
+            throw new RuntimeException();
+        }
+        if (cv != null) {
+            return cv.visitTypeAnnotation(typeRef, typePath, desc, visible);
+        }
+        return null;
+    }
+
+    /**
      * Visits a non standard attribute of the class.
-     *
-     * @param attr an attribute.
+     * 
+     * @param attr
+     *            an attribute.
      */
     public void visitAttribute(Attribute attr) {
         if (cv != null) {
@@ -172,24 +217,23 @@ public abstract class ClassVisitor {
     /**
      * Visits information about an inner class. This inner class is not
      * necessarily a member of the class being visited.
-     *
-     * @param name the internal name of an inner class (see
-     *        {@link Type#getInternalName() getInternalName}).
-     * @param outerName the internal name of the class to which the inner class
-     *        belongs (see {@link Type#getInternalName() getInternalName}). May
-     *        be <tt>null</tt> for not member classes.
-     * @param innerName the (simple) name of the inner class inside its
-     *        enclosing class. May be <tt>null</tt> for anonymous inner
-     *        classes.
-     * @param access the access flags of the inner class as originally declared
-     *        in the enclosing class.
+     * 
+     * @param name
+     *            the internal name of an inner class (see
+     *            {@link Type#getInternalName() getInternalName}).
+     * @param outerName
+     *            the internal name of the class to which the inner class
+     *            belongs (see {@link Type#getInternalName() getInternalName}).
+     *            May be <tt>null</tt> for not member classes.
+     * @param innerName
+     *            the (simple) name of the inner class inside its enclosing
+     *            class. May be <tt>null</tt> for anonymous inner classes.
+     * @param access
+     *            the access flags of the inner class as originally declared in
+     *            the enclosing class.
      */
-    public void visitInnerClass(
-        String name,
-        String outerName,
-        String innerName,
-        int access)
-    {
+    public void visitInnerClass(String name, String outerName,
+            String innerName, int access) {
         if (cv != null) {
             cv.visitInnerClass(name, outerName, innerName, access);
         }
@@ -197,34 +241,33 @@ public abstract class ClassVisitor {
 
     /**
      * Visits a field of the class.
-     *
-     * @param access the field's access flags (see {@link Opcodes}). This
-     *        parameter also indicates if the field is synthetic and/or
-     *        deprecated.
-     * @param name the field's name.
-     * @param desc the field's descriptor (see {@link Type Type}).
-     * @param signature the field's signature. May be <tt>null</tt> if the
-     *        field's type does not use generic types.
-     * @param value the field's initial value. This parameter, which may be
-     *        <tt>null</tt> if the field does not have an initial value, must
-     *        be an {@link Integer}, a {@link Float}, a {@link Long}, a
-     *        {@link Double} or a {@link String} (for <tt>int</tt>,
-     *        <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields
-     *        respectively). <i>This parameter is only used for static fields</i>.
-     *        Its value is ignored for non static fields, which must be
-     *        initialized through bytecode instructions in constructors or
-     *        methods.
+     * 
+     * @param access
+     *            the field's access flags (see {@link Opcodes}). This parameter
+     *            also indicates if the field is synthetic and/or deprecated.
+     * @param name
+     *            the field's name.
+     * @param desc
+     *            the field's descriptor (see {@link Type Type}).
+     * @param signature
+     *            the field's signature. May be <tt>null</tt> if the field's
+     *            type does not use generic types.
+     * @param value
+     *            the field's initial value. This parameter, which may be
+     *            <tt>null</tt> if the field does not have an initial value,
+     *            must be an {@link Integer}, a {@link Float}, a {@link Long}, a
+     *            {@link Double} or a {@link String} (for <tt>int</tt>,
+     *            <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields
+     *            respectively). <i>This parameter is only used for static
+     *            fields</i>. Its value is ignored for non static fields, which
+     *            must be initialized through bytecode instructions in
+     *            constructors or methods.
      * @return a visitor to visit field annotations and attributes, or
-     *         <tt>null</tt> if this class visitor is not interested in
-     *         visiting these annotations and attributes.
+     *         <tt>null</tt> if this class visitor is not interested in visiting
+     *         these annotations and attributes.
      */
-    public FieldVisitor visitField(
-        int access,
-        String name,
-        String desc,
-        String signature,
-        Object value)
-    {
+    public FieldVisitor visitField(int access, String name, String desc,
+            String signature, Object value) {
         if (cv != null) {
             return cv.visitField(access, name, desc, signature, value);
         }
@@ -233,31 +276,31 @@ public abstract class ClassVisitor {
 
     /**
      * Visits a method of the class. This method <i>must</i> return a new
-     * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is
-     * called, i.e., it should not return a previously returned visitor.
-     *
-     * @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 Type}).
-     * @param signature the method's signature. May be <tt>null</tt> if the
-     *        method parameters, return type and exceptions do not use generic
-     *        types.
-     * @param exceptions the internal names of the method's exception classes
-     *        (see {@link Type#getInternalName() getInternalName}). May be
-     *        <tt>null</tt>.
+     * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is called,
+     * i.e., it should not return a previously returned visitor.
+     * 
+     * @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 Type}).
+     * @param signature
+     *            the method's signature. May be <tt>null</tt> if the method
+     *            parameters, return type and exceptions do not use generic
+     *            types.
+     * @param exceptions
+     *            the internal names of the method's exception classes (see
+     *            {@link Type#getInternalName() getInternalName}). May be
+     *            <tt>null</tt>.
      * @return an object to visit the byte code of the method, or <tt>null</tt>
      *         if this class visitor is not interested in visiting the code of
      *         this method.
      */
-    public MethodVisitor visitMethod(
-        int access,
-        String name,
-        String desc,
-        String signature,
-        String[] exceptions)
-    {
+    public MethodVisitor visitMethod(int access, String name, String desc,
+            String signature, String[] exceptions) {
         if (cv != null) {
             return cv.visitMethod(access, name, desc, signature, exceptions);
         }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
index ab7547b..6cd89a5 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
@@ -35,7 +35,7 @@ package org.apache.tapestry5.internal.plastic.asm;
  * file format. It can be used alone, to generate a Java class "from scratch",
  * or with one or more {@link ClassReader ClassReader} and adapter class visitor
  * to generate a modified class from one or more existing Java classes.
- *
+ * 
  * @author Eric Bruneton
  */
 public class ClassWriter extends ClassVisitor {
@@ -47,7 +47,7 @@ public class ClassWriter extends ClassVisitor {
      * {@link MethodVisitor} returned by the {@link #visitMethod visitMethod}
      * method will be ignored, and computed automatically from the signature and
      * the bytecode of each method.
-     *
+     * 
      * @see #ClassWriter(int)
      */
     public static final int COMPUTE_MAXS = 1;
@@ -60,18 +60,24 @@ public class ClassWriter extends ClassVisitor {
      * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
      * recomputed from the bytecode. In other words, computeFrames implies
      * computeMaxs.
-     *
+     * 
      * @see #ClassWriter(int)
      */
     public static final int COMPUTE_FRAMES = 2;
 
     /**
-     * Pseudo access flag to distinguish between the synthetic attribute and
-     * the synthetic access flag.
+     * Pseudo access flag to distinguish between the synthetic attribute and the
+     * synthetic access flag.
      */
     static final int ACC_SYNTHETIC_ATTRIBUTE = 0x40000;
 
     /**
+     * Factor to convert from ACC_SYNTHETIC_ATTRIBUTE to Opcode.ACC_SYNTHETIC.
+     */
+    static final int TO_ACC_SYNTHETIC = ACC_SYNTHETIC_ATTRIBUTE
+            / Opcodes.ACC_SYNTHETIC;
+
+    /**
      * The type of instructions without any argument.
      */
     static final int NOARG_INSN = 0;
@@ -238,8 +244,8 @@ public class ClassWriter extends ClassVisitor {
 
     /**
      * The base value for all CONSTANT_MethodHandle constant pool items.
-     * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into
-     * 9 different items.
+     * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9
+     * different items.
      */
     static final int HANDLE_BASE = 20;
 
@@ -266,9 +272,8 @@ public class ClassWriter extends ClassVisitor {
     static final int TYPE_MERGED = 32;
 
     /**
-     * The type of BootstrapMethods items. These items are stored in a
-     * special class attribute named BootstrapMethods and
-     * not in the constant pool.
+     * The type of BootstrapMethods items. These items are stored in a special
+     * class attribute named BootstrapMethods and not in the constant pool.
      */
     static final int BSM = 33;
 
@@ -327,10 +332,10 @@ public class ClassWriter extends ClassVisitor {
      * necessarily be stored in the constant pool. This type table is used by
      * the control flow and data flow analysis algorithm used to compute stack
      * map frames from scratch. This array associates to each index <tt>i</tt>
-     * the Item whose index is <tt>i</tt>. All Item objects stored in this
-     * array are also stored in the {@link #items} hash table. These two arrays
-     * allow to retrieve an Item from its index or, conversely, to get the index
-     * of an Item from its value. Each Item stores an internal name in its
+     * the Item whose index is <tt>i</tt>. All Item objects stored in this array
+     * are also stored in the {@link #items} hash table. These two arrays allow
+     * to retrieve an Item from its index or, conversely, to get the index of an
+     * Item from its value. Each Item stores an internal name in its
      * {@link Item#strVal1} field.
      */
     Item[] typeTable;
@@ -412,6 +417,16 @@ public class ClassWriter extends ClassVisitor {
     private AnnotationWriter ianns;
 
     /**
+     * The runtime visible type annotations of this class.
+     */
+    private AnnotationWriter tanns;
+
+    /**
+     * The runtime invisible type annotations of this class.
+     */
+    private AnnotationWriter itanns;
+
+    /**
      * The non standard attributes of this class.
      */
     private Attribute attrs;
@@ -439,16 +454,16 @@ public class ClassWriter extends ClassVisitor {
     /**
      * The fields of this class. These fields are stored in a linked list of
      * {@link FieldWriter} objects, linked to each other by their
-     * {@link FieldWriter#fv} field. This field stores the first element of
-     * this list.
+     * {@link FieldWriter#fv} field. This field stores the first element of this
+     * list.
      */
     FieldWriter firstField;
 
     /**
      * The fields of this class. These fields are stored in a linked list of
      * {@link FieldWriter} objects, linked to each other by their
-     * {@link FieldWriter#fv} field. This field stores the last element of
-     * this list.
+     * {@link FieldWriter#fv} field. This field stores the last element of this
+     * list.
      */
     FieldWriter lastField;
 
@@ -463,8 +478,8 @@ public class ClassWriter extends ClassVisitor {
     /**
      * The methods of this class. These methods are stored in a linked list of
      * {@link MethodWriter} objects, linked to each other by their
-     * {@link MethodWriter#mv} field. This field stores the last element of
-     * this list.
+     * {@link MethodWriter#mv} field. This field stores the last element of this
+     * list.
      */
     MethodWriter lastMethod;
 
@@ -472,12 +487,12 @@ public class ClassWriter extends ClassVisitor {
      * <tt>true</tt> if the maximum stack size and number of local variables
      * must be automatically computed.
      */
-    private final boolean computeMaxs;
+    private boolean computeMaxs;
 
     /**
      * <tt>true</tt> if the stack map frames must be recomputed from scratch.
      */
-    private final boolean computeFrames;
+    private boolean computeFrames;
 
     /**
      * <tt>true</tt> if the stack map tables of this class are invalid. The
@@ -583,12 +598,14 @@ public class ClassWriter extends ClassVisitor {
 
     /**
      * Constructs a new {@link ClassWriter} object.
-     *
-     * @param flags option flags that can be used to modify the default behavior
-     *        of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
+     * 
+     * @param flags
+     *            option flags that can be used to modify the default behavior
+     *            of this class. See {@link #COMPUTE_MAXS},
+     *            {@link #COMPUTE_FRAMES}.
      */
     public ClassWriter(final int flags) {
-        super(Opcodes.ASM4);
+        super(Opcodes.ASM5);
         index = 1;
         pool = new ByteVector();
         items = new Item[256];
@@ -605,27 +622,33 @@ public class ClassWriter extends ClassVisitor {
      * Constructs a new {@link ClassWriter} object and enables optimizations for
      * "mostly add" bytecode transformations. These optimizations are the
      * following:
-     *
-     * <ul> <li>The constant pool from the original class is copied as is in the
-     * new class, which saves time. New constant pool entries will be added at
-     * the end if necessary, but unused constant pool entries <i>won't be
-     * removed</i>.</li> <li>Methods that are not transformed are copied as is
-     * in the new class, directly from the original class bytecode (i.e. without
-     * emitting visit events for all the method instructions), which saves a
-     * <i>lot</i> of time. Untransformed methods are detected by the fact that
-     * the {@link ClassReader} receives {@link MethodVisitor} objects that come
-     * from a {@link ClassWriter} (and not from any other {@link ClassVisitor}
-     * instance).</li> </ul>
-     *
-     * @param classReader the {@link ClassReader} used to read the original
-     *        class. It will be used to copy the entire constant pool from the
-     *        original class and also to copy other fragments of original
-     *        bytecode where applicable.
-     * @param flags option flags that can be used to modify the default behavior
-     *        of this class. <i>These option flags do not affect methods that
-     *        are copied as is in the new class. This means that the maximum
-     *        stack size nor the stack frames will be computed for these
-     *        methods</i>. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
+     * 
+     * <ul>
+     * <li>The constant pool from the original class is copied as is in the new
+     * class, which saves time. New constant pool entries will be added at the
+     * end if necessary, but unused constant pool entries <i>won't be
+     * removed</i>.</li>
+     * <li>Methods that are not transformed are copied as is in the new class,
+     * directly from the original class bytecode (i.e. without emitting visit
+     * events for all the method instructions), which saves a <i>lot</i> of
+     * time. Untransformed methods are detected by the fact that the
+     * {@link ClassReader} receives {@link MethodVisitor} objects that come from
+     * a {@link ClassWriter} (and not from any other {@link ClassVisitor}
+     * instance).</li>
+     * </ul>
+     * 
+     * @param classReader
+     *            the {@link ClassReader} used to read the original class. It
+     *            will be used to copy the entire constant pool from the
+     *            original class and also to copy other fragments of original
+     *            bytecode where applicable.
+     * @param flags
+     *            option flags that can be used to modify the default behavior
+     *            of this class. <i>These option flags do not affect methods
+     *            that are copied as is in the new class. This means that the
+     *            maximum stack size nor the stack frames will be computed for
+     *            these methods</i>. See {@link #COMPUTE_MAXS},
+     *            {@link #COMPUTE_FRAMES}.
      */
     public ClassWriter(final ClassReader classReader, final int flags) {
         this(flags);
@@ -638,14 +661,9 @@ public class ClassWriter extends ClassVisitor {
     // ------------------------------------------------------------------------
 
     @Override
-    public final void visit(
-        final int version,
-        final int access,
-        final String name,
-        final String signature,
-        final String superName,
-        final String[] interfaces)
-    {
+    public final void visit(final int version, final int access,
+            final String name, final String signature, final String superName,
+            final String[] interfaces) {
         this.version = version;
         this.access = access;
         this.name = newClass(name);
@@ -669,16 +687,14 @@ public class ClassWriter extends ClassVisitor {
             sourceFile = newUTF8(file);
         }
         if (debug != null) {
-            sourceDebug = new ByteVector().putUTF8(debug);
+            sourceDebug = new ByteVector().encodeUTF8(debug, 0,
+                    Integer.MAX_VALUE);
         }
     }
 
     @Override
-    public final void visitOuterClass(
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    public final void visitOuterClass(final String owner, final String name,
+            final String desc) {
         enclosingMethodOwner = newClass(owner);
         if (name != null && desc != null) {
             enclosingMethod = newNameType(name, desc);
@@ -686,10 +702,8 @@ public class ClassWriter extends ClassVisitor {
     }
 
     @Override
-    public final AnnotationVisitor visitAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public final AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
         if (!ClassReader.ANNOTATIONS) {
             return null;
         }
@@ -708,55 +722,76 @@ public class ClassWriter extends ClassVisitor {
     }
 
     @Override
+    public final AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, final String desc, final boolean visible) {
+        if (!ClassReader.ANNOTATIONS) {
+            return null;
+        }
+        ByteVector bv = new ByteVector();
+        // write target_type and target_info
+        AnnotationWriter.putTarget(typeRef, typePath, bv);
+        // write type, and reserve space for values count
+        bv.putShort(newUTF8(desc)).putShort(0);
+        AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv,
+                bv.length - 2);
+        if (visible) {
+            aw.next = tanns;
+            tanns = aw;
+        } else {
+            aw.next = itanns;
+            itanns = aw;
+        }
+        return aw;
+    }
+
+    @Override
     public final void visitAttribute(final Attribute attr) {
         attr.next = attrs;
         attrs = attr;
     }
 
     @Override
-    public final void visitInnerClass(
-        final String name,
-        final String outerName,
-        final String innerName,
-        final int access)
-    {
+    public final void visitInnerClass(final String name,
+            final String outerName, final String innerName, final int access) {
         if (innerClasses == null) {
             innerClasses = new ByteVector();
         }
-        ++innerClassesCount;
-        innerClasses.putShort(name == null ? 0 : newClass(name));
-        innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
-        innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
-        innerClasses.putShort(access);
+        // �4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the
+        // constant_pool table which represents a class or interface C that is
+        // not a package member must have exactly one corresponding entry in the
+        // classes array". To avoid duplicates we keep track in the intVal field
+        // of the Item of each CONSTANT_Class_info entry C whether an inner
+        // class entry has already been added for C (this field is unused for
+        // class entries, and changing its value does not change the hashcode
+        // and equality tests). If so we store the index of this inner class
+        // entry (plus one) in intVal. This hack allows duplicate detection in
+        // O(1) time.
+        Item nameItem = newClassItem(name);
+        if (nameItem.intVal == 0) {
+            ++innerClassesCount;
+            innerClasses.putShort(nameItem.index);
+            innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
+            innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
+            innerClasses.putShort(access);
+            nameItem.intVal = innerClassesCount;
+        } else {
+            // Compare the inner classes entry nameItem.intVal - 1 with the
+            // arguments of this method and throw an exception if there is a
+            // difference?
+        }
     }
 
     @Override
-    public final FieldVisitor visitField(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final Object value)
-    {
+    public final FieldVisitor visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
         return new FieldWriter(this, access, name, desc, signature, value);
     }
 
     @Override
-    public final MethodVisitor visitMethod(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final String[] exceptions)
-    {
-        return new MethodWriter(this,
-                access,
-                name,
-                desc,
-                signature,
-                exceptions,
-                computeMaxs,
-                computeFrames);
+    public final MethodVisitor visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        return new MethodWriter(this, access, name, desc, signature,
+                exceptions, computeMaxs, computeFrames);
     }
 
     @Override
@@ -769,11 +804,11 @@ public class ClassWriter extends ClassVisitor {
 
     /**
      * Returns the bytecode of the class that was build with this class writer.
-     *
+     * 
      * @return the bytecode of the class that was build with this class writer.
      */
     public byte[] toByteArray() {
-        if (index > Short.MAX_VALUE) {
+        if (index > 0xFFFF) {
             throw new RuntimeException("Class file too large!");
         }
         // computes the real size of the bytecode of this class
@@ -793,8 +828,9 @@ public class ClassWriter extends ClassVisitor {
             mb = (MethodWriter) mb.mv;
         }
         int attributeCount = 0;
-        if (bootstrapMethods != null) {  // we put it as first argument in order
-                                         // to improve a bit ClassReader.copyBootstrapMethods
+        if (bootstrapMethods != null) {
+            // we put it as first attribute in order to improve a bit
+            // ClassReader.copyBootstrapMethods
             ++attributeCount;
             size += 8 + bootstrapMethods.length;
             newUTF8("BootstrapMethods");
@@ -811,7 +847,7 @@ public class ClassWriter extends ClassVisitor {
         }
         if (sourceDebug != null) {
             ++attributeCount;
-            size += sourceDebug.length + 4;
+            size += sourceDebug.length + 6;
             newUTF8("SourceDebugExtension");
         }
         if (enclosingMethodOwner != 0) {
@@ -824,12 +860,13 @@ public class ClassWriter extends ClassVisitor {
             size += 6;
             newUTF8("Deprecated");
         }
-        if ((access & Opcodes.ACC_SYNTHETIC) != 0
-                && ((version & 0xFFFF) < Opcodes.V1_5 || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0))
-        {
-            ++attributeCount;
-            size += 6;
-            newUTF8("Synthetic");
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            if ((version & 0xFFFF) < Opcodes.V1_5
+                    || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+                ++attributeCount;
+                size += 6;
+                newUTF8("Synthetic");
+            }
         }
         if (innerClasses != null) {
             ++attributeCount;
@@ -846,6 +883,16 @@ public class ClassWriter extends ClassVisitor {
             size += 8 + ianns.getSize();
             newUTF8("RuntimeInvisibleAnnotations");
         }
+        if (ClassReader.ANNOTATIONS && tanns != null) {
+            ++attributeCount;
+            size += 8 + tanns.getSize();
+            newUTF8("RuntimeVisibleTypeAnnotations");
+        }
+        if (ClassReader.ANNOTATIONS && itanns != null) {
+            ++attributeCount;
+            size += 8 + itanns.getSize();
+            newUTF8("RuntimeInvisibleTypeAnnotations");
+        }
         if (attrs != null) {
             attributeCount += attrs.getCount();
             size += attrs.getSize(this, null, 0, -1, -1);
@@ -856,9 +903,8 @@ public class ClassWriter extends ClassVisitor {
         ByteVector out = new ByteVector(size);
         out.putInt(0xCAFEBABE).putInt(version);
         out.putShort(index).putByteArray(pool.data, 0, pool.length);
-        int mask = Opcodes.ACC_DEPRECATED
-                | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
-                | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC));
+        int mask = Opcodes.ACC_DEPRECATED | ACC_SYNTHETIC_ATTRIBUTE
+                | ((access & ACC_SYNTHETIC_ATTRIBUTE) / TO_ACC_SYNTHETIC);
         out.putShort(access & ~mask).putShort(name).putShort(superName);
         out.putShort(interfaceCount);
         for (int i = 0; i < interfaceCount; ++i) {
@@ -877,9 +923,10 @@ public class ClassWriter extends ClassVisitor {
             mb = (MethodWriter) mb.mv;
         }
         out.putShort(attributeCount);
-        if (bootstrapMethods != null) {   // should be the first class attribute ?
+        if (bootstrapMethods != null) {
             out.putShort(newUTF8("BootstrapMethods"));
-            out.putInt(bootstrapMethods.length + 2).putShort(bootstrapMethodsCount);
+            out.putInt(bootstrapMethods.length + 2).putShort(
+                    bootstrapMethodsCount);
             out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length);
         }
         if (ClassReader.SIGNATURES && signature != 0) {
@@ -889,9 +936,9 @@ public class ClassWriter extends ClassVisitor {
             out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);
         }
         if (sourceDebug != null) {
-            int len = sourceDebug.length - 2;
+            int len = sourceDebug.length;
             out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
-            out.putByteArray(sourceDebug.data, 2, len);
+            out.putByteArray(sourceDebug.data, 0, len);
         }
         if (enclosingMethodOwner != 0) {
             out.putShort(newUTF8("EnclosingMethod")).putInt(4);
@@ -900,10 +947,11 @@ public class ClassWriter extends ClassVisitor {
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             out.putShort(newUTF8("Deprecated")).putInt(0);
         }
-        if ((access & Opcodes.ACC_SYNTHETIC) != 0
-                && ((version & 0xFFFF) < Opcodes.V1_5 || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0))
-        {
-            out.putShort(newUTF8("Synthetic")).putInt(0);
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            if ((version & 0xFFFF) < Opcodes.V1_5
+                    || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+                out.putShort(newUTF8("Synthetic")).putInt(0);
+            }
         }
         if (innerClasses != null) {
             out.putShort(newUTF8("InnerClasses"));
@@ -918,13 +966,34 @@ public class ClassWriter extends ClassVisitor {
             out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
             ianns.put(out);
         }
+        if (ClassReader.ANNOTATIONS && tanns != null) {
+            out.putShort(newUTF8("RuntimeVisibleTypeAnnotations"));
+            tanns.put(out);
+        }
+        if (ClassReader.ANNOTATIONS && itanns != null) {
+            out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations"));
+            itanns.put(out);
+        }
         if (attrs != null) {
             attrs.put(this, null, 0, -1, -1, out);
         }
         if (invalidFrames) {
-            ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
-            new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES);
-            return cw.toByteArray();
+            anns = null;
+            ianns = null;
+            attrs = null;
+            innerClassesCount = 0;
+            innerClasses = null;
+            bootstrapMethodsCount = 0;
+            bootstrapMethods = null;
+            firstField = null;
+            lastField = null;
+            firstMethod = null;
+            lastMethod = null;
+            computeMaxs = false;
+            computeFrames = true;
+            invalidFrames = false;
+            new ClassReader(out.data).accept(this, ClassReader.SKIP_FRAMES);
+            return toByteArray();
         }
         return out.data;
     }
@@ -936,11 +1005,12 @@ public class ClassWriter extends ClassVisitor {
     /**
      * Adds a number or string constant to the constant pool of the class being
      * build. Does nothing if the constant pool already contains a similar item.
-     *
-     * @param cst the value of the constant to be added to the constant pool.
-     *        This parameter must be an {@link Integer}, a {@link Float}, a
-     *        {@link Long}, a {@link Double}, a {@link String} or a
-     *        {@link Type}.
+     * 
+     * @param cst
+     *            the value of the constant to be added to the constant pool.
+     *            This parameter must be an {@link Integer}, a {@link Float}, a
+     *            {@link Long}, a {@link Double}, a {@link String} or a
+     *            {@link Type}.
      * @return a new or already existing constant item with the given value.
      */
     Item newConstItem(final Object cst) {
@@ -973,12 +1043,12 @@ public class ClassWriter extends ClassVisitor {
         } else if (cst instanceof Type) {
             Type t = (Type) cst;
             int s = t.getSort();
-            if (s == Type.ARRAY) {
-                return newClassItem(t.getDescriptor());
-            } else if (s == Type.OBJECT) {
+            if (s == Type.OBJECT) {
                 return newClassItem(t.getInternalName());
-            } else { // s == Type.METHOD
+            } else if (s == Type.METHOD) {
                 return newMethodTypeItem(t.getDescriptor());
+            } else { // s == primitive type or array
+                return newClassItem(t.getDescriptor());
             }
         } else if (cst instanceof Handle) {
             Handle h = (Handle) cst;
@@ -993,10 +1063,11 @@ public class ClassWriter extends ClassVisitor {
      * build. Does nothing if the constant pool already contains a similar item.
      * <i>This method is intended for {@link Attribute} sub classes, and is
      * normally not needed by class generators or adapters.</i>
-     *
-     * @param cst the value of the constant to be added to the constant pool.
-     *        This parameter must be an {@link Integer}, a {@link Float}, a
-     *        {@link Long}, a {@link Double} or a {@link String}.
+     * 
+     * @param cst
+     *            the value of the constant to be added to the constant pool.
+     *            This parameter must be an {@link Integer}, a {@link Float}, a
+     *            {@link Long}, a {@link Double} or a {@link String}.
      * @return the index of a new or already existing constant item with the
      *         given value.
      */
@@ -1009,8 +1080,9 @@ public class ClassWriter extends ClassVisitor {
      * nothing if the constant pool already contains a similar item. <i>This
      * method is intended for {@link Attribute} sub classes, and is normally not
      * needed by class generators or adapters.</i>
-     *
-     * @param value the String value.
+     * 
+     * @param value
+     *            the String value.
      * @return the index of a new or already existing UTF8 item.
      */
     public int newUTF8(final String value) {
@@ -1029,8 +1101,9 @@ public class ClassWriter extends ClassVisitor {
      * Does nothing if the constant pool already contains a similar item.
      * <i>This method is intended for {@link Attribute} sub classes, and is
      * normally not needed by class generators or adapters.</i>
-     *
-     * @param value the internal name of the class.
+     * 
+     * @param value
+     *            the internal name of the class.
      * @return a new or already existing class reference item.
      */
     Item newClassItem(final String value) {
@@ -1049,8 +1122,9 @@ public class ClassWriter extends ClassVisitor {
      * Does nothing if the constant pool already contains a similar item.
      * <i>This method is intended for {@link Attribute} sub classes, and is
      * normally not needed by class generators or adapters.</i>
-     *
-     * @param value the internal name of the class.
+     * 
+     * @param value
+     *            the internal name of the class.
      * @return the index of a new or already existing class reference item.
      */
     public int newClass(final String value) {
@@ -1062,8 +1136,9 @@ public class ClassWriter extends ClassVisitor {
      * build. Does nothing if the constant pool already contains a similar item.
      * <i>This method is intended for {@link Attribute} sub classes, and is
      * normally not needed by class generators or adapters.</i>
-     *
-     * @param methodDesc method descriptor of the method type.
+     * 
+     * @param methodDesc
+     *            method descriptor of the method type.
      * @return a new or already existing method type reference item.
      */
     Item newMethodTypeItem(final String methodDesc) {
@@ -1082,8 +1157,9 @@ public class ClassWriter extends ClassVisitor {
      * build. Does nothing if the constant pool already contains a similar item.
      * <i>This method is intended for {@link Attribute} sub classes, and is
      * normally not needed by class generators or adapters.</i>
-     *
-     * @param methodDesc method descriptor of the method type.
+     * 
+     * @param methodDesc
+     *            method descriptor of the method type.
      * @return the index of a new or already existing method type reference
      *         item.
      */
@@ -1096,34 +1172,35 @@ public class ClassWriter extends ClassVisitor {
      * if the constant pool already contains a similar item. <i>This method is
      * intended for {@link Attribute} sub classes, and is normally not needed by
      * class generators or adapters.</i>
-     *
-     * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
-     *        {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
-     *        {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
-     *        {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
-     *        {@link Opcodes#H_NEWINVOKESPECIAL} or
-     *        {@link Opcodes#H_INVOKEINTERFACE}.
-     * @param owner the internal name of the field or method owner class.
-     * @param name the name of the field or method.
-     * @param desc the descriptor of the field or method.
+     * 
+     * @param tag
+     *            the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
+     *            {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
+     *            {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
+     *            {@link Opcodes#H_INVOKESTATIC},
+     *            {@link Opcodes#H_INVOKESPECIAL},
+     *            {@link Opcodes#H_NEWINVOKESPECIAL} or
+     *            {@link Opcodes#H_INVOKEINTERFACE}.
+     * @param owner
+     *            the internal name of the field or method owner class.
+     * @param name
+     *            the name of the field or method.
+     * @param desc
+     *            the descriptor of the field or method.
      * @return a new or an already existing method type reference item.
      */
-    Item newHandleItem(
-        final int tag,
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    Item newHandleItem(final int tag, final String owner, final String name,
+            final String desc) {
         key4.set(HANDLE_BASE + tag, owner, name, desc);
         Item result = get(key4);
         if (result == null) {
             if (tag <= Opcodes.H_PUTSTATIC) {
                 put112(HANDLE, tag, newField(owner, name, desc));
             } else {
-                put112(HANDLE, tag, newMethod(owner,
-                        name,
-                        desc,
-                        tag == Opcodes.H_INVOKEINTERFACE));
+                put112(HANDLE,
+                        tag,
+                        newMethod(owner, name, desc,
+                                tag == Opcodes.H_INVOKEINTERFACE));
             }
             result = new Item(index++, key4);
             put(result);
@@ -1132,29 +1209,30 @@ public class ClassWriter extends ClassVisitor {
     }
 
     /**
-     * Adds a handle to the constant pool of the class being
-     * build. Does nothing if the constant pool already contains a similar item.
-     * <i>This method is intended for {@link Attribute} sub classes, and is
-     * normally not needed by class generators or adapters.</i>
-     *
-     * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
-     *        {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
-     *        {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
-     *        {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
-     *        {@link Opcodes#H_NEWINVOKESPECIAL} or
-     *        {@link Opcodes#H_INVOKEINTERFACE}.
-     * @param owner the internal name of the field or method owner class.
-     * @param name the name of the field or method.
-     * @param desc the descriptor of the field or method.
+     * Adds a handle to the constant pool of the class being build. Does nothing
+     * if the constant pool already contains a similar item. <i>This method is
+     * intended for {@link Attribute} sub classes, and is normally not needed by
+     * class generators or adapters.</i>
+     * 
+     * @param tag
+     *            the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
+     *            {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
+     *            {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
+     *            {@link Opcodes#H_INVOKESTATIC},
+     *            {@link Opcodes#H_INVOKESPECIAL},
+     *            {@link Opcodes#H_NEWINVOKESPECIAL} or
+     *            {@link Opcodes#H_INVOKEINTERFACE}.
+     * @param owner
+     *            the internal name of the field or method owner class.
+     * @param name
+     *            the name of the field or method.
+     * @param desc
+     *            the descriptor of the field or method.
      * @return the index of a new or already existing method type reference
      *         item.
      */
-    public int newHandle(
-        final int tag,
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    public int newHandle(final int tag, final String owner, final String name,
+            final String desc) {
         return newHandleItem(tag, owner, name, desc).index;
     }
 
@@ -1163,20 +1241,20 @@ public class ClassWriter extends ClassVisitor {
      * build. Does nothing if the constant pool already contains a similar item.
      * <i>This method is intended for {@link Attribute} sub classes, and is
      * normally not needed by class generators or adapters.</i>
-     *
-     * @param name name of the invoked method.
-     * @param desc descriptor of the invoke method.
-     * @param bsm the bootstrap method.
-     * @param bsmArgs the bootstrap method constant arguments.
-     *
+     * 
+     * @param name
+     *            name of the invoked method.
+     * @param desc
+     *            descriptor of the invoke method.
+     * @param bsm
+     *            the bootstrap method.
+     * @param bsmArgs
+     *            the bootstrap method constant arguments.
+     * 
      * @return a new or an already existing invokedynamic type reference item.
      */
-    Item newInvokeDynamicItem(
-        final String name,
-        final String desc,
-        final Handle bsm,
-        final Object... bsmArgs)
-    {
+    Item newInvokeDynamicItem(final String name, final String desc,
+            final Handle bsm, final Object... bsmArgs) {
         // cache for performance
         ByteVector bootstrapMethods = this.bootstrapMethods;
         if (bootstrapMethods == null) {
@@ -1186,9 +1264,7 @@ public class ClassWriter extends ClassVisitor {
         int position = bootstrapMethods.length; // record current position
 
         int hashCode = bsm.hashCode();
-        bootstrapMethods.putShort(newHandle(bsm.tag,
-                bsm.owner,
-                bsm.name,
+        bootstrapMethods.putShort(newHandle(bsm.tag, bsm.owner, bsm.name,
                 bsm.desc));
 
         int argsLength = bsmArgs.length;
@@ -1249,35 +1325,37 @@ public class ClassWriter extends ClassVisitor {
      * build. Does nothing if the constant pool already contains a similar item.
      * <i>This method is intended for {@link Attribute} sub classes, and is
      * normally not needed by class generators or adapters.</i>
-     *
-     * @param name name of the invoked method.
-     * @param desc descriptor of the invoke method.
-     * @param bsm the bootstrap method.
-     * @param bsmArgs the bootstrap method constant arguments.
-     *
-     * @return the index of a new or already existing invokedynamic
-     *         reference item.
-     */
-    public int newInvokeDynamic(
-        final String name,
-        final String desc,
-        final Handle bsm,
-        final Object... bsmArgs)
-    {
+     * 
+     * @param name
+     *            name of the invoked method.
+     * @param desc
+     *            descriptor of the invoke method.
+     * @param bsm
+     *            the bootstrap method.
+     * @param bsmArgs
+     *            the bootstrap method constant arguments.
+     * 
+     * @return the index of a new or already existing invokedynamic reference
+     *         item.
+     */
+    public int newInvokeDynamic(final String name, final String desc,
+            final Handle bsm, final Object... bsmArgs) {
         return newInvokeDynamicItem(name, desc, bsm, bsmArgs).index;
     }
 
     /**
      * Adds a field reference to the constant pool of the class being build.
      * Does nothing if the constant pool already contains a similar item.
-     *
-     * @param owner the internal name of the field's owner class.
-     * @param name the field's name.
-     * @param desc the field's descriptor.
+     * 
+     * @param owner
+     *            the internal name of the field's owner class.
+     * @param name
+     *            the field's name.
+     * @param desc
+     *            the field's descriptor.
      * @return a new or already existing field reference item.
      */
-    Item newFieldItem(final String owner, final String name, final String desc)
-    {
+    Item newFieldItem(final String owner, final String name, final String desc) {
         key3.set(FIELD, owner, name, desc);
         Item result = get(key3);
         if (result == null) {
@@ -1293,33 +1371,35 @@ public class ClassWriter extends ClassVisitor {
      * Does nothing if the constant pool already contains a similar item.
      * <i>This method is intended for {@link Attribute} sub classes, and is
      * normally not needed by class generators or adapters.</i>
-     *
-     * @param owner the internal name of the field's owner class.
-     * @param name the field's name.
-     * @param desc the field's descriptor.
+     * 
+     * @param owner
+     *            the internal name of the field's owner class.
+     * @param name
+     *            the field's name.
+     * @param desc
+     *            the field's descriptor.
      * @return the index of a new or already existing field reference item.
      */
-    public int newField(final String owner, final String name, final String desc)
-    {
+    public int newField(final String owner, final String name, final String desc) {
         return newFieldItem(owner, name, desc).index;
     }
 
     /**
      * Adds a method reference to the constant pool of the class being build.
      * Does nothing if the constant pool already contains a similar item.
-     *
-     * @param owner the internal name of the method's owner class.
-     * @param name the method's name.
-     * @param desc the method's descriptor.
-     * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
+     * 
+     * @param owner
+     *            the internal name of the method's owner class.
+     * @param name
+     *            the method's name.
+     * @param desc
+     *            the method's descriptor.
+     * @param itf
+     *            <tt>true</tt> if <tt>owner</tt> is an interface.
      * @return a new or already existing method reference item.
      */
-    Item newMethodItem(
-        final String owner,
-        final String name,
-        final String desc,
-        final boolean itf)
-    {
+    Item newMethodItem(final String owner, final String name,
+            final String desc, final boolean itf) {
         int type = itf ? IMETH : METH;
         key3.set(type, owner, name, desc);
         Item result = get(key3);
@@ -1336,27 +1416,28 @@ public class ClassWriter extends ClassVisitor {
      * Does nothing if the constant pool already contains a similar item.
      * <i>This method is intended for {@link Attribute} sub classes, and is
      * normally not needed by class generators or adapters.</i>
-     *
-     * @param owner the internal name of the method's owner class.
-     * @param name the method's name.
-     * @param desc the method's descriptor.
-     * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
+     * 
+     * @param owner
+     *            the internal name of the method's owner class.
+     * @param name
+     *            the method's name.
+     * @param desc
+     *            the method's descriptor.
+     * @param itf
+     *            <tt>true</tt> if <tt>owner</tt> is an interface.
      * @return the index of a new or already existing method reference item.
      */
-    public int newMethod(
-        final String owner,
-        final String name,
-        final String desc,
-        final boolean itf)
-    {
+    public int newMethod(final String owner, final String name,
+            final String desc, final boolean itf) {
         return newMethodItem(owner, name, desc, itf).index;
     }
 
     /**
      * Adds an integer to the constant pool of the class being build. Does
      * nothing if the constant pool already contains a similar item.
-     *
-     * @param value the int value.
+     * 
+     * @param value
+     *            the int value.
      * @return a new or already existing int item.
      */
     Item newInteger(final int value) {
@@ -1373,8 +1454,9 @@ public class ClassWriter extends ClassVisitor {
     /**
      * Adds a float to the constant pool of the class being build. Does nothing
      * if the constant pool already contains a similar item.
-     *
-     * @param value the float value.
+     * 
+     * @param value
+     *            the float value.
      * @return a new or already existing float item.
      */
     Item newFloat(final float value) {
@@ -1391,8 +1473,9 @@ public class ClassWriter extends ClassVisitor {
     /**
      * Adds a long to the constant pool of the class being build. Does nothing
      * if the constant pool already contains a similar item.
-     *
-     * @param value the long value.
+     * 
+     * @param value
+     *            the long value.
      * @return a new or already existing long item.
      */
     Item newLong(final long value) {
@@ -1410,8 +1493,9 @@ public class ClassWriter extends ClassVisitor {
     /**
      * Adds a double to the constant pool of the class being build. Does nothing
      * if the constant pool already contains a similar item.
-     *
-     * @param value the double value.
+     * 
+     * @param value
+     *            the double value.
      * @return a new or already existing double item.
      */
     Item newDouble(final double value) {
@@ -1429,8 +1513,9 @@ public class ClassWriter extends ClassVisitor {
     /**
      * Adds a string to the constant pool of the class being build. Does nothing
      * if the constant pool already contains a similar item.
-     *
-     * @param value the String value.
+     * 
+     * @param value
+     *            the String value.
      * @return a new or already existing string item.
      */
     private Item newString(final String value) {
@@ -1449,9 +1534,11 @@ public class ClassWriter extends ClassVisitor {
      * nothing if the constant pool already contains a similar item. <i>This
      * method is intended for {@link Attribute} sub classes, and is normally not
      * needed by class generators or adapters.</i>
-     *
-     * @param name a name.
-     * @param desc a type descriptor.
+     * 
+     * @param name
+     *            a name.
+     * @param desc
+     *            a type descriptor.
      * @return the index of a new or already existing name and type item.
      */
     public int newNameType(final String name, final String desc) {
@@ -1461,9 +1548,11 @@ public class ClassWriter extends ClassVisitor {
     /**
      * Adds a name and type to the constant pool of the class being build. Does
      * nothing if the constant pool already contains a similar item.
-     *
-     * @param name a name.
-     * @param desc a type descriptor.
+     * 
+     * @param name
+     *            a name.
+     * @param desc
+     *            a type descriptor.
      * @return a new or already existing name and type item.
      */
     Item newNameTypeItem(final String name, final String desc) {
@@ -1480,8 +1569,9 @@ public class ClassWriter extends ClassVisitor {
     /**
      * Adds the given internal name to {@link #typeTable} and returns its index.
      * Does nothing if the type table already contains this internal name.
-     *
-     * @param type the internal name to be added to the type table.
+     * 
+     * @param type
+     *            the internal name to be added to the type table.
      * @return the index of this internal name in the type table.
      */
     int addType(final String type) {
@@ -1497,10 +1587,12 @@ public class ClassWriter extends ClassVisitor {
      * Adds the given "uninitialized" type to {@link #typeTable} and returns its
      * index. This method is used for UNINITIALIZED types, made of an internal
      * name and a bytecode offset.
-     *
-     * @param type the internal name to be added to the type table.
-     * @param offset the bytecode offset of the NEW instruction that created
-     *        this UNINITIALIZED type value.
+     * 
+     * @param type
+     *            the internal name to be added to the type table.
+     * @param offset
+     *            the bytecode offset of the NEW instruction that created this
+     *            UNINITIALIZED type value.
      * @return the index of this internal name in the type table.
      */
     int addUninitializedType(final String type, final int offset) {
@@ -1517,8 +1609,9 @@ public class ClassWriter extends ClassVisitor {
 
     /**
      * Adds the given Item to {@link #typeTable}.
-     *
-     * @param item the value to be added to the type table.
+     * 
+     * @param item
+     *            the value to be added to the type table.
      * @return the added Item, which a new Item instance with the same value as
      *         the given Item.
      */
@@ -1543,9 +1636,11 @@ public class ClassWriter extends ClassVisitor {
      * method calls {@link #getCommonSuperClass} and caches the result in the
      * {@link #items} hash table to speedup future calls with the same
      * parameters.
-     *
-     * @param type1 index of an internal name in {@link #typeTable}.
-     * @param type2 index of an internal name in {@link #typeTable}.
+     * 
+     * @param type1
+     *            index of an internal name in {@link #typeTable}.
+     * @param type2
+     *            index of an internal name in {@link #typeTable}.
      * @return the index of the common super type of the two given types.
      */
     int getMergedType(final int type1, final int type2) {
@@ -1565,20 +1660,21 @@ public class ClassWriter extends ClassVisitor {
 
     /**
      * Returns the common super type of the two given types. The default
-     * implementation of this method <i>loads<i> the two given classes and uses
+     * implementation of this method <i>loads</i> the two given classes and uses
      * the java.lang.Class methods to find the common super class. It can be
      * overridden to compute this common super type in other ways, in particular
      * without actually loading any class, or to take into account the class
      * that is currently being generated by this ClassWriter, which can of
      * course not be loaded since it is under construction.
-     *
-     * @param type1 the internal name of a class.
-     * @param type2 the internal name of another class.
+     * 
+     * @param type1
+     *            the internal name of a class.
+     * @param type2
+     *            the internal name of another class.
      * @return the internal name of the common super class of the two given
      *         classes.
      */
-    protected String getCommonSuperClass(final String type1, final String type2)
-    {
+    protected String getCommonSuperClass(final String type1, final String type2) {
         Class<?> c, d;
         ClassLoader classLoader = getClass().getClassLoader();
         try {
@@ -1606,8 +1702,9 @@ public class ClassWriter extends ClassVisitor {
     /**
      * Returns the constant pool's hash table item which is equal to the given
      * item.
-     *
-     * @param key a constant pool item.
+     * 
+     * @param key
+     *            a constant pool item.
      * @return the constant pool's hash table item which is equal to the given
      *         item, or <tt>null</tt> if there is no such item.
      */
@@ -1622,8 +1719,9 @@ public class ClassWriter extends ClassVisitor {
     /**
      * Puts the given item in the constant pool's hash table. The hash table
      * <i>must</i> not already contains this item.
-     *
-     * @param i the item to be added to the constant pool's hash table.
+     * 
+     * @param i
+     *            the item to be added to the constant pool's hash table.
      */
     private void put(final Item i) {
         if (index + typeCount > threshold) {
@@ -1650,10 +1748,13 @@ public class ClassWriter extends ClassVisitor {
 
     /**
      * Puts one byte and two shorts into the constant pool.
-     *
-     * @param b a byte.
-     * @param s1 a short.
-     * @param s2 another short.
+     * 
+     * @param b
+     *            a byte.
+     * @param s1
+     *            a short.
+     * @param s2
+     *            another short.
      */
     private void put122(final int b, final int s1, final int s2) {
         pool.put12(b, s1).putShort(s2);
@@ -1661,10 +1762,13 @@ public class ClassWriter extends ClassVisitor {
 
     /**
      * Puts two bytes and one short into the constant pool.
-     *
-     * @param b1 a byte.
-     * @param b2 another byte.
-     * @param s a short.
+     * 
+     * @param b1
+     *            a byte.
+     * @param b2
+     *            another byte.
+     * @param s
+     *            a short.
      */
     private void put112(final int b1, final int b2, final int s) {
         pool.put11(b1, b2).putShort(s);

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java
new file mode 100644
index 0000000..27983d6
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java
@@ -0,0 +1,145 @@
+/***
+ * 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;
+
+/**
+ * Information about a class being parsed in a {@link ClassReader}.
+ * 
+ * @author Eric Bruneton
+ */
+class Context {
+
+    /**
+     * Prototypes of the attributes that must be parsed for this class.
+     */
+    Attribute[] attrs;
+
+    /**
+     * The {@link ClassReader} option flags for the parsing of this class.
+     */
+    int flags;
+
+    /**
+     * The buffer used to read strings.
+     */
+    char[] buffer;
+
+    /**
+     * The start index of each bootstrap method.
+     */
+    int[] bootstrapMethods;
+
+    /**
+     * The access flags of the method currently being parsed.
+     */
+    int access;
+
+    /**
+     * The name of the method currently being parsed.
+     */
+    String name;
+
+    /**
+     * The descriptor of the method currently being parsed.
+     */
+    String desc;
+
+    /**
+     * The label objects, indexed by bytecode offset, of the method currently
+     * being parsed (only bytecode offsets for which a label is needed have a
+     * non null associated Label object).
+     */
+    Label[] labels;
+
+    /**
+     * The target of the type annotation currently being parsed.
+     */
+    int typeRef;
+
+    /**
+     * The path of the type annotation currently being parsed.
+     */
+    TypePath typePath;
+
+    /**
+     * The offset of the latest stack map frame that has been parsed.
+     */
+    int offset;
+
+    /**
+     * The labels corresponding to the start of the local variable ranges in the
+     * local variable type annotation currently being parsed.
+     */
+    Label[] start;
+
+    /**
+     * The labels corresponding to the end of the local variable ranges in the
+     * local variable type annotation currently being parsed.
+     */
+    Label[] end;
+
+    /**
+     * The local variable indices for each local variable range in the local
+     * variable type annotation currently being parsed.
+     */
+    int[] index;
+
+    /**
+     * The encoding of the latest stack map frame that has been parsed.
+     */
+    int mode;
+
+    /**
+     * The number of locals in the latest stack map frame that has been parsed.
+     */
+    int localCount;
+
+    /**
+     * The number locals in the latest stack map frame that has been parsed,
+     * minus the number of locals in the previous frame.
+     */
+    int localDiff;
+
+    /**
+     * The local values of the latest stack map frame that has been parsed.
+     */
+    Object[] local;
+
+    /**
+     * The stack size of the latest stack map frame that has been parsed.
+     */
+    int stackCount;
+
+    /**
+     * The stack values of the latest stack map frame that has been parsed.
+     */
+    Object[] stack;
+}
\ 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/Edge.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java
index 80222bc..9347888 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
 
 /**
  * An edge in the control flow graph of a method body. See {@link Label Label}.
- *
+ * 
  * @author Eric Bruneton
  */
 class Edge {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
index 32c23d1..107af8f 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
@@ -30,17 +30,17 @@
 package org.apache.tapestry5.internal.plastic.asm;
 
 /**
- * A visitor to visit a Java field. The methods of this class must be called
- * in the following order: ( <tt>visitAnnotation</tt> |
- * <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
- *
+ * A visitor to visit a Java field. The methods of this class must be called in
+ * the following order: ( <tt>visitAnnotation</tt> |
+ * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
+ * 
  * @author Eric Bruneton
  */
 public abstract class FieldVisitor {
 
     /**
      * The ASM API version implemented by this visitor. The value of this field
-     * must be one of {@link Opcodes#ASM4}.
+     * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
      */
     protected final int api;
 
@@ -52,9 +52,10 @@ public abstract class FieldVisitor {
 
     /**
      * Constructs a new {@link FieldVisitor}.
-     *
-     * @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 FieldVisitor(final int api) {
         this(api, null);
@@ -62,25 +63,29 @@ public abstract class FieldVisitor {
 
     /**
      * Constructs a new {@link FieldVisitor}.
-     *
-     * @param api the ASM API version implemented by this visitor. Must be one
-     *        of {@link Opcodes#ASM4}.
-     * @param fv the field visitor to which this visitor must delegate method
-     *        calls. May be null.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param fv
+     *            the field visitor to which this visitor must delegate method
+     *            calls. May be null.
      */
     public FieldVisitor(final int api, final FieldVisitor fv) {
-        /*if (api != Opcodes.ASM4) {
+        if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
             throw new IllegalArgumentException();
-        }*/
+        }
         this.api = api;
         this.fv = fv;
     }
 
     /**
      * Visits an annotation of the field.
-     *
-     * @param desc the class descriptor of the annotation class.
-     * @param visible <tt>true</tt> if the annotation is visible at runtime.
+     * 
+     * @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.
      */
@@ -92,9 +97,39 @@ public abstract class FieldVisitor {
     }
 
     /**
+     * Visits an annotation on the type of the field.
+     * 
+     * @param typeRef
+     *            a reference to the annotated type. The sort of this type
+     *            reference must be {@link TypeReference#FIELD FIELD}. 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.
+     * @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.
+     */
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        if (api < Opcodes.ASM5) {
+            throw new RuntimeException();
+        }
+        if (fv != null) {
+            return fv.visitTypeAnnotation(typeRef, typePath, desc, visible);
+        }
+        return null;
+    }
+
+    /**
      * Visits a non standard attribute of the field.
-     *
-     * @param attr an attribute.
+     * 
+     * @param attr
+     *            an attribute.
      */
     public void visitAttribute(Attribute attr) {
         if (fv != null) {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
index b61105a..4a5f406 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
 
 /**
  * An {@link FieldVisitor} that generates Java fields in bytecode form.
- *
+ * 
  * @author Eric Bruneton
  */
 final class FieldWriter extends FieldVisitor {
@@ -81,6 +81,17 @@ final class FieldWriter extends FieldVisitor {
     private AnnotationWriter ianns;
 
     /**
+     * The runtime visible type annotations of this field. May be <tt>null</tt>.
+     */
+    private AnnotationWriter tanns;
+
+    /**
+     * The runtime invisible type annotations of this field. May be
+     * <tt>null</tt>.
+     */
+    private AnnotationWriter itanns;
+
+    /**
      * The non standard attributes of this field. May be <tt>null</tt>.
      */
     private Attribute attrs;
@@ -91,23 +102,23 @@ final class FieldWriter extends FieldVisitor {
 
     /**
      * Constructs a new {@link FieldWriter}.
-     *
-     * @param cw the class writer to which this field must be added.
-     * @param access the field's access flags (see {@link Opcodes}).
-     * @param name the field's name.
-     * @param desc the field's descriptor (see {@link Type}).
-     * @param signature the field's signature. May be <tt>null</tt>.
-     * @param value the field's constant value. May be <tt>null</tt>.
+     * 
+     * @param cw
+     *            the class writer to which this field must be added.
+     * @param access
+     *            the field's access flags (see {@link Opcodes}).
+     * @param name
+     *            the field's name.
+     * @param desc
+     *            the field's descriptor (see {@link Type}).
+     * @param signature
+     *            the field's signature. May be <tt>null</tt>.
+     * @param value
+     *            the field's constant value. May be <tt>null</tt>.
      */
-    FieldWriter(
-        final ClassWriter cw,
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final Object value)
-    {
-        super(Opcodes.ASM4);
+    FieldWriter(final ClassWriter cw, final int access, final String name,
+            final String desc, final String signature, final Object value) {
+        super(Opcodes.ASM5);
         if (cw.firstField == null) {
             cw.firstField = this;
         } else {
@@ -131,10 +142,8 @@ final class FieldWriter extends FieldVisitor {
     // ------------------------------------------------------------------------
 
     @Override
-    public AnnotationVisitor visitAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
         if (!ClassReader.ANNOTATIONS) {
             return null;
         }
@@ -153,6 +162,29 @@ final class FieldWriter extends FieldVisitor {
     }
 
     @Override
+    public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        if (!ClassReader.ANNOTATIONS) {
+            return null;
+        }
+        ByteVector bv = new ByteVector();
+        // write target_type and target_info
+        AnnotationWriter.putTarget(typeRef, typePath, bv);
+        // write type, and reserve space for values count
+        bv.putShort(cw.newUTF8(desc)).putShort(0);
+        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+                bv.length - 2);
+        if (visible) {
+            aw.next = tanns;
+            tanns = aw;
+        } else {
+            aw.next = itanns;
+            itanns = aw;
+        }
+        return aw;
+    }
+
+    @Override
     public void visitAttribute(final Attribute attr) {
         attr.next = attrs;
         attrs = attr;
@@ -168,7 +200,7 @@ final class FieldWriter extends FieldVisitor {
 
     /**
      * Returns the size of this field.
-     *
+     * 
      * @return the size of this field.
      */
     int getSize() {
@@ -177,11 +209,12 @@ final class FieldWriter extends FieldVisitor {
             cw.newUTF8("ConstantValue");
             size += 8;
         }
-        if ((access & Opcodes.ACC_SYNTHETIC) != 0
-                && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
-        {
-            cw.newUTF8("Synthetic");
-            size += 6;
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            if ((cw.version & 0xFFFF) < Opcodes.V1_5
+                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+                cw.newUTF8("Synthetic");
+                size += 6;
+            }
         }
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             cw.newUTF8("Deprecated");
@@ -199,6 +232,14 @@ final class FieldWriter extends FieldVisitor {
             cw.newUTF8("RuntimeInvisibleAnnotations");
             size += 8 + ianns.getSize();
         }
+        if (ClassReader.ANNOTATIONS && tanns != null) {
+            cw.newUTF8("RuntimeVisibleTypeAnnotations");
+            size += 8 + tanns.getSize();
+        }
+        if (ClassReader.ANNOTATIONS && itanns != null) {
+            cw.newUTF8("RuntimeInvisibleTypeAnnotations");
+            size += 8 + itanns.getSize();
+        }
         if (attrs != null) {
             size += attrs.getSize(cw, null, 0, -1, -1);
         }
@@ -207,22 +248,24 @@ final class FieldWriter extends FieldVisitor {
 
     /**
      * Puts the content of this field into the given byte vector.
-     *
-     * @param out where the content of this field must be put.
+     * 
+     * @param out
+     *            where the content of this field must be put.
      */
     void put(final ByteVector out) {
-        int mask = Opcodes.ACC_DEPRECATED
-                | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
-                | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC));
+        final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
+        int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+                | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
         out.putShort(access & ~mask).putShort(name).putShort(desc);
         int attributeCount = 0;
         if (value != 0) {
             ++attributeCount;
         }
-        if ((access & Opcodes.ACC_SYNTHETIC) != 0
-                && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
-        {
-            ++attributeCount;
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            if ((cw.version & 0xFFFF) < Opcodes.V1_5
+                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+                ++attributeCount;
+            }
         }
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             ++attributeCount;
@@ -236,6 +279,12 @@ final class FieldWriter extends FieldVisitor {
         if (ClassReader.ANNOTATIONS && ianns != null) {
             ++attributeCount;
         }
+        if (ClassReader.ANNOTATIONS && tanns != null) {
+            ++attributeCount;
+        }
+        if (ClassReader.ANNOTATIONS && itanns != null) {
+            ++attributeCount;
+        }
         if (attrs != null) {
             attributeCount += attrs.getCount();
         }
@@ -244,10 +293,11 @@ final class FieldWriter extends FieldVisitor {
             out.putShort(cw.newUTF8("ConstantValue"));
             out.putInt(2).putShort(value);
         }
-        if ((access & Opcodes.ACC_SYNTHETIC) != 0
-                && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
-        {
-            out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            if ((cw.version & 0xFFFF) < Opcodes.V1_5
+                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+                out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+            }
         }
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             out.putShort(cw.newUTF8("Deprecated")).putInt(0);
@@ -264,6 +314,14 @@ final class FieldWriter extends FieldVisitor {
             out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
             ianns.put(out);
         }
+        if (ClassReader.ANNOTATIONS && tanns != null) {
+            out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
+            tanns.put(out);
+        }
+        if (ClassReader.ANNOTATIONS && itanns != null) {
+            out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
+            itanns.put(out);
+        }
         if (attrs != null) {
             attrs.put(cw, null, 0, -1, -1, out);
         }


[16/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
new file mode 100644
index 0000000..c256825
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
@@ -0,0 +1,947 @@
+/***
+ * 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.commons;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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;
+
+/**
+ * A {@link MethodVisitor} that keeps track of stack map frame changes between
+ * {@link #visitFrame(int, int, Object[], int, Object[]) visitFrame} calls. This
+ * adapter must be used with the
+ * {@link org.apache.tapestry5.internal.plastic.asm.ClassReader#EXPAND_FRAMES} option. Each
+ * visit<i>X</i> instruction delegates to the next visitor in the chain, if any,
+ * and then simulates the effect of this instruction on the stack map frame,
+ * represented by {@link #locals} and {@link #stack}. The next visitor in the
+ * chain can get the state of the stack map frame <i>before</i> each instruction
+ * by reading the value of these fields in its visit<i>X</i> methods (this
+ * requires a reference to the AnalyzerAdapter that is before it in the chain).
+ * If this adapter is used with a class that does not contain stack map table
+ * attributes (i.e., pre Java 6 classes) then this adapter may not be able to
+ * compute the stack map frame for each instruction. In this case no exception
+ * is thrown but the {@link #locals} and {@link #stack} fields will be null for
+ * these instructions.
+ * 
+ * @author Eric Bruneton
+ */
+public class AnalyzerAdapter extends MethodVisitor {
+
+    /**
+     * <code>List</code> of the local variable slots for current execution
+     * frame. Primitive types are represented by {@link Opcodes#TOP},
+     * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+     * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
+     * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by
+     * two elements, the second one being TOP). Reference types are represented
+     * by String objects (representing internal names), and uninitialized types
+     * by Label objects (this label designates the NEW instruction that created
+     * this uninitialized value). This field is <tt>null</tt> for unreachable
+     * instructions.
+     */
+    public List<Object> locals;
+
+    /**
+     * <code>List</code> of the operand stack slots for current execution frame.
+     * Primitive types are represented by {@link Opcodes#TOP},
+     * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+     * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
+     * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by
+     * two elements, the second one being TOP). Reference types are represented
+     * by String objects (representing internal names), and uninitialized types
+     * by Label objects (this label designates the NEW instruction that created
+     * this uninitialized value). This field is <tt>null</tt> for unreachable
+     * instructions.
+     */
+    public List<Object> stack;
+
+    /**
+     * The labels that designate the next instruction to be visited. May be
+     * <tt>null</tt>.
+     */
+    private List<Label> labels;
+
+    /**
+     * Information about uninitialized types in the current execution frame.
+     * This map associates internal names to Label objects. Each label
+     * designates a NEW instruction that created the currently uninitialized
+     * types, and the associated internal name represents the NEW operand, i.e.
+     * the final, initialized type value.
+     */
+    public Map<Object, Object> uninitializedTypes;
+
+    /**
+     * The maximum stack size of this method.
+     */
+    private int maxStack;
+
+    /**
+     * The maximum number of local variables of this method.
+     */
+    private int maxLocals;
+
+    /**
+     * The owner's class name.
+     */
+    private String owner;
+
+    /**
+     * Creates a new {@link AnalyzerAdapter}. <i>Subclasses must not use this
+     * constructor</i>. Instead, they must use the
+     * {@link #AnalyzerAdapter(int, String, int, String, String, MethodVisitor)}
+     * version.
+     * 
+     * @param owner
+     *            the owner's class name.
+     * @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}).
+     * @param mv
+     *            the method visitor to which this adapter delegates calls. May
+     *            be <tt>null</tt>.
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public AnalyzerAdapter(final String owner, final int access,
+            final String name, final String desc, final MethodVisitor mv) {
+        this(Opcodes.ASM5, owner, access, name, desc, mv);
+        if (getClass() != AnalyzerAdapter.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Creates a new {@link AnalyzerAdapter}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param owner
+     *            the owner's class name.
+     * @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}).
+     * @param mv
+     *            the method visitor to which this adapter delegates calls. May
+     *            be <tt>null</tt>.
+     */
+    protected AnalyzerAdapter(final int api, final String owner,
+            final int access, final String name, final String desc,
+            final MethodVisitor mv) {
+        super(api, mv);
+        this.owner = owner;
+        locals = new ArrayList<Object>();
+        stack = new ArrayList<Object>();
+        uninitializedTypes = new HashMap<Object, Object>();
+
+        if ((access & Opcodes.ACC_STATIC) == 0) {
+            if ("<init>".equals(name)) {
+                locals.add(Opcodes.UNINITIALIZED_THIS);
+            } else {
+                locals.add(owner);
+            }
+        }
+        Type[] types = Type.getArgumentTypes(desc);
+        for (int i = 0; i < types.length; ++i) {
+            Type type = types[i];
+            switch (type.getSort()) {
+            case Type.BOOLEAN:
+            case Type.CHAR:
+            case Type.BYTE:
+            case Type.SHORT:
+            case Type.INT:
+                locals.add(Opcodes.INTEGER);
+                break;
+            case Type.FLOAT:
+                locals.add(Opcodes.FLOAT);
+                break;
+            case Type.LONG:
+                locals.add(Opcodes.LONG);
+                locals.add(Opcodes.TOP);
+                break;
+            case Type.DOUBLE:
+                locals.add(Opcodes.DOUBLE);
+                locals.add(Opcodes.TOP);
+                break;
+            case Type.ARRAY:
+                locals.add(types[i].getDescriptor());
+                break;
+            // case Type.OBJECT:
+            default:
+                locals.add(types[i].getInternalName());
+            }
+        }
+        maxLocals = locals.size();
+    }
+
+    @Override
+    public void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack) {
+        if (type != Opcodes.F_NEW) { // uncompressed frame
+            throw new IllegalStateException(
+                    "ClassReader.accept() should be called with EXPAND_FRAMES flag");
+        }
+
+        if (mv != null) {
+            mv.visitFrame(type, nLocal, local, nStack, stack);
+        }
+
+        if (this.locals != null) {
+            this.locals.clear();
+            this.stack.clear();
+        } else {
+            this.locals = new ArrayList<Object>();
+            this.stack = new ArrayList<Object>();
+        }
+        visitFrameTypes(nLocal, local, this.locals);
+        visitFrameTypes(nStack, stack, this.stack);
+        maxStack = Math.max(maxStack, this.stack.size());
+    }
+
+    private static void visitFrameTypes(final int n, final Object[] types,
+            final List<Object> result) {
+        for (int i = 0; i < n; ++i) {
+            Object type = types[i];
+            result.add(type);
+            if (type == Opcodes.LONG || type == Opcodes.DOUBLE) {
+                result.add(Opcodes.TOP);
+            }
+        }
+    }
+
+    @Override
+    public void visitInsn(final int opcode) {
+        if (mv != null) {
+            mv.visitInsn(opcode);
+        }
+        execute(opcode, 0, null);
+        if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
+                || opcode == Opcodes.ATHROW) {
+            this.locals = null;
+            this.stack = null;
+        }
+    }
+
+    @Override
+    public void visitIntInsn(final int opcode, final int operand) {
+        if (mv != null) {
+            mv.visitIntInsn(opcode, operand);
+        }
+        execute(opcode, operand, null);
+    }
+
+    @Override
+    public void visitVarInsn(final int opcode, final int var) {
+        if (mv != null) {
+            mv.visitVarInsn(opcode, var);
+        }
+        execute(opcode, var, null);
+    }
+
+    @Override
+    public void visitTypeInsn(final int opcode, final String type) {
+        if (opcode == Opcodes.NEW) {
+            if (labels == null) {
+                Label l = new Label();
+                labels = new ArrayList<Label>(3);
+                labels.add(l);
+                if (mv != null) {
+                    mv.visitLabel(l);
+                }
+            }
+            for (int i = 0; i < labels.size(); ++i) {
+                uninitializedTypes.put(labels.get(i), type);
+            }
+        }
+        if (mv != null) {
+            mv.visitTypeInsn(opcode, type);
+        }
+        execute(opcode, 0, type);
+    }
+
+    @Override
+    public void visitFieldInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (mv != null) {
+            mv.visitFieldInsn(opcode, owner, name, desc);
+        }
+        execute(opcode, 0, desc);
+    }
+
+    @Deprecated
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (api >= Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc,
+                opcode == Opcodes.INVOKEINTERFACE);
+    }
+
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    private void doVisitMethodInsn(int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (mv != null) {
+            mv.visitMethodInsn(opcode, owner, name, desc, itf);
+        }
+        if (this.locals == null) {
+            labels = null;
+            return;
+        }
+        pop(desc);
+        if (opcode != Opcodes.INVOKESTATIC) {
+            Object t = pop();
+            if (opcode == Opcodes.INVOKESPECIAL && name.charAt(0) == '<') {
+                Object u;
+                if (t == Opcodes.UNINITIALIZED_THIS) {
+                    u = this.owner;
+                } else {
+                    u = uninitializedTypes.get(t);
+                }
+                for (int i = 0; i < locals.size(); ++i) {
+                    if (locals.get(i) == t) {
+                        locals.set(i, u);
+                    }
+                }
+                for (int i = 0; i < stack.size(); ++i) {
+                    if (stack.get(i) == t) {
+                        stack.set(i, u);
+                    }
+                }
+            }
+        }
+        pushDesc(desc);
+        labels = null;
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        if (mv != null) {
+            mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+        }
+        if (this.locals == null) {
+            labels = null;
+            return;
+        }
+        pop(desc);
+        pushDesc(desc);
+        labels = null;
+    }
+
+    @Override
+    public void visitJumpInsn(final int opcode, final Label label) {
+        if (mv != null) {
+            mv.visitJumpInsn(opcode, label);
+        }
+        execute(opcode, 0, null);
+        if (opcode == Opcodes.GOTO) {
+            this.locals = null;
+            this.stack = null;
+        }
+    }
+
+    @Override
+    public void visitLabel(final Label label) {
+        if (mv != null) {
+            mv.visitLabel(label);
+        }
+        if (labels == null) {
+            labels = new ArrayList<Label>(3);
+        }
+        labels.add(label);
+    }
+
+    @Override
+    public void visitLdcInsn(final Object cst) {
+        if (mv != null) {
+            mv.visitLdcInsn(cst);
+        }
+        if (this.locals == null) {
+            labels = null;
+            return;
+        }
+        if (cst instanceof Integer) {
+            push(Opcodes.INTEGER);
+        } else if (cst instanceof Long) {
+            push(Opcodes.LONG);
+            push(Opcodes.TOP);
+        } else if (cst instanceof Float) {
+            push(Opcodes.FLOAT);
+        } else if (cst instanceof Double) {
+            push(Opcodes.DOUBLE);
+            push(Opcodes.TOP);
+        } else if (cst instanceof String) {
+            push("java/lang/String");
+        } else if (cst instanceof Type) {
+            int sort = ((Type) cst).getSort();
+            if (sort == Type.OBJECT || sort == Type.ARRAY) {
+                push("java/lang/Class");
+            } else if (sort == Type.METHOD) {
+                push("java/lang/invoke/MethodType");
+            } else {
+                throw new IllegalArgumentException();
+            }
+        } else if (cst instanceof Handle) {
+            push("java/lang/invoke/MethodHandle");
+        } else {
+            throw new IllegalArgumentException();
+        }
+        labels = null;
+    }
+
+    @Override
+    public void visitIincInsn(final int var, final int increment) {
+        if (mv != null) {
+            mv.visitIincInsn(var, increment);
+        }
+        execute(Opcodes.IINC, var, null);
+    }
+
+    @Override
+    public void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels) {
+        if (mv != null) {
+            mv.visitTableSwitchInsn(min, max, dflt, labels);
+        }
+        execute(Opcodes.TABLESWITCH, 0, null);
+        this.locals = null;
+        this.stack = null;
+    }
+
+    @Override
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
+        if (mv != null) {
+            mv.visitLookupSwitchInsn(dflt, keys, labels);
+        }
+        execute(Opcodes.LOOKUPSWITCH, 0, null);
+        this.locals = null;
+        this.stack = null;
+    }
+
+    @Override
+    public void visitMultiANewArrayInsn(final String desc, final int dims) {
+        if (mv != null) {
+            mv.visitMultiANewArrayInsn(desc, dims);
+        }
+        execute(Opcodes.MULTIANEWARRAY, dims, desc);
+    }
+
+    @Override
+    public void visitMaxs(final int maxStack, final int maxLocals) {
+        if (mv != null) {
+            this.maxStack = Math.max(this.maxStack, maxStack);
+            this.maxLocals = Math.max(this.maxLocals, maxLocals);
+            mv.visitMaxs(this.maxStack, this.maxLocals);
+        }
+    }
+
+    // ------------------------------------------------------------------------
+
+    private Object get(final int local) {
+        maxLocals = Math.max(maxLocals, local + 1);
+        return local < locals.size() ? locals.get(local) : Opcodes.TOP;
+    }
+
+    private void set(final int local, final Object type) {
+        maxLocals = Math.max(maxLocals, local + 1);
+        while (local >= locals.size()) {
+            locals.add(Opcodes.TOP);
+        }
+        locals.set(local, type);
+    }
+
+    private void push(final Object type) {
+        stack.add(type);
+        maxStack = Math.max(maxStack, stack.size());
+    }
+
+    private void pushDesc(final String desc) {
+        int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
+        switch (desc.charAt(index)) {
+        case 'V':
+            return;
+        case 'Z':
+        case 'C':
+        case 'B':
+        case 'S':
+        case 'I':
+            push(Opcodes.INTEGER);
+            return;
+        case 'F':
+            push(Opcodes.FLOAT);
+            return;
+        case 'J':
+            push(Opcodes.LONG);
+            push(Opcodes.TOP);
+            return;
+        case 'D':
+            push(Opcodes.DOUBLE);
+            push(Opcodes.TOP);
+            return;
+        case '[':
+            if (index == 0) {
+                push(desc);
+            } else {
+                push(desc.substring(index, desc.length()));
+            }
+            break;
+        // case 'L':
+        default:
+            if (index == 0) {
+                push(desc.substring(1, desc.length() - 1));
+            } else {
+                push(desc.substring(index + 1, desc.length() - 1));
+            }
+        }
+    }
+
+    private Object pop() {
+        return stack.remove(stack.size() - 1);
+    }
+
+    private void pop(final int n) {
+        int size = stack.size();
+        int end = size - n;
+        for (int i = size - 1; i >= end; --i) {
+            stack.remove(i);
+        }
+    }
+
+    private void pop(final String desc) {
+        char c = desc.charAt(0);
+        if (c == '(') {
+            int n = 0;
+            Type[] types = Type.getArgumentTypes(desc);
+            for (int i = 0; i < types.length; ++i) {
+                n += types[i].getSize();
+            }
+            pop(n);
+        } else if (c == 'J' || c == 'D') {
+            pop(2);
+        } else {
+            pop(1);
+        }
+    }
+
+    private void execute(final int opcode, final int iarg, final String sarg) {
+        if (this.locals == null) {
+            labels = null;
+            return;
+        }
+        Object t1, t2, t3, t4;
+        switch (opcode) {
+        case Opcodes.NOP:
+        case Opcodes.INEG:
+        case Opcodes.LNEG:
+        case Opcodes.FNEG:
+        case Opcodes.DNEG:
+        case Opcodes.I2B:
+        case Opcodes.I2C:
+        case Opcodes.I2S:
+        case Opcodes.GOTO:
+        case Opcodes.RETURN:
+            break;
+        case Opcodes.ACONST_NULL:
+            push(Opcodes.NULL);
+            break;
+        case Opcodes.ICONST_M1:
+        case Opcodes.ICONST_0:
+        case Opcodes.ICONST_1:
+        case Opcodes.ICONST_2:
+        case Opcodes.ICONST_3:
+        case Opcodes.ICONST_4:
+        case Opcodes.ICONST_5:
+        case Opcodes.BIPUSH:
+        case Opcodes.SIPUSH:
+            push(Opcodes.INTEGER);
+            break;
+        case Opcodes.LCONST_0:
+        case Opcodes.LCONST_1:
+            push(Opcodes.LONG);
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.FCONST_0:
+        case Opcodes.FCONST_1:
+        case Opcodes.FCONST_2:
+            push(Opcodes.FLOAT);
+            break;
+        case Opcodes.DCONST_0:
+        case Opcodes.DCONST_1:
+            push(Opcodes.DOUBLE);
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.ILOAD:
+        case Opcodes.FLOAD:
+        case Opcodes.ALOAD:
+            push(get(iarg));
+            break;
+        case Opcodes.LLOAD:
+        case Opcodes.DLOAD:
+            push(get(iarg));
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.IALOAD:
+        case Opcodes.BALOAD:
+        case Opcodes.CALOAD:
+        case Opcodes.SALOAD:
+            pop(2);
+            push(Opcodes.INTEGER);
+            break;
+        case Opcodes.LALOAD:
+        case Opcodes.D2L:
+            pop(2);
+            push(Opcodes.LONG);
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.FALOAD:
+            pop(2);
+            push(Opcodes.FLOAT);
+            break;
+        case Opcodes.DALOAD:
+        case Opcodes.L2D:
+            pop(2);
+            push(Opcodes.DOUBLE);
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.AALOAD:
+            pop(1);
+            t1 = pop();
+            if (t1 instanceof String) {
+                pushDesc(((String) t1).substring(1));
+            } else {
+                push("java/lang/Object");
+            }
+            break;
+        case Opcodes.ISTORE:
+        case Opcodes.FSTORE:
+        case Opcodes.ASTORE:
+            t1 = pop();
+            set(iarg, t1);
+            if (iarg > 0) {
+                t2 = get(iarg - 1);
+                if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) {
+                    set(iarg - 1, Opcodes.TOP);
+                }
+            }
+            break;
+        case Opcodes.LSTORE:
+        case Opcodes.DSTORE:
+            pop(1);
+            t1 = pop();
+            set(iarg, t1);
+            set(iarg + 1, Opcodes.TOP);
+            if (iarg > 0) {
+                t2 = get(iarg - 1);
+                if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) {
+                    set(iarg - 1, Opcodes.TOP);
+                }
+            }
+            break;
+        case Opcodes.IASTORE:
+        case Opcodes.BASTORE:
+        case Opcodes.CASTORE:
+        case Opcodes.SASTORE:
+        case Opcodes.FASTORE:
+        case Opcodes.AASTORE:
+            pop(3);
+            break;
+        case Opcodes.LASTORE:
+        case Opcodes.DASTORE:
+            pop(4);
+            break;
+        case Opcodes.POP:
+        case Opcodes.IFEQ:
+        case Opcodes.IFNE:
+        case Opcodes.IFLT:
+        case Opcodes.IFGE:
+        case Opcodes.IFGT:
+        case Opcodes.IFLE:
+        case Opcodes.IRETURN:
+        case Opcodes.FRETURN:
+        case Opcodes.ARETURN:
+        case Opcodes.TABLESWITCH:
+        case Opcodes.LOOKUPSWITCH:
+        case Opcodes.ATHROW:
+        case Opcodes.MONITORENTER:
+        case Opcodes.MONITOREXIT:
+        case Opcodes.IFNULL:
+        case Opcodes.IFNONNULL:
+            pop(1);
+            break;
+        case Opcodes.POP2:
+        case Opcodes.IF_ICMPEQ:
+        case Opcodes.IF_ICMPNE:
+        case Opcodes.IF_ICMPLT:
+        case Opcodes.IF_ICMPGE:
+        case Opcodes.IF_ICMPGT:
+        case Opcodes.IF_ICMPLE:
+        case Opcodes.IF_ACMPEQ:
+        case Opcodes.IF_ACMPNE:
+        case Opcodes.LRETURN:
+        case Opcodes.DRETURN:
+            pop(2);
+            break;
+        case Opcodes.DUP:
+            t1 = pop();
+            push(t1);
+            push(t1);
+            break;
+        case Opcodes.DUP_X1:
+            t1 = pop();
+            t2 = pop();
+            push(t1);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.DUP_X2:
+            t1 = pop();
+            t2 = pop();
+            t3 = pop();
+            push(t1);
+            push(t3);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.DUP2:
+            t1 = pop();
+            t2 = pop();
+            push(t2);
+            push(t1);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.DUP2_X1:
+            t1 = pop();
+            t2 = pop();
+            t3 = pop();
+            push(t2);
+            push(t1);
+            push(t3);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.DUP2_X2:
+            t1 = pop();
+            t2 = pop();
+            t3 = pop();
+            t4 = pop();
+            push(t2);
+            push(t1);
+            push(t4);
+            push(t3);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.SWAP:
+            t1 = pop();
+            t2 = pop();
+            push(t1);
+            push(t2);
+            break;
+        case Opcodes.IADD:
+        case Opcodes.ISUB:
+        case Opcodes.IMUL:
+        case Opcodes.IDIV:
+        case Opcodes.IREM:
+        case Opcodes.IAND:
+        case Opcodes.IOR:
+        case Opcodes.IXOR:
+        case Opcodes.ISHL:
+        case Opcodes.ISHR:
+        case Opcodes.IUSHR:
+        case Opcodes.L2I:
+        case Opcodes.D2I:
+        case Opcodes.FCMPL:
+        case Opcodes.FCMPG:
+            pop(2);
+            push(Opcodes.INTEGER);
+            break;
+        case Opcodes.LADD:
+        case Opcodes.LSUB:
+        case Opcodes.LMUL:
+        case Opcodes.LDIV:
+        case Opcodes.LREM:
+        case Opcodes.LAND:
+        case Opcodes.LOR:
+        case Opcodes.LXOR:
+            pop(4);
+            push(Opcodes.LONG);
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.FADD:
+        case Opcodes.FSUB:
+        case Opcodes.FMUL:
+        case Opcodes.FDIV:
+        case Opcodes.FREM:
+        case Opcodes.L2F:
+        case Opcodes.D2F:
+            pop(2);
+            push(Opcodes.FLOAT);
+            break;
+        case Opcodes.DADD:
+        case Opcodes.DSUB:
+        case Opcodes.DMUL:
+        case Opcodes.DDIV:
+        case Opcodes.DREM:
+            pop(4);
+            push(Opcodes.DOUBLE);
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.LSHL:
+        case Opcodes.LSHR:
+        case Opcodes.LUSHR:
+            pop(3);
+            push(Opcodes.LONG);
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.IINC:
+            set(iarg, Opcodes.INTEGER);
+            break;
+        case Opcodes.I2L:
+        case Opcodes.F2L:
+            pop(1);
+            push(Opcodes.LONG);
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.I2F:
+            pop(1);
+            push(Opcodes.FLOAT);
+            break;
+        case Opcodes.I2D:
+        case Opcodes.F2D:
+            pop(1);
+            push(Opcodes.DOUBLE);
+            push(Opcodes.TOP);
+            break;
+        case Opcodes.F2I:
+        case Opcodes.ARRAYLENGTH:
+        case Opcodes.INSTANCEOF:
+            pop(1);
+            push(Opcodes.INTEGER);
+            break;
+        case Opcodes.LCMP:
+        case Opcodes.DCMPL:
+        case Opcodes.DCMPG:
+            pop(4);
+            push(Opcodes.INTEGER);
+            break;
+        case Opcodes.JSR:
+        case Opcodes.RET:
+            throw new RuntimeException("JSR/RET are not supported");
+        case Opcodes.GETSTATIC:
+            pushDesc(sarg);
+            break;
+        case Opcodes.PUTSTATIC:
+            pop(sarg);
+            break;
+        case Opcodes.GETFIELD:
+            pop(1);
+            pushDesc(sarg);
+            break;
+        case Opcodes.PUTFIELD:
+            pop(sarg);
+            pop();
+            break;
+        case Opcodes.NEW:
+            push(labels.get(0));
+            break;
+        case Opcodes.NEWARRAY:
+            pop();
+            switch (iarg) {
+            case Opcodes.T_BOOLEAN:
+                pushDesc("[Z");
+                break;
+            case Opcodes.T_CHAR:
+                pushDesc("[C");
+                break;
+            case Opcodes.T_BYTE:
+                pushDesc("[B");
+                break;
+            case Opcodes.T_SHORT:
+                pushDesc("[S");
+                break;
+            case Opcodes.T_INT:
+                pushDesc("[I");
+                break;
+            case Opcodes.T_FLOAT:
+                pushDesc("[F");
+                break;
+            case Opcodes.T_DOUBLE:
+                pushDesc("[D");
+                break;
+            // case Opcodes.T_LONG:
+            default:
+                pushDesc("[J");
+                break;
+            }
+            break;
+        case Opcodes.ANEWARRAY:
+            pop();
+            pushDesc("[" + Type.getObjectType(sarg));
+            break;
+        case Opcodes.CHECKCAST:
+            pop();
+            pushDesc(Type.getObjectType(sarg).getDescriptor());
+            break;
+        // case Opcodes.MULTIANEWARRAY:
+        default:
+            pop(iarg);
+            pushDesc(sarg);
+            break;
+        }
+        labels = null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java
new file mode 100644
index 0000000..d146a36
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java
@@ -0,0 +1,238 @@
+/***
+ * 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.commons;
+
+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;
+
+/**
+ * A {@link MethodVisitor} that can be used to approximate method size.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class CodeSizeEvaluator extends MethodVisitor implements Opcodes {
+
+    private int minSize;
+
+    private int maxSize;
+
+    public CodeSizeEvaluator(final MethodVisitor mv) {
+        this(Opcodes.ASM5, mv);
+    }
+
+    protected CodeSizeEvaluator(final int api, final MethodVisitor mv) {
+        super(api, mv);
+    }
+
+    public int getMinSize() {
+        return this.minSize;
+    }
+
+    public int getMaxSize() {
+        return this.maxSize;
+    }
+
+    @Override
+    public void visitInsn(final int opcode) {
+        minSize += 1;
+        maxSize += 1;
+        if (mv != null) {
+            mv.visitInsn(opcode);
+        }
+    }
+
+    @Override
+    public void visitIntInsn(final int opcode, final int operand) {
+        if (opcode == SIPUSH) {
+            minSize += 3;
+            maxSize += 3;
+        } else {
+            minSize += 2;
+            maxSize += 2;
+        }
+        if (mv != null) {
+            mv.visitIntInsn(opcode, operand);
+        }
+    }
+
+    @Override
+    public void visitVarInsn(final int opcode, final int var) {
+        if (var < 4 && opcode != RET) {
+            minSize += 1;
+            maxSize += 1;
+        } else if (var >= 256) {
+            minSize += 4;
+            maxSize += 4;
+        } else {
+            minSize += 2;
+            maxSize += 2;
+        }
+        if (mv != null) {
+            mv.visitVarInsn(opcode, var);
+        }
+    }
+
+    @Override
+    public void visitTypeInsn(final int opcode, final String type) {
+        minSize += 3;
+        maxSize += 3;
+        if (mv != null) {
+            mv.visitTypeInsn(opcode, type);
+        }
+    }
+
+    @Override
+    public void visitFieldInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        minSize += 3;
+        maxSize += 3;
+        if (mv != null) {
+            mv.visitFieldInsn(opcode, owner, name, desc);
+        }
+    }
+
+    @Deprecated
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (api >= Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc,
+                opcode == Opcodes.INVOKEINTERFACE);
+    }
+
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    private void doVisitMethodInsn(int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (opcode == INVOKEINTERFACE) {
+            minSize += 5;
+            maxSize += 5;
+        } else {
+            minSize += 3;
+            maxSize += 3;
+        }
+        if (mv != null) {
+            mv.visitMethodInsn(opcode, owner, name, desc, itf);
+        }
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        minSize += 5;
+        maxSize += 5;
+        if (mv != null) {
+            mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+        }
+    }
+
+    @Override
+    public void visitJumpInsn(final int opcode, final Label label) {
+        minSize += 3;
+        if (opcode == GOTO || opcode == JSR) {
+            maxSize += 5;
+        } else {
+            maxSize += 8;
+        }
+        if (mv != null) {
+            mv.visitJumpInsn(opcode, label);
+        }
+    }
+
+    @Override
+    public void visitLdcInsn(final Object cst) {
+        if (cst instanceof Long || cst instanceof Double) {
+            minSize += 3;
+            maxSize += 3;
+        } else {
+            minSize += 2;
+            maxSize += 3;
+        }
+        if (mv != null) {
+            mv.visitLdcInsn(cst);
+        }
+    }
+
+    @Override
+    public void visitIincInsn(final int var, final int increment) {
+        if (var > 255 || increment > 127 || increment < -128) {
+            minSize += 6;
+            maxSize += 6;
+        } else {
+            minSize += 3;
+            maxSize += 3;
+        }
+        if (mv != null) {
+            mv.visitIincInsn(var, increment);
+        }
+    }
+
+    @Override
+    public void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels) {
+        minSize += 13 + labels.length * 4;
+        maxSize += 16 + labels.length * 4;
+        if (mv != null) {
+            mv.visitTableSwitchInsn(min, max, dflt, labels);
+        }
+    }
+
+    @Override
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
+        minSize += 9 + keys.length * 8;
+        maxSize += 12 + keys.length * 8;
+        if (mv != null) {
+            mv.visitLookupSwitchInsn(dflt, keys, labels);
+        }
+    }
+
+    @Override
+    public void visitMultiANewArrayInsn(final String desc, final int dims) {
+        minSize += 4;
+        maxSize += 4;
+        if (mv != null) {
+            mv.visitMultiANewArrayInsn(desc, dims);
+        }
+    }
+}


[15/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java
new file mode 100644
index 0000000..ceb051f
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java
@@ -0,0 +1,1628 @@
+/***
+ * 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.commons;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+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;
+
+/**
+ * A {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor} with convenient methods to generate
+ * code. For example, using this adapter, the class below
+ * 
+ * <pre>
+ * public class Example {
+ *     public static void main(String[] args) {
+ *         System.out.println(&quot;Hello world!&quot;);
+ *     }
+ * }
+ * </pre>
+ * 
+ * can be generated as follows:
+ * 
+ * <pre>
+ * ClassWriter cw = new ClassWriter(true);
+ * cw.visit(V1_1, ACC_PUBLIC, &quot;Example&quot;, null, &quot;java/lang/Object&quot;, null);
+ * 
+ * Method m = Method.getMethod(&quot;void &lt;init&gt; ()&quot;);
+ * GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cw);
+ * mg.loadThis();
+ * mg.invokeConstructor(Type.getType(Object.class), m);
+ * mg.returnValue();
+ * mg.endMethod();
+ * 
+ * m = Method.getMethod(&quot;void main (String[])&quot;);
+ * mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw);
+ * mg.getStatic(Type.getType(System.class), &quot;out&quot;, Type.getType(PrintStream.class));
+ * mg.push(&quot;Hello world!&quot;);
+ * mg.invokeVirtual(Type.getType(PrintStream.class),
+ *         Method.getMethod(&quot;void println (String)&quot;));
+ * mg.returnValue();
+ * mg.endMethod();
+ * 
+ * cw.visitEnd();
+ * </pre>
+ * 
+ * @author Juozas Baliuka
+ * @author Chris Nokleberg
+ * @author Eric Bruneton
+ * @author Prashant Deva
+ */
+public class GeneratorAdapter extends LocalVariablesSorter {
+
+    private static final String CLDESC = "Ljava/lang/Class;";
+
+    private static final Type BYTE_TYPE = Type.getObjectType("java/lang/Byte");
+
+    private static final Type BOOLEAN_TYPE = Type
+            .getObjectType("java/lang/Boolean");
+
+    private static final Type SHORT_TYPE = Type
+            .getObjectType("java/lang/Short");
+
+    private static final Type CHARACTER_TYPE = Type
+            .getObjectType("java/lang/Character");
+
+    private static final Type INTEGER_TYPE = Type
+            .getObjectType("java/lang/Integer");
+
+    private static final Type FLOAT_TYPE = Type
+            .getObjectType("java/lang/Float");
+
+    private static final Type LONG_TYPE = Type.getObjectType("java/lang/Long");
+
+    private static final Type DOUBLE_TYPE = Type
+            .getObjectType("java/lang/Double");
+
+    private static final Type NUMBER_TYPE = Type
+            .getObjectType("java/lang/Number");
+
+    private static final Type OBJECT_TYPE = Type
+            .getObjectType("java/lang/Object");
+
+    private static final Method BOOLEAN_VALUE = Method
+            .getMethod("boolean booleanValue()");
+
+    private static final Method CHAR_VALUE = Method
+            .getMethod("char charValue()");
+
+    private static final Method INT_VALUE = Method.getMethod("int intValue()");
+
+    private static final Method FLOAT_VALUE = Method
+            .getMethod("float floatValue()");
+
+    private static final Method LONG_VALUE = Method
+            .getMethod("long longValue()");
+
+    private static final Method DOUBLE_VALUE = Method
+            .getMethod("double doubleValue()");
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int ADD = Opcodes.IADD;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int SUB = Opcodes.ISUB;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int MUL = Opcodes.IMUL;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int DIV = Opcodes.IDIV;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int REM = Opcodes.IREM;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int NEG = Opcodes.INEG;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int SHL = Opcodes.ISHL;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int SHR = Opcodes.ISHR;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int USHR = Opcodes.IUSHR;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int AND = Opcodes.IAND;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int OR = Opcodes.IOR;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public static final int XOR = Opcodes.IXOR;
+
+    /**
+     * Constant for the {@link #ifCmp ifCmp} method.
+     */
+    public static final int EQ = Opcodes.IFEQ;
+
+    /**
+     * Constant for the {@link #ifCmp ifCmp} method.
+     */
+    public static final int NE = Opcodes.IFNE;
+
+    /**
+     * Constant for the {@link #ifCmp ifCmp} method.
+     */
+    public static final int LT = Opcodes.IFLT;
+
+    /**
+     * Constant for the {@link #ifCmp ifCmp} method.
+     */
+    public static final int GE = Opcodes.IFGE;
+
+    /**
+     * Constant for the {@link #ifCmp ifCmp} method.
+     */
+    public static final int GT = Opcodes.IFGT;
+
+    /**
+     * Constant for the {@link #ifCmp ifCmp} method.
+     */
+    public static final int LE = Opcodes.IFLE;
+
+    /**
+     * Access flags of the method visited by this adapter.
+     */
+    private final int access;
+
+    /**
+     * Return type of the method visited by this adapter.
+     */
+    private final Type returnType;
+
+    /**
+     * Argument types of the method visited by this adapter.
+     */
+    private final Type[] argumentTypes;
+
+    /**
+     * Types of the local variables of the method visited by this adapter.
+     */
+    private final List<Type> localTypes = new ArrayList<Type>();
+
+    /**
+     * Creates a new {@link GeneratorAdapter}. <i>Subclasses must not use this
+     * constructor</i>. Instead, they must use the
+     * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
+     * version.
+     * 
+     * @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}).
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public GeneratorAdapter(final MethodVisitor mv, final int access,
+            final String name, final String desc) {
+        this(Opcodes.ASM5, mv, access, name, desc);
+        if (getClass() != GeneratorAdapter.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Creates a new {@link GeneratorAdapter}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @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 GeneratorAdapter(final int api, final MethodVisitor mv,
+            final int access, final String name, final String desc) {
+        super(api, access, desc, mv);
+        this.access = access;
+        this.returnType = Type.getReturnType(desc);
+        this.argumentTypes = Type.getArgumentTypes(desc);
+    }
+
+    /**
+     * Creates a new {@link GeneratorAdapter}. <i>Subclasses must not use this
+     * constructor</i>. Instead, they must use the
+     * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
+     * version.
+     * 
+     * @param access
+     *            access flags of the adapted method.
+     * @param method
+     *            the adapted method.
+     * @param mv
+     *            the method visitor to which this adapter delegates calls.
+     */
+    public GeneratorAdapter(final int access, final Method method,
+            final MethodVisitor mv) {
+        this(mv, access, null, method.getDescriptor());
+    }
+
+    /**
+     * Creates a new {@link GeneratorAdapter}. <i>Subclasses must not use this
+     * constructor</i>. Instead, they must use the
+     * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
+     * version.
+     * 
+     * @param access
+     *            access flags of the adapted method.
+     * @param method
+     *            the adapted method.
+     * @param signature
+     *            the signature of the adapted method (may be <tt>null</tt>).
+     * @param exceptions
+     *            the exceptions thrown by the adapted method (may be
+     *            <tt>null</tt>).
+     * @param cv
+     *            the class visitor to which this adapter delegates calls.
+     */
+    public GeneratorAdapter(final int access, final Method method,
+            final String signature, final Type[] exceptions,
+            final ClassVisitor cv) {
+        this(access, method, cv
+                .visitMethod(access, method.getName(), method.getDescriptor(),
+                        signature, getInternalNames(exceptions)));
+    }
+
+    /**
+     * Returns the internal names of the given types.
+     * 
+     * @param types
+     *            a set of types.
+     * @return the internal names of the given types.
+     */
+    private static String[] getInternalNames(final Type[] types) {
+        if (types == null) {
+            return null;
+        }
+        String[] names = new String[types.length];
+        for (int i = 0; i < names.length; ++i) {
+            names[i] = types[i].getInternalName();
+        }
+        return names;
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to push constants on the stack
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value
+     *            the value to be pushed on the stack.
+     */
+    public void push(final boolean value) {
+        push(value ? 1 : 0);
+    }
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value
+     *            the value to be pushed on the stack.
+     */
+    public void push(final int value) {
+        if (value >= -1 && value <= 5) {
+            mv.visitInsn(Opcodes.ICONST_0 + value);
+        } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
+            mv.visitIntInsn(Opcodes.BIPUSH, value);
+        } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
+            mv.visitIntInsn(Opcodes.SIPUSH, value);
+        } else {
+            mv.visitLdcInsn(new Integer(value));
+        }
+    }
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value
+     *            the value to be pushed on the stack.
+     */
+    public void push(final long value) {
+        if (value == 0L || value == 1L) {
+            mv.visitInsn(Opcodes.LCONST_0 + (int) value);
+        } else {
+            mv.visitLdcInsn(new Long(value));
+        }
+    }
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value
+     *            the value to be pushed on the stack.
+     */
+    public void push(final float value) {
+        int bits = Float.floatToIntBits(value);
+        if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2
+            mv.visitInsn(Opcodes.FCONST_0 + (int) value);
+        } else {
+            mv.visitLdcInsn(new Float(value));
+        }
+    }
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value
+     *            the value to be pushed on the stack.
+     */
+    public void push(final double value) {
+        long bits = Double.doubleToLongBits(value);
+        if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d
+            mv.visitInsn(Opcodes.DCONST_0 + (int) value);
+        } else {
+            mv.visitLdcInsn(new Double(value));
+        }
+    }
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value
+     *            the value to be pushed on the stack. May be <tt>null</tt>.
+     */
+    public void push(final String value) {
+        if (value == null) {
+            mv.visitInsn(Opcodes.ACONST_NULL);
+        } else {
+            mv.visitLdcInsn(value);
+        }
+    }
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value
+     *            the value to be pushed on the stack.
+     */
+    public void push(final Type value) {
+        if (value == null) {
+            mv.visitInsn(Opcodes.ACONST_NULL);
+        } else {
+            switch (value.getSort()) {
+            case Type.BOOLEAN:
+                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean",
+                        "TYPE", CLDESC);
+                break;
+            case Type.CHAR:
+                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Character",
+                        "TYPE", CLDESC);
+                break;
+            case Type.BYTE:
+                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Byte", "TYPE",
+                        CLDESC);
+                break;
+            case Type.SHORT:
+                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Short", "TYPE",
+                        CLDESC);
+                break;
+            case Type.INT:
+                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Integer",
+                        "TYPE", CLDESC);
+                break;
+            case Type.FLOAT:
+                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Float", "TYPE",
+                        CLDESC);
+                break;
+            case Type.LONG:
+                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Long", "TYPE",
+                        CLDESC);
+                break;
+            case Type.DOUBLE:
+                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Double",
+                        "TYPE", CLDESC);
+                break;
+            default:
+                mv.visitLdcInsn(value);
+            }
+        }
+    }
+
+    /**
+     * Generates the instruction to push a handle on the stack.
+     * 
+     * @param handle
+     *            the handle to be pushed on the stack.
+     */
+    public void push(final Handle handle) {
+        mv.visitLdcInsn(handle);
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to load and store method arguments
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the index of the given method argument in the frame's local
+     * variables array.
+     * 
+     * @param arg
+     *            the index of a method argument.
+     * @return the index of the given method argument in the frame's local
+     *         variables array.
+     */
+    private int getArgIndex(final int arg) {
+        int index = (access & Opcodes.ACC_STATIC) == 0 ? 1 : 0;
+        for (int i = 0; i < arg; i++) {
+            index += argumentTypes[i].getSize();
+        }
+        return index;
+    }
+
+    /**
+     * Generates the instruction to push a local variable on the stack.
+     * 
+     * @param type
+     *            the type of the local variable to be loaded.
+     * @param index
+     *            an index in the frame's local variables array.
+     */
+    private void loadInsn(final Type type, final int index) {
+        mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), index);
+    }
+
+    /**
+     * Generates the instruction to store the top stack value in a local
+     * variable.
+     * 
+     * @param type
+     *            the type of the local variable to be stored.
+     * @param index
+     *            an index in the frame's local variables array.
+     */
+    private void storeInsn(final Type type, final int index) {
+        mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), index);
+    }
+
+    /**
+     * Generates the instruction to load 'this' on the stack.
+     */
+    public void loadThis() {
+        if ((access & Opcodes.ACC_STATIC) != 0) {
+            throw new IllegalStateException(
+                    "no 'this' pointer within static method");
+        }
+        mv.visitVarInsn(Opcodes.ALOAD, 0);
+    }
+
+    /**
+     * Generates the instruction to load the given method argument on the stack.
+     * 
+     * @param arg
+     *            the index of a method argument.
+     */
+    public void loadArg(final int arg) {
+        loadInsn(argumentTypes[arg], getArgIndex(arg));
+    }
+
+    /**
+     * Generates the instructions to load the given method arguments on the
+     * stack.
+     * 
+     * @param arg
+     *            the index of the first method argument to be loaded.
+     * @param count
+     *            the number of method arguments to be loaded.
+     */
+    public void loadArgs(final int arg, final int count) {
+        int index = getArgIndex(arg);
+        for (int i = 0; i < count; ++i) {
+            Type t = argumentTypes[arg + i];
+            loadInsn(t, index);
+            index += t.getSize();
+        }
+    }
+
+    /**
+     * Generates the instructions to load all the method arguments on the stack.
+     */
+    public void loadArgs() {
+        loadArgs(0, argumentTypes.length);
+    }
+
+    /**
+     * Generates the instructions to load all the method arguments on the stack,
+     * as a single object array.
+     */
+    public void loadArgArray() {
+        push(argumentTypes.length);
+        newArray(OBJECT_TYPE);
+        for (int i = 0; i < argumentTypes.length; i++) {
+            dup();
+            push(i);
+            loadArg(i);
+            box(argumentTypes[i]);
+            arrayStore(OBJECT_TYPE);
+        }
+    }
+
+    /**
+     * Generates the instruction to store the top stack value in the given
+     * method argument.
+     * 
+     * @param arg
+     *            the index of a method argument.
+     */
+    public void storeArg(final int arg) {
+        storeInsn(argumentTypes[arg], getArgIndex(arg));
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to load and store local variables
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the type of the given local variable.
+     * 
+     * @param local
+     *            a local variable identifier, as returned by
+     *            {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+     * @return the type of the given local variable.
+     */
+    public Type getLocalType(final int local) {
+        return localTypes.get(local - firstLocal);
+    }
+
+    @Override
+    protected void setLocalType(final int local, final Type type) {
+        int index = local - firstLocal;
+        while (localTypes.size() < index + 1) {
+            localTypes.add(null);
+        }
+        localTypes.set(index, type);
+    }
+
+    /**
+     * Generates the instruction to load the given local variable on the stack.
+     * 
+     * @param local
+     *            a local variable identifier, as returned by
+     *            {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+     */
+    public void loadLocal(final int local) {
+        loadInsn(getLocalType(local), local);
+    }
+
+    /**
+     * Generates the instruction to load the given local variable on the stack.
+     * 
+     * @param local
+     *            a local variable identifier, as returned by
+     *            {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+     * @param type
+     *            the type of this local variable.
+     */
+    public void loadLocal(final int local, final Type type) {
+        setLocalType(local, type);
+        loadInsn(type, local);
+    }
+
+    /**
+     * Generates the instruction to store the top stack value in the given local
+     * variable.
+     * 
+     * @param local
+     *            a local variable identifier, as returned by
+     *            {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+     */
+    public void storeLocal(final int local) {
+        storeInsn(getLocalType(local), local);
+    }
+
+    /**
+     * Generates the instruction to store the top stack value in the given local
+     * variable.
+     * 
+     * @param local
+     *            a local variable identifier, as returned by
+     *            {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+     * @param type
+     *            the type of this local variable.
+     */
+    public void storeLocal(final int local, final Type type) {
+        setLocalType(local, type);
+        storeInsn(type, local);
+    }
+
+    /**
+     * Generates the instruction to load an element from an array.
+     * 
+     * @param type
+     *            the type of the array element to be loaded.
+     */
+    public void arrayLoad(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
+    }
+
+    /**
+     * Generates the instruction to store an element in an array.
+     * 
+     * @param type
+     *            the type of the array element to be stored.
+     */
+    public void arrayStore(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to manage the stack
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates a POP instruction.
+     */
+    public void pop() {
+        mv.visitInsn(Opcodes.POP);
+    }
+
+    /**
+     * Generates a POP2 instruction.
+     */
+    public void pop2() {
+        mv.visitInsn(Opcodes.POP2);
+    }
+
+    /**
+     * Generates a DUP instruction.
+     */
+    public void dup() {
+        mv.visitInsn(Opcodes.DUP);
+    }
+
+    /**
+     * Generates a DUP2 instruction.
+     */
+    public void dup2() {
+        mv.visitInsn(Opcodes.DUP2);
+    }
+
+    /**
+     * Generates a DUP_X1 instruction.
+     */
+    public void dupX1() {
+        mv.visitInsn(Opcodes.DUP_X1);
+    }
+
+    /**
+     * Generates a DUP_X2 instruction.
+     */
+    public void dupX2() {
+        mv.visitInsn(Opcodes.DUP_X2);
+    }
+
+    /**
+     * Generates a DUP2_X1 instruction.
+     */
+    public void dup2X1() {
+        mv.visitInsn(Opcodes.DUP2_X1);
+    }
+
+    /**
+     * Generates a DUP2_X2 instruction.
+     */
+    public void dup2X2() {
+        mv.visitInsn(Opcodes.DUP2_X2);
+    }
+
+    /**
+     * Generates a SWAP instruction.
+     */
+    public void swap() {
+        mv.visitInsn(Opcodes.SWAP);
+    }
+
+    /**
+     * Generates the instructions to swap the top two stack values.
+     * 
+     * @param prev
+     *            type of the top - 1 stack value.
+     * @param type
+     *            type of the top stack value.
+     */
+    public void swap(final Type prev, final Type type) {
+        if (type.getSize() == 1) {
+            if (prev.getSize() == 1) {
+                swap(); // same as dupX1(), pop();
+            } else {
+                dupX2();
+                pop();
+            }
+        } else {
+            if (prev.getSize() == 1) {
+                dup2X1();
+                pop2();
+            } else {
+                dup2X2();
+                pop2();
+            }
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to do mathematical and logical operations
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates the instruction to do the specified mathematical or logical
+     * operation.
+     * 
+     * @param op
+     *            a mathematical or logical operation. Must be one of ADD, SUB,
+     *            MUL, DIV, REM, NEG, SHL, SHR, USHR, AND, OR, XOR.
+     * @param type
+     *            the type of the operand(s) for this operation.
+     */
+    public void math(final int op, final Type type) {
+        mv.visitInsn(type.getOpcode(op));
+    }
+
+    /**
+     * Generates the instructions to compute the bitwise negation of the top
+     * stack value.
+     */
+    public void not() {
+        mv.visitInsn(Opcodes.ICONST_1);
+        mv.visitInsn(Opcodes.IXOR);
+    }
+
+    /**
+     * Generates the instruction to increment the given local variable.
+     * 
+     * @param local
+     *            the local variable to be incremented.
+     * @param amount
+     *            the amount by which the local variable must be incremented.
+     */
+    public void iinc(final int local, final int amount) {
+        mv.visitIincInsn(local, amount);
+    }
+
+    /**
+     * Generates the instructions to cast a numerical value from one type to
+     * another.
+     * 
+     * @param from
+     *            the type of the top stack value
+     * @param to
+     *            the type into which this value must be cast.
+     */
+    public void cast(final Type from, final Type to) {
+        if (from != to) {
+            if (from == Type.DOUBLE_TYPE) {
+                if (to == Type.FLOAT_TYPE) {
+                    mv.visitInsn(Opcodes.D2F);
+                } else if (to == Type.LONG_TYPE) {
+                    mv.visitInsn(Opcodes.D2L);
+                } else {
+                    mv.visitInsn(Opcodes.D2I);
+                    cast(Type.INT_TYPE, to);
+                }
+            } else if (from == Type.FLOAT_TYPE) {
+                if (to == Type.DOUBLE_TYPE) {
+                    mv.visitInsn(Opcodes.F2D);
+                } else if (to == Type.LONG_TYPE) {
+                    mv.visitInsn(Opcodes.F2L);
+                } else {
+                    mv.visitInsn(Opcodes.F2I);
+                    cast(Type.INT_TYPE, to);
+                }
+            } else if (from == Type.LONG_TYPE) {
+                if (to == Type.DOUBLE_TYPE) {
+                    mv.visitInsn(Opcodes.L2D);
+                } else if (to == Type.FLOAT_TYPE) {
+                    mv.visitInsn(Opcodes.L2F);
+                } else {
+                    mv.visitInsn(Opcodes.L2I);
+                    cast(Type.INT_TYPE, to);
+                }
+            } else {
+                if (to == Type.BYTE_TYPE) {
+                    mv.visitInsn(Opcodes.I2B);
+                } else if (to == Type.CHAR_TYPE) {
+                    mv.visitInsn(Opcodes.I2C);
+                } else if (to == Type.DOUBLE_TYPE) {
+                    mv.visitInsn(Opcodes.I2D);
+                } else if (to == Type.FLOAT_TYPE) {
+                    mv.visitInsn(Opcodes.I2F);
+                } else if (to == Type.LONG_TYPE) {
+                    mv.visitInsn(Opcodes.I2L);
+                } else if (to == Type.SHORT_TYPE) {
+                    mv.visitInsn(Opcodes.I2S);
+                }
+            }
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to do boxing and unboxing operations
+    // ------------------------------------------------------------------------
+
+    private static Type getBoxedType(final Type type) {
+        switch (type.getSort()) {
+        case Type.BYTE:
+            return BYTE_TYPE;
+        case Type.BOOLEAN:
+            return BOOLEAN_TYPE;
+        case Type.SHORT:
+            return SHORT_TYPE;
+        case Type.CHAR:
+            return CHARACTER_TYPE;
+        case Type.INT:
+            return INTEGER_TYPE;
+        case Type.FLOAT:
+            return FLOAT_TYPE;
+        case Type.LONG:
+            return LONG_TYPE;
+        case Type.DOUBLE:
+            return DOUBLE_TYPE;
+        }
+        return type;
+    }
+
+    /**
+     * Generates the instructions to box the top stack value. This value is
+     * replaced by its boxed equivalent on top of the stack.
+     * 
+     * @param type
+     *            the type of the top stack value.
+     */
+    public void box(final Type type) {
+        if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
+            return;
+        }
+        if (type == Type.VOID_TYPE) {
+            push((String) null);
+        } else {
+            Type boxed = getBoxedType(type);
+            newInstance(boxed);
+            if (type.getSize() == 2) {
+                // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o
+                dupX2();
+                dupX2();
+                pop();
+            } else {
+                // p -> po -> opo -> oop -> o
+                dupX1();
+                swap();
+            }
+            invokeConstructor(boxed, new Method("<init>", Type.VOID_TYPE,
+                    new Type[] { type }));
+        }
+    }
+
+    /**
+     * Generates the instructions to box the top stack value using Java 5's
+     * valueOf() method. This value is replaced by its boxed equivalent on top
+     * of the stack.
+     * 
+     * @param type
+     *            the type of the top stack value.
+     */
+    public void valueOf(final Type type) {
+        if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
+            return;
+        }
+        if (type == Type.VOID_TYPE) {
+            push((String) null);
+        } else {
+            Type boxed = getBoxedType(type);
+            invokeStatic(boxed, new Method("valueOf", boxed,
+                    new Type[] { type }));
+        }
+    }
+
+    /**
+     * Generates the instructions to unbox the top stack value. This value is
+     * replaced by its unboxed equivalent on top of the stack.
+     * 
+     * @param type
+     *            the type of the top stack value.
+     */
+    public void unbox(final Type type) {
+        Type t = NUMBER_TYPE;
+        Method sig = null;
+        switch (type.getSort()) {
+        case Type.VOID:
+            return;
+        case Type.CHAR:
+            t = CHARACTER_TYPE;
+            sig = CHAR_VALUE;
+            break;
+        case Type.BOOLEAN:
+            t = BOOLEAN_TYPE;
+            sig = BOOLEAN_VALUE;
+            break;
+        case Type.DOUBLE:
+            sig = DOUBLE_VALUE;
+            break;
+        case Type.FLOAT:
+            sig = FLOAT_VALUE;
+            break;
+        case Type.LONG:
+            sig = LONG_VALUE;
+            break;
+        case Type.INT:
+        case Type.SHORT:
+        case Type.BYTE:
+            sig = INT_VALUE;
+        }
+        if (sig == null) {
+            checkCast(type);
+        } else {
+            checkCast(t);
+            invokeVirtual(t, sig);
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to jump to other instructions
+    // ------------------------------------------------------------------------
+
+    /**
+     * Creates a new {@link Label}.
+     * 
+     * @return a new {@link Label}.
+     */
+    public Label newLabel() {
+        return new Label();
+    }
+
+    /**
+     * Marks the current code position with the given label.
+     * 
+     * @param label
+     *            a label.
+     */
+    public void mark(final Label label) {
+        mv.visitLabel(label);
+    }
+
+    /**
+     * Marks the current code position with a new label.
+     * 
+     * @return the label that was created to mark the current code position.
+     */
+    public Label mark() {
+        Label label = new Label();
+        mv.visitLabel(label);
+        return label;
+    }
+
+    /**
+     * Generates the instructions to jump to a label based on the comparison of
+     * the top two stack values.
+     * 
+     * @param type
+     *            the type of the top two stack values.
+     * @param mode
+     *            how these values must be compared. One of EQ, NE, LT, GE, GT,
+     *            LE.
+     * @param label
+     *            where to jump if the comparison result is <tt>true</tt>.
+     */
+    public void ifCmp(final Type type, final int mode, final Label label) {
+        switch (type.getSort()) {
+        case Type.LONG:
+            mv.visitInsn(Opcodes.LCMP);
+            break;
+        case Type.DOUBLE:
+            mv.visitInsn(mode == GE || mode == GT ? Opcodes.DCMPL
+                    : Opcodes.DCMPG);
+            break;
+        case Type.FLOAT:
+            mv.visitInsn(mode == GE || mode == GT ? Opcodes.FCMPL
+                    : Opcodes.FCMPG);
+            break;
+        case Type.ARRAY:
+        case Type.OBJECT:
+            switch (mode) {
+            case EQ:
+                mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
+                return;
+            case NE:
+                mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
+                return;
+            }
+            throw new IllegalArgumentException("Bad comparison for type "
+                    + type);
+        default:
+            int intOp = -1;
+            switch (mode) {
+            case EQ:
+                intOp = Opcodes.IF_ICMPEQ;
+                break;
+            case NE:
+                intOp = Opcodes.IF_ICMPNE;
+                break;
+            case GE:
+                intOp = Opcodes.IF_ICMPGE;
+                break;
+            case LT:
+                intOp = Opcodes.IF_ICMPLT;
+                break;
+            case LE:
+                intOp = Opcodes.IF_ICMPLE;
+                break;
+            case GT:
+                intOp = Opcodes.IF_ICMPGT;
+                break;
+            }
+            mv.visitJumpInsn(intOp, label);
+            return;
+        }
+        mv.visitJumpInsn(mode, label);
+    }
+
+    /**
+     * Generates the instructions to jump to a label based on the comparison of
+     * the top two integer stack values.
+     * 
+     * @param mode
+     *            how these values must be compared. One of EQ, NE, LT, GE, GT,
+     *            LE.
+     * @param label
+     *            where to jump if the comparison result is <tt>true</tt>.
+     */
+    public void ifICmp(final int mode, final Label label) {
+        ifCmp(Type.INT_TYPE, mode, label);
+    }
+
+    /**
+     * Generates the instructions to jump to a label based on the comparison of
+     * the top integer stack value with zero.
+     * 
+     * @param mode
+     *            how these values must be compared. One of EQ, NE, LT, GE, GT,
+     *            LE.
+     * @param label
+     *            where to jump if the comparison result is <tt>true</tt>.
+     */
+    public void ifZCmp(final int mode, final Label label) {
+        mv.visitJumpInsn(mode, label);
+    }
+
+    /**
+     * Generates the instruction to jump to the given label if the top stack
+     * value is null.
+     * 
+     * @param label
+     *            where to jump if the condition is <tt>true</tt>.
+     */
+    public void ifNull(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFNULL, label);
+    }
+
+    /**
+     * Generates the instruction to jump to the given label if the top stack
+     * value is not null.
+     * 
+     * @param label
+     *            where to jump if the condition is <tt>true</tt>.
+     */
+    public void ifNonNull(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFNONNULL, label);
+    }
+
+    /**
+     * Generates the instruction to jump to the given label.
+     * 
+     * @param label
+     *            where to jump if the condition is <tt>true</tt>.
+     */
+    public void goTo(final Label label) {
+        mv.visitJumpInsn(Opcodes.GOTO, label);
+    }
+
+    /**
+     * Generates a RET instruction.
+     * 
+     * @param local
+     *            a local variable identifier, as returned by
+     *            {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+     */
+    public void ret(final int local) {
+        mv.visitVarInsn(Opcodes.RET, local);
+    }
+
+    /**
+     * Generates the instructions for a switch statement.
+     * 
+     * @param keys
+     *            the switch case keys.
+     * @param generator
+     *            a generator to generate the code for the switch cases.
+     */
+    public void tableSwitch(final int[] keys,
+            final TableSwitchGenerator generator) {
+        float density;
+        if (keys.length == 0) {
+            density = 0;
+        } else {
+            density = (float) keys.length
+                    / (keys[keys.length - 1] - keys[0] + 1);
+        }
+        tableSwitch(keys, generator, density >= 0.5f);
+    }
+
+    /**
+     * Generates the instructions for a switch statement.
+     * 
+     * @param keys
+     *            the switch case keys.
+     * @param generator
+     *            a generator to generate the code for the switch cases.
+     * @param useTable
+     *            <tt>true</tt> to use a TABLESWITCH instruction, or
+     *            <tt>false</tt> to use a LOOKUPSWITCH instruction.
+     */
+    public void tableSwitch(final int[] keys,
+            final TableSwitchGenerator generator, final boolean useTable) {
+        for (int i = 1; i < keys.length; ++i) {
+            if (keys[i] < keys[i - 1]) {
+                throw new IllegalArgumentException(
+                        "keys must be sorted ascending");
+            }
+        }
+        Label def = newLabel();
+        Label end = newLabel();
+        if (keys.length > 0) {
+            int len = keys.length;
+            int min = keys[0];
+            int max = keys[len - 1];
+            int range = max - min + 1;
+            if (useTable) {
+                Label[] labels = new Label[range];
+                Arrays.fill(labels, def);
+                for (int i = 0; i < len; ++i) {
+                    labels[keys[i] - min] = newLabel();
+                }
+                mv.visitTableSwitchInsn(min, max, def, labels);
+                for (int i = 0; i < range; ++i) {
+                    Label label = labels[i];
+                    if (label != def) {
+                        mark(label);
+                        generator.generateCase(i + min, end);
+                    }
+                }
+            } else {
+                Label[] labels = new Label[len];
+                for (int i = 0; i < len; ++i) {
+                    labels[i] = newLabel();
+                }
+                mv.visitLookupSwitchInsn(def, keys, labels);
+                for (int i = 0; i < len; ++i) {
+                    mark(labels[i]);
+                    generator.generateCase(keys[i], end);
+                }
+            }
+        }
+        mark(def);
+        generator.generateDefault();
+        mark(end);
+    }
+
+    /**
+     * Generates the instruction to return the top stack value to the caller.
+     */
+    public void returnValue() {
+        mv.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to load and store fields
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates a get field or set field instruction.
+     * 
+     * @param opcode
+     *            the instruction's opcode.
+     * @param ownerType
+     *            the class in which the field is defined.
+     * @param name
+     *            the name of the field.
+     * @param fieldType
+     *            the type of the field.
+     */
+    private void fieldInsn(final int opcode, final Type ownerType,
+            final String name, final Type fieldType) {
+        mv.visitFieldInsn(opcode, ownerType.getInternalName(), name,
+                fieldType.getDescriptor());
+    }
+
+    /**
+     * Generates the instruction to push the value of a static field on the
+     * stack.
+     * 
+     * @param owner
+     *            the class in which the field is defined.
+     * @param name
+     *            the name of the field.
+     * @param type
+     *            the type of the field.
+     */
+    public void getStatic(final Type owner, final String name, final Type type) {
+        fieldInsn(Opcodes.GETSTATIC, owner, name, type);
+    }
+
+    /**
+     * Generates the instruction to store the top stack value in a static field.
+     * 
+     * @param owner
+     *            the class in which the field is defined.
+     * @param name
+     *            the name of the field.
+     * @param type
+     *            the type of the field.
+     */
+    public void putStatic(final Type owner, final String name, final Type type) {
+        fieldInsn(Opcodes.PUTSTATIC, owner, name, type);
+    }
+
+    /**
+     * Generates the instruction to push the value of a non static field on the
+     * stack.
+     * 
+     * @param owner
+     *            the class in which the field is defined.
+     * @param name
+     *            the name of the field.
+     * @param type
+     *            the type of the field.
+     */
+    public void getField(final Type owner, final String name, final Type type) {
+        fieldInsn(Opcodes.GETFIELD, owner, name, type);
+    }
+
+    /**
+     * Generates the instruction to store the top stack value in a non static
+     * field.
+     * 
+     * @param owner
+     *            the class in which the field is defined.
+     * @param name
+     *            the name of the field.
+     * @param type
+     *            the type of the field.
+     */
+    public void putField(final Type owner, final String name, final Type type) {
+        fieldInsn(Opcodes.PUTFIELD, owner, name, type);
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to invoke methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates an invoke method instruction.
+     * 
+     * @param opcode
+     *            the instruction's opcode.
+     * @param type
+     *            the class in which the method is defined.
+     * @param method
+     *            the method to be invoked.
+     */
+    private void invokeInsn(final int opcode, final Type type,
+            final Method method, final boolean itf) {
+        String owner = type.getSort() == Type.ARRAY ? type.getDescriptor()
+                : type.getInternalName();
+        mv.visitMethodInsn(opcode, owner, method.getName(),
+                method.getDescriptor(), itf);
+    }
+
+    /**
+     * Generates the instruction to invoke a normal method.
+     * 
+     * @param owner
+     *            the class in which the method is defined.
+     * @param method
+     *            the method to be invoked.
+     */
+    public void invokeVirtual(final Type owner, final Method method) {
+        invokeInsn(Opcodes.INVOKEVIRTUAL, owner, method, false);
+    }
+
+    /**
+     * Generates the instruction to invoke a constructor.
+     * 
+     * @param type
+     *            the class in which the constructor is defined.
+     * @param method
+     *            the constructor to be invoked.
+     */
+    public void invokeConstructor(final Type type, final Method method) {
+        invokeInsn(Opcodes.INVOKESPECIAL, type, method, false);
+    }
+
+    /**
+     * Generates the instruction to invoke a static method.
+     * 
+     * @param owner
+     *            the class in which the method is defined.
+     * @param method
+     *            the method to be invoked.
+     */
+    public void invokeStatic(final Type owner, final Method method) {
+        invokeInsn(Opcodes.INVOKESTATIC, owner, method, false);
+    }
+
+    /**
+     * Generates the instruction to invoke an interface method.
+     * 
+     * @param owner
+     *            the class in which the method is defined.
+     * @param method
+     *            the method to be invoked.
+     */
+    public void invokeInterface(final Type owner, final Method method) {
+        invokeInsn(Opcodes.INVOKEINTERFACE, owner, method, true);
+    }
+
+    /**
+     * Generates 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.
+     */
+    public void invokeDynamic(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to create objects and arrays
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates a type dependent instruction.
+     * 
+     * @param opcode
+     *            the instruction's opcode.
+     * @param type
+     *            the instruction's operand.
+     */
+    private void typeInsn(final int opcode, final Type type) {
+        mv.visitTypeInsn(opcode, type.getInternalName());
+    }
+
+    /**
+     * Generates the instruction to create a new object.
+     * 
+     * @param type
+     *            the class of the object to be created.
+     */
+    public void newInstance(final Type type) {
+        typeInsn(Opcodes.NEW, type);
+    }
+
+    /**
+     * Generates the instruction to create a new array.
+     * 
+     * @param type
+     *            the type of the array elements.
+     */
+    public void newArray(final Type type) {
+        int typ;
+        switch (type.getSort()) {
+        case Type.BOOLEAN:
+            typ = Opcodes.T_BOOLEAN;
+            break;
+        case Type.CHAR:
+            typ = Opcodes.T_CHAR;
+            break;
+        case Type.BYTE:
+            typ = Opcodes.T_BYTE;
+            break;
+        case Type.SHORT:
+            typ = Opcodes.T_SHORT;
+            break;
+        case Type.INT:
+            typ = Opcodes.T_INT;
+            break;
+        case Type.FLOAT:
+            typ = Opcodes.T_FLOAT;
+            break;
+        case Type.LONG:
+            typ = Opcodes.T_LONG;
+            break;
+        case Type.DOUBLE:
+            typ = Opcodes.T_DOUBLE;
+            break;
+        default:
+            typeInsn(Opcodes.ANEWARRAY, type);
+            return;
+        }
+        mv.visitIntInsn(Opcodes.NEWARRAY, typ);
+    }
+
+    // ------------------------------------------------------------------------
+    // Miscelaneous instructions
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates the instruction to compute the length of an array.
+     */
+    public void arrayLength() {
+        mv.visitInsn(Opcodes.ARRAYLENGTH);
+    }
+
+    /**
+     * Generates the instruction to throw an exception.
+     */
+    public void throwException() {
+        mv.visitInsn(Opcodes.ATHROW);
+    }
+
+    /**
+     * Generates the instructions to create and throw an exception. The
+     * exception class must have a constructor with a single String argument.
+     * 
+     * @param type
+     *            the class of the exception to be thrown.
+     * @param msg
+     *            the detailed message of the exception.
+     */
+    public void throwException(final Type type, final String msg) {
+        newInstance(type);
+        dup();
+        push(msg);
+        invokeConstructor(type, Method.getMethod("void <init> (String)"));
+        throwException();
+    }
+
+    /**
+     * Generates the instruction to check that the top stack value is of the
+     * given type.
+     * 
+     * @param type
+     *            a class or interface type.
+     */
+    public void checkCast(final Type type) {
+        if (!type.equals(OBJECT_TYPE)) {
+            typeInsn(Opcodes.CHECKCAST, type);
+        }
+    }
+
+    /**
+     * Generates the instruction to test if the top stack value is of the given
+     * type.
+     * 
+     * @param type
+     *            a class or interface type.
+     */
+    public void instanceOf(final Type type) {
+        typeInsn(Opcodes.INSTANCEOF, type);
+    }
+
+    /**
+     * Generates the instruction to get the monitor of the top stack value.
+     */
+    public void monitorEnter() {
+        mv.visitInsn(Opcodes.MONITORENTER);
+    }
+
+    /**
+     * Generates the instruction to release the monitor of the top stack value.
+     */
+    public void monitorExit() {
+        mv.visitInsn(Opcodes.MONITOREXIT);
+    }
+
+    // ------------------------------------------------------------------------
+    // Non instructions
+    // ------------------------------------------------------------------------
+
+    /**
+     * Marks the end of the visited method.
+     */
+    public void endMethod() {
+        if ((access & Opcodes.ACC_ABSTRACT) == 0) {
+            mv.visitMaxs(0, 0);
+        }
+        mv.visitEnd();
+    }
+
+    /**
+     * Marks the start of an exception handler.
+     * 
+     * @param start
+     *            beginning of the exception handler's scope (inclusive).
+     * @param end
+     *            end of the exception handler's scope (exclusive).
+     * @param exception
+     *            internal name of the type of exceptions handled by the
+     *            handler.
+     */
+    public void catchException(final Label start, final Label end,
+            final Type exception) {
+        if (exception == null) {
+            mv.visitTryCatchBlock(start, end, mark(), null);
+        } else {
+            mv.visitTryCatchBlock(start, end, mark(),
+                    exception.getInternalName());
+        }
+    }
+}


[13/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java
new file mode 100644
index 0000000..bffd20e
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java
@@ -0,0 +1,223 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureReader;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureWriter;
+
+/**
+ * A class responsible for remapping types and names. Subclasses can override
+ * the following methods:
+ * 
+ * <ul>
+ * <li>{@link #map(String)} - map type</li>
+ * <li>{@link #mapFieldName(String, String, String)} - map field name</li>
+ * <li>{@link #mapMethodName(String, String, String)} - map method name</li>
+ * </ul>
+ * 
+ * @author Eugene Kuleshov
+ */
+public abstract class Remapper {
+
+    public String mapDesc(String desc) {
+        Type t = Type.getType(desc);
+        switch (t.getSort()) {
+        case Type.ARRAY:
+            String s = mapDesc(t.getElementType().getDescriptor());
+            for (int i = 0; i < t.getDimensions(); ++i) {
+                s = '[' + s;
+            }
+            return s;
+        case Type.OBJECT:
+            String newType = map(t.getInternalName());
+            if (newType != null) {
+                return 'L' + newType + ';';
+            }
+        }
+        return desc;
+    }
+
+    private Type mapType(Type t) {
+        switch (t.getSort()) {
+        case Type.ARRAY:
+            String s = mapDesc(t.getElementType().getDescriptor());
+            for (int i = 0; i < t.getDimensions(); ++i) {
+                s = '[' + s;
+            }
+            return Type.getType(s);
+        case Type.OBJECT:
+            s = map(t.getInternalName());
+            return s != null ? Type.getObjectType(s) : t;
+        case Type.METHOD:
+            return Type.getMethodType(mapMethodDesc(t.getDescriptor()));
+        }
+        return t;
+    }
+
+    public String mapType(String type) {
+        if (type == null) {
+            return null;
+        }
+        return mapType(Type.getObjectType(type)).getInternalName();
+    }
+
+    public String[] mapTypes(String[] types) {
+        String[] newTypes = null;
+        boolean needMapping = false;
+        for (int i = 0; i < types.length; i++) {
+            String type = types[i];
+            String newType = map(type);
+            if (newType != null && newTypes == null) {
+                newTypes = new String[types.length];
+                if (i > 0) {
+                    System.arraycopy(types, 0, newTypes, 0, i);
+                }
+                needMapping = true;
+            }
+            if (needMapping) {
+                newTypes[i] = newType == null ? type : newType;
+            }
+        }
+        return needMapping ? newTypes : types;
+    }
+
+    public String mapMethodDesc(String desc) {
+        if ("()V".equals(desc)) {
+            return desc;
+        }
+
+        Type[] args = Type.getArgumentTypes(desc);
+        StringBuffer s = new StringBuffer("(");
+        for (int i = 0; i < args.length; i++) {
+            s.append(mapDesc(args[i].getDescriptor()));
+        }
+        Type returnType = Type.getReturnType(desc);
+        if (returnType == Type.VOID_TYPE) {
+            s.append(")V");
+            return s.toString();
+        }
+        s.append(')').append(mapDesc(returnType.getDescriptor()));
+        return s.toString();
+    }
+
+    public Object mapValue(Object value) {
+        if (value instanceof Type) {
+            return mapType((Type) value);
+        }
+        if (value instanceof Handle) {
+            Handle h = (Handle) value;
+            return new Handle(h.getTag(), mapType(h.getOwner()), mapMethodName(
+                    h.getOwner(), h.getName(), h.getDesc()),
+                    mapMethodDesc(h.getDesc()));
+        }
+        return value;
+    }
+
+    /**
+     * 
+     * @param typeSignature
+     *            true if signature is a FieldTypeSignature, such as the
+     *            signature parameter of the ClassVisitor.visitField or
+     *            MethodVisitor.visitLocalVariable methods
+     */
+    public String mapSignature(String signature, boolean typeSignature) {
+        if (signature == null) {
+            return null;
+        }
+        SignatureReader r = new SignatureReader(signature);
+        SignatureWriter w = new SignatureWriter();
+        SignatureVisitor a = createRemappingSignatureAdapter(w);
+        if (typeSignature) {
+            r.acceptType(a);
+        } else {
+            r.accept(a);
+        }
+        return w.toString();
+    }
+
+    protected SignatureVisitor createRemappingSignatureAdapter(
+            SignatureVisitor v) {
+        return new RemappingSignatureAdapter(v, this);
+    }
+
+    /**
+     * Map method name to the new name. Subclasses can override.
+     * 
+     * @param owner
+     *            owner of the method.
+     * @param name
+     *            name of the method.
+     * @param desc
+     *            descriptor of the method.
+     * @return new name of the method
+     */
+    public String mapMethodName(String owner, String name, String desc) {
+        return name;
+    }
+
+    /**
+     * Map invokedynamic method name to the new name. Subclasses can override.
+     * 
+     * @param name
+     *            name of the invokedynamic.
+     * @param desc
+     *            descriptor of the invokedynamic.
+     * @return new invokdynamic name.
+     */
+    public String mapInvokeDynamicMethodName(String name, String desc) {
+        return name;
+    }
+
+    /**
+     * Map field name to the new name. Subclasses can override.
+     * 
+     * @param owner
+     *            owner of the field.
+     * @param name
+     *            name of the field
+     * @param desc
+     *            descriptor of the field
+     * @return new name of the field.
+     */
+    public String mapFieldName(String owner, String name, String desc) {
+        return name;
+    }
+
+    /**
+     * Map type name to the new name. Subclasses can override.
+     */
+    public String map(String typeName) {
+        return typeName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java
new file mode 100644
index 0000000..2f253dd
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java
@@ -0,0 +1,79 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
+/**
+ * An {@link AnnotationVisitor} adapter for type remapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingAnnotationAdapter extends AnnotationVisitor {
+
+    protected final Remapper remapper;
+
+    public RemappingAnnotationAdapter(final AnnotationVisitor av,
+            final Remapper remapper) {
+        this(Opcodes.ASM5, av, remapper);
+    }
+
+    protected RemappingAnnotationAdapter(final int api,
+            final AnnotationVisitor av, final Remapper remapper) {
+        super(api, av);
+        this.remapper = remapper;
+    }
+
+    @Override
+    public void visit(String name, Object value) {
+        av.visit(name, remapper.mapValue(value));
+    }
+
+    @Override
+    public void visitEnum(String name, String desc, String value) {
+        av.visitEnum(name, remapper.mapDesc(desc), value);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(String name, String desc) {
+        AnnotationVisitor v = av.visitAnnotation(name, remapper.mapDesc(desc));
+        return v == null ? null : (v == av ? this
+                : new RemappingAnnotationAdapter(v, remapper));
+    }
+
+    @Override
+    public AnnotationVisitor visitArray(String name) {
+        AnnotationVisitor v = av.visitArray(name);
+        return v == null ? null : (v == av ? this
+                : new RemappingAnnotationAdapter(v, remapper));
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java
new file mode 100644
index 0000000..7dbae24
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java
@@ -0,0 +1,135 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A {@link ClassVisitor} for type remapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingClassAdapter extends ClassVisitor {
+
+    protected final Remapper remapper;
+
+    protected String className;
+
+    public RemappingClassAdapter(final ClassVisitor cv, final Remapper remapper) {
+        this(Opcodes.ASM5, cv, remapper);
+    }
+
+    protected RemappingClassAdapter(final int api, final ClassVisitor cv,
+            final Remapper remapper) {
+        super(api, cv);
+        this.remapper = remapper;
+    }
+
+    @Override
+    public void visit(int version, int access, String name, String signature,
+            String superName, String[] interfaces) {
+        this.className = name;
+        super.visit(version, access, remapper.mapType(name), remapper
+                .mapSignature(signature, false), remapper.mapType(superName),
+                interfaces == null ? null : remapper.mapTypes(interfaces));
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
+                visible);
+        return av == null ? null : createRemappingAnnotationAdapter(av);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
+                remapper.mapDesc(desc), visible);
+        return av == null ? null : createRemappingAnnotationAdapter(av);
+    }
+
+    @Override
+    public FieldVisitor visitField(int access, String name, String desc,
+            String signature, Object value) {
+        FieldVisitor fv = super.visitField(access,
+                remapper.mapFieldName(className, name, desc),
+                remapper.mapDesc(desc), remapper.mapSignature(signature, true),
+                remapper.mapValue(value));
+        return fv == null ? null : createRemappingFieldAdapter(fv);
+    }
+
+    @Override
+    public MethodVisitor visitMethod(int access, String name, String desc,
+            String signature, String[] exceptions) {
+        String newDesc = remapper.mapMethodDesc(desc);
+        MethodVisitor mv = super.visitMethod(access, remapper.mapMethodName(
+                className, name, desc), newDesc, remapper.mapSignature(
+                signature, false),
+                exceptions == null ? null : remapper.mapTypes(exceptions));
+        return mv == null ? null : createRemappingMethodAdapter(access,
+                newDesc, mv);
+    }
+
+    @Override
+    public void visitInnerClass(String name, String outerName,
+            String innerName, int access) {
+        // TODO should innerName be changed?
+        super.visitInnerClass(remapper.mapType(name), outerName == null ? null
+                : remapper.mapType(outerName), innerName, access);
+    }
+
+    @Override
+    public void visitOuterClass(String owner, String name, String desc) {
+        super.visitOuterClass(remapper.mapType(owner), name == null ? null
+                : remapper.mapMethodName(owner, name, desc),
+                desc == null ? null : remapper.mapMethodDesc(desc));
+    }
+
+    protected FieldVisitor createRemappingFieldAdapter(FieldVisitor fv) {
+        return new RemappingFieldAdapter(fv, remapper);
+    }
+
+    protected MethodVisitor createRemappingMethodAdapter(int access,
+            String newDesc, MethodVisitor mv) {
+        return new RemappingMethodAdapter(access, newDesc, mv, remapper);
+    }
+
+    protected AnnotationVisitor createRemappingAnnotationAdapter(
+            AnnotationVisitor av) {
+        return new RemappingAnnotationAdapter(av, remapper);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java
new file mode 100644
index 0000000..8a8420d
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java
@@ -0,0 +1,71 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A {@link FieldVisitor} adapter for type remapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingFieldAdapter extends FieldVisitor {
+
+    private final Remapper remapper;
+
+    public RemappingFieldAdapter(final FieldVisitor fv, final Remapper remapper) {
+        this(Opcodes.ASM5, fv, remapper);
+    }
+
+    protected RemappingFieldAdapter(final int api, final FieldVisitor fv,
+            final Remapper remapper) {
+        super(api, fv);
+        this.remapper = remapper;
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        AnnotationVisitor av = fv.visitAnnotation(remapper.mapDesc(desc),
+                visible);
+        return av == null ? null : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
+                remapper.mapDesc(desc), visible);
+        return av == null ? null : new RemappingAnnotationAdapter(av, remapper);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java
new file mode 100644
index 0000000..1dec924
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java
@@ -0,0 +1,224 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+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.TypePath;
+
+/**
+ * A {@link LocalVariablesSorter} for type mapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingMethodAdapter extends LocalVariablesSorter {
+
+    protected final Remapper remapper;
+
+    public RemappingMethodAdapter(final int access, final String desc,
+            final MethodVisitor mv, final Remapper remapper) {
+        this(Opcodes.ASM5, access, desc, mv, remapper);
+    }
+
+    protected RemappingMethodAdapter(final int api, final int access,
+            final String desc, final MethodVisitor mv, final Remapper remapper) {
+        super(api, access, desc, mv);
+        this.remapper = remapper;
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotationDefault() {
+        AnnotationVisitor av = super.visitAnnotationDefault();
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
+                visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
+                remapper.mapDesc(desc), visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public AnnotationVisitor visitParameterAnnotation(int parameter,
+            String desc, boolean visible) {
+        AnnotationVisitor av = super.visitParameterAnnotation(parameter,
+                remapper.mapDesc(desc), visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public void visitFrame(int type, int nLocal, Object[] local, int nStack,
+            Object[] stack) {
+        super.visitFrame(type, nLocal, remapEntries(nLocal, local), nStack,
+                remapEntries(nStack, stack));
+    }
+
+    private Object[] remapEntries(int n, Object[] entries) {
+        for (int i = 0; i < n; i++) {
+            if (entries[i] instanceof String) {
+                Object[] newEntries = new Object[n];
+                if (i > 0) {
+                    System.arraycopy(entries, 0, newEntries, 0, i);
+                }
+                do {
+                    Object t = entries[i];
+                    newEntries[i++] = t instanceof String ? remapper
+                            .mapType((String) t) : t;
+                } while (i < n);
+                return newEntries;
+            }
+        }
+        return entries;
+    }
+
+    @Override
+    public void visitFieldInsn(int opcode, String owner, String name,
+            String desc) {
+        super.visitFieldInsn(opcode, remapper.mapType(owner),
+                remapper.mapFieldName(owner, name, desc),
+                remapper.mapDesc(desc));
+    }
+
+    @Deprecated
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (api >= Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc,
+                opcode == Opcodes.INVOKEINTERFACE);
+    }
+
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    private void doVisitMethodInsn(int opcode, String owner, String name,
+            String desc, boolean itf) {
+        // Calling super.visitMethodInsn requires to call the correct version
+        // depending on this.api (otherwise infinite loops can occur). To
+        // simplify and to make it easier to automatically remove the backward
+        // compatibility code, we inline the code of the overridden method here.
+        // IMPORTANT: THIS ASSUMES THAT visitMethodInsn IS NOT OVERRIDDEN IN
+        // LocalVariableSorter.
+        if (mv != null) {
+            mv.visitMethodInsn(opcode, remapper.mapType(owner),
+                    remapper.mapMethodName(owner, name, desc),
+                    remapper.mapMethodDesc(desc), itf);
+        }
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        for (int i = 0; i < bsmArgs.length; i++) {
+            bsmArgs[i] = remapper.mapValue(bsmArgs[i]);
+        }
+        super.visitInvokeDynamicInsn(
+                remapper.mapInvokeDynamicMethodName(name, desc),
+                remapper.mapMethodDesc(desc), (Handle) remapper.mapValue(bsm),
+                bsmArgs);
+    }
+
+    @Override
+    public void visitTypeInsn(int opcode, String type) {
+        super.visitTypeInsn(opcode, remapper.mapType(type));
+    }
+
+    @Override
+    public void visitLdcInsn(Object cst) {
+        super.visitLdcInsn(remapper.mapValue(cst));
+    }
+
+    @Override
+    public void visitMultiANewArrayInsn(String desc, int dims) {
+        super.visitMultiANewArrayInsn(remapper.mapDesc(desc), dims);
+    }
+
+    @Override
+    public AnnotationVisitor visitInsnAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        AnnotationVisitor av = super.visitInsnAnnotation(typeRef, typePath,
+                remapper.mapDesc(desc), visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public void visitTryCatchBlock(Label start, Label end, Label handler,
+            String type) {
+        super.visitTryCatchBlock(start, end, handler, type == null ? null
+                : remapper.mapType(type));
+    }
+
+    @Override
+    public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        AnnotationVisitor av = super.visitTryCatchAnnotation(typeRef, typePath,
+                remapper.mapDesc(desc), visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    @Override
+    public void visitLocalVariable(String name, String desc, String signature,
+            Label start, Label end, int index) {
+        super.visitLocalVariable(name, remapper.mapDesc(desc),
+                remapper.mapSignature(signature, true), start, end, index);
+    }
+
+    @Override
+    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+            TypePath typePath, Label[] start, Label[] end, int[] index,
+            String desc, boolean visible) {
+        AnnotationVisitor av = super.visitLocalVariableAnnotation(typeRef,
+                typePath, start, end, index, remapper.mapDesc(desc), visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java
new file mode 100644
index 0000000..ff608a4
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java
@@ -0,0 +1,155 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
+
+/**
+ * A {@link SignatureVisitor} adapter for type mapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingSignatureAdapter extends SignatureVisitor {
+
+    private final SignatureVisitor v;
+
+    private final Remapper remapper;
+
+    private String className;
+
+    public RemappingSignatureAdapter(final SignatureVisitor v,
+            final Remapper remapper) {
+        this(Opcodes.ASM5, v, remapper);
+    }
+
+    protected RemappingSignatureAdapter(final int api,
+            final SignatureVisitor v, final Remapper remapper) {
+        super(api);
+        this.v = v;
+        this.remapper = remapper;
+    }
+
+    @Override
+    public void visitClassType(String name) {
+        className = name;
+        v.visitClassType(remapper.mapType(name));
+    }
+
+    @Override
+    public void visitInnerClassType(String name) {
+        String remappedOuter = remapper.mapType(className) + '$';
+        className = className + '$' + name;
+        String remappedName = remapper.mapType(className);
+        int index = remappedName.startsWith(remappedOuter) ? remappedOuter
+                .length() : remappedName.lastIndexOf('$') + 1;
+        v.visitInnerClassType(remappedName.substring(index));
+    }
+
+    @Override
+    public void visitFormalTypeParameter(String name) {
+        v.visitFormalTypeParameter(name);
+    }
+
+    @Override
+    public void visitTypeVariable(String name) {
+        v.visitTypeVariable(name);
+    }
+
+    @Override
+    public SignatureVisitor visitArrayType() {
+        v.visitArrayType();
+        return this;
+    }
+
+    @Override
+    public void visitBaseType(char descriptor) {
+        v.visitBaseType(descriptor);
+    }
+
+    @Override
+    public SignatureVisitor visitClassBound() {
+        v.visitClassBound();
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitExceptionType() {
+        v.visitExceptionType();
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitInterface() {
+        v.visitInterface();
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitInterfaceBound() {
+        v.visitInterfaceBound();
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitParameterType() {
+        v.visitParameterType();
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitReturnType() {
+        v.visitReturnType();
+        return this;
+    }
+
+    @Override
+    public SignatureVisitor visitSuperclass() {
+        v.visitSuperclass();
+        return this;
+    }
+
+    @Override
+    public void visitTypeArgument() {
+        v.visitTypeArgument();
+    }
+
+    @Override
+    public SignatureVisitor visitTypeArgument(char wildcard) {
+        v.visitTypeArgument(wildcard);
+        return this;
+    }
+
+    @Override
+    public void visitEnd() {
+        v.visitEnd();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
new file mode 100644
index 0000000..04dcc9b
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
@@ -0,0 +1,540 @@
+/***
+ * 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.commons;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
+/**
+ * A {@link ClassVisitor} that adds a serial version unique identifier to a
+ * class if missing. Here is typical usage of this class:
+ * 
+ * <pre>
+ *   ClassWriter cw = new ClassWriter(...);
+ *   ClassVisitor sv = new SerialVersionUIDAdder(cw);
+ *   ClassVisitor ca = new MyClassAdapter(sv);
+ *   new ClassReader(orginalClass).accept(ca, false);
+ * </pre>
+ * 
+ * The SVUID algorithm can be found <a href=
+ * "http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html"
+ * >http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html</a>:
+ * 
+ * <pre>
+ * The serialVersionUID is computed using the signature of a stream of bytes
+ * that reflect the class definition. The National Institute of Standards and
+ * Technology (NIST) Secure Hash Algorithm (SHA-1) is used to compute a
+ * signature for the stream. The first two 32-bit quantities are used to form a
+ * 64-bit hash. A java.lang.DataOutputStream is used to convert primitive data
+ * types to a sequence of bytes. The values input to the stream are defined by
+ * the Java Virtual Machine (VM) specification for classes.
+ * 
+ * The sequence of items in the stream is as follows:
+ * 
+ * 1. The class name written using UTF encoding.
+ * 2. The class modifiers written as a 32-bit integer.
+ * 3. The name of each interface sorted by name written using UTF encoding.
+ * 4. For each field of the class sorted by field name (except private static
+ * and private transient fields):
+ * 1. The name of the field in UTF encoding.
+ * 2. The modifiers of the field written as a 32-bit integer.
+ * 3. The descriptor of the field in UTF encoding
+ * 5. If a class initializer exists, write out the following:
+ * 1. The name of the method, &lt;clinit&gt;, in UTF encoding.
+ * 2. The modifier of the method, java.lang.reflect.Modifier.STATIC,
+ * written as a 32-bit integer.
+ * 3. The descriptor of the method, ()V, in UTF encoding.
+ * 6. For each non-private constructor sorted by method name and signature:
+ * 1. The name of the method, &lt;init&gt;, in UTF encoding.
+ * 2. The modifiers of the method written as a 32-bit integer.
+ * 3. The descriptor of the method in UTF encoding.
+ * 7. For each non-private method sorted by method name and signature:
+ * 1. The name of the method in UTF encoding.
+ * 2. The modifiers of the method written as a 32-bit integer.
+ * 3. The descriptor of the method in UTF encoding.
+ * 8. The SHA-1 algorithm is executed on the stream of bytes produced by
+ * DataOutputStream and produces five 32-bit values sha[0..4].
+ * 
+ * 9. The hash value is assembled from the first and second 32-bit values of
+ * the SHA-1 message digest. If the result of the message digest, the five
+ * 32-bit words H0 H1 H2 H3 H4, is in an array of five int values named
+ * sha, the hash value would be computed as follows:
+ * 
+ * long hash = ((sha[0] &gt;&gt;&gt; 24) &amp; 0xFF) |
+ * ((sha[0] &gt;&gt;&gt; 16) &amp; 0xFF) &lt;&lt; 8 |
+ * ((sha[0] &gt;&gt;&gt; 8) &amp; 0xFF) &lt;&lt; 16 |
+ * ((sha[0] &gt;&gt;&gt; 0) &amp; 0xFF) &lt;&lt; 24 |
+ * ((sha[1] &gt;&gt;&gt; 24) &amp; 0xFF) &lt;&lt; 32 |
+ * ((sha[1] &gt;&gt;&gt; 16) &amp; 0xFF) &lt;&lt; 40 |
+ * ((sha[1] &gt;&gt;&gt; 8) &amp; 0xFF) &lt;&lt; 48 |
+ * ((sha[1] &gt;&gt;&gt; 0) &amp; 0xFF) &lt;&lt; 56;
+ * </pre>
+ * 
+ * @author Rajendra Inamdar, Vishal Vishnoi
+ */
+public class SerialVersionUIDAdder extends ClassVisitor {
+
+    /**
+     * Flag that indicates if we need to compute SVUID.
+     */
+    private boolean computeSVUID;
+
+    /**
+     * Set to true if the class already has SVUID.
+     */
+    private boolean hasSVUID;
+
+    /**
+     * Classes access flags.
+     */
+    private int access;
+
+    /**
+     * Internal name of the class
+     */
+    private String name;
+
+    /**
+     * Interfaces implemented by the class.
+     */
+    private String[] interfaces;
+
+    /**
+     * Collection of fields. (except private static and private transient
+     * fields)
+     */
+    private Collection<Item> svuidFields;
+
+    /**
+     * Set to true if the class has static initializer.
+     */
+    private boolean hasStaticInitializer;
+
+    /**
+     * Collection of non-private constructors.
+     */
+    private Collection<Item> svuidConstructors;
+
+    /**
+     * Collection of non-private methods.
+     */
+    private Collection<Item> svuidMethods;
+
+    /**
+     * Creates a new {@link SerialVersionUIDAdder}. <i>Subclasses must not use
+     * this constructor</i>. Instead, they must use the
+     * {@link #SerialVersionUIDAdder(int, ClassVisitor)} version.
+     * 
+     * @param cv
+     *            a {@link ClassVisitor} to which this visitor will delegate
+     *            calls.
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public SerialVersionUIDAdder(final ClassVisitor cv) {
+        this(Opcodes.ASM5, cv);
+        if (getClass() != SerialVersionUIDAdder.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Creates a new {@link SerialVersionUIDAdder}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param cv
+     *            a {@link ClassVisitor} to which this visitor will delegate
+     *            calls.
+     */
+    protected SerialVersionUIDAdder(final int api, final ClassVisitor cv) {
+        super(api, cv);
+        svuidFields = new ArrayList<Item>();
+        svuidConstructors = new ArrayList<Item>();
+        svuidMethods = new ArrayList<Item>();
+    }
+
+    // ------------------------------------------------------------------------
+    // Overridden methods
+    // ------------------------------------------------------------------------
+
+    /*
+     * Visit class header and get class name, access , and interfaces
+     * information (step 1,2, and 3) for SVUID computation.
+     */
+    @Override
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
+        computeSVUID = (access & Opcodes.ACC_INTERFACE) == 0;
+
+        if (computeSVUID) {
+            this.name = name;
+            this.access = access;
+            this.interfaces = new String[interfaces.length];
+            System.arraycopy(interfaces, 0, this.interfaces, 0,
+                    interfaces.length);
+        }
+
+        super.visit(version, access, name, signature, superName, interfaces);
+    }
+
+    /*
+     * Visit the methods and get constructor and method information (step 5 and
+     * 7). Also determine if there is a class initializer (step 6).
+     */
+    @Override
+    public MethodVisitor visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        if (computeSVUID) {
+            if ("<clinit>".equals(name)) {
+                hasStaticInitializer = true;
+            }
+            /*
+             * Remembers non private constructors and methods for SVUID
+             * computation For constructor and method modifiers, only the
+             * ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
+             * ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT and ACC_STRICT flags
+             * are used.
+             */
+            int mods = access
+                    & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE
+                            | Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
+                            | Opcodes.ACC_FINAL | Opcodes.ACC_SYNCHRONIZED
+                            | Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_STRICT);
+
+            // all non private methods
+            if ((access & Opcodes.ACC_PRIVATE) == 0) {
+                if ("<init>".equals(name)) {
+                    svuidConstructors.add(new Item(name, mods, desc));
+                } else if (!"<clinit>".equals(name)) {
+                    svuidMethods.add(new Item(name, mods, desc));
+                }
+            }
+        }
+
+        return super.visitMethod(access, name, desc, signature, exceptions);
+    }
+
+    /*
+     * Gets class field information for step 4 of the algorithm. Also determines
+     * if the class already has a SVUID.
+     */
+    @Override
+    public FieldVisitor visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
+        if (computeSVUID) {
+            if ("serialVersionUID".equals(name)) {
+                // since the class already has SVUID, we won't be computing it.
+                computeSVUID = false;
+                hasSVUID = true;
+            }
+            /*
+             * Remember field for SVUID computation For field modifiers, only
+             * the ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC,
+             * ACC_FINAL, ACC_VOLATILE, and ACC_TRANSIENT flags are used when
+             * computing serialVersionUID values.
+             */
+            if ((access & Opcodes.ACC_PRIVATE) == 0
+                    || (access & (Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT)) == 0) {
+                int mods = access
+                        & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE
+                                | Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
+                                | Opcodes.ACC_FINAL | Opcodes.ACC_VOLATILE | Opcodes.ACC_TRANSIENT);
+                svuidFields.add(new Item(name, mods, desc));
+            }
+        }
+
+        return super.visitField(access, name, desc, signature, value);
+    }
+
+    /**
+     * Handle a bizarre special case. Nested classes (static classes declared
+     * inside another class) that are protected have their access bit set to
+     * public in their class files to deal with some odd reflection situation.
+     * Our SVUID computation must do as the JVM does and ignore access bits in
+     * the class file in favor of the access bits InnerClass attribute.
+     */
+    @Override
+    public void visitInnerClass(final String aname, final String outerName,
+            final String innerName, final int attr_access) {
+        if ((name != null) && name.equals(aname)) {
+            this.access = attr_access;
+        }
+        super.visitInnerClass(aname, outerName, innerName, attr_access);
+    }
+
+    /*
+     * Add the SVUID if class doesn't have one
+     */
+    @Override
+    public void visitEnd() {
+        // compute SVUID and add it to the class
+        if (computeSVUID && !hasSVUID) {
+            try {
+                addSVUID(computeSVUID());
+            } catch (Throwable e) {
+                throw new RuntimeException("Error while computing SVUID for "
+                        + name, e);
+            }
+        }
+
+        super.visitEnd();
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns true if the class already has a SVUID field. The result of this
+     * method is only valid when visitEnd is or has been called.
+     * 
+     * @return true if the class already has a SVUID field.
+     */
+    public boolean hasSVUID() {
+        return hasSVUID;
+    }
+
+    protected void addSVUID(long svuid) {
+        FieldVisitor fv = super.visitField(Opcodes.ACC_FINAL
+                + Opcodes.ACC_STATIC, "serialVersionUID", "J", null, new Long(
+                svuid));
+        if (fv != null) {
+            fv.visitEnd();
+        }
+    }
+
+    /**
+     * Computes and returns the value of SVUID.
+     * 
+     * @return Returns the serial version UID
+     * @throws IOException
+     *             if an I/O error occurs
+     */
+    protected long computeSVUID() throws IOException {
+        ByteArrayOutputStream bos;
+        DataOutputStream dos = null;
+        long svuid = 0;
+
+        try {
+            bos = new ByteArrayOutputStream();
+            dos = new DataOutputStream(bos);
+
+            /*
+             * 1. The class name written using UTF encoding.
+             */
+            dos.writeUTF(name.replace('/', '.'));
+
+            /*
+             * 2. The class modifiers written as a 32-bit integer.
+             */
+            dos.writeInt(access
+                    & (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL
+                            | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT));
+
+            /*
+             * 3. The name of each interface sorted by name written using UTF
+             * encoding.
+             */
+            Arrays.sort(interfaces);
+            for (int i = 0; i < interfaces.length; i++) {
+                dos.writeUTF(interfaces[i].replace('/', '.'));
+            }
+
+            /*
+             * 4. For each field of the class sorted by field name (except
+             * private static and private transient fields):
+             * 
+             * 1. The name of the field in UTF encoding. 2. The modifiers of the
+             * field written as a 32-bit integer. 3. The descriptor of the field
+             * in UTF encoding
+             * 
+             * Note that field signatures are not dot separated. Method and
+             * constructor signatures are dot separated. Go figure...
+             */
+            writeItems(svuidFields, dos, false);
+
+            /*
+             * 5. If a class initializer exists, write out the following: 1. The
+             * name of the method, <clinit>, in UTF encoding. 2. The modifier of
+             * the method, java.lang.reflect.Modifier.STATIC, written as a
+             * 32-bit integer. 3. The descriptor of the method, ()V, in UTF
+             * encoding.
+             */
+            if (hasStaticInitializer) {
+                dos.writeUTF("<clinit>");
+                dos.writeInt(Opcodes.ACC_STATIC);
+                dos.writeUTF("()V");
+            } // if..
+
+            /*
+             * 6. For each non-private constructor sorted by method name and
+             * signature: 1. The name of the method, <init>, in UTF encoding. 2.
+             * The modifiers of the method written as a 32-bit integer. 3. The
+             * descriptor of the method in UTF encoding.
+             */
+            writeItems(svuidConstructors, dos, true);
+
+            /*
+             * 7. For each non-private method sorted by method name and
+             * signature: 1. The name of the method in UTF encoding. 2. The
+             * modifiers of the method written as a 32-bit integer. 3. The
+             * descriptor of the method in UTF encoding.
+             */
+            writeItems(svuidMethods, dos, true);
+
+            dos.flush();
+
+            /*
+             * 8. The SHA-1 algorithm is executed on the stream of bytes
+             * produced by DataOutputStream and produces five 32-bit values
+             * sha[0..4].
+             */
+            byte[] hashBytes = computeSHAdigest(bos.toByteArray());
+
+            /*
+             * 9. The hash value is assembled from the first and second 32-bit
+             * values of the SHA-1 message digest. If the result of the message
+             * digest, the five 32-bit words H0 H1 H2 H3 H4, is in an array of
+             * five int values named sha, the hash value would be computed as
+             * follows:
+             * 
+             * long hash = ((sha[0] >>> 24) & 0xFF) | ((sha[0] >>> 16) & 0xFF)
+             * << 8 | ((sha[0] >>> 8) & 0xFF) << 16 | ((sha[0] >>> 0) & 0xFF) <<
+             * 24 | ((sha[1] >>> 24) & 0xFF) << 32 | ((sha[1] >>> 16) & 0xFF) <<
+             * 40 | ((sha[1] >>> 8) & 0xFF) << 48 | ((sha[1] >>> 0) & 0xFF) <<
+             * 56;
+             */
+            for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
+                svuid = (svuid << 8) | (hashBytes[i] & 0xFF);
+            }
+        } finally {
+            // close the stream (if open)
+            if (dos != null) {
+                dos.close();
+            }
+        }
+
+        return svuid;
+    }
+
+    /**
+     * Returns the SHA-1 message digest of the given value.
+     * 
+     * @param value
+     *            the value whose SHA message digest must be computed.
+     * @return the SHA-1 message digest of the given value.
+     */
+    protected byte[] computeSHAdigest(final byte[] value) {
+        try {
+            return MessageDigest.getInstance("SHA").digest(value);
+        } catch (Exception e) {
+            throw new UnsupportedOperationException(e.toString());
+        }
+    }
+
+    /**
+     * Sorts the items in the collection and writes it to the data output stream
+     * 
+     * @param itemCollection
+     *            collection of items
+     * @param dos
+     *            a <code>DataOutputStream</code> value
+     * @param dotted
+     *            a <code>boolean</code> value
+     * @exception IOException
+     *                if an error occurs
+     */
+    private static void writeItems(final Collection<Item> itemCollection,
+            final DataOutput dos, final boolean dotted) throws IOException {
+        int size = itemCollection.size();
+        Item[] items = itemCollection.toArray(new Item[size]);
+        Arrays.sort(items);
+        for (int i = 0; i < size; i++) {
+            dos.writeUTF(items[i].name);
+            dos.writeInt(items[i].access);
+            dos.writeUTF(dotted ? items[i].desc.replace('/', '.')
+                    : items[i].desc);
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Inner classes
+    // ------------------------------------------------------------------------
+
+    private static class Item implements Comparable<Item> {
+
+        final String name;
+
+        final int access;
+
+        final String desc;
+
+        Item(final String name, final int access, final String desc) {
+            this.name = name;
+            this.access = access;
+            this.desc = desc;
+        }
+
+        public int compareTo(final Item other) {
+            int retVal = name.compareTo(other.name);
+            if (retVal == 0) {
+                retVal = desc.compareTo(other.desc);
+            }
+            return retVal;
+        }
+
+        @Override
+        public boolean equals(final Object o) {
+            if (o instanceof Item) {
+                return compareTo((Item) o) == 0;
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return (name + desc).hashCode();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java
new file mode 100644
index 0000000..25b594d
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java
@@ -0,0 +1,69 @@
+/***
+ * 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.commons;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * A {@link Remapper} using a {@link Map} to define its mapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class SimpleRemapper extends Remapper {
+
+    private final Map<String, String> mapping;
+
+    public SimpleRemapper(Map<String, String> mapping) {
+        this.mapping = mapping;
+    }
+
+    public SimpleRemapper(String oldName, String newName) {
+        this.mapping = Collections.singletonMap(oldName, newName);
+    }
+
+    @Override
+    public String mapMethodName(String owner, String name, String desc) {
+        String s = map(owner + '.' + name + desc);
+        return s == null ? name : s;
+    }
+
+    @Override
+    public String mapFieldName(String owner, String name, String desc) {
+        String s = map(owner + '.' + name);
+        return s == null ? name : s;
+    }
+
+    @Override
+    public String map(String key) {
+        return mapping.get(key);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.java
new file mode 100644
index 0000000..8291c66
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.java
@@ -0,0 +1,97 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
+/**
+ * A {@link ClassVisitor} that merges clinit methods into a single one.
+ * 
+ * @author Eric Bruneton
+ */
+public class StaticInitMerger extends ClassVisitor {
+
+    private String name;
+
+    private MethodVisitor clinit;
+
+    private final String prefix;
+
+    private int counter;
+
+    public StaticInitMerger(final String prefix, final ClassVisitor cv) {
+        this(Opcodes.ASM5, prefix, cv);
+    }
+
+    protected StaticInitMerger(final int api, final String prefix,
+            final ClassVisitor cv) {
+        super(api, cv);
+        this.prefix = prefix;
+    }
+
+    @Override
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
+        cv.visit(version, access, name, signature, superName, interfaces);
+        this.name = name;
+    }
+
+    @Override
+    public MethodVisitor visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        MethodVisitor mv;
+        if ("<clinit>".equals(name)) {
+            int a = Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC;
+            String n = prefix + counter++;
+            mv = cv.visitMethod(a, n, desc, signature, exceptions);
+
+            if (clinit == null) {
+                clinit = cv.visitMethod(a, name, desc, null, null);
+            }
+            clinit.visitMethodInsn(Opcodes.INVOKESTATIC, this.name, n, desc,
+                    false);
+        } else {
+            mv = cv.visitMethod(access, name, desc, signature, exceptions);
+        }
+        return mv;
+    }
+
+    @Override
+    public void visitEnd() {
+        if (clinit != null) {
+            clinit.visitInsn(Opcodes.RETURN);
+            clinit.visitMaxs(0, 0);
+        }
+        cv.visitEnd();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java
new file mode 100644
index 0000000..322d7bb
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java
@@ -0,0 +1,57 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.Label;
+
+/**
+ * A code generator for switch statements.
+ * 
+ * @author Juozas Baliuka
+ * @author Chris Nokleberg
+ * @author Eric Bruneton
+ */
+public interface TableSwitchGenerator {
+
+    /**
+     * Generates the code for a switch case.
+     * 
+     * @param key
+     *            the switch case key.
+     * @param end
+     *            a label that corresponds to the end of the switch statement.
+     */
+    void generateCase(int key, Label end);
+
+    /**
+     * Generates the code for the default switch case.
+     */
+    void generateDefault();
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java
new file mode 100644
index 0000000..4b4641a
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java
@@ -0,0 +1,96 @@
+/***
+ * 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.commons;
+
+import java.util.Collections;
+import java.util.Comparator;
+
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TryCatchBlockNode;
+
+/**
+ * A {@link MethodVisitor} adapter to sort the exception handlers. The handlers
+ * are sorted in a method innermost-to-outermost. This allows the programmer to
+ * add handlers without worrying about ordering them correctly with respect to
+ * existing, in-code handlers.
+ * 
+ * Behavior is only defined for properly-nested handlers. If any "try" blocks
+ * overlap (something that isn't possible in Java code) then this may not do
+ * what you want. In fact, this adapter just sorts by the length of the "try"
+ * block, taking advantage of the fact that a given try block must be larger
+ * than any block it contains).
+ * 
+ * @author Adrian Sampson
+ */
+public class TryCatchBlockSorter extends MethodNode {
+
+    public TryCatchBlockSorter(final MethodVisitor mv, final int access,
+            final String name, final String desc, final String signature,
+            final String[] exceptions) {
+        this(Opcodes.ASM5, mv, access, name, desc, signature, exceptions);
+    }
+
+    protected TryCatchBlockSorter(final int api, final MethodVisitor mv,
+            final int access, final String name, final String desc,
+            final String signature, final String[] exceptions) {
+        super(api, access, name, desc, signature, exceptions);
+        this.mv = mv;
+    }
+
+    @Override
+    public void visitEnd() {
+        // Compares TryCatchBlockNodes by the length of their "try" block.
+        Comparator<TryCatchBlockNode> comp = new Comparator<TryCatchBlockNode>() {
+
+            public int compare(TryCatchBlockNode t1, TryCatchBlockNode t2) {
+                int len1 = blockLength(t1);
+                int len2 = blockLength(t2);
+                return len1 - len2;
+            }
+
+            private int blockLength(TryCatchBlockNode block) {
+                int startidx = instructions.indexOf(block.start);
+                int endidx = instructions.indexOf(block.end);
+                return endidx - startidx;
+            }
+        };
+        Collections.sort(tryCatchBlocks, comp);
+        // Updates the 'target' of each try catch block annotation.
+        for (int i = 0; i < tryCatchBlocks.size(); ++i) {
+            tryCatchBlocks.get(i).updateIndex(i);
+        }
+        if (mv != null) {
+            accept(mv);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/package.html
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/package.html b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/package.html
new file mode 100644
index 0000000..4ce0db8
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/package.html
@@ -0,0 +1,48 @@
+<html>
+<!--
+ * 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.
+-->
+<body>
+Provides some useful class and method adapters. <i>The preferred way of using
+these adapters is by chaining them together and to custom adapters (instead of
+inheriting from them)</i>. Indeed this approach provides more combination
+possibilities than inheritance. For instance, suppose you want to implement an
+adapter MyAdapter than needs sorted local variables and intermediate stack map
+frame values taking into account the local variables sort. By using inheritance,
+this would require MyAdapter to extend AnalyzerAdapter, itself extending
+LocalVariablesSorter. But AnalyzerAdapter is not a subclass of
+LocalVariablesSorter, so this is not possible. On the contrary, by using
+delegation, you can make LocalVariablesSorter delegate to AnalyzerAdapter,
+itself delegating to MyAdapter. In this case AnalyzerAdapter computes
+intermediate frames based on the output of LocalVariablesSorter, and MyAdapter
+can add new locals by calling the newLocal method on LocalVariablesSorter, and
+can get the stack map frame state before each instruction by reading the locals
+and stack fields in AnalyzerAdapter (this requires references from MyAdapter
+back to LocalVariablesSorter and AnalyzerAdapter).
+</body>
\ 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/optimizer/AnnotationConstantsCollector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/AnnotationConstantsCollector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/AnnotationConstantsCollector.java
new file mode 100644
index 0000000..84aff49
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/AnnotationConstantsCollector.java
@@ -0,0 +1,147 @@
+/***
+ * 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.optimizer;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * An {@link AnnotationVisitor} that collects the {@link Constant}s of the
+ * annotations it visits.
+ * 
+ * @author Eric Bruneton
+ */
+public class AnnotationConstantsCollector extends AnnotationVisitor {
+
+    private final ConstantPool cp;
+
+    public AnnotationConstantsCollector(final AnnotationVisitor av,
+            final ConstantPool cp) {
+        super(Opcodes.ASM5, av);
+        this.cp = cp;
+    }
+
+    @Override
+    public void visit(final String name, final Object value) {
+        if (name != null) {
+            cp.newUTF8(name);
+        }
+        if (value instanceof Byte) {
+            cp.newInteger(((Byte) value).byteValue());
+        } else if (value instanceof Boolean) {
+            cp.newInteger(((Boolean) value).booleanValue() ? 1 : 0);
+        } else if (value instanceof Character) {
+            cp.newInteger(((Character) value).charValue());
+        } else if (value instanceof Short) {
+            cp.newInteger(((Short) value).shortValue());
+        } else if (value instanceof Type) {
+            cp.newUTF8(((Type) value).getDescriptor());
+        } else if (value instanceof byte[]) {
+            byte[] v = (byte[]) value;
+            for (int i = 0; i < v.length; i++) {
+                cp.newInteger(v[i]);
+            }
+        } else if (value instanceof boolean[]) {
+            boolean[] v = (boolean[]) value;
+            for (int i = 0; i < v.length; i++) {
+                cp.newInteger(v[i] ? 1 : 0);
+            }
+        } else if (value instanceof short[]) {
+            short[] v = (short[]) value;
+            for (int i = 0; i < v.length; i++) {
+                cp.newInteger(v[i]);
+            }
+        } else if (value instanceof char[]) {
+            char[] v = (char[]) value;
+            for (int i = 0; i < v.length; i++) {
+                cp.newInteger(v[i]);
+            }
+        } else if (value instanceof int[]) {
+            int[] v = (int[]) value;
+            for (int i = 0; i < v.length; i++) {
+                cp.newInteger(v[i]);
+            }
+        } else if (value instanceof long[]) {
+            long[] v = (long[]) value;
+            for (int i = 0; i < v.length; i++) {
+                cp.newLong(v[i]);
+            }
+        } else if (value instanceof float[]) {
+            float[] v = (float[]) value;
+            for (int i = 0; i < v.length; i++) {
+                cp.newFloat(v[i]);
+            }
+        } else if (value instanceof double[]) {
+            double[] v = (double[]) value;
+            for (int i = 0; i < v.length; i++) {
+                cp.newDouble(v[i]);
+            }
+        } else {
+            cp.newConst(value);
+        }
+        av.visit(name, value);
+    }
+
+    @Override
+    public void visitEnum(final String name, final String desc,
+            final String value) {
+        if (name != null) {
+            cp.newUTF8(name);
+        }
+        cp.newUTF8(desc);
+        cp.newUTF8(value);
+        av.visitEnum(name, desc, value);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String name,
+            final String desc) {
+        if (name != null) {
+            cp.newUTF8(name);
+        }
+        cp.newUTF8(desc);
+        return new AnnotationConstantsCollector(av.visitAnnotation(name, desc),
+                cp);
+    }
+
+    @Override
+    public AnnotationVisitor visitArray(final String name) {
+        if (name != null) {
+            cp.newUTF8(name);
+        }
+        return new AnnotationConstantsCollector(av.visitArray(name), cp);
+    }
+
+    @Override
+    public void visitEnd() {
+        av.visitEnd();
+    }
+}


[19/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/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 f0676b7..4585e67 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
@@ -30,27 +30,33 @@
 package org.apache.tapestry5.internal.plastic.asm;
 
 /**
- * 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>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>
- * must be called <i>before</i> the labels passed as arguments have been
- * 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.
- *
+ * A visitor to visit a Java method. The methods of this class must be called in
+ * the following order: ( <tt>visitParameter</tt> )* [
+ * <tt>visitAnnotationDefault</tt> ] ( <tt>visitAnnotation</tt> |
+ * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* [
+ * <tt>visitCode</tt> ( <tt>visitFrame</tt> | <tt>visit<i>X</i>Insn</tt> |
+ * <tt>visitLabel</tt> | <tt>visitInsnAnnotation</tt> |
+ * <tt>visitTryCatchBlock</tt> | <tt>visitTryCatchBlockAnnotation</tt> |
+ * <tt>visitLocalVariable</tt> | <tt>visitLocalVariableAnnotation</tt> |
+ * <tt>visitLineNumber</tt> )* <tt>visitMaxs</tt> ] <tt>visitEnd</tt>. In
+ * addition, the <tt>visit<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>visitInsnAnnotation</tt> must be called <i>after</i> the annotated
+ * instruction, <tt>visitTryCatchBlock</tt> must be called <i>before</i> the
+ * labels passed as arguments have been visited,
+ * <tt>visitTryCatchBlockAnnotation</tt> must be called <i>after</i> the
+ * corresponding try catch block has been visited, and the
+ * <tt>visitLocalVariable</tt>, <tt>visitLocalVariableAnnotation</tt> and
+ * <tt>visitLineNumber</tt> methods must be called <i>after</i> the labels
+ * passed as arguments have been visited.
+ * 
  * @author Eric Bruneton
  */
 public abstract class MethodVisitor {
 
     /**
      * The ASM API version implemented by this visitor. The value of this field
-     * must be one of {@link Opcodes#ASM4}.
+     * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
      */
     protected final int api;
 
@@ -62,9 +68,10 @@ public abstract class MethodVisitor {
 
     /**
      * Constructs a new {@link MethodVisitor}.
-     *
-     * @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 MethodVisitor(final int api) {
         this(api, null);
@@ -72,30 +79,51 @@ public abstract class MethodVisitor {
 
     /**
      * 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.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @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) {
+        if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
             throw new IllegalArgumentException();
-        }*/
+        }
         this.api = api;
         this.mv = mv;
     }
 
     // -------------------------------------------------------------------------
-    // Annotations and non standard attributes
+    // Parameters, annotations and non standard attributes
     // -------------------------------------------------------------------------
 
     /**
+     * Visits a parameter of this method.
+     * 
+     * @param name
+     *            parameter name or null if none is provided.
+     * @param access
+     *            the parameter's access flags, only <tt>ACC_FINAL</tt>,
+     *            <tt>ACC_SYNTHETIC</tt> or/and <tt>ACC_MANDATED</tt> are
+     *            allowed (see {@link Opcodes}).
+     */
+    public void visitParameter(String name, int access) {
+        if (api < Opcodes.ASM5) {
+            throw new RuntimeException();
+        }
+        if (mv != null) {
+            mv.visitParameter(name, access);
+        }
+    }
+
+    /**
      * 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'
+     *         annotation interface method, or <tt>null</tt> if this visitor is
+     *         not interested in visiting this default value. The 'name'
      *         parameters passed to the methods of this annotation visitor are
      *         ignored. Moreover, exacly one visit method must be called on this
      *         annotation visitor, followed by visitEnd.
@@ -109,9 +137,11 @@ public abstract class MethodVisitor {
 
     /**
      * 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.
+     * 
+     * @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.
      */
@@ -123,19 +153,55 @@ public abstract class MethodVisitor {
     }
 
     /**
+     * Visits an annotation on a type in the method signature.
+     * 
+     * @param typeRef
+     *            a reference to the annotated type. The sort of this type
+     *            reference must be {@link TypeReference#METHOD_TYPE_PARAMETER
+     *            METHOD_TYPE_PARAMETER},
+     *            {@link TypeReference#METHOD_TYPE_PARAMETER_BOUND
+     *            METHOD_TYPE_PARAMETER_BOUND},
+     *            {@link TypeReference#METHOD_RETURN METHOD_RETURN},
+     *            {@link TypeReference#METHOD_RECEIVER METHOD_RECEIVER},
+     *            {@link TypeReference#METHOD_FORMAL_PARAMETER
+     *            METHOD_FORMAL_PARAMETER} or {@link TypeReference#THROWS
+     *            THROWS}. 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.
+     * @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.
+     */
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        if (api < Opcodes.ASM5) {
+            throw new RuntimeException();
+        }
+        if (mv != null) {
+            return mv.visitTypeAnnotation(typeRef, typePath, 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.
+     * 
+     * @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.
      */
-    public AnnotationVisitor visitParameterAnnotation(
-        int parameter,
-        String desc,
-        boolean visible)
-    {
+    public AnnotationVisitor visitParameterAnnotation(int parameter,
+            String desc, boolean visible) {
         if (mv != null) {
             return mv.visitParameterAnnotation(parameter, desc, visible);
         }
@@ -144,8 +210,9 @@ public abstract class MethodVisitor {
 
     /**
      * Visits a non standard attribute of this method.
-     *
-     * @param attr an attribute.
+     * 
+     * @param attr
+     *            an attribute.
      */
     public void visitAttribute(Attribute attr) {
         if (mv != null) {
@@ -169,57 +236,76 @@ public abstract class MethodVisitor {
      * such as GOTO or THROW, that is the target of a jump instruction, or that
      * starts an exception handler block. The visited types must describe the
      * values of the local variables and of the operand stack elements <i>just
-     * before</i> <b>i</b> is executed. <br> <br> (*) this is mandatory only
-     * for classes whose version is greater than or equal to
-     * {@link Opcodes#V1_6 V1_6}. <br> <br> Packed frames are basically
-     * "deltas" from the state of the previous frame (very first frame is
-     * implicitly defined by the method's parameters and access flags): <ul>
+     * before</i> <b>i</b> is executed.<br>
+     * <br>
+     * (*) this is mandatory only for classes whose version is greater than or
+     * equal to {@link Opcodes#V1_6 V1_6}. <br>
+     * <br>
+     * The frames of a method must be given either in expanded form, or in
+     * compressed form (all frames must use the same format, i.e. you must not
+     * mix expanded and compressed frames within a single method):
+     * <ul>
+     * <li>In expanded form, all frames must have the F_NEW type.</li>
+     * <li>In compressed form, frames are basically "deltas" from the state of
+     * the previous frame:
+     * <ul>
      * <li>{@link Opcodes#F_SAME} representing frame with exactly the same
-     * locals as the previous frame and with the empty stack.</li> <li>{@link Opcodes#F_SAME1}
-     * representing frame with exactly the same locals as the previous frame and
-     * with single value on the stack (<code>nStack</code> is 1 and
-     * <code>stack[0]</code> contains value for the type of the stack item).</li>
+     * locals as the previous frame and with the empty stack.</li>
+     * <li>{@link Opcodes#F_SAME1} representing frame with exactly the same
+     * locals as the previous frame and with single value on the stack (
+     * <code>nStack</code> is 1 and <code>stack[0]</code> contains value for the
+     * type of the stack item).</li>
      * <li>{@link Opcodes#F_APPEND} representing frame with current locals are
      * the same as the locals in the previous frame, except that additional
      * locals are defined (<code>nLocal</code> is 1, 2 or 3 and
      * <code>local</code> elements contains values representing added types).</li>
-     * <li>{@link Opcodes#F_CHOP} representing frame with current locals are
-     * the same as the locals in the previous frame, except that the last 1-3
-     * 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},
-     *        {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
-     *        {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed
-     *        frames.
-     * @param nLocal the number of local variables in the visited frame.
-     * @param local the local variable types in this frame. This array must not
-     *        be modified. Primitive types are represented by
-     *        {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
-     *        {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
-     *        {@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
-     *        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.
-     * @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).
-     */
-    public void visitFrame(
-        int type,
-        int nLocal,
-        Object[] local,
-        int nStack,
-        Object[] stack)
-    {
+     * <li>{@link Opcodes#F_CHOP} representing frame with current locals are the
+     * same as the locals in the previous frame, except that the last 1-3 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>
+     * </ul>
+     * </li>
+     * </ul>
+     * <br>
+     * In both cases the first frame, corresponding to the method's parameters
+     * and access flags, is implicit and must not be visited. Also, it is
+     * illegal to visit two or more frames for the same code location (i.e., at
+     * least one instruction must be visited between two calls to visitFrame).
+     * 
+     * @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},
+     *            {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
+     *            {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for
+     *            compressed frames.
+     * @param nLocal
+     *            the number of local variables in the visited frame.
+     * @param local
+     *            the local variable types in this frame. This array must not be
+     *            modified. Primitive types are represented by
+     *            {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
+     *            {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+     *            {@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 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.
+     * @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).
+     */
+    public void visitFrame(int type, int nLocal, Object[] local, int nStack,
+            Object[] stack) {
         if (mv != null) {
             mv.visitFrame(type, nLocal, local, nStack, stack);
         }
@@ -231,21 +317,23 @@ public abstract class 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,
-     *        FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD, FALOAD,
-     *        DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE, FASTORE,
-     *        DASTORE, AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2, DUP,
-     *        DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP, IADD, LADD, FADD,
-     *        DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV,
-     *        FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL,
-     *        LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR,
-     *        I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B,
-     *        I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN,
-     *        FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW,
-     *        MONITORENTER, or MONITOREXIT.
+     * 
+     * @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, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD,
+     *            LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD,
+     *            IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE,
+     *            SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1,
+     *            DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB,
+     *            IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM,
+     *            FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR,
+     *            IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D,
+     *            L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S,
+     *            LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN,
+     *            DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER,
+     *            or MONITOREXIT.
      */
     public void visitInsn(int opcode) {
         if (mv != null) {
@@ -255,18 +343,21 @@ public abstract class MethodVisitor {
 
     /**
      * 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
-     *        opcode is BIPUSH, operand value should be between Byte.MIN_VALUE
-     *        and Byte.MAX_VALUE.<br> When opcode is SIPUSH, operand value
-     *        should be between Short.MIN_VALUE and Short.MAX_VALUE.<br> When
-     *        opcode is NEWARRAY, operand value should be one of
-     *        {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR},
-     *        {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE},
-     *        {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT},
-     *        {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.
+     * 
+     * @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 opcode is BIPUSH, operand value should be between
+     *            Byte.MIN_VALUE and Byte.MAX_VALUE.<br>
+     *            When opcode is SIPUSH, operand value should be between
+     *            Short.MIN_VALUE and Short.MAX_VALUE.<br>
+     *            When opcode is NEWARRAY, operand value should be one of
+     *            {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR},
+     *            {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE},
+     *            {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT},
+     *            {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.
      */
     public void visitIntInsn(int opcode, int operand) {
         if (mv != null) {
@@ -277,12 +368,14 @@ public abstract class MethodVisitor {
     /**
      * 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.
+     * 
+     * @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.
      */
     public void visitVarInsn(int opcode, int var) {
         if (mv != null) {
@@ -293,12 +386,14 @@ public abstract class MethodVisitor {
     /**
      * 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
-     *        Type#getInternalName() getInternalName}).
+     * 
+     * @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 Type#getInternalName() getInternalName}).
      */
     public void visitTypeInsn(int opcode, String type) {
         if (mv != null) {
@@ -309,15 +404,20 @@ public abstract class MethodVisitor {
     /**
      * 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
-     *        Type#getInternalName() getInternalName}).
-     * @param name the field's name.
-     * @param desc the field's descriptor (see {@link Type Type}).
-     */
-    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
+     * 
+     * @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 Type#getInternalName() getInternalName}).
+     * @param name
+     *            the field's name.
+     * @param desc
+     *            the field's descriptor (see {@link Type Type}).
+     */
+    public void visitFieldInsn(int opcode, String owner, String name,
+            String desc) {
         if (mv != null) {
             mv.visitFieldInsn(opcode, owner, name, desc);
         }
@@ -326,34 +426,83 @@ public abstract class MethodVisitor {
     /**
      * 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
-     *        or INVOKEINTERFACE.
-     * @param owner the internal name of the method's owner class (see {@link
-     *        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) {
+     * 
+     * @param opcode
+     *            the opcode of the type instruction to be visited. This opcode
+     *            is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+     *            INVOKEINTERFACE.
+     * @param owner
+     *            the internal name of the method's owner class (see
+     *            {@link Type#getInternalName() getInternalName}).
+     * @param name
+     *            the method's name.
+     * @param desc
+     *            the method's descriptor (see {@link Type Type}).
+     */
+    @Deprecated
+    public void visitMethodInsn(int opcode, String owner, String name,
+            String desc) {
+        if (api >= Opcodes.ASM5) {
+            boolean itf = opcode == Opcodes.INVOKEINTERFACE;
+            visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
         if (mv != null) {
             mv.visitMethodInsn(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 or
+     *            INVOKEINTERFACE.
+     * @param owner
+     *            the internal name of the method's owner class (see
+     *            {@link Type#getInternalName() getInternalName}).
+     * @param name
+     *            the method's name.
+     * @param desc
+     *            the method's descriptor (see {@link Type Type}).
+     * @param itf
+     *            if the method's owner class is an interface.
+     */
+    public void visitMethodInsn(int opcode, String owner, String name,
+            String desc, boolean itf) {
+        if (api < Opcodes.ASM5) {
+            if (itf != (opcode == Opcodes.INVOKEINTERFACE)) {
+                throw new IllegalArgumentException(
+                        "INVOKESPECIAL/STATIC on interfaces require ASM 5");
+            }
+            visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        if (mv != null) {
+            mv.visitMethodInsn(opcode, owner, name, desc, itf);
+        }
+    }
+
+    /**
      * 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.
-     */
-    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
+     * 
+     * @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.
+     */
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
         if (mv != null) {
             mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
         }
@@ -362,14 +511,16 @@ public abstract class MethodVisitor {
     /**
      * 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,
-     *        IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
-     * @param label the operand of the instruction to be visited. This operand
-     *        is a label that designates the instruction to which the jump
-     *        instruction may jump.
+     * 
+     * @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, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
+     * @param label
+     *            the operand of the instruction to be visited. This operand is
+     *            a label that designates the instruction to which the jump
+     *            instruction may jump.
      */
     public void visitJumpInsn(int opcode, Label label) {
         if (mv != null) {
@@ -380,8 +531,9 @@ public abstract class MethodVisitor {
     /**
      * Visits a label. A label designates the instruction that will be visited
      * just after it.
-     *
-     * @param label a {@link Label Label} object.
+     * 
+     * @param label
+     *            a {@link Label Label} object.
      */
     public void visitLabel(Label label) {
         if (mv != null) {
@@ -398,41 +550,44 @@ public abstract class MethodVisitor {
      * 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 (cst instanceof Double) {
      *     // ...
-     *   } else if (sort == Type.METHOD) {
+     * } else if (cst instanceof String) {
      *     // ...
-     *   } else {
-     *     // throw an exception
-     *   }
+     * } 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}, 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.
+     *     // 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}, 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.
      */
     public void visitLdcInsn(Object cst) {
         if (mv != null) {
@@ -442,9 +597,11 @@ public abstract class MethodVisitor {
 
     /**
      * Visits an IINC instruction.
-     *
-     * @param var index of the local variable to be incremented.
-     * @param increment amount to increment the local variable by.
+     * 
+     * @param var
+     *            index of the local variable to be incremented.
+     * @param increment
+     *            amount to increment the local variable by.
      */
     public void visitIincInsn(int var, int increment) {
         if (mv != null) {
@@ -454,14 +611,19 @@ public abstract class MethodVisitor {
 
     /**
      * 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.
-     */
-    public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
+     * 
+     * @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 void visitTableSwitchInsn(int min, int max, Label dflt,
+            Label... labels) {
         if (mv != null) {
             mv.visitTableSwitchInsn(min, max, dflt, labels);
         }
@@ -469,11 +631,14 @@ public abstract class MethodVisitor {
 
     /**
      * 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.
+     * 
+     * @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.
      */
     public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
         if (mv != null) {
@@ -483,9 +648,11 @@ public abstract class MethodVisitor {
 
     /**
      * Visits a MULTIANEWARRAY instruction.
-     *
-     * @param desc an array type descriptor (see {@link Type Type}).
-     * @param dims number of dimensions of the array to allocate.
+     * 
+     * @param desc
+     *            an array type descriptor (see {@link Type Type}).
+     * @param dims
+     *            number of dimensions of the array to allocate.
      */
     public void visitMultiANewArrayInsn(String desc, int dims) {
         if (mv != null) {
@@ -493,68 +660,191 @@ public abstract class MethodVisitor {
         }
     }
 
+    /**
+     * Visits an annotation on an instruction. This method must be called just
+     * <i>after</i> the annotated instruction. It can be called several times
+     * for the same instruction.
+     * 
+     * @param typeRef
+     *            a reference to the annotated type. The sort of this type
+     *            reference must be {@link TypeReference#INSTANCEOF INSTANCEOF},
+     *            {@link TypeReference#NEW NEW},
+     *            {@link TypeReference#CONSTRUCTOR_REFERENCE
+     *            CONSTRUCTOR_REFERENCE}, {@link TypeReference#METHOD_REFERENCE
+     *            METHOD_REFERENCE}, {@link TypeReference#CAST CAST},
+     *            {@link TypeReference#CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+     *            CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+     *            {@link TypeReference#METHOD_INVOCATION_TYPE_ARGUMENT
+     *            METHOD_INVOCATION_TYPE_ARGUMENT},
+     *            {@link TypeReference#CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+     *            CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+     *            {@link TypeReference#METHOD_REFERENCE_TYPE_ARGUMENT
+     *            METHOD_REFERENCE_TYPE_ARGUMENT}. 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.
+     * @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.
+     */
+    public AnnotationVisitor visitInsnAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        if (api < Opcodes.ASM5) {
+            throw new RuntimeException();
+        }
+        if (mv != null) {
+            return mv.visitInsnAnnotation(typeRef, typePath, desc, visible);
+        }
+        return null;
+    }
+
     // -------------------------------------------------------------------------
     // Exceptions table entries, debug information, max stack and max locals
     // -------------------------------------------------------------------------
 
     /**
      * 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.
-     * @param type internal name of the type of exceptions handled by the
-     *        handler, or <tt>null</tt> to catch any exceptions (for "finally"
-     *        blocks).
-     * @throws IllegalArgumentException if one of the labels has already been
-     *         visited by this visitor (by the {@link #visitLabel visitLabel}
-     *         method).
-     */
-    public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
+     * 
+     * @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).
+     * @throws IllegalArgumentException
+     *             if one of the labels has already been visited by this visitor
+     *             (by the {@link #visitLabel visitLabel} method).
+     */
+    public void visitTryCatchBlock(Label start, Label end, Label handler,
+            String type) {
         if (mv != null) {
             mv.visitTryCatchBlock(start, end, handler, type);
         }
     }
 
     /**
+     * Visits an annotation on an exception handler type. This method must be
+     * called <i>after</i> the {@link #visitTryCatchBlock} for the annotated
+     * exception handler. It can be called several times for the same exception
+     * handler.
+     * 
+     * @param typeRef
+     *            a reference to the annotated type. The sort of this type
+     *            reference must be {@link TypeReference#EXCEPTION_PARAMETER
+     *            EXCEPTION_PARAMETER}. 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.
+     * @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.
+     */
+    public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        if (api < Opcodes.ASM5) {
+            throw new RuntimeException();
+        }
+        if (mv != null) {
+            return mv.visitTryCatchAnnotation(typeRef, typePath, desc, visible);
+        }
+        return null;
+    }
+
+    /**
      * 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
-     *        <tt>null</tt> if the local variable type does not use generic
-     *        types.
-     * @param start the first instruction corresponding to the scope of this
-     *        local variable (inclusive).
-     * @param end the last instruction corresponding to the scope of this local
-     *        variable (exclusive).
-     * @param index the local variable's index.
-     * @throws IllegalArgumentException if one of the labels has not already
-     *         been visited by this visitor (by the
-     *         {@link #visitLabel visitLabel} method).
-     */
-    public void visitLocalVariable(
-        String name,
-        String desc,
-        String signature,
-        Label start,
-        Label end,
-        int index)
-    {
+     * 
+     * @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
+     *            <tt>null</tt> if the local variable type does not use generic
+     *            types.
+     * @param start
+     *            the first instruction corresponding to the scope of this local
+     *            variable (inclusive).
+     * @param end
+     *            the last instruction corresponding to the scope of this local
+     *            variable (exclusive).
+     * @param index
+     *            the local variable's index.
+     * @throws IllegalArgumentException
+     *             if one of the labels has not already been visited by this
+     *             visitor (by the {@link #visitLabel visitLabel} method).
+     */
+    public void visitLocalVariable(String name, String desc, String signature,
+            Label start, Label end, int index) {
         if (mv != null) {
             mv.visitLocalVariable(name, desc, signature, start, end, index);
         }
     }
 
     /**
+     * Visits an annotation on a local variable type.
+     * 
+     * @param typeRef
+     *            a reference to the annotated type. The sort of this type
+     *            reference must be {@link TypeReference#LOCAL_VARIABLE
+     *            LOCAL_VARIABLE} or {@link TypeReference#RESOURCE_VARIABLE
+     *            RESOURCE_VARIABLE}. 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 start
+     *            the fist instructions corresponding to the continuous ranges
+     *            that make the scope of this local variable (inclusive).
+     * @param end
+     *            the last instructions corresponding to the continuous ranges
+     *            that make the scope of this local variable (exclusive). This
+     *            array must have the same size as the 'start' array.
+     * @param index
+     *            the local variable's index in each range. This array must have
+     *            the same size as the 'start' array.
+     * @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.
+     */
+    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+            TypePath typePath, Label[] start, Label[] end, int[] index,
+            String desc, boolean visible) {
+        if (api < Opcodes.ASM5) {
+            throw new RuntimeException();
+        }
+        if (mv != null) {
+            return mv.visitLocalVariableAnnotation(typeRef, typePath, start,
+                    end, index, desc, visible);
+        }
+        return null;
+    }
+
+    /**
      * 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.
-     * @throws IllegalArgumentException if <tt>start</tt> has not already been
-     *         visited by this visitor (by the {@link #visitLabel visitLabel}
-     *         method).
+     * 
+     * @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.
+     * @throws IllegalArgumentException
+     *             if <tt>start</tt> has not already been visited by this
+     *             visitor (by the {@link #visitLabel visitLabel} method).
      */
     public void visitLineNumber(int line, Label start) {
         if (mv != null) {
@@ -565,9 +855,11 @@ public abstract class MethodVisitor {
     /**
      * 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.
+     * 
+     * @param maxStack
+     *            maximum stack size of the method.
+     * @param maxLocals
+     *            maximum number of local variables for the method.
      */
     public void visitMaxs(int maxStack, int maxLocals) {
         if (mv != null) {


[18/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/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 70b26b8..3128ff6 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
@@ -33,7 +33,7 @@ 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
  */
@@ -42,7 +42,7 @@ class MethodWriter extends MethodVisitor {
     /**
      * Pseudo access flag used to denote constructors.
      */
-    static final int ACC_CONSTRUCTOR = 262144;
+    static final int ACC_CONSTRUCTOR = 0x80000;
 
     /**
      * Frame has exactly the same locals as the previous stack map frame and
@@ -96,7 +96,7 @@ class MethodWriter extends 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,14 +104,14 @@ class MethodWriter extends 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;
@@ -192,6 +192,18 @@ class MethodWriter extends MethodVisitor {
     private AnnotationWriter ianns;
 
     /**
+     * The runtime visible type annotations of this method. May be <tt>null</tt>
+     * .
+     */
+    private AnnotationWriter tanns;
+
+    /**
+     * The runtime invisible type annotations of this method. May be
+     * <tt>null</tt>.
+     */
+    private AnnotationWriter itanns;
+
+    /**
      * The runtime visible parameter annotations of this method. May be
      * <tt>null</tt>.
      */
@@ -229,7 +241,7 @@ class MethodWriter extends MethodVisitor {
     private int maxLocals;
 
     /**
-     *  Number of local variables in the current stack map frame.
+     * Number of local variables in the current stack map frame.
      */
     private int currentLocals;
 
@@ -251,17 +263,12 @@ class MethodWriter extends MethodVisitor {
 
     /**
      * The last frame that was written in the StackMapTable attribute.
-     *
+     * 
      * @see #frame
      */
     private int[] previousFrame;
 
     /**
-     * Index of the next element to be added in {@link #frame}.
-     */
-    private int frameIndex;
-
-    /**
      * The current stack map frame. The first element contains the offset of the
      * instruction to which the frame corresponds, the second element is the
      * number of locals and the third one is the number of stack elements. The
@@ -288,6 +295,16 @@ class MethodWriter extends MethodVisitor {
     private Handler lastHandler;
 
     /**
+     * Number of entries in the MethodParameters attribute.
+     */
+    private int methodParametersCount;
+
+    /**
+     * The MethodParameters attribute.
+     */
+    private ByteVector methodParameters;
+
+    /**
      * Number of entries in the LocalVariableTable attribute.
      */
     private int localVarCount;
@@ -318,6 +335,21 @@ class MethodWriter extends MethodVisitor {
     private ByteVector lineNumber;
 
     /**
+     * The start offset of the last visited instruction.
+     */
+    private int lastCodeOffset;
+
+    /**
+     * The runtime visible type annotations of the code. May be <tt>null</tt>.
+     */
+    private AnnotationWriter ctanns;
+
+    /**
+     * The runtime invisible type annotations of the code. May be <tt>null</tt>.
+     */
+    private AnnotationWriter ictanns;
+
+    /**
      * The non standard attributes of the method's code.
      */
     private Attribute cattrs;
@@ -346,7 +378,7 @@ class MethodWriter extends MethodVisitor {
 
     /**
      * Indicates what must be automatically computed.
-     *
+     * 
      * @see #FRAMES
      * @see #MAXS
      * @see #NOTHING
@@ -357,7 +389,8 @@ class MethodWriter extends MethodVisitor {
      * A list of labels. This list is the list of basic blocks in the method,
      * i.e. a list of Label objects linked to each other by their
      * {@link Label#successor} field, in the order they are visited by
-     * {@link MethodVisitor#visitLabel}, and starting with the first basic block.
+     * {@link MethodVisitor#visitLabel}, and starting with the first basic
+     * block.
      */
     private Label labels;
 
@@ -395,30 +428,32 @@ class MethodWriter extends 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.
-     * @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 exceptions. May be
-     *        <tt>null</tt>.
-     * @param computeMaxs <tt>true</tt> if the maximum stack size and number
-     *        of local variables must be automatically computed.
-     * @param computeFrames <tt>true</tt> if the stack map tables must be
-     *        recomputed from scratch.
-     */
-    MethodWriter(
-        final ClassWriter cw,
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final String[] exceptions,
-        final boolean computeMaxs,
-        final boolean computeFrames)
-    {
-        super(Opcodes.ASM4);
+     * 
+     * @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.
+     * @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 exceptions. May be
+     *            <tt>null</tt>.
+     * @param computeMaxs
+     *            <tt>true</tt> if the maximum stack size and number of local
+     *            variables must be automatically computed.
+     * @param computeFrames
+     *            <tt>true</tt> if the stack map tables must be recomputed from
+     *            scratch.
+     */
+    MethodWriter(final ClassWriter cw, final int access, final String name,
+            final String desc, final String signature,
+            final String[] exceptions, final boolean computeMaxs,
+            final boolean computeFrames) {
+        super(Opcodes.ASM5);
         if (cw.firstMethod == null) {
             cw.firstMethod = this;
         } else {
@@ -427,6 +462,9 @@ class MethodWriter extends MethodVisitor {
         cw.lastMethod = this;
         this.cw = cw;
         this.access = access;
+        if ("<init>".equals(name)) {
+            this.access |= ACC_CONSTRUCTOR;
+        }
         this.name = cw.newUTF8(name);
         this.desc = cw.newUTF8(desc);
         this.descriptor = desc;
@@ -442,9 +480,6 @@ class MethodWriter extends MethodVisitor {
         }
         this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING);
         if (computeMaxs || computeFrames) {
-            if (computeFrames && "<init>".equals(name)) {
-                this.access |= ACC_CONSTRUCTOR;
-            }
             // updates maxLocals
             int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2;
             if ((access & Opcodes.ACC_STATIC) != 0) {
@@ -464,6 +499,16 @@ class MethodWriter extends MethodVisitor {
     // ------------------------------------------------------------------------
 
     @Override
+    public void visitParameter(String name, int access) {
+        if (methodParameters == null) {
+            methodParameters = new ByteVector();
+        }
+        ++methodParametersCount;
+        methodParameters.putShort((name == null) ? 0 : cw.newUTF8(name))
+                .putShort(access);
+    }
+
+    @Override
     public AnnotationVisitor visitAnnotationDefault() {
         if (!ClassReader.ANNOTATIONS) {
             return null;
@@ -473,10 +518,8 @@ class MethodWriter extends MethodVisitor {
     }
 
     @Override
-    public AnnotationVisitor visitAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
         if (!ClassReader.ANNOTATIONS) {
             return null;
         }
@@ -495,11 +538,31 @@ class MethodWriter extends MethodVisitor {
     }
 
     @Override
-    public AnnotationVisitor visitParameterAnnotation(
-        final int parameter,
-        final String desc,
-        final boolean visible)
-    {
+    public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        if (!ClassReader.ANNOTATIONS) {
+            return null;
+        }
+        ByteVector bv = new ByteVector();
+        // write target_type and target_info
+        AnnotationWriter.putTarget(typeRef, typePath, bv);
+        // write type, and reserve space for values count
+        bv.putShort(cw.newUTF8(desc)).putShort(0);
+        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+                bv.length - 2);
+        if (visible) {
+            aw.next = tanns;
+            tanns = aw;
+        } else {
+            aw.next = itanns;
+            itanns = aw;
+        }
+        return aw;
+    }
+
+    @Override
+    public AnnotationVisitor visitParameterAnnotation(final int parameter,
+            final String desc, final boolean visible) {
         if (!ClassReader.ANNOTATIONS) {
             return null;
         }
@@ -545,20 +608,18 @@ class MethodWriter extends MethodVisitor {
     }
 
     @Override
-    public void visitFrame(
-        final int type,
-        final int nLocal,
-        final Object[] local,
-        final int nStack,
-        final Object[] stack)
-    {
+    public void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack) {
         if (!ClassReader.FRAMES || compute == FRAMES) {
             return;
         }
 
         if (type == Opcodes.F_NEW) {
+            if (previousFrame == null) {
+                visitImplicitFirstFrame();
+            }
             currentLocals = nLocal;
-            startFrame(code.length, nLocal, nStack);
+            int frameIndex = startFrame(code.length, nLocal, nStack);
             for (int i = 0; i < nLocal; ++i) {
                 if (local[i] instanceof String) {
                     frame[frameIndex++] = Frame.OBJECT
@@ -601,48 +662,44 @@ class MethodWriter extends MethodVisitor {
             }
 
             switch (type) {
-                case Opcodes.F_FULL:
-                    currentLocals = nLocal;
-                    stackMap.putByte(FULL_FRAME)
-                            .putShort(delta)
-                            .putShort(nLocal);
-                    for (int i = 0; i < nLocal; ++i) {
-                        writeFrameType(local[i]);
-                    }
-                    stackMap.putShort(nStack);
-                    for (int i = 0; i < nStack; ++i) {
-                        writeFrameType(stack[i]);
-                    }
-                    break;
-                case Opcodes.F_APPEND:
-                    currentLocals += nLocal;
-                    stackMap.putByte(SAME_FRAME_EXTENDED + nLocal)
-                            .putShort(delta);
-                    for (int i = 0; i < nLocal; ++i) {
-                        writeFrameType(local[i]);
-                    }
-                    break;
-                case Opcodes.F_CHOP:
-                    currentLocals -= nLocal;
-                    stackMap.putByte(SAME_FRAME_EXTENDED - nLocal)
+            case Opcodes.F_FULL:
+                currentLocals = nLocal;
+                stackMap.putByte(FULL_FRAME).putShort(delta).putShort(nLocal);
+                for (int i = 0; i < nLocal; ++i) {
+                    writeFrameType(local[i]);
+                }
+                stackMap.putShort(nStack);
+                for (int i = 0; i < nStack; ++i) {
+                    writeFrameType(stack[i]);
+                }
+                break;
+            case Opcodes.F_APPEND:
+                currentLocals += nLocal;
+                stackMap.putByte(SAME_FRAME_EXTENDED + nLocal).putShort(delta);
+                for (int i = 0; i < nLocal; ++i) {
+                    writeFrameType(local[i]);
+                }
+                break;
+            case Opcodes.F_CHOP:
+                currentLocals -= nLocal;
+                stackMap.putByte(SAME_FRAME_EXTENDED - nLocal).putShort(delta);
+                break;
+            case Opcodes.F_SAME:
+                if (delta < 64) {
+                    stackMap.putByte(delta);
+                } else {
+                    stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
+                }
+                break;
+            case Opcodes.F_SAME1:
+                if (delta < 64) {
+                    stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
+                } else {
+                    stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
                             .putShort(delta);
-                    break;
-                case Opcodes.F_SAME:
-                    if (delta < 64) {
-                        stackMap.putByte(delta);
-                    } else {
-                        stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
-                    }
-                    break;
-                case Opcodes.F_SAME1:
-                    if (delta < 64) {
-                        stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
-                    } else {
-                        stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
-                                .putShort(delta);
-                    }
-                    writeFrameType(stack[0]);
-                    break;
+                }
+                writeFrameType(stack[0]);
+                break;
             }
 
             previousFrameOffset = code.length;
@@ -655,6 +712,7 @@ class MethodWriter extends MethodVisitor {
 
     @Override
     public void visitInsn(final int opcode) {
+        lastCodeOffset = code.length;
         // adds the instruction to the bytecode of the method
         code.putByte(opcode);
         // update currentBlock
@@ -672,8 +730,7 @@ class MethodWriter extends MethodVisitor {
             }
             // if opcode == ATHROW or xRETURN, ends current block (no successor)
             if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
-                    || opcode == Opcodes.ATHROW)
-            {
+                    || opcode == Opcodes.ATHROW) {
                 noSuccessor();
             }
         }
@@ -681,6 +738,7 @@ class MethodWriter extends MethodVisitor {
 
     @Override
     public void visitIntInsn(final int opcode, final int operand) {
+        lastCodeOffset = code.length;
         // Label currentBlock = this.currentBlock;
         if (currentBlock != null) {
             if (compute == FRAMES) {
@@ -705,6 +763,7 @@ class MethodWriter extends MethodVisitor {
 
     @Override
     public void visitVarInsn(final int opcode, final int var) {
+        lastCodeOffset = code.length;
         // Label currentBlock = this.currentBlock;
         if (currentBlock != null) {
             if (compute == FRAMES) {
@@ -731,8 +790,7 @@ class MethodWriter extends MethodVisitor {
             // updates max locals
             int n;
             if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD
-                    || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE)
-            {
+                    || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) {
                 n = var + 2;
             } else {
                 n = var + 1;
@@ -764,6 +822,7 @@ class MethodWriter extends MethodVisitor {
 
     @Override
     public void visitTypeInsn(final int opcode, final String type) {
+        lastCodeOffset = code.length;
         Item i = cw.newClassItem(type);
         // Label currentBlock = this.currentBlock;
         if (currentBlock != null) {
@@ -784,12 +843,9 @@ class MethodWriter 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) {
+        lastCodeOffset = code.length;
         Item i = cw.newFieldItem(owner, name, desc);
         // Label currentBlock = this.currentBlock;
         if (currentBlock != null) {
@@ -800,19 +856,19 @@ class MethodWriter extends MethodVisitor {
                 // computes the stack size variation
                 char c = desc.charAt(0);
                 switch (opcode) {
-                    case Opcodes.GETSTATIC:
-                        size = stackSize + (c == 'D' || c == 'J' ? 2 : 1);
-                        break;
-                    case Opcodes.PUTSTATIC:
-                        size = stackSize + (c == 'D' || c == 'J' ? -2 : -1);
-                        break;
-                    case Opcodes.GETFIELD:
-                        size = stackSize + (c == 'D' || c == 'J' ? 1 : 0);
-                        break;
-                    // case Constants.PUTFIELD:
-                    default:
-                        size = stackSize + (c == 'D' || c == 'J' ? -3 : -2);
-                        break;
+                case Opcodes.GETSTATIC:
+                    size = stackSize + (c == 'D' || c == 'J' ? 2 : 1);
+                    break;
+                case Opcodes.PUTSTATIC:
+                    size = stackSize + (c == 'D' || c == 'J' ? -2 : -1);
+                    break;
+                case Opcodes.GETFIELD:
+                    size = stackSize + (c == 'D' || c == 'J' ? 1 : 0);
+                    break;
+                // case Constants.PUTFIELD:
+                default:
+                    size = stackSize + (c == 'D' || c == 'J' ? -3 : -2);
+                    break;
                 }
                 // updates current and max stack sizes
                 if (size > maxStackSize) {
@@ -826,13 +882,9 @@ class MethodWriter extends MethodVisitor {
     }
 
     @Override
-    public void visitMethodInsn(
-        final int opcode,
-        final String owner,
-        final String name,
-        final String desc)
-    {
-        boolean itf = opcode == Opcodes.INVOKEINTERFACE;
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        lastCodeOffset = code.length;
         Item i = cw.newMethodItem(owner, name, desc, itf);
         int argSize = i.intVal;
         // Label currentBlock = this.currentBlock;
@@ -870,7 +922,7 @@ class MethodWriter extends MethodVisitor {
             }
         }
         // adds the instruction to the bytecode of the method
-        if (itf) {
+        if (opcode == Opcodes.INVOKEINTERFACE) {
             if (argSize == 0) {
                 argSize = Type.getArgumentsAndReturnSizes(desc);
                 i.intVal = argSize;
@@ -882,12 +934,9 @@ class MethodWriter extends MethodVisitor {
     }
 
     @Override
-    public void visitInvokeDynamicInsn(
-        final String name,
-        final String desc,
-        final Handle bsm,
-        final Object... bsmArgs)
-    {
+    public void visitInvokeDynamicInsn(final String name, final String desc,
+            final Handle bsm, final Object... bsmArgs) {
+        lastCodeOffset = code.length;
         Item i = cw.newInvokeDynamicItem(name, desc, bsm, bsmArgs);
         int argSize = i.intVal;
         // Label currentBlock = this.currentBlock;
@@ -927,6 +976,7 @@ class MethodWriter extends MethodVisitor {
 
     @Override
     public void visitJumpInsn(final int opcode, final Label label) {
+        lastCodeOffset = code.length;
         Label nextInsn = null;
         // Label currentBlock = this.currentBlock;
         if (currentBlock != null) {
@@ -967,8 +1017,7 @@ class MethodWriter extends MethodVisitor {
         }
         // adds the instruction to the bytecode of the method
         if ((label.status & Label.RESOLVED) != 0
-                && label.position - code.length < Short.MIN_VALUE)
-        {
+                && label.position - code.length < Short.MIN_VALUE) {
             /*
              * case of a backward jump with an offset < -32768. In this case we
              * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx
@@ -986,8 +1035,7 @@ class MethodWriter extends MethodVisitor {
                 if (nextInsn != null) {
                     nextInsn.status |= Label.TARGET;
                 }
-                code.putByte(opcode <= 166
-                        ? ((opcode + 1) ^ 1) - 1
+                code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
                         : opcode ^ 1);
                 code.putShort(8); // jump offset
                 code.putByte(200); // GOTO_W
@@ -1074,6 +1122,7 @@ class MethodWriter extends MethodVisitor {
 
     @Override
     public void visitLdcInsn(final Object cst) {
+        lastCodeOffset = code.length;
         Item i = cw.newConstItem(cst);
         // Label currentBlock = this.currentBlock;
         if (currentBlock != null) {
@@ -1082,8 +1131,7 @@ class MethodWriter extends MethodVisitor {
             } else {
                 int size;
                 // computes the stack size variation
-                if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE)
-                {
+                if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {
                     size = stackSize + 2;
                 } else {
                     size = stackSize + 1;
@@ -1108,6 +1156,7 @@ class MethodWriter extends MethodVisitor {
 
     @Override
     public void visitIincInsn(final int var, final int increment) {
+        lastCodeOffset = code.length;
         if (currentBlock != null) {
             if (compute == FRAMES) {
                 currentBlock.frame.execute(Opcodes.IINC, var, null, null);
@@ -1122,8 +1171,7 @@ class MethodWriter extends MethodVisitor {
         }
         // adds the instruction to the bytecode of the method
         if ((var > 255) || (increment > 127) || (increment < -128)) {
-            code.putByte(196 /* WIDE */)
-                    .put12(Opcodes.IINC, var)
+            code.putByte(196 /* WIDE */).put12(Opcodes.IINC, var)
                     .putShort(increment);
         } else {
             code.putByte(Opcodes.IINC).put11(var, increment);
@@ -1131,12 +1179,9 @@ class MethodWriter extends MethodVisitor {
     }
 
     @Override
-    public void visitTableSwitchInsn(
-        final int min,
-        final int max,
-        final Label dflt,
-        final Label... labels)
-    {
+    public void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels) {
+        lastCodeOffset = code.length;
         // adds the instruction to the bytecode of the method
         int source = code.length;
         code.putByte(Opcodes.TABLESWITCH);
@@ -1151,11 +1196,9 @@ class MethodWriter extends MethodVisitor {
     }
 
     @Override
-    public void visitLookupSwitchInsn(
-        final Label dflt,
-        final int[] keys,
-        final Label[] labels)
-    {
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
+        lastCodeOffset = code.length;
         // adds the instruction to the bytecode of the method
         int source = code.length;
         code.putByte(Opcodes.LOOKUPSWITCH);
@@ -1198,6 +1241,7 @@ class MethodWriter extends MethodVisitor {
 
     @Override
     public void visitMultiANewArrayInsn(final String desc, final int dims) {
+        lastCodeOffset = code.length;
         Item i = cw.newClassItem(desc);
         // Label currentBlock = this.currentBlock;
         if (currentBlock != null) {
@@ -1214,12 +1258,32 @@ class MethodWriter 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) {
+        if (!ClassReader.ANNOTATIONS) {
+            return null;
+        }
+        ByteVector bv = new ByteVector();
+        // write target_type and target_info
+        typeRef = (typeRef & 0xFF0000FF) | (lastCodeOffset << 8);
+        AnnotationWriter.putTarget(typeRef, typePath, bv);
+        // write type, and reserve space for values count
+        bv.putShort(cw.newUTF8(desc)).putShort(0);
+        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+                bv.length - 2);
+        if (visible) {
+            aw.next = ctanns;
+            ctanns = aw;
+        } else {
+            aw.next = ictanns;
+            ictanns = aw;
+        }
+        return aw;
+    }
+
+    @Override
+    public void visitTryCatchBlock(final Label start, final Label end,
+            final Label handler, final String type) {
         ++handlerCount;
         Handler h = new Handler();
         h.start = start;
@@ -1236,14 +1300,32 @@ class MethodWriter extends MethodVisitor {
     }
 
     @Override
-    public void visitLocalVariable(
-        final String name,
-        final String desc,
-        final String signature,
-        final Label start,
-        final Label end,
-        final int index)
-    {
+    public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        if (!ClassReader.ANNOTATIONS) {
+            return null;
+        }
+        ByteVector bv = new ByteVector();
+        // write target_type and target_info
+        AnnotationWriter.putTarget(typeRef, typePath, bv);
+        // write type, and reserve space for values count
+        bv.putShort(cw.newUTF8(desc)).putShort(0);
+        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+                bv.length - 2);
+        if (visible) {
+            aw.next = ctanns;
+            ctanns = aw;
+        } else {
+            aw.next = ictanns;
+            ictanns = aw;
+        }
+        return aw;
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
         if (signature != null) {
             if (localVarType == null) {
                 localVarType = new ByteVector();
@@ -1251,8 +1333,7 @@ class MethodWriter extends MethodVisitor {
             ++localVarTypeCount;
             localVarType.putShort(start.position)
                     .putShort(end.position - start.position)
-                    .putShort(cw.newUTF8(name))
-                    .putShort(cw.newUTF8(signature))
+                    .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(signature))
                     .putShort(index);
         }
         if (localVar == null) {
@@ -1261,8 +1342,7 @@ class MethodWriter extends MethodVisitor {
         ++localVarCount;
         localVar.putShort(start.position)
                 .putShort(end.position - start.position)
-                .putShort(cw.newUTF8(name))
-                .putShort(cw.newUTF8(desc))
+                .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(desc))
                 .putShort(index);
         if (compute != NOTHING) {
             // updates max locals
@@ -1275,6 +1355,41 @@ class MethodWriter extends MethodVisitor {
     }
 
     @Override
+    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+            TypePath typePath, Label[] start, Label[] end, int[] index,
+            String desc, boolean visible) {
+        if (!ClassReader.ANNOTATIONS) {
+            return null;
+        }
+        ByteVector bv = new ByteVector();
+        // write target_type and target_info
+        bv.putByte(typeRef >>> 24).putShort(start.length);
+        for (int i = 0; i < start.length; ++i) {
+            bv.putShort(start[i].position)
+                    .putShort(end[i].position - start[i].position)
+                    .putShort(index[i]);
+        }
+        if (typePath == null) {
+            bv.putByte(0);
+        } else {
+            int length = typePath.b[typePath.offset] * 2 + 1;
+            bv.putByteArray(typePath.b, typePath.offset, length);
+        }
+        // write type, and reserve space for values count
+        bv.putShort(cw.newUTF8(desc)).putShort(0);
+        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+                bv.length - 2);
+        if (visible) {
+            aw.next = ctanns;
+            ctanns = aw;
+        } else {
+            aw.next = ictanns;
+            ictanns = aw;
+        }
+        return aw;
+    }
+
+    @Override
     public void visitLineNumber(final int line, final Label start) {
         if (lineNumber == null) {
             lineNumber = new ByteVector();
@@ -1286,6 +1401,14 @@ class MethodWriter extends MethodVisitor {
 
     @Override
     public void visitMaxs(final int maxStack, final int maxLocals) {
+        if (resize) {
+            // replaces the temporary jump opcodes introduced by Label.resolve.
+            if (ClassReader.RESIZE) {
+                resizeInstructions();
+            } else {
+                throw new RuntimeException("Method code too large!");
+            }
+        }
         if (ClassReader.FRAMES && compute == FRAMES) {
             // completes the control flow graph with exception handler blocks
             Handler handler = firstHandler;
@@ -1294,8 +1417,7 @@ class MethodWriter extends MethodVisitor {
                 Label h = handler.handler.getFirst();
                 Label e = handler.end.getFirst();
                 // computes the kind of the edges to 'h'
-                String t = handler.desc == null
-                        ? "java/lang/Throwable"
+                String t = handler.desc == null ? "java/lang/Throwable"
                         : handler.desc;
                 int kind = Frame.OBJECT | cw.addType(t);
                 // h is an exception handler
@@ -1382,11 +1504,12 @@ class MethodWriter extends MethodVisitor {
                         }
                         code.data[end] = (byte) Opcodes.ATHROW;
                         // emits a frame for this unreachable block
-                        startFrame(start, 0, 1);
-                        frame[frameIndex++] = Frame.OBJECT
+                        int frameIndex = startFrame(start, 0, 1);
+                        frame[frameIndex] = Frame.OBJECT
                                 | cw.addType("java/lang/Throwable");
                         endFrame();
-                        // removes the start-end range from the exception handlers
+                        // removes the start-end range from the exception
+                        // handlers
                         firstHandler = Handler.remove(firstHandler, l, k);
                     }
                 }
@@ -1534,9 +1657,11 @@ class MethodWriter extends 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.
+     * 
+     * @param info
+     *            information about the control flow edge to be added.
+     * @param successor
+     *            the successor block to be added to the current block.
      */
     private void addSuccessor(final int info, final Label successor) {
         // creates and initializes an Edge object...
@@ -1572,8 +1697,9 @@ class MethodWriter extends MethodVisitor {
 
     /**
      * Visits a frame that has been computed from scratch.
-     *
-     * @param f the frame that must be visited.
+     * 
+     * @param f
+     *            the frame that must be visited.
      */
     private void visitFrame(final Frame f) {
         int i, t;
@@ -1606,7 +1732,7 @@ class MethodWriter extends MethodVisitor {
             }
         }
         // visits the frame and its content
-        startFrame(f.owner.position, nLocal, nStack);
+        int frameIndex = startFrame(f.owner.position, nLocal, nStack);
         for (i = 0; nLocal > 0; ++i, --nLocal) {
             t = locals[i];
             frame[frameIndex++] = t;
@@ -1625,15 +1751,78 @@ class MethodWriter extends MethodVisitor {
     }
 
     /**
+     * Visit the implicit first frame of this method.
+     */
+    private void visitImplicitFirstFrame() {
+        // There can be at most descriptor.length() + 1 locals
+        int frameIndex = startFrame(0, descriptor.length() + 1, 0);
+        if ((access & Opcodes.ACC_STATIC) == 0) {
+            if ((access & ACC_CONSTRUCTOR) == 0) {
+                frame[frameIndex++] = Frame.OBJECT | cw.addType(cw.thisName);
+            } else {
+                frame[frameIndex++] = 6; // Opcodes.UNINITIALIZED_THIS;
+            }
+        }
+        int i = 1;
+        loop: while (true) {
+            int j = i;
+            switch (descriptor.charAt(i++)) {
+            case 'Z':
+            case 'C':
+            case 'B':
+            case 'S':
+            case 'I':
+                frame[frameIndex++] = 1; // Opcodes.INTEGER;
+                break;
+            case 'F':
+                frame[frameIndex++] = 2; // Opcodes.FLOAT;
+                break;
+            case 'J':
+                frame[frameIndex++] = 4; // Opcodes.LONG;
+                break;
+            case 'D':
+                frame[frameIndex++] = 3; // Opcodes.DOUBLE;
+                break;
+            case '[':
+                while (descriptor.charAt(i) == '[') {
+                    ++i;
+                }
+                if (descriptor.charAt(i) == 'L') {
+                    ++i;
+                    while (descriptor.charAt(i) != ';') {
+                        ++i;
+                    }
+                }
+                frame[frameIndex++] = Frame.OBJECT
+                        | cw.addType(descriptor.substring(j, ++i));
+                break;
+            case 'L':
+                while (descriptor.charAt(i) != ';') {
+                    ++i;
+                }
+                frame[frameIndex++] = Frame.OBJECT
+                        | cw.addType(descriptor.substring(j + 1, i++));
+                break;
+            default:
+                break loop;
+            }
+        }
+        frame[1] = frameIndex - 3;
+        endFrame();
+    }
+
+    /**
      * 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.
-     * @param nStack the number of stack elements in the frame.
-     */
-    private void startFrame(final int offset, final int nLocal, final int nStack)
-    {
+     * 
+     * @param offset
+     *            the offset of the instruction to which the frame corresponds.
+     * @param nLocal
+     *            the number of local variables in the frame.
+     * @param nStack
+     *            the number of stack elements in the frame.
+     * @return the index of the next element to be written in this frame.
+     */
+    private int startFrame(final int offset, final int nLocal, final int nStack) {
         int n = 3 + nLocal + nStack;
         if (frame == null || frame.length < n) {
             frame = new int[n];
@@ -1641,7 +1830,7 @@ class MethodWriter extends MethodVisitor {
         frame[0] = offset;
         frame[1] = nLocal;
         frame[2] = nStack;
-        frameIndex = 3;
+        return 3;
     }
 
     /**
@@ -1686,24 +1875,23 @@ class MethodWriter extends MethodVisitor {
         if (cstackSize == 0) {
             k = clocalsSize - localsSize;
             switch (k) {
-                case -3:
-                case -2:
-                case -1:
-                    type = CHOP_FRAME;
-                    localsSize = clocalsSize;
-                    break;
-                case 0:
-                    type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED;
-                    break;
-                case 1:
-                case 2:
-                case 3:
-                    type = APPEND_FRAME;
-                    break;
+            case -3:
+            case -2:
+            case -1:
+                type = CHOP_FRAME;
+                localsSize = clocalsSize;
+                break;
+            case 0:
+                type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED;
+                break;
+            case 1:
+            case 2:
+            case 3:
+                type = APPEND_FRAME;
+                break;
             }
         } else if (clocalsSize == localsSize && cstackSize == 1) {
-            type = delta < 63
-                    ? SAME_LOCALS_1_STACK_ITEM_FRAME
+            type = delta < 63 ? SAME_LOCALS_1_STACK_ITEM_FRAME
                     : SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;
         }
         if (type != FULL_FRAME) {
@@ -1718,36 +1906,34 @@ class MethodWriter extends MethodVisitor {
             }
         }
         switch (type) {
-            case SAME_FRAME:
-                stackMap.putByte(delta);
-                break;
-            case SAME_LOCALS_1_STACK_ITEM_FRAME:
-                stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
-                writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
-                break;
-            case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:
-                stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
-                        .putShort(delta);
-                writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
-                break;
-            case SAME_FRAME_EXTENDED:
-                stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
-                break;
-            case CHOP_FRAME:
-                stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
-                break;
-            case APPEND_FRAME:
-                stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
-                writeFrameTypes(3 + localsSize, 3 + clocalsSize);
-                break;
-            // case FULL_FRAME:
-            default:
-                stackMap.putByte(FULL_FRAME)
-                        .putShort(delta)
-                        .putShort(clocalsSize);
-                writeFrameTypes(3, 3 + clocalsSize);
-                stackMap.putShort(cstackSize);
-                writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);
+        case SAME_FRAME:
+            stackMap.putByte(delta);
+            break;
+        case SAME_LOCALS_1_STACK_ITEM_FRAME:
+            stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
+            writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
+            break;
+        case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:
+            stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED).putShort(
+                    delta);
+            writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
+            break;
+        case SAME_FRAME_EXTENDED:
+            stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
+            break;
+        case CHOP_FRAME:
+            stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
+            break;
+        case APPEND_FRAME:
+            stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
+            writeFrameTypes(3 + localsSize, 3 + clocalsSize);
+            break;
+        // case FULL_FRAME:
+        default:
+            stackMap.putByte(FULL_FRAME).putShort(delta).putShort(clocalsSize);
+            writeFrameTypes(3, 3 + clocalsSize);
+            stackMap.putShort(cstackSize);
+            writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);
         }
     }
 
@@ -1756,9 +1942,11 @@ class MethodWriter extends 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).
+     * 
+     * @param start
+     *            index of the first type in {@link #frame} to write.
+     * @param end
+     *            index of last type in {@link #frame} to write (exclusive).
      */
     private void writeFrameTypes(final int start, final int end) {
         for (int i = start; i < end; ++i) {
@@ -1767,15 +1955,15 @@ class MethodWriter extends MethodVisitor {
             if (d == 0) {
                 int v = t & Frame.BASE_VALUE;
                 switch (t & Frame.BASE_KIND) {
-                    case Frame.OBJECT:
-                        stackMap.putByte(7)
-                                .putShort(cw.newClass(cw.typeTable[v].strVal1));
-                        break;
-                    case Frame.UNINITIALIZED:
-                        stackMap.putByte(8).putShort(cw.typeTable[v].intVal);
-                        break;
-                    default:
-                        stackMap.putByte(v);
+                case Frame.OBJECT:
+                    stackMap.putByte(7).putShort(
+                            cw.newClass(cw.typeTable[v].strVal1));
+                    break;
+                case Frame.UNINITIALIZED:
+                    stackMap.putByte(8).putShort(cw.typeTable[v].intVal);
+                    break;
+                default:
+                    stackMap.putByte(v);
                 }
             } else {
                 StringBuffer buf = new StringBuffer();
@@ -1789,29 +1977,29 @@ class MethodWriter extends MethodVisitor {
                     buf.append(';');
                 } else {
                     switch (t & 0xF) {
-                        case 1:
-                            buf.append('I');
-                            break;
-                        case 2:
-                            buf.append('F');
-                            break;
-                        case 3:
-                            buf.append('D');
-                            break;
-                        case 9:
-                            buf.append('Z');
-                            break;
-                        case 10:
-                            buf.append('B');
-                            break;
-                        case 11:
-                            buf.append('C');
-                            break;
-                        case 12:
-                            buf.append('S');
-                            break;
-                        default:
-                            buf.append('J');
+                    case 1:
+                        buf.append('I');
+                        break;
+                    case 2:
+                        buf.append('F');
+                        break;
+                    case 3:
+                        buf.append('D');
+                        break;
+                    case 9:
+                        buf.append('Z');
+                        break;
+                    case 10:
+                        buf.append('B');
+                        break;
+                    case 11:
+                        buf.append('C');
+                        break;
+                    case 12:
+                        buf.append('S');
+                        break;
+                    default:
+                        buf.append('J');
                     }
                 }
                 stackMap.putByte(7).putShort(cw.newClass(buf.toString()));
@@ -1835,21 +2023,13 @@ class MethodWriter extends MethodVisitor {
 
     /**
      * Returns the size of the bytecode of this method.
-     *
+     * 
      * @return the size of the bytecode of this method.
      */
     final int getSize() {
         if (classReaderOffset != 0) {
             return 6 + classReaderLength;
         }
-        if (resize) {
-            // replaces the temporary jump opcodes introduced by Label.resolve.
-            if (ClassReader.RESIZE) {
-                resizeInstructions();
-            } else {
-                throw new RuntimeException("Method code too large!");
-            }
-        }
         int size = 8;
         if (code.length > 0) {
             if (code.length > 65536) {
@@ -1874,11 +2054,16 @@ class MethodWriter extends MethodVisitor {
                 cw.newUTF8(zip ? "StackMapTable" : "StackMap");
                 size += 8 + stackMap.length;
             }
+            if (ClassReader.ANNOTATIONS && ctanns != null) {
+                cw.newUTF8("RuntimeVisibleTypeAnnotations");
+                size += 8 + ctanns.getSize();
+            }
+            if (ClassReader.ANNOTATIONS && ictanns != null) {
+                cw.newUTF8("RuntimeInvisibleTypeAnnotations");
+                size += 8 + ictanns.getSize();
+            }
             if (cattrs != null) {
-                size += cattrs.getSize(cw,
-                        code.data,
-                        code.length,
-                        maxStack,
+                size += cattrs.getSize(cw, code.data, code.length, maxStack,
                         maxLocals);
             }
         }
@@ -1886,11 +2071,12 @@ class MethodWriter extends MethodVisitor {
             cw.newUTF8("Exceptions");
             size += 8 + 2 * exceptionCount;
         }
-        if ((access & Opcodes.ACC_SYNTHETIC) != 0
-                && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
-        {
-            cw.newUTF8("Synthetic");
-            size += 6;
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            if ((cw.version & 0xFFFF) < Opcodes.V1_5
+                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+                cw.newUTF8("Synthetic");
+                size += 6;
+            }
         }
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             cw.newUTF8("Deprecated");
@@ -1901,6 +2087,10 @@ class MethodWriter extends MethodVisitor {
             cw.newUTF8(signature);
             size += 8;
         }
+        if (methodParameters != null) {
+            cw.newUTF8("MethodParameters");
+            size += 7 + methodParameters.length;
+        }
         if (ClassReader.ANNOTATIONS && annd != null) {
             cw.newUTF8("AnnotationDefault");
             size += 6 + annd.length;
@@ -1913,6 +2103,14 @@ class MethodWriter extends MethodVisitor {
             cw.newUTF8("RuntimeInvisibleAnnotations");
             size += 8 + ianns.getSize();
         }
+        if (ClassReader.ANNOTATIONS && tanns != null) {
+            cw.newUTF8("RuntimeVisibleTypeAnnotations");
+            size += 8 + tanns.getSize();
+        }
+        if (ClassReader.ANNOTATIONS && itanns != null) {
+            cw.newUTF8("RuntimeInvisibleTypeAnnotations");
+            size += 8 + itanns.getSize();
+        }
         if (ClassReader.ANNOTATIONS && panns != null) {
             cw.newUTF8("RuntimeVisibleParameterAnnotations");
             size += 7 + 2 * (panns.length - synthetics);
@@ -1935,14 +2133,16 @@ class MethodWriter extends 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.
+     * 
+     * @param out
+     *            the byte vector into which the bytecode of this method must be
+     *            copied.
      */
     final void put(final ByteVector out) {
-        int mask = Opcodes.ACC_DEPRECATED
+        final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
+        int mask = ACC_CONSTRUCTOR | Opcodes.ACC_DEPRECATED
                 | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
-                | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC));
+                | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
         out.putShort(access & ~mask).putShort(name).putShort(desc);
         if (classReaderOffset != 0) {
             out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength);
@@ -1955,10 +2155,11 @@ class MethodWriter extends MethodVisitor {
         if (exceptionCount > 0) {
             ++attributeCount;
         }
-        if ((access & Opcodes.ACC_SYNTHETIC) != 0
-                && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
-        {
-            ++attributeCount;
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            if ((cw.version & 0xFFFF) < Opcodes.V1_5
+                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+                ++attributeCount;
+            }
         }
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             ++attributeCount;
@@ -1966,6 +2167,9 @@ class MethodWriter extends MethodVisitor {
         if (ClassReader.SIGNATURES && signature != null) {
             ++attributeCount;
         }
+        if (methodParameters != null) {
+            ++attributeCount;
+        }
         if (ClassReader.ANNOTATIONS && annd != null) {
             ++attributeCount;
         }
@@ -1975,6 +2179,12 @@ class MethodWriter extends MethodVisitor {
         if (ClassReader.ANNOTATIONS && ianns != null) {
             ++attributeCount;
         }
+        if (ClassReader.ANNOTATIONS && tanns != null) {
+            ++attributeCount;
+        }
+        if (ClassReader.ANNOTATIONS && itanns != null) {
+            ++attributeCount;
+        }
         if (ClassReader.ANNOTATIONS && panns != null) {
             ++attributeCount;
         }
@@ -1999,11 +2209,14 @@ class MethodWriter extends MethodVisitor {
             if (stackMap != null) {
                 size += 8 + stackMap.length;
             }
+            if (ClassReader.ANNOTATIONS && ctanns != null) {
+                size += 8 + ctanns.getSize();
+            }
+            if (ClassReader.ANNOTATIONS && ictanns != null) {
+                size += 8 + ictanns.getSize();
+            }
             if (cattrs != null) {
-                size += cattrs.getSize(cw,
-                        code.data,
-                        code.length,
-                        maxStack,
+                size += cattrs.getSize(cw, code.data, code.length, maxStack,
                         maxLocals);
             }
             out.putShort(cw.newUTF8("Code")).putInt(size);
@@ -2013,10 +2226,8 @@ class MethodWriter extends MethodVisitor {
             if (handlerCount > 0) {
                 Handler h = firstHandler;
                 while (h != null) {
-                    out.putShort(h.start.position)
-                            .putShort(h.end.position)
-                            .putShort(h.handler.position)
-                            .putShort(h.type);
+                    out.putShort(h.start.position).putShort(h.end.position)
+                            .putShort(h.handler.position).putShort(h.type);
                     h = h.next;
                 }
             }
@@ -2033,6 +2244,12 @@ class MethodWriter extends MethodVisitor {
             if (stackMap != null) {
                 ++attributeCount;
             }
+            if (ClassReader.ANNOTATIONS && ctanns != null) {
+                ++attributeCount;
+            }
+            if (ClassReader.ANNOTATIONS && ictanns != null) {
+                ++attributeCount;
+            }
             if (cattrs != null) {
                 attributeCount += cattrs.getCount();
             }
@@ -2058,31 +2275,45 @@ class MethodWriter extends MethodVisitor {
                 out.putInt(stackMap.length + 2).putShort(frameCount);
                 out.putByteArray(stackMap.data, 0, stackMap.length);
             }
+            if (ClassReader.ANNOTATIONS && ctanns != null) {
+                out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
+                ctanns.put(out);
+            }
+            if (ClassReader.ANNOTATIONS && ictanns != null) {
+                out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
+                ictanns.put(out);
+            }
             if (cattrs != null) {
                 cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out);
             }
         }
         if (exceptionCount > 0) {
-            out.putShort(cw.newUTF8("Exceptions"))
-                    .putInt(2 * exceptionCount + 2);
+            out.putShort(cw.newUTF8("Exceptions")).putInt(
+                    2 * exceptionCount + 2);
             out.putShort(exceptionCount);
             for (int i = 0; i < exceptionCount; ++i) {
                 out.putShort(exceptions[i]);
             }
         }
-        if ((access & Opcodes.ACC_SYNTHETIC) != 0
-                && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
-        {
-            out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            if ((cw.version & 0xFFFF) < Opcodes.V1_5
+                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+                out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+            }
         }
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             out.putShort(cw.newUTF8("Deprecated")).putInt(0);
         }
         if (ClassReader.SIGNATURES && signature != null) {
-            out.putShort(cw.newUTF8("Signature"))
-                    .putInt(2)
+            out.putShort(cw.newUTF8("Signature")).putInt(2)
                     .putShort(cw.newUTF8(signature));
         }
+        if (methodParameters != null) {
+            out.putShort(cw.newUTF8("MethodParameters"));
+            out.putInt(methodParameters.length + 1).putByte(
+                    methodParametersCount);
+            out.putByteArray(methodParameters.data, 0, methodParameters.length);
+        }
         if (ClassReader.ANNOTATIONS && annd != null) {
             out.putShort(cw.newUTF8("AnnotationDefault"));
             out.putInt(annd.length);
@@ -2096,6 +2327,14 @@ class MethodWriter extends MethodVisitor {
             out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
             ianns.put(out);
         }
+        if (ClassReader.ANNOTATIONS && tanns != null) {
+            out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
+            tanns.put(out);
+        }
+        if (ClassReader.ANNOTATIONS && itanns != null) {
+            out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
+            itanns.put(out);
+        }
         if (ClassReader.ANNOTATIONS && panns != null) {
             out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations"));
             AnnotationWriter.put(panns, synthetics, out);
@@ -2123,10 +2362,12 @@ class MethodWriter extends MethodVisitor {
      * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W
      * 32765. This, in turn, may require to increase the size of another jump
      * instruction, and so on... All these operations are handled automatically
-     * by this method. <p> <i>This method must be called after all the method
-     * that is being built has been visited</i>. In particular, the
-     * {@link Label Label} objects used to construct the method are no longer
-     * valid after this method has been called.
+     * by this method.
+     * <p>
+     * <i>This method must be called after all the method that is being built
+     * has been visited</i>. In particular, the {@link Label Label} objects used
+     * to construct the method are no longer valid after this method has been
+     * called.
      */
     private void resizeInstructions() {
         byte[] b = code.data; // bytecode of the method
@@ -2138,17 +2379,17 @@ class MethodWriter extends 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
@@ -2176,158 +2417,14 @@ class MethodWriter extends MethodVisitor {
                 int insert = 0; // bytes to be added after this instruction
 
                 switch (ClassWriter.TYPE[opcode]) {
-                    case ClassWriter.NOARG_INSN:
-                    case ClassWriter.IMPLVAR_INSN:
-                        u += 1;
-                        break;
-                    case ClassWriter.LABEL_INSN:
-                        if (opcode > 201) {
-                            // converts temporary opcodes 202 to 217, 218 and
-                            // 219 to IFEQ ... JSR (inclusive), IFNULL and
-                            // IFNONNULL
-                            opcode = opcode < 218 ? opcode - 49 : opcode - 20;
-                            label = u + readUnsignedShort(b, u + 1);
-                        } else {
-                            label = u + readShort(b, u + 1);
-                        }
-                        newOffset = getNewOffset(allIndexes, allSizes, u, label);
-                        if (newOffset < Short.MIN_VALUE
-                                || newOffset > Short.MAX_VALUE)
-                        {
-                            if (!resize[u]) {
-                                if (opcode == Opcodes.GOTO
-                                        || opcode == Opcodes.JSR)
-                                {
-                                    // two additional bytes will be required to
-                                    // replace this GOTO or JSR instruction with
-                                    // a GOTO_W or a JSR_W
-                                    insert = 2;
-                                } else {
-                                    // five additional bytes will be required to
-                                    // replace this IFxxx <l> instruction with
-                                    // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx
-                                    // is the "opposite" opcode of IFxxx (i.e.,
-                                    // IFNE for IFEQ) and where <l'> designates
-                                    // the instruction just after the GOTO_W.
-                                    insert = 5;
-                                }
-                                resize[u] = true;
-                            }
-                        }
-                        u += 3;
-                        break;
-                    case ClassWriter.LABELW_INSN:
-                        u += 5;
-                        break;
-                    case ClassWriter.TABL_INSN:
-                        if (state == 1) {
-                            // true number of bytes to be added (or removed)
-                            // from this instruction = (future number of padding
-                            // bytes - current number of padding byte) -
-                            // previously over estimated variation =
-                            // = ((3 - newOffset%4) - (3 - u%4)) - u%4
-                            // = (-newOffset%4 + u%4) - u%4
-                            // = -(newOffset & 3)
-                            newOffset = getNewOffset(allIndexes, allSizes, 0, u);
-                            insert = -(newOffset & 3);
-                        } else if (!resize[u]) {
-                            // over estimation of the number of bytes to be
-                            // added to this instruction = 3 - current number
-                            // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3
-                            insert = u & 3;
-                            resize[u] = true;
-                        }
-                        // skips instruction
-                        u = u + 4 - (u & 3);
-                        u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12;
-                        break;
-                    case ClassWriter.LOOK_INSN:
-                        if (state == 1) {
-                            // like TABL_INSN
-                            newOffset = getNewOffset(allIndexes, allSizes, 0, u);
-                            insert = -(newOffset & 3);
-                        } else if (!resize[u]) {
-                            // like TABL_INSN
-                            insert = u & 3;
-                            resize[u] = true;
-                        }
-                        // skips instruction
-                        u = u + 4 - (u & 3);
-                        u += 8 * readInt(b, u + 4) + 8;
-                        break;
-                    case ClassWriter.WIDE_INSN:
-                        opcode = b[u + 1] & 0xFF;
-                        if (opcode == Opcodes.IINC) {
-                            u += 6;
-                        } else {
-                            u += 4;
-                        }
-                        break;
-                    case ClassWriter.VAR_INSN:
-                    case ClassWriter.SBYTE_INSN:
-                    case ClassWriter.LDC_INSN:
-                        u += 2;
-                        break;
-                    case ClassWriter.SHORT_INSN:
-                    case ClassWriter.LDCW_INSN:
-                    case ClassWriter.FIELDORMETH_INSN:
-                    case ClassWriter.TYPE_INSN:
-                    case ClassWriter.IINC_INSN:
-                        u += 3;
-                        break;
-                    case ClassWriter.ITFMETH_INSN:
-                    case ClassWriter.INDYMETH_INSN:
-                        u += 5;
-                        break;
-                    // case ClassWriter.MANA_INSN:
-                    default:
-                        u += 4;
-                        break;
-                }
-                if (insert != 0) {
-                    // adds a new (u, insert) entry in the allIndexes and
-                    // allSizes arrays
-                    int[] newIndexes = new int[allIndexes.length + 1];
-                    int[] newSizes = new int[allSizes.length + 1];
-                    System.arraycopy(allIndexes,
-                            0,
-                            newIndexes,
-                            0,
-                            allIndexes.length);
-                    System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length);
-                    newIndexes[allIndexes.length] = u;
-                    newSizes[allSizes.length] = insert;
-                    allIndexes = newIndexes;
-                    allSizes = newSizes;
-                    if (insert > 0) {
-                        state = 3;
-                    }
-                }
-            }
-            if (state < 3) {
-                --state;
-            }
-        } while (state != 0);
-
-        // 2nd step:
-        // copies the bytecode of the method into a new bytevector, updates the
-        // offsets, and inserts (or removes) bytes as requested.
-
-        ByteVector newCode = new ByteVector(code.length);
-
-        u = 0;
-        while (u < code.length) {
-            int opcode = b[u] & 0xFF;
-            switch (ClassWriter.TYPE[opcode]) {
                 case ClassWriter.NOARG_INSN:
                 case ClassWriter.IMPLVAR_INSN:
-                    newCode.putByte(opcode);
                     u += 1;
                     break;
                 case ClassWriter.LABEL_INSN:
                     if (opcode > 201) {
-                        // changes temporary opcodes 202 to 217 (inclusive), 218
-                        // and 219 to IFEQ ... JSR (inclusive), IFNULL and
+                        // converts temporary opcodes 202 to 217, 218 and
+                        // 219 to IFEQ ... JSR (inclusive), IFNULL and
                         // IFNONNULL
                         opcode = opcode < 218 ? opcode - 49 : opcode - 20;
                         label = u + readUnsignedShort(b, u + 1);
@@ -2335,100 +2432,78 @@ class MethodWriter extends MethodVisitor {
                         label = u + readShort(b, u + 1);
                     }
                     newOffset = getNewOffset(allIndexes, allSizes, u, label);
-                    if (resize[u]) {
-                        // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
-                        // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is
-                        // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
-                        // and where <l'> designates the instruction just after
-                        // the GOTO_W.
-                        if (opcode == Opcodes.GOTO) {
-                            newCode.putByte(200); // GOTO_W
-                        } else if (opcode == Opcodes.JSR) {
-                            newCode.putByte(201); // JSR_W
-                        } else {
-                            newCode.putByte(opcode <= 166
-                                    ? ((opcode + 1) ^ 1) - 1
-                                    : opcode ^ 1);
-                            newCode.putShort(8); // jump offset
-                            newCode.putByte(200); // GOTO_W
-                            // newOffset now computed from start of GOTO_W
-                            newOffset -= 3;
+                    if (newOffset < Short.MIN_VALUE
+                            || newOffset > Short.MAX_VALUE) {
+                        if (!resize[u]) {
+                            if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
+                                // two additional bytes will be required to
+                                // replace this GOTO or JSR instruction with
+                                // a GOTO_W or a JSR_W
+                                insert = 2;
+                            } else {
+                                // five additional bytes will be required to
+                                // replace this IFxxx <l> instruction with
+                                // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx
+                                // is the "opposite" opcode of IFxxx (i.e.,
+                                // IFNE for IFEQ) and where <l'> designates
+                                // the instruction just after the GOTO_W.
+                                insert = 5;
+                            }
+                            resize[u] = true;
                         }
-                        newCode.putInt(newOffset);
-                    } else {
-                        newCode.putByte(opcode);
-                        newCode.putShort(newOffset);
                     }
                     u += 3;
                     break;
                 case ClassWriter.LABELW_INSN:
-                    label = u + readInt(b, u + 1);
-                    newOffset = getNewOffset(allIndexes, allSizes, u, label);
-                    newCode.putByte(opcode);
-                    newCode.putInt(newOffset);
                     u += 5;
                     break;
                 case ClassWriter.TABL_INSN:
-                    // skips 0 to 3 padding bytes
-                    v = u;
-                    u = u + 4 - (v & 3);
-                    // reads and copies instruction
-                    newCode.putByte(Opcodes.TABLESWITCH);
-                    newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
-                    label = v + readInt(b, u);
-                    u += 4;
-                    newOffset = getNewOffset(allIndexes, allSizes, v, label);
-                    newCode.putInt(newOffset);
-                    j = readInt(b, u);
-                    u += 4;
-                    newCode.putInt(j);
-                    j = readInt(b, u) - j + 1;
-                    u += 4;
-                    newCode.putInt(readInt(b, u - 4));
-                    for (; j > 0; --j) {
-                        label = v + readInt(b, u);
-                        u += 4;
-                        newOffset = getNewOffset(allIndexes, allSizes, v, label);
-                        newCode.putInt(newOffset);
+                    if (state == 1) {
+                        // true number of bytes to be added (or removed)
+                        // from this instruction = (future number of padding
+                        // bytes - current number of padding byte) -
+                        // previously over estimated variation =
+                        // = ((3 - newOffset%4) - (3 - u%4)) - u%4
+                        // = (-newOffset%4 + u%4) - u%4
+                        // = -(newOffset & 3)
+                        newOffset = getNewOffset(allIndexes, allSizes, 0, u);
+                        insert = -(newOffset & 3);
+                    } else if (!resize[u]) {
+                        // over estimation of the number of bytes to be
+                        // added to this instruction = 3 - current number
+                        // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3
+                        insert = u & 3;
+                        resize[u] = true;
                     }
+                    // skips instruction
+                    u = u + 4 - (u & 3);
+                    u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12;
                     break;
                 case ClassWriter.LOOK_INSN:
-                    // skips 0 to 3 padding bytes
-                    v = u;
-                    u = u + 4 - (v & 3);
-                    // reads and copies instruction
-                    newCode.putByte(Opcodes.LOOKUPSWITCH);
-                    newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
-                    label = v + readInt(b, u);
-                    u += 4;
-                    newOffset = getNewOffset(allIndexes, allSizes, v, label);
-                    newCode.putInt(newOffset);
-                    j = readInt(b, u);
-                    u += 4;
-                    newCode.putInt(j);
-                    for (; j > 0; --j) {
-                        newCode.putInt(readInt(b, u));
-                        u += 4;
-                        label = v + readInt(b, u);
-                        u += 4;
-                        newOffset = getNewOffset(allIndexes, allSizes, v, label);
-                        newCode.putInt(newOffset);
+                    if (state == 1) {
+                        // like TABL_INSN
+                        newOffset = getNewOffset(allIndexes, allSizes, 0, u);
+                        insert = -(newOffset & 3);
+                    } else if (!resize[u]) {
+                        // like TABL_INSN
+                        insert = u & 3;
+                        resize[u] = true;
                     }
+                    // skips instruction
+                    u = u + 4 - (u & 3);
+                    u += 8 * readInt(b, u + 4) + 8;
                     break;
                 case ClassWriter.WIDE_INSN:
                     opcode = b[u + 1] & 0xFF;
                     if (opcode == Opcodes.IINC) {
-                        newCode.putByteArray(b, u, 6);
                         u += 6;
                     } else {
-                        newCode.putByteArray(b, u, 4);
                         u += 4;
                     }
                     break;
                 case ClassWriter.VAR_INSN:
                 case ClassWriter.SBYTE_INSN:
                 case ClassWriter.LDC_INSN:
-                    newCode.putByteArray(b, u, 2);
                     u += 2;
                     break;
                 case ClassWriter.SHORT_INSN:
@@ -2436,66 +2511,225 @@ class MethodWriter extends MethodVisitor {
                 case ClassWriter.FIELDORMETH_INSN:
                 case ClassWriter.TYPE_INSN:
                 case ClassWriter.IINC_INSN:
-                    newCode.putByteArray(b, u, 3);
                     u += 3;
                     break;
                 case ClassWriter.ITFMETH_INSN:
                 case ClassWriter.INDYMETH_INSN:
-                    newCode.putByteArray(b, u, 5);
                     u += 5;
                     break;
-                // case MANA_INSN:
+                // case ClassWriter.MANA_INSN:
                 default:
-                    newCode.putByteArray(b, u, 4);
                     u += 4;
                     break;
+                }
+                if (insert != 0) {
+                    // adds a new (u, insert) entry in the allIndexes and
+                    // allSizes arrays
+                    int[] newIndexes = new int[allIndexes.length + 1];
+                    int[] newSizes = new int[allSizes.length + 1];
+                    System.arraycopy(allIndexes, 0, newIndexes, 0,
+                            allIndexes.length);
+                    System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length);
+                    newIndexes[allIndexes.length] = u;
+                    newSizes[allSizes.length] = insert;
+                    allIndexes = newIndexes;
+                    allSizes = newSizes;
+                    if (insert > 0) {
+                        state = 3;
+                    }
+                }
             }
-        }
+            if (state < 3) {
+                --state;
+            }
+        } while (state != 0);
 
-        // recomputes the stack map frames
-        if (frameCount > 0) {
-            if (compute == FRAMES) {
-                frameCount = 0;
-                stackMap = null;
-                previousFrame = null;
-                frame = null;
-                Frame f = new Frame();
-                f.owner = labels;
-                Type[] args = Type.getArgumentTypes(descriptor);
-                f.initInputFrame(cw, access, args, maxLocals);
-                visitFrame(f);
-                Label l = labels;
-                while (l != null) {
-                    /*
-                     * here we need the original label position. getNewOffset
-                     * must therefore never have been called for this label.
-                     */
-                    u = l.position - 3;
-                    if ((l.status & Label.STORE) != 0 || (u >= 0 && resize[u]))
-                    {
-                        getNewOffset(allIndexes, allSizes, l);
-                        // TODO update offsets in UNINITIALIZED values
-                        visitFrame(l.frame);
+        // 2nd step:
+        // copies the bytecode of the method into a new bytevector, updates the
+        // offsets, and inserts (or removes) bytes as requested.
+
+        ByteVector newCode = new ByteVector(code.length);
+
+        u = 0;
+        while (u < code.length) {
+            int opcode = b[u] & 0xFF;
+            switch (ClassWriter.TYPE[opcode]) {
+            case ClassWriter.NOARG_INSN:
+            case ClassWriter.IMPLVAR_INSN:
+                newCode.putByte(opcode);
+                u += 1;
+                break;
+            case ClassWriter.LABEL_INSN:
+                if (opcode > 201) {
+                    // changes temporary opcodes 202 to 217 (inclusive), 218
+                    // and 219 to IFEQ ... JSR (inclusive), IFNULL and
+                    // IFNONNULL
+                    opcode = opcode < 218 ? opcode - 49 : opcode - 20;
+                    label = u + readUnsignedShort(b, u + 1);
+                } else {
+                    label = u + readShort(b, u + 1);
+                }
+                newOffset = getNewOffset(allIndexes, allSizes, u, label);
+                if (resize[u]) {
+                    // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
+                    // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is
+                    // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
+                    // and where <l'> designates the instruction just after
+                    // the GOTO_W.
+                    if (opcode == Opcodes.GOTO) {
+                        newCode.putByte(200); // GOTO_W
+                    } else if (opcode == Opcodes.JSR) {
+                        newCode.putByte(201); // JSR_W
+                    } else {
+                        newCode.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
+                                : opcode ^ 1);
+                        newCode.putShort(8); // jump offset
+                        newCode.putByte(200); // GOTO_W
+                        // newOffset now computed from start of GOTO_W
+                        newOffset -= 3;
                     }
-                    l = l.successor;
+                    newCode.putInt(newOffset);
+                } else {
+                    newCode.putByte(opcode);
+                    newCode.putShort(newOffset);
                 }
-            } else {
+                u += 3;
+                break;
+            case ClassWriter.LABELW_INSN:
+                label = u + readInt(b, u + 1);
+                newOffset = getNewOffset(allIndexes, allSizes, u, label);
+                newCode.putByte(opcode);
+                newCode.putInt(newOffset);
+                u += 5;
+                break;
+            case ClassWriter.TABL_INSN:
+                // skips 0 to 3 padding bytes
+                v = u;
+                u = u + 4 - (v & 3);
+                // reads and copies instruction
+                newCode.putByte(Opcodes.TABLESWITCH);
+                newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
+                label = v + readInt(b, u);
+                u += 4;
+                newOffset = getNewOffset(allIndexes, allSizes, v, label);
+                newCode.putInt(newOffset);
+                j = readInt(b, u);
+                u += 4;
+                newCode.putInt(j);
+                j = readInt(b, u) - j + 1;
+                u += 4;
+                newCode.putInt(readInt(b, u - 4));
+                for (; j > 0; --j) {
+                    label = v + readInt(b, u);
+                    u += 4;
+                    newOffset = getNewOffset(allIndexes, allSizes, v, label);
+                    newCode.putInt(newOffset);
+                }
+                break;
+            case ClassWriter.LOOK_INSN:
+                // skips 0 to 3 padding bytes
+                v = u;
+                u = u + 4 - (v & 3);
+                // reads and copies instruction
+                newCode.putByte(Opcodes.LOOKUPSWITCH);
+                newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
+                label = v + readInt(b, u);
+                u += 4;
+                newOffset = getNewOffset(allIndexes, allSizes, v, label);
+                newCode.putInt(newOffset);
+                j = readInt(b, u);
+                u += 4;
+                newCode.putInt(j);
+                for (; j > 0; --j) {
+                    newCode.putInt(readInt(b, u));
+                    u += 4;
+                    label = v + readInt(b, u);
+                    u += 4;
+                    newOffset = getNewOffset(allIndexes, allSizes, v, label);
+                    newCode.putInt(newOffset);
+                }
+                break;
+            case ClassWriter.WIDE_INSN:
+                opcode = b[u + 1] & 0xFF;
+                if (opcode == Opcodes.IINC) {
+                    newCode.putByteArray(b, u, 6);
+                    u += 6;
+                } else {
+                    newCode.putByteArray(b, u, 4);
+                    u += 4;
+                }
+                break;
+            case ClassWriter.VAR_INSN:
+            case ClassWriter.SBYTE_INSN:
+            case ClassWriter.LDC_INSN:
+                newCode.putByteArray(b, u, 2);
+                u += 2;
+                break;
+            case ClassWriter.SHORT_INSN:
+            case ClassWriter.LDCW_INSN:
+            case ClassWriter.FIELDORMETH_INSN:
+            case ClassWriter.TYPE_INSN:
+            case ClassWriter.IINC_INSN:
+                newCode.putByteArray(b, u, 3);
+                u += 3;
+                break;
+            case ClassWriter.ITFMETH_INSN:
+            case ClassWriter.INDYMETH_INSN:
+                newCode.putByteArray(b, u, 5);
+                u += 5;
+                break;
+            // case MANA_INSN:
+            default:
+                newCode.putByteArray(b, u, 4);
+                u += 4;
+                break;
+            }
+        }
+
+        // updates the stack map frame labels
+        if (compute == FRAMES) {
+            Label l = labels;
+            while (l != null) {
                 /*
-                 * Resizing an existing stack map frame table is really hard.
-                 * Not only the table must be parsed to update the offets, but
-                 * new frames may be needed for jump instructions that were
-                 * inserted by this method. And updating the offsets or
-                 * inserting frames can change the format of the following
-                 * frames, in case of packed frames. In practice the whole table
-                 * must be recomputed. For this the frames are marked as
-                 * potentially invalid. This will cause the whole class to be
-                 * reread and rewritten with the COMPUTE_FRAMES option (see the
-                 * ClassWriter.toByteArray method). This is not very efficient
-                 * but is much easier and requires much less code than any other
-                 * method I can think of.
+                 * Detects the labels that are just after an IF instruction that
+                 * has been resized with the IFNOT GOTO_W pattern. These labels
+                 * are now the target of a jump instruction (the IFNOT
+                 * instruction). Note that we need the original label position
+                 * here. getNewOffset must therefore never have been called for
+                 * this label.
                  */
-                cw.invalidFrames = true;
+                u = l.position - 3;
+                if (u >= 0 && resize[u]) {
+                    l.status |= Label.TARGET;
+                }
+                getNewOffset(allIndexes, allSizes, l);
+                l = l.successor;
+            }
+            // Update the offsets in the uninitialized types
+            for (i = 0; i < cw.typeTable.length; ++i) {
+                Item item = cw.typeTable[i];
+                if (item != null && item.type == ClassWriter.TYPE_UNINIT) {
+                    item.intVal = getNewOffset(allIndexes, allSizes, 0,
+                            item.intVal);
+                }
             }
+            // The stack map frames are not serialized yet, so we don't need
+            // to update them. They will be serialized in visitMaxs.
+        } else if (frameCount > 0) {
+            /*
+             * Resizing an existing stack map frame table is really hard. Not
+             * only the table must be parsed to update the offets, but new
+             * frames may be needed for jump instructions that were inserted by
+             * this method. And updating the offsets or inserting frames can
+             * change the format of the following frames, in case of packed
+             * frames. In practice the whole table must be recomputed. For this
+             * the frames are marked as potentially invalid. This will cause the
+             * whole class to be reread and rewritten with the COMPUTE_FRAMES
+             * option (see the ClassWriter.toByteArray method). This is not very
+             * efficient but is much easier and requires much less code than any
+             * other method I can think of.
+             */
+            cw.invalidFrames = true;
         }
         // updates the exception handler block labels
         Handler h = firstHandler;
@@ -2528,10 +2762,11 @@ class MethodWriter extends MethodVisitor {
             b = lineNumber.data;
             u = 0;
             while (u < lineNumber.length) {
-                writeShort(b, u, getNewOffset(allIndexes,
-                        allSizes,
-                        0,
-                        readUnsignedShort(b, u)));
+                writeShort(
+                        b,
+                        u,
+                        getNewOffset(allIndexes, allSizes, 0,
+                                readUnsignedShort(b, u)));
                 u += 4;
             }
         }
@@ -2553,9 +2788,11 @@ class MethodWriter extends 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.
+     * 
+     * @param b
+     *            a byte array.
+     * @param index
+     *            the start index of the value to be read.
      * @return the read value.
      */
     static int readUnsignedShort(final byte[] b, final int index) {
@@ -2564,9 +2801,11 @@ class MethodWriter extends 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.
+     * 
+     * @param b
+     *            a byte array.
+     * @param index
+     *            the start index of the value to be read.
      * @return the read value.
      */
     static short readShort(final byte[] b, final int index) {
@@ -2575,9 +2814,11 @@ class MethodWriter extends 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.
+     * 
+     * @param b
+     *            a byte array.
+     * @param index
+     *            the start index of the value to be read.
      * @return the read value.
      */
     static int readInt(final byte[] b, final int index) {
@@ -2587,10 +2828,13 @@ class MethodWriter extends 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.
+     * 
+     * @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.
      */
     static void writeShort(final byte[] b, final int index, final int s) {
         b[index] = (byte) (s >>> 8);
@@ -2598,32 +2842,34 @@ class MethodWriter extends MethodVisitor {
     }
 
     /**
-     * Computes the future value of a bytecode offset. <p> Note: it is possible
-     * 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').
-     *


<TRUNCATED>

[10/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
index a248cdf..d6c9c90 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
@@ -29,14 +29,19 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
-import org.apache.tapestry5.internal.plastic.asm.*;
-
 import java.util.ArrayList;
 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.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
 /**
  * A node that represents a field.
- *
+ * 
  * @author Eric Bruneton
  */
 public class FieldNode extends FieldVisitor {
@@ -63,8 +68,8 @@ public class FieldNode extends FieldVisitor {
     public String signature;
 
     /**
-     * The field's initial value. This field, which may be <tt>null</tt> if
-     * the field does not have an initial value, must be an {@link Integer}, a
+     * The field's initial value. This field, which may be <tt>null</tt> if the
+     * field does not have an initial value, must be an {@link Integer}, a
      * {@link Float}, a {@link Long}, a {@link Double} or a {@link String}.
      */
     public Object value;
@@ -72,8 +77,8 @@ public class FieldNode extends FieldVisitor {
     /**
      * The runtime visible annotations of this field. 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;
@@ -81,17 +86,35 @@ public class FieldNode extends FieldVisitor {
     /**
      * The runtime invisible annotations of this field. 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 field. 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 field. 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 field. 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;
 
@@ -99,56 +122,60 @@ public class FieldNode extends FieldVisitor {
      * Constructs a new {@link FieldNode}. <i>Subclasses must not use this
      * constructor</i>. Instead, they must use the
      * {@link #FieldNode(int, int, String, String, String, Object)} version.
-     *
-     * @param access the field's access flags (see
-     *        {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This parameter also indicates
-     *        if the field is synthetic and/or deprecated.
-     * @param name the field's name.
-     * @param desc the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type
-     *        Type}).
-     * @param signature the field's signature.
-     * @param value the field's initial value. This parameter, which may be
-     *        <tt>null</tt> if the field does not have an initial value, must be
-     *        an {@link Integer}, a {@link Float}, a {@link Long}, a
-     *        {@link Double} or a {@link String}.
+     * 
+     * @param access
+     *            the field's access flags (see
+     *            {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This parameter also
+     *            indicates if the field is synthetic and/or deprecated.
+     * @param name
+     *            the field's name.
+     * @param desc
+     *            the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type
+     *            Type}).
+     * @param signature
+     *            the field's signature.
+     * @param value
+     *            the field's initial value. This parameter, which may be
+     *            <tt>null</tt> if the field does not have an initial value,
+     *            must be an {@link Integer}, a {@link Float}, a {@link Long}, a
+     *            {@link Double} or a {@link String}.
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
      */
-    public FieldNode(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final Object value)
-    {
-        this(Opcodes.ASM4, access, name, desc, signature, value);
+    public FieldNode(final int access, final String name, final String desc,
+            final String signature, final Object value) {
+        this(Opcodes.ASM5, access, name, desc, signature, value);
+        if (getClass() != FieldNode.class) {
+            throw new IllegalStateException();
+        }
     }
 
     /**
      * Constructs a new {@link FieldNode}. <i>Subclasses must not use this
-     * constructor</i>. Instead, they must use the
-     * {@link #FieldNode(int, int, String, String, String, Object)} version.
-     *
-     * @param api the ASM API version implemented by this visitor. Must be one
-     *        of {@link Opcodes#ASM4}.
-     * @param access the field's access flags (see
-     *        {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This parameter also indicates
-     *        if the field is synthetic and/or deprecated.
-     * @param name the field's name.
-     * @param desc the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type
-     *        Type}).
-     * @param signature the field's signature.
-     * @param value the field's initial value. This parameter, which may be
-     *        <tt>null</tt> if the field does not have an initial value, must be
-     *        an {@link Integer}, a {@link Float}, a {@link Long}, a
-     *        {@link Double} or a {@link String}.
+     * constructor</i>.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param access
+     *            the field's access flags (see
+     *            {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This parameter also
+     *            indicates if the field is synthetic and/or deprecated.
+     * @param name
+     *            the field's name.
+     * @param desc
+     *            the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type
+     *            Type}).
+     * @param signature
+     *            the field's signature.
+     * @param value
+     *            the field's initial value. This parameter, which may be
+     *            <tt>null</tt> if the field does not have an initial value,
+     *            must be an {@link Integer}, a {@link Float}, a {@link Long}, a
+     *            {@link Double} or a {@link String}.
      */
-    public FieldNode(
-        final int api,
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final Object value)
-    {
+    public FieldNode(final int api, final int access, final String name,
+            final String desc, final String signature, final Object value) {
         super(api);
         this.access = access;
         this.name = name;
@@ -162,10 +189,8 @@ public class FieldNode extends FieldVisitor {
     // ------------------------------------------------------------------------
 
     @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) {
@@ -182,6 +207,24 @@ public class FieldNode extends FieldVisitor {
     }
 
     @Override
+    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 void visitAttribute(final Attribute attr) {
         if (attrs == null) {
             attrs = new ArrayList<Attribute>(1);
@@ -202,17 +245,29 @@ public class FieldNode extends FieldVisitor {
      * 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();
+            }
+        }
     }
 
     /**
      * Makes the given class visitor visit this field.
-     *
-     * @param cv a class visitor.
+     * 
+     * @param cv
+     *            a class visitor.
      */
     public void accept(final ClassVisitor cv) {
         FieldVisitor fv = cv.visitField(access, name, desc, signature, value);
@@ -230,6 +285,19 @@ public class FieldNode extends FieldVisitor {
             AnnotationNode an = invisibleAnnotations.get(i);
             an.accept(fv.visitAnnotation(an.desc, false));
         }
+        n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
+        for (i = 0; i < n; ++i) {
+            TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+            an.accept(fv.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(fv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+                    false));
+        }
         n = attrs == null ? 0 : attrs.size();
         for (i = 0; i < n; ++i) {
             fv.visitAttribute(attrs.get(i));

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
index c2564e3..8600566 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
@@ -29,14 +29,14 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
-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.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
 /**
  * A node that represents a stack map frame. These nodes are pseudo instruction
  * nodes in order to be inserted in an instruction list. In fact these nodes
@@ -45,18 +45,19 @@ import java.util.Map;
  * the target of a jump instruction, or that starts an exception handler block.
  * The stack map frame types must describe the values of the local variables and
  * of the operand stack elements <i>just before</i> <b>i</b> is executed. <br>
- * <br> (*) this is mandatory only for classes whose version is greater than or
- * equal to {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#V1_6 V1_6}.
- *
+ * <br>
+ * (*) this is mandatory only for classes whose version is greater than or equal
+ * to {@link Opcodes#V1_6 V1_6}.
+ * 
  * @author Eric Bruneton
  */
 public class FrameNode extends AbstractInsnNode {
 
     /**
-     * The type of this frame. Must be {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_NEW} for expanded
-     * frames, or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_FULL}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_APPEND},
-     * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_CHOP}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_SAME} or
-     * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_APPEND}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_SAME1} for compressed frames.
+     * The type of this frame. Must be {@link Opcodes#F_NEW} for expanded
+     * frames, or {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
+     * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
+     * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
      */
     public int type;
 
@@ -82,49 +83,49 @@ public class FrameNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link FrameNode}.
-     *
-     * @param type the type of this frame. Must be {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_NEW} for
-     *        expanded frames, or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_FULL},
-     *        {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_APPEND}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_CHOP},
-     *        {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_SAME} or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_APPEND},
-     *        {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_SAME1} for compressed frames.
-     * @param nLocal number of local variables of this stack map frame.
-     * @param local the types of the local variables of this stack map frame.
-     *        Elements of this list can be Integer, String or LabelNode objects
-     *        (for primitive, reference and uninitialized types respectively -
-     *        see {@link MethodVisitor}).
-     * @param nStack number of operand stack elements of this stack map frame.
-     * @param stack the types of the operand stack elements of this stack map
-     *        frame. Elements of this list can be Integer, String or LabelNode
-     *        objects (for primitive, reference and uninitialized types
-     *        respectively - see {@link MethodVisitor}).
+     * 
+     * @param type
+     *            the type of this frame. Must be {@link Opcodes#F_NEW} for
+     *            expanded frames, or {@link Opcodes#F_FULL},
+     *            {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP},
+     *            {@link Opcodes#F_SAME} or {@link Opcodes#F_APPEND},
+     *            {@link Opcodes#F_SAME1} for compressed frames.
+     * @param nLocal
+     *            number of local variables of this stack map frame.
+     * @param local
+     *            the types of the local variables of this stack map frame.
+     *            Elements of this list can be Integer, String or LabelNode
+     *            objects (for primitive, reference and uninitialized types
+     *            respectively - see {@link MethodVisitor}).
+     * @param nStack
+     *            number of operand stack elements of this stack map frame.
+     * @param stack
+     *            the types of the operand stack elements of this stack map
+     *            frame. Elements of this list can be Integer, String or
+     *            LabelNode objects (for primitive, reference and uninitialized
+     *            types respectively - see {@link MethodVisitor}).
      */
-    public FrameNode(
-        final int type,
-        final int nLocal,
-        final Object[] local,
-        final int nStack,
-        final Object[] stack)
-    {
+    public FrameNode(final int type, final int nLocal, final Object[] local,
+            final int nStack, final Object[] stack) {
         super(-1);
         this.type = type;
         switch (type) {
-            case Opcodes.F_NEW:
-            case Opcodes.F_FULL:
-                this.local = asList(nLocal, local);
-                this.stack = asList(nStack, stack);
-                break;
-            case Opcodes.F_APPEND:
-                this.local = asList(nLocal, local);
-                break;
-            case Opcodes.F_CHOP:
-                this.local = Arrays.asList(new Object[nLocal]);
-                break;
-            case Opcodes.F_SAME:
-                break;
-            case Opcodes.F_SAME1:
-                this.stack = asList(1, stack);
-                break;
+        case Opcodes.F_NEW:
+        case Opcodes.F_FULL:
+            this.local = asList(nLocal, local);
+            this.stack = asList(nStack, stack);
+            break;
+        case Opcodes.F_APPEND:
+            this.local = asList(nLocal, local);
+            break;
+        case Opcodes.F_CHOP:
+            this.local = Arrays.asList(new Object[nLocal]);
+            break;
+        case Opcodes.F_SAME:
+            break;
+        case Opcodes.F_SAME1:
+            this.stack = asList(1, stack);
+            break;
         }
     }
 
@@ -135,32 +136,30 @@ public class FrameNode extends AbstractInsnNode {
 
     /**
      * Makes the given visitor visit this stack map frame.
-     *
-     * @param mv a method visitor.
+     * 
+     * @param mv
+     *            a method visitor.
      */
     @Override
     public void accept(final MethodVisitor mv) {
         switch (type) {
-            case Opcodes.F_NEW:
-            case Opcodes.F_FULL:
-                mv.visitFrame(type,
-                        local.size(),
-                        asArray(local),
-                        stack.size(),
-                        asArray(stack));
-                break;
-            case Opcodes.F_APPEND:
-                mv.visitFrame(type, local.size(), asArray(local), 0, null);
-                break;
-            case Opcodes.F_CHOP:
-                mv.visitFrame(type, local.size(), null, 0, null);
-                break;
-            case Opcodes.F_SAME:
-                mv.visitFrame(type, 0, null, 0, null);
-                break;
-            case Opcodes.F_SAME1:
-                mv.visitFrame(type, 0, null, 1, asArray(stack));
-                break;
+        case Opcodes.F_NEW:
+        case Opcodes.F_FULL:
+            mv.visitFrame(type, local.size(), asArray(local), stack.size(),
+                    asArray(stack));
+            break;
+        case Opcodes.F_APPEND:
+            mv.visitFrame(type, local.size(), asArray(local), 0, null);
+            break;
+        case Opcodes.F_CHOP:
+            mv.visitFrame(type, local.size(), null, 0, null);
+            break;
+        case Opcodes.F_SAME:
+            mv.visitFrame(type, 0, null, 0, null);
+            break;
+        case Opcodes.F_SAME1:
+            mv.visitFrame(type, 0, null, 1, asArray(stack));
+            break;
         }
     }
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java
index c1b13dd..729dd3e 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.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 an IINC instruction.
- *
+ * 
  * @author Eric Bruneton
  */
 public class IincInsnNode extends AbstractInsnNode {
@@ -53,9 +53,11 @@ public class IincInsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link IincInsnNode}.
-     *
-     * @param var index of the local variable to be incremented.
-     * @param incr increment amount to increment the local variable by.
+     * 
+     * @param var
+     *            index of the local variable to be incremented.
+     * @param incr
+     *            increment amount to increment the local variable by.
      */
     public IincInsnNode(final int var, final int incr) {
         super(Opcodes.IINC);
@@ -71,10 +73,11 @@ public class IincInsnNode extends AbstractInsnNode {
     @Override
     public void accept(final MethodVisitor mv) {
         mv.visitIincInsn(var, incr);
+        acceptAnnotations(mv);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new IincInsnNode(var, incr);
+        return new IincInsnNode(var, incr).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/InnerClassNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java
index bfc16b0..877430f 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java
@@ -33,7 +33,7 @@ import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
 
 /**
  * A node that represents an inner class.
- *
+ * 
  * @author Eric Bruneton
  */
 public class InnerClassNode {
@@ -46,8 +46,8 @@ public class InnerClassNode {
 
     /**
      * The internal name of the class to which the inner class belongs (see
-     * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). May
-     * be <tt>null</tt>.
+     * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). May be
+     * <tt>null</tt>.
      */
     public String outerName;
 
@@ -65,25 +65,24 @@ public class InnerClassNode {
 
     /**
      * Constructs a new {@link InnerClassNode}.
-     *
-     * @param name the internal name of an inner class (see
-     *        {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}).
-     * @param outerName the internal name of the class to which the inner class
-     *        belongs (see
-     *        {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}).
-     *        May be <tt>null</tt>.
-     * @param innerName the (simple) name of the inner class inside its
-     *        enclosing class. May be <tt>null</tt> for anonymous inner
-     *        classes.
-     * @param access the access flags of the inner class as originally declared
-     *        in the enclosing class.
+     * 
+     * @param name
+     *            the internal name of an inner class (see
+     *            {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+     *            getInternalName}).
+     * @param outerName
+     *            the internal name of the class to which the inner class
+     *            belongs (see {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+     *            getInternalName}). May be <tt>null</tt>.
+     * @param innerName
+     *            the (simple) name of the inner class inside its enclosing
+     *            class. May be <tt>null</tt> for anonymous inner classes.
+     * @param access
+     *            the access flags of the inner class as originally declared in
+     *            the enclosing class.
      */
-    public InnerClassNode(
-        final String name,
-        final String outerName,
-        final String innerName,
-        final int access)
-    {
+    public InnerClassNode(final String name, final String outerName,
+            final String innerName, final int access) {
         this.name = name;
         this.outerName = outerName;
         this.innerName = innerName;
@@ -92,8 +91,9 @@ public class InnerClassNode {
 
     /**
      * Makes the given class visitor visit this inner class.
-     *
-     * @param cv a class visitor.
+     * 
+     * @param cv
+     *            a class visitor.
      */
     public void accept(final ClassVisitor cv) {
         cv.visitInnerClass(name, outerName, innerName, access);

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
index c4fa98a..8eaaf68 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
@@ -29,11 +29,11 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
 import java.util.ListIterator;
 import java.util.NoSuchElementException;
 
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
 /**
  * A doubly linked list of {@link AbstractInsnNode} objects. <i>This
  * implementation is not thread safe</i>.
@@ -63,7 +63,7 @@ public class InsnList {
 
     /**
      * Returns the number of instructions in this list.
-     *
+     * 
      * @return the number of instructions in this list.
      */
     public int size() {
@@ -72,9 +72,9 @@ public class InsnList {
 
     /**
      * Returns the first instruction in this list.
-     *
-     * @return the first instruction in this list, or <tt>null</tt> if the
-     *         list is empty.
+     * 
+     * @return the first instruction in this list, or <tt>null</tt> if the list
+     *         is empty.
      */
     public AbstractInsnNode getFirst() {
         return first;
@@ -82,7 +82,7 @@ public class InsnList {
 
     /**
      * Returns the last instruction in this list.
-     *
+     * 
      * @return the last instruction in this list, or <tt>null</tt> if the list
      *         is empty.
      */
@@ -95,10 +95,12 @@ public class InsnList {
      * of the instructions in this list to avoid scanning the whole list each
      * time it is called. Once the cache is built, this method run in constant
      * time. This cache is invalidated by all the methods that modify the list.
-     *
-     * @param index the index of the instruction that must be returned.
+     * 
+     * @param index
+     *            the index of the instruction that must be returned.
      * @return the instruction whose index is given.
-     * @throws IndexOutOfBoundsException if (index < 0 || index >= size()).
+     * @throws IndexOutOfBoundsException
+     *             if (index &lt; 0 || index &gt;= size()).
      */
     public AbstractInsnNode get(final int index) {
         if (index < 0 || index >= size) {
@@ -111,11 +113,12 @@ public class InsnList {
     }
 
     /**
-     * Returns <tt>true</tt> if the given instruction belongs to this list.
-     * This method always scans the instructions of this list until it finds the
+     * Returns <tt>true</tt> if the given instruction belongs to this list. This
+     * method always scans the instructions of this list until it finds the
      * given instruction or reaches the end of the list.
-     *
-     * @param insn an instruction.
+     * 
+     * @param insn
+     *            an instruction.
      * @return <tt>true</tt> if the given instruction belongs to this list.
      */
     public boolean contains(final AbstractInsnNode insn) {
@@ -132,8 +135,9 @@ public class InsnList {
      * list each time it is called. Once the cache is built, this method run in
      * constant time. The cache is invalidated by all the methods that modify
      * the list.
-     *
-     * @param insn an instruction <i>of this list</i>.
+     * 
+     * @param insn
+     *            an instruction <i>of this list</i>.
      * @return the index of the given instruction in this list. <i>The result of
      *         this method is undefined if the given instruction does not belong
      *         to this list</i>. Use {@link #contains contains} to test if an
@@ -148,8 +152,9 @@ public class InsnList {
 
     /**
      * Makes the given visitor visit all of the instructions in this list.
-     *
-     * @param mv the method visitor that must visit the instructions.
+     * 
+     * @param mv
+     *            the method visitor that must visit the instructions.
      */
     public void accept(final MethodVisitor mv) {
         AbstractInsnNode insn = first;
@@ -161,7 +166,7 @@ public class InsnList {
 
     /**
      * Returns an iterator over the instructions in this list.
-     *
+     * 
      * @return an iterator over the instructions in this list.
      */
     public ListIterator<AbstractInsnNode> iterator() {
@@ -170,7 +175,7 @@ public class InsnList {
 
     /**
      * Returns an iterator over the instructions in this list.
-     *
+     * 
      * @return an iterator over the instructions in this list.
      */
     @SuppressWarnings("unchecked")
@@ -180,7 +185,7 @@ public class InsnList {
 
     /**
      * Returns an array containing all of the instructions in this list.
-     *
+     * 
      * @return an array containing all of the instructions in this list.
      */
     public AbstractInsnNode[] toArray() {
@@ -197,10 +202,12 @@ public class InsnList {
 
     /**
      * Replaces an instruction of this list with another instruction.
-     *
-     * @param location an instruction <i>of this list</i>.
-     * @param insn another instruction, <i>which must not belong to any
-     *        {@link InsnList}</i>.
+     * 
+     * @param location
+     *            an instruction <i>of this list</i>.
+     * @param insn
+     *            another instruction, <i>which must not belong to any
+     *            {@link InsnList}</i>.
      */
     public void set(final AbstractInsnNode location, final AbstractInsnNode insn) {
         AbstractInsnNode next = location.next;
@@ -231,9 +238,10 @@ public class InsnList {
 
     /**
      * Adds the given instruction to the end of this list.
-     *
-     * @param insn an instruction, <i>which must not belong to any
-     *        {@link InsnList}</i>.
+     * 
+     * @param insn
+     *            an instruction, <i>which must not belong to any
+     *            {@link InsnList}</i>.
      */
     public void add(final AbstractInsnNode insn) {
         ++size;
@@ -251,9 +259,10 @@ public class InsnList {
 
     /**
      * Adds the given instructions to the end of this list.
-     *
-     * @param insns an instruction list, which is cleared during the process.
-     *        This list must be different from 'this'.
+     * 
+     * @param insns
+     *            an instruction list, which is cleared during the process. This
+     *            list must be different from 'this'.
      */
     public void add(final InsnList insns) {
         if (insns.size == 0) {
@@ -275,9 +284,10 @@ public class InsnList {
 
     /**
      * Inserts the given instruction at the begining of this list.
-     *
-     * @param insn an instruction, <i>which must not belong to any
-     *        {@link InsnList}</i>.
+     * 
+     * @param insn
+     *            an instruction, <i>which must not belong to any
+     *            {@link InsnList}</i>.
      */
     public void insert(final AbstractInsnNode insn) {
         ++size;
@@ -295,9 +305,10 @@ public class InsnList {
 
     /**
      * Inserts the given instructions at the begining of this list.
-     *
-     * @param insns an instruction list, which is cleared during the process.
-     *        This list must be different from 'this'.
+     * 
+     * @param insns
+     *            an instruction list, which is cleared during the process. This
+     *            list must be different from 'this'.
      */
     public void insert(final InsnList insns) {
         if (insns.size == 0) {
@@ -319,13 +330,16 @@ public class InsnList {
 
     /**
      * Inserts the given instruction after the specified instruction.
-     *
-     * @param location an instruction <i>of this list</i> after which insn must be
-     *        inserted.
-     * @param insn the instruction to be inserted, <i>which must not belong to
-     *        any {@link InsnList}</i>.
+     * 
+     * @param location
+     *            an instruction <i>of this list</i> after which insn must be
+     *            inserted.
+     * @param insn
+     *            the instruction to be inserted, <i>which must not belong to
+     *            any {@link InsnList}</i>.
      */
-    public void insert(final AbstractInsnNode location, final AbstractInsnNode insn) {
+    public void insert(final AbstractInsnNode location,
+            final AbstractInsnNode insn) {
         ++size;
         AbstractInsnNode next = location.next;
         if (next == null) {
@@ -342,11 +356,13 @@ public class InsnList {
 
     /**
      * Inserts the given instructions after the specified instruction.
-     *
-     * @param location an instruction <i>of this list</i> after which the
-     *        instructions must be inserted.
-     * @param insns the instruction list to be inserted, which is cleared during
-     *        the process. This list must be different from 'this'.
+     * 
+     * @param location
+     *            an instruction <i>of this list</i> after which the
+     *            instructions must be inserted.
+     * @param insns
+     *            the instruction list to be inserted, which is cleared during
+     *            the process. This list must be different from 'this'.
      */
     public void insert(final AbstractInsnNode location, final InsnList insns) {
         if (insns.size == 0) {
@@ -370,13 +386,16 @@ public class InsnList {
 
     /**
      * Inserts the given instruction before the specified instruction.
-     *
-     * @param location an instruction <i>of this list</i> before which insn must be
-     *        inserted.
-     * @param insn the instruction to be inserted, <i>which must not belong to
-     *        any {@link InsnList}</i>.
+     * 
+     * @param location
+     *            an instruction <i>of this list</i> before which insn must be
+     *            inserted.
+     * @param insn
+     *            the instruction to be inserted, <i>which must not belong to
+     *            any {@link InsnList}</i>.
      */
-    public void insertBefore(final AbstractInsnNode location, final AbstractInsnNode insn) {
+    public void insertBefore(final AbstractInsnNode location,
+            final AbstractInsnNode insn) {
         ++size;
         AbstractInsnNode prev = location.prev;
         if (prev == null) {
@@ -393,38 +412,40 @@ public class InsnList {
 
     /**
      * Inserts the given instructions before the specified instruction.
-     *
-     * @param location  an instruction <i>of this list</i> before which the instructions
-     *        must be inserted.
-     * @param insns the instruction list to be inserted, which is cleared during
-     *        the process. This list must be different from 'this'.
+     * 
+     * @param location
+     *            an instruction <i>of this list</i> before which the
+     *            instructions must be inserted.
+     * @param insns
+     *            the instruction list to be inserted, which is cleared during
+     *            the process. This list must be different from 'this'.
      */
-    public void insertBefore(final AbstractInsnNode location, final InsnList insns) {
+    public void insertBefore(final AbstractInsnNode location,
+            final InsnList insns) {
         if (insns.size == 0) {
             return;
         }
         size += insns.size;
         AbstractInsnNode ifirst = insns.first;
         AbstractInsnNode ilast = insns.last;
-        AbstractInsnNode prev = location .prev;
+        AbstractInsnNode prev = location.prev;
         if (prev == null) {
             first = ifirst;
         } else {
             prev.next = ifirst;
         }
-        location .prev = ilast;
-        ilast.next = location ;
+        location.prev = ilast;
+        ilast.next = location;
         ifirst.prev = prev;
         cache = null;
         insns.removeAll(false);
     }
 
-
-
     /**
      * Removes the given instruction from this list.
-     *
-     * @param insn the instruction <i>of this list</i> that must be removed.
+     * 
+     * @param insn
+     *            the instruction <i>of this list</i> that must be removed.
      */
     public void remove(final AbstractInsnNode insn) {
         --size;
@@ -455,9 +476,10 @@ public class InsnList {
 
     /**
      * Removes all of the instructions of this list.
-     *
-     * @param mark if the instructions must be marked as no longer belonging to
-     *        any {@link InsnList}.
+     * 
+     * @param mark
+     *            if the instructions must be marked as no longer belonging to
+     *            any {@link InsnList}.
      */
     void removeAll(final boolean mark) {
         if (mark) {
@@ -499,14 +521,16 @@ public class InsnList {
     }
 
     // this class is not generified because it will create bridges
-    private final class InsnListIterator implements ListIterator/*<AbstractInsnNode>*/ {
+    private final class InsnListIterator implements ListIterator {
 
         AbstractInsnNode next;
 
         AbstractInsnNode prev;
 
+        AbstractInsnNode remove;
+
         InsnListIterator(int index) {
-            if(index==size()) {
+            if (index == size()) {
                 next = null;
                 prev = getLast();
             } else {
@@ -526,12 +550,22 @@ public class InsnList {
             AbstractInsnNode result = next;
             prev = result;
             next = result.next;
+            remove = result;
             return result;
         }
 
         public void remove() {
-            InsnList.this.remove(prev);
-            prev = prev.prev;
+            if (remove != null) {
+                if (remove == next) {
+                    next = next.next;
+                } else {
+                    prev = prev.prev;
+                }
+                InsnList.this.remove(remove);
+                remove = null;
+            } else {
+                throw new IllegalStateException();
+            }
         }
 
         public boolean hasPrevious() {
@@ -542,6 +576,7 @@ public class InsnList {
             AbstractInsnNode result = prev;
             next = result;
             prev = result.prev;
+            remove = result;
             return result;
         }
 
@@ -568,6 +603,7 @@ public class InsnList {
         public void add(Object o) {
             InsnList.this.insertBefore(next, (AbstractInsnNode) o);
             prev = (AbstractInsnNode) o;
+            remove = null;
         }
 
         public void set(Object o) {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
index 6abed41..7eb2359 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
@@ -29,34 +29,36 @@
  */
 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 zero operand instruction.
- *
+ * 
  * @author Eric Bruneton
  */
 public class InsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link InsnNode}.
-     *
-     * @param opcode the opcode of the instruction to be constructed. This
-     *        opcode must be NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1,
-     *        ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1,
-     *        FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD,
-     *        FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE,
-     *        FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2,
-     *        DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP, IADD, LADD,
-     *        FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV,
-     *        LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG,
-     *        ISHL, LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR,
-     *        LXOR, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F,
-     *        I2B, I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN,
-     *        FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW,
-     *        MONITORENTER, or MONITOREXIT.
+     * 
+     * @param opcode
+     *            the opcode of the instruction to be constructed. This opcode
+     *            must be NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1,
+     *            ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1,
+     *            FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD,
+     *            LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD,
+     *            IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE,
+     *            SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1,
+     *            DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB,
+     *            IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM,
+     *            FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR,
+     *            IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D,
+     *            L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S,
+     *            LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN,
+     *            DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER,
+     *            or MONITOREXIT.
      */
     public InsnNode(final int opcode) {
         super(opcode);
@@ -69,16 +71,18 @@ public class InsnNode extends AbstractInsnNode {
 
     /**
      * Makes the given visitor visit this instruction.
-     *
-     * @param mv a method visitor.
+     * 
+     * @param mv
+     *            a method visitor.
      */
     @Override
     public void accept(final MethodVisitor mv) {
         mv.visitInsn(opcode);
+        acceptAnnotations(mv);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new InsnNode(opcode);
+        return new InsnNode(opcode).cloneAnnotations(this);
     }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
index 03c0d54..5b0c351 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
@@ -29,13 +29,13 @@
  */
 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 an instruction with a single int operand.
- *
+ * 
  * @author Eric Bruneton
  */
 public class IntInsnNode extends AbstractInsnNode {
@@ -47,10 +47,12 @@ public class IntInsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link IntInsnNode}.
-     *
-     * @param opcode the opcode of the instruction to be constructed. This
-     *        opcode must be BIPUSH, SIPUSH or NEWARRAY.
-     * @param operand the operand of the instruction to be constructed.
+     * 
+     * @param opcode
+     *            the opcode of the instruction to be constructed. This opcode
+     *            must be BIPUSH, SIPUSH or NEWARRAY.
+     * @param operand
+     *            the operand of the instruction to be constructed.
      */
     public IntInsnNode(final int opcode, final int operand) {
         super(opcode);
@@ -59,9 +61,10 @@ public class IntInsnNode extends AbstractInsnNode {
 
     /**
      * Sets the opcode of this instruction.
-     *
-     * @param opcode the new instruction opcode. This opcode must be BIPUSH,
-     *        SIPUSH or NEWARRAY.
+     * 
+     * @param opcode
+     *            the new instruction opcode. This opcode must be BIPUSH, SIPUSH
+     *            or NEWARRAY.
      */
     public void setOpcode(final int opcode) {
         this.opcode = opcode;
@@ -75,10 +78,11 @@ public class IntInsnNode extends AbstractInsnNode {
     @Override
     public void accept(final MethodVisitor mv) {
         mv.visitIntInsn(opcode, operand);
+        acceptAnnotations(mv);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new IntInsnNode(opcode, operand);
+        return new IntInsnNode(opcode, operand).cloneAnnotations(this);
     }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
index d67b72f..2578768 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
@@ -29,15 +29,15 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
+import java.util.Map;
+
 import org.apache.tapestry5.internal.plastic.asm.Handle;
 import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
 import org.apache.tapestry5.internal.plastic.asm.Opcodes;
 
-import java.util.Map;
-
 /**
  * A node that represents an invokedynamic instruction.
- *
+ * 
  * @author Remi Forax
  */
 public class InvokeDynamicInsnNode extends AbstractInsnNode {
@@ -64,18 +64,18 @@ public class InvokeDynamicInsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link InvokeDynamicInsnNode}.
-     *
-     * @param name invokedynamic name.
-     * @param desc invokedynamic descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
-     * @param bsm the bootstrap method.
-     * @param bsmArgs the boostrap constant arguments.
+     * 
+     * @param name
+     *            invokedynamic name.
+     * @param desc
+     *            invokedynamic descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+     * @param bsm
+     *            the bootstrap method.
+     * @param bsmArgs
+     *            the boostrap constant arguments.
      */
-    public InvokeDynamicInsnNode(
-        final String name,
-        final String desc,
-        final Handle bsm,
-        final Object... bsmArgs)
-    {
+    public InvokeDynamicInsnNode(final String name, final String desc,
+            final Handle bsm, final Object... bsmArgs) {
         super(Opcodes.INVOKEDYNAMIC);
         this.name = name;
         this.desc = desc;
@@ -91,10 +91,12 @@ public class InvokeDynamicInsnNode extends AbstractInsnNode {
     @Override
     public void accept(final MethodVisitor mv) {
         mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+        acceptAnnotations(mv);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs);
+        return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs)
+                .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/JumpInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.java
index d0011a2..386c900 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.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 jump instruction. A jump instruction is an
  * instruction that may jump to another instruction.
- *
+ * 
  * @author Eric Bruneton
  */
 public class JumpInsnNode extends AbstractInsnNode {
@@ -49,14 +49,16 @@ public class JumpInsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link JumpInsnNode}.
-     *
-     * @param opcode the opcode of the type instruction to be constructed. This
-     *        opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
-     *        IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ,
-     *        IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
-     * @param label the operand of the instruction to be constructed. This
-     *        operand is a label that designates the instruction to which the
-     *        jump instruction may jump.
+     * 
+     * @param opcode
+     *            the opcode of the type instruction to be constructed. This
+     *            opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
+     *            IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
+     *            IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
+     * @param label
+     *            the operand of the instruction to be constructed. This operand
+     *            is a label that designates the instruction to which the jump
+     *            instruction may jump.
      */
     public JumpInsnNode(final int opcode, final LabelNode label) {
         super(opcode);
@@ -65,11 +67,12 @@ public class JumpInsnNode extends AbstractInsnNode {
 
     /**
      * Sets the opcode of this instruction.
-     *
-     * @param opcode the new instruction opcode. This opcode must be IFEQ, IFNE,
-     *        IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT,
-     *        IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO, JSR,
-     *        IFNULL or IFNONNULL.
+     * 
+     * @param opcode
+     *            the new instruction opcode. This opcode must be IFEQ, IFNE,
+     *            IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT,
+     *            IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO,
+     *            JSR, IFNULL or IFNONNULL.
      */
     public void setOpcode(final int opcode) {
         this.opcode = opcode;
@@ -83,10 +86,12 @@ public class JumpInsnNode extends AbstractInsnNode {
     @Override
     public void accept(final MethodVisitor mv) {
         mv.visitJumpInsn(opcode, label.getLabel());
+        acceptAnnotations(mv);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new JumpInsnNode(opcode, clone(label, labels));
+        return new JumpInsnNode(opcode, clone(label, labels))
+                .cloneAnnotations(this);
     }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
index a21f0d0..39c08ef 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
@@ -29,11 +29,11 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
+import java.util.Map;
+
 import org.apache.tapestry5.internal.plastic.asm.Label;
 import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
 
-import java.util.Map;
-
 /**
  * An {@link AbstractInsnNode} that encapsulates a {@link Label}.
  */

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java
index 82748cb..e048e74 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.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 an LDC instruction.
- *
+ * 
  * @author Eric Bruneton
  */
 public class LdcInsnNode extends AbstractInsnNode {
@@ -50,10 +50,11 @@ public class LdcInsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link LdcInsnNode}.
-     *
-     * @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} or a {@link String}.
+     * 
+     * @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} or a {@link String}.
      */
     public LdcInsnNode(final Object cst) {
         super(Opcodes.LDC);
@@ -68,10 +69,11 @@ public class LdcInsnNode extends AbstractInsnNode {
     @Override
     public void accept(final MethodVisitor mv) {
         mv.visitLdcInsn(cst);
+        acceptAnnotations(mv);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new LdcInsnNode(cst);
+        return new LdcInsnNode(cst).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/LineNumberNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.java
index fe4d39b..c475ee8 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.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 line number declaration. These nodes are pseudo
  * instruction nodes in order to be inserted in an instruction list.
- *
+ * 
  * @author Eric Bruneton
  */
 public class LineNumberNode extends AbstractInsnNode {
@@ -54,10 +54,12 @@ public class LineNumberNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link LineNumberNode}.
-     *
-     * @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.
+     * 
+     * @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.
      */
     public LineNumberNode(final int line, final LabelNode start) {
         super(-1);

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java
new file mode 100644
index 0000000..27f6e09
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java
@@ -0,0 +1,157 @@
+/***
+ * 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 java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+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.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+
+/**
+ * A node that represents a type annotation on a local or resource variable.
+ * 
+ * @author Eric Bruneton
+ */
+public class LocalVariableAnnotationNode extends TypeAnnotationNode {
+
+    /**
+     * The fist instructions corresponding to the continuous ranges that make
+     * the scope of this local variable (inclusive). Must not be <tt>null</tt>.
+     */
+    public List<LabelNode> start;
+
+    /**
+     * The last instructions corresponding to the continuous ranges that make
+     * the scope of this local variable (exclusive). This list must have the
+     * same size as the 'start' list. Must not be <tt>null</tt>.
+     */
+    public List<LabelNode> end;
+
+    /**
+     * The local variable's index in each range. This list must have the same
+     * size as the 'start' list. Must not be <tt>null</tt>.
+     */
+    public List<Integer> index;
+
+    /**
+     * Constructs a new {@link LocalVariableAnnotationNode}. <i>Subclasses must
+     * not use this constructor</i>. Instead, they must use the
+     * {@link #LocalVariableAnnotationNode(int, TypePath, LabelNode[], LabelNode[], int[], 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 start
+     *            the fist instructions corresponding to the continuous ranges
+     *            that make the scope of this local variable (inclusive).
+     * @param end
+     *            the last instructions corresponding to the continuous ranges
+     *            that make the scope of this local variable (exclusive). This
+     *            array must have the same size as the 'start' array.
+     * @param index
+     *            the local variable's index in each range. This array must have
+     *            the same size as the 'start' array.
+     * @param desc
+     *            the class descriptor of the annotation class.
+     */
+    public LocalVariableAnnotationNode(int typeRef, TypePath typePath,
+            LabelNode[] start, LabelNode[] end, int[] index, String desc) {
+        this(Opcodes.ASM5, typeRef, typePath, start, end, index, desc);
+    }
+
+    /**
+     * Constructs a new {@link LocalVariableAnnotationNode}.
+     * 
+     * @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 start
+     *            the fist instructions corresponding to the continuous ranges
+     *            that make the scope of this local variable (inclusive).
+     * @param end
+     *            the last instructions corresponding to the continuous ranges
+     *            that make the scope of this local variable (exclusive). This
+     *            array must have the same size as the 'start' array.
+     * @param index
+     *            the local variable's index in each range. This array must have
+     *            the same size as the 'start' array.
+     * @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 LocalVariableAnnotationNode(int api, int typeRef, TypePath typePath,
+            LabelNode[] start, LabelNode[] end, int[] index, String desc) {
+        super(api, typeRef, typePath, desc);
+        this.start = new ArrayList<LabelNode>(start.length);
+        this.start.addAll(Arrays.asList(start));
+        this.end = new ArrayList<LabelNode>(end.length);
+        this.end.addAll(Arrays.asList(end));
+        this.index = new ArrayList<Integer>(index.length);
+        for (int i : index) {
+            this.index.add(i);
+        }
+    }
+
+    /**
+     * Makes the given visitor visit this type annotation.
+     * 
+     * @param mv
+     *            the visitor that must visit this annotation.
+     * @param visible
+     *            <tt>true</tt> if the annotation is visible at runtime.
+     */
+    public void accept(final MethodVisitor mv, boolean visible) {
+        Label[] start = new Label[this.start.size()];
+        Label[] end = new Label[this.end.size()];
+        int[] index = new int[this.index.size()];
+        for (int i = 0; i < start.length; ++i) {
+            start[i] = this.start.get(i).getLabel();
+            end[i] = this.end.get(i).getLabel();
+            index[i] = this.index.get(i);
+        }
+        accept(mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
+                index, desc, true));
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
index 8494414..775a6e8 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
@@ -33,7 +33,7 @@ import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
 
 /**
  * A node that represents a local variable declaration.
- *
+ * 
  * @author Eric Bruneton
  */
 public class LocalVariableNode {
@@ -72,25 +72,25 @@ public class LocalVariableNode {
 
     /**
      * Constructs a new {@link LocalVariableNode}.
-     *
-     * @param name the name of a local variable.
-     * @param desc the type descriptor of this local variable.
-     * @param signature the signature of this local variable. May be
-     *        <tt>null</tt>.
-     * @param start the first instruction corresponding to the scope of this
-     *        local variable (inclusive).
-     * @param end the last instruction corresponding to the scope of this local
-     *        variable (exclusive).
-     * @param index the local variable's index.
+     * 
+     * @param name
+     *            the name of a local variable.
+     * @param desc
+     *            the type descriptor of this local variable.
+     * @param signature
+     *            the signature of this local variable. May be <tt>null</tt>.
+     * @param start
+     *            the first instruction corresponding to the scope of this local
+     *            variable (inclusive).
+     * @param end
+     *            the last instruction corresponding to the scope of this local
+     *            variable (exclusive).
+     * @param index
+     *            the local variable's index.
      */
-    public LocalVariableNode(
-        final String name,
-        final String desc,
-        final String signature,
-        final LabelNode start,
-        final LabelNode end,
-        final int index)
-    {
+    public LocalVariableNode(final String name, final String desc,
+            final String signature, final LabelNode start, final LabelNode end,
+            final int index) {
         this.name = name;
         this.desc = desc;
         this.signature = signature;
@@ -101,15 +101,12 @@ public class LocalVariableNode {
 
     /**
      * Makes the given visitor visit this local variable declaration.
-     *
-     * @param mv a method visitor.
+     * 
+     * @param mv
+     *            a method visitor.
      */
     public void accept(final MethodVisitor mv) {
-        mv.visitLocalVariable(name,
-                desc,
-                signature,
-                start.getLabel(),
-                end.getLabel(),
-                index);
+        mv.visitLocalVariable(name, desc, signature, start.getLabel(),
+                end.getLabel(), index);
     }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java
index 5beca30..af635d7 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.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 LOOKUPSWITCH instruction.
- *
+ * 
  * @author Eric Bruneton
  */
 public class LookupSwitchInsnNode extends AbstractInsnNode {
@@ -63,21 +63,22 @@ public class LookupSwitchInsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link LookupSwitchInsnNode}.
-     *
-     * @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.
+     * 
+     * @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.
      */
-    public LookupSwitchInsnNode(
-        final LabelNode dflt,
-        final int[] keys,
-        final LabelNode[] labels)
-    {
+    public LookupSwitchInsnNode(final LabelNode dflt, final int[] keys,
+            final LabelNode[] labels) {
         super(Opcodes.LOOKUPSWITCH);
         this.dflt = dflt;
         this.keys = new ArrayList<Integer>(keys == null ? 0 : keys.length);
-        this.labels = new ArrayList<LabelNode>(labels == null ? 0 : labels.length);
+        this.labels = new ArrayList<LabelNode>(labels == null ? 0
+                : labels.length);
         if (keys != null) {
             for (int i = 0; i < keys.length; ++i) {
                 this.keys.add(new Integer(keys[i]));
@@ -104,6 +105,7 @@ public class LookupSwitchInsnNode extends AbstractInsnNode {
             labels[i] = this.labels.get(i).getLabel();
         }
         mv.visitLookupSwitchInsn(dflt.getLabel(), keys, labels);
+        acceptAnnotations(mv);
     }
 
     @Override
@@ -111,6 +113,6 @@ public class LookupSwitchInsnNode extends AbstractInsnNode {
         LookupSwitchInsnNode clone = new LookupSwitchInsnNode(clone(dflt,
                 labels), null, clone(this.labels, labels));
         clone.keys.addAll(keys);
-        return clone;
+        return clone.cloneAnnotations(this);
     }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
index f87234c..5d0c730 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
@@ -29,14 +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;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
 /**
  * A node that represents a method instruction. A method instruction is an
  * instruction that invokes a method.
- *
+ * 
  * @author Eric Bruneton
  */
 public class MethodInsnNode extends AbstractInsnNode {
@@ -58,33 +59,65 @@ public class MethodInsnNode extends AbstractInsnNode {
     public String desc;
 
     /**
+     * If the method's owner class if an interface.
+     */
+    public boolean itf;
+
+    /**
+     * Constructs a new {@link MethodInsnNode}.
+     * 
+     * @param opcode
+     *            the opcode of the type instruction to be constructed. This
+     *            opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+     *            INVOKEINTERFACE.
+     * @param owner
+     *            the internal name of the method's owner class (see
+     *            {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+     *            getInternalName}).
+     * @param name
+     *            the method's name.
+     * @param desc
+     *            the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+     */
+    @Deprecated
+    public MethodInsnNode(final int opcode, final String owner,
+            final String name, final String desc) {
+        this(opcode, owner, name, desc, opcode == Opcodes.INVOKEINTERFACE);
+    }
+
+    /**
      * Constructs a new {@link MethodInsnNode}.
-     *
-     * @param opcode the opcode of the type instruction to be constructed. This
-     *        opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
-     *        INVOKEINTERFACE.
-     * @param owner the internal name of the method's owner class (see
-     *        {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}).
-     * @param name the method's name.
-     * @param desc the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+     * 
+     * @param opcode
+     *            the opcode of the type instruction to be constructed. This
+     *            opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+     *            INVOKEINTERFACE.
+     * @param owner
+     *            the internal name of the method's owner class (see
+     *            {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+     *            getInternalName}).
+     * @param name
+     *            the method's name.
+     * @param desc
+     *            the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+     * @param itf
+     *            if the method's owner class is an interface.
      */
-    public MethodInsnNode(
-        final int opcode,
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    public MethodInsnNode(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
         super(opcode);
         this.owner = owner;
         this.name = name;
         this.desc = desc;
+        this.itf = itf;
     }
 
     /**
      * Sets the opcode of this instruction.
-     *
-     * @param opcode the new instruction opcode. This opcode must be
-     *        INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
+     * 
+     * @param opcode
+     *            the new instruction opcode. This opcode must be INVOKEVIRTUAL,
+     *            INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
      */
     public void setOpcode(final int opcode) {
         this.opcode = opcode;
@@ -97,11 +130,11 @@ public class MethodInsnNode extends AbstractInsnNode {
 
     @Override
     public void accept(final MethodVisitor mv) {
-        mv.visitMethodInsn(opcode, owner, name, desc);
+        mv.visitMethodInsn(opcode, owner, name, desc, itf);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new MethodInsnNode(opcode, owner, name, desc);
+        return new MethodInsnNode(opcode, owner, name, desc, itf);
     }
 }
\ No newline at end of file


[20/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
index fce84e9..5aa3aff 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
 
 /**
  * Information about the input and output stack map frames of a basic block.
- *
+ * 
  * @author Eric Bruneton
  */
 final class Frame {
@@ -46,14 +46,14 @@ final class Frame {
      * of the first basic block (which is computed from the method descriptor),
      * and by using the previously computed output frames to compute the input
      * state of the other blocks.
-     *
+     * 
      * All output and input frames are stored as arrays of integers. Reference
      * and array types are represented by an index into a type table (which is
      * not the same as the constant pool of the class, in order to avoid adding
      * unnecessary constants in the pool - not all computed frames will end up
      * being stored in the stack map table). This allows very fast type
      * comparisons.
-     *
+     * 
      * Output stack map frames are computed relatively to the input frame of the
      * basic block, which is not yet known when output frames are computed. It
      * is therefore necessary to be able to represent abstract types such as
@@ -61,7 +61,7 @@ final class Frame {
      * position x from the top of the input frame stack" or even "the type at
      * position x in the input frame, with y more (or less) array dimensions".
      * This explains the rather complicated type format used in output frames.
-     *
+     * 
      * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a
      * signed number of array dimensions (from -8 to 7). KIND is either BASE,
      * LOCAL or STACK. BASE is used for types that are not relative to the input
@@ -70,23 +70,23 @@ final class Frame {
      * stack types. VALUE depends on KIND. For LOCAL types, it is an index in
      * the input local variable types. For STACK types, it is a position
      * relatively to the top of input frame stack. For BASE types, it is either
-     * one of the constants defined in FrameVisitor, or for OBJECT and
-     * UNINITIALIZED types, a tag and an index in the type table.
-     *
+     * one of the constants defined below, or for OBJECT and UNINITIALIZED
+     * types, a tag and an index in the type table.
+     * 
      * Output frames can contain types of any kind and with a positive or
      * negative dimension (and even unassigned types, represented by 0 - which
      * does not correspond to any valid type value). Input frames can only
      * contain BASE types of positive or null dimension. In all cases the type
      * table contains only internal type names (array type descriptors are
      * forbidden - dimensions must be represented through the DIM field).
-     *
-     * The LONG and DOUBLE types are always represented by using two slots (LONG +
-     * TOP or DOUBLE + TOP), for local variable types as well as in the operand
-     * stack. This is necessary to be able to simulate DUPx_y instructions,
-     * whose effect would be dependent on the actual type values if types were
-     * always represented by a single slot in the stack (and this is not
-     * possible, since actual type values are not always known - cf LOCAL and
-     * STACK type kinds).
+     * 
+     * The LONG and DOUBLE types are always represented by using two slots (LONG
+     * + TOP or DOUBLE + TOP), for local variable types as well as in the
+     * operand stack. This is necessary to be able to simulate DUPx_y
+     * instructions, whose effect would be dependent on the actual type values
+     * if types were always represented by a single slot in the stack (and this
+     * is not possible, since actual type values are not always known - cf LOCAL
+     * and STACK type kinds).
      */
 
     /**
@@ -107,7 +107,7 @@ final class Frame {
 
     /**
      * Mask to get the kind of a frame type.
-     *
+     * 
      * @see #BASE
      * @see #LOCAL
      * @see #STACK
@@ -117,9 +117,9 @@ final class Frame {
     /**
      * Flag used for LOCAL and STACK types. Indicates that if this type happens
      * to be a long or double type (during the computations of input frames),
-     * then it must be set to TOP because the second word of this value has
-     * been reused to store other data in the basic block. Hence the first word
-     * no longer stores a valid long or double value.
+     * then it must be set to TOP because the second word of this value has been
+     * reused to store other data in the basic block. Hence the first word no
+     * longer stores a valid long or double value.
      */
     static final int TOP_IF_LONG_OR_DOUBLE = 0x800000;
 
@@ -489,10 +489,10 @@ final class Frame {
     /**
      * Relative size of the output stack. The exact semantics of this field
      * depends on the algorithm that is used.
-     *
+     * 
      * When only the maximum stack size is computed, this field is the size of
      * the output stack relatively to the top of the input stack.
-     *
+     * 
      * When the stack map frames are completely computed, this field is the
      * actual number of types in {@link #outputStack}.
      */
@@ -500,7 +500,7 @@ final class Frame {
 
     /**
      * Number of types that are initialized in the basic block.
-     *
+     * 
      * @see #initializations
      */
     private int initializationCount;
@@ -522,8 +522,9 @@ final class Frame {
 
     /**
      * Returns the output frame local variable type at the given index.
-     *
-     * @param local the index of the local that must be returned.
+     * 
+     * @param local
+     *            the index of the local that must be returned.
      * @return the output frame local variable type at the given index.
      */
     private int get(final int local) {
@@ -544,9 +545,11 @@ final class Frame {
 
     /**
      * Sets the output frame local variable type at the given index.
-     *
-     * @param local the index of the local that must be set.
-     * @param type the value of the local that must be set.
+     * 
+     * @param local
+     *            the index of the local that must be set.
+     * @param type
+     *            the value of the local that must be set.
      */
     private void set(final int local, final int type) {
         // creates and/or resizes the output local variables array if necessary
@@ -565,8 +568,9 @@ final class Frame {
 
     /**
      * Pushes a new type onto the output frame stack.
-     *
-     * @param type the type that must be pushed.
+     * 
+     * @param type
+     *            the type that must be pushed.
      */
     private void push(final int type) {
         // creates and/or resizes the output stack array if necessary
@@ -590,11 +594,13 @@ final class Frame {
 
     /**
      * Pushes a new type onto the output frame stack.
-     *
-     * @param cw the ClassWriter to which this label belongs.
-     * @param desc the descriptor of the type to be pushed. Can also be a method
-     *        descriptor (in this case this method pushes its return type onto
-     *        the output frame stack).
+     * 
+     * @param cw
+     *            the ClassWriter to which this label belongs.
+     * @param desc
+     *            the descriptor of the type to be pushed. Can also be a method
+     *            descriptor (in this case this method pushes its return type
+     *            onto the output frame stack).
      */
     private void push(final ClassWriter cw, final String desc) {
         int type = type(cw, desc);
@@ -608,79 +614,81 @@ final class Frame {
 
     /**
      * Returns the int encoding of the given type.
-     *
-     * @param cw the ClassWriter to which this label belongs.
-     * @param desc a type descriptor.
+     * 
+     * @param cw
+     *            the ClassWriter to which this label belongs.
+     * @param desc
+     *            a type descriptor.
      * @return the int encoding of the given type.
      */
     private static int type(final ClassWriter cw, final String desc) {
         String t;
         int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
         switch (desc.charAt(index)) {
-            case 'V':
-                return 0;
+        case 'V':
+            return 0;
+        case 'Z':
+        case 'C':
+        case 'B':
+        case 'S':
+        case 'I':
+            return INTEGER;
+        case 'F':
+            return FLOAT;
+        case 'J':
+            return LONG;
+        case 'D':
+            return DOUBLE;
+        case 'L':
+            // stores the internal name, not the descriptor!
+            t = desc.substring(index + 1, desc.length() - 1);
+            return OBJECT | cw.addType(t);
+            // case '[':
+        default:
+            // extracts the dimensions and the element type
+            int data;
+            int dims = index + 1;
+            while (desc.charAt(dims) == '[') {
+                ++dims;
+            }
+            switch (desc.charAt(dims)) {
             case 'Z':
+                data = BOOLEAN;
+                break;
             case 'C':
+                data = CHAR;
+                break;
             case 'B':
+                data = BYTE;
+                break;
             case 'S':
+                data = SHORT;
+                break;
             case 'I':
-                return INTEGER;
+                data = INTEGER;
+                break;
             case 'F':
-                return FLOAT;
+                data = FLOAT;
+                break;
             case 'J':
-                return LONG;
+                data = LONG;
+                break;
             case 'D':
-                return DOUBLE;
-            case 'L':
-                // stores the internal name, not the descriptor!
-                t = desc.substring(index + 1, desc.length() - 1);
-                return OBJECT | cw.addType(t);
-                // case '[':
+                data = DOUBLE;
+                break;
+            // case 'L':
             default:
-                // extracts the dimensions and the element type
-                int data;
-                int dims = index + 1;
-                while (desc.charAt(dims) == '[') {
-                    ++dims;
-                }
-                switch (desc.charAt(dims)) {
-                    case 'Z':
-                        data = BOOLEAN;
-                        break;
-                    case 'C':
-                        data = CHAR;
-                        break;
-                    case 'B':
-                        data = BYTE;
-                        break;
-                    case 'S':
-                        data = SHORT;
-                        break;
-                    case 'I':
-                        data = INTEGER;
-                        break;
-                    case 'F':
-                        data = FLOAT;
-                        break;
-                    case 'J':
-                        data = LONG;
-                        break;
-                    case 'D':
-                        data = DOUBLE;
-                        break;
-                    // case 'L':
-                    default:
-                        // stores the internal name, not the descriptor
-                        t = desc.substring(dims + 1, desc.length() - 1);
-                        data = OBJECT | cw.addType(t);
-                }
-                return (dims - index) << 28 | data;
+                // stores the internal name, not the descriptor
+                t = desc.substring(dims + 1, desc.length() - 1);
+                data = OBJECT | cw.addType(t);
+            }
+            return (dims - index) << 28 | data;
         }
     }
 
     /**
      * Pops a type from the output frame stack and returns its value.
-     *
+     * 
      * @return the type that has been popped from the output frame stack.
      */
     private int pop() {
@@ -694,8 +702,9 @@ final class Frame {
 
     /**
      * Pops the given number of types from the output frame stack.
-     *
-     * @param elements the number of types that must be popped.
+     * 
+     * @param elements
+     *            the number of types that must be popped.
      */
     private void pop(final int elements) {
         if (outputStackTop >= elements) {
@@ -711,10 +720,11 @@ final class Frame {
 
     /**
      * Pops a type from the output frame stack.
-     *
-     * @param desc the descriptor of the type to be popped. Can also be a method
-     *        descriptor (in this case this method pops the types corresponding
-     *        to the method arguments).
+     * 
+     * @param desc
+     *            the descriptor of the type to be popped. Can also be a method
+     *            descriptor (in this case this method pops the types
+     *            corresponding to the method arguments).
      */
     private void pop(final String desc) {
         char c = desc.charAt(0);
@@ -730,8 +740,9 @@ final class Frame {
     /**
      * Adds a new type to the list of types on which a constructor is invoked in
      * the basic block.
-     *
-     * @param var a type on a which a constructor is invoked.
+     * 
+     * @param var
+     *            a type on a which a constructor is invoked.
      */
     private void init(final int var) {
         // creates and/or resizes the initializations array if necessary
@@ -751,9 +762,11 @@ final class Frame {
     /**
      * Replaces the given type with the appropriate type if it is one of the
      * types on which a constructor is invoked in the basic block.
-     *
-     * @param cw the ClassWriter to which this label belongs.
-     * @param t a type
+     * 
+     * @param cw
+     *            the ClassWriter to which this label belongs.
+     * @param t
+     *            a type
      * @return t or, if t is one of the types on which a constructor is invoked
      *         in the basic block, the type corresponding to this constructor.
      */
@@ -786,18 +799,18 @@ final class Frame {
     /**
      * Initializes the input frame of the first basic block from the method
      * descriptor.
-     *
-     * @param cw the ClassWriter to which this label belongs.
-     * @param access the access flags of the method to which this label belongs.
-     * @param args the formal parameter types of this method.
-     * @param maxLocals the maximum number of local variables of this method.
+     * 
+     * @param cw
+     *            the ClassWriter to which this label belongs.
+     * @param access
+     *            the access flags of the method to which this label belongs.
+     * @param args
+     *            the formal parameter types of this method.
+     * @param maxLocals
+     *            the maximum number of local variables of this method.
      */
-    void initInputFrame(
-        final ClassWriter cw,
-        final int access,
-        final Type[] args,
-        final int maxLocals)
-    {
+    void initInputFrame(final ClassWriter cw, final int access,
+            final Type[] args, final int maxLocals) {
         inputLocals = new int[maxLocals];
         inputStack = new int[0];
         int i = 0;
@@ -822,436 +835,436 @@ final class Frame {
 
     /**
      * Simulates the action of the given instruction on the output stack frame.
-     *
-     * @param opcode the opcode of the instruction.
-     * @param arg the operand of the instruction, if any.
-     * @param cw the class writer to which this label belongs.
-     * @param item the operand of the instructions, if any.
+     * 
+     * @param opcode
+     *            the opcode of the instruction.
+     * @param arg
+     *            the operand of the instruction, if any.
+     * @param cw
+     *            the class writer to which this label belongs.
+     * @param item
+     *            the operand of the instructions, if any.
      */
-    void execute(
-        final int opcode,
-        final int arg,
-        final ClassWriter cw,
-        final Item item)
-    {
+    void execute(final int opcode, final int arg, final ClassWriter cw,
+            final Item item) {
         int t1, t2, t3, t4;
         switch (opcode) {
-            case Opcodes.NOP:
-            case Opcodes.INEG:
-            case Opcodes.LNEG:
-            case Opcodes.FNEG:
-            case Opcodes.DNEG:
-            case Opcodes.I2B:
-            case Opcodes.I2C:
-            case Opcodes.I2S:
-            case Opcodes.GOTO:
-            case Opcodes.RETURN:
-                break;
-            case Opcodes.ACONST_NULL:
-                push(NULL);
-                break;
-            case Opcodes.ICONST_M1:
-            case Opcodes.ICONST_0:
-            case Opcodes.ICONST_1:
-            case Opcodes.ICONST_2:
-            case Opcodes.ICONST_3:
-            case Opcodes.ICONST_4:
-            case Opcodes.ICONST_5:
-            case Opcodes.BIPUSH:
-            case Opcodes.SIPUSH:
-            case Opcodes.ILOAD:
+        case Opcodes.NOP:
+        case Opcodes.INEG:
+        case Opcodes.LNEG:
+        case Opcodes.FNEG:
+        case Opcodes.DNEG:
+        case Opcodes.I2B:
+        case Opcodes.I2C:
+        case Opcodes.I2S:
+        case Opcodes.GOTO:
+        case Opcodes.RETURN:
+            break;
+        case Opcodes.ACONST_NULL:
+            push(NULL);
+            break;
+        case Opcodes.ICONST_M1:
+        case Opcodes.ICONST_0:
+        case Opcodes.ICONST_1:
+        case Opcodes.ICONST_2:
+        case Opcodes.ICONST_3:
+        case Opcodes.ICONST_4:
+        case Opcodes.ICONST_5:
+        case Opcodes.BIPUSH:
+        case Opcodes.SIPUSH:
+        case Opcodes.ILOAD:
+            push(INTEGER);
+            break;
+        case Opcodes.LCONST_0:
+        case Opcodes.LCONST_1:
+        case Opcodes.LLOAD:
+            push(LONG);
+            push(TOP);
+            break;
+        case Opcodes.FCONST_0:
+        case Opcodes.FCONST_1:
+        case Opcodes.FCONST_2:
+        case Opcodes.FLOAD:
+            push(FLOAT);
+            break;
+        case Opcodes.DCONST_0:
+        case Opcodes.DCONST_1:
+        case Opcodes.DLOAD:
+            push(DOUBLE);
+            push(TOP);
+            break;
+        case Opcodes.LDC:
+            switch (item.type) {
+            case ClassWriter.INT:
                 push(INTEGER);
                 break;
-            case Opcodes.LCONST_0:
-            case Opcodes.LCONST_1:
-            case Opcodes.LLOAD:
+            case ClassWriter.LONG:
                 push(LONG);
                 push(TOP);
                 break;
-            case Opcodes.FCONST_0:
-            case Opcodes.FCONST_1:
-            case Opcodes.FCONST_2:
-            case Opcodes.FLOAD:
+            case ClassWriter.FLOAT:
                 push(FLOAT);
                 break;
-            case Opcodes.DCONST_0:
-            case Opcodes.DCONST_1:
-            case Opcodes.DLOAD:
+            case ClassWriter.DOUBLE:
                 push(DOUBLE);
                 push(TOP);
                 break;
-            case Opcodes.LDC:
-                switch (item.type) {
-                    case ClassWriter.INT:
-                        push(INTEGER);
-                        break;
-                    case ClassWriter.LONG:
-                        push(LONG);
-                        push(TOP);
-                        break;
-                    case ClassWriter.FLOAT:
-                        push(FLOAT);
-                        break;
-                    case ClassWriter.DOUBLE:
-                        push(DOUBLE);
-                        push(TOP);
-                        break;
-                    case ClassWriter.CLASS:
-                        push(OBJECT | cw.addType("java/lang/Class"));
-                        break;
-                    case ClassWriter.STR:
-                        push(OBJECT | cw.addType("java/lang/String"));
-                        break;
-                    case ClassWriter.MTYPE:
-                        push(OBJECT | cw.addType("java/lang/invoke/MethodType"));
-                        break;
-                    // case ClassWriter.HANDLE_BASE + [1..9]:
-                    default:
-                        push(OBJECT | cw.addType("java/lang/invoke/MethodHandle"));
-                }
-                break;
-            case Opcodes.ALOAD:
-                push(get(arg));
-                break;
-            case Opcodes.IALOAD:
-            case Opcodes.BALOAD:
-            case Opcodes.CALOAD:
-            case Opcodes.SALOAD:
-                pop(2);
-                push(INTEGER);
-                break;
-            case Opcodes.LALOAD:
-            case Opcodes.D2L:
-                pop(2);
-                push(LONG);
-                push(TOP);
-                break;
-            case Opcodes.FALOAD:
-                pop(2);
-                push(FLOAT);
+            case ClassWriter.CLASS:
+                push(OBJECT | cw.addType("java/lang/Class"));
                 break;
-            case Opcodes.DALOAD:
-            case Opcodes.L2D:
-                pop(2);
-                push(DOUBLE);
-                push(TOP);
+            case ClassWriter.STR:
+                push(OBJECT | cw.addType("java/lang/String"));
                 break;
-            case Opcodes.AALOAD:
-                pop(1);
-                t1 = pop();
-                push(ELEMENT_OF + t1);
+            case ClassWriter.MTYPE:
+                push(OBJECT | cw.addType("java/lang/invoke/MethodType"));
                 break;
-            case Opcodes.ISTORE:
-            case Opcodes.FSTORE:
-            case Opcodes.ASTORE:
-                t1 = pop();
-                set(arg, t1);
-                if (arg > 0) {
-                    t2 = get(arg - 1);
-                    // if t2 is of kind STACK or LOCAL we cannot know its size!
-                    if (t2 == LONG || t2 == DOUBLE) {
-                        set(arg - 1, TOP);
-                    } else if ((t2 & KIND) != BASE) {
-                        set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
-                    }
+            // case ClassWriter.HANDLE_BASE + [1..9]:
+            default:
+                push(OBJECT | cw.addType("java/lang/invoke/MethodHandle"));
+            }
+            break;
+        case Opcodes.ALOAD:
+            push(get(arg));
+            break;
+        case Opcodes.IALOAD:
+        case Opcodes.BALOAD:
+        case Opcodes.CALOAD:
+        case Opcodes.SALOAD:
+            pop(2);
+            push(INTEGER);
+            break;
+        case Opcodes.LALOAD:
+        case Opcodes.D2L:
+            pop(2);
+            push(LONG);
+            push(TOP);
+            break;
+        case Opcodes.FALOAD:
+            pop(2);
+            push(FLOAT);
+            break;
+        case Opcodes.DALOAD:
+        case Opcodes.L2D:
+            pop(2);
+            push(DOUBLE);
+            push(TOP);
+            break;
+        case Opcodes.AALOAD:
+            pop(1);
+            t1 = pop();
+            push(ELEMENT_OF + t1);
+            break;
+        case Opcodes.ISTORE:
+        case Opcodes.FSTORE:
+        case Opcodes.ASTORE:
+            t1 = pop();
+            set(arg, t1);
+            if (arg > 0) {
+                t2 = get(arg - 1);
+                // if t2 is of kind STACK or LOCAL we cannot know its size!
+                if (t2 == LONG || t2 == DOUBLE) {
+                    set(arg - 1, TOP);
+                } else if ((t2 & KIND) != BASE) {
+                    set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
                 }
-                break;
-            case Opcodes.LSTORE:
-            case Opcodes.DSTORE:
-                pop(1);
-                t1 = pop();
-                set(arg, t1);
-                set(arg + 1, TOP);
-                if (arg > 0) {
-                    t2 = get(arg - 1);
-                    // if t2 is of kind STACK or LOCAL we cannot know its size!
-                    if (t2 == LONG || t2 == DOUBLE) {
-                        set(arg - 1, TOP);
-                    } else if ((t2 & KIND) != BASE) {
-                        set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
-                    }
+            }
+            break;
+        case Opcodes.LSTORE:
+        case Opcodes.DSTORE:
+            pop(1);
+            t1 = pop();
+            set(arg, t1);
+            set(arg + 1, TOP);
+            if (arg > 0) {
+                t2 = get(arg - 1);
+                // if t2 is of kind STACK or LOCAL we cannot know its size!
+                if (t2 == LONG || t2 == DOUBLE) {
+                    set(arg - 1, TOP);
+                } else if ((t2 & KIND) != BASE) {
+                    set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
                 }
-                break;
-            case Opcodes.IASTORE:
-            case Opcodes.BASTORE:
-            case Opcodes.CASTORE:
-            case Opcodes.SASTORE:
-            case Opcodes.FASTORE:
-            case Opcodes.AASTORE:
-                pop(3);
-                break;
-            case Opcodes.LASTORE:
-            case Opcodes.DASTORE:
-                pop(4);
-                break;
-            case Opcodes.POP:
-            case Opcodes.IFEQ:
-            case Opcodes.IFNE:
-            case Opcodes.IFLT:
-            case Opcodes.IFGE:
-            case Opcodes.IFGT:
-            case Opcodes.IFLE:
-            case Opcodes.IRETURN:
-            case Opcodes.FRETURN:
-            case Opcodes.ARETURN:
-            case Opcodes.TABLESWITCH:
-            case Opcodes.LOOKUPSWITCH:
-            case Opcodes.ATHROW:
-            case Opcodes.MONITORENTER:
-            case Opcodes.MONITOREXIT:
-            case Opcodes.IFNULL:
-            case Opcodes.IFNONNULL:
-                pop(1);
-                break;
-            case Opcodes.POP2:
-            case Opcodes.IF_ICMPEQ:
-            case Opcodes.IF_ICMPNE:
-            case Opcodes.IF_ICMPLT:
-            case Opcodes.IF_ICMPGE:
-            case Opcodes.IF_ICMPGT:
-            case Opcodes.IF_ICMPLE:
-            case Opcodes.IF_ACMPEQ:
-            case Opcodes.IF_ACMPNE:
-            case Opcodes.LRETURN:
-            case Opcodes.DRETURN:
-                pop(2);
-                break;
-            case Opcodes.DUP:
-                t1 = pop();
-                push(t1);
-                push(t1);
-                break;
-            case Opcodes.DUP_X1:
-                t1 = pop();
-                t2 = pop();
-                push(t1);
-                push(t2);
-                push(t1);
-                break;
-            case Opcodes.DUP_X2:
-                t1 = pop();
-                t2 = pop();
-                t3 = pop();
-                push(t1);
-                push(t3);
-                push(t2);
-                push(t1);
-                break;
-            case Opcodes.DUP2:
-                t1 = pop();
-                t2 = pop();
-                push(t2);
-                push(t1);
-                push(t2);
-                push(t1);
-                break;
-            case Opcodes.DUP2_X1:
-                t1 = pop();
-                t2 = pop();
-                t3 = pop();
-                push(t2);
-                push(t1);
-                push(t3);
-                push(t2);
-                push(t1);
-                break;
-            case Opcodes.DUP2_X2:
-                t1 = pop();
-                t2 = pop();
-                t3 = pop();
-                t4 = pop();
-                push(t2);
-                push(t1);
-                push(t4);
-                push(t3);
-                push(t2);
-                push(t1);
-                break;
-            case Opcodes.SWAP:
+            }
+            break;
+        case Opcodes.IASTORE:
+        case Opcodes.BASTORE:
+        case Opcodes.CASTORE:
+        case Opcodes.SASTORE:
+        case Opcodes.FASTORE:
+        case Opcodes.AASTORE:
+            pop(3);
+            break;
+        case Opcodes.LASTORE:
+        case Opcodes.DASTORE:
+            pop(4);
+            break;
+        case Opcodes.POP:
+        case Opcodes.IFEQ:
+        case Opcodes.IFNE:
+        case Opcodes.IFLT:
+        case Opcodes.IFGE:
+        case Opcodes.IFGT:
+        case Opcodes.IFLE:
+        case Opcodes.IRETURN:
+        case Opcodes.FRETURN:
+        case Opcodes.ARETURN:
+        case Opcodes.TABLESWITCH:
+        case Opcodes.LOOKUPSWITCH:
+        case Opcodes.ATHROW:
+        case Opcodes.MONITORENTER:
+        case Opcodes.MONITOREXIT:
+        case Opcodes.IFNULL:
+        case Opcodes.IFNONNULL:
+            pop(1);
+            break;
+        case Opcodes.POP2:
+        case Opcodes.IF_ICMPEQ:
+        case Opcodes.IF_ICMPNE:
+        case Opcodes.IF_ICMPLT:
+        case Opcodes.IF_ICMPGE:
+        case Opcodes.IF_ICMPGT:
+        case Opcodes.IF_ICMPLE:
+        case Opcodes.IF_ACMPEQ:
+        case Opcodes.IF_ACMPNE:
+        case Opcodes.LRETURN:
+        case Opcodes.DRETURN:
+            pop(2);
+            break;
+        case Opcodes.DUP:
+            t1 = pop();
+            push(t1);
+            push(t1);
+            break;
+        case Opcodes.DUP_X1:
+            t1 = pop();
+            t2 = pop();
+            push(t1);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.DUP_X2:
+            t1 = pop();
+            t2 = pop();
+            t3 = pop();
+            push(t1);
+            push(t3);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.DUP2:
+            t1 = pop();
+            t2 = pop();
+            push(t2);
+            push(t1);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.DUP2_X1:
+            t1 = pop();
+            t2 = pop();
+            t3 = pop();
+            push(t2);
+            push(t1);
+            push(t3);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.DUP2_X2:
+            t1 = pop();
+            t2 = pop();
+            t3 = pop();
+            t4 = pop();
+            push(t2);
+            push(t1);
+            push(t4);
+            push(t3);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.SWAP:
+            t1 = pop();
+            t2 = pop();
+            push(t1);
+            push(t2);
+            break;
+        case Opcodes.IADD:
+        case Opcodes.ISUB:
+        case Opcodes.IMUL:
+        case Opcodes.IDIV:
+        case Opcodes.IREM:
+        case Opcodes.IAND:
+        case Opcodes.IOR:
+        case Opcodes.IXOR:
+        case Opcodes.ISHL:
+        case Opcodes.ISHR:
+        case Opcodes.IUSHR:
+        case Opcodes.L2I:
+        case Opcodes.D2I:
+        case Opcodes.FCMPL:
+        case Opcodes.FCMPG:
+            pop(2);
+            push(INTEGER);
+            break;
+        case Opcodes.LADD:
+        case Opcodes.LSUB:
+        case Opcodes.LMUL:
+        case Opcodes.LDIV:
+        case Opcodes.LREM:
+        case Opcodes.LAND:
+        case Opcodes.LOR:
+        case Opcodes.LXOR:
+            pop(4);
+            push(LONG);
+            push(TOP);
+            break;
+        case Opcodes.FADD:
+        case Opcodes.FSUB:
+        case Opcodes.FMUL:
+        case Opcodes.FDIV:
+        case Opcodes.FREM:
+        case Opcodes.L2F:
+        case Opcodes.D2F:
+            pop(2);
+            push(FLOAT);
+            break;
+        case Opcodes.DADD:
+        case Opcodes.DSUB:
+        case Opcodes.DMUL:
+        case Opcodes.DDIV:
+        case Opcodes.DREM:
+            pop(4);
+            push(DOUBLE);
+            push(TOP);
+            break;
+        case Opcodes.LSHL:
+        case Opcodes.LSHR:
+        case Opcodes.LUSHR:
+            pop(3);
+            push(LONG);
+            push(TOP);
+            break;
+        case Opcodes.IINC:
+            set(arg, INTEGER);
+            break;
+        case Opcodes.I2L:
+        case Opcodes.F2L:
+            pop(1);
+            push(LONG);
+            push(TOP);
+            break;
+        case Opcodes.I2F:
+            pop(1);
+            push(FLOAT);
+            break;
+        case Opcodes.I2D:
+        case Opcodes.F2D:
+            pop(1);
+            push(DOUBLE);
+            push(TOP);
+            break;
+        case Opcodes.F2I:
+        case Opcodes.ARRAYLENGTH:
+        case Opcodes.INSTANCEOF:
+            pop(1);
+            push(INTEGER);
+            break;
+        case Opcodes.LCMP:
+        case Opcodes.DCMPL:
+        case Opcodes.DCMPG:
+            pop(4);
+            push(INTEGER);
+            break;
+        case Opcodes.JSR:
+        case Opcodes.RET:
+            throw new RuntimeException(
+                    "JSR/RET are not supported with computeFrames option");
+        case Opcodes.GETSTATIC:
+            push(cw, item.strVal3);
+            break;
+        case Opcodes.PUTSTATIC:
+            pop(item.strVal3);
+            break;
+        case Opcodes.GETFIELD:
+            pop(1);
+            push(cw, item.strVal3);
+            break;
+        case Opcodes.PUTFIELD:
+            pop(item.strVal3);
+            pop();
+            break;
+        case Opcodes.INVOKEVIRTUAL:
+        case Opcodes.INVOKESPECIAL:
+        case Opcodes.INVOKESTATIC:
+        case Opcodes.INVOKEINTERFACE:
+            pop(item.strVal3);
+            if (opcode != Opcodes.INVOKESTATIC) {
                 t1 = pop();
-                t2 = pop();
-                push(t1);
-                push(t2);
-                break;
-            case Opcodes.IADD:
-            case Opcodes.ISUB:
-            case Opcodes.IMUL:
-            case Opcodes.IDIV:
-            case Opcodes.IREM:
-            case Opcodes.IAND:
-            case Opcodes.IOR:
-            case Opcodes.IXOR:
-            case Opcodes.ISHL:
-            case Opcodes.ISHR:
-            case Opcodes.IUSHR:
-            case Opcodes.L2I:
-            case Opcodes.D2I:
-            case Opcodes.FCMPL:
-            case Opcodes.FCMPG:
-                pop(2);
-                push(INTEGER);
-                break;
-            case Opcodes.LADD:
-            case Opcodes.LSUB:
-            case Opcodes.LMUL:
-            case Opcodes.LDIV:
-            case Opcodes.LREM:
-            case Opcodes.LAND:
-            case Opcodes.LOR:
-            case Opcodes.LXOR:
-                pop(4);
-                push(LONG);
-                push(TOP);
-                break;
-            case Opcodes.FADD:
-            case Opcodes.FSUB:
-            case Opcodes.FMUL:
-            case Opcodes.FDIV:
-            case Opcodes.FREM:
-            case Opcodes.L2F:
-            case Opcodes.D2F:
-                pop(2);
-                push(FLOAT);
-                break;
-            case Opcodes.DADD:
-            case Opcodes.DSUB:
-            case Opcodes.DMUL:
-            case Opcodes.DDIV:
-            case Opcodes.DREM:
-                pop(4);
-                push(DOUBLE);
-                push(TOP);
-                break;
-            case Opcodes.LSHL:
-            case Opcodes.LSHR:
-            case Opcodes.LUSHR:
-                pop(3);
-                push(LONG);
-                push(TOP);
-                break;
-            case Opcodes.IINC:
-                set(arg, INTEGER);
-                break;
-            case Opcodes.I2L:
-            case Opcodes.F2L:
-                pop(1);
-                push(LONG);
-                push(TOP);
-                break;
-            case Opcodes.I2F:
-                pop(1);
-                push(FLOAT);
-                break;
-            case Opcodes.I2D:
-            case Opcodes.F2D:
-                pop(1);
-                push(DOUBLE);
-                push(TOP);
-                break;
-            case Opcodes.F2I:
-            case Opcodes.ARRAYLENGTH:
-            case Opcodes.INSTANCEOF:
-                pop(1);
-                push(INTEGER);
-                break;
-            case Opcodes.LCMP:
-            case Opcodes.DCMPL:
-            case Opcodes.DCMPG:
-                pop(4);
-                push(INTEGER);
-                break;
-            case Opcodes.JSR:
-            case Opcodes.RET:
-                throw new RuntimeException("JSR/RET are not supported with computeFrames option");
-            case Opcodes.GETSTATIC:
-                push(cw, item.strVal3);
-                break;
-            case Opcodes.PUTSTATIC:
-                pop(item.strVal3);
-                break;
-            case Opcodes.GETFIELD:
-                pop(1);
-                push(cw, item.strVal3);
-                break;
-            case Opcodes.PUTFIELD:
-                pop(item.strVal3);
-                pop();
-                break;
-            case Opcodes.INVOKEVIRTUAL:
-            case Opcodes.INVOKESPECIAL:
-            case Opcodes.INVOKESTATIC:
-            case Opcodes.INVOKEINTERFACE:
-                pop(item.strVal3);
-                if (opcode != Opcodes.INVOKESTATIC) {
-                    t1 = pop();
-                    if (opcode == Opcodes.INVOKESPECIAL
-                            && item.strVal2.charAt(0) == '<')
-                    {
-                        init(t1);
-                    }
+                if (opcode == Opcodes.INVOKESPECIAL
+                        && item.strVal2.charAt(0) == '<') {
+                    init(t1);
                 }
-                push(cw, item.strVal3);
+            }
+            push(cw, item.strVal3);
+            break;
+        case Opcodes.INVOKEDYNAMIC:
+            pop(item.strVal2);
+            push(cw, item.strVal2);
+            break;
+        case Opcodes.NEW:
+            push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
+            break;
+        case Opcodes.NEWARRAY:
+            pop();
+            switch (arg) {
+            case Opcodes.T_BOOLEAN:
+                push(ARRAY_OF | BOOLEAN);
                 break;
-            case Opcodes.INVOKEDYNAMIC:
-                pop(item.strVal2);
-                push(cw, item.strVal2);
+            case Opcodes.T_CHAR:
+                push(ARRAY_OF | CHAR);
                 break;
-            case Opcodes.NEW:
-                push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
+            case Opcodes.T_BYTE:
+                push(ARRAY_OF | BYTE);
                 break;
-            case Opcodes.NEWARRAY:
-                pop();
-                switch (arg) {
-                    case Opcodes.T_BOOLEAN:
-                        push(ARRAY_OF | BOOLEAN);
-                        break;
-                    case Opcodes.T_CHAR:
-                        push(ARRAY_OF | CHAR);
-                        break;
-                    case Opcodes.T_BYTE:
-                        push(ARRAY_OF | BYTE);
-                        break;
-                    case Opcodes.T_SHORT:
-                        push(ARRAY_OF | SHORT);
-                        break;
-                    case Opcodes.T_INT:
-                        push(ARRAY_OF | INTEGER);
-                        break;
-                    case Opcodes.T_FLOAT:
-                        push(ARRAY_OF | FLOAT);
-                        break;
-                    case Opcodes.T_DOUBLE:
-                        push(ARRAY_OF | DOUBLE);
-                        break;
-                    // case Opcodes.T_LONG:
-                    default:
-                        push(ARRAY_OF | LONG);
-                        break;
-                }
+            case Opcodes.T_SHORT:
+                push(ARRAY_OF | SHORT);
                 break;
-            case Opcodes.ANEWARRAY:
-                String s = item.strVal1;
-                pop();
-                if (s.charAt(0) == '[') {
-                    push(cw, '[' + s);
-                } else {
-                    push(ARRAY_OF | OBJECT | cw.addType(s));
-                }
+            case Opcodes.T_INT:
+                push(ARRAY_OF | INTEGER);
                 break;
-            case Opcodes.CHECKCAST:
-                s = item.strVal1;
-                pop();
-                if (s.charAt(0) == '[') {
-                    push(cw, s);
-                } else {
-                    push(OBJECT | cw.addType(s));
-                }
+            case Opcodes.T_FLOAT:
+                push(ARRAY_OF | FLOAT);
+                break;
+            case Opcodes.T_DOUBLE:
+                push(ARRAY_OF | DOUBLE);
                 break;
-            // case Opcodes.MULTIANEWARRAY:
+            // case Opcodes.T_LONG:
             default:
-                pop(arg);
-                push(cw, item.strVal1);
+                push(ARRAY_OF | LONG);
                 break;
+            }
+            break;
+        case Opcodes.ANEWARRAY:
+            String s = item.strVal1;
+            pop();
+            if (s.charAt(0) == '[') {
+                push(cw, '[' + s);
+            } else {
+                push(ARRAY_OF | OBJECT | cw.addType(s));
+            }
+            break;
+        case Opcodes.CHECKCAST:
+            s = item.strVal1;
+            pop();
+            if (s.charAt(0) == '[') {
+                push(cw, s);
+            } else {
+                push(OBJECT | cw.addType(s));
+            }
+            break;
+        // case Opcodes.MULTIANEWARRAY:
+        default:
+            pop(arg);
+            push(cw, item.strVal1);
+            break;
         }
     }
 
@@ -1259,11 +1272,14 @@ final class Frame {
      * Merges the input frame of the given basic block with the input and output
      * frames of this basic block. Returns <tt>true</tt> if the input frame of
      * the given label has been changed by this operation.
-     *
-     * @param cw the ClassWriter to which this label belongs.
-     * @param frame the basic block whose input frame must be updated.
-     * @param edge the kind of the {@link Edge} between this label and 'label'.
-     *        See {@link Edge#info}.
+     * 
+     * @param cw
+     *            the ClassWriter to which this label belongs.
+     * @param frame
+     *            the basic block whose input frame must be updated.
+     * @param edge
+     *            the kind of the {@link Edge} between this label and 'label'.
+     *            See {@link Edge#info}.
      * @return <tt>true</tt> if the input frame of the given label has been
      *         changed by this operation.
      */
@@ -1294,7 +1310,8 @@ final class Frame {
                         } else {
                             t = dim + inputStack[nStack - (s & VALUE)];
                         }
-                        if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 && (t == LONG || t == DOUBLE)) {
+                        if ((s & TOP_IF_LONG_OR_DOUBLE) != 0
+                                && (t == LONG || t == DOUBLE)) {
                             t = TOP;
                         }
                     }
@@ -1346,7 +1363,8 @@ final class Frame {
                 } else {
                     t = dim + inputStack[nStack - (s & VALUE)];
                 }
-                if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 && (t == LONG || t == DOUBLE)) {
+                if ((s & TOP_IF_LONG_OR_DOUBLE) != 0
+                        && (t == LONG || t == DOUBLE)) {
                     t = TOP;
                 }
             }
@@ -1362,20 +1380,20 @@ final class Frame {
      * Merges the type at the given index in the given type array with the given
      * type. Returns <tt>true</tt> if the type array has been modified by this
      * operation.
-     *
-     * @param cw the ClassWriter to which this label belongs.
-     * @param t the type with which the type array element must be merged.
-     * @param types an array of types.
-     * @param index the index of the type that must be merged in 'types'.
+     * 
+     * @param cw
+     *            the ClassWriter to which this label belongs.
+     * @param t
+     *            the type with which the type array element must be merged.
+     * @param types
+     *            an array of types.
+     * @param index
+     *            the index of the type that must be merged in 'types'.
      * @return <tt>true</tt> if the type array has been modified by this
      *         operation.
      */
-    private static boolean merge(
-        final ClassWriter cw,
-        int t,
-        final int[] types,
-        final int index)
-    {
+    private static boolean merge(final ClassWriter cw, int t,
+            final int[] types, final int index) {
         int u = types[index];
         if (u == t) {
             // if the types are equal, merge(u,t)=u, so there is no change
@@ -1399,6 +1417,7 @@ final class Frame {
                 // if t is the NULL type, merge(u,t)=u, so there is no change
                 return false;
             } else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) {
+                // if t and u have the same dimension and same base kind
                 if ((u & BASE_KIND) == OBJECT) {
                     // if t is also a reference type, and if u and t have the
                     // same dimension merge(u,t) = dim(t) | common parent of the
@@ -1411,9 +1430,13 @@ final class Frame {
                     v = OBJECT | cw.addType("java/lang/Object");
                 }
             } else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) {
-                // if t is any other reference or array type,
-                // merge(u,t)=java/lang/Object
-                v = OBJECT | cw.addType("java/lang/Object");
+                // if t is any other reference or array type, the merged type
+                // is Object, or min(dim(u), dim(t)) | java/lang/Object is u
+                // and t have different array dimensions
+                int tdim = t & DIM;
+                int udim = u & DIM;
+                v = (udim != tdim ? Math.min(tdim, udim) : 0) | OBJECT
+                        | cw.addType("java/lang/Object");
             } else {
                 // if t is any other type, merge(u,t)=TOP
                 v = TOP;

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
index e8906fe..e01fd40 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
@@ -32,7 +32,7 @@ package org.apache.tapestry5.internal.plastic.asm;
 
 /**
  * A reference to a field or a method.
- *
+ * 
  * @author Remi Forax
  * @author Eric Bruneton
  */
@@ -49,7 +49,8 @@ public final class Handle {
     final int tag;
 
     /**
-     * The internal name of the field or method designed by this handle.
+     * The internal name of the class that owns the field or method designated
+     * by this handle.
      */
     final String owner;
 
@@ -65,19 +66,24 @@ public final class Handle {
 
     /**
      * Constructs a new field or method handle.
-     *
-     * @param tag the kind of field or method designated by this Handle. Must be
-     *        {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
-     *        {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
-     *        {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
-     *        {@link Opcodes#H_INVOKESPECIAL},
-     *        {@link Opcodes#H_NEWINVOKESPECIAL} or
-     *        {@link Opcodes#H_INVOKEINTERFACE}.
-     * @param owner the internal name of the field or method designed by this
-     *        handle.
-     * @param name the name of the field or method designated by this handle.
-     * @param desc the descriptor of the field or method designated by this
-     *        handle.
+     * 
+     * @param tag
+     *            the kind of field or method designated by this Handle. Must be
+     *            {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
+     *            {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
+     *            {@link Opcodes#H_INVOKEVIRTUAL},
+     *            {@link Opcodes#H_INVOKESTATIC},
+     *            {@link Opcodes#H_INVOKESPECIAL},
+     *            {@link Opcodes#H_NEWINVOKESPECIAL} or
+     *            {@link Opcodes#H_INVOKEINTERFACE}.
+     * @param owner
+     *            the internal name of the class that owns the field or method
+     *            designated by this handle.
+     * @param name
+     *            the name of the field or method designated by this handle.
+     * @param desc
+     *            the descriptor of the field or method designated by this
+     *            handle.
      */
     public Handle(int tag, String owner, String name, String desc) {
         this.tag = tag;
@@ -88,7 +94,7 @@ public final class Handle {
 
     /**
      * Returns the kind of field or method designated by this handle.
-     *
+     * 
      * @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
      *         {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
      *         {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
@@ -101,11 +107,11 @@ public final class Handle {
     }
 
     /**
-     * Returns the internal name of the field or method designed by this
-     * handle.
-     *
-     * @return the internal name of the field or method designed by this
-     *         handle.
+     * Returns the internal name of the class that owns the field or method
+     * designated by this handle.
+     * 
+     * @return the internal name of the class that owns the field or method
+     *         designated by this handle.
      */
     public String getOwner() {
         return owner;
@@ -113,7 +119,7 @@ public final class Handle {
 
     /**
      * Returns the name of the field or method designated by this handle.
-     *
+     * 
      * @return the name of the field or method designated by this handle.
      */
     public String getName() {
@@ -122,7 +128,7 @@ public final class Handle {
 
     /**
      * Returns the descriptor of the field or method designated by this handle.
-     *
+     * 
      * @return the descriptor of the field or method designated by this handle.
      */
     public String getDesc() {
@@ -138,8 +144,8 @@ public final class Handle {
             return false;
         }
         Handle h = (Handle) obj;
-        return tag == h.tag && owner.equals(h.owner)
-                && name.equals(h.name) && desc.equals(h.desc);
+        return tag == h.tag && owner.equals(h.owner) && name.equals(h.name)
+                && desc.equals(h.desc);
     }
 
     @Override
@@ -149,8 +155,13 @@ public final class Handle {
 
     /**
      * Returns the textual representation of this handle. The textual
-     * representation is: <pre>owner '.' name desc ' ' '(' tag ')'</pre>. As
-     * this format is unambiguous, it can be parsed if necessary.
+     * representation is:
+     * 
+     * <pre>
+     * owner '.' name desc ' ' '(' tag ')'
+     * </pre>
+     * 
+     * . As this format is unambiguous, it can be parsed if necessary.
      */
     @Override
     public String toString() {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
index 94ac8e5..a387654 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
 
 /**
  * Information about an exception handler block.
- *
+ * 
  * @author Eric Bruneton
  */
 class Handler {
@@ -71,10 +71,13 @@ class Handler {
     /**
      * Removes the range between start and end from the given exception
      * handlers.
-     *
-     * @param h an exception handler list.
-     * @param start the start of the range to be removed.
-     * @param end the end of the range to be removed. Maybe null.
+     * 
+     * @param h
+     *            an exception handler list.
+     * @param start
+     *            the start of the range to be removed.
+     * @param end
+     *            the end of the range to be removed. Maybe null.
      * @return the exception handler list with the start-end range removed.
      */
     static Handler remove(Handler h, Label start, Label end) {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java
index 4fab86a..fa4f454 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java
@@ -32,7 +32,7 @@ package org.apache.tapestry5.internal.plastic.asm;
 /**
  * A constant pool item. Constant pool items can be created with the 'newXXX'
  * methods in the {@link ClassWriter} class.
- *
+ * 
  * @author Eric Bruneton
  */
 final class Item {
@@ -52,11 +52,11 @@ final class Item {
      * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
      * {@link ClassWriter#METH}, {@link ClassWriter#IMETH},
      * {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
-     *
-     * MethodHandle constant 9 variations are stored using a range
-     * of 9 values from {@link ClassWriter#HANDLE_BASE} + 1 to
+     * 
+     * MethodHandle constant 9 variations are stored using a range of 9 values
+     * from {@link ClassWriter#HANDLE_BASE} + 1 to
      * {@link ClassWriter#HANDLE_BASE} + 9.
-     *
+     * 
      * Special Item types are used for Items that are stored in the ClassWriter
      * {@link ClassWriter#typeTable}, instead of the constant pool, in order to
      * avoid clashes with normal constant pool items in the ClassWriter constant
@@ -114,8 +114,9 @@ final class Item {
     /**
      * Constructs an uninitialized {@link Item} for constant pool element at
      * given position.
-     *
-     * @param index index of the item to be constructed.
+     * 
+     * @param index
+     *            index of the item to be constructed.
      */
     Item(final int index) {
         this.index = index;
@@ -123,9 +124,11 @@ final class Item {
 
     /**
      * Constructs a copy of the given item.
-     *
-     * @param index index of the item to be constructed.
-     * @param i the item that must be copied into the item to be constructed.
+     * 
+     * @param index
+     *            index of the item to be constructed.
+     * @param i
+     *            the item that must be copied into the item to be constructed.
      */
     Item(final int index, final Item i) {
         this.index = index;
@@ -140,8 +143,9 @@ final class Item {
 
     /**
      * Sets this item to an integer item.
-     *
-     * @param intVal the value of this item.
+     * 
+     * @param intVal
+     *            the value of this item.
      */
     void set(final int intVal) {
         this.type = ClassWriter.INT;
@@ -151,8 +155,9 @@ final class Item {
 
     /**
      * Sets this item to a long item.
-     *
-     * @param longVal the value of this item.
+     * 
+     * @param longVal
+     *            the value of this item.
      */
     void set(final long longVal) {
         this.type = ClassWriter.LONG;
@@ -162,8 +167,9 @@ final class Item {
 
     /**
      * Sets this item to a float item.
-     *
-     * @param floatVal the value of this item.
+     * 
+     * @param floatVal
+     *            the value of this item.
      */
     void set(final float floatVal) {
         this.type = ClassWriter.FLOAT;
@@ -173,8 +179,9 @@ final class Item {
 
     /**
      * Sets this item to a double item.
-     *
-     * @param doubleVal the value of this item.
+     * 
+     * @param doubleVal
+     *            the value of this item.
      */
     void set(final double doubleVal) {
         this.type = ClassWriter.DOUBLE;
@@ -184,50 +191,54 @@ final class Item {
 
     /**
      * Sets this item to an item that do not hold a primitive value.
-     *
-     * @param type the type of this item.
-     * @param strVal1 first part of the value of this item.
-     * @param strVal2 second part of the value of this item.
-     * @param strVal3 third part of the value of this item.
+     * 
+     * @param type
+     *            the type of this item.
+     * @param strVal1
+     *            first part of the value of this item.
+     * @param strVal2
+     *            second part of the value of this item.
+     * @param strVal3
+     *            third part of the value of this item.
      */
-    void set(
-        final int type,
-        final String strVal1,
-        final String strVal2,
-        final String strVal3)
-    {
+    void set(final int type, final String strVal1, final String strVal2,
+            final String strVal3) {
         this.type = type;
         this.strVal1 = strVal1;
         this.strVal2 = strVal2;
         this.strVal3 = strVal3;
         switch (type) {
-            case ClassWriter.UTF8:
-            case ClassWriter.STR:
-            case ClassWriter.CLASS:
-            case ClassWriter.MTYPE:
-            case ClassWriter.TYPE_NORMAL:
-                hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
-                return;
-            case ClassWriter.NAME_TYPE:
-                hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
-                        * strVal2.hashCode());
-                return;
-                // ClassWriter.FIELD:
-                // ClassWriter.METH:
-                // ClassWriter.IMETH:
-                // ClassWriter.HANDLE_BASE + 1..9
-            default:
-                hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
-                        * strVal2.hashCode() * strVal3.hashCode());
+        case ClassWriter.UTF8:
+        case ClassWriter.STR:
+        case ClassWriter.CLASS:
+        case ClassWriter.MTYPE:
+        case ClassWriter.TYPE_NORMAL:
+            hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
+            return;
+        case ClassWriter.NAME_TYPE: {
+            hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+                    * strVal2.hashCode());
+            return;
+        }
+        // ClassWriter.FIELD:
+        // ClassWriter.METH:
+        // ClassWriter.IMETH:
+        // ClassWriter.HANDLE_BASE + 1..9
+        default:
+            hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+                    * strVal2.hashCode() * strVal3.hashCode());
         }
     }
 
     /**
      * Sets the item to an InvokeDynamic item.
-     *
-     * @param name invokedynamic's name.
-     * @param desc invokedynamic's desc.
-     * @param bsmIndex zero based index into the class attribute BootrapMethods.
+     * 
+     * @param name
+     *            invokedynamic's name.
+     * @param desc
+     *            invokedynamic's desc.
+     * @param bsmIndex
+     *            zero based index into the class attribute BootrapMethods.
      */
     void set(String name, String desc, int bsmIndex) {
         this.type = ClassWriter.INDY;
@@ -240,11 +251,13 @@ final class Item {
 
     /**
      * Sets the item to a BootstrapMethod item.
-     *
-     * @param position position in byte in the class attribute BootrapMethods.
-     * @param hashCode hashcode of the item. This hashcode is processed from
-     *        the hashcode of the bootstrap method and the hashcode of
-     *        all bootstrap arguments.
+     * 
+     * @param position
+     *            position in byte in the class attribute BootrapMethods.
+     * @param hashCode
+     *            hashcode of the item. This hashcode is processed from the
+     *            hashcode of the bootstrap method and the hashcode of all
+     *            bootstrap arguments.
      */
     void set(int position, int hashCode) {
         this.type = ClassWriter.BSM;
@@ -255,42 +268,43 @@ final class Item {
     /**
      * Indicates if the given item is equal to this one. <i>This method assumes
      * that the two items have the same {@link #type}</i>.
-     *
-     * @param i the item to be compared to this one. Both items must have the
-     *       same {@link #type}.
+     * 
+     * @param i
+     *            the item to be compared to this one. Both items must have the
+     *            same {@link #type}.
      * @return <tt>true</tt> if the given item if equal to this one,
      *         <tt>false</tt> otherwise.
      */
     boolean isEqualTo(final Item i) {
         switch (type) {
-            case ClassWriter.UTF8:
-            case ClassWriter.STR:
-            case ClassWriter.CLASS:
-            case ClassWriter.MTYPE:
-            case ClassWriter.TYPE_NORMAL:
-                return i.strVal1.equals(strVal1);
-            case ClassWriter.TYPE_MERGED:
-            case ClassWriter.LONG:
-            case ClassWriter.DOUBLE:
-                return i.longVal == longVal;
-            case ClassWriter.INT:
-            case ClassWriter.FLOAT:
-                return i.intVal == intVal;
-            case ClassWriter.TYPE_UNINIT:
-                return i.intVal == intVal && i.strVal1.equals(strVal1);
-            case ClassWriter.NAME_TYPE:
-                return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
-            case ClassWriter.INDY:
-                return i.longVal == longVal && i.strVal1.equals(strVal1)
-                        && i.strVal2.equals(strVal2);
-
-            // case ClassWriter.FIELD:
-            // case ClassWriter.METH:
-            // case ClassWriter.IMETH:
-            // case ClassWriter.HANDLE_BASE + 1..9
-            default:
-                return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2)
-                        && i.strVal3.equals(strVal3);
+        case ClassWriter.UTF8:
+        case ClassWriter.STR:
+        case ClassWriter.CLASS:
+        case ClassWriter.MTYPE:
+        case ClassWriter.TYPE_NORMAL:
+            return i.strVal1.equals(strVal1);
+        case ClassWriter.TYPE_MERGED:
+        case ClassWriter.LONG:
+        case ClassWriter.DOUBLE:
+            return i.longVal == longVal;
+        case ClassWriter.INT:
+        case ClassWriter.FLOAT:
+            return i.intVal == intVal;
+        case ClassWriter.TYPE_UNINIT:
+            return i.intVal == intVal && i.strVal1.equals(strVal1);
+        case ClassWriter.NAME_TYPE:
+            return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
+        case ClassWriter.INDY: {
+            return i.longVal == longVal && i.strVal1.equals(strVal1)
+                    && i.strVal2.equals(strVal2);
+        }
+        // case ClassWriter.FIELD:
+        // case ClassWriter.METH:
+        // case ClassWriter.IMETH:
+        // case ClassWriter.HANDLE_BASE + 1..9
+        default:
+            return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2)
+                    && i.strVal3.equals(strVal3);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
index ef338c3..c0bbe7e 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
@@ -32,10 +32,10 @@ package org.apache.tapestry5.internal.plastic.asm;
 /**
  * A label represents a position in the bytecode of a method. Labels are used
  * for jump, goto, and switch instructions, and for try catch blocks. A label
- * designates the <i>instruction</i> that is just after. Note however that
- * there can be other elements between a label and the instruction it
- * designates (such as other labels, stack map frames, line numbers, etc.).
- *
+ * designates the <i>instruction</i> that is just after. Note however that there
+ * can be other elements between a label and the instruction it designates (such
+ * as other labels, stack map frames, line numbers, etc.).
+ * 
  * @author Eric Bruneton
  */
 public class Label {
@@ -110,14 +110,14 @@ public class Label {
     /**
      * Field used to associate user information to a label. Warning: this field
      * is used by the ASM tree package. In order to use it with the ASM tree
-     * package you must override the {@link
-     * org.apache.tapestry5.internal.plastic.asm.tree.MethodNode#getLabelNode} method.
+     * package you must override the
+     * {@link org.apache.tapestry5.internal.plastic.asm.tree.MethodNode#getLabelNode} method.
      */
     public Object info;
 
     /**
      * Flags that indicate the status of this label.
-     *
+     * 
      * @see #DEBUG
      * @see #RESOLVED
      * @see #RESIZED
@@ -154,7 +154,7 @@ public class Label {
      * indicates if this reference uses 2 or 4 bytes, and its absolute value
      * gives the position of the bytecode instruction. This array is also used
      * as a bitset to store the subroutines to which a basic block belongs. This
-     * information is needed in {@linked  MethodWriter#visitMaxs}, after all
+     * information is needed in {@linked MethodWriter#visitMaxs}, after all
      * forward references have been resolved. Hence the same array can be used
      * for both purposes without problems.
      */
@@ -170,19 +170,19 @@ public class Label {
      * represented by the Label object that corresponds to the first instruction
      * of this basic block. Each node also stores the list of its successors in
      * the graph, as a linked list of Edge objects.
-     *
+     * 
      * The control flow analysis algorithms used to compute the maximum stack
      * size or the stack map frames are similar and use two steps. The first
      * step, during the visit of each instruction, builds information about the
      * state of the local variables and the operand stack at the end of each
      * basic block, called the "output frame", <i>relatively</i> to the frame
      * state at the beginning of the basic block, which is called the "input
-     * frame", and which is <i>unknown</i> during this step. The second step,
-     * in {@link MethodWriter#visitMaxs}, is a fix point algorithm that
-     * computes information about the input frame of each basic block, from the
-     * input state of the first basic block (known from the method signature),
-     * and by the using the previously computed relative output frames.
-     *
+     * frame", and which is <i>unknown</i> during this step. The second step, in
+     * {@link MethodWriter#visitMaxs}, is a fix point algorithm that computes
+     * information about the input frame of each basic block, from the input
+     * state of the first basic block (known from the method signature), and by
+     * the using the previously computed relative output frames.
+     * 
      * The algorithm used to compute the maximum stack size only computes the
      * relative output and absolute input stack heights, while the algorithm
      * used to compute stack map frames computes relative output frames and
@@ -192,10 +192,10 @@ public class Label {
     /**
      * Start of the output stack relatively to the input stack. The exact
      * semantics of this field depends on the algorithm that is used.
-     *
+     * 
      * When only the maximum stack size is computed, this field is the number of
      * elements in the input stack.
-     *
+     * 
      * When the stack map frames are completely computed, this field is the
      * offset of the first output stack element relatively to the top of the
      * input stack. This offset is always negative or null. A null offset means
@@ -240,7 +240,7 @@ public class Label {
      * main loop of the fix point algorithm used in the second step of the
      * control flow analysis algorithms. It is also used in
      * {@link #visitSubroutine} to avoid using a recursive method.
-     *
+     * 
      * @see MethodWriter#visitMaxs
      */
     Label next;
@@ -264,13 +264,15 @@ public class Label {
      * from the start of the method's bytecode. <i>This method is intended for
      * {@link Attribute} sub classes, and is normally not needed by class
      * generators or adapters.</i>
-     *
+     * 
      * @return the offset corresponding to this label.
-     * @throws IllegalStateException if this label is not resolved yet.
+     * @throws IllegalStateException
+     *             if this label is not resolved yet.
      */
     public int getOffset() {
         if ((status & RESOLVED) == 0) {
-            throw new IllegalStateException("Label offset position has not been resolved yet");
+            throw new IllegalStateException(
+                    "Label offset position has not been resolved yet");
         }
         return position;
     }
@@ -280,22 +282,22 @@ public class Label {
      * position of the label is known, the offset is computed and written
      * directly. Otherwise, a null offset is written and a new forward reference
      * is declared for this label.
-     *
-     * @param owner the code writer that calls this method.
-     * @param out the bytecode of the method.
-     * @param source the position of first byte of the bytecode instruction that
-     *        contains this label.
-     * @param wideOffset <tt>true</tt> if the reference must be stored in 4
-     *        bytes, or <tt>false</tt> if it must be stored with 2 bytes.
-     * @throws IllegalArgumentException if this label has not been created by
-     *         the given code writer.
-     */
-    void put(
-        final MethodWriter owner,
-        final ByteVector out,
-        final int source,
-        final boolean wideOffset)
-    {
+     * 
+     * @param owner
+     *            the code writer that calls this method.
+     * @param out
+     *            the bytecode of the method.
+     * @param source
+     *            the position of first byte of the bytecode instruction that
+     *            contains this label.
+     * @param wideOffset
+     *            <tt>true</tt> if the reference must be stored in 4 bytes, or
+     *            <tt>false</tt> if it must be stored with 2 bytes.
+     * @throws IllegalArgumentException
+     *             if this label has not been created by the given code writer.
+     */
+    void put(final MethodWriter owner, final ByteVector out, final int source,
+            final boolean wideOffset) {
         if ((status & RESOLVED) == 0) {
             if (wideOffset) {
                 addReference(-1 - source, out.length);
@@ -318,26 +320,22 @@ public class Label {
      * for a true forward reference, i.e. only if this label is not resolved
      * yet. For backward references, the offset of the reference can be, and
      * must be, computed and stored directly.
-     *
-     * @param sourcePosition the position of the referencing instruction. This
-     *        position will be used to compute the offset of this forward
-     *        reference.
-     * @param referencePosition the position where the offset for this forward
-     *        reference must be stored.
-     */
-    private void addReference(
-        final int sourcePosition,
-        final int referencePosition)
-    {
+     * 
+     * @param sourcePosition
+     *            the position of the referencing instruction. This position
+     *            will be used to compute the offset of this forward reference.
+     * @param referencePosition
+     *            the position where the offset for this forward reference must
+     *            be stored.
+     */
+    private void addReference(final int sourcePosition,
+            final int referencePosition) {
         if (srcAndRefPositions == null) {
             srcAndRefPositions = new int[6];
         }
         if (referenceCount >= srcAndRefPositions.length) {
             int[] a = new int[srcAndRefPositions.length + 6];
-            System.arraycopy(srcAndRefPositions,
-                    0,
-                    a,
-                    0,
+            System.arraycopy(srcAndRefPositions, 0, a, 0,
                     srcAndRefPositions.length);
             srcAndRefPositions = a;
         }
@@ -350,10 +348,13 @@ public class Label {
      * when this label is added to the bytecode of the method, i.e. when its
      * position becomes known. This method fills in the blanks that where left
      * in the bytecode by each forward reference previously added to this label.
-     *
-     * @param owner the code writer that calls this method.
-     * @param position the position of this label in the bytecode.
-     * @param data the bytecode of the method.
+     * 
+     * @param owner
+     *            the code writer that calls this method.
+     * @param position
+     *            the position of this label in the bytecode.
+     * @param data
+     *            the bytecode of the method.
      * @return <tt>true</tt> if a blank that was left for this label was to
      *         small to store the offset. In such a case the corresponding jump
      *         instruction is replaced with a pseudo instruction (using unused
@@ -361,14 +362,12 @@ public class Label {
      *         instructions will need to be replaced with true instructions with
      *         wider offsets (4 bytes instead of 2). This is done in
      *         {@link MethodWriter#resizeInstructions}.
-     * @throws IllegalArgumentException if this label has already been resolved,
-     *         or if it has not been created by the given code writer.
-     */
-    boolean resolve(
-        final MethodWriter owner,
-        final int position,
-        final byte[] data)
-    {
+     * @throws IllegalArgumentException
+     *             if this label has already been resolved, or if it has not
+     *             been created by the given code writer.
+     */
+    boolean resolve(final MethodWriter owner, final int position,
+            final byte[] data) {
         boolean needUpdate = false;
         this.status |= RESOLVED;
         this.position = position;
@@ -417,7 +416,7 @@ public class Label {
      * isolated label or for the first label in a series of successive labels,
      * this method returns the label itself. For other labels it returns the
      * first label of the series.
-     *
+     * 
      * @return the first label of the series to which this label belongs.
      */
     Label getFirst() {
@@ -430,8 +429,9 @@ public class Label {
 
     /**
      * Returns true is this basic block belongs to the given subroutine.
-     *
-     * @param id a subroutine id.
+     * 
+     * @param id
+     *            a subroutine id.
      * @return true is this basic block belongs to the given subroutine.
      */
     boolean inSubroutine(final long id) {
@@ -444,8 +444,9 @@ public class Label {
     /**
      * Returns true if this basic block and the given one belong to a common
      * subroutine.
-     *
-     * @param block another basic block.
+     * 
+     * @param block
+     *            another basic block.
      * @return true if this basic block and the given one belong to a common
      *         subroutine.
      */
@@ -463,9 +464,11 @@ public class Label {
 
     /**
      * Marks this basic block as belonging to the given subroutine.
-     *
-     * @param id a subroutine id.
-     * @param nbSubroutines the total number of subroutines in the method.
+     * 
+     * @param id
+     *            a subroutine id.
+     * @param nbSubroutines
+     *            the total number of subroutines in the method.
      */
     void addToSubroutine(final long id, final int nbSubroutines) {
         if ((status & VISITED) == 0) {
@@ -480,15 +483,17 @@ public class Label {
      * blocks as belonging to this subroutine. This method follows the control
      * flow graph to find all the blocks that are reachable from the current
      * block WITHOUT following any JSR target.
-     *
-     * @param JSR a JSR block that jumps to this subroutine. If this JSR is not
-     *        null it is added to the successor of the RET blocks found in the
-     *        subroutine.
-     * @param id the id of this subroutine.
-     * @param nbSubroutines the total number of subroutines in the method.
-     */
-    void visitSubroutine(final Label JSR, final long id, final int nbSubroutines)
-    {
+     * 
+     * @param JSR
+     *            a JSR block that jumps to this subroutine. If this JSR is not
+     *            null it is added to the successor of the RET blocks found in
+     *            the subroutine.
+     * @param id
+     *            the id of this subroutine.
+     * @param nbSubroutines
+     *            the total number of subroutines in the method.
+     */
+    void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) {
         // user managed stack of labels, to avoid using a recursive method
         // (recursivity can lead to stack overflow with very large methods)
         Label stack = this;
@@ -545,7 +550,7 @@ public class Label {
 
     /**
      * Returns a string representation of this label.
-     *
+     * 
      * @return a string representation of this label.
      */
     @Override


[06/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java
new file mode 100644
index 0000000..294fd46
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java
@@ -0,0 +1,1009 @@
+/***
+ * 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.util;
+
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+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;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+import org.apache.tapestry5.internal.plastic.asm.tree.ClassNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.Analyzer;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicValue;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.Frame;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.SimpleVerifier;
+
+/**
+ * A {@link ClassVisitor} that checks that its methods are properly used. More
+ * precisely this class adapter checks each method call individually, based
+ * <i>only</i> on its arguments, but does <i>not</i> check the <i>sequence</i>
+ * of method calls. For example, the invalid sequence
+ * <tt>visitField(ACC_PUBLIC, "i", "I", null)</tt> <tt>visitField(ACC_PUBLIC,
+ * "i", "D", null)</tt> will <i>not</i> be detected by this class adapter.
+ * 
+ * <p>
+ * <code>CheckClassAdapter</code> can be also used to verify bytecode
+ * transformations in order to make sure transformed bytecode is sane. For
+ * example:
+ * 
+ * <pre>
+ *   InputStream is = ...; // get bytes for the source class
+ *   ClassReader cr = new ClassReader(is);
+ *   ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
+ *   ClassVisitor cv = new <b>MyClassAdapter</b>(new CheckClassAdapter(cw));
+ *   cr.accept(cv, 0);
+ * 
+ *   StringWriter sw = new StringWriter();
+ *   PrintWriter pw = new PrintWriter(sw);
+ *   CheckClassAdapter.verify(new ClassReader(cw.toByteArray()), false, pw);
+ *   assertTrue(sw.toString(), sw.toString().length()==0);
+ * </pre>
+ * 
+ * Above code runs transformed bytecode trough the
+ * <code>CheckClassAdapter</code>. It won't be exactly the same verification as
+ * JVM does, but it run data flow analysis for the code of each method and
+ * checks that expectations are met for each method instruction.
+ * 
+ * <p>
+ * If method bytecode has errors, assertion text will show the erroneous
+ * instruction number and dump of the failed method with information about
+ * locals and stack slot for each instruction. For example (format is -
+ * insnNumber locals : stack):
+ * 
+ * <pre>
+ * org.objectweb.asm.tree.analysis.AnalyzerException: Error at instruction 71: Expected I, but found .
+ *   at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:289)
+ *   at org.objectweb.asm.util.CheckClassAdapter.verify(CheckClassAdapter.java:135)
+ * ...
+ * remove()V
+ * 00000 LinkedBlockingQueue$Itr . . . . . . . .  :
+ *   ICONST_0
+ * 00001 LinkedBlockingQueue$Itr . . . . . . . .  : I
+ *   ISTORE 2
+ * 00001 LinkedBlockingQueue$Itr <b>.</b> I . . . . . .  :
+ * ...
+ * 
+ * 00071 LinkedBlockingQueue$Itr <b>.</b> I . . . . . .  :
+ *   ILOAD 1
+ * 00072 <b>?</b>
+ *   INVOKESPECIAL java/lang/Integer.&lt;init&gt; (I)V
+ * ...
+ * </pre>
+ * 
+ * In the above output you can see that variable 1 loaded by
+ * <code>ILOAD 1</code> instruction at position <code>00071</code> is not
+ * initialized. You can also see that at the beginning of the method (code
+ * inserted by the transformation) variable 2 is initialized.
+ * 
+ * <p>
+ * Note that when used like that, <code>CheckClassAdapter.verify()</code> can
+ * trigger additional class loading, because it is using
+ * <code>SimpleVerifier</code>.
+ * 
+ * @author Eric Bruneton
+ */
+public class CheckClassAdapter extends ClassVisitor {
+
+    /**
+     * The class version number.
+     */
+    private int version;
+
+    /**
+     * <tt>true</tt> if the visit method has been called.
+     */
+    private boolean start;
+
+    /**
+     * <tt>true</tt> if the visitSource method has been called.
+     */
+    private boolean source;
+
+    /**
+     * <tt>true</tt> if the visitOuterClass method has been called.
+     */
+    private boolean outer;
+
+    /**
+     * <tt>true</tt> if the visitEnd method has been called.
+     */
+    private boolean end;
+
+    /**
+     * The already visited labels. This map associate Integer values to Label
+     * keys.
+     */
+    private Map<Label, Integer> labels;
+
+    /**
+     * <tt>true</tt> if the method code must be checked with a BasicVerifier.
+     */
+    private boolean checkDataFlow;
+
+    /**
+     * Checks a given class.
+     * <p>
+     * Usage: CheckClassAdapter &lt;binary class name or class file name&gt;
+     * 
+     * @param args
+     *            the command line arguments.
+     * 
+     * @throws Exception
+     *             if the class cannot be found, or if an IO exception occurs.
+     */
+    public static void main(final String[] args) throws Exception {
+        if (args.length != 1) {
+            System.err.println("Verifies the given class.");
+            System.err.println("Usage: CheckClassAdapter "
+                    + "<fully qualified class name or class file name>");
+            return;
+        }
+        ClassReader cr;
+        if (args[0].endsWith(".class")) {
+            cr = new ClassReader(new FileInputStream(args[0]));
+        } else {
+            cr = new ClassReader(args[0]);
+        }
+
+        verify(cr, false, new PrintWriter(System.err));
+    }
+
+    /**
+     * Checks a given class.
+     * 
+     * @param cr
+     *            a <code>ClassReader</code> that contains bytecode for the
+     *            analysis.
+     * @param loader
+     *            a <code>ClassLoader</code> which will be used to load
+     *            referenced classes. This is useful if you are verifiying
+     *            multiple interdependent classes.
+     * @param dump
+     *            true if bytecode should be printed out not only when errors
+     *            are found.
+     * @param pw
+     *            write where results going to be printed
+     */
+    public static void verify(final ClassReader cr, final ClassLoader loader,
+            final boolean dump, final PrintWriter pw) {
+        ClassNode cn = new ClassNode();
+        cr.accept(new CheckClassAdapter(cn, false), ClassReader.SKIP_DEBUG);
+
+        Type syperType = cn.superName == null ? null : Type
+                .getObjectType(cn.superName);
+        List<MethodNode> methods = cn.methods;
+
+        List<Type> interfaces = new ArrayList<Type>();
+        for (Iterator<String> i = cn.interfaces.iterator(); i.hasNext();) {
+            interfaces.add(Type.getObjectType(i.next()));
+        }
+
+        for (int i = 0; i < methods.size(); ++i) {
+            MethodNode method = methods.get(i);
+            SimpleVerifier verifier = new SimpleVerifier(
+                    Type.getObjectType(cn.name), syperType, interfaces,
+                    (cn.access & Opcodes.ACC_INTERFACE) != 0);
+            Analyzer<BasicValue> a = new Analyzer<BasicValue>(verifier);
+            if (loader != null) {
+                verifier.setClassLoader(loader);
+            }
+            try {
+                a.analyze(cn.name, method);
+                if (!dump) {
+                    continue;
+                }
+            } catch (Exception e) {
+                e.printStackTrace(pw);
+            }
+            printAnalyzerResult(method, a, pw);
+        }
+        pw.flush();
+    }
+
+    /**
+     * Checks a given class
+     * 
+     * @param cr
+     *            a <code>ClassReader</code> that contains bytecode for the
+     *            analysis.
+     * @param dump
+     *            true if bytecode should be printed out not only when errors
+     *            are found.
+     * @param pw
+     *            write where results going to be printed
+     */
+    public static void verify(final ClassReader cr, final boolean dump,
+            final PrintWriter pw) {
+        verify(cr, null, dump, pw);
+    }
+
+    static void printAnalyzerResult(MethodNode method, Analyzer<BasicValue> a,
+            final PrintWriter pw) {
+        Frame<BasicValue>[] frames = a.getFrames();
+        Textifier t = new Textifier();
+        TraceMethodVisitor mv = new TraceMethodVisitor(t);
+
+        pw.println(method.name + method.desc);
+        for (int j = 0; j < method.instructions.size(); ++j) {
+            method.instructions.get(j).accept(mv);
+
+            StringBuffer s = new StringBuffer();
+            Frame<BasicValue> f = frames[j];
+            if (f == null) {
+                s.append('?');
+            } else {
+                for (int k = 0; k < f.getLocals(); ++k) {
+                    s.append(getShortName(f.getLocal(k).toString()))
+                            .append(' ');
+                }
+                s.append(" : ");
+                for (int k = 0; k < f.getStackSize(); ++k) {
+                    s.append(getShortName(f.getStack(k).toString()))
+                            .append(' ');
+                }
+            }
+            while (s.length() < method.maxStack + method.maxLocals + 1) {
+                s.append(' ');
+            }
+            pw.print(Integer.toString(j + 100000).substring(1));
+            pw.print(" " + s + " : " + t.text.get(t.text.size() - 1));
+        }
+        for (int j = 0; j < method.tryCatchBlocks.size(); ++j) {
+            method.tryCatchBlocks.get(j).accept(mv);
+            pw.print(" " + t.text.get(t.text.size() - 1));
+        }
+        pw.println();
+    }
+
+    private static String getShortName(final String name) {
+        int n = name.lastIndexOf('/');
+        int k = name.length();
+        if (name.charAt(k - 1) == ';') {
+            k--;
+        }
+        return n == -1 ? name : name.substring(n + 1, k);
+    }
+
+    /**
+     * Constructs a new {@link CheckClassAdapter}. <i>Subclasses must not use
+     * this constructor</i>. Instead, they must use the
+     * {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version.
+     * 
+     * @param cv
+     *            the class visitor to which this adapter must delegate calls.
+     */
+    public CheckClassAdapter(final ClassVisitor cv) {
+        this(cv, true);
+    }
+
+    /**
+     * Constructs a new {@link CheckClassAdapter}. <i>Subclasses must not use
+     * this constructor</i>. Instead, they must use the
+     * {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version.
+     * 
+     * @param cv
+     *            the class visitor to which this adapter must delegate calls.
+     * @param checkDataFlow
+     *            <tt>true</tt> to perform basic data flow checks, or
+     *            <tt>false</tt> to not perform any data flow check (see
+     *            {@link CheckMethodAdapter}). This option requires valid
+     *            maxLocals and maxStack values.
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public CheckClassAdapter(final ClassVisitor cv, final boolean checkDataFlow) {
+        this(Opcodes.ASM5, cv, checkDataFlow);
+        if (getClass() != CheckClassAdapter.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Constructs a new {@link CheckClassAdapter}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param cv
+     *            the class visitor to which this adapter must delegate calls.
+     * @param checkDataFlow
+     *            <tt>true</tt> to perform basic data flow checks, or
+     *            <tt>false</tt> to not perform any data flow check (see
+     *            {@link CheckMethodAdapter}). This option requires valid
+     *            maxLocals and maxStack values.
+     */
+    protected CheckClassAdapter(final int api, final ClassVisitor cv,
+            final boolean checkDataFlow) {
+        super(api, cv);
+        this.labels = new HashMap<Label, Integer>();
+        this.checkDataFlow = checkDataFlow;
+    }
+
+    // ------------------------------------------------------------------------
+    // Implementation of the ClassVisitor interface
+    // ------------------------------------------------------------------------
+
+    @Override
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
+        if (start) {
+            throw new IllegalStateException("visit must be called only once");
+        }
+        start = true;
+        checkState();
+        checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL
+                + Opcodes.ACC_SUPER + Opcodes.ACC_INTERFACE
+                + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
+                + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM
+                + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+        if (name == null || !name.endsWith("package-info")) {
+            CheckMethodAdapter.checkInternalName(name, "class name");
+        }
+        if ("java/lang/Object".equals(name)) {
+            if (superName != null) {
+                throw new IllegalArgumentException(
+                        "The super class name of the Object class must be 'null'");
+            }
+        } else {
+            CheckMethodAdapter.checkInternalName(superName, "super class name");
+        }
+        if (signature != null) {
+            checkClassSignature(signature);
+        }
+        if ((access & Opcodes.ACC_INTERFACE) != 0) {
+            if (!"java/lang/Object".equals(superName)) {
+                throw new IllegalArgumentException(
+                        "The super class name of interfaces must be 'java/lang/Object'");
+            }
+        }
+        if (interfaces != null) {
+            for (int i = 0; i < interfaces.length; ++i) {
+                CheckMethodAdapter.checkInternalName(interfaces[i],
+                        "interface name at index " + i);
+            }
+        }
+        this.version = version;
+        super.visit(version, access, name, signature, superName, interfaces);
+    }
+
+    @Override
+    public void visitSource(final String file, final String debug) {
+        checkState();
+        if (source) {
+            throw new IllegalStateException(
+                    "visitSource can be called only once.");
+        }
+        source = true;
+        super.visitSource(file, debug);
+    }
+
+    @Override
+    public void visitOuterClass(final String owner, final String name,
+            final String desc) {
+        checkState();
+        if (outer) {
+            throw new IllegalStateException(
+                    "visitOuterClass can be called only once.");
+        }
+        outer = true;
+        if (owner == null) {
+            throw new IllegalArgumentException("Illegal outer class owner");
+        }
+        if (desc != null) {
+            CheckMethodAdapter.checkMethodDesc(desc);
+        }
+        super.visitOuterClass(owner, name, desc);
+    }
+
+    @Override
+    public void visitInnerClass(final String name, final String outerName,
+            final String innerName, final int access) {
+        checkState();
+        CheckMethodAdapter.checkInternalName(name, "class name");
+        if (outerName != null) {
+            CheckMethodAdapter.checkInternalName(outerName, "outer class name");
+        }
+        if (innerName != null) {
+            int start = 0;
+            while (start < innerName.length()
+                    && Character.isDigit(innerName.charAt(start))) {
+                start++;
+            }
+            if (start == 0 || start < innerName.length()) {
+                CheckMethodAdapter.checkIdentifier(innerName, start, -1,
+                        "inner class name");
+            }
+        }
+        checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+                + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+                + Opcodes.ACC_FINAL + Opcodes.ACC_INTERFACE
+                + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
+                + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM);
+        super.visitInnerClass(name, outerName, innerName, access);
+    }
+
+    @Override
+    public FieldVisitor visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
+        checkState();
+        checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+                + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+                + Opcodes.ACC_FINAL + Opcodes.ACC_VOLATILE
+                + Opcodes.ACC_TRANSIENT + Opcodes.ACC_SYNTHETIC
+                + Opcodes.ACC_ENUM + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+        CheckMethodAdapter.checkUnqualifiedName(version, name, "field name");
+        CheckMethodAdapter.checkDesc(desc, false);
+        if (signature != null) {
+            checkFieldSignature(signature);
+        }
+        if (value != null) {
+            CheckMethodAdapter.checkConstant(value);
+        }
+        FieldVisitor av = super
+                .visitField(access, name, desc, signature, value);
+        return new CheckFieldAdapter(av);
+    }
+
+    @Override
+    public MethodVisitor visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        checkState();
+        checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+                + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+                + Opcodes.ACC_FINAL + Opcodes.ACC_SYNCHRONIZED
+                + Opcodes.ACC_BRIDGE + Opcodes.ACC_VARARGS + Opcodes.ACC_NATIVE
+                + Opcodes.ACC_ABSTRACT + Opcodes.ACC_STRICT
+                + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+        if (!"<init>".equals(name) && !"<clinit>".equals(name)) {
+            CheckMethodAdapter.checkMethodIdentifier(version, name,
+                    "method name");
+        }
+        CheckMethodAdapter.checkMethodDesc(desc);
+        if (signature != null) {
+            checkMethodSignature(signature);
+        }
+        if (exceptions != null) {
+            for (int i = 0; i < exceptions.length; ++i) {
+                CheckMethodAdapter.checkInternalName(exceptions[i],
+                        "exception name at index " + i);
+            }
+        }
+        CheckMethodAdapter cma;
+        if (checkDataFlow) {
+            cma = new CheckMethodAdapter(access, name, desc, super.visitMethod(
+                    access, name, desc, signature, exceptions), labels);
+        } else {
+            cma = new CheckMethodAdapter(super.visitMethod(access, name, desc,
+                    signature, exceptions), labels);
+        }
+        cma.version = version;
+        return cma;
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        checkState();
+        CheckMethodAdapter.checkDesc(desc, false);
+        return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        checkState();
+        int sort = typeRef >>> 24;
+        if (sort != TypeReference.CLASS_TYPE_PARAMETER
+                && sort != TypeReference.CLASS_TYPE_PARAMETER_BOUND
+                && sort != TypeReference.CLASS_EXTENDS) {
+            throw new IllegalArgumentException("Invalid type reference sort 0x"
+                    + Integer.toHexString(sort));
+        }
+        checkTypeRefAndPath(typeRef, typePath);
+        CheckMethodAdapter.checkDesc(desc, false);
+        return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef,
+                typePath, desc, visible));
+    }
+
+    @Override
+    public void visitAttribute(final Attribute attr) {
+        checkState();
+        if (attr == null) {
+            throw new IllegalArgumentException(
+                    "Invalid attribute (must not be null)");
+        }
+        super.visitAttribute(attr);
+    }
+
+    @Override
+    public void visitEnd() {
+        checkState();
+        end = true;
+        super.visitEnd();
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Checks that the visit method has been called and that visitEnd has not
+     * been called.
+     */
+    private void checkState() {
+        if (!start) {
+            throw new IllegalStateException(
+                    "Cannot visit member before visit has been called.");
+        }
+        if (end) {
+            throw new IllegalStateException(
+                    "Cannot visit member after visitEnd has been called.");
+        }
+    }
+
+    /**
+     * Checks that the given access flags do not contain invalid flags. This
+     * method also checks that mutually incompatible flags are not set
+     * simultaneously.
+     * 
+     * @param access
+     *            the access flags to be checked
+     * @param possibleAccess
+     *            the valid access flags.
+     */
+    static void checkAccess(final int access, final int possibleAccess) {
+        if ((access & ~possibleAccess) != 0) {
+            throw new IllegalArgumentException("Invalid access flags: "
+                    + access);
+        }
+        int pub = (access & Opcodes.ACC_PUBLIC) == 0 ? 0 : 1;
+        int pri = (access & Opcodes.ACC_PRIVATE) == 0 ? 0 : 1;
+        int pro = (access & Opcodes.ACC_PROTECTED) == 0 ? 0 : 1;
+        if (pub + pri + pro > 1) {
+            throw new IllegalArgumentException(
+                    "public private and protected are mutually exclusive: "
+                            + access);
+        }
+        int fin = (access & Opcodes.ACC_FINAL) == 0 ? 0 : 1;
+        int abs = (access & Opcodes.ACC_ABSTRACT) == 0 ? 0 : 1;
+        if (fin + abs > 1) {
+            throw new IllegalArgumentException(
+                    "final and abstract are mutually exclusive: " + access);
+        }
+    }
+
+    /**
+     * Checks a class signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     */
+    public static void checkClassSignature(final String signature) {
+        // ClassSignature:
+        // FormalTypeParameters? ClassTypeSignature ClassTypeSignature*
+
+        int pos = 0;
+        if (getChar(signature, 0) == '<') {
+            pos = checkFormalTypeParameters(signature, pos);
+        }
+        pos = checkClassTypeSignature(signature, pos);
+        while (getChar(signature, pos) == 'L') {
+            pos = checkClassTypeSignature(signature, pos);
+        }
+        if (pos != signature.length()) {
+            throw new IllegalArgumentException(signature + ": error at index "
+                    + pos);
+        }
+    }
+
+    /**
+     * Checks a method signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     */
+    public static void checkMethodSignature(final String signature) {
+        // MethodTypeSignature:
+        // FormalTypeParameters? ( TypeSignature* ) ( TypeSignature | V ) (
+        // ^ClassTypeSignature | ^TypeVariableSignature )*
+
+        int pos = 0;
+        if (getChar(signature, 0) == '<') {
+            pos = checkFormalTypeParameters(signature, pos);
+        }
+        pos = checkChar('(', signature, pos);
+        while ("ZCBSIFJDL[T".indexOf(getChar(signature, pos)) != -1) {
+            pos = checkTypeSignature(signature, pos);
+        }
+        pos = checkChar(')', signature, pos);
+        if (getChar(signature, pos) == 'V') {
+            ++pos;
+        } else {
+            pos = checkTypeSignature(signature, pos);
+        }
+        while (getChar(signature, pos) == '^') {
+            ++pos;
+            if (getChar(signature, pos) == 'L') {
+                pos = checkClassTypeSignature(signature, pos);
+            } else {
+                pos = checkTypeVariableSignature(signature, pos);
+            }
+        }
+        if (pos != signature.length()) {
+            throw new IllegalArgumentException(signature + ": error at index "
+                    + pos);
+        }
+    }
+
+    /**
+     * Checks a field signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     */
+    public static void checkFieldSignature(final String signature) {
+        int pos = checkFieldTypeSignature(signature, 0);
+        if (pos != signature.length()) {
+            throw new IllegalArgumentException(signature + ": error at index "
+                    + pos);
+        }
+    }
+
+    /**
+     * Checks the reference to a type in a type annotation.
+     * 
+     * @param typeRef
+     *            a reference to an annotated type.
+     * @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.
+     */
+    static void checkTypeRefAndPath(int typeRef, TypePath typePath) {
+        int mask = 0;
+        switch (typeRef >>> 24) {
+        case TypeReference.CLASS_TYPE_PARAMETER:
+        case TypeReference.METHOD_TYPE_PARAMETER:
+        case TypeReference.METHOD_FORMAL_PARAMETER:
+            mask = 0xFFFF0000;
+            break;
+        case TypeReference.FIELD:
+        case TypeReference.METHOD_RETURN:
+        case TypeReference.METHOD_RECEIVER:
+        case TypeReference.LOCAL_VARIABLE:
+        case TypeReference.RESOURCE_VARIABLE:
+        case TypeReference.INSTANCEOF:
+        case TypeReference.NEW:
+        case TypeReference.CONSTRUCTOR_REFERENCE:
+        case TypeReference.METHOD_REFERENCE:
+            mask = 0xFF000000;
+            break;
+        case TypeReference.CLASS_EXTENDS:
+        case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
+        case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
+        case TypeReference.THROWS:
+        case TypeReference.EXCEPTION_PARAMETER:
+            mask = 0xFFFFFF00;
+            break;
+        case TypeReference.CAST:
+        case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
+        case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT:
+        case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
+        case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT:
+            mask = 0xFF0000FF;
+            break;
+        default:
+            throw new IllegalArgumentException("Invalid type reference sort 0x"
+                    + Integer.toHexString(typeRef >>> 24));
+        }
+        if ((typeRef & ~mask) != 0) {
+            throw new IllegalArgumentException("Invalid type reference 0x"
+                    + Integer.toHexString(typeRef));
+        }
+        if (typePath != null) {
+            for (int i = 0; i < typePath.getLength(); ++i) {
+                int step = typePath.getStep(i);
+                if (step != TypePath.ARRAY_ELEMENT
+                        && step != TypePath.INNER_TYPE
+                        && step != TypePath.TYPE_ARGUMENT
+                        && step != TypePath.WILDCARD_BOUND) {
+                    throw new IllegalArgumentException(
+                            "Invalid type path step " + i + " in " + typePath);
+                }
+                if (step != TypePath.TYPE_ARGUMENT
+                        && typePath.getStepArgument(i) != 0) {
+                    throw new IllegalArgumentException(
+                            "Invalid type path step argument for step " + i
+                                    + " in " + typePath);
+                }
+            }
+        }
+    }
+
+    /**
+     * Checks the formal type parameters of a class or method signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkFormalTypeParameters(final String signature, int pos) {
+        // FormalTypeParameters:
+        // < FormalTypeParameter+ >
+
+        pos = checkChar('<', signature, pos);
+        pos = checkFormalTypeParameter(signature, pos);
+        while (getChar(signature, pos) != '>') {
+            pos = checkFormalTypeParameter(signature, pos);
+        }
+        return pos + 1;
+    }
+
+    /**
+     * Checks a formal type parameter of a class or method signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkFormalTypeParameter(final String signature, int pos) {
+        // FormalTypeParameter:
+        // Identifier : FieldTypeSignature? (: FieldTypeSignature)*
+
+        pos = checkIdentifier(signature, pos);
+        pos = checkChar(':', signature, pos);
+        if ("L[T".indexOf(getChar(signature, pos)) != -1) {
+            pos = checkFieldTypeSignature(signature, pos);
+        }
+        while (getChar(signature, pos) == ':') {
+            pos = checkFieldTypeSignature(signature, pos + 1);
+        }
+        return pos;
+    }
+
+    /**
+     * Checks a field type signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkFieldTypeSignature(final String signature, int pos) {
+        // FieldTypeSignature:
+        // ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature
+        //
+        // ArrayTypeSignature:
+        // [ TypeSignature
+
+        switch (getChar(signature, pos)) {
+        case 'L':
+            return checkClassTypeSignature(signature, pos);
+        case '[':
+            return checkTypeSignature(signature, pos + 1);
+        default:
+            return checkTypeVariableSignature(signature, pos);
+        }
+    }
+
+    /**
+     * Checks a class type signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkClassTypeSignature(final String signature, int pos) {
+        // ClassTypeSignature:
+        // L Identifier ( / Identifier )* TypeArguments? ( . Identifier
+        // TypeArguments? )* ;
+
+        pos = checkChar('L', signature, pos);
+        pos = checkIdentifier(signature, pos);
+        while (getChar(signature, pos) == '/') {
+            pos = checkIdentifier(signature, pos + 1);
+        }
+        if (getChar(signature, pos) == '<') {
+            pos = checkTypeArguments(signature, pos);
+        }
+        while (getChar(signature, pos) == '.') {
+            pos = checkIdentifier(signature, pos + 1);
+            if (getChar(signature, pos) == '<') {
+                pos = checkTypeArguments(signature, pos);
+            }
+        }
+        return checkChar(';', signature, pos);
+    }
+
+    /**
+     * Checks the type arguments in a class type signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkTypeArguments(final String signature, int pos) {
+        // TypeArguments:
+        // < TypeArgument+ >
+
+        pos = checkChar('<', signature, pos);
+        pos = checkTypeArgument(signature, pos);
+        while (getChar(signature, pos) != '>') {
+            pos = checkTypeArgument(signature, pos);
+        }
+        return pos + 1;
+    }
+
+    /**
+     * Checks a type argument in a class type signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkTypeArgument(final String signature, int pos) {
+        // TypeArgument:
+        // * | ( ( + | - )? FieldTypeSignature )
+
+        char c = getChar(signature, pos);
+        if (c == '*') {
+            return pos + 1;
+        } else if (c == '+' || c == '-') {
+            pos++;
+        }
+        return checkFieldTypeSignature(signature, pos);
+    }
+
+    /**
+     * Checks a type variable signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkTypeVariableSignature(final String signature,
+            int pos) {
+        // TypeVariableSignature:
+        // T Identifier ;
+
+        pos = checkChar('T', signature, pos);
+        pos = checkIdentifier(signature, pos);
+        return checkChar(';', signature, pos);
+    }
+
+    /**
+     * Checks a type signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkTypeSignature(final String signature, int pos) {
+        // TypeSignature:
+        // Z | C | B | S | I | F | J | D | FieldTypeSignature
+
+        switch (getChar(signature, pos)) {
+        case 'Z':
+        case 'C':
+        case 'B':
+        case 'S':
+        case 'I':
+        case 'F':
+        case 'J':
+        case 'D':
+            return pos + 1;
+        default:
+            return checkFieldTypeSignature(signature, pos);
+        }
+    }
+
+    /**
+     * Checks an identifier.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkIdentifier(final String signature, int pos) {
+        if (!Character.isJavaIdentifierStart(getChar(signature, pos))) {
+            throw new IllegalArgumentException(signature
+                    + ": identifier expected at index " + pos);
+        }
+        ++pos;
+        while (Character.isJavaIdentifierPart(getChar(signature, pos))) {
+            ++pos;
+        }
+        return pos;
+    }
+
+    /**
+     * Checks a single character.
+     * 
+     * @param signature
+     *            a string containing the signature that must be checked.
+     * @param pos
+     *            index of first character to be checked.
+     * @return the index of the first character after the checked part.
+     */
+    private static int checkChar(final char c, final String signature, int pos) {
+        if (getChar(signature, pos) == c) {
+            return pos + 1;
+        }
+        throw new IllegalArgumentException(signature + ": '" + c
+                + "' expected at index " + pos);
+    }
+
+    /**
+     * Returns the signature car at the given index.
+     * 
+     * @param signature
+     *            a signature.
+     * @param pos
+     *            an index in signature.
+     * @return the character at the given index, or 0 if there is no such
+     *         character.
+     */
+    private static char getChar(final String signature, int pos) {
+        return pos < signature.length() ? signature.charAt(pos) : (char) 0;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java
new file mode 100644
index 0000000..753025b
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java
@@ -0,0 +1,122 @@
+/***
+ * 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.util;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+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 {@link FieldVisitor} that checks that its methods are properly used.
+ */
+public class CheckFieldAdapter extends FieldVisitor {
+
+    private boolean end;
+
+    /**
+     * Constructs a new {@link CheckFieldAdapter}. <i>Subclasses must not use
+     * this constructor</i>. Instead, they must use the
+     * {@link #CheckFieldAdapter(int, FieldVisitor)} version.
+     * 
+     * @param fv
+     *            the field visitor to which this adapter must delegate calls.
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public CheckFieldAdapter(final FieldVisitor fv) {
+        this(Opcodes.ASM5, fv);
+        if (getClass() != CheckFieldAdapter.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Constructs a new {@link CheckFieldAdapter}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param fv
+     *            the field visitor to which this adapter must delegate calls.
+     */
+    protected CheckFieldAdapter(final int api, final FieldVisitor fv) {
+        super(api, fv);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        checkEnd();
+        CheckMethodAdapter.checkDesc(desc, false);
+        return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        checkEnd();
+        int sort = typeRef >>> 24;
+        if (sort != TypeReference.FIELD) {
+            throw new IllegalArgumentException("Invalid type reference sort 0x"
+                    + Integer.toHexString(sort));
+        }
+        CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+        CheckMethodAdapter.checkDesc(desc, false);
+        return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef,
+                typePath, desc, visible));
+    }
+
+    @Override
+    public void visitAttribute(final Attribute attr) {
+        checkEnd();
+        if (attr == null) {
+            throw new IllegalArgumentException(
+                    "Invalid attribute (must not be null)");
+        }
+        super.visitAttribute(attr);
+    }
+
+    @Override
+    public void visitEnd() {
+        checkEnd();
+        end = true;
+        super.visitEnd();
+    }
+
+    private void checkEnd() {
+        if (end) {
+            throw new IllegalStateException(
+                    "Cannot call a visit method after visitEnd has been called");
+        }
+    }
+}


[14/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
new file mode 100644
index 0000000..fe8400a
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
@@ -0,0 +1,1170 @@
+/***
+ * 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.commons;
+
+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;
+
+/**
+ * A {@link MethodVisitor} providing a more detailed API to generate and
+ * transform instructions.
+ * 
+ * @author Eric Bruneton
+ */
+public class InstructionAdapter extends MethodVisitor {
+
+    public final static Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;");
+
+    /**
+     * Creates a new {@link InstructionAdapter}. <i>Subclasses must not use this
+     * constructor</i>. Instead, they must use the
+     * {@link #InstructionAdapter(int, MethodVisitor)} version.
+     * 
+     * @param mv
+     *            the method visitor to which this adapter delegates calls.
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public InstructionAdapter(final MethodVisitor mv) {
+        this(Opcodes.ASM5, mv);
+        if (getClass() != InstructionAdapter.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Creates a new {@link InstructionAdapter}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param mv
+     *            the method visitor to which this adapter delegates calls.
+     */
+    protected InstructionAdapter(final int api, final MethodVisitor mv) {
+        super(api, mv);
+    }
+
+    @Override
+    public void visitInsn(final int opcode) {
+        switch (opcode) {
+        case Opcodes.NOP:
+            nop();
+            break;
+        case Opcodes.ACONST_NULL:
+            aconst(null);
+            break;
+        case Opcodes.ICONST_M1:
+        case Opcodes.ICONST_0:
+        case Opcodes.ICONST_1:
+        case Opcodes.ICONST_2:
+        case Opcodes.ICONST_3:
+        case Opcodes.ICONST_4:
+        case Opcodes.ICONST_5:
+            iconst(opcode - Opcodes.ICONST_0);
+            break;
+        case Opcodes.LCONST_0:
+        case Opcodes.LCONST_1:
+            lconst(opcode - Opcodes.LCONST_0);
+            break;
+        case Opcodes.FCONST_0:
+        case Opcodes.FCONST_1:
+        case Opcodes.FCONST_2:
+            fconst(opcode - Opcodes.FCONST_0);
+            break;
+        case Opcodes.DCONST_0:
+        case Opcodes.DCONST_1:
+            dconst(opcode - Opcodes.DCONST_0);
+            break;
+        case Opcodes.IALOAD:
+            aload(Type.INT_TYPE);
+            break;
+        case Opcodes.LALOAD:
+            aload(Type.LONG_TYPE);
+            break;
+        case Opcodes.FALOAD:
+            aload(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DALOAD:
+            aload(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.AALOAD:
+            aload(OBJECT_TYPE);
+            break;
+        case Opcodes.BALOAD:
+            aload(Type.BYTE_TYPE);
+            break;
+        case Opcodes.CALOAD:
+            aload(Type.CHAR_TYPE);
+            break;
+        case Opcodes.SALOAD:
+            aload(Type.SHORT_TYPE);
+            break;
+        case Opcodes.IASTORE:
+            astore(Type.INT_TYPE);
+            break;
+        case Opcodes.LASTORE:
+            astore(Type.LONG_TYPE);
+            break;
+        case Opcodes.FASTORE:
+            astore(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DASTORE:
+            astore(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.AASTORE:
+            astore(OBJECT_TYPE);
+            break;
+        case Opcodes.BASTORE:
+            astore(Type.BYTE_TYPE);
+            break;
+        case Opcodes.CASTORE:
+            astore(Type.CHAR_TYPE);
+            break;
+        case Opcodes.SASTORE:
+            astore(Type.SHORT_TYPE);
+            break;
+        case Opcodes.POP:
+            pop();
+            break;
+        case Opcodes.POP2:
+            pop2();
+            break;
+        case Opcodes.DUP:
+            dup();
+            break;
+        case Opcodes.DUP_X1:
+            dupX1();
+            break;
+        case Opcodes.DUP_X2:
+            dupX2();
+            break;
+        case Opcodes.DUP2:
+            dup2();
+            break;
+        case Opcodes.DUP2_X1:
+            dup2X1();
+            break;
+        case Opcodes.DUP2_X2:
+            dup2X2();
+            break;
+        case Opcodes.SWAP:
+            swap();
+            break;
+        case Opcodes.IADD:
+            add(Type.INT_TYPE);
+            break;
+        case Opcodes.LADD:
+            add(Type.LONG_TYPE);
+            break;
+        case Opcodes.FADD:
+            add(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DADD:
+            add(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.ISUB:
+            sub(Type.INT_TYPE);
+            break;
+        case Opcodes.LSUB:
+            sub(Type.LONG_TYPE);
+            break;
+        case Opcodes.FSUB:
+            sub(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DSUB:
+            sub(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.IMUL:
+            mul(Type.INT_TYPE);
+            break;
+        case Opcodes.LMUL:
+            mul(Type.LONG_TYPE);
+            break;
+        case Opcodes.FMUL:
+            mul(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DMUL:
+            mul(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.IDIV:
+            div(Type.INT_TYPE);
+            break;
+        case Opcodes.LDIV:
+            div(Type.LONG_TYPE);
+            break;
+        case Opcodes.FDIV:
+            div(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DDIV:
+            div(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.IREM:
+            rem(Type.INT_TYPE);
+            break;
+        case Opcodes.LREM:
+            rem(Type.LONG_TYPE);
+            break;
+        case Opcodes.FREM:
+            rem(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DREM:
+            rem(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.INEG:
+            neg(Type.INT_TYPE);
+            break;
+        case Opcodes.LNEG:
+            neg(Type.LONG_TYPE);
+            break;
+        case Opcodes.FNEG:
+            neg(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DNEG:
+            neg(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.ISHL:
+            shl(Type.INT_TYPE);
+            break;
+        case Opcodes.LSHL:
+            shl(Type.LONG_TYPE);
+            break;
+        case Opcodes.ISHR:
+            shr(Type.INT_TYPE);
+            break;
+        case Opcodes.LSHR:
+            shr(Type.LONG_TYPE);
+            break;
+        case Opcodes.IUSHR:
+            ushr(Type.INT_TYPE);
+            break;
+        case Opcodes.LUSHR:
+            ushr(Type.LONG_TYPE);
+            break;
+        case Opcodes.IAND:
+            and(Type.INT_TYPE);
+            break;
+        case Opcodes.LAND:
+            and(Type.LONG_TYPE);
+            break;
+        case Opcodes.IOR:
+            or(Type.INT_TYPE);
+            break;
+        case Opcodes.LOR:
+            or(Type.LONG_TYPE);
+            break;
+        case Opcodes.IXOR:
+            xor(Type.INT_TYPE);
+            break;
+        case Opcodes.LXOR:
+            xor(Type.LONG_TYPE);
+            break;
+        case Opcodes.I2L:
+            cast(Type.INT_TYPE, Type.LONG_TYPE);
+            break;
+        case Opcodes.I2F:
+            cast(Type.INT_TYPE, Type.FLOAT_TYPE);
+            break;
+        case Opcodes.I2D:
+            cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.L2I:
+            cast(Type.LONG_TYPE, Type.INT_TYPE);
+            break;
+        case Opcodes.L2F:
+            cast(Type.LONG_TYPE, Type.FLOAT_TYPE);
+            break;
+        case Opcodes.L2D:
+            cast(Type.LONG_TYPE, Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.F2I:
+            cast(Type.FLOAT_TYPE, Type.INT_TYPE);
+            break;
+        case Opcodes.F2L:
+            cast(Type.FLOAT_TYPE, Type.LONG_TYPE);
+            break;
+        case Opcodes.F2D:
+            cast(Type.FLOAT_TYPE, Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.D2I:
+            cast(Type.DOUBLE_TYPE, Type.INT_TYPE);
+            break;
+        case Opcodes.D2L:
+            cast(Type.DOUBLE_TYPE, Type.LONG_TYPE);
+            break;
+        case Opcodes.D2F:
+            cast(Type.DOUBLE_TYPE, Type.FLOAT_TYPE);
+            break;
+        case Opcodes.I2B:
+            cast(Type.INT_TYPE, Type.BYTE_TYPE);
+            break;
+        case Opcodes.I2C:
+            cast(Type.INT_TYPE, Type.CHAR_TYPE);
+            break;
+        case Opcodes.I2S:
+            cast(Type.INT_TYPE, Type.SHORT_TYPE);
+            break;
+        case Opcodes.LCMP:
+            lcmp();
+            break;
+        case Opcodes.FCMPL:
+            cmpl(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.FCMPG:
+            cmpg(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DCMPL:
+            cmpl(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.DCMPG:
+            cmpg(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.IRETURN:
+            areturn(Type.INT_TYPE);
+            break;
+        case Opcodes.LRETURN:
+            areturn(Type.LONG_TYPE);
+            break;
+        case Opcodes.FRETURN:
+            areturn(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DRETURN:
+            areturn(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.ARETURN:
+            areturn(OBJECT_TYPE);
+            break;
+        case Opcodes.RETURN:
+            areturn(Type.VOID_TYPE);
+            break;
+        case Opcodes.ARRAYLENGTH:
+            arraylength();
+            break;
+        case Opcodes.ATHROW:
+            athrow();
+            break;
+        case Opcodes.MONITORENTER:
+            monitorenter();
+            break;
+        case Opcodes.MONITOREXIT:
+            monitorexit();
+            break;
+        default:
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public void visitIntInsn(final int opcode, final int operand) {
+        switch (opcode) {
+        case Opcodes.BIPUSH:
+            iconst(operand);
+            break;
+        case Opcodes.SIPUSH:
+            iconst(operand);
+            break;
+        case Opcodes.NEWARRAY:
+            switch (operand) {
+            case Opcodes.T_BOOLEAN:
+                newarray(Type.BOOLEAN_TYPE);
+                break;
+            case Opcodes.T_CHAR:
+                newarray(Type.CHAR_TYPE);
+                break;
+            case Opcodes.T_BYTE:
+                newarray(Type.BYTE_TYPE);
+                break;
+            case Opcodes.T_SHORT:
+                newarray(Type.SHORT_TYPE);
+                break;
+            case Opcodes.T_INT:
+                newarray(Type.INT_TYPE);
+                break;
+            case Opcodes.T_FLOAT:
+                newarray(Type.FLOAT_TYPE);
+                break;
+            case Opcodes.T_LONG:
+                newarray(Type.LONG_TYPE);
+                break;
+            case Opcodes.T_DOUBLE:
+                newarray(Type.DOUBLE_TYPE);
+                break;
+            default:
+                throw new IllegalArgumentException();
+            }
+            break;
+        default:
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public void visitVarInsn(final int opcode, final int var) {
+        switch (opcode) {
+        case Opcodes.ILOAD:
+            load(var, Type.INT_TYPE);
+            break;
+        case Opcodes.LLOAD:
+            load(var, Type.LONG_TYPE);
+            break;
+        case Opcodes.FLOAD:
+            load(var, Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DLOAD:
+            load(var, Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.ALOAD:
+            load(var, OBJECT_TYPE);
+            break;
+        case Opcodes.ISTORE:
+            store(var, Type.INT_TYPE);
+            break;
+        case Opcodes.LSTORE:
+            store(var, Type.LONG_TYPE);
+            break;
+        case Opcodes.FSTORE:
+            store(var, Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DSTORE:
+            store(var, Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.ASTORE:
+            store(var, OBJECT_TYPE);
+            break;
+        case Opcodes.RET:
+            ret(var);
+            break;
+        default:
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public void visitTypeInsn(final int opcode, final String type) {
+        Type t = Type.getObjectType(type);
+        switch (opcode) {
+        case Opcodes.NEW:
+            anew(t);
+            break;
+        case Opcodes.ANEWARRAY:
+            newarray(t);
+            break;
+        case Opcodes.CHECKCAST:
+            checkcast(t);
+            break;
+        case Opcodes.INSTANCEOF:
+            instanceOf(t);
+            break;
+        default:
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public void visitFieldInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        switch (opcode) {
+        case Opcodes.GETSTATIC:
+            getstatic(owner, name, desc);
+            break;
+        case Opcodes.PUTSTATIC:
+            putstatic(owner, name, desc);
+            break;
+        case Opcodes.GETFIELD:
+            getfield(owner, name, desc);
+            break;
+        case Opcodes.PUTFIELD:
+            putfield(owner, name, desc);
+            break;
+        default:
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Deprecated
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (api >= Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc,
+                opcode == Opcodes.INVOKEINTERFACE);
+    }
+
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    private void doVisitMethodInsn(int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        switch (opcode) {
+        case Opcodes.INVOKESPECIAL:
+            invokespecial(owner, name, desc, itf);
+            break;
+        case Opcodes.INVOKEVIRTUAL:
+            invokevirtual(owner, name, desc, itf);
+            break;
+        case Opcodes.INVOKESTATIC:
+            invokestatic(owner, name, desc, itf);
+            break;
+        case Opcodes.INVOKEINTERFACE:
+            invokeinterface(owner, name, desc);
+            break;
+        default:
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        invokedynamic(name, desc, bsm, bsmArgs);
+    }
+
+    @Override
+    public void visitJumpInsn(final int opcode, final Label label) {
+        switch (opcode) {
+        case Opcodes.IFEQ:
+            ifeq(label);
+            break;
+        case Opcodes.IFNE:
+            ifne(label);
+            break;
+        case Opcodes.IFLT:
+            iflt(label);
+            break;
+        case Opcodes.IFGE:
+            ifge(label);
+            break;
+        case Opcodes.IFGT:
+            ifgt(label);
+            break;
+        case Opcodes.IFLE:
+            ifle(label);
+            break;
+        case Opcodes.IF_ICMPEQ:
+            ificmpeq(label);
+            break;
+        case Opcodes.IF_ICMPNE:
+            ificmpne(label);
+            break;
+        case Opcodes.IF_ICMPLT:
+            ificmplt(label);
+            break;
+        case Opcodes.IF_ICMPGE:
+            ificmpge(label);
+            break;
+        case Opcodes.IF_ICMPGT:
+            ificmpgt(label);
+            break;
+        case Opcodes.IF_ICMPLE:
+            ificmple(label);
+            break;
+        case Opcodes.IF_ACMPEQ:
+            ifacmpeq(label);
+            break;
+        case Opcodes.IF_ACMPNE:
+            ifacmpne(label);
+            break;
+        case Opcodes.GOTO:
+            goTo(label);
+            break;
+        case Opcodes.JSR:
+            jsr(label);
+            break;
+        case Opcodes.IFNULL:
+            ifnull(label);
+            break;
+        case Opcodes.IFNONNULL:
+            ifnonnull(label);
+            break;
+        default:
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public void visitLabel(final Label label) {
+        mark(label);
+    }
+
+    @Override
+    public void visitLdcInsn(final Object cst) {
+        if (cst instanceof Integer) {
+            int val = ((Integer) cst).intValue();
+            iconst(val);
+        } else if (cst instanceof Byte) {
+            int val = ((Byte) cst).intValue();
+            iconst(val);
+        } else if (cst instanceof Character) {
+            int val = ((Character) cst).charValue();
+            iconst(val);
+        } else if (cst instanceof Short) {
+            int val = ((Short) cst).intValue();
+            iconst(val);
+        } else if (cst instanceof Boolean) {
+            int val = ((Boolean) cst).booleanValue() ? 1 : 0;
+            iconst(val);
+        } else if (cst instanceof Float) {
+            float val = ((Float) cst).floatValue();
+            fconst(val);
+        } else if (cst instanceof Long) {
+            long val = ((Long) cst).longValue();
+            lconst(val);
+        } else if (cst instanceof Double) {
+            double val = ((Double) cst).doubleValue();
+            dconst(val);
+        } else if (cst instanceof String) {
+            aconst(cst);
+        } else if (cst instanceof Type) {
+            tconst((Type) cst);
+        } else if (cst instanceof Handle) {
+            hconst((Handle) cst);
+        } else {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public void visitIincInsn(final int var, final int increment) {
+        iinc(var, increment);
+    }
+
+    @Override
+    public void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels) {
+        tableswitch(min, max, dflt, labels);
+    }
+
+    @Override
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
+        lookupswitch(dflt, keys, labels);
+    }
+
+    @Override
+    public void visitMultiANewArrayInsn(final String desc, final int dims) {
+        multianewarray(desc, dims);
+    }
+
+    // -----------------------------------------------------------------------
+
+    public void nop() {
+        mv.visitInsn(Opcodes.NOP);
+    }
+
+    public void aconst(final Object cst) {
+        if (cst == null) {
+            mv.visitInsn(Opcodes.ACONST_NULL);
+        } else {
+            mv.visitLdcInsn(cst);
+        }
+    }
+
+    public void iconst(final int cst) {
+        if (cst >= -1 && cst <= 5) {
+            mv.visitInsn(Opcodes.ICONST_0 + cst);
+        } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {
+            mv.visitIntInsn(Opcodes.BIPUSH, cst);
+        } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {
+            mv.visitIntInsn(Opcodes.SIPUSH, cst);
+        } else {
+            mv.visitLdcInsn(new Integer(cst));
+        }
+    }
+
+    public void lconst(final long cst) {
+        if (cst == 0L || cst == 1L) {
+            mv.visitInsn(Opcodes.LCONST_0 + (int) cst);
+        } else {
+            mv.visitLdcInsn(new Long(cst));
+        }
+    }
+
+    public void fconst(final float cst) {
+        int bits = Float.floatToIntBits(cst);
+        if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2
+            mv.visitInsn(Opcodes.FCONST_0 + (int) cst);
+        } else {
+            mv.visitLdcInsn(new Float(cst));
+        }
+    }
+
+    public void dconst(final double cst) {
+        long bits = Double.doubleToLongBits(cst);
+        if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d
+            mv.visitInsn(Opcodes.DCONST_0 + (int) cst);
+        } else {
+            mv.visitLdcInsn(new Double(cst));
+        }
+    }
+
+    public void tconst(final Type type) {
+        mv.visitLdcInsn(type);
+    }
+
+    public void hconst(final Handle handle) {
+        mv.visitLdcInsn(handle);
+    }
+
+    public void load(final int var, final Type type) {
+        mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), var);
+    }
+
+    public void aload(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
+    }
+
+    public void store(final int var, final Type type) {
+        mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), var);
+    }
+
+    public void astore(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
+    }
+
+    public void pop() {
+        mv.visitInsn(Opcodes.POP);
+    }
+
+    public void pop2() {
+        mv.visitInsn(Opcodes.POP2);
+    }
+
+    public void dup() {
+        mv.visitInsn(Opcodes.DUP);
+    }
+
+    public void dup2() {
+        mv.visitInsn(Opcodes.DUP2);
+    }
+
+    public void dupX1() {
+        mv.visitInsn(Opcodes.DUP_X1);
+    }
+
+    public void dupX2() {
+        mv.visitInsn(Opcodes.DUP_X2);
+    }
+
+    public void dup2X1() {
+        mv.visitInsn(Opcodes.DUP2_X1);
+    }
+
+    public void dup2X2() {
+        mv.visitInsn(Opcodes.DUP2_X2);
+    }
+
+    public void swap() {
+        mv.visitInsn(Opcodes.SWAP);
+    }
+
+    public void add(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IADD));
+    }
+
+    public void sub(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.ISUB));
+    }
+
+    public void mul(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IMUL));
+    }
+
+    public void div(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IDIV));
+    }
+
+    public void rem(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IREM));
+    }
+
+    public void neg(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.INEG));
+    }
+
+    public void shl(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.ISHL));
+    }
+
+    public void shr(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.ISHR));
+    }
+
+    public void ushr(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IUSHR));
+    }
+
+    public void and(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IAND));
+    }
+
+    public void or(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IOR));
+    }
+
+    public void xor(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IXOR));
+    }
+
+    public void iinc(final int var, final int increment) {
+        mv.visitIincInsn(var, increment);
+    }
+
+    public void cast(final Type from, final Type to) {
+        if (from != to) {
+            if (from == Type.DOUBLE_TYPE) {
+                if (to == Type.FLOAT_TYPE) {
+                    mv.visitInsn(Opcodes.D2F);
+                } else if (to == Type.LONG_TYPE) {
+                    mv.visitInsn(Opcodes.D2L);
+                } else {
+                    mv.visitInsn(Opcodes.D2I);
+                    cast(Type.INT_TYPE, to);
+                }
+            } else if (from == Type.FLOAT_TYPE) {
+                if (to == Type.DOUBLE_TYPE) {
+                    mv.visitInsn(Opcodes.F2D);
+                } else if (to == Type.LONG_TYPE) {
+                    mv.visitInsn(Opcodes.F2L);
+                } else {
+                    mv.visitInsn(Opcodes.F2I);
+                    cast(Type.INT_TYPE, to);
+                }
+            } else if (from == Type.LONG_TYPE) {
+                if (to == Type.DOUBLE_TYPE) {
+                    mv.visitInsn(Opcodes.L2D);
+                } else if (to == Type.FLOAT_TYPE) {
+                    mv.visitInsn(Opcodes.L2F);
+                } else {
+                    mv.visitInsn(Opcodes.L2I);
+                    cast(Type.INT_TYPE, to);
+                }
+            } else {
+                if (to == Type.BYTE_TYPE) {
+                    mv.visitInsn(Opcodes.I2B);
+                } else if (to == Type.CHAR_TYPE) {
+                    mv.visitInsn(Opcodes.I2C);
+                } else if (to == Type.DOUBLE_TYPE) {
+                    mv.visitInsn(Opcodes.I2D);
+                } else if (to == Type.FLOAT_TYPE) {
+                    mv.visitInsn(Opcodes.I2F);
+                } else if (to == Type.LONG_TYPE) {
+                    mv.visitInsn(Opcodes.I2L);
+                } else if (to == Type.SHORT_TYPE) {
+                    mv.visitInsn(Opcodes.I2S);
+                }
+            }
+        }
+    }
+
+    public void lcmp() {
+        mv.visitInsn(Opcodes.LCMP);
+    }
+
+    public void cmpl(final Type type) {
+        mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPL : Opcodes.DCMPL);
+    }
+
+    public void cmpg(final Type type) {
+        mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPG : Opcodes.DCMPG);
+    }
+
+    public void ifeq(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFEQ, label);
+    }
+
+    public void ifne(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFNE, label);
+    }
+
+    public void iflt(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFLT, label);
+    }
+
+    public void ifge(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFGE, label);
+    }
+
+    public void ifgt(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFGT, label);
+    }
+
+    public void ifle(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFLE, label);
+    }
+
+    public void ificmpeq(final Label label) {
+        mv.visitJumpInsn(Opcodes.IF_ICMPEQ, label);
+    }
+
+    public void ificmpne(final Label label) {
+        mv.visitJumpInsn(Opcodes.IF_ICMPNE, label);
+    }
+
+    public void ificmplt(final Label label) {
+        mv.visitJumpInsn(Opcodes.IF_ICMPLT, label);
+    }
+
+    public void ificmpge(final Label label) {
+        mv.visitJumpInsn(Opcodes.IF_ICMPGE, label);
+    }
+
+    public void ificmpgt(final Label label) {
+        mv.visitJumpInsn(Opcodes.IF_ICMPGT, label);
+    }
+
+    public void ificmple(final Label label) {
+        mv.visitJumpInsn(Opcodes.IF_ICMPLE, label);
+    }
+
+    public void ifacmpeq(final Label label) {
+        mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
+    }
+
+    public void ifacmpne(final Label label) {
+        mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
+    }
+
+    public void goTo(final Label label) {
+        mv.visitJumpInsn(Opcodes.GOTO, label);
+    }
+
+    public void jsr(final Label label) {
+        mv.visitJumpInsn(Opcodes.JSR, label);
+    }
+
+    public void ret(final int var) {
+        mv.visitVarInsn(Opcodes.RET, var);
+    }
+
+    public void tableswitch(final int min, final int max, final Label dflt,
+            final Label... labels) {
+        mv.visitTableSwitchInsn(min, max, dflt, labels);
+    }
+
+    public void lookupswitch(final Label dflt, final int[] keys,
+            final Label[] labels) {
+        mv.visitLookupSwitchInsn(dflt, keys, labels);
+    }
+
+    public void areturn(final Type t) {
+        mv.visitInsn(t.getOpcode(Opcodes.IRETURN));
+    }
+
+    public void getstatic(final String owner, final String name,
+            final String desc) {
+        mv.visitFieldInsn(Opcodes.GETSTATIC, owner, name, desc);
+    }
+
+    public void putstatic(final String owner, final String name,
+            final String desc) {
+        mv.visitFieldInsn(Opcodes.PUTSTATIC, owner, name, desc);
+    }
+
+    public void getfield(final String owner, final String name,
+            final String desc) {
+        mv.visitFieldInsn(Opcodes.GETFIELD, owner, name, desc);
+    }
+
+    public void putfield(final String owner, final String name,
+            final String desc) {
+        mv.visitFieldInsn(Opcodes.PUTFIELD, owner, name, desc);
+    }
+
+    @Deprecated
+    public void invokevirtual(final String owner, final String name,
+            final String desc) {
+        if (api >= Opcodes.ASM5) {
+            invokevirtual(owner, name, desc, false);
+            return;
+        }
+        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc);
+    }
+
+    public void invokevirtual(final String owner, final String name,
+            final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            if (itf) {
+                throw new IllegalArgumentException(
+                        "INVOKEVIRTUAL on interfaces require ASM 5");
+            }
+            invokevirtual(owner, name, desc);
+            return;
+        }
+        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, itf);
+    }
+
+    @Deprecated
+    public void invokespecial(final String owner, final String name,
+            final String desc) {
+        if (api >= Opcodes.ASM5) {
+            invokespecial(owner, name, desc, false);
+            return;
+        }
+        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, false);
+    }
+
+    public void invokespecial(final String owner, final String name,
+            final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            if (itf) {
+                throw new IllegalArgumentException(
+                        "INVOKESPECIAL on interfaces require ASM 5");
+            }
+            invokespecial(owner, name, desc);
+            return;
+        }
+        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, itf);
+    }
+
+    @Deprecated
+    public void invokestatic(final String owner, final String name,
+            final String desc) {
+        if (api >= Opcodes.ASM5) {
+            invokestatic(owner, name, desc, false);
+            return;
+        }
+        mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, false);
+    }
+
+    public void invokestatic(final String owner, final String name,
+            final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            if (itf) {
+                throw new IllegalArgumentException(
+                        "INVOKESTATIC on interfaces require ASM 5");
+            }
+            invokestatic(owner, name, desc);
+            return;
+        }
+        mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, itf);
+    }
+
+    public void invokeinterface(final String owner, final String name,
+            final String desc) {
+        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, desc, true);
+    }
+
+    public void invokedynamic(String name, String desc, Handle bsm,
+            Object[] bsmArgs) {
+        mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+    }
+
+    public void anew(final Type type) {
+        mv.visitTypeInsn(Opcodes.NEW, type.getInternalName());
+    }
+
+    public void newarray(final Type type) {
+        int typ;
+        switch (type.getSort()) {
+        case Type.BOOLEAN:
+            typ = Opcodes.T_BOOLEAN;
+            break;
+        case Type.CHAR:
+            typ = Opcodes.T_CHAR;
+            break;
+        case Type.BYTE:
+            typ = Opcodes.T_BYTE;
+            break;
+        case Type.SHORT:
+            typ = Opcodes.T_SHORT;
+            break;
+        case Type.INT:
+            typ = Opcodes.T_INT;
+            break;
+        case Type.FLOAT:
+            typ = Opcodes.T_FLOAT;
+            break;
+        case Type.LONG:
+            typ = Opcodes.T_LONG;
+            break;
+        case Type.DOUBLE:
+            typ = Opcodes.T_DOUBLE;
+            break;
+        default:
+            mv.visitTypeInsn(Opcodes.ANEWARRAY, type.getInternalName());
+            return;
+        }
+        mv.visitIntInsn(Opcodes.NEWARRAY, typ);
+    }
+
+    public void arraylength() {
+        mv.visitInsn(Opcodes.ARRAYLENGTH);
+    }
+
+    public void athrow() {
+        mv.visitInsn(Opcodes.ATHROW);
+    }
+
+    public void checkcast(final Type type) {
+        mv.visitTypeInsn(Opcodes.CHECKCAST, type.getInternalName());
+    }
+
+    public void instanceOf(final Type type) {
+        mv.visitTypeInsn(Opcodes.INSTANCEOF, type.getInternalName());
+    }
+
+    public void monitorenter() {
+        mv.visitInsn(Opcodes.MONITORENTER);
+    }
+
+    public void monitorexit() {
+        mv.visitInsn(Opcodes.MONITOREXIT);
+    }
+
+    public void multianewarray(final String desc, final int dims) {
+        mv.visitMultiANewArrayInsn(desc, dims);
+    }
+
+    public void ifnull(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFNULL, label);
+    }
+
+    public void ifnonnull(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFNONNULL, label);
+    }
+
+    public void mark(final Label label) {
+        mv.visitLabel(label);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
index 21f1d68..08e1f3c 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
@@ -29,32 +29,47 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.commons;
 
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 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.tree.*;
-
-import java.util.*;
+import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.InsnList;
+import org.apache.tapestry5.internal.plastic.asm.tree.InsnNode;
+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.LocalVariableNode;
+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;
 
 /**
  * A {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor} that removes JSR instructions and
  * inlines the referenced subroutines.
- *
+ * 
  * <b>Explanation of how it works</b> TODO
- *
+ * 
  * @author Niko Matsakis
  */
-public class JSRInlinerAdapter extends MethodNode implements Opcodes
-{
+public class JSRInlinerAdapter extends MethodNode implements Opcodes {
 
     private static final boolean LOGGING = false;
 
     /**
-     * For each label that is jumped to by a JSR, we create a BitSet
-     * instance.
+     * For each label that is jumped to by a JSR, we create a BitSet instance.
      */
-    private final Map<LabelNode,BitSet> subroutineHeads = new HashMap<LabelNode,BitSet>();
+    private final Map<LabelNode, BitSet> subroutineHeads = new HashMap<LabelNode, BitSet>();
 
     /**
      * This subroutine instance denotes the line of execution that is not
@@ -72,58 +87,65 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
     /**
      * Creates a new JSRInliner. <i>Subclasses must not use this
      * constructor</i>. Instead, they must use the
-     * {@link #JSRInlinerAdapter(int, org.apache.tapestry5.internal.plastic.asm.MethodVisitor, int, String, String, String, String[])}
+     * {@link #JSRInlinerAdapter(int, MethodVisitor, int, String, String, String, String[])}
      * version.
-     *
-     * @param mv the <code>MethodVisitor</code> to send the resulting inlined
-     *        method code to (use <code>null</code> for none).
-     * @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>.
+     * 
+     * @param mv
+     *            the <code>MethodVisitor</code> to send the resulting inlined
+     *            method code to (use <code>null</code> for none).
+     * @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 JSRInlinerAdapter(
-        final MethodVisitor mv,
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final String[] exceptions)
-    {
-        this(Opcodes.ASM4, mv, access, name, desc, signature, exceptions);
+    public JSRInlinerAdapter(final MethodVisitor mv, final int access,
+            final String name, final String desc, final String signature,
+            final String[] exceptions) {
+        this(Opcodes.ASM5, mv, access, name, desc, signature, exceptions);
+        if (getClass() != JSRInlinerAdapter.class) {
+            throw new IllegalStateException();
+        }
     }
 
     /**
      * Creates a new JSRInliner.
-     *
-     * @param api the ASM API version implemented by this visitor. Must be one
-     *        of {@link Opcodes#ASM4}.
-     * @param mv the <code>MethodVisitor</code> to send the resulting inlined
-     *        method code to (use <code>null</code> for none).
-     * @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>.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param mv
+     *            the <code>MethodVisitor</code> to send the resulting inlined
+     *            method code to (use <code>null</code> for none).
+     * @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>.
      */
-    protected JSRInlinerAdapter(
-        final int api,
-        final MethodVisitor mv,
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final String[] exceptions)
-    {
+    protected JSRInlinerAdapter(final int api, final MethodVisitor mv,
+            final int access, final String name, final String desc,
+            final String signature, final String[] exceptions) {
         super(api, access, name, desc, signature, exceptions);
         this.mv = mv;
     }
@@ -179,9 +201,9 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
 
         // Go through the head of each subroutine and find any nodes reachable
         // to that subroutine without following any JSR links.
-        for (Iterator<Map.Entry<LabelNode,BitSet>> it = subroutineHeads.entrySet().iterator(); it.hasNext();)
-        {
-            Map.Entry<LabelNode,BitSet> entry = it.next();
+        for (Iterator<Map.Entry<LabelNode, BitSet>> it = subroutineHeads
+                .entrySet().iterator(); it.hasNext();) {
+            Map.Entry<LabelNode, BitSet> entry = it.next();
             LabelNode lab = entry.getKey();
             BitSet sub = entry.getValue();
             int index = instructions.indexOf(lab);
@@ -191,24 +213,22 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
 
     /**
      * Performs a depth first search walking the normal byte code path starting
-     * at <code>index</code>, and adding each instruction encountered into
-     * the subroutine <code>sub</code>. After this walk is complete, iterates
-     * over the exception handlers to ensure that we also include those byte
-     * codes which are reachable through an exception that may be thrown during
-     * the execution of the subroutine. Invoked from
-     * <code>markSubroutines()</code>.
-     *
-     * @param sub the subroutine whose instructions must be computed.
-     * @param index an instruction of this subroutine.
-     * @param anyvisited indexes of the already visited instructions, i.e.
-     *        marked as part of this subroutine or any previously computed
-     *        subroutine.
+     * at <code>index</code>, and adding each instruction encountered into the
+     * subroutine <code>sub</code>. After this walk is complete, iterates over
+     * the exception handlers to ensure that we also include those byte codes
+     * which are reachable through an exception that may be thrown during the
+     * execution of the subroutine. Invoked from <code>markSubroutines()</code>.
+     * 
+     * @param sub
+     *            the subroutine whose instructions must be computed.
+     * @param index
+     *            an instruction of this subroutine.
+     * @param anyvisited
+     *            indexes of the already visited instructions, i.e. marked as
+     *            part of this subroutine or any previously computed subroutine.
      */
-    private void markSubroutineWalk(
-        final BitSet sub,
-        final int index,
-        final BitSet anyvisited)
-    {
+    private void markSubroutineWalk(final BitSet sub, final int index,
+            final BitSet anyvisited) {
         if (LOGGING) {
             log("markSubroutineWalk: sub=" + sub + " index=" + index);
         }
@@ -220,7 +240,8 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
         boolean loop = true;
         while (loop) {
             loop = false;
-            for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it.hasNext();) {
+            for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it
+                    .hasNext();) {
                 TryCatchBlockNode trycatch = it.next();
 
                 if (LOGGING) {
@@ -252,20 +273,19 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
 
     /**
      * Performs a simple DFS of the instructions, assigning each to the
-     * subroutine <code>sub</code>. Starts from <code>index</code>.
-     * Invoked only by <code>markSubroutineWalk()</code>.
-     *
-     * @param sub the subroutine whose instructions must be computed.
-     * @param index an instruction of this subroutine.
-     * @param anyvisited indexes of the already visited instructions, i.e.
-     *        marked as part of this subroutine or any previously computed
-     *        subroutine.
+     * subroutine <code>sub</code>. Starts from <code>index</code>. Invoked only
+     * by <code>markSubroutineWalk()</code>.
+     * 
+     * @param sub
+     *            the subroutine whose instructions must be computed.
+     * @param index
+     *            an instruction of this subroutine.
+     * @param anyvisited
+     *            indexes of the already visited instructions, i.e. marked as
+     *            part of this subroutine or any previously computed subroutine.
      */
-    private void markSubroutineWalkDFS(
-        final BitSet sub,
-        int index,
-        final BitSet anyvisited)
-    {
+    private void markSubroutineWalkDFS(final BitSet sub, int index,
+            final BitSet anyvisited) {
         while (true) {
             AbstractInsnNode node = instructions.get(index);
 
@@ -285,8 +305,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
             anyvisited.set(index);
 
             if (node.getType() == AbstractInsnNode.JUMP_INSN
-                    && node.getOpcode() != JSR)
-            {
+                    && node.getOpcode() != JSR) {
                 // we do not follow recursively called subroutines here; but any
                 // other sort of branch we do follow
                 JumpInsnNode jnode = (JumpInsnNode) node;
@@ -317,27 +336,38 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
             // check to see if this opcode falls through to the next instruction
             // or not; if not, return.
             switch (instructions.get(index).getOpcode()) {
-                case GOTO:
-                case RET:
-                case TABLESWITCH:
-                case LOOKUPSWITCH:
-                case IRETURN:
-                case LRETURN:
-                case FRETURN:
-                case DRETURN:
-                case ARETURN:
-                case RETURN:
-                case ATHROW:
-                    /*
-                     * note: this either returns from this subroutine, or a
-                     * parent subroutine which invoked it
-                     */
-                    return;
+            case GOTO:
+            case RET:
+            case TABLESWITCH:
+            case LOOKUPSWITCH:
+            case IRETURN:
+            case LRETURN:
+            case FRETURN:
+            case DRETURN:
+            case ARETURN:
+            case RETURN:
+            case ATHROW:
+                /*
+                 * note: this either returns from this subroutine, or a parent
+                 * subroutine which invoked it
+                 */
+                return;
             }
 
             // Use tail recursion here in the form of an outer while loop to
             // avoid our stack growing needlessly:
             index++;
+
+            // We implicitly assumed above that execution can always fall
+            // through to the next instruction after a JSR. But a subroutine may
+            // never return, in which case the code after the JSR is unreachable
+            // and can be anything. In particular, it can seem to fall off the
+            // end of the method, so we must handle this case here (we could
+            // instead detect whether execution can return or not from a JSR,
+            // but this is more complicated).
+            if (index >= instructions.size()) {
+                return;
+            }
         }
     }
 
@@ -358,10 +388,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
         List<LocalVariableNode> newLocalVariables = new ArrayList<LocalVariableNode>();
         while (!worklist.isEmpty()) {
             Instantiation inst = worklist.removeFirst();
-            emitSubroutine(inst,
-                    worklist,
-                    newInstructions,
-                    newTryCatchBlocks,
+            emitSubroutine(inst, worklist, newInstructions, newTryCatchBlocks,
                     newLocalVariables);
         }
         instructions = newInstructions;
@@ -371,24 +398,25 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
 
     /**
      * Emits one instantiation of one subroutine, specified by
-     * <code>instant</code>. May add new instantiations that are invoked by
-     * this one to the <code>worklist</code> parameter, and new try/catch
-     * blocks to <code>newTryCatchBlocks</code>.
-     *
-     * @param instant the instantiation that must be performed.
-     * @param worklist list of the instantiations that remain to be done.
-     * @param newInstructions the instruction list to which the instantiated
-     *        code must be appended.
-     * @param newTryCatchBlocks the exception handler list to which the
-     *        instantiated handlers must be appended.
+     * <code>instant</code>. May add new instantiations that are invoked by this
+     * one to the <code>worklist</code> parameter, and new try/catch blocks to
+     * <code>newTryCatchBlocks</code>.
+     * 
+     * @param instant
+     *            the instantiation that must be performed.
+     * @param worklist
+     *            list of the instantiations that remain to be done.
+     * @param newInstructions
+     *            the instruction list to which the instantiated code must be
+     *            appended.
+     * @param newTryCatchBlocks
+     *            the exception handler list to which the instantiated handlers
+     *            must be appended.
      */
-    private void emitSubroutine(
-        final Instantiation instant,
-        final List<Instantiation> worklist,
-        final InsnList newInstructions,
-        final List<TryCatchBlockNode> newTryCatchBlocks,
-        final List<LocalVariableNode> newLocalVariables)
-    {
+    private void emitSubroutine(final Instantiation instant,
+            final List<Instantiation> worklist, final InsnList newInstructions,
+            final List<TryCatchBlockNode> newTryCatchBlocks,
+            final List<LocalVariableNode> newLocalVariables) {
         LabelNode duplbl = null;
 
         if (LOGGING) {
@@ -485,7 +513,8 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
         }
 
         // Emit try/catch blocks that are relevant to this method.
-        for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it.hasNext();) {
+        for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it
+                .hasNext();) {
             TryCatchBlockNode trycatch = it.next();
 
             if (LOGGING) {
@@ -517,13 +546,12 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
                 throw new RuntimeException("Internal error!");
             }
 
-            newTryCatchBlocks.add(new TryCatchBlockNode(start,
-                    end,
-                    handler,
+            newTryCatchBlocks.add(new TryCatchBlockNode(start, end, handler,
                     trycatch.type));
         }
 
-        for (Iterator<LocalVariableNode> it = localVariables.iterator(); it.hasNext();) {
+        for (Iterator<LocalVariableNode> it = localVariables.iterator(); it
+                .hasNext();) {
             LocalVariableNode lvnode = it.next();
             if (LOGGING) {
                 log("local var " + lvnode.name);
@@ -537,11 +565,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
                 continue;
             }
             newLocalVariables.add(new LocalVariableNode(lvnode.name,
-                    lvnode.desc,
-                    lvnode.signature,
-                    start,
-                    end,
-                    lvnode.index));
+                    lvnode.desc, lvnode.signature, start, end, lvnode.index));
         }
     }
 
@@ -574,14 +598,14 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
          * This table maps Labels from the original source to Labels pointing at
          * code specific to this instantiation, for use in remapping try/catch
          * blocks,as well as gotos.
-         *
+         * 
          * Note that in the presence of dual citizens instructions, that is,
          * instructions which belong to more than one subroutine due to the
          * merging of control flow without a RET instruction, we will map the
          * target label of a GOTO to the label used by the instantiation lowest
          * on the stack. This avoids code duplication during inlining in most
          * cases.
-         *
+         * 
          * @see #findOwner(int)
          */
         public final Map<LabelNode, LabelNode> rangeTable = new HashMap<LabelNode, LabelNode>();
@@ -644,21 +668,22 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
          * Returns the "owner" of a particular instruction relative to this
          * instantiation: the owner referes to the Instantiation which will emit
          * the version of this instruction that we will execute.
-         *
+         * 
          * Typically, the return value is either <code>this</code> or
          * <code>null</code>. <code>this</code> indicates that this
          * instantiation will generate the version of this instruction that we
-         * will execute, and <code>null</code> indicates that this
-         * instantiation never executes the given instruction.
-         *
+         * will execute, and <code>null</code> indicates that this instantiation
+         * never executes the given instruction.
+         * 
          * Sometimes, however, an instruction can belong to multiple
          * subroutines; this is called a "dual citizen" instruction (though it
          * may belong to more than 2 subroutines), and occurs when multiple
          * subroutines branch to common points of control. In this case, the
          * owner is the subroutine that appears lowest on the stack, and which
          * also owns the instruction in question.
-         *
-         * @param i the index of the instruction in the original code
+         * 
+         * @param i
+         *            the index of the instruction in the original code
          * @return the "owner" of a particular instruction relative to this
          *         instantiation.
          */
@@ -679,12 +704,13 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
         }
 
         /**
-         * Looks up the label <code>l</code> in the <code>gotoTable</code>,
-         * thus translating it from a Label in the original code, to a Label in
-         * the inlined code that is appropriate for use by an instruction that
+         * Looks up the label <code>l</code> in the <code>gotoTable</code>, thus
+         * translating it from a Label in the original code, to a Label in the
+         * inlined code that is appropriate for use by an instruction that
          * branched to the original label.
-         *
-         * @param l The label we will be translating
+         * 
+         * @param l
+         *            The label we will be translating
          * @return a label for use by a branch instruction in the inlined code
          * @see #rangeLabel
          */
@@ -700,8 +726,9 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
          * thus translating it from a Label in the original code, to a Label in
          * the inlined code that is appropriate for use by an try/catch or
          * variable use annotation.
-         *
-         * @param l The label we will be translating
+         * 
+         * @param l
+         *            The label we will be translating
          * @return a label for use by a try/catch or variable annotation in the
          *         original code
          * @see #rangeTable

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java
new file mode 100644
index 0000000..3a21047
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java
@@ -0,0 +1,381 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+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 {@link MethodVisitor} that renumbers local variables in their order of
+ * appearance. This adapter allows one to easily add new local variables to a
+ * method. It may be used by inheriting from this class, but the preferred way
+ * of using it is via delegation: the next visitor in the chain can indeed add
+ * new locals when needed by calling {@link #newLocal} on this adapter (this
+ * requires a reference back to this {@link LocalVariablesSorter}).
+ * 
+ * @author Chris Nokleberg
+ * @author Eugene Kuleshov
+ * @author Eric Bruneton
+ */
+public class LocalVariablesSorter extends MethodVisitor {
+
+    private static final Type OBJECT_TYPE = Type
+            .getObjectType("java/lang/Object");
+
+    /**
+     * Mapping from old to new local variable indexes. A local variable at index
+     * i of size 1 is remapped to 'mapping[2*i]', while a local variable at
+     * index i of size 2 is remapped to 'mapping[2*i+1]'.
+     */
+    private int[] mapping = new int[40];
+
+    /**
+     * Array used to store stack map local variable types after remapping.
+     */
+    private Object[] newLocals = new Object[20];
+
+    /**
+     * Index of the first local variable, after formal parameters.
+     */
+    protected final int firstLocal;
+
+    /**
+     * Index of the next local variable to be created by {@link #newLocal}.
+     */
+    protected int nextLocal;
+
+    /**
+     * Indicates if at least one local variable has moved due to remapping.
+     */
+    private boolean changed;
+
+    /**
+     * Creates a new {@link LocalVariablesSorter}. <i>Subclasses must not use
+     * this constructor</i>. Instead, they must use the
+     * {@link #LocalVariablesSorter(int, int, String, MethodVisitor)} version.
+     * 
+     * @param access
+     *            access flags of the adapted method.
+     * @param desc
+     *            the method's descriptor (see {@link Type Type}).
+     * @param mv
+     *            the method visitor to which this adapter delegates calls.
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public LocalVariablesSorter(final int access, final String desc,
+            final MethodVisitor mv) {
+        this(Opcodes.ASM5, access, desc, mv);
+        if (getClass() != LocalVariablesSorter.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Creates a new {@link LocalVariablesSorter}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param access
+     *            access flags of the adapted method.
+     * @param desc
+     *            the method's descriptor (see {@link Type Type}).
+     * @param mv
+     *            the method visitor to which this adapter delegates calls.
+     */
+    protected LocalVariablesSorter(final int api, final int access,
+            final String desc, final MethodVisitor mv) {
+        super(api, mv);
+        Type[] args = Type.getArgumentTypes(desc);
+        nextLocal = (Opcodes.ACC_STATIC & access) == 0 ? 1 : 0;
+        for (int i = 0; i < args.length; i++) {
+            nextLocal += args[i].getSize();
+        }
+        firstLocal = nextLocal;
+    }
+
+    @Override
+    public void visitVarInsn(final int opcode, final int var) {
+        Type type;
+        switch (opcode) {
+        case Opcodes.LLOAD:
+        case Opcodes.LSTORE:
+            type = Type.LONG_TYPE;
+            break;
+
+        case Opcodes.DLOAD:
+        case Opcodes.DSTORE:
+            type = Type.DOUBLE_TYPE;
+            break;
+
+        case Opcodes.FLOAD:
+        case Opcodes.FSTORE:
+            type = Type.FLOAT_TYPE;
+            break;
+
+        case Opcodes.ILOAD:
+        case Opcodes.ISTORE:
+            type = Type.INT_TYPE;
+            break;
+
+        default:
+            // case Opcodes.ALOAD:
+            // case Opcodes.ASTORE:
+            // case RET:
+            type = OBJECT_TYPE;
+            break;
+        }
+        mv.visitVarInsn(opcode, remap(var, type));
+    }
+
+    @Override
+    public void visitIincInsn(final int var, final int increment) {
+        mv.visitIincInsn(remap(var, Type.INT_TYPE), increment);
+    }
+
+    @Override
+    public void visitMaxs(final int maxStack, final int maxLocals) {
+        mv.visitMaxs(maxStack, nextLocal);
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
+        int newIndex = remap(index, Type.getType(desc));
+        mv.visitLocalVariable(name, desc, signature, start, end, newIndex);
+    }
+
+    @Override
+    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+            TypePath typePath, Label[] start, Label[] end, int[] index,
+            String desc, boolean visible) {
+        Type t = Type.getType(desc);
+        int[] newIndex = new int[index.length];
+        for (int i = 0; i < newIndex.length; ++i) {
+            newIndex[i] = remap(index[i], t);
+        }
+        return mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
+                newIndex, desc, visible);
+    }
+
+    @Override
+    public void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack) {
+        if (type != Opcodes.F_NEW) { // uncompressed frame
+            throw new IllegalStateException(
+                    "ClassReader.accept() should be called with EXPAND_FRAMES flag");
+        }
+
+        if (!changed) { // optimization for the case where mapping = identity
+            mv.visitFrame(type, nLocal, local, nStack, stack);
+            return;
+        }
+
+        // creates a copy of newLocals
+        Object[] oldLocals = new Object[newLocals.length];
+        System.arraycopy(newLocals, 0, oldLocals, 0, oldLocals.length);
+
+        updateNewLocals(newLocals);
+
+        // copies types from 'local' to 'newLocals'
+        // 'newLocals' already contains the variables added with 'newLocal'
+
+        int index = 0; // old local variable index
+        int number = 0; // old local variable number
+        for (; number < nLocal; ++number) {
+            Object t = local[number];
+            int size = t == Opcodes.LONG || t == Opcodes.DOUBLE ? 2 : 1;
+            if (t != Opcodes.TOP) {
+                Type typ = OBJECT_TYPE;
+                if (t == Opcodes.INTEGER) {
+                    typ = Type.INT_TYPE;
+                } else if (t == Opcodes.FLOAT) {
+                    typ = Type.FLOAT_TYPE;
+                } else if (t == Opcodes.LONG) {
+                    typ = Type.LONG_TYPE;
+                } else if (t == Opcodes.DOUBLE) {
+                    typ = Type.DOUBLE_TYPE;
+                } else if (t instanceof String) {
+                    typ = Type.getObjectType((String) t);
+                }
+                setFrameLocal(remap(index, typ), t);
+            }
+            index += size;
+        }
+
+        // removes TOP after long and double types as well as trailing TOPs
+
+        index = 0;
+        number = 0;
+        for (int i = 0; index < newLocals.length; ++i) {
+            Object t = newLocals[index++];
+            if (t != null && t != Opcodes.TOP) {
+                newLocals[i] = t;
+                number = i + 1;
+                if (t == Opcodes.LONG || t == Opcodes.DOUBLE) {
+                    index += 1;
+                }
+            } else {
+                newLocals[i] = Opcodes.TOP;
+            }
+        }
+
+        // visits remapped frame
+        mv.visitFrame(type, number, newLocals, nStack, stack);
+
+        // restores original value of 'newLocals'
+        newLocals = oldLocals;
+    }
+
+    // -------------
+
+    /**
+     * Creates a new local variable of the given type.
+     * 
+     * @param type
+     *            the type of the local variable to be created.
+     * @return the identifier of the newly created local variable.
+     */
+    public int newLocal(final Type type) {
+        Object t;
+        switch (type.getSort()) {
+        case Type.BOOLEAN:
+        case Type.CHAR:
+        case Type.BYTE:
+        case Type.SHORT:
+        case Type.INT:
+            t = Opcodes.INTEGER;
+            break;
+        case Type.FLOAT:
+            t = Opcodes.FLOAT;
+            break;
+        case Type.LONG:
+            t = Opcodes.LONG;
+            break;
+        case Type.DOUBLE:
+            t = Opcodes.DOUBLE;
+            break;
+        case Type.ARRAY:
+            t = type.getDescriptor();
+            break;
+        // case Type.OBJECT:
+        default:
+            t = type.getInternalName();
+            break;
+        }
+        int local = newLocalMapping(type);
+        setLocalType(local, type);
+        setFrameLocal(local, t);
+        changed = true;
+        return local;
+    }
+
+    /**
+     * Notifies subclasses that a new stack map frame is being visited. The
+     * array argument contains the stack map frame types corresponding to the
+     * local variables added with {@link #newLocal}. This method can update
+     * these types in place for the stack map frame being visited. The default
+     * implementation of this method does nothing, i.e. a local variable added
+     * with {@link #newLocal} will have the same type in all stack map frames.
+     * But this behavior is not always the desired one, for instance if a local
+     * variable is added in the middle of a try/catch block: the frame for the
+     * exception handler should have a TOP type for this new local.
+     * 
+     * @param newLocals
+     *            the stack map frame types corresponding to the local variables
+     *            added with {@link #newLocal} (and null for the others). The
+     *            format of this array is the same as in
+     *            {@link MethodVisitor#visitFrame}, except that long and double
+     *            types use two slots. The types for the current stack map frame
+     *            must be updated in place in this array.
+     */
+    protected void updateNewLocals(Object[] newLocals) {
+    }
+
+    /**
+     * Notifies subclasses that a local variable has been added or remapped. The
+     * default implementation of this method does nothing.
+     * 
+     * @param local
+     *            a local variable identifier, as returned by {@link #newLocal
+     *            newLocal()}.
+     * @param type
+     *            the type of the value being stored in the local variable.
+     */
+    protected void setLocalType(final int local, final Type type) {
+    }
+
+    private void setFrameLocal(final int local, final Object type) {
+        int l = newLocals.length;
+        if (local >= l) {
+            Object[] a = new Object[Math.max(2 * l, local + 1)];
+            System.arraycopy(newLocals, 0, a, 0, l);
+            newLocals = a;
+        }
+        newLocals[local] = type;
+    }
+
+    private int remap(final int var, final Type type) {
+        if (var + type.getSize() <= firstLocal) {
+            return var;
+        }
+        int key = 2 * var + type.getSize() - 1;
+        int size = mapping.length;
+        if (key >= size) {
+            int[] newMapping = new int[Math.max(2 * size, key + 1)];
+            System.arraycopy(mapping, 0, newMapping, 0, size);
+            mapping = newMapping;
+        }
+        int value = mapping[key];
+        if (value == 0) {
+            value = newLocalMapping(type);
+            setLocalType(value, type);
+            mapping[key] = value + 1;
+        } else {
+            value--;
+        }
+        if (value != var) {
+            changed = true;
+        }
+        return value;
+    }
+
+    protected int newLocalMapping(final Type type) {
+        int local = nextLocal;
+        nextLocal += type.getSize();
+        return local;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java
new file mode 100644
index 0000000..73c3e96
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java
@@ -0,0 +1,282 @@
+/***
+ * 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.commons;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A named method descriptor.
+ * 
+ * @author Juozas Baliuka
+ * @author Chris Nokleberg
+ * @author Eric Bruneton
+ */
+public class Method {
+
+    /**
+     * The method name.
+     */
+    private final String name;
+
+    /**
+     * The method descriptor.
+     */
+    private final String desc;
+
+    /**
+     * Maps primitive Java type names to their descriptors.
+     */
+    private static final Map<String, String> DESCRIPTORS;
+
+    static {
+        DESCRIPTORS = new HashMap<String, String>();
+        DESCRIPTORS.put("void", "V");
+        DESCRIPTORS.put("byte", "B");
+        DESCRIPTORS.put("char", "C");
+        DESCRIPTORS.put("double", "D");
+        DESCRIPTORS.put("float", "F");
+        DESCRIPTORS.put("int", "I");
+        DESCRIPTORS.put("long", "J");
+        DESCRIPTORS.put("short", "S");
+        DESCRIPTORS.put("boolean", "Z");
+    }
+
+    /**
+     * Creates a new {@link Method}.
+     * 
+     * @param name
+     *            the method's name.
+     * @param desc
+     *            the method's descriptor.
+     */
+    public Method(final String name, final String desc) {
+        this.name = name;
+        this.desc = desc;
+    }
+
+    /**
+     * Creates a new {@link Method}.
+     * 
+     * @param name
+     *            the method's name.
+     * @param returnType
+     *            the method's return type.
+     * @param argumentTypes
+     *            the method's argument types.
+     */
+    public Method(final String name, final Type returnType,
+            final Type[] argumentTypes) {
+        this(name, Type.getMethodDescriptor(returnType, argumentTypes));
+    }
+
+    /**
+     * Creates a new {@link Method}.
+     * 
+     * @param m
+     *            a java.lang.reflect method descriptor
+     * @return a {@link Method} corresponding to the given Java method
+     *         declaration.
+     */
+    public static Method getMethod(java.lang.reflect.Method m) {
+        return new Method(m.getName(), Type.getMethodDescriptor(m));
+    }
+
+    /**
+     * Creates a new {@link Method}.
+     * 
+     * @param c
+     *            a java.lang.reflect constructor descriptor
+     * @return a {@link Method} corresponding to the given Java constructor
+     *         declaration.
+     */
+    public static Method getMethod(java.lang.reflect.Constructor<?> c) {
+        return new Method("<init>", Type.getConstructorDescriptor(c));
+    }
+
+    /**
+     * Returns a {@link Method} corresponding to the given Java method
+     * declaration.
+     * 
+     * @param method
+     *            a Java method declaration, without argument names, of the form
+     *            "returnType name (argumentType1, ... argumentTypeN)", where
+     *            the types are in plain Java (e.g. "int", "float",
+     *            "java.util.List", ...). Classes of the java.lang package can
+     *            be specified by their unqualified name; all other classes
+     *            names must be fully qualified.
+     * @return a {@link Method} corresponding to the given Java method
+     *         declaration.
+     * @throws IllegalArgumentException
+     *             if <code>method</code> could not get parsed.
+     */
+    public static Method getMethod(final String method)
+            throws IllegalArgumentException {
+        return getMethod(method, false);
+    }
+
+    /**
+     * Returns a {@link Method} corresponding to the given Java method
+     * declaration.
+     * 
+     * @param method
+     *            a Java method declaration, without argument names, of the form
+     *            "returnType name (argumentType1, ... argumentTypeN)", where
+     *            the types are in plain Java (e.g. "int", "float",
+     *            "java.util.List", ...). Classes of the java.lang package may
+     *            be specified by their unqualified name, depending on the
+     *            defaultPackage argument; all other classes names must be fully
+     *            qualified.
+     * @param defaultPackage
+     *            true if unqualified class names belong to the default package,
+     *            or false if they correspond to java.lang classes. For instance
+     *            "Object" means "Object" if this option is true, or
+     *            "java.lang.Object" otherwise.
+     * @return a {@link Method} corresponding to the given Java method
+     *         declaration.
+     * @throws IllegalArgumentException
+     *             if <code>method</code> could not get parsed.
+     */
+    public static Method getMethod(final String method,
+            final boolean defaultPackage) throws IllegalArgumentException {
+        int space = method.indexOf(' ');
+        int start = method.indexOf('(', space) + 1;
+        int end = method.indexOf(')', start);
+        if (space == -1 || start == -1 || end == -1) {
+            throw new IllegalArgumentException();
+        }
+        String returnType = method.substring(0, space);
+        String methodName = method.substring(space + 1, start - 1).trim();
+        StringBuffer sb = new StringBuffer();
+        sb.append('(');
+        int p;
+        do {
+            String s;
+            p = method.indexOf(',', start);
+            if (p == -1) {
+                s = map(method.substring(start, end).trim(), defaultPackage);
+            } else {
+                s = map(method.substring(start, p).trim(), defaultPackage);
+                start = p + 1;
+            }
+            sb.append(s);
+        } while (p != -1);
+        sb.append(')');
+        sb.append(map(returnType, defaultPackage));
+        return new Method(methodName, sb.toString());
+    }
+
+    private static String map(final String type, final boolean defaultPackage) {
+        if ("".equals(type)) {
+            return type;
+        }
+
+        StringBuffer sb = new StringBuffer();
+        int index = 0;
+        while ((index = type.indexOf("[]", index) + 1) > 0) {
+            sb.append('[');
+        }
+
+        String t = type.substring(0, type.length() - sb.length() * 2);
+        String desc = DESCRIPTORS.get(t);
+        if (desc != null) {
+            sb.append(desc);
+        } else {
+            sb.append('L');
+            if (t.indexOf('.') < 0) {
+                if (!defaultPackage) {
+                    sb.append("java/lang/");
+                }
+                sb.append(t);
+            } else {
+                sb.append(t.replace('.', '/'));
+            }
+            sb.append(';');
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Returns the name of the method described by this object.
+     * 
+     * @return the name of the method described by this object.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns the descriptor of the method described by this object.
+     * 
+     * @return the descriptor of the method described by this object.
+     */
+    public String getDescriptor() {
+        return desc;
+    }
+
+    /**
+     * Returns the return type of the method described by this object.
+     * 
+     * @return the return type of the method described by this object.
+     */
+    public Type getReturnType() {
+        return Type.getReturnType(desc);
+    }
+
+    /**
+     * Returns the argument types of the method described by this object.
+     * 
+     * @return the argument types of the method described by this object.
+     */
+    public Type[] getArgumentTypes() {
+        return Type.getArgumentTypes(desc);
+    }
+
+    @Override
+    public String toString() {
+        return name + desc;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (!(o instanceof Method)) {
+            return false;
+        }
+        Method other = (Method) o;
+        return name.equals(other.name) && desc.equals(other.desc);
+    }
+
+    @Override
+    public int hashCode() {
+        return name.hashCode() ^ desc.hashCode();
+    }
+}
\ No newline at end of file


[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?"

Posted by ka...@apache.org.
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;
+    }
+}


[23/23] git commit: 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?"

Posted by ka...@apache.org.
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?"

Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/a0ac605d
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/a0ac605d
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/a0ac605d

Branch: refs/heads/5.3
Commit: a0ac605dbd89f543b0396d747f5909e1ba38205b
Parents: 1a03c56
Author: kaosko <ka...@apache.org>
Authored: Tue Mar 25 11:29:43 2014 -0700
Committer: kaosko <ka...@apache.org>
Committed: Tue Mar 25 11:29:43 2014 -0700

----------------------------------------------------------------------
 plastic/LICENSE-ASM-3_3_1.txt                   |   29 -
 plastic/LICENSE-ASM-5_0.txt                     |   29 +
 plastic/NOTICE.txt                              |    4 +-
 .../internal/plastic/asm/AnnotationVisitor.java |   82 +-
 .../internal/plastic/asm/AnnotationWriter.java  |  123 +-
 .../internal/plastic/asm/Attribute.java         |  213 +-
 .../internal/plastic/asm/ByteVector.java        |  168 +-
 .../internal/plastic/asm/ClassReader.java       | 3350 ++++++++++--------
 .../internal/plastic/asm/ClassVisitor.java      |  291 +-
 .../internal/plastic/asm/ClassWriter.java       |  694 ++--
 .../tapestry5/internal/plastic/asm/Context.java |  145 +
 .../tapestry5/internal/plastic/asm/Edge.java    |    2 +-
 .../internal/plastic/asm/FieldVisitor.java      |   75 +-
 .../internal/plastic/asm/FieldWriter.java       |  138 +-
 .../tapestry5/internal/plastic/asm/Frame.java   | 1087 +++---
 .../tapestry5/internal/plastic/asm/Handle.java  |   65 +-
 .../tapestry5/internal/plastic/asm/Handler.java |   13 +-
 .../tapestry5/internal/plastic/asm/Item.java    |  188 +-
 .../tapestry5/internal/plastic/asm/Label.java   |  169 +-
 .../internal/plastic/asm/MethodVisitor.java     |  808 +++--
 .../internal/plastic/asm/MethodWriter.java      | 1535 ++++----
 .../tapestry5/internal/plastic/asm/Opcodes.java |    9 +-
 .../tapestry5/internal/plastic/asm/Type.java    |  333 +-
 .../internal/plastic/asm/TypePath.java          |  193 +
 .../internal/plastic/asm/TypeReference.java     |  452 +++
 .../plastic/asm/commons/AdviceAdapter.java      |  646 ++++
 .../plastic/asm/commons/AnalyzerAdapter.java    |  947 +++++
 .../plastic/asm/commons/CodeSizeEvaluator.java  |  238 ++
 .../plastic/asm/commons/GeneratorAdapter.java   | 1628 +++++++++
 .../plastic/asm/commons/InstructionAdapter.java | 1170 ++++++
 .../plastic/asm/commons/JSRInlinerAdapter.java  |  333 +-
 .../asm/commons/LocalVariablesSorter.java       |  381 ++
 .../internal/plastic/asm/commons/Method.java    |  282 ++
 .../internal/plastic/asm/commons/Remapper.java  |  223 ++
 .../asm/commons/RemappingAnnotationAdapter.java |   79 +
 .../asm/commons/RemappingClassAdapter.java      |  135 +
 .../asm/commons/RemappingFieldAdapter.java      |   71 +
 .../asm/commons/RemappingMethodAdapter.java     |  224 ++
 .../asm/commons/RemappingSignatureAdapter.java  |  155 +
 .../asm/commons/SerialVersionUIDAdder.java      |  540 +++
 .../plastic/asm/commons/SimpleRemapper.java     |   69 +
 .../plastic/asm/commons/StaticInitMerger.java   |   97 +
 .../asm/commons/TableSwitchGenerator.java       |   57 +
 .../asm/commons/TryCatchBlockSorter.java        |   96 +
 .../internal/plastic/asm/commons/package.html   |   48 +
 .../optimizer/AnnotationConstantsCollector.java |  147 +
 .../asm/optimizer/ClassConstantsCollector.java  |  198 ++
 .../plastic/asm/optimizer/ClassOptimizer.java   |  260 ++
 .../plastic/asm/optimizer/Constant.java         |  323 ++
 .../plastic/asm/optimizer/ConstantPool.java     |  249 ++
 .../asm/optimizer/FieldConstantsCollector.java  |   89 +
 .../plastic/asm/optimizer/JarOptimizer.java     |  235 ++
 .../asm/optimizer/MethodConstantsCollector.java |  224 ++
 .../plastic/asm/optimizer/MethodOptimizer.java  |  136 +
 .../plastic/asm/optimizer/NameMapping.java      |  114 +
 .../plastic/asm/optimizer/Shrinker.java         |  283 ++
 .../plastic/asm/optimizer/jdk1.2.2_017.txt.gz   |  Bin 0 -> 113814 bytes
 .../plastic/asm/optimizer/jdk1.3.1_19.txt.gz    |  Bin 0 -> 128067 bytes
 .../asm/optimizer/shrink-annotations.properties |   53 +
 .../asm/optimizer/shrink-frames.properties      |   62 +
 .../asm/optimizer/shrink-resize.properties      |   37 +
 .../asm/optimizer/shrink-signatures.properties  |   43 +
 .../asm/optimizer/shrink-writer.properties      |   66 +
 .../plastic/asm/optimizer/shrink.properties     |  380 ++
 .../plastic/asm/signature/SignatureReader.java  |  191 +-
 .../plastic/asm/signature/SignatureVisitor.java |   88 +-
 .../plastic/asm/signature/SignatureWriter.java  |    6 +-
 .../plastic/asm/tree/AbstractInsnNode.java      |  132 +-
 .../plastic/asm/tree/AnnotationNode.java        |   72 +-
 .../internal/plastic/asm/tree/ClassNode.java    |  199 +-
 .../plastic/asm/tree/FieldInsnNode.java         |   48 +-
 .../internal/plastic/asm/tree/FieldNode.java    |  198 +-
 .../internal/plastic/asm/tree/FrameNode.java    |  141 +-
 .../internal/plastic/asm/tree/IincInsnNode.java |   17 +-
 .../plastic/asm/tree/InnerClassNode.java        |   46 +-
 .../internal/plastic/asm/tree/InsnList.java     |  184 +-
 .../internal/plastic/asm/tree/InsnNode.java     |   46 +-
 .../internal/plastic/asm/tree/IntInsnNode.java  |   26 +-
 .../plastic/asm/tree/InvokeDynamicInsnNode.java |   32 +-
 .../internal/plastic/asm/tree/JumpInsnNode.java |   39 +-
 .../internal/plastic/asm/tree/LabelNode.java    |    4 +-
 .../internal/plastic/asm/tree/LdcInsnNode.java  |   18 +-
 .../plastic/asm/tree/LineNumberNode.java        |   16 +-
 .../asm/tree/LocalVariableAnnotationNode.java   |  157 +
 .../plastic/asm/tree/LocalVariableNode.java     |   51 +-
 .../plastic/asm/tree/LookupSwitchInsnNode.java  |   36 +-
 .../plastic/asm/tree/MethodInsnNode.java        |   77 +-
 .../internal/plastic/asm/tree/MethodNode.java   |  542 ++-
 .../asm/tree/MultiANewArrayInsnNode.java        |   17 +-
 .../plastic/asm/tree/ParameterNode.java         |   76 +
 .../plastic/asm/tree/TableSwitchInsnNode.java   |   41 +-
 .../plastic/asm/tree/TryCatchBlockNode.java     |   97 +-
 .../plastic/asm/tree/TypeAnnotationNode.java    |  100 +
 .../internal/plastic/asm/tree/TypeInsnNode.java |   28 +-
 .../internal/plastic/asm/tree/VarInsnNode.java  |   34 +-
 .../plastic/asm/tree/analysis/Analyzer.java     |  549 +++
 .../asm/tree/analysis/AnalyzerException.java    |   61 +
 .../asm/tree/analysis/BasicInterpreter.java     |  358 ++
 .../plastic/asm/tree/analysis/BasicValue.java   |  111 +
 .../asm/tree/analysis/BasicVerifier.java        |  433 +++
 .../plastic/asm/tree/analysis/Frame.java        |  738 ++++
 .../plastic/asm/tree/analysis/Interpreter.java  |  226 ++
 .../asm/tree/analysis/SimpleVerifier.java       |  320 ++
 .../plastic/asm/tree/analysis/SmallSet.java     |  134 +
 .../asm/tree/analysis/SourceInterpreter.java    |  198 ++
 .../plastic/asm/tree/analysis/SourceValue.java  |   97 +
 .../plastic/asm/tree/analysis/Subroutine.java   |   90 +
 .../plastic/asm/tree/analysis/Value.java        |   45 +
 .../plastic/asm/tree/analysis/package.html      |   67 +
 .../internal/plastic/asm/util/ASMifiable.java   |   19 +-
 .../internal/plastic/asm/util/ASMifier.java     | 1285 +++++++
 .../asm/util/CheckAnnotationAdapter.java        |  136 +
 .../plastic/asm/util/CheckClassAdapter.java     | 1009 ++++++
 .../plastic/asm/util/CheckFieldAdapter.java     |  122 +
 .../plastic/asm/util/CheckMethodAdapter.java    | 1542 ++++++++
 .../plastic/asm/util/CheckSignatureAdapter.java |  330 ++
 .../internal/plastic/asm/util/Printer.java      |  421 ++-
 .../internal/plastic/asm/util/Textifiable.java  |   16 +-
 .../internal/plastic/asm/util/Textifier.java    |  732 ++--
 .../asm/util/TraceAnnotationVisitor.java        |   32 +-
 .../plastic/asm/util/TraceClassVisitor.java     |  158 +-
 .../plastic/asm/util/TraceFieldVisitor.java     |   27 +-
 .../plastic/asm/util/TraceMethodVisitor.java    |  172 +-
 .../plastic/asm/util/TraceSignatureVisitor.java |   70 +-
 .../plastic/asm/xml/ASMContentHandler.java      | 1453 ++++++++
 .../internal/plastic/asm/xml/Processor.java     | 1044 ++++++
 .../internal/plastic/asm/xml/SAXAdapter.java    |   89 +
 .../plastic/asm/xml/SAXAnnotationAdapter.java   |  242 ++
 .../plastic/asm/xml/SAXClassAdapter.java        |  335 ++
 .../plastic/asm/xml/SAXCodeAdapter.java         |  415 +++
 .../plastic/asm/xml/SAXFieldAdapter.java        |   71 +
 .../internal/plastic/asm/xml/asm-xml.dtd        |  349 ++
 .../internal/plastic/asm/xml/package.html       |   96 +
 133 files changed, 31009 insertions(+), 5855 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/LICENSE-ASM-3_3_1.txt
----------------------------------------------------------------------
diff --git a/plastic/LICENSE-ASM-3_3_1.txt b/plastic/LICENSE-ASM-3_3_1.txt
deleted file mode 100644
index c5aba7b..0000000
--- a/plastic/LICENSE-ASM-3_3_1.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-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.

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/LICENSE-ASM-5_0.txt
----------------------------------------------------------------------
diff --git a/plastic/LICENSE-ASM-5_0.txt b/plastic/LICENSE-ASM-5_0.txt
new file mode 100644
index 0000000..c5aba7b
--- /dev/null
+++ b/plastic/LICENSE-ASM-5_0.txt
@@ -0,0 +1,29 @@
+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.

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/NOTICE.txt
----------------------------------------------------------------------
diff --git a/plastic/NOTICE.txt b/plastic/NOTICE.txt
index 96158f5..beec8e0 100644
--- a/plastic/NOTICE.txt
+++ b/plastic/NOTICE.txt
@@ -1,6 +1,6 @@
 This product includes software developed by
 The Apache Software Foundation (http://www.apache.org/).
 
-This product imports and repackages ASM 3.3.1 code which is
-released under the BSD License
+This product imports and repackages ASM 5.0.1 code which is
+released under a BSD style License
 http://asm.ow2.org/license.html

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
index 693b355..1102d54 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
@@ -33,7 +33,7 @@ package org.apache.tapestry5.internal.plastic.asm;
  * A visitor to visit a Java annotation. The methods of this class must be
  * called in the following order: ( <tt>visit</tt> | <tt>visitEnum</tt> |
  * <tt>visitAnnotation</tt> | <tt>visitArray</tt> )* <tt>visitEnd</tt>.
- *
+ * 
  * @author Eric Bruneton
  * @author Eugene Kuleshov
  */
@@ -41,7 +41,7 @@ public abstract class AnnotationVisitor {
 
     /**
      * The ASM API version implemented by this visitor. The value of this field
-     * must be one of {@link Opcodes#ASM4}.
+     * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
      */
     protected final int api;
 
@@ -53,9 +53,10 @@ public abstract class AnnotationVisitor {
 
     /**
      * Constructs a new {@link AnnotationVisitor}.
-     *
-     * @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 AnnotationVisitor(final int api) {
         this(api, null);
@@ -63,31 +64,36 @@ public abstract class AnnotationVisitor {
 
     /**
      * Constructs a new {@link AnnotationVisitor}.
-     *
-     * @param api the ASM API version implemented by this visitor. Must be one
-     *        of {@link Opcodes#ASM4}.
-     * @param av the annotation visitor to which this visitor must delegate
-     *        method calls. May be null.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param av
+     *            the annotation visitor to which this visitor must delegate
+     *            method calls. May be null.
      */
     public AnnotationVisitor(final int api, final AnnotationVisitor av) {
-        /*if (api != Opcodes.ASM4) {
+        if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
             throw new IllegalArgumentException();
-        }*/
+        }
         this.api = api;
         this.av = av;
     }
 
     /**
      * Visits a primitive value of the annotation.
-     *
-     * @param name the value name.
-     * @param value the actual value, whose type must be {@link Byte},
-     *        {@link Boolean}, {@link Character}, {@link Short}, {@link Integer}
-     *        , {@link Long}, {@link Float}, {@link Double}, {@link String} or
-     *        {@link Type} or OBJECT or ARRAY sort. This value can also be an
-     *        array of byte, boolean, short, char, int, long, float or double
-     *        values (this is equivalent to using {@link #visitArray visitArray}
-     *        and visiting each array element in turn, but is more convenient).
+     * 
+     * @param name
+     *            the value name.
+     * @param value
+     *            the actual value, whose type must be {@link Byte},
+     *            {@link Boolean}, {@link Character}, {@link Short},
+     *            {@link Integer} , {@link Long}, {@link Float}, {@link Double},
+     *            {@link String} or {@link Type} or OBJECT or ARRAY sort. This
+     *            value can also be an array of byte, boolean, short, char, int,
+     *            long, float or double values (this is equivalent to using
+     *            {@link #visitArray visitArray} and visiting each array element
+     *            in turn, but is more convenient).
      */
     public void visit(String name, Object value) {
         if (av != null) {
@@ -97,10 +103,13 @@ public abstract class AnnotationVisitor {
 
     /**
      * Visits an enumeration value of the annotation.
-     *
-     * @param name the value name.
-     * @param desc the class descriptor of the enumeration class.
-     * @param value the actual enumeration value.
+     * 
+     * @param name
+     *            the value name.
+     * @param desc
+     *            the class descriptor of the enumeration class.
+     * @param value
+     *            the actual enumeration value.
      */
     public void visitEnum(String name, String desc, String value) {
         if (av != null) {
@@ -110,13 +119,15 @@ public abstract class AnnotationVisitor {
 
     /**
      * Visits a nested annotation value of the annotation.
-     *
-     * @param name the value name.
-     * @param desc the class descriptor of the nested annotation class.
+     * 
+     * @param name
+     *            the value name.
+     * @param desc
+     *            the class descriptor of the nested annotation class.
      * @return a visitor to visit the actual nested annotation value, or
-     *         <tt>null</tt> if this visitor is not interested in visiting
-     *         this nested annotation. <i>The nested annotation value must be
-     *         fully visited before calling other methods on this annotation
+     *         <tt>null</tt> if this visitor is not interested in visiting this
+     *         nested annotation. <i>The nested annotation value must be fully
+     *         visited before calling other methods on this annotation
      *         visitor</i>.
      */
     public AnnotationVisitor visitAnnotation(String name, String desc) {
@@ -131,11 +142,12 @@ public abstract class AnnotationVisitor {
      * types (such as byte, boolean, short, char, int, long, float or double)
      * can be passed as value to {@link #visit visit}. This is what
      * {@link ClassReader} does.
-     *
-     * @param name the value name.
+     * 
+     * @param name
+     *            the value name.
      * @return a visitor to visit the actual array value elements, or
-     *         <tt>null</tt> if this visitor is not interested in visiting
-     *         these values. The 'name' parameters passed to the methods of this
+     *         <tt>null</tt> if this visitor is not interested in visiting these
+     *         values. The 'name' parameters passed to the methods of this
      *         visitor are ignored. <i>All the array values must be visited
      *         before calling other methods on this annotation visitor</i>.
      */

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
index a26f5ca..679aa66 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
 
 /**
  * An {@link AnnotationVisitor} that generates annotations in bytecode form.
- *
+ * 
  * @author Eric Bruneton
  * @author Eugene Kuleshov
  */
@@ -89,22 +89,22 @@ final class AnnotationWriter extends AnnotationVisitor {
 
     /**
      * Constructs a new {@link AnnotationWriter}.
-     *
-     * @param cw the class writer to which this annotation must be added.
-     * @param named <tt>true<tt> if values are named, <tt>false</tt> otherwise.
-     * @param bv where the annotation values must be stored.
-     * @param parent where the number of annotation values must be stored.
-     * @param offset where in <tt>parent</tt> the number of annotation values must
-     *      be stored.
+     * 
+     * @param cw
+     *            the class writer to which this annotation must be added.
+     * @param named
+     *            <tt>true<tt> if values are named, <tt>false</tt> otherwise.
+     * @param bv
+     *            where the annotation values must be stored.
+     * @param parent
+     *            where the number of annotation values must be stored.
+     * @param offset
+     *            where in <tt>parent</tt> the number of annotation values must
+     *            be stored.
      */
-    AnnotationWriter(
-        final ClassWriter cw,
-        final boolean named,
-        final ByteVector bv,
-        final ByteVector parent,
-        final int offset)
-    {
-        super(Opcodes.ASM4);
+    AnnotationWriter(final ClassWriter cw, final boolean named,
+            final ByteVector bv, final ByteVector parent, final int offset) {
+        super(Opcodes.ASM5);
         this.cw = cw;
         this.named = named;
         this.bv = bv;
@@ -190,11 +190,8 @@ final class AnnotationWriter extends AnnotationVisitor {
     }
 
     @Override
-    public void visitEnum(
-        final String name,
-        final String desc,
-        final String value)
-    {
+    public void visitEnum(final String name, final String desc,
+            final String value) {
         ++size;
         if (named) {
             bv.putShort(cw.newUTF8(name));
@@ -203,10 +200,8 @@ final class AnnotationWriter extends AnnotationVisitor {
     }
 
     @Override
-    public AnnotationVisitor visitAnnotation(
-        final String name,
-        final String desc)
-    {
+    public AnnotationVisitor visitAnnotation(final String name,
+            final String desc) {
         ++size;
         if (named) {
             bv.putShort(cw.newUTF8(name));
@@ -242,7 +237,7 @@ final class AnnotationWriter extends AnnotationVisitor {
 
     /**
      * Returns the size of this annotation writer list.
-     *
+     * 
      * @return the size of this annotation writer list.
      */
     int getSize() {
@@ -258,8 +253,9 @@ final class AnnotationWriter extends AnnotationVisitor {
     /**
      * Puts the annotations of this annotation writer list into the given byte
      * vector.
-     *
-     * @param out where the annotations must be put.
+     * 
+     * @param out
+     *            where the annotations must be put.
      */
     void put(final ByteVector out) {
         int n = 0;
@@ -285,16 +281,16 @@ final class AnnotationWriter extends AnnotationVisitor {
 
     /**
      * Puts the given annotation lists into the given byte vector.
-     *
-     * @param panns an array of annotation writer lists.
-     * @param off index of the first annotation to be written.
-     * @param out where the annotations must be put.
+     * 
+     * @param panns
+     *            an array of annotation writer lists.
+     * @param off
+     *            index of the first annotation to be written.
+     * @param out
+     *            where the annotations must be put.
      */
-    static void put(
-        final AnnotationWriter[] panns,
-        final int off,
-        final ByteVector out)
-    {
+    static void put(final AnnotationWriter[] panns, final int off,
+            final ByteVector out) {
         int size = 1 + 2 * (panns.length - off);
         for (int i = off; i < panns.length; ++i) {
             size += panns[i] == null ? 0 : panns[i].getSize();
@@ -319,4 +315,57 @@ final class AnnotationWriter extends AnnotationVisitor {
             }
         }
     }
+
+    /**
+     * Puts the given type reference and type path into the given bytevector.
+     * LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported.
+     * 
+     * @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 out
+     *            where the type reference and type path must be put.
+     */
+    static void putTarget(int typeRef, TypePath typePath, ByteVector out) {
+        switch (typeRef >>> 24) {
+        case 0x00: // CLASS_TYPE_PARAMETER
+        case 0x01: // METHOD_TYPE_PARAMETER
+        case 0x16: // METHOD_FORMAL_PARAMETER
+            out.putShort(typeRef >>> 16);
+            break;
+        case 0x13: // FIELD
+        case 0x14: // METHOD_RETURN
+        case 0x15: // METHOD_RECEIVER
+            out.putByte(typeRef >>> 24);
+            break;
+        case 0x47: // CAST
+        case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+        case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
+        case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+        case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
+            out.putInt(typeRef);
+            break;
+        // case 0x10: // CLASS_EXTENDS
+        // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
+        // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
+        // case 0x17: // THROWS
+        // case 0x42: // EXCEPTION_PARAMETER
+        // case 0x43: // INSTANCEOF
+        // case 0x44: // NEW
+        // case 0x45: // CONSTRUCTOR_REFERENCE
+        // case 0x46: // METHOD_REFERENCE
+        default:
+            out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8);
+            break;
+        }
+        if (typePath == null) {
+            out.putByte(0);
+        } else {
+            int length = typePath.b[typePath.offset] * 2 + 1;
+            out.putByteArray(typePath.b, typePath.offset, length);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
index 8f29872..fae580f 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
 
 /**
  * A non standard class, field, method or code attribute.
- *
+ * 
  * @author Eric Bruneton
  * @author Eugene Kuleshov
  */
@@ -54,8 +54,9 @@ public class Attribute {
 
     /**
      * Constructs a new empty attribute.
-     *
-     * @param type the type of the attribute.
+     * 
+     * @param type
+     *            the type of the attribute.
      */
     protected Attribute(final String type) {
         this.type = type;
@@ -64,7 +65,7 @@ public class Attribute {
     /**
      * Returns <tt>true</tt> if this type of attribute is unknown. The default
      * implementation of this method always returns <tt>true</tt>.
-     *
+     * 
      * @return <tt>true</tt> if this type of attribute is unknown.
      */
     public boolean isUnknown() {
@@ -73,7 +74,7 @@ public class Attribute {
 
     /**
      * Returns <tt>true</tt> if this type of attribute is a code attribute.
-     *
+     * 
      * @return <tt>true</tt> if this type of attribute is a code attribute.
      */
     public boolean isCodeAttribute() {
@@ -82,7 +83,7 @@ public class Attribute {
 
     /**
      * Returns the labels corresponding to this attribute.
-     *
+     * 
      * @return the labels corresponding to this attribute, or <tt>null</tt> if
      *         this attribute is not a code attribute that contains labels.
      */
@@ -91,39 +92,39 @@ public class Attribute {
     }
 
     /**
-     * Reads a {@link #type type} attribute. This method must return a <i>new</i>
-     * {@link Attribute} object, of type {@link #type type}, corresponding to
-     * the <tt>len</tt> bytes starting at the given offset, in the given class
-     * reader.
-     *
-     * @param cr the class that contains the attribute to be read.
-     * @param off index of the first byte of the attribute's content in {@link
-     *        ClassReader#b cr.b}. The 6 attribute header bytes, containing the
-     *        type and the length of the attribute, are not taken into account
-     *        here.
-     * @param len the length of the attribute's content.
-     * @param buf buffer to be used to call
-     *        {@link ClassReader#readUTF8 readUTF8},
-     *        {@link ClassReader#readClass(int,char[]) readClass} or
-     *        {@link ClassReader#readConst readConst}.
-     * @param codeOff index of the first byte of code's attribute content in
-     *        {@link ClassReader#b cr.b}, or -1 if the attribute to be read is
-     *        not a code attribute. The 6 attribute header bytes, containing the
-     *        type and the length of the attribute, are not taken into account
-     *        here.
-     * @param labels the labels of the method's code, or <tt>null</tt> if the
-     *        attribute to be read is not a code attribute.
+     * Reads a {@link #type type} attribute. This method must return a
+     * <i>new</i> {@link Attribute} object, of type {@link #type type},
+     * corresponding to the <tt>len</tt> bytes starting at the given offset, in
+     * the given class reader.
+     * 
+     * @param cr
+     *            the class that contains the attribute to be read.
+     * @param off
+     *            index of the first byte of the attribute's content in
+     *            {@link ClassReader#b cr.b}. The 6 attribute header bytes,
+     *            containing the type and the length of the attribute, are not
+     *            taken into account here.
+     * @param len
+     *            the length of the attribute's content.
+     * @param buf
+     *            buffer to be used to call {@link ClassReader#readUTF8
+     *            readUTF8}, {@link ClassReader#readClass(int,char[]) readClass}
+     *            or {@link ClassReader#readConst readConst}.
+     * @param codeOff
+     *            index of the first byte of code's attribute content in
+     *            {@link ClassReader#b cr.b}, or -1 if the attribute to be read
+     *            is not a code attribute. The 6 attribute header bytes,
+     *            containing the type and the length of the attribute, are not
+     *            taken into account here.
+     * @param labels
+     *            the labels of the method's code, or <tt>null</tt> if the
+     *            attribute to be read is not a code attribute.
      * @return a <i>new</i> {@link Attribute} object corresponding to the given
      *         bytes.
      */
-    protected Attribute read(
-        final ClassReader cr,
-        final int off,
-        final int len,
-        final char[] buf,
-        final int codeOff,
-        final Label[] labels)
-    {
+    protected Attribute read(final ClassReader cr, final int off,
+            final int len, final char[] buf, final int codeOff,
+            final Label[] labels) {
         Attribute attr = new Attribute(type);
         attr.value = new byte[len];
         System.arraycopy(cr.b, off, attr.value, 0, len);
@@ -132,31 +133,31 @@ public class Attribute {
 
     /**
      * Returns the byte array form of this attribute.
-     *
-     * @param cw the class to which this attribute must be added. This parameter
-     *        can be used to add to the constant pool of this class the items
-     *        that corresponds to this attribute.
-     * @param code the bytecode of the method corresponding to this code
-     *        attribute, or <tt>null</tt> if this attribute is not a code
-     *        attributes.
-     * @param len the length of the bytecode of the method corresponding to this
-     *        code attribute, or <tt>null</tt> if this attribute is not a code
-     *        attribute.
-     * @param maxStack the maximum stack size of the method corresponding to
-     *        this code attribute, or -1 if this attribute is not a code
-     *        attribute.
-     * @param maxLocals the maximum number of local variables of the method
-     *        corresponding to this code attribute, or -1 if this attribute is
-     *        not a code attribute.
+     * 
+     * @param cw
+     *            the class to which this attribute must be added. This
+     *            parameter can be used to add to the constant pool of this
+     *            class the items that corresponds to this attribute.
+     * @param code
+     *            the bytecode of the method corresponding to this code
+     *            attribute, or <tt>null</tt> if this attribute is not a code
+     *            attributes.
+     * @param len
+     *            the length of the bytecode of the method corresponding to this
+     *            code attribute, or <tt>null</tt> if this attribute is not a
+     *            code attribute.
+     * @param maxStack
+     *            the maximum stack size of the method corresponding to this
+     *            code attribute, or -1 if this attribute is not a code
+     *            attribute.
+     * @param maxLocals
+     *            the maximum number of local variables of the method
+     *            corresponding to this code attribute, or -1 if this attribute
+     *            is not a code attribute.
      * @return the byte array form of this attribute.
      */
-    protected ByteVector write(
-        final ClassWriter cw,
-        final byte[] code,
-        final int len,
-        final int maxStack,
-        final int maxLocals)
-    {
+    protected ByteVector write(final ClassWriter cw, final byte[] code,
+            final int len, final int maxStack, final int maxLocals) {
         ByteVector v = new ByteVector();
         v.data = value;
         v.length = value.length;
@@ -165,7 +166,7 @@ public class Attribute {
 
     /**
      * Returns the length of the attribute list that begins with this attribute.
-     *
+     * 
      * @return the length of the attribute list that begins with this attribute.
      */
     final int getCount() {
@@ -180,31 +181,31 @@ public class Attribute {
 
     /**
      * Returns the size of all the attributes in this attribute list.
-     *
-     * @param cw the class writer to be used to convert the attributes into byte
-     *        arrays, with the {@link #write write} method.
-     * @param code the bytecode of the method corresponding to these code
-     *        attributes, or <tt>null</tt> if these attributes are not code
-     *        attributes.
-     * @param len the length of the bytecode of the method corresponding to
-     *        these code attributes, or <tt>null</tt> if these attributes are
-     *        not code attributes.
-     * @param maxStack the maximum stack size of the method corresponding to
-     *        these code attributes, or -1 if these attributes are not code
-     *        attributes.
-     * @param maxLocals the maximum number of local variables of the method
-     *        corresponding to these code attributes, or -1 if these attributes
-     *        are not code attributes.
+     * 
+     * @param cw
+     *            the class writer to be used to convert the attributes into
+     *            byte arrays, with the {@link #write write} method.
+     * @param code
+     *            the bytecode of the method corresponding to these code
+     *            attributes, or <tt>null</tt> if these attributes are not code
+     *            attributes.
+     * @param len
+     *            the length of the bytecode of the method corresponding to
+     *            these code attributes, or <tt>null</tt> if these attributes
+     *            are not code attributes.
+     * @param maxStack
+     *            the maximum stack size of the method corresponding to these
+     *            code attributes, or -1 if these attributes are not code
+     *            attributes.
+     * @param maxLocals
+     *            the maximum number of local variables of the method
+     *            corresponding to these code attributes, or -1 if these
+     *            attributes are not code attributes.
      * @return the size of all the attributes in this attribute list. This size
      *         includes the size of the attribute headers.
      */
-    final int getSize(
-        final ClassWriter cw,
-        final byte[] code,
-        final int len,
-        final int maxStack,
-        final int maxLocals)
-    {
+    final int getSize(final ClassWriter cw, final byte[] code, final int len,
+            final int maxStack, final int maxLocals) {
         Attribute attr = this;
         int size = 0;
         while (attr != null) {
@@ -218,31 +219,31 @@ public class Attribute {
     /**
      * Writes all the attributes of this attribute list in the given byte
      * vector.
-     *
-     * @param cw the class writer to be used to convert the attributes into byte
-     *        arrays, with the {@link #write write} method.
-     * @param code the bytecode of the method corresponding to these code
-     *        attributes, or <tt>null</tt> if these attributes are not code
-     *        attributes.
-     * @param len the length of the bytecode of the method corresponding to
-     *        these code attributes, or <tt>null</tt> if these attributes are
-     *        not code attributes.
-     * @param maxStack the maximum stack size of the method corresponding to
-     *        these code attributes, or -1 if these attributes are not code
-     *        attributes.
-     * @param maxLocals the maximum number of local variables of the method
-     *        corresponding to these code attributes, or -1 if these attributes
-     *        are not code attributes.
-     * @param out where the attributes must be written.
+     * 
+     * @param cw
+     *            the class writer to be used to convert the attributes into
+     *            byte arrays, with the {@link #write write} method.
+     * @param code
+     *            the bytecode of the method corresponding to these code
+     *            attributes, or <tt>null</tt> if these attributes are not code
+     *            attributes.
+     * @param len
+     *            the length of the bytecode of the method corresponding to
+     *            these code attributes, or <tt>null</tt> if these attributes
+     *            are not code attributes.
+     * @param maxStack
+     *            the maximum stack size of the method corresponding to these
+     *            code attributes, or -1 if these attributes are not code
+     *            attributes.
+     * @param maxLocals
+     *            the maximum number of local variables of the method
+     *            corresponding to these code attributes, or -1 if these
+     *            attributes are not code attributes.
+     * @param out
+     *            where the attributes must be written.
      */
-    final void put(
-        final ClassWriter cw,
-        final byte[] code,
-        final int len,
-        final int maxStack,
-        final int maxLocals,
-        final ByteVector out)
-    {
+    final void put(final ClassWriter cw, final byte[] code, final int len,
+            final int maxStack, final int maxLocals, final ByteVector out) {
         Attribute attr = this;
         while (attr != null) {
             ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
index e689d87..24506f9 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
@@ -32,7 +32,7 @@ package org.apache.tapestry5.internal.plastic.asm;
 /**
  * A dynamically extensible vector of bytes. This class is roughly equivalent to
  * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
- *
+ * 
  * @author Eric Bruneton
  */
 public class ByteVector {
@@ -58,8 +58,9 @@ public class ByteVector {
     /**
      * Constructs a new {@link ByteVector ByteVector} with the given initial
      * size.
-     *
-     * @param initialSize the initial size of the byte vector to be constructed.
+     * 
+     * @param initialSize
+     *            the initial size of the byte vector to be constructed.
      */
     public ByteVector(final int initialSize) {
         data = new byte[initialSize];
@@ -68,8 +69,9 @@ public class ByteVector {
     /**
      * Puts a byte into this byte vector. The byte vector is automatically
      * enlarged if necessary.
-     *
-     * @param b a byte.
+     * 
+     * @param b
+     *            a byte.
      * @return this byte vector.
      */
     public ByteVector putByte(final int b) {
@@ -85,9 +87,11 @@ public class ByteVector {
     /**
      * Puts two bytes into this byte vector. The byte vector is automatically
      * enlarged if necessary.
-     *
-     * @param b1 a byte.
-     * @param b2 another byte.
+     * 
+     * @param b1
+     *            a byte.
+     * @param b2
+     *            another byte.
      * @return this byte vector.
      */
     ByteVector put11(final int b1, final int b2) {
@@ -105,8 +109,9 @@ public class ByteVector {
     /**
      * Puts a short into this byte vector. The byte vector is automatically
      * enlarged if necessary.
-     *
-     * @param s a short.
+     * 
+     * @param s
+     *            a short.
      * @return this byte vector.
      */
     public ByteVector putShort(final int s) {
@@ -124,9 +129,11 @@ public class ByteVector {
     /**
      * Puts a byte and a short into this byte vector. The byte vector is
      * automatically enlarged if necessary.
-     *
-     * @param b a byte.
-     * @param s a short.
+     * 
+     * @param b
+     *            a byte.
+     * @param s
+     *            a short.
      * @return this byte vector.
      */
     ByteVector put12(final int b, final int s) {
@@ -145,8 +152,9 @@ public class ByteVector {
     /**
      * Puts an int into this byte vector. The byte vector is automatically
      * enlarged if necessary.
-     *
-     * @param i an int.
+     * 
+     * @param i
+     *            an int.
      * @return this byte vector.
      */
     public ByteVector putInt(final int i) {
@@ -166,8 +174,9 @@ public class ByteVector {
     /**
      * Puts a long into this byte vector. The byte vector is automatically
      * enlarged if necessary.
-     *
-     * @param l a long.
+     * 
+     * @param l
+     *            a long.
      * @return this byte vector.
      */
     public ByteVector putLong(final long l) {
@@ -193,12 +202,16 @@ public class ByteVector {
     /**
      * Puts an UTF8 string into this byte vector. The byte vector is
      * automatically enlarged if necessary.
-     *
-     * @param s a String.
+     * 
+     * @param s
+     *            a String whose UTF8 encoded length must be less than 65536.
      * @return this byte vector.
      */
     public ByteVector putUTF8(final String s) {
         int charLength = s.length();
+        if (charLength > 65535) {
+            throw new IllegalArgumentException();
+        }
         int len = length;
         if (len + 2 + charLength > data.length) {
             enlarge(2 + charLength);
@@ -217,38 +230,68 @@ public class ByteVector {
             if (c >= '\001' && c <= '\177') {
                 data[len++] = (byte) c;
             } else {
-                int byteLength = i;
-                for (int j = i; j < charLength; ++j) {
-                    c = s.charAt(j);
-                    if (c >= '\001' && c <= '\177') {
-                        byteLength++;
-                    } else if (c > '\u07FF') {
-                        byteLength += 3;
-                    } else {
-                        byteLength += 2;
-                    }
-                }
-                data[length] = (byte) (byteLength >>> 8);
-                data[length + 1] = (byte) byteLength;
-                if (length + 2 + byteLength > data.length) {
-                    length = len;
-                    enlarge(2 + byteLength);
-                    data = this.data;
-                }
-                for (int j = i; j < charLength; ++j) {
-                    c = s.charAt(j);
-                    if (c >= '\001' && c <= '\177') {
-                        data[len++] = (byte) c;
-                    } else if (c > '\u07FF') {
-                        data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
-                        data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
-                        data[len++] = (byte) (0x80 | c & 0x3F);
-                    } else {
-                        data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
-                        data[len++] = (byte) (0x80 | c & 0x3F);
-                    }
-                }
-                break;
+                length = len;
+                return encodeUTF8(s, i, 65535);
+            }
+        }
+        length = len;
+        return this;
+    }
+
+    /**
+     * Puts an UTF8 string into this byte vector. The byte vector is
+     * automatically enlarged if necessary. The string length is encoded in two
+     * bytes before the encoded characters, if there is space for that (i.e. if
+     * this.length - i - 2 >= 0).
+     * 
+     * @param s
+     *            the String to encode.
+     * @param i
+     *            the index of the first character to encode. The previous
+     *            characters are supposed to have already been encoded, using
+     *            only one byte per character.
+     * @param maxByteLength
+     *            the maximum byte length of the encoded string, including the
+     *            already encoded characters.
+     * @return this byte vector.
+     */
+    ByteVector encodeUTF8(final String s, int i, int maxByteLength) {
+        int charLength = s.length();
+        int byteLength = i;
+        char c;
+        for (int j = i; j < charLength; ++j) {
+            c = s.charAt(j);
+            if (c >= '\001' && c <= '\177') {
+                byteLength++;
+            } else if (c > '\u07FF') {
+                byteLength += 3;
+            } else {
+                byteLength += 2;
+            }
+        }
+        if (byteLength > maxByteLength) {
+            throw new IllegalArgumentException();
+        }
+        int start = length - i - 2;
+        if (start >= 0) {
+          data[start] = (byte) (byteLength >>> 8);
+          data[start + 1] = (byte) byteLength;
+        }
+        if (length + byteLength - i > data.length) {
+            enlarge(byteLength - i);
+        }
+        int len = length;
+        for (int j = i; j < charLength; ++j) {
+            c = s.charAt(j);
+            if (c >= '\001' && c <= '\177') {
+                data[len++] = (byte) c;
+            } else if (c > '\u07FF') {
+                data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
+                data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
+                data[len++] = (byte) (0x80 | c & 0x3F);
+            } else {
+                data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
+                data[len++] = (byte) (0x80 | c & 0x3F);
             }
         }
         length = len;
@@ -258,15 +301,17 @@ public class ByteVector {
     /**
      * Puts an array of bytes into this byte vector. The byte vector is
      * automatically enlarged if necessary.
-     *
-     * @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
-     *        null bytes into this byte vector.
-     * @param off index of the fist byte of b that must be copied.
-     * @param len number of bytes of b that must be copied.
+     * 
+     * @param b
+     *            an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
+     *            null bytes into this byte vector.
+     * @param off
+     *            index of the fist byte of b that must be copied.
+     * @param len
+     *            number of bytes of b that must be copied.
      * @return this byte vector.
      */
-    public ByteVector putByteArray(final byte[] b, final int off, final int len)
-    {
+    public ByteVector putByteArray(final byte[] b, final int off, final int len) {
         if (length + len > data.length) {
             enlarge(len);
         }
@@ -279,9 +324,10 @@ public class ByteVector {
 
     /**
      * Enlarge this byte vector so that it can receive n more bytes.
-     *
-     * @param size number of additional bytes that this byte vector should be
-     *        able to receive.
+     * 
+     * @param size
+     *            number of additional bytes that this byte vector should be
+     *            able to receive.
      */
     private void enlarge(final int size) {
         int length1 = 2 * data.length;


[08/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java
new file mode 100644
index 0000000..0656c65
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java
@@ -0,0 +1,358 @@
+/***
+ * 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.List;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+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.FieldInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.IntInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.InvokeDynamicInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LdcInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MultiANewArrayInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TypeInsnNode;
+
+/**
+ * An {@link Interpreter} for {@link BasicValue} values.
+ * 
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class BasicInterpreter extends Interpreter<BasicValue> implements
+        Opcodes {
+
+    public BasicInterpreter() {
+        super(ASM5);
+    }
+
+    protected BasicInterpreter(final int api) {
+        super(api);
+    }
+
+    @Override
+    public BasicValue newValue(final Type type) {
+        if (type == null) {
+            return BasicValue.UNINITIALIZED_VALUE;
+        }
+        switch (type.getSort()) {
+        case Type.VOID:
+            return null;
+        case Type.BOOLEAN:
+        case Type.CHAR:
+        case Type.BYTE:
+        case Type.SHORT:
+        case Type.INT:
+            return BasicValue.INT_VALUE;
+        case Type.FLOAT:
+            return BasicValue.FLOAT_VALUE;
+        case Type.LONG:
+            return BasicValue.LONG_VALUE;
+        case Type.DOUBLE:
+            return BasicValue.DOUBLE_VALUE;
+        case Type.ARRAY:
+        case Type.OBJECT:
+            return BasicValue.REFERENCE_VALUE;
+        default:
+            throw new Error("Internal error");
+        }
+    }
+
+    @Override
+    public BasicValue newOperation(final AbstractInsnNode insn)
+            throws AnalyzerException {
+        switch (insn.getOpcode()) {
+        case ACONST_NULL:
+            return newValue(Type.getObjectType("null"));
+        case ICONST_M1:
+        case ICONST_0:
+        case ICONST_1:
+        case ICONST_2:
+        case ICONST_3:
+        case ICONST_4:
+        case ICONST_5:
+            return BasicValue.INT_VALUE;
+        case LCONST_0:
+        case LCONST_1:
+            return BasicValue.LONG_VALUE;
+        case FCONST_0:
+        case FCONST_1:
+        case FCONST_2:
+            return BasicValue.FLOAT_VALUE;
+        case DCONST_0:
+        case DCONST_1:
+            return BasicValue.DOUBLE_VALUE;
+        case BIPUSH:
+        case SIPUSH:
+            return BasicValue.INT_VALUE;
+        case LDC:
+            Object cst = ((LdcInsnNode) insn).cst;
+            if (cst instanceof Integer) {
+                return BasicValue.INT_VALUE;
+            } else if (cst instanceof Float) {
+                return BasicValue.FLOAT_VALUE;
+            } else if (cst instanceof Long) {
+                return BasicValue.LONG_VALUE;
+            } else if (cst instanceof Double) {
+                return BasicValue.DOUBLE_VALUE;
+            } else if (cst instanceof String) {
+                return newValue(Type.getObjectType("java/lang/String"));
+            } else if (cst instanceof Type) {
+                int sort = ((Type) cst).getSort();
+                if (sort == Type.OBJECT || sort == Type.ARRAY) {
+                    return newValue(Type.getObjectType("java/lang/Class"));
+                } else if (sort == Type.METHOD) {
+                    return newValue(Type
+                            .getObjectType("java/lang/invoke/MethodType"));
+                } else {
+                    throw new IllegalArgumentException("Illegal LDC constant "
+                            + cst);
+                }
+            } else if (cst instanceof Handle) {
+                return newValue(Type
+                        .getObjectType("java/lang/invoke/MethodHandle"));
+            } else {
+                throw new IllegalArgumentException("Illegal LDC constant "
+                        + cst);
+            }
+        case JSR:
+            return BasicValue.RETURNADDRESS_VALUE;
+        case GETSTATIC:
+            return newValue(Type.getType(((FieldInsnNode) insn).desc));
+        case NEW:
+            return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
+        default:
+            throw new Error("Internal error.");
+        }
+    }
+
+    @Override
+    public BasicValue copyOperation(final AbstractInsnNode insn,
+            final BasicValue value) throws AnalyzerException {
+        return value;
+    }
+
+    @Override
+    public BasicValue unaryOperation(final AbstractInsnNode insn,
+            final BasicValue value) throws AnalyzerException {
+        switch (insn.getOpcode()) {
+        case INEG:
+        case IINC:
+        case L2I:
+        case F2I:
+        case D2I:
+        case I2B:
+        case I2C:
+        case I2S:
+            return BasicValue.INT_VALUE;
+        case FNEG:
+        case I2F:
+        case L2F:
+        case D2F:
+            return BasicValue.FLOAT_VALUE;
+        case LNEG:
+        case I2L:
+        case F2L:
+        case D2L:
+            return BasicValue.LONG_VALUE;
+        case DNEG:
+        case I2D:
+        case L2D:
+        case F2D:
+            return BasicValue.DOUBLE_VALUE;
+        case IFEQ:
+        case IFNE:
+        case IFLT:
+        case IFGE:
+        case IFGT:
+        case IFLE:
+        case TABLESWITCH:
+        case LOOKUPSWITCH:
+        case IRETURN:
+        case LRETURN:
+        case FRETURN:
+        case DRETURN:
+        case ARETURN:
+        case PUTSTATIC:
+            return null;
+        case GETFIELD:
+            return newValue(Type.getType(((FieldInsnNode) insn).desc));
+        case NEWARRAY:
+            switch (((IntInsnNode) insn).operand) {
+            case T_BOOLEAN:
+                return newValue(Type.getType("[Z"));
+            case T_CHAR:
+                return newValue(Type.getType("[C"));
+            case T_BYTE:
+                return newValue(Type.getType("[B"));
+            case T_SHORT:
+                return newValue(Type.getType("[S"));
+            case T_INT:
+                return newValue(Type.getType("[I"));
+            case T_FLOAT:
+                return newValue(Type.getType("[F"));
+            case T_DOUBLE:
+                return newValue(Type.getType("[D"));
+            case T_LONG:
+                return newValue(Type.getType("[J"));
+            default:
+                throw new AnalyzerException(insn, "Invalid array type");
+            }
+        case ANEWARRAY:
+            String desc = ((TypeInsnNode) insn).desc;
+            return newValue(Type.getType("[" + Type.getObjectType(desc)));
+        case ARRAYLENGTH:
+            return BasicValue.INT_VALUE;
+        case ATHROW:
+            return null;
+        case CHECKCAST:
+            desc = ((TypeInsnNode) insn).desc;
+            return newValue(Type.getObjectType(desc));
+        case INSTANCEOF:
+            return BasicValue.INT_VALUE;
+        case MONITORENTER:
+        case MONITOREXIT:
+        case IFNULL:
+        case IFNONNULL:
+            return null;
+        default:
+            throw new Error("Internal error.");
+        }
+    }
+
+    @Override
+    public BasicValue binaryOperation(final AbstractInsnNode insn,
+            final BasicValue value1, final BasicValue value2)
+            throws AnalyzerException {
+        switch (insn.getOpcode()) {
+        case IALOAD:
+        case BALOAD:
+        case CALOAD:
+        case SALOAD:
+        case IADD:
+        case ISUB:
+        case IMUL:
+        case IDIV:
+        case IREM:
+        case ISHL:
+        case ISHR:
+        case IUSHR:
+        case IAND:
+        case IOR:
+        case IXOR:
+            return BasicValue.INT_VALUE;
+        case FALOAD:
+        case FADD:
+        case FSUB:
+        case FMUL:
+        case FDIV:
+        case FREM:
+            return BasicValue.FLOAT_VALUE;
+        case LALOAD:
+        case LADD:
+        case LSUB:
+        case LMUL:
+        case LDIV:
+        case LREM:
+        case LSHL:
+        case LSHR:
+        case LUSHR:
+        case LAND:
+        case LOR:
+        case LXOR:
+            return BasicValue.LONG_VALUE;
+        case DALOAD:
+        case DADD:
+        case DSUB:
+        case DMUL:
+        case DDIV:
+        case DREM:
+            return BasicValue.DOUBLE_VALUE;
+        case AALOAD:
+            return BasicValue.REFERENCE_VALUE;
+        case LCMP:
+        case FCMPL:
+        case FCMPG:
+        case DCMPL:
+        case DCMPG:
+            return BasicValue.INT_VALUE;
+        case IF_ICMPEQ:
+        case IF_ICMPNE:
+        case IF_ICMPLT:
+        case IF_ICMPGE:
+        case IF_ICMPGT:
+        case IF_ICMPLE:
+        case IF_ACMPEQ:
+        case IF_ACMPNE:
+        case PUTFIELD:
+            return null;
+        default:
+            throw new Error("Internal error.");
+        }
+    }
+
+    @Override
+    public BasicValue ternaryOperation(final AbstractInsnNode insn,
+            final BasicValue value1, final BasicValue value2,
+            final BasicValue value3) throws AnalyzerException {
+        return null;
+    }
+
+    @Override
+    public BasicValue naryOperation(final AbstractInsnNode insn,
+            final List<? extends BasicValue> values) throws AnalyzerException {
+        int opcode = insn.getOpcode();
+        if (opcode == MULTIANEWARRAY) {
+            return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
+        } else if (opcode == INVOKEDYNAMIC) {
+            return newValue(Type
+                    .getReturnType(((InvokeDynamicInsnNode) insn).desc));
+        } else {
+            return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
+        }
+    }
+
+    @Override
+    public void returnOperation(final AbstractInsnNode insn,
+            final BasicValue value, final BasicValue expected)
+            throws AnalyzerException {
+    }
+
+    @Override
+    public BasicValue merge(final BasicValue v, final BasicValue w) {
+        if (!v.equals(w)) {
+            return BasicValue.UNINITIALIZED_VALUE;
+        }
+        return v;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java
new file mode 100644
index 0000000..44b0704
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java
@@ -0,0 +1,111 @@
+/***
+ * 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.Type;
+
+/**
+ * A {@link Value} that is represented by its type in a seven types type system.
+ * This type system distinguishes the UNINITIALZED, INT, FLOAT, LONG, DOUBLE,
+ * REFERENCE and RETURNADDRESS types.
+ * 
+ * @author Eric Bruneton
+ */
+public class BasicValue implements Value {
+
+    public static final BasicValue UNINITIALIZED_VALUE = new BasicValue(null);
+
+    public static final BasicValue INT_VALUE = new BasicValue(Type.INT_TYPE);
+
+    public static final BasicValue FLOAT_VALUE = new BasicValue(Type.FLOAT_TYPE);
+
+    public static final BasicValue LONG_VALUE = new BasicValue(Type.LONG_TYPE);
+
+    public static final BasicValue DOUBLE_VALUE = new BasicValue(
+            Type.DOUBLE_TYPE);
+
+    public static final BasicValue REFERENCE_VALUE = new BasicValue(
+            Type.getObjectType("java/lang/Object"));
+
+    public static final BasicValue RETURNADDRESS_VALUE = new BasicValue(
+            Type.VOID_TYPE);
+
+    private final Type type;
+
+    public BasicValue(final Type type) {
+        this.type = type;
+    }
+
+    public Type getType() {
+        return type;
+    }
+
+    public int getSize() {
+        return type == Type.LONG_TYPE || type == Type.DOUBLE_TYPE ? 2 : 1;
+    }
+
+    public boolean isReference() {
+        return type != null
+                && (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY);
+    }
+
+    @Override
+    public boolean equals(final Object value) {
+        if (value == this) {
+            return true;
+        } else if (value instanceof BasicValue) {
+            if (type == null) {
+                return ((BasicValue) value).type == null;
+            } else {
+                return type.equals(((BasicValue) value).type);
+            }
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return type == null ? 0 : type.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        if (this == UNINITIALIZED_VALUE) {
+            return ".";
+        } else if (this == RETURNADDRESS_VALUE) {
+            return "A";
+        } else if (this == REFERENCE_VALUE) {
+            return "R";
+        } else {
+            return type.getDescriptor();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java
new file mode 100644
index 0000000..50f4a84
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java
@@ -0,0 +1,433 @@
+/***
+ * 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.List;
+
+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.FieldInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.InvokeDynamicInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodInsnNode;
+
+/**
+ * An extended {@link BasicInterpreter} that checks that bytecode instructions
+ * are correctly used.
+ * 
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class BasicVerifier extends BasicInterpreter {
+
+    public BasicVerifier() {
+        super(ASM5);
+    }
+
+    protected BasicVerifier(final int api) {
+        super(api);
+    }
+
+    @Override
+    public BasicValue copyOperation(final AbstractInsnNode insn,
+            final BasicValue value) throws AnalyzerException {
+        Value expected;
+        switch (insn.getOpcode()) {
+        case ILOAD:
+        case ISTORE:
+            expected = BasicValue.INT_VALUE;
+            break;
+        case FLOAD:
+        case FSTORE:
+            expected = BasicValue.FLOAT_VALUE;
+            break;
+        case LLOAD:
+        case LSTORE:
+            expected = BasicValue.LONG_VALUE;
+            break;
+        case DLOAD:
+        case DSTORE:
+            expected = BasicValue.DOUBLE_VALUE;
+            break;
+        case ALOAD:
+            if (!value.isReference()) {
+                throw new AnalyzerException(insn, null, "an object reference",
+                        value);
+            }
+            return value;
+        case ASTORE:
+            if (!value.isReference()
+                    && !BasicValue.RETURNADDRESS_VALUE.equals(value)) {
+                throw new AnalyzerException(insn, null,
+                        "an object reference or a return address", value);
+            }
+            return value;
+        default:
+            return value;
+        }
+        if (!expected.equals(value)) {
+            throw new AnalyzerException(insn, null, expected, value);
+        }
+        return value;
+    }
+
+    @Override
+    public BasicValue unaryOperation(final AbstractInsnNode insn,
+            final BasicValue value) throws AnalyzerException {
+        BasicValue expected;
+        switch (insn.getOpcode()) {
+        case INEG:
+        case IINC:
+        case I2F:
+        case I2L:
+        case I2D:
+        case I2B:
+        case I2C:
+        case I2S:
+        case IFEQ:
+        case IFNE:
+        case IFLT:
+        case IFGE:
+        case IFGT:
+        case IFLE:
+        case TABLESWITCH:
+        case LOOKUPSWITCH:
+        case IRETURN:
+        case NEWARRAY:
+        case ANEWARRAY:
+            expected = BasicValue.INT_VALUE;
+            break;
+        case FNEG:
+        case F2I:
+        case F2L:
+        case F2D:
+        case FRETURN:
+            expected = BasicValue.FLOAT_VALUE;
+            break;
+        case LNEG:
+        case L2I:
+        case L2F:
+        case L2D:
+        case LRETURN:
+            expected = BasicValue.LONG_VALUE;
+            break;
+        case DNEG:
+        case D2I:
+        case D2F:
+        case D2L:
+        case DRETURN:
+            expected = BasicValue.DOUBLE_VALUE;
+            break;
+        case GETFIELD:
+            expected = newValue(Type
+                    .getObjectType(((FieldInsnNode) insn).owner));
+            break;
+        case CHECKCAST:
+            if (!value.isReference()) {
+                throw new AnalyzerException(insn, null, "an object reference",
+                        value);
+            }
+            return super.unaryOperation(insn, value);
+        case ARRAYLENGTH:
+            if (!isArrayValue(value)) {
+                throw new AnalyzerException(insn, null, "an array reference",
+                        value);
+            }
+            return super.unaryOperation(insn, value);
+        case ARETURN:
+        case ATHROW:
+        case INSTANCEOF:
+        case MONITORENTER:
+        case MONITOREXIT:
+        case IFNULL:
+        case IFNONNULL:
+            if (!value.isReference()) {
+                throw new AnalyzerException(insn, null, "an object reference",
+                        value);
+            }
+            return super.unaryOperation(insn, value);
+        case PUTSTATIC:
+            expected = newValue(Type.getType(((FieldInsnNode) insn).desc));
+            break;
+        default:
+            throw new Error("Internal error.");
+        }
+        if (!isSubTypeOf(value, expected)) {
+            throw new AnalyzerException(insn, null, expected, value);
+        }
+        return super.unaryOperation(insn, value);
+    }
+
+    @Override
+    public BasicValue binaryOperation(final AbstractInsnNode insn,
+            final BasicValue value1, final BasicValue value2)
+            throws AnalyzerException {
+        BasicValue expected1;
+        BasicValue expected2;
+        switch (insn.getOpcode()) {
+        case IALOAD:
+            expected1 = newValue(Type.getType("[I"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case BALOAD:
+            if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
+                expected1 = newValue(Type.getType("[Z"));
+            } else {
+                expected1 = newValue(Type.getType("[B"));
+            }
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case CALOAD:
+            expected1 = newValue(Type.getType("[C"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case SALOAD:
+            expected1 = newValue(Type.getType("[S"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case LALOAD:
+            expected1 = newValue(Type.getType("[J"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case FALOAD:
+            expected1 = newValue(Type.getType("[F"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case DALOAD:
+            expected1 = newValue(Type.getType("[D"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case AALOAD:
+            expected1 = newValue(Type.getType("[Ljava/lang/Object;"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case IADD:
+        case ISUB:
+        case IMUL:
+        case IDIV:
+        case IREM:
+        case ISHL:
+        case ISHR:
+        case IUSHR:
+        case IAND:
+        case IOR:
+        case IXOR:
+        case IF_ICMPEQ:
+        case IF_ICMPNE:
+        case IF_ICMPLT:
+        case IF_ICMPGE:
+        case IF_ICMPGT:
+        case IF_ICMPLE:
+            expected1 = BasicValue.INT_VALUE;
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case FADD:
+        case FSUB:
+        case FMUL:
+        case FDIV:
+        case FREM:
+        case FCMPL:
+        case FCMPG:
+            expected1 = BasicValue.FLOAT_VALUE;
+            expected2 = BasicValue.FLOAT_VALUE;
+            break;
+        case LADD:
+        case LSUB:
+        case LMUL:
+        case LDIV:
+        case LREM:
+        case LAND:
+        case LOR:
+        case LXOR:
+        case LCMP:
+            expected1 = BasicValue.LONG_VALUE;
+            expected2 = BasicValue.LONG_VALUE;
+            break;
+        case LSHL:
+        case LSHR:
+        case LUSHR:
+            expected1 = BasicValue.LONG_VALUE;
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case DADD:
+        case DSUB:
+        case DMUL:
+        case DDIV:
+        case DREM:
+        case DCMPL:
+        case DCMPG:
+            expected1 = BasicValue.DOUBLE_VALUE;
+            expected2 = BasicValue.DOUBLE_VALUE;
+            break;
+        case IF_ACMPEQ:
+        case IF_ACMPNE:
+            expected1 = BasicValue.REFERENCE_VALUE;
+            expected2 = BasicValue.REFERENCE_VALUE;
+            break;
+        case PUTFIELD:
+            FieldInsnNode fin = (FieldInsnNode) insn;
+            expected1 = newValue(Type.getObjectType(fin.owner));
+            expected2 = newValue(Type.getType(fin.desc));
+            break;
+        default:
+            throw new Error("Internal error.");
+        }
+        if (!isSubTypeOf(value1, expected1)) {
+            throw new AnalyzerException(insn, "First argument", expected1,
+                    value1);
+        } else if (!isSubTypeOf(value2, expected2)) {
+            throw new AnalyzerException(insn, "Second argument", expected2,
+                    value2);
+        }
+        if (insn.getOpcode() == AALOAD) {
+            return getElementValue(value1);
+        } else {
+            return super.binaryOperation(insn, value1, value2);
+        }
+    }
+
+    @Override
+    public BasicValue ternaryOperation(final AbstractInsnNode insn,
+            final BasicValue value1, final BasicValue value2,
+            final BasicValue value3) throws AnalyzerException {
+        BasicValue expected1;
+        BasicValue expected3;
+        switch (insn.getOpcode()) {
+        case IASTORE:
+            expected1 = newValue(Type.getType("[I"));
+            expected3 = BasicValue.INT_VALUE;
+            break;
+        case BASTORE:
+            if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
+                expected1 = newValue(Type.getType("[Z"));
+            } else {
+                expected1 = newValue(Type.getType("[B"));
+            }
+            expected3 = BasicValue.INT_VALUE;
+            break;
+        case CASTORE:
+            expected1 = newValue(Type.getType("[C"));
+            expected3 = BasicValue.INT_VALUE;
+            break;
+        case SASTORE:
+            expected1 = newValue(Type.getType("[S"));
+            expected3 = BasicValue.INT_VALUE;
+            break;
+        case LASTORE:
+            expected1 = newValue(Type.getType("[J"));
+            expected3 = BasicValue.LONG_VALUE;
+            break;
+        case FASTORE:
+            expected1 = newValue(Type.getType("[F"));
+            expected3 = BasicValue.FLOAT_VALUE;
+            break;
+        case DASTORE:
+            expected1 = newValue(Type.getType("[D"));
+            expected3 = BasicValue.DOUBLE_VALUE;
+            break;
+        case AASTORE:
+            expected1 = value1;
+            expected3 = BasicValue.REFERENCE_VALUE;
+            break;
+        default:
+            throw new Error("Internal error.");
+        }
+        if (!isSubTypeOf(value1, expected1)) {
+            throw new AnalyzerException(insn, "First argument", "a "
+                    + expected1 + " array reference", value1);
+        } else if (!BasicValue.INT_VALUE.equals(value2)) {
+            throw new AnalyzerException(insn, "Second argument",
+                    BasicValue.INT_VALUE, value2);
+        } else if (!isSubTypeOf(value3, expected3)) {
+            throw new AnalyzerException(insn, "Third argument", expected3,
+                    value3);
+        }
+        return null;
+    }
+
+    @Override
+    public BasicValue naryOperation(final AbstractInsnNode insn,
+            final List<? extends BasicValue> values) throws AnalyzerException {
+        int opcode = insn.getOpcode();
+        if (opcode == MULTIANEWARRAY) {
+            for (int i = 0; i < values.size(); ++i) {
+                if (!BasicValue.INT_VALUE.equals(values.get(i))) {
+                    throw new AnalyzerException(insn, null,
+                            BasicValue.INT_VALUE, values.get(i));
+                }
+            }
+        } else {
+            int i = 0;
+            int j = 0;
+            if (opcode != INVOKESTATIC && opcode != INVOKEDYNAMIC) {
+                Type owner = Type.getObjectType(((MethodInsnNode) insn).owner);
+                if (!isSubTypeOf(values.get(i++), newValue(owner))) {
+                    throw new AnalyzerException(insn, "Method owner",
+                            newValue(owner), values.get(0));
+                }
+            }
+            String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc
+                    : ((MethodInsnNode) insn).desc;
+            Type[] args = Type.getArgumentTypes(desc);
+            while (i < values.size()) {
+                BasicValue expected = newValue(args[j++]);
+                BasicValue encountered = values.get(i++);
+                if (!isSubTypeOf(encountered, expected)) {
+                    throw new AnalyzerException(insn, "Argument " + j,
+                            expected, encountered);
+                }
+            }
+        }
+        return super.naryOperation(insn, values);
+    }
+
+    @Override
+    public void returnOperation(final AbstractInsnNode insn,
+            final BasicValue value, final BasicValue expected)
+            throws AnalyzerException {
+        if (!isSubTypeOf(value, expected)) {
+            throw new AnalyzerException(insn, "Incompatible return type",
+                    expected, value);
+        }
+    }
+
+    protected boolean isArrayValue(final BasicValue value) {
+        return value.isReference();
+    }
+
+    protected BasicValue getElementValue(final BasicValue objectArrayValue)
+            throws AnalyzerException {
+        return BasicValue.REFERENCE_VALUE;
+    }
+
+    protected boolean isSubTypeOf(final BasicValue value,
+            final BasicValue expected) {
+        return value.equals(expected);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java
new file mode 100644
index 0000000..fdbb0a9
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java
@@ -0,0 +1,738 @@
+/***
+ * 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.List;
+
+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.InvokeDynamicInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MultiANewArrayInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.VarInsnNode;
+
+/**
+ * A symbolic execution stack frame. A stack frame contains a set of local
+ * variable slots, and an operand stack. Warning: long and double values are
+ * represented by <i>two</i> slots in local variables, and by <i>one</i> slot in
+ * the operand stack.
+ * 
+ * @param <V>
+ *            type of the Value used for the analysis.
+ * 
+ * @author Eric Bruneton
+ */
+public class Frame<V extends Value> {
+
+    /**
+     * The expected return type of the analyzed method, or <tt>null</tt> if the
+     * method returns void.
+     */
+    private V returnValue;
+
+    /**
+     * The local variables and operand stack of this frame.
+     */
+    private V[] values;
+
+    /**
+     * The number of local variables of this frame.
+     */
+    private int locals;
+
+    /**
+     * The number of elements in the operand stack.
+     */
+    private int top;
+
+    /**
+     * 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.
+     */
+    public Frame(final int nLocals, final int nStack) {
+        this.values = (V[]) new Value[nLocals + nStack];
+        this.locals = nLocals;
+    }
+
+    /**
+     * Constructs a new frame that is identical to the given frame.
+     * 
+     * @param src
+     *            a frame.
+     */
+    public Frame(final Frame<? extends V> src) {
+        this(src.locals, src.values.length - src.locals);
+        init(src);
+    }
+
+    /**
+     * Copies the state of the given frame into this frame.
+     * 
+     * @param src
+     *            a frame.
+     * @return this frame.
+     */
+    public Frame<V> init(final Frame<? extends V> src) {
+        returnValue = src.returnValue;
+        System.arraycopy(src.values, 0, values, 0, values.length);
+        top = src.top;
+        return this;
+    }
+
+    /**
+     * Sets the expected return type of the analyzed method.
+     * 
+     * @param v
+     *            the expected return type of the analyzed method, or
+     *            <tt>null</tt> if the method returns void.
+     */
+    public void setReturn(final V v) {
+        returnValue = v;
+    }
+
+    /**
+     * Returns the maximum number of local variables of this frame.
+     * 
+     * @return the maximum number of local variables of this frame.
+     */
+    public int getLocals() {
+        return locals;
+    }
+
+    /**
+     * Returns the maximum stack size of this frame.
+     * 
+     * @return the maximum stack size of this frame.
+     */
+    public int getMaxStackSize() {
+        return values.length - locals;
+    }
+    
+    /**
+     * Returns the value of the given local variable.
+     * 
+     * @param i
+     *            a local variable index.
+     * @return the value of the given local variable.
+     * @throws IndexOutOfBoundsException
+     *             if the variable does not exist.
+     */
+    public V getLocal(final int i) throws IndexOutOfBoundsException {
+        if (i >= locals) {
+            throw new IndexOutOfBoundsException(
+                    "Trying to access an inexistant local variable");
+        }
+        return values[i];
+    }
+
+    /**
+     * Sets the value of the given local variable.
+     * 
+     * @param i
+     *            a local variable index.
+     * @param value
+     *            the new value of this local variable.
+     * @throws IndexOutOfBoundsException
+     *             if the variable does not exist.
+     */
+    public void setLocal(final int i, final V value)
+            throws IndexOutOfBoundsException {
+        if (i >= locals) {
+            throw new IndexOutOfBoundsException(
+                    "Trying to access an inexistant local variable " + i);
+        }
+        values[i] = value;
+    }
+
+    /**
+     * Returns the number of values in the operand stack of this frame. Long and
+     * double values are treated as single values.
+     * 
+     * @return the number of values in the operand stack of this frame.
+     */
+    public int getStackSize() {
+        return top;
+    }
+
+    /**
+     * Returns the value of the given operand stack slot.
+     * 
+     * @param i
+     *            the index of an operand stack slot.
+     * @return the value of the given operand stack slot.
+     * @throws IndexOutOfBoundsException
+     *             if the operand stack slot does not exist.
+     */
+    public V getStack(final int i) throws IndexOutOfBoundsException {
+        return values[i + locals];
+    }
+
+    /**
+     * Clears the operand stack of this frame.
+     */
+    public void clearStack() {
+        top = 0;
+    }
+
+    /**
+     * Pops a value from the operand stack of this frame.
+     * 
+     * @return the value that has been popped from the stack.
+     * @throws IndexOutOfBoundsException
+     *             if the operand stack is empty.
+     */
+    public V pop() throws IndexOutOfBoundsException {
+        if (top == 0) {
+            throw new IndexOutOfBoundsException(
+                    "Cannot pop operand off an empty stack.");
+        }
+        return values[--top + locals];
+    }
+
+    /**
+     * Pushes a value into the operand stack of this frame.
+     * 
+     * @param value
+     *            the value that must be pushed into the stack.
+     * @throws IndexOutOfBoundsException
+     *             if the operand stack is full.
+     */
+    public void push(final V value) throws IndexOutOfBoundsException {
+        if (top + locals >= values.length) {
+            throw new IndexOutOfBoundsException(
+                    "Insufficient maximum stack size.");
+        }
+        values[top++ + locals] = value;
+    }
+
+    public void execute(final AbstractInsnNode insn,
+            final Interpreter<V> interpreter) throws AnalyzerException {
+        V value1, value2, value3, value4;
+        List<V> values;
+        int var;
+
+        switch (insn.getOpcode()) {
+        case Opcodes.NOP:
+            break;
+        case Opcodes.ACONST_NULL:
+        case Opcodes.ICONST_M1:
+        case Opcodes.ICONST_0:
+        case Opcodes.ICONST_1:
+        case Opcodes.ICONST_2:
+        case Opcodes.ICONST_3:
+        case Opcodes.ICONST_4:
+        case Opcodes.ICONST_5:
+        case Opcodes.LCONST_0:
+        case Opcodes.LCONST_1:
+        case Opcodes.FCONST_0:
+        case Opcodes.FCONST_1:
+        case Opcodes.FCONST_2:
+        case Opcodes.DCONST_0:
+        case Opcodes.DCONST_1:
+        case Opcodes.BIPUSH:
+        case Opcodes.SIPUSH:
+        case Opcodes.LDC:
+            push(interpreter.newOperation(insn));
+            break;
+        case Opcodes.ILOAD:
+        case Opcodes.LLOAD:
+        case Opcodes.FLOAD:
+        case Opcodes.DLOAD:
+        case Opcodes.ALOAD:
+            push(interpreter.copyOperation(insn,
+                    getLocal(((VarInsnNode) insn).var)));
+            break;
+        case Opcodes.IALOAD:
+        case Opcodes.LALOAD:
+        case Opcodes.FALOAD:
+        case Opcodes.DALOAD:
+        case Opcodes.AALOAD:
+        case Opcodes.BALOAD:
+        case Opcodes.CALOAD:
+        case Opcodes.SALOAD:
+            value2 = pop();
+            value1 = pop();
+            push(interpreter.binaryOperation(insn, value1, value2));
+            break;
+        case Opcodes.ISTORE:
+        case Opcodes.LSTORE:
+        case Opcodes.FSTORE:
+        case Opcodes.DSTORE:
+        case Opcodes.ASTORE:
+            value1 = interpreter.copyOperation(insn, pop());
+            var = ((VarInsnNode) insn).var;
+            setLocal(var, value1);
+            if (value1.getSize() == 2) {
+                setLocal(var + 1, interpreter.newValue(null));
+            }
+            if (var > 0) {
+                Value local = getLocal(var - 1);
+                if (local != null && local.getSize() == 2) {
+                    setLocal(var - 1, interpreter.newValue(null));
+                }
+            }
+            break;
+        case Opcodes.IASTORE:
+        case Opcodes.LASTORE:
+        case Opcodes.FASTORE:
+        case Opcodes.DASTORE:
+        case Opcodes.AASTORE:
+        case Opcodes.BASTORE:
+        case Opcodes.CASTORE:
+        case Opcodes.SASTORE:
+            value3 = pop();
+            value2 = pop();
+            value1 = pop();
+            interpreter.ternaryOperation(insn, value1, value2, value3);
+            break;
+        case Opcodes.POP:
+            if (pop().getSize() == 2) {
+                throw new AnalyzerException(insn, "Illegal use of POP");
+            }
+            break;
+        case Opcodes.POP2:
+            if (pop().getSize() == 1) {
+                if (pop().getSize() != 1) {
+                    throw new AnalyzerException(insn, "Illegal use of POP2");
+                }
+            }
+            break;
+        case Opcodes.DUP:
+            value1 = pop();
+            if (value1.getSize() != 1) {
+                throw new AnalyzerException(insn, "Illegal use of DUP");
+            }
+            push(value1);
+            push(interpreter.copyOperation(insn, value1));
+            break;
+        case Opcodes.DUP_X1:
+            value1 = pop();
+            value2 = pop();
+            if (value1.getSize() != 1 || value2.getSize() != 1) {
+                throw new AnalyzerException(insn, "Illegal use of DUP_X1");
+            }
+            push(interpreter.copyOperation(insn, value1));
+            push(value2);
+            push(value1);
+            break;
+        case Opcodes.DUP_X2:
+            value1 = pop();
+            if (value1.getSize() == 1) {
+                value2 = pop();
+                if (value2.getSize() == 1) {
+                    value3 = pop();
+                    if (value3.getSize() == 1) {
+                        push(interpreter.copyOperation(insn, value1));
+                        push(value3);
+                        push(value2);
+                        push(value1);
+                        break;
+                    }
+                } else {
+                    push(interpreter.copyOperation(insn, value1));
+                    push(value2);
+                    push(value1);
+                    break;
+                }
+            }
+            throw new AnalyzerException(insn, "Illegal use of DUP_X2");
+        case Opcodes.DUP2:
+            value1 = pop();
+            if (value1.getSize() == 1) {
+                value2 = pop();
+                if (value2.getSize() == 1) {
+                    push(value2);
+                    push(value1);
+                    push(interpreter.copyOperation(insn, value2));
+                    push(interpreter.copyOperation(insn, value1));
+                    break;
+                }
+            } else {
+                push(value1);
+                push(interpreter.copyOperation(insn, value1));
+                break;
+            }
+            throw new AnalyzerException(insn, "Illegal use of DUP2");
+        case Opcodes.DUP2_X1:
+            value1 = pop();
+            if (value1.getSize() == 1) {
+                value2 = pop();
+                if (value2.getSize() == 1) {
+                    value3 = pop();
+                    if (value3.getSize() == 1) {
+                        push(interpreter.copyOperation(insn, value2));
+                        push(interpreter.copyOperation(insn, value1));
+                        push(value3);
+                        push(value2);
+                        push(value1);
+                        break;
+                    }
+                }
+            } else {
+                value2 = pop();
+                if (value2.getSize() == 1) {
+                    push(interpreter.copyOperation(insn, value1));
+                    push(value2);
+                    push(value1);
+                    break;
+                }
+            }
+            throw new AnalyzerException(insn, "Illegal use of DUP2_X1");
+        case Opcodes.DUP2_X2:
+            value1 = pop();
+            if (value1.getSize() == 1) {
+                value2 = pop();
+                if (value2.getSize() == 1) {
+                    value3 = pop();
+                    if (value3.getSize() == 1) {
+                        value4 = pop();
+                        if (value4.getSize() == 1) {
+                            push(interpreter.copyOperation(insn, value2));
+                            push(interpreter.copyOperation(insn, value1));
+                            push(value4);
+                            push(value3);
+                            push(value2);
+                            push(value1);
+                            break;
+                        }
+                    } else {
+                        push(interpreter.copyOperation(insn, value2));
+                        push(interpreter.copyOperation(insn, value1));
+                        push(value3);
+                        push(value2);
+                        push(value1);
+                        break;
+                    }
+                }
+            } else {
+                value2 = pop();
+                if (value2.getSize() == 1) {
+                    value3 = pop();
+                    if (value3.getSize() == 1) {
+                        push(interpreter.copyOperation(insn, value1));
+                        push(value3);
+                        push(value2);
+                        push(value1);
+                        break;
+                    }
+                } else {
+                    push(interpreter.copyOperation(insn, value1));
+                    push(value2);
+                    push(value1);
+                    break;
+                }
+            }
+            throw new AnalyzerException(insn, "Illegal use of DUP2_X2");
+        case Opcodes.SWAP:
+            value2 = pop();
+            value1 = pop();
+            if (value1.getSize() != 1 || value2.getSize() != 1) {
+                throw new AnalyzerException(insn, "Illegal use of SWAP");
+            }
+            push(interpreter.copyOperation(insn, value2));
+            push(interpreter.copyOperation(insn, value1));
+            break;
+        case Opcodes.IADD:
+        case Opcodes.LADD:
+        case Opcodes.FADD:
+        case Opcodes.DADD:
+        case Opcodes.ISUB:
+        case Opcodes.LSUB:
+        case Opcodes.FSUB:
+        case Opcodes.DSUB:
+        case Opcodes.IMUL:
+        case Opcodes.LMUL:
+        case Opcodes.FMUL:
+        case Opcodes.DMUL:
+        case Opcodes.IDIV:
+        case Opcodes.LDIV:
+        case Opcodes.FDIV:
+        case Opcodes.DDIV:
+        case Opcodes.IREM:
+        case Opcodes.LREM:
+        case Opcodes.FREM:
+        case Opcodes.DREM:
+            value2 = pop();
+            value1 = pop();
+            push(interpreter.binaryOperation(insn, value1, value2));
+            break;
+        case Opcodes.INEG:
+        case Opcodes.LNEG:
+        case Opcodes.FNEG:
+        case Opcodes.DNEG:
+            push(interpreter.unaryOperation(insn, pop()));
+            break;
+        case Opcodes.ISHL:
+        case Opcodes.LSHL:
+        case Opcodes.ISHR:
+        case Opcodes.LSHR:
+        case Opcodes.IUSHR:
+        case Opcodes.LUSHR:
+        case Opcodes.IAND:
+        case Opcodes.LAND:
+        case Opcodes.IOR:
+        case Opcodes.LOR:
+        case Opcodes.IXOR:
+        case Opcodes.LXOR:
+            value2 = pop();
+            value1 = pop();
+            push(interpreter.binaryOperation(insn, value1, value2));
+            break;
+        case Opcodes.IINC:
+            var = ((IincInsnNode) insn).var;
+            setLocal(var, interpreter.unaryOperation(insn, getLocal(var)));
+            break;
+        case Opcodes.I2L:
+        case Opcodes.I2F:
+        case Opcodes.I2D:
+        case Opcodes.L2I:
+        case Opcodes.L2F:
+        case Opcodes.L2D:
+        case Opcodes.F2I:
+        case Opcodes.F2L:
+        case Opcodes.F2D:
+        case Opcodes.D2I:
+        case Opcodes.D2L:
+        case Opcodes.D2F:
+        case Opcodes.I2B:
+        case Opcodes.I2C:
+        case Opcodes.I2S:
+            push(interpreter.unaryOperation(insn, pop()));
+            break;
+        case Opcodes.LCMP:
+        case Opcodes.FCMPL:
+        case Opcodes.FCMPG:
+        case Opcodes.DCMPL:
+        case Opcodes.DCMPG:
+            value2 = pop();
+            value1 = pop();
+            push(interpreter.binaryOperation(insn, value1, value2));
+            break;
+        case Opcodes.IFEQ:
+        case Opcodes.IFNE:
+        case Opcodes.IFLT:
+        case Opcodes.IFGE:
+        case Opcodes.IFGT:
+        case Opcodes.IFLE:
+            interpreter.unaryOperation(insn, pop());
+            break;
+        case Opcodes.IF_ICMPEQ:
+        case Opcodes.IF_ICMPNE:
+        case Opcodes.IF_ICMPLT:
+        case Opcodes.IF_ICMPGE:
+        case Opcodes.IF_ICMPGT:
+        case Opcodes.IF_ICMPLE:
+        case Opcodes.IF_ACMPEQ:
+        case Opcodes.IF_ACMPNE:
+            value2 = pop();
+            value1 = pop();
+            interpreter.binaryOperation(insn, value1, value2);
+            break;
+        case Opcodes.GOTO:
+            break;
+        case Opcodes.JSR:
+            push(interpreter.newOperation(insn));
+            break;
+        case Opcodes.RET:
+            break;
+        case Opcodes.TABLESWITCH:
+        case Opcodes.LOOKUPSWITCH:
+            interpreter.unaryOperation(insn, pop());
+            break;
+        case Opcodes.IRETURN:
+        case Opcodes.LRETURN:
+        case Opcodes.FRETURN:
+        case Opcodes.DRETURN:
+        case Opcodes.ARETURN:
+            value1 = pop();
+            interpreter.unaryOperation(insn, value1);
+            interpreter.returnOperation(insn, value1, returnValue);
+            break;
+        case Opcodes.RETURN:
+            if (returnValue != null) {
+                throw new AnalyzerException(insn, "Incompatible return type");
+            }
+            break;
+        case Opcodes.GETSTATIC:
+            push(interpreter.newOperation(insn));
+            break;
+        case Opcodes.PUTSTATIC:
+            interpreter.unaryOperation(insn, pop());
+            break;
+        case Opcodes.GETFIELD:
+            push(interpreter.unaryOperation(insn, pop()));
+            break;
+        case Opcodes.PUTFIELD:
+            value2 = pop();
+            value1 = pop();
+            interpreter.binaryOperation(insn, value1, value2);
+            break;
+        case Opcodes.INVOKEVIRTUAL:
+        case Opcodes.INVOKESPECIAL:
+        case Opcodes.INVOKESTATIC:
+        case Opcodes.INVOKEINTERFACE: {
+            values = new ArrayList<V>();
+            String desc = ((MethodInsnNode) insn).desc;
+            for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) {
+                values.add(0, pop());
+            }
+            if (insn.getOpcode() != Opcodes.INVOKESTATIC) {
+                values.add(0, pop());
+            }
+            if (Type.getReturnType(desc) == Type.VOID_TYPE) {
+                interpreter.naryOperation(insn, values);
+            } else {
+                push(interpreter.naryOperation(insn, values));
+            }
+            break;
+        }
+        case Opcodes.INVOKEDYNAMIC: {
+            values = new ArrayList<V>();
+            String desc = ((InvokeDynamicInsnNode) insn).desc;
+            for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) {
+                values.add(0, pop());
+            }
+            if (Type.getReturnType(desc) == Type.VOID_TYPE) {
+                interpreter.naryOperation(insn, values);
+            } else {
+                push(interpreter.naryOperation(insn, values));
+            }
+            break;
+        }
+        case Opcodes.NEW:
+            push(interpreter.newOperation(insn));
+            break;
+        case Opcodes.NEWARRAY:
+        case Opcodes.ANEWARRAY:
+        case Opcodes.ARRAYLENGTH:
+            push(interpreter.unaryOperation(insn, pop()));
+            break;
+        case Opcodes.ATHROW:
+            interpreter.unaryOperation(insn, pop());
+            break;
+        case Opcodes.CHECKCAST:
+        case Opcodes.INSTANCEOF:
+            push(interpreter.unaryOperation(insn, pop()));
+            break;
+        case Opcodes.MONITORENTER:
+        case Opcodes.MONITOREXIT:
+            interpreter.unaryOperation(insn, pop());
+            break;
+        case Opcodes.MULTIANEWARRAY:
+            values = new ArrayList<V>();
+            for (int i = ((MultiANewArrayInsnNode) insn).dims; i > 0; --i) {
+                values.add(0, pop());
+            }
+            push(interpreter.naryOperation(insn, values));
+            break;
+        case Opcodes.IFNULL:
+        case Opcodes.IFNONNULL:
+            interpreter.unaryOperation(insn, pop());
+            break;
+        default:
+            throw new RuntimeException("Illegal opcode " + insn.getOpcode());
+        }
+    }
+
+    /**
+     * Merges this frame with the given frame.
+     * 
+     * @param frame
+     *            a frame.
+     * @param interpreter
+     *            the interpreter used to merge values.
+     * @return <tt>true</tt> if this frame has been changed as a result of the
+     *         merge operation, or <tt>false</tt> otherwise.
+     * @throws AnalyzerException
+     *             if the frames have incompatible sizes.
+     */
+    public boolean merge(final Frame<? extends V> frame,
+            final Interpreter<V> interpreter) throws AnalyzerException {
+        if (top != frame.top) {
+            throw new AnalyzerException(null, "Incompatible stack heights");
+        }
+        boolean changes = false;
+        for (int i = 0; i < locals + top; ++i) {
+            V v = interpreter.merge(values[i], frame.values[i]);
+            if (!v.equals(values[i])) {
+                values[i] = v;
+                changes = true;
+            }
+        }
+        return changes;
+    }
+
+    /**
+     * Merges this frame with the given frame (case of a RET instruction).
+     * 
+     * @param frame
+     *            a frame
+     * @param access
+     *            the local variables that have been accessed by the subroutine
+     *            to which the RET instruction corresponds.
+     * @return <tt>true</tt> if this frame has been changed as a result of the
+     *         merge operation, or <tt>false</tt> otherwise.
+     */
+    public boolean merge(final Frame<? extends V> frame, final boolean[] access) {
+        boolean changes = false;
+        for (int i = 0; i < locals; ++i) {
+            if (!access[i] && !values[i].equals(frame.values[i])) {
+                values[i] = frame.values[i];
+                changes = true;
+            }
+        }
+        return changes;
+    }
+
+    /**
+     * Returns a string representation of this frame.
+     * 
+     * @return a string representation of this frame.
+     */
+    @Override
+    public String toString() {
+        StringBuffer b = new StringBuffer();
+        for (int i = 0; i < getLocals(); ++i) {
+            b.append(getLocal(i));
+        }
+        b.append(' ');
+        for (int i = 0; i < getStackSize(); ++i) {
+            b.append(getStack(i).toString());
+        }
+        return b.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java
new file mode 100644
index 0000000..b7c94c8
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java
@@ -0,0 +1,226 @@
+/***
+ * 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.List;
+
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
+
+/**
+ * A semantic bytecode interpreter. More precisely, this interpreter only
+ * manages the computation of values from other values: it does not manage the
+ * transfer of values to or from the stack, and to or from the local variables.
+ * This separation allows a generic bytecode {@link Analyzer} to work with
+ * various semantic interpreters, without needing to duplicate the code to
+ * simulate the transfer of values.
+ * 
+ * @param <V>
+ *            type of the Value used for the analysis.
+ * 
+ * @author Eric Bruneton
+ */
+public abstract class Interpreter<V extends Value> {
+
+    protected final int api;
+
+    protected Interpreter(final int api) {
+        this.api = api;
+    }
+
+    /**
+     * Creates a new value that represents the given type.
+     * 
+     * Called for method parameters (including <code>this</code>), exception
+     * handler variable and with <code>null</code> type for variables reserved
+     * by long and double types.
+     * 
+     * @param type
+     *            a primitive or reference type, or <tt>null</tt> to represent
+     *            an uninitialized value.
+     * @return a value that represents the given type. The size of the returned
+     *         value must be equal to the size of the given type.
+     */
+    public abstract V newValue(Type type);
+
+    /**
+     * Interprets a bytecode instruction without arguments. This method is
+     * called for the following opcodes:
+     * 
+     * ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4,
+     * ICONST_5, LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0,
+     * DCONST_1, BIPUSH, SIPUSH, LDC, JSR, GETSTATIC, NEW
+     * 
+     * @param insn
+     *            the bytecode instruction to be interpreted.
+     * @return the result of the interpretation of the given instruction.
+     * @throws AnalyzerException
+     *             if an error occured during the interpretation.
+     */
+    public abstract V newOperation(AbstractInsnNode insn)
+            throws AnalyzerException;
+
+    /**
+     * Interprets a bytecode instruction that moves a value on the stack or to
+     * or from local variables. This method is called for the following opcodes:
+     * 
+     * ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE,
+     * ASTORE, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP
+     * 
+     * @param insn
+     *            the bytecode instruction to be interpreted.
+     * @param value
+     *            the value that must be moved by the instruction.
+     * @return the result of the interpretation of the given instruction. The
+     *         returned value must be <tt>equal</tt> to the given value.
+     * @throws AnalyzerException
+     *             if an error occured during the interpretation.
+     */
+    public abstract V copyOperation(AbstractInsnNode insn, V value)
+            throws AnalyzerException;
+
+    /**
+     * Interprets a bytecode instruction with a single argument. This method is
+     * called for the following opcodes:
+     * 
+     * INEG, LNEG, FNEG, DNEG, IINC, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L,
+     * F2D, D2I, D2L, D2F, I2B, I2C, I2S, IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE,
+     * TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN, FRETURN, DRETURN, ARETURN,
+     * PUTSTATIC, GETFIELD, NEWARRAY, ANEWARRAY, ARRAYLENGTH, ATHROW, CHECKCAST,
+     * INSTANCEOF, MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL
+     * 
+     * @param insn
+     *            the bytecode instruction to be interpreted.
+     * @param value
+     *            the argument of the instruction to be interpreted.
+     * @return the result of the interpretation of the given instruction.
+     * @throws AnalyzerException
+     *             if an error occured during the interpretation.
+     */
+    public abstract V unaryOperation(AbstractInsnNode insn, V value)
+            throws AnalyzerException;
+
+    /**
+     * Interprets a bytecode instruction with two arguments. This method is
+     * called for the following opcodes:
+     * 
+     * IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IADD,
+     * LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV,
+     * LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, ISHL, LSHL, ISHR, LSHR, IUSHR,
+     * LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, LCMP, FCMPL, FCMPG, DCMPL,
+     * DCMPG, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
+     * IF_ACMPEQ, IF_ACMPNE, PUTFIELD
+     * 
+     * @param insn
+     *            the bytecode instruction to be interpreted.
+     * @param value1
+     *            the first argument of the instruction to be interpreted.
+     * @param value2
+     *            the second argument of the instruction to be interpreted.
+     * @return the result of the interpretation of the given instruction.
+     * @throws AnalyzerException
+     *             if an error occured during the interpretation.
+     */
+    public abstract V binaryOperation(AbstractInsnNode insn, V value1, V value2)
+            throws AnalyzerException;
+
+    /**
+     * Interprets a bytecode instruction with three arguments. This method is
+     * called for the following opcodes:
+     * 
+     * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE
+     * 
+     * @param insn
+     *            the bytecode instruction to be interpreted.
+     * @param value1
+     *            the first argument of the instruction to be interpreted.
+     * @param value2
+     *            the second argument of the instruction to be interpreted.
+     * @param value3
+     *            the third argument of the instruction to be interpreted.
+     * @return the result of the interpretation of the given instruction.
+     * @throws AnalyzerException
+     *             if an error occured during the interpretation.
+     */
+    public abstract V ternaryOperation(AbstractInsnNode insn, V value1,
+            V value2, V value3) throws AnalyzerException;
+
+    /**
+     * Interprets a bytecode instruction with a variable number of arguments.
+     * This method is called for the following opcodes:
+     * 
+     * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE,
+     * MULTIANEWARRAY and INVOKEDYNAMIC
+     * 
+     * @param insn
+     *            the bytecode instruction to be interpreted.
+     * @param values
+     *            the arguments of the instruction to be interpreted.
+     * @return the result of the interpretation of the given instruction.
+     * @throws AnalyzerException
+     *             if an error occured during the interpretation.
+     */
+    public abstract V naryOperation(AbstractInsnNode insn,
+            List<? extends V> values) throws AnalyzerException;
+
+    /**
+     * Interprets a bytecode return instruction. This method is called for the
+     * following opcodes:
+     * 
+     * IRETURN, LRETURN, FRETURN, DRETURN, ARETURN
+     * 
+     * @param insn
+     *            the bytecode instruction to be interpreted.
+     * @param value
+     *            the argument of the instruction to be interpreted.
+     * @param expected
+     *            the expected return type of the analyzed method.
+     * @throws AnalyzerException
+     *             if an error occured during the interpretation.
+     */
+    public abstract void returnOperation(AbstractInsnNode insn, V value,
+            V expected) throws AnalyzerException;
+
+    /**
+     * Merges two values. The merge operation must return a value that
+     * represents both values (for instance, if the two values are two types,
+     * the merged value must be a common super type of the two types. If the two
+     * values are integer intervals, the merged value must be an interval that
+     * contains the previous ones. Likewise for other types of values).
+     * 
+     * @param v
+     *            a value.
+     * @param w
+     *            another value.
+     * @return the merged value. If the merged value is equal to <tt>v</tt>,
+     *         this method <i>must</i> return <tt>v</tt>.
+     */
+    public abstract V merge(V v, V w);
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java
new file mode 100644
index 0000000..c53beb4
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java
@@ -0,0 +1,320 @@
+/***
+ * 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.List;
+
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * An extended {@link BasicVerifier} that performs more precise verifications.
+ * This verifier computes exact class types, instead of using a single "object
+ * reference" type (as done in the {@link BasicVerifier}).
+ * 
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class SimpleVerifier extends BasicVerifier {
+
+    /**
+     * The class that is verified.
+     */
+    private final Type currentClass;
+
+    /**
+     * The super class of the class that is verified.
+     */
+    private final Type currentSuperClass;
+
+    /**
+     * The interfaces implemented by the class that is verified.
+     */
+    private final List<Type> currentClassInterfaces;
+
+    /**
+     * If the class that is verified is an interface.
+     */
+    private final boolean isInterface;
+
+    /**
+     * The loader to use for referenced classes.
+     */
+    private ClassLoader loader = getClass().getClassLoader();
+
+    /**
+     * Constructs a new {@link SimpleVerifier}.
+     */
+    public SimpleVerifier() {
+        this(null, null, false);
+    }
+
+    /**
+     * Constructs a new {@link SimpleVerifier} to verify a specific class. This
+     * class will not be loaded into the JVM since it may be incorrect.
+     * 
+     * @param currentClass
+     *            the class that is verified.
+     * @param currentSuperClass
+     *            the super class of the class that is verified.
+     * @param isInterface
+     *            if the class that is verified is an interface.
+     */
+    public SimpleVerifier(final Type currentClass,
+            final Type currentSuperClass, final boolean isInterface) {
+        this(currentClass, currentSuperClass, null, isInterface);
+    }
+
+    /**
+     * Constructs a new {@link SimpleVerifier} to verify a specific class. This
+     * class will not be loaded into the JVM since it may be incorrect.
+     * 
+     * @param currentClass
+     *            the class that is verified.
+     * @param currentSuperClass
+     *            the super class of the class that is verified.
+     * @param currentClassInterfaces
+     *            the interfaces implemented by the class that is verified.
+     * @param isInterface
+     *            if the class that is verified is an interface.
+     */
+    public SimpleVerifier(final Type currentClass,
+            final Type currentSuperClass,
+            final List<Type> currentClassInterfaces, final boolean isInterface) {
+        this(ASM5, currentClass, currentSuperClass, currentClassInterfaces,
+                isInterface);
+    }
+
+    protected SimpleVerifier(final int api, final Type currentClass,
+            final Type currentSuperClass,
+            final List<Type> currentClassInterfaces, final boolean isInterface) {
+        super(api);
+        this.currentClass = currentClass;
+        this.currentSuperClass = currentSuperClass;
+        this.currentClassInterfaces = currentClassInterfaces;
+        this.isInterface = isInterface;
+    }
+
+    /**
+     * Set the <code>ClassLoader</code> which will be used to load referenced
+     * classes. This is useful if you are verifying multiple interdependent
+     * classes.
+     * 
+     * @param loader
+     *            a <code>ClassLoader</code> to use
+     */
+    public void setClassLoader(final ClassLoader loader) {
+        this.loader = loader;
+    }
+
+    @Override
+    public BasicValue newValue(final Type type) {
+        if (type == null) {
+            return BasicValue.UNINITIALIZED_VALUE;
+        }
+
+        boolean isArray = type.getSort() == Type.ARRAY;
+        if (isArray) {
+            switch (type.getElementType().getSort()) {
+            case Type.BOOLEAN:
+            case Type.CHAR:
+            case Type.BYTE:
+            case Type.SHORT:
+                return new BasicValue(type);
+            }
+        }
+
+        BasicValue v = super.newValue(type);
+        if (BasicValue.REFERENCE_VALUE.equals(v)) {
+            if (isArray) {
+                v = newValue(type.getElementType());
+                String desc = v.getType().getDescriptor();
+                for (int i = 0; i < type.getDimensions(); ++i) {
+                    desc = '[' + desc;
+                }
+                v = new BasicValue(Type.getType(desc));
+            } else {
+                v = new BasicValue(type);
+            }
+        }
+        return v;
+    }
+
+    @Override
+    protected boolean isArrayValue(final BasicValue value) {
+        Type t = value.getType();
+        return t != null
+                && ("Lnull;".equals(t.getDescriptor()) || t.getSort() == Type.ARRAY);
+    }
+
+    @Override
+    protected BasicValue getElementValue(final BasicValue objectArrayValue)
+            throws AnalyzerException {
+        Type arrayType = objectArrayValue.getType();
+        if (arrayType != null) {
+            if (arrayType.getSort() == Type.ARRAY) {
+                return newValue(Type.getType(arrayType.getDescriptor()
+                        .substring(1)));
+            } else if ("Lnull;".equals(arrayType.getDescriptor())) {
+                return objectArrayValue;
+            }
+        }
+        throw new Error("Internal error");
+    }
+
+    @Override
+    protected boolean isSubTypeOf(final BasicValue value,
+            final BasicValue expected) {
+        Type expectedType = expected.getType();
+        Type type = value.getType();
+        switch (expectedType.getSort()) {
+        case Type.INT:
+        case Type.FLOAT:
+        case Type.LONG:
+        case Type.DOUBLE:
+            return type.equals(expectedType);
+        case Type.ARRAY:
+        case Type.OBJECT:
+            if ("Lnull;".equals(type.getDescriptor())) {
+                return true;
+            } else if (type.getSort() == Type.OBJECT
+                    || type.getSort() == Type.ARRAY) {
+                return isAssignableFrom(expectedType, type);
+            } else {
+                return false;
+            }
+        default:
+            throw new Error("Internal error");
+        }
+    }
+
+    @Override
+    public BasicValue merge(final BasicValue v, final BasicValue w) {
+        if (!v.equals(w)) {
+            Type t = v.getType();
+            Type u = w.getType();
+            if (t != null
+                    && (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY)) {
+                if (u != null
+                        && (u.getSort() == Type.OBJECT || u.getSort() == Type.ARRAY)) {
+                    if ("Lnull;".equals(t.getDescriptor())) {
+                        return w;
+                    }
+                    if ("Lnull;".equals(u.getDescriptor())) {
+                        return v;
+                    }
+                    if (isAssignableFrom(t, u)) {
+                        return v;
+                    }
+                    if (isAssignableFrom(u, t)) {
+                        return w;
+                    }
+                    // TODO case of array classes of the same dimension
+                    // TODO should we look also for a common super interface?
+                    // problem: there may be several possible common super
+                    // interfaces
+                    do {
+                        if (t == null || isInterface(t)) {
+                            return BasicValue.REFERENCE_VALUE;
+                        }
+                        t = getSuperClass(t);
+                        if (isAssignableFrom(t, u)) {
+                            return newValue(t);
+                        }
+                    } while (true);
+                }
+            }
+            return BasicValue.UNINITIALIZED_VALUE;
+        }
+        return v;
+    }
+
+    protected boolean isInterface(final Type t) {
+        if (currentClass != null && t.equals(currentClass)) {
+            return isInterface;
+        }
+        return getClass(t).isInterface();
+    }
+
+    protected Type getSuperClass(final Type t) {
+        if (currentClass != null && t.equals(currentClass)) {
+            return currentSuperClass;
+        }
+        Class<?> c = getClass(t).getSuperclass();
+        return c == null ? null : Type.getType(c);
+    }
+
+    protected boolean isAssignableFrom(final Type t, final Type u) {
+        if (t.equals(u)) {
+            return true;
+        }
+        if (currentClass != null && t.equals(currentClass)) {
+            if (getSuperClass(u) == null) {
+                return false;
+            } else {
+                if (isInterface) {
+                    return u.getSort() == Type.OBJECT
+                            || u.getSort() == Type.ARRAY;
+                }
+                return isAssignableFrom(t, getSuperClass(u));
+            }
+        }
+        if (currentClass != null && u.equals(currentClass)) {
+            if (isAssignableFrom(t, currentSuperClass)) {
+                return true;
+            }
+            if (currentClassInterfaces != null) {
+                for (int i = 0; i < currentClassInterfaces.size(); ++i) {
+                    Type v = currentClassInterfaces.get(i);
+                    if (isAssignableFrom(t, v)) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+        Class<?> tc = getClass(t);
+        if (tc.isInterface()) {
+            tc = Object.class;
+        }
+        return tc.isAssignableFrom(getClass(u));
+    }
+
+    protected Class<?> getClass(final Type t) {
+        try {
+            if (t.getSort() == Type.ARRAY) {
+                return Class.forName(t.getDescriptor().replace('/', '.'),
+                        false, loader);
+            }
+            return Class.forName(t.getClassName(), false, loader);
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException(e.toString());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java
new file mode 100644
index 0000000..2aacb42
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java
@@ -0,0 +1,134 @@
+/***
+ * 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.AbstractSet;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * A set of at most two elements.
+ * 
+ * @author Eric Bruneton
+ */
+class SmallSet<E> extends AbstractSet<E> implements Iterator<E> {
+
+    // if e1 is null, e2 must be null; otherwise e2 must be different from e1
+
+    E e1, e2;
+
+    static final <T> Set<T> emptySet() {
+        return new SmallSet<T>(null, null);
+    }
+
+    SmallSet(final E e1, final E e2) {
+        this.e1 = e1;
+        this.e2 = e2;
+    }
+
+    // -------------------------------------------------------------------------
+    // Implementation of inherited abstract methods
+    // -------------------------------------------------------------------------
+
+    @Override
+    public Iterator<E> iterator() {
+        return new SmallSet<E>(e1, e2);
+    }
+
+    @Override
+    public int size() {
+        return e1 == null ? 0 : (e2 == null ? 1 : 2);
+    }
+
+    // -------------------------------------------------------------------------
+    // Implementation of the Iterator interface
+    // -------------------------------------------------------------------------
+
+    public boolean hasNext() {
+        return e1 != null;
+    }
+
+    public E next() {
+        if (e1 == null) {
+            throw new NoSuchElementException();
+        }
+        E e = e1;
+        e1 = e2;
+        e2 = null;
+        return e;
+    }
+
+    public void remove() {
+    }
+
+    // -------------------------------------------------------------------------
+    // Utility methods
+    // -------------------------------------------------------------------------
+
+    Set<E> union(final SmallSet<E> s) {
+        if ((s.e1 == e1 && s.e2 == e2) || (s.e1 == e2 && s.e2 == e1)) {
+            return this; // if the two sets are equal, return this
+        }
+        if (s.e1 == null) {
+            return this; // if s is empty, return this
+        }
+        if (e1 == null) {
+            return s; // if this is empty, return s
+        }
+        if (s.e2 == null) { // s contains exactly one element
+            if (e2 == null) {
+                return new SmallSet<E>(e1, s.e1); // necessarily e1 != s.e1
+            } else if (s.e1 == e1 || s.e1 == e2) { // s is included in this
+                return this;
+            }
+        }
+        if (e2 == null) { // this contains exactly one element
+            // if (s.e2 == null) { // cannot happen
+            // return new SmallSet(e1, s.e1); // necessarily e1 != s.e1
+            // } else
+            if (e1 == s.e1 || e1 == s.e2) { // this in included in s
+                return s;
+            }
+        }
+        // here we know that there are at least 3 distinct elements
+        HashSet<E> r = new HashSet<E>(4);
+        r.add(e1);
+        if (e2 != null) {
+            r.add(e2);
+        }
+        r.add(s.e1);
+        if (s.e2 != null) {
+            r.add(s.e2);
+        }
+        return r;
+    }
+}


[20/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
index fce84e9..5aa3aff 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
 
 /**
  * Information about the input and output stack map frames of a basic block.
- *
+ * 
  * @author Eric Bruneton
  */
 final class Frame {
@@ -46,14 +46,14 @@ final class Frame {
      * of the first basic block (which is computed from the method descriptor),
      * and by using the previously computed output frames to compute the input
      * state of the other blocks.
-     *
+     * 
      * All output and input frames are stored as arrays of integers. Reference
      * and array types are represented by an index into a type table (which is
      * not the same as the constant pool of the class, in order to avoid adding
      * unnecessary constants in the pool - not all computed frames will end up
      * being stored in the stack map table). This allows very fast type
      * comparisons.
-     *
+     * 
      * Output stack map frames are computed relatively to the input frame of the
      * basic block, which is not yet known when output frames are computed. It
      * is therefore necessary to be able to represent abstract types such as
@@ -61,7 +61,7 @@ final class Frame {
      * position x from the top of the input frame stack" or even "the type at
      * position x in the input frame, with y more (or less) array dimensions".
      * This explains the rather complicated type format used in output frames.
-     *
+     * 
      * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a
      * signed number of array dimensions (from -8 to 7). KIND is either BASE,
      * LOCAL or STACK. BASE is used for types that are not relative to the input
@@ -70,23 +70,23 @@ final class Frame {
      * stack types. VALUE depends on KIND. For LOCAL types, it is an index in
      * the input local variable types. For STACK types, it is a position
      * relatively to the top of input frame stack. For BASE types, it is either
-     * one of the constants defined in FrameVisitor, or for OBJECT and
-     * UNINITIALIZED types, a tag and an index in the type table.
-     *
+     * one of the constants defined below, or for OBJECT and UNINITIALIZED
+     * types, a tag and an index in the type table.
+     * 
      * Output frames can contain types of any kind and with a positive or
      * negative dimension (and even unassigned types, represented by 0 - which
      * does not correspond to any valid type value). Input frames can only
      * contain BASE types of positive or null dimension. In all cases the type
      * table contains only internal type names (array type descriptors are
      * forbidden - dimensions must be represented through the DIM field).
-     *
-     * The LONG and DOUBLE types are always represented by using two slots (LONG +
-     * TOP or DOUBLE + TOP), for local variable types as well as in the operand
-     * stack. This is necessary to be able to simulate DUPx_y instructions,
-     * whose effect would be dependent on the actual type values if types were
-     * always represented by a single slot in the stack (and this is not
-     * possible, since actual type values are not always known - cf LOCAL and
-     * STACK type kinds).
+     * 
+     * The LONG and DOUBLE types are always represented by using two slots (LONG
+     * + TOP or DOUBLE + TOP), for local variable types as well as in the
+     * operand stack. This is necessary to be able to simulate DUPx_y
+     * instructions, whose effect would be dependent on the actual type values
+     * if types were always represented by a single slot in the stack (and this
+     * is not possible, since actual type values are not always known - cf LOCAL
+     * and STACK type kinds).
      */
 
     /**
@@ -107,7 +107,7 @@ final class Frame {
 
     /**
      * Mask to get the kind of a frame type.
-     *
+     * 
      * @see #BASE
      * @see #LOCAL
      * @see #STACK
@@ -117,9 +117,9 @@ final class Frame {
     /**
      * Flag used for LOCAL and STACK types. Indicates that if this type happens
      * to be a long or double type (during the computations of input frames),
-     * then it must be set to TOP because the second word of this value has
-     * been reused to store other data in the basic block. Hence the first word
-     * no longer stores a valid long or double value.
+     * then it must be set to TOP because the second word of this value has been
+     * reused to store other data in the basic block. Hence the first word no
+     * longer stores a valid long or double value.
      */
     static final int TOP_IF_LONG_OR_DOUBLE = 0x800000;
 
@@ -489,10 +489,10 @@ final class Frame {
     /**
      * Relative size of the output stack. The exact semantics of this field
      * depends on the algorithm that is used.
-     *
+     * 
      * When only the maximum stack size is computed, this field is the size of
      * the output stack relatively to the top of the input stack.
-     *
+     * 
      * When the stack map frames are completely computed, this field is the
      * actual number of types in {@link #outputStack}.
      */
@@ -500,7 +500,7 @@ final class Frame {
 
     /**
      * Number of types that are initialized in the basic block.
-     *
+     * 
      * @see #initializations
      */
     private int initializationCount;
@@ -522,8 +522,9 @@ final class Frame {
 
     /**
      * Returns the output frame local variable type at the given index.
-     *
-     * @param local the index of the local that must be returned.
+     * 
+     * @param local
+     *            the index of the local that must be returned.
      * @return the output frame local variable type at the given index.
      */
     private int get(final int local) {
@@ -544,9 +545,11 @@ final class Frame {
 
     /**
      * Sets the output frame local variable type at the given index.
-     *
-     * @param local the index of the local that must be set.
-     * @param type the value of the local that must be set.
+     * 
+     * @param local
+     *            the index of the local that must be set.
+     * @param type
+     *            the value of the local that must be set.
      */
     private void set(final int local, final int type) {
         // creates and/or resizes the output local variables array if necessary
@@ -565,8 +568,9 @@ final class Frame {
 
     /**
      * Pushes a new type onto the output frame stack.
-     *
-     * @param type the type that must be pushed.
+     * 
+     * @param type
+     *            the type that must be pushed.
      */
     private void push(final int type) {
         // creates and/or resizes the output stack array if necessary
@@ -590,11 +594,13 @@ final class Frame {
 
     /**
      * Pushes a new type onto the output frame stack.
-     *
-     * @param cw the ClassWriter to which this label belongs.
-     * @param desc the descriptor of the type to be pushed. Can also be a method
-     *        descriptor (in this case this method pushes its return type onto
-     *        the output frame stack).
+     * 
+     * @param cw
+     *            the ClassWriter to which this label belongs.
+     * @param desc
+     *            the descriptor of the type to be pushed. Can also be a method
+     *            descriptor (in this case this method pushes its return type
+     *            onto the output frame stack).
      */
     private void push(final ClassWriter cw, final String desc) {
         int type = type(cw, desc);
@@ -608,79 +614,81 @@ final class Frame {
 
     /**
      * Returns the int encoding of the given type.
-     *
-     * @param cw the ClassWriter to which this label belongs.
-     * @param desc a type descriptor.
+     * 
+     * @param cw
+     *            the ClassWriter to which this label belongs.
+     * @param desc
+     *            a type descriptor.
      * @return the int encoding of the given type.
      */
     private static int type(final ClassWriter cw, final String desc) {
         String t;
         int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
         switch (desc.charAt(index)) {
-            case 'V':
-                return 0;
+        case 'V':
+            return 0;
+        case 'Z':
+        case 'C':
+        case 'B':
+        case 'S':
+        case 'I':
+            return INTEGER;
+        case 'F':
+            return FLOAT;
+        case 'J':
+            return LONG;
+        case 'D':
+            return DOUBLE;
+        case 'L':
+            // stores the internal name, not the descriptor!
+            t = desc.substring(index + 1, desc.length() - 1);
+            return OBJECT | cw.addType(t);
+            // case '[':
+        default:
+            // extracts the dimensions and the element type
+            int data;
+            int dims = index + 1;
+            while (desc.charAt(dims) == '[') {
+                ++dims;
+            }
+            switch (desc.charAt(dims)) {
             case 'Z':
+                data = BOOLEAN;
+                break;
             case 'C':
+                data = CHAR;
+                break;
             case 'B':
+                data = BYTE;
+                break;
             case 'S':
+                data = SHORT;
+                break;
             case 'I':
-                return INTEGER;
+                data = INTEGER;
+                break;
             case 'F':
-                return FLOAT;
+                data = FLOAT;
+                break;
             case 'J':
-                return LONG;
+                data = LONG;
+                break;
             case 'D':
-                return DOUBLE;
-            case 'L':
-                // stores the internal name, not the descriptor!
-                t = desc.substring(index + 1, desc.length() - 1);
-                return OBJECT | cw.addType(t);
-                // case '[':
+                data = DOUBLE;
+                break;
+            // case 'L':
             default:
-                // extracts the dimensions and the element type
-                int data;
-                int dims = index + 1;
-                while (desc.charAt(dims) == '[') {
-                    ++dims;
-                }
-                switch (desc.charAt(dims)) {
-                    case 'Z':
-                        data = BOOLEAN;
-                        break;
-                    case 'C':
-                        data = CHAR;
-                        break;
-                    case 'B':
-                        data = BYTE;
-                        break;
-                    case 'S':
-                        data = SHORT;
-                        break;
-                    case 'I':
-                        data = INTEGER;
-                        break;
-                    case 'F':
-                        data = FLOAT;
-                        break;
-                    case 'J':
-                        data = LONG;
-                        break;
-                    case 'D':
-                        data = DOUBLE;
-                        break;
-                    // case 'L':
-                    default:
-                        // stores the internal name, not the descriptor
-                        t = desc.substring(dims + 1, desc.length() - 1);
-                        data = OBJECT | cw.addType(t);
-                }
-                return (dims - index) << 28 | data;
+                // stores the internal name, not the descriptor
+                t = desc.substring(dims + 1, desc.length() - 1);
+                data = OBJECT | cw.addType(t);
+            }
+            return (dims - index) << 28 | data;
         }
     }
 
     /**
      * Pops a type from the output frame stack and returns its value.
-     *
+     * 
      * @return the type that has been popped from the output frame stack.
      */
     private int pop() {
@@ -694,8 +702,9 @@ final class Frame {
 
     /**
      * Pops the given number of types from the output frame stack.
-     *
-     * @param elements the number of types that must be popped.
+     * 
+     * @param elements
+     *            the number of types that must be popped.
      */
     private void pop(final int elements) {
         if (outputStackTop >= elements) {
@@ -711,10 +720,11 @@ final class Frame {
 
     /**
      * Pops a type from the output frame stack.
-     *
-     * @param desc the descriptor of the type to be popped. Can also be a method
-     *        descriptor (in this case this method pops the types corresponding
-     *        to the method arguments).
+     * 
+     * @param desc
+     *            the descriptor of the type to be popped. Can also be a method
+     *            descriptor (in this case this method pops the types
+     *            corresponding to the method arguments).
      */
     private void pop(final String desc) {
         char c = desc.charAt(0);
@@ -730,8 +740,9 @@ final class Frame {
     /**
      * Adds a new type to the list of types on which a constructor is invoked in
      * the basic block.
-     *
-     * @param var a type on a which a constructor is invoked.
+     * 
+     * @param var
+     *            a type on a which a constructor is invoked.
      */
     private void init(final int var) {
         // creates and/or resizes the initializations array if necessary
@@ -751,9 +762,11 @@ final class Frame {
     /**
      * Replaces the given type with the appropriate type if it is one of the
      * types on which a constructor is invoked in the basic block.
-     *
-     * @param cw the ClassWriter to which this label belongs.
-     * @param t a type
+     * 
+     * @param cw
+     *            the ClassWriter to which this label belongs.
+     * @param t
+     *            a type
      * @return t or, if t is one of the types on which a constructor is invoked
      *         in the basic block, the type corresponding to this constructor.
      */
@@ -786,18 +799,18 @@ final class Frame {
     /**
      * Initializes the input frame of the first basic block from the method
      * descriptor.
-     *
-     * @param cw the ClassWriter to which this label belongs.
-     * @param access the access flags of the method to which this label belongs.
-     * @param args the formal parameter types of this method.
-     * @param maxLocals the maximum number of local variables of this method.
+     * 
+     * @param cw
+     *            the ClassWriter to which this label belongs.
+     * @param access
+     *            the access flags of the method to which this label belongs.
+     * @param args
+     *            the formal parameter types of this method.
+     * @param maxLocals
+     *            the maximum number of local variables of this method.
      */
-    void initInputFrame(
-        final ClassWriter cw,
-        final int access,
-        final Type[] args,
-        final int maxLocals)
-    {
+    void initInputFrame(final ClassWriter cw, final int access,
+            final Type[] args, final int maxLocals) {
         inputLocals = new int[maxLocals];
         inputStack = new int[0];
         int i = 0;
@@ -822,436 +835,436 @@ final class Frame {
 
     /**
      * Simulates the action of the given instruction on the output stack frame.
-     *
-     * @param opcode the opcode of the instruction.
-     * @param arg the operand of the instruction, if any.
-     * @param cw the class writer to which this label belongs.
-     * @param item the operand of the instructions, if any.
+     * 
+     * @param opcode
+     *            the opcode of the instruction.
+     * @param arg
+     *            the operand of the instruction, if any.
+     * @param cw
+     *            the class writer to which this label belongs.
+     * @param item
+     *            the operand of the instructions, if any.
      */
-    void execute(
-        final int opcode,
-        final int arg,
-        final ClassWriter cw,
-        final Item item)
-    {
+    void execute(final int opcode, final int arg, final ClassWriter cw,
+            final Item item) {
         int t1, t2, t3, t4;
         switch (opcode) {
-            case Opcodes.NOP:
-            case Opcodes.INEG:
-            case Opcodes.LNEG:
-            case Opcodes.FNEG:
-            case Opcodes.DNEG:
-            case Opcodes.I2B:
-            case Opcodes.I2C:
-            case Opcodes.I2S:
-            case Opcodes.GOTO:
-            case Opcodes.RETURN:
-                break;
-            case Opcodes.ACONST_NULL:
-                push(NULL);
-                break;
-            case Opcodes.ICONST_M1:
-            case Opcodes.ICONST_0:
-            case Opcodes.ICONST_1:
-            case Opcodes.ICONST_2:
-            case Opcodes.ICONST_3:
-            case Opcodes.ICONST_4:
-            case Opcodes.ICONST_5:
-            case Opcodes.BIPUSH:
-            case Opcodes.SIPUSH:
-            case Opcodes.ILOAD:
+        case Opcodes.NOP:
+        case Opcodes.INEG:
+        case Opcodes.LNEG:
+        case Opcodes.FNEG:
+        case Opcodes.DNEG:
+        case Opcodes.I2B:
+        case Opcodes.I2C:
+        case Opcodes.I2S:
+        case Opcodes.GOTO:
+        case Opcodes.RETURN:
+            break;
+        case Opcodes.ACONST_NULL:
+            push(NULL);
+            break;
+        case Opcodes.ICONST_M1:
+        case Opcodes.ICONST_0:
+        case Opcodes.ICONST_1:
+        case Opcodes.ICONST_2:
+        case Opcodes.ICONST_3:
+        case Opcodes.ICONST_4:
+        case Opcodes.ICONST_5:
+        case Opcodes.BIPUSH:
+        case Opcodes.SIPUSH:
+        case Opcodes.ILOAD:
+            push(INTEGER);
+            break;
+        case Opcodes.LCONST_0:
+        case Opcodes.LCONST_1:
+        case Opcodes.LLOAD:
+            push(LONG);
+            push(TOP);
+            break;
+        case Opcodes.FCONST_0:
+        case Opcodes.FCONST_1:
+        case Opcodes.FCONST_2:
+        case Opcodes.FLOAD:
+            push(FLOAT);
+            break;
+        case Opcodes.DCONST_0:
+        case Opcodes.DCONST_1:
+        case Opcodes.DLOAD:
+            push(DOUBLE);
+            push(TOP);
+            break;
+        case Opcodes.LDC:
+            switch (item.type) {
+            case ClassWriter.INT:
                 push(INTEGER);
                 break;
-            case Opcodes.LCONST_0:
-            case Opcodes.LCONST_1:
-            case Opcodes.LLOAD:
+            case ClassWriter.LONG:
                 push(LONG);
                 push(TOP);
                 break;
-            case Opcodes.FCONST_0:
-            case Opcodes.FCONST_1:
-            case Opcodes.FCONST_2:
-            case Opcodes.FLOAD:
+            case ClassWriter.FLOAT:
                 push(FLOAT);
                 break;
-            case Opcodes.DCONST_0:
-            case Opcodes.DCONST_1:
-            case Opcodes.DLOAD:
+            case ClassWriter.DOUBLE:
                 push(DOUBLE);
                 push(TOP);
                 break;
-            case Opcodes.LDC:
-                switch (item.type) {
-                    case ClassWriter.INT:
-                        push(INTEGER);
-                        break;
-                    case ClassWriter.LONG:
-                        push(LONG);
-                        push(TOP);
-                        break;
-                    case ClassWriter.FLOAT:
-                        push(FLOAT);
-                        break;
-                    case ClassWriter.DOUBLE:
-                        push(DOUBLE);
-                        push(TOP);
-                        break;
-                    case ClassWriter.CLASS:
-                        push(OBJECT | cw.addType("java/lang/Class"));
-                        break;
-                    case ClassWriter.STR:
-                        push(OBJECT | cw.addType("java/lang/String"));
-                        break;
-                    case ClassWriter.MTYPE:
-                        push(OBJECT | cw.addType("java/lang/invoke/MethodType"));
-                        break;
-                    // case ClassWriter.HANDLE_BASE + [1..9]:
-                    default:
-                        push(OBJECT | cw.addType("java/lang/invoke/MethodHandle"));
-                }
-                break;
-            case Opcodes.ALOAD:
-                push(get(arg));
-                break;
-            case Opcodes.IALOAD:
-            case Opcodes.BALOAD:
-            case Opcodes.CALOAD:
-            case Opcodes.SALOAD:
-                pop(2);
-                push(INTEGER);
-                break;
-            case Opcodes.LALOAD:
-            case Opcodes.D2L:
-                pop(2);
-                push(LONG);
-                push(TOP);
-                break;
-            case Opcodes.FALOAD:
-                pop(2);
-                push(FLOAT);
+            case ClassWriter.CLASS:
+                push(OBJECT | cw.addType("java/lang/Class"));
                 break;
-            case Opcodes.DALOAD:
-            case Opcodes.L2D:
-                pop(2);
-                push(DOUBLE);
-                push(TOP);
+            case ClassWriter.STR:
+                push(OBJECT | cw.addType("java/lang/String"));
                 break;
-            case Opcodes.AALOAD:
-                pop(1);
-                t1 = pop();
-                push(ELEMENT_OF + t1);
+            case ClassWriter.MTYPE:
+                push(OBJECT | cw.addType("java/lang/invoke/MethodType"));
                 break;
-            case Opcodes.ISTORE:
-            case Opcodes.FSTORE:
-            case Opcodes.ASTORE:
-                t1 = pop();
-                set(arg, t1);
-                if (arg > 0) {
-                    t2 = get(arg - 1);
-                    // if t2 is of kind STACK or LOCAL we cannot know its size!
-                    if (t2 == LONG || t2 == DOUBLE) {
-                        set(arg - 1, TOP);
-                    } else if ((t2 & KIND) != BASE) {
-                        set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
-                    }
+            // case ClassWriter.HANDLE_BASE + [1..9]:
+            default:
+                push(OBJECT | cw.addType("java/lang/invoke/MethodHandle"));
+            }
+            break;
+        case Opcodes.ALOAD:
+            push(get(arg));
+            break;
+        case Opcodes.IALOAD:
+        case Opcodes.BALOAD:
+        case Opcodes.CALOAD:
+        case Opcodes.SALOAD:
+            pop(2);
+            push(INTEGER);
+            break;
+        case Opcodes.LALOAD:
+        case Opcodes.D2L:
+            pop(2);
+            push(LONG);
+            push(TOP);
+            break;
+        case Opcodes.FALOAD:
+            pop(2);
+            push(FLOAT);
+            break;
+        case Opcodes.DALOAD:
+        case Opcodes.L2D:
+            pop(2);
+            push(DOUBLE);
+            push(TOP);
+            break;
+        case Opcodes.AALOAD:
+            pop(1);
+            t1 = pop();
+            push(ELEMENT_OF + t1);
+            break;
+        case Opcodes.ISTORE:
+        case Opcodes.FSTORE:
+        case Opcodes.ASTORE:
+            t1 = pop();
+            set(arg, t1);
+            if (arg > 0) {
+                t2 = get(arg - 1);
+                // if t2 is of kind STACK or LOCAL we cannot know its size!
+                if (t2 == LONG || t2 == DOUBLE) {
+                    set(arg - 1, TOP);
+                } else if ((t2 & KIND) != BASE) {
+                    set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
                 }
-                break;
-            case Opcodes.LSTORE:
-            case Opcodes.DSTORE:
-                pop(1);
-                t1 = pop();
-                set(arg, t1);
-                set(arg + 1, TOP);
-                if (arg > 0) {
-                    t2 = get(arg - 1);
-                    // if t2 is of kind STACK or LOCAL we cannot know its size!
-                    if (t2 == LONG || t2 == DOUBLE) {
-                        set(arg - 1, TOP);
-                    } else if ((t2 & KIND) != BASE) {
-                        set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
-                    }
+            }
+            break;
+        case Opcodes.LSTORE:
+        case Opcodes.DSTORE:
+            pop(1);
+            t1 = pop();
+            set(arg, t1);
+            set(arg + 1, TOP);
+            if (arg > 0) {
+                t2 = get(arg - 1);
+                // if t2 is of kind STACK or LOCAL we cannot know its size!
+                if (t2 == LONG || t2 == DOUBLE) {
+                    set(arg - 1, TOP);
+                } else if ((t2 & KIND) != BASE) {
+                    set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
                 }
-                break;
-            case Opcodes.IASTORE:
-            case Opcodes.BASTORE:
-            case Opcodes.CASTORE:
-            case Opcodes.SASTORE:
-            case Opcodes.FASTORE:
-            case Opcodes.AASTORE:
-                pop(3);
-                break;
-            case Opcodes.LASTORE:
-            case Opcodes.DASTORE:
-                pop(4);
-                break;
-            case Opcodes.POP:
-            case Opcodes.IFEQ:
-            case Opcodes.IFNE:
-            case Opcodes.IFLT:
-            case Opcodes.IFGE:
-            case Opcodes.IFGT:
-            case Opcodes.IFLE:
-            case Opcodes.IRETURN:
-            case Opcodes.FRETURN:
-            case Opcodes.ARETURN:
-            case Opcodes.TABLESWITCH:
-            case Opcodes.LOOKUPSWITCH:
-            case Opcodes.ATHROW:
-            case Opcodes.MONITORENTER:
-            case Opcodes.MONITOREXIT:
-            case Opcodes.IFNULL:
-            case Opcodes.IFNONNULL:
-                pop(1);
-                break;
-            case Opcodes.POP2:
-            case Opcodes.IF_ICMPEQ:
-            case Opcodes.IF_ICMPNE:
-            case Opcodes.IF_ICMPLT:
-            case Opcodes.IF_ICMPGE:
-            case Opcodes.IF_ICMPGT:
-            case Opcodes.IF_ICMPLE:
-            case Opcodes.IF_ACMPEQ:
-            case Opcodes.IF_ACMPNE:
-            case Opcodes.LRETURN:
-            case Opcodes.DRETURN:
-                pop(2);
-                break;
-            case Opcodes.DUP:
-                t1 = pop();
-                push(t1);
-                push(t1);
-                break;
-            case Opcodes.DUP_X1:
-                t1 = pop();
-                t2 = pop();
-                push(t1);
-                push(t2);
-                push(t1);
-                break;
-            case Opcodes.DUP_X2:
-                t1 = pop();
-                t2 = pop();
-                t3 = pop();
-                push(t1);
-                push(t3);
-                push(t2);
-                push(t1);
-                break;
-            case Opcodes.DUP2:
-                t1 = pop();
-                t2 = pop();
-                push(t2);
-                push(t1);
-                push(t2);
-                push(t1);
-                break;
-            case Opcodes.DUP2_X1:
-                t1 = pop();
-                t2 = pop();
-                t3 = pop();
-                push(t2);
-                push(t1);
-                push(t3);
-                push(t2);
-                push(t1);
-                break;
-            case Opcodes.DUP2_X2:
-                t1 = pop();
-                t2 = pop();
-                t3 = pop();
-                t4 = pop();
-                push(t2);
-                push(t1);
-                push(t4);
-                push(t3);
-                push(t2);
-                push(t1);
-                break;
-            case Opcodes.SWAP:
+            }
+            break;
+        case Opcodes.IASTORE:
+        case Opcodes.BASTORE:
+        case Opcodes.CASTORE:
+        case Opcodes.SASTORE:
+        case Opcodes.FASTORE:
+        case Opcodes.AASTORE:
+            pop(3);
+            break;
+        case Opcodes.LASTORE:
+        case Opcodes.DASTORE:
+            pop(4);
+            break;
+        case Opcodes.POP:
+        case Opcodes.IFEQ:
+        case Opcodes.IFNE:
+        case Opcodes.IFLT:
+        case Opcodes.IFGE:
+        case Opcodes.IFGT:
+        case Opcodes.IFLE:
+        case Opcodes.IRETURN:
+        case Opcodes.FRETURN:
+        case Opcodes.ARETURN:
+        case Opcodes.TABLESWITCH:
+        case Opcodes.LOOKUPSWITCH:
+        case Opcodes.ATHROW:
+        case Opcodes.MONITORENTER:
+        case Opcodes.MONITOREXIT:
+        case Opcodes.IFNULL:
+        case Opcodes.IFNONNULL:
+            pop(1);
+            break;
+        case Opcodes.POP2:
+        case Opcodes.IF_ICMPEQ:
+        case Opcodes.IF_ICMPNE:
+        case Opcodes.IF_ICMPLT:
+        case Opcodes.IF_ICMPGE:
+        case Opcodes.IF_ICMPGT:
+        case Opcodes.IF_ICMPLE:
+        case Opcodes.IF_ACMPEQ:
+        case Opcodes.IF_ACMPNE:
+        case Opcodes.LRETURN:
+        case Opcodes.DRETURN:
+            pop(2);
+            break;
+        case Opcodes.DUP:
+            t1 = pop();
+            push(t1);
+            push(t1);
+            break;
+        case Opcodes.DUP_X1:
+            t1 = pop();
+            t2 = pop();
+            push(t1);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.DUP_X2:
+            t1 = pop();
+            t2 = pop();
+            t3 = pop();
+            push(t1);
+            push(t3);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.DUP2:
+            t1 = pop();
+            t2 = pop();
+            push(t2);
+            push(t1);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.DUP2_X1:
+            t1 = pop();
+            t2 = pop();
+            t3 = pop();
+            push(t2);
+            push(t1);
+            push(t3);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.DUP2_X2:
+            t1 = pop();
+            t2 = pop();
+            t3 = pop();
+            t4 = pop();
+            push(t2);
+            push(t1);
+            push(t4);
+            push(t3);
+            push(t2);
+            push(t1);
+            break;
+        case Opcodes.SWAP:
+            t1 = pop();
+            t2 = pop();
+            push(t1);
+            push(t2);
+            break;
+        case Opcodes.IADD:
+        case Opcodes.ISUB:
+        case Opcodes.IMUL:
+        case Opcodes.IDIV:
+        case Opcodes.IREM:
+        case Opcodes.IAND:
+        case Opcodes.IOR:
+        case Opcodes.IXOR:
+        case Opcodes.ISHL:
+        case Opcodes.ISHR:
+        case Opcodes.IUSHR:
+        case Opcodes.L2I:
+        case Opcodes.D2I:
+        case Opcodes.FCMPL:
+        case Opcodes.FCMPG:
+            pop(2);
+            push(INTEGER);
+            break;
+        case Opcodes.LADD:
+        case Opcodes.LSUB:
+        case Opcodes.LMUL:
+        case Opcodes.LDIV:
+        case Opcodes.LREM:
+        case Opcodes.LAND:
+        case Opcodes.LOR:
+        case Opcodes.LXOR:
+            pop(4);
+            push(LONG);
+            push(TOP);
+            break;
+        case Opcodes.FADD:
+        case Opcodes.FSUB:
+        case Opcodes.FMUL:
+        case Opcodes.FDIV:
+        case Opcodes.FREM:
+        case Opcodes.L2F:
+        case Opcodes.D2F:
+            pop(2);
+            push(FLOAT);
+            break;
+        case Opcodes.DADD:
+        case Opcodes.DSUB:
+        case Opcodes.DMUL:
+        case Opcodes.DDIV:
+        case Opcodes.DREM:
+            pop(4);
+            push(DOUBLE);
+            push(TOP);
+            break;
+        case Opcodes.LSHL:
+        case Opcodes.LSHR:
+        case Opcodes.LUSHR:
+            pop(3);
+            push(LONG);
+            push(TOP);
+            break;
+        case Opcodes.IINC:
+            set(arg, INTEGER);
+            break;
+        case Opcodes.I2L:
+        case Opcodes.F2L:
+            pop(1);
+            push(LONG);
+            push(TOP);
+            break;
+        case Opcodes.I2F:
+            pop(1);
+            push(FLOAT);
+            break;
+        case Opcodes.I2D:
+        case Opcodes.F2D:
+            pop(1);
+            push(DOUBLE);
+            push(TOP);
+            break;
+        case Opcodes.F2I:
+        case Opcodes.ARRAYLENGTH:
+        case Opcodes.INSTANCEOF:
+            pop(1);
+            push(INTEGER);
+            break;
+        case Opcodes.LCMP:
+        case Opcodes.DCMPL:
+        case Opcodes.DCMPG:
+            pop(4);
+            push(INTEGER);
+            break;
+        case Opcodes.JSR:
+        case Opcodes.RET:
+            throw new RuntimeException(
+                    "JSR/RET are not supported with computeFrames option");
+        case Opcodes.GETSTATIC:
+            push(cw, item.strVal3);
+            break;
+        case Opcodes.PUTSTATIC:
+            pop(item.strVal3);
+            break;
+        case Opcodes.GETFIELD:
+            pop(1);
+            push(cw, item.strVal3);
+            break;
+        case Opcodes.PUTFIELD:
+            pop(item.strVal3);
+            pop();
+            break;
+        case Opcodes.INVOKEVIRTUAL:
+        case Opcodes.INVOKESPECIAL:
+        case Opcodes.INVOKESTATIC:
+        case Opcodes.INVOKEINTERFACE:
+            pop(item.strVal3);
+            if (opcode != Opcodes.INVOKESTATIC) {
                 t1 = pop();
-                t2 = pop();
-                push(t1);
-                push(t2);
-                break;
-            case Opcodes.IADD:
-            case Opcodes.ISUB:
-            case Opcodes.IMUL:
-            case Opcodes.IDIV:
-            case Opcodes.IREM:
-            case Opcodes.IAND:
-            case Opcodes.IOR:
-            case Opcodes.IXOR:
-            case Opcodes.ISHL:
-            case Opcodes.ISHR:
-            case Opcodes.IUSHR:
-            case Opcodes.L2I:
-            case Opcodes.D2I:
-            case Opcodes.FCMPL:
-            case Opcodes.FCMPG:
-                pop(2);
-                push(INTEGER);
-                break;
-            case Opcodes.LADD:
-            case Opcodes.LSUB:
-            case Opcodes.LMUL:
-            case Opcodes.LDIV:
-            case Opcodes.LREM:
-            case Opcodes.LAND:
-            case Opcodes.LOR:
-            case Opcodes.LXOR:
-                pop(4);
-                push(LONG);
-                push(TOP);
-                break;
-            case Opcodes.FADD:
-            case Opcodes.FSUB:
-            case Opcodes.FMUL:
-            case Opcodes.FDIV:
-            case Opcodes.FREM:
-            case Opcodes.L2F:
-            case Opcodes.D2F:
-                pop(2);
-                push(FLOAT);
-                break;
-            case Opcodes.DADD:
-            case Opcodes.DSUB:
-            case Opcodes.DMUL:
-            case Opcodes.DDIV:
-            case Opcodes.DREM:
-                pop(4);
-                push(DOUBLE);
-                push(TOP);
-                break;
-            case Opcodes.LSHL:
-            case Opcodes.LSHR:
-            case Opcodes.LUSHR:
-                pop(3);
-                push(LONG);
-                push(TOP);
-                break;
-            case Opcodes.IINC:
-                set(arg, INTEGER);
-                break;
-            case Opcodes.I2L:
-            case Opcodes.F2L:
-                pop(1);
-                push(LONG);
-                push(TOP);
-                break;
-            case Opcodes.I2F:
-                pop(1);
-                push(FLOAT);
-                break;
-            case Opcodes.I2D:
-            case Opcodes.F2D:
-                pop(1);
-                push(DOUBLE);
-                push(TOP);
-                break;
-            case Opcodes.F2I:
-            case Opcodes.ARRAYLENGTH:
-            case Opcodes.INSTANCEOF:
-                pop(1);
-                push(INTEGER);
-                break;
-            case Opcodes.LCMP:
-            case Opcodes.DCMPL:
-            case Opcodes.DCMPG:
-                pop(4);
-                push(INTEGER);
-                break;
-            case Opcodes.JSR:
-            case Opcodes.RET:
-                throw new RuntimeException("JSR/RET are not supported with computeFrames option");
-            case Opcodes.GETSTATIC:
-                push(cw, item.strVal3);
-                break;
-            case Opcodes.PUTSTATIC:
-                pop(item.strVal3);
-                break;
-            case Opcodes.GETFIELD:
-                pop(1);
-                push(cw, item.strVal3);
-                break;
-            case Opcodes.PUTFIELD:
-                pop(item.strVal3);
-                pop();
-                break;
-            case Opcodes.INVOKEVIRTUAL:
-            case Opcodes.INVOKESPECIAL:
-            case Opcodes.INVOKESTATIC:
-            case Opcodes.INVOKEINTERFACE:
-                pop(item.strVal3);
-                if (opcode != Opcodes.INVOKESTATIC) {
-                    t1 = pop();
-                    if (opcode == Opcodes.INVOKESPECIAL
-                            && item.strVal2.charAt(0) == '<')
-                    {
-                        init(t1);
-                    }
+                if (opcode == Opcodes.INVOKESPECIAL
+                        && item.strVal2.charAt(0) == '<') {
+                    init(t1);
                 }
-                push(cw, item.strVal3);
+            }
+            push(cw, item.strVal3);
+            break;
+        case Opcodes.INVOKEDYNAMIC:
+            pop(item.strVal2);
+            push(cw, item.strVal2);
+            break;
+        case Opcodes.NEW:
+            push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
+            break;
+        case Opcodes.NEWARRAY:
+            pop();
+            switch (arg) {
+            case Opcodes.T_BOOLEAN:
+                push(ARRAY_OF | BOOLEAN);
                 break;
-            case Opcodes.INVOKEDYNAMIC:
-                pop(item.strVal2);
-                push(cw, item.strVal2);
+            case Opcodes.T_CHAR:
+                push(ARRAY_OF | CHAR);
                 break;
-            case Opcodes.NEW:
-                push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
+            case Opcodes.T_BYTE:
+                push(ARRAY_OF | BYTE);
                 break;
-            case Opcodes.NEWARRAY:
-                pop();
-                switch (arg) {
-                    case Opcodes.T_BOOLEAN:
-                        push(ARRAY_OF | BOOLEAN);
-                        break;
-                    case Opcodes.T_CHAR:
-                        push(ARRAY_OF | CHAR);
-                        break;
-                    case Opcodes.T_BYTE:
-                        push(ARRAY_OF | BYTE);
-                        break;
-                    case Opcodes.T_SHORT:
-                        push(ARRAY_OF | SHORT);
-                        break;
-                    case Opcodes.T_INT:
-                        push(ARRAY_OF | INTEGER);
-                        break;
-                    case Opcodes.T_FLOAT:
-                        push(ARRAY_OF | FLOAT);
-                        break;
-                    case Opcodes.T_DOUBLE:
-                        push(ARRAY_OF | DOUBLE);
-                        break;
-                    // case Opcodes.T_LONG:
-                    default:
-                        push(ARRAY_OF | LONG);
-                        break;
-                }
+            case Opcodes.T_SHORT:
+                push(ARRAY_OF | SHORT);
                 break;
-            case Opcodes.ANEWARRAY:
-                String s = item.strVal1;
-                pop();
-                if (s.charAt(0) == '[') {
-                    push(cw, '[' + s);
-                } else {
-                    push(ARRAY_OF | OBJECT | cw.addType(s));
-                }
+            case Opcodes.T_INT:
+                push(ARRAY_OF | INTEGER);
                 break;
-            case Opcodes.CHECKCAST:
-                s = item.strVal1;
-                pop();
-                if (s.charAt(0) == '[') {
-                    push(cw, s);
-                } else {
-                    push(OBJECT | cw.addType(s));
-                }
+            case Opcodes.T_FLOAT:
+                push(ARRAY_OF | FLOAT);
+                break;
+            case Opcodes.T_DOUBLE:
+                push(ARRAY_OF | DOUBLE);
                 break;
-            // case Opcodes.MULTIANEWARRAY:
+            // case Opcodes.T_LONG:
             default:
-                pop(arg);
-                push(cw, item.strVal1);
+                push(ARRAY_OF | LONG);
                 break;
+            }
+            break;
+        case Opcodes.ANEWARRAY:
+            String s = item.strVal1;
+            pop();
+            if (s.charAt(0) == '[') {
+                push(cw, '[' + s);
+            } else {
+                push(ARRAY_OF | OBJECT | cw.addType(s));
+            }
+            break;
+        case Opcodes.CHECKCAST:
+            s = item.strVal1;
+            pop();
+            if (s.charAt(0) == '[') {
+                push(cw, s);
+            } else {
+                push(OBJECT | cw.addType(s));
+            }
+            break;
+        // case Opcodes.MULTIANEWARRAY:
+        default:
+            pop(arg);
+            push(cw, item.strVal1);
+            break;
         }
     }
 
@@ -1259,11 +1272,14 @@ final class Frame {
      * Merges the input frame of the given basic block with the input and output
      * frames of this basic block. Returns <tt>true</tt> if the input frame of
      * the given label has been changed by this operation.
-     *
-     * @param cw the ClassWriter to which this label belongs.
-     * @param frame the basic block whose input frame must be updated.
-     * @param edge the kind of the {@link Edge} between this label and 'label'.
-     *        See {@link Edge#info}.
+     * 
+     * @param cw
+     *            the ClassWriter to which this label belongs.
+     * @param frame
+     *            the basic block whose input frame must be updated.
+     * @param edge
+     *            the kind of the {@link Edge} between this label and 'label'.
+     *            See {@link Edge#info}.
      * @return <tt>true</tt> if the input frame of the given label has been
      *         changed by this operation.
      */
@@ -1294,7 +1310,8 @@ final class Frame {
                         } else {
                             t = dim + inputStack[nStack - (s & VALUE)];
                         }
-                        if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 && (t == LONG || t == DOUBLE)) {
+                        if ((s & TOP_IF_LONG_OR_DOUBLE) != 0
+                                && (t == LONG || t == DOUBLE)) {
                             t = TOP;
                         }
                     }
@@ -1346,7 +1363,8 @@ final class Frame {
                 } else {
                     t = dim + inputStack[nStack - (s & VALUE)];
                 }
-                if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 && (t == LONG || t == DOUBLE)) {
+                if ((s & TOP_IF_LONG_OR_DOUBLE) != 0
+                        && (t == LONG || t == DOUBLE)) {
                     t = TOP;
                 }
             }
@@ -1362,20 +1380,20 @@ final class Frame {
      * Merges the type at the given index in the given type array with the given
      * type. Returns <tt>true</tt> if the type array has been modified by this
      * operation.
-     *
-     * @param cw the ClassWriter to which this label belongs.
-     * @param t the type with which the type array element must be merged.
-     * @param types an array of types.
-     * @param index the index of the type that must be merged in 'types'.
+     * 
+     * @param cw
+     *            the ClassWriter to which this label belongs.
+     * @param t
+     *            the type with which the type array element must be merged.
+     * @param types
+     *            an array of types.
+     * @param index
+     *            the index of the type that must be merged in 'types'.
      * @return <tt>true</tt> if the type array has been modified by this
      *         operation.
      */
-    private static boolean merge(
-        final ClassWriter cw,
-        int t,
-        final int[] types,
-        final int index)
-    {
+    private static boolean merge(final ClassWriter cw, int t,
+            final int[] types, final int index) {
         int u = types[index];
         if (u == t) {
             // if the types are equal, merge(u,t)=u, so there is no change
@@ -1399,6 +1417,7 @@ final class Frame {
                 // if t is the NULL type, merge(u,t)=u, so there is no change
                 return false;
             } else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) {
+                // if t and u have the same dimension and same base kind
                 if ((u & BASE_KIND) == OBJECT) {
                     // if t is also a reference type, and if u and t have the
                     // same dimension merge(u,t) = dim(t) | common parent of the
@@ -1411,9 +1430,13 @@ final class Frame {
                     v = OBJECT | cw.addType("java/lang/Object");
                 }
             } else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) {
-                // if t is any other reference or array type,
-                // merge(u,t)=java/lang/Object
-                v = OBJECT | cw.addType("java/lang/Object");
+                // if t is any other reference or array type, the merged type
+                // is Object, or min(dim(u), dim(t)) | java/lang/Object is u
+                // and t have different array dimensions
+                int tdim = t & DIM;
+                int udim = u & DIM;
+                v = (udim != tdim ? Math.min(tdim, udim) : 0) | OBJECT
+                        | cw.addType("java/lang/Object");
             } else {
                 // if t is any other type, merge(u,t)=TOP
                 v = TOP;

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
index e8906fe..e01fd40 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
@@ -32,7 +32,7 @@ package org.apache.tapestry5.internal.plastic.asm;
 
 /**
  * A reference to a field or a method.
- *
+ * 
  * @author Remi Forax
  * @author Eric Bruneton
  */
@@ -49,7 +49,8 @@ public final class Handle {
     final int tag;
 
     /**
-     * The internal name of the field or method designed by this handle.
+     * The internal name of the class that owns the field or method designated
+     * by this handle.
      */
     final String owner;
 
@@ -65,19 +66,24 @@ public final class Handle {
 
     /**
      * Constructs a new field or method handle.
-     *
-     * @param tag the kind of field or method designated by this Handle. Must be
-     *        {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
-     *        {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
-     *        {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
-     *        {@link Opcodes#H_INVOKESPECIAL},
-     *        {@link Opcodes#H_NEWINVOKESPECIAL} or
-     *        {@link Opcodes#H_INVOKEINTERFACE}.
-     * @param owner the internal name of the field or method designed by this
-     *        handle.
-     * @param name the name of the field or method designated by this handle.
-     * @param desc the descriptor of the field or method designated by this
-     *        handle.
+     * 
+     * @param tag
+     *            the kind of field or method designated by this Handle. Must be
+     *            {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
+     *            {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
+     *            {@link Opcodes#H_INVOKEVIRTUAL},
+     *            {@link Opcodes#H_INVOKESTATIC},
+     *            {@link Opcodes#H_INVOKESPECIAL},
+     *            {@link Opcodes#H_NEWINVOKESPECIAL} or
+     *            {@link Opcodes#H_INVOKEINTERFACE}.
+     * @param owner
+     *            the internal name of the class that owns the field or method
+     *            designated by this handle.
+     * @param name
+     *            the name of the field or method designated by this handle.
+     * @param desc
+     *            the descriptor of the field or method designated by this
+     *            handle.
      */
     public Handle(int tag, String owner, String name, String desc) {
         this.tag = tag;
@@ -88,7 +94,7 @@ public final class Handle {
 
     /**
      * Returns the kind of field or method designated by this handle.
-     *
+     * 
      * @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
      *         {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
      *         {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
@@ -101,11 +107,11 @@ public final class Handle {
     }
 
     /**
-     * Returns the internal name of the field or method designed by this
-     * handle.
-     *
-     * @return the internal name of the field or method designed by this
-     *         handle.
+     * Returns the internal name of the class that owns the field or method
+     * designated by this handle.
+     * 
+     * @return the internal name of the class that owns the field or method
+     *         designated by this handle.
      */
     public String getOwner() {
         return owner;
@@ -113,7 +119,7 @@ public final class Handle {
 
     /**
      * Returns the name of the field or method designated by this handle.
-     *
+     * 
      * @return the name of the field or method designated by this handle.
      */
     public String getName() {
@@ -122,7 +128,7 @@ public final class Handle {
 
     /**
      * Returns the descriptor of the field or method designated by this handle.
-     *
+     * 
      * @return the descriptor of the field or method designated by this handle.
      */
     public String getDesc() {
@@ -138,8 +144,8 @@ public final class Handle {
             return false;
         }
         Handle h = (Handle) obj;
-        return tag == h.tag && owner.equals(h.owner)
-                && name.equals(h.name) && desc.equals(h.desc);
+        return tag == h.tag && owner.equals(h.owner) && name.equals(h.name)
+                && desc.equals(h.desc);
     }
 
     @Override
@@ -149,8 +155,13 @@ public final class Handle {
 
     /**
      * Returns the textual representation of this handle. The textual
-     * representation is: <pre>owner '.' name desc ' ' '(' tag ')'</pre>. As
-     * this format is unambiguous, it can be parsed if necessary.
+     * representation is:
+     * 
+     * <pre>
+     * owner '.' name desc ' ' '(' tag ')'
+     * </pre>
+     * 
+     * . As this format is unambiguous, it can be parsed if necessary.
      */
     @Override
     public String toString() {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
index 94ac8e5..a387654 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
 
 /**
  * Information about an exception handler block.
- *
+ * 
  * @author Eric Bruneton
  */
 class Handler {
@@ -71,10 +71,13 @@ class Handler {
     /**
      * Removes the range between start and end from the given exception
      * handlers.
-     *
-     * @param h an exception handler list.
-     * @param start the start of the range to be removed.
-     * @param end the end of the range to be removed. Maybe null.
+     * 
+     * @param h
+     *            an exception handler list.
+     * @param start
+     *            the start of the range to be removed.
+     * @param end
+     *            the end of the range to be removed. Maybe null.
      * @return the exception handler list with the start-end range removed.
      */
     static Handler remove(Handler h, Label start, Label end) {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java
index 4fab86a..fa4f454 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java
@@ -32,7 +32,7 @@ package org.apache.tapestry5.internal.plastic.asm;
 /**
  * A constant pool item. Constant pool items can be created with the 'newXXX'
  * methods in the {@link ClassWriter} class.
- *
+ * 
  * @author Eric Bruneton
  */
 final class Item {
@@ -52,11 +52,11 @@ final class Item {
      * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
      * {@link ClassWriter#METH}, {@link ClassWriter#IMETH},
      * {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
-     *
-     * MethodHandle constant 9 variations are stored using a range
-     * of 9 values from {@link ClassWriter#HANDLE_BASE} + 1 to
+     * 
+     * MethodHandle constant 9 variations are stored using a range of 9 values
+     * from {@link ClassWriter#HANDLE_BASE} + 1 to
      * {@link ClassWriter#HANDLE_BASE} + 9.
-     *
+     * 
      * Special Item types are used for Items that are stored in the ClassWriter
      * {@link ClassWriter#typeTable}, instead of the constant pool, in order to
      * avoid clashes with normal constant pool items in the ClassWriter constant
@@ -114,8 +114,9 @@ final class Item {
     /**
      * Constructs an uninitialized {@link Item} for constant pool element at
      * given position.
-     *
-     * @param index index of the item to be constructed.
+     * 
+     * @param index
+     *            index of the item to be constructed.
      */
     Item(final int index) {
         this.index = index;
@@ -123,9 +124,11 @@ final class Item {
 
     /**
      * Constructs a copy of the given item.
-     *
-     * @param index index of the item to be constructed.
-     * @param i the item that must be copied into the item to be constructed.
+     * 
+     * @param index
+     *            index of the item to be constructed.
+     * @param i
+     *            the item that must be copied into the item to be constructed.
      */
     Item(final int index, final Item i) {
         this.index = index;
@@ -140,8 +143,9 @@ final class Item {
 
     /**
      * Sets this item to an integer item.
-     *
-     * @param intVal the value of this item.
+     * 
+     * @param intVal
+     *            the value of this item.
      */
     void set(final int intVal) {
         this.type = ClassWriter.INT;
@@ -151,8 +155,9 @@ final class Item {
 
     /**
      * Sets this item to a long item.
-     *
-     * @param longVal the value of this item.
+     * 
+     * @param longVal
+     *            the value of this item.
      */
     void set(final long longVal) {
         this.type = ClassWriter.LONG;
@@ -162,8 +167,9 @@ final class Item {
 
     /**
      * Sets this item to a float item.
-     *
-     * @param floatVal the value of this item.
+     * 
+     * @param floatVal
+     *            the value of this item.
      */
     void set(final float floatVal) {
         this.type = ClassWriter.FLOAT;
@@ -173,8 +179,9 @@ final class Item {
 
     /**
      * Sets this item to a double item.
-     *
-     * @param doubleVal the value of this item.
+     * 
+     * @param doubleVal
+     *            the value of this item.
      */
     void set(final double doubleVal) {
         this.type = ClassWriter.DOUBLE;
@@ -184,50 +191,54 @@ final class Item {
 
     /**
      * Sets this item to an item that do not hold a primitive value.
-     *
-     * @param type the type of this item.
-     * @param strVal1 first part of the value of this item.
-     * @param strVal2 second part of the value of this item.
-     * @param strVal3 third part of the value of this item.
+     * 
+     * @param type
+     *            the type of this item.
+     * @param strVal1
+     *            first part of the value of this item.
+     * @param strVal2
+     *            second part of the value of this item.
+     * @param strVal3
+     *            third part of the value of this item.
      */
-    void set(
-        final int type,
-        final String strVal1,
-        final String strVal2,
-        final String strVal3)
-    {
+    void set(final int type, final String strVal1, final String strVal2,
+            final String strVal3) {
         this.type = type;
         this.strVal1 = strVal1;
         this.strVal2 = strVal2;
         this.strVal3 = strVal3;
         switch (type) {
-            case ClassWriter.UTF8:
-            case ClassWriter.STR:
-            case ClassWriter.CLASS:
-            case ClassWriter.MTYPE:
-            case ClassWriter.TYPE_NORMAL:
-                hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
-                return;
-            case ClassWriter.NAME_TYPE:
-                hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
-                        * strVal2.hashCode());
-                return;
-                // ClassWriter.FIELD:
-                // ClassWriter.METH:
-                // ClassWriter.IMETH:
-                // ClassWriter.HANDLE_BASE + 1..9
-            default:
-                hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
-                        * strVal2.hashCode() * strVal3.hashCode());
+        case ClassWriter.UTF8:
+        case ClassWriter.STR:
+        case ClassWriter.CLASS:
+        case ClassWriter.MTYPE:
+        case ClassWriter.TYPE_NORMAL:
+            hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
+            return;
+        case ClassWriter.NAME_TYPE: {
+            hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+                    * strVal2.hashCode());
+            return;
+        }
+        // ClassWriter.FIELD:
+        // ClassWriter.METH:
+        // ClassWriter.IMETH:
+        // ClassWriter.HANDLE_BASE + 1..9
+        default:
+            hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+                    * strVal2.hashCode() * strVal3.hashCode());
         }
     }
 
     /**
      * Sets the item to an InvokeDynamic item.
-     *
-     * @param name invokedynamic's name.
-     * @param desc invokedynamic's desc.
-     * @param bsmIndex zero based index into the class attribute BootrapMethods.
+     * 
+     * @param name
+     *            invokedynamic's name.
+     * @param desc
+     *            invokedynamic's desc.
+     * @param bsmIndex
+     *            zero based index into the class attribute BootrapMethods.
      */
     void set(String name, String desc, int bsmIndex) {
         this.type = ClassWriter.INDY;
@@ -240,11 +251,13 @@ final class Item {
 
     /**
      * Sets the item to a BootstrapMethod item.
-     *
-     * @param position position in byte in the class attribute BootrapMethods.
-     * @param hashCode hashcode of the item. This hashcode is processed from
-     *        the hashcode of the bootstrap method and the hashcode of
-     *        all bootstrap arguments.
+     * 
+     * @param position
+     *            position in byte in the class attribute BootrapMethods.
+     * @param hashCode
+     *            hashcode of the item. This hashcode is processed from the
+     *            hashcode of the bootstrap method and the hashcode of all
+     *            bootstrap arguments.
      */
     void set(int position, int hashCode) {
         this.type = ClassWriter.BSM;
@@ -255,42 +268,43 @@ final class Item {
     /**
      * Indicates if the given item is equal to this one. <i>This method assumes
      * that the two items have the same {@link #type}</i>.
-     *
-     * @param i the item to be compared to this one. Both items must have the
-     *       same {@link #type}.
+     * 
+     * @param i
+     *            the item to be compared to this one. Both items must have the
+     *            same {@link #type}.
      * @return <tt>true</tt> if the given item if equal to this one,
      *         <tt>false</tt> otherwise.
      */
     boolean isEqualTo(final Item i) {
         switch (type) {
-            case ClassWriter.UTF8:
-            case ClassWriter.STR:
-            case ClassWriter.CLASS:
-            case ClassWriter.MTYPE:
-            case ClassWriter.TYPE_NORMAL:
-                return i.strVal1.equals(strVal1);
-            case ClassWriter.TYPE_MERGED:
-            case ClassWriter.LONG:
-            case ClassWriter.DOUBLE:
-                return i.longVal == longVal;
-            case ClassWriter.INT:
-            case ClassWriter.FLOAT:
-                return i.intVal == intVal;
-            case ClassWriter.TYPE_UNINIT:
-                return i.intVal == intVal && i.strVal1.equals(strVal1);
-            case ClassWriter.NAME_TYPE:
-                return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
-            case ClassWriter.INDY:
-                return i.longVal == longVal && i.strVal1.equals(strVal1)
-                        && i.strVal2.equals(strVal2);
-
-            // case ClassWriter.FIELD:
-            // case ClassWriter.METH:
-            // case ClassWriter.IMETH:
-            // case ClassWriter.HANDLE_BASE + 1..9
-            default:
-                return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2)
-                        && i.strVal3.equals(strVal3);
+        case ClassWriter.UTF8:
+        case ClassWriter.STR:
+        case ClassWriter.CLASS:
+        case ClassWriter.MTYPE:
+        case ClassWriter.TYPE_NORMAL:
+            return i.strVal1.equals(strVal1);
+        case ClassWriter.TYPE_MERGED:
+        case ClassWriter.LONG:
+        case ClassWriter.DOUBLE:
+            return i.longVal == longVal;
+        case ClassWriter.INT:
+        case ClassWriter.FLOAT:
+            return i.intVal == intVal;
+        case ClassWriter.TYPE_UNINIT:
+            return i.intVal == intVal && i.strVal1.equals(strVal1);
+        case ClassWriter.NAME_TYPE:
+            return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
+        case ClassWriter.INDY: {
+            return i.longVal == longVal && i.strVal1.equals(strVal1)
+                    && i.strVal2.equals(strVal2);
+        }
+        // case ClassWriter.FIELD:
+        // case ClassWriter.METH:
+        // case ClassWriter.IMETH:
+        // case ClassWriter.HANDLE_BASE + 1..9
+        default:
+            return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2)
+                    && i.strVal3.equals(strVal3);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
index ef338c3..c0bbe7e 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
@@ -32,10 +32,10 @@ package org.apache.tapestry5.internal.plastic.asm;
 /**
  * A label represents a position in the bytecode of a method. Labels are used
  * for jump, goto, and switch instructions, and for try catch blocks. A label
- * designates the <i>instruction</i> that is just after. Note however that
- * there can be other elements between a label and the instruction it
- * designates (such as other labels, stack map frames, line numbers, etc.).
- *
+ * designates the <i>instruction</i> that is just after. Note however that there
+ * can be other elements between a label and the instruction it designates (such
+ * as other labels, stack map frames, line numbers, etc.).
+ * 
  * @author Eric Bruneton
  */
 public class Label {
@@ -110,14 +110,14 @@ public class Label {
     /**
      * Field used to associate user information to a label. Warning: this field
      * is used by the ASM tree package. In order to use it with the ASM tree
-     * package you must override the {@link
-     * org.apache.tapestry5.internal.plastic.asm.tree.MethodNode#getLabelNode} method.
+     * package you must override the
+     * {@link org.apache.tapestry5.internal.plastic.asm.tree.MethodNode#getLabelNode} method.
      */
     public Object info;
 
     /**
      * Flags that indicate the status of this label.
-     *
+     * 
      * @see #DEBUG
      * @see #RESOLVED
      * @see #RESIZED
@@ -154,7 +154,7 @@ public class Label {
      * indicates if this reference uses 2 or 4 bytes, and its absolute value
      * gives the position of the bytecode instruction. This array is also used
      * as a bitset to store the subroutines to which a basic block belongs. This
-     * information is needed in {@linked  MethodWriter#visitMaxs}, after all
+     * information is needed in {@linked MethodWriter#visitMaxs}, after all
      * forward references have been resolved. Hence the same array can be used
      * for both purposes without problems.
      */
@@ -170,19 +170,19 @@ public class Label {
      * represented by the Label object that corresponds to the first instruction
      * of this basic block. Each node also stores the list of its successors in
      * the graph, as a linked list of Edge objects.
-     *
+     * 
      * The control flow analysis algorithms used to compute the maximum stack
      * size or the stack map frames are similar and use two steps. The first
      * step, during the visit of each instruction, builds information about the
      * state of the local variables and the operand stack at the end of each
      * basic block, called the "output frame", <i>relatively</i> to the frame
      * state at the beginning of the basic block, which is called the "input
-     * frame", and which is <i>unknown</i> during this step. The second step,
-     * in {@link MethodWriter#visitMaxs}, is a fix point algorithm that
-     * computes information about the input frame of each basic block, from the
-     * input state of the first basic block (known from the method signature),
-     * and by the using the previously computed relative output frames.
-     *
+     * frame", and which is <i>unknown</i> during this step. The second step, in
+     * {@link MethodWriter#visitMaxs}, is a fix point algorithm that computes
+     * information about the input frame of each basic block, from the input
+     * state of the first basic block (known from the method signature), and by
+     * the using the previously computed relative output frames.
+     * 
      * The algorithm used to compute the maximum stack size only computes the
      * relative output and absolute input stack heights, while the algorithm
      * used to compute stack map frames computes relative output frames and
@@ -192,10 +192,10 @@ public class Label {
     /**
      * Start of the output stack relatively to the input stack. The exact
      * semantics of this field depends on the algorithm that is used.
-     *
+     * 
      * When only the maximum stack size is computed, this field is the number of
      * elements in the input stack.
-     *
+     * 
      * When the stack map frames are completely computed, this field is the
      * offset of the first output stack element relatively to the top of the
      * input stack. This offset is always negative or null. A null offset means
@@ -240,7 +240,7 @@ public class Label {
      * main loop of the fix point algorithm used in the second step of the
      * control flow analysis algorithms. It is also used in
      * {@link #visitSubroutine} to avoid using a recursive method.
-     *
+     * 
      * @see MethodWriter#visitMaxs
      */
     Label next;
@@ -264,13 +264,15 @@ public class Label {
      * from the start of the method's bytecode. <i>This method is intended for
      * {@link Attribute} sub classes, and is normally not needed by class
      * generators or adapters.</i>
-     *
+     * 
      * @return the offset corresponding to this label.
-     * @throws IllegalStateException if this label is not resolved yet.
+     * @throws IllegalStateException
+     *             if this label is not resolved yet.
      */
     public int getOffset() {
         if ((status & RESOLVED) == 0) {
-            throw new IllegalStateException("Label offset position has not been resolved yet");
+            throw new IllegalStateException(
+                    "Label offset position has not been resolved yet");
         }
         return position;
     }
@@ -280,22 +282,22 @@ public class Label {
      * position of the label is known, the offset is computed and written
      * directly. Otherwise, a null offset is written and a new forward reference
      * is declared for this label.
-     *
-     * @param owner the code writer that calls this method.
-     * @param out the bytecode of the method.
-     * @param source the position of first byte of the bytecode instruction that
-     *        contains this label.
-     * @param wideOffset <tt>true</tt> if the reference must be stored in 4
-     *        bytes, or <tt>false</tt> if it must be stored with 2 bytes.
-     * @throws IllegalArgumentException if this label has not been created by
-     *         the given code writer.
-     */
-    void put(
-        final MethodWriter owner,
-        final ByteVector out,
-        final int source,
-        final boolean wideOffset)
-    {
+     * 
+     * @param owner
+     *            the code writer that calls this method.
+     * @param out
+     *            the bytecode of the method.
+     * @param source
+     *            the position of first byte of the bytecode instruction that
+     *            contains this label.
+     * @param wideOffset
+     *            <tt>true</tt> if the reference must be stored in 4 bytes, or
+     *            <tt>false</tt> if it must be stored with 2 bytes.
+     * @throws IllegalArgumentException
+     *             if this label has not been created by the given code writer.
+     */
+    void put(final MethodWriter owner, final ByteVector out, final int source,
+            final boolean wideOffset) {
         if ((status & RESOLVED) == 0) {
             if (wideOffset) {
                 addReference(-1 - source, out.length);
@@ -318,26 +320,22 @@ public class Label {
      * for a true forward reference, i.e. only if this label is not resolved
      * yet. For backward references, the offset of the reference can be, and
      * must be, computed and stored directly.
-     *
-     * @param sourcePosition the position of the referencing instruction. This
-     *        position will be used to compute the offset of this forward
-     *        reference.
-     * @param referencePosition the position where the offset for this forward
-     *        reference must be stored.
-     */
-    private void addReference(
-        final int sourcePosition,
-        final int referencePosition)
-    {
+     * 
+     * @param sourcePosition
+     *            the position of the referencing instruction. This position
+     *            will be used to compute the offset of this forward reference.
+     * @param referencePosition
+     *            the position where the offset for this forward reference must
+     *            be stored.
+     */
+    private void addReference(final int sourcePosition,
+            final int referencePosition) {
         if (srcAndRefPositions == null) {
             srcAndRefPositions = new int[6];
         }
         if (referenceCount >= srcAndRefPositions.length) {
             int[] a = new int[srcAndRefPositions.length + 6];
-            System.arraycopy(srcAndRefPositions,
-                    0,
-                    a,
-                    0,
+            System.arraycopy(srcAndRefPositions, 0, a, 0,
                     srcAndRefPositions.length);
             srcAndRefPositions = a;
         }
@@ -350,10 +348,13 @@ public class Label {
      * when this label is added to the bytecode of the method, i.e. when its
      * position becomes known. This method fills in the blanks that where left
      * in the bytecode by each forward reference previously added to this label.
-     *
-     * @param owner the code writer that calls this method.
-     * @param position the position of this label in the bytecode.
-     * @param data the bytecode of the method.
+     * 
+     * @param owner
+     *            the code writer that calls this method.
+     * @param position
+     *            the position of this label in the bytecode.
+     * @param data
+     *            the bytecode of the method.
      * @return <tt>true</tt> if a blank that was left for this label was to
      *         small to store the offset. In such a case the corresponding jump
      *         instruction is replaced with a pseudo instruction (using unused
@@ -361,14 +362,12 @@ public class Label {
      *         instructions will need to be replaced with true instructions with
      *         wider offsets (4 bytes instead of 2). This is done in
      *         {@link MethodWriter#resizeInstructions}.
-     * @throws IllegalArgumentException if this label has already been resolved,
-     *         or if it has not been created by the given code writer.
-     */
-    boolean resolve(
-        final MethodWriter owner,
-        final int position,
-        final byte[] data)
-    {
+     * @throws IllegalArgumentException
+     *             if this label has already been resolved, or if it has not
+     *             been created by the given code writer.
+     */
+    boolean resolve(final MethodWriter owner, final int position,
+            final byte[] data) {
         boolean needUpdate = false;
         this.status |= RESOLVED;
         this.position = position;
@@ -417,7 +416,7 @@ public class Label {
      * isolated label or for the first label in a series of successive labels,
      * this method returns the label itself. For other labels it returns the
      * first label of the series.
-     *
+     * 
      * @return the first label of the series to which this label belongs.
      */
     Label getFirst() {
@@ -430,8 +429,9 @@ public class Label {
 
     /**
      * Returns true is this basic block belongs to the given subroutine.
-     *
-     * @param id a subroutine id.
+     * 
+     * @param id
+     *            a subroutine id.
      * @return true is this basic block belongs to the given subroutine.
      */
     boolean inSubroutine(final long id) {
@@ -444,8 +444,9 @@ public class Label {
     /**
      * Returns true if this basic block and the given one belong to a common
      * subroutine.
-     *
-     * @param block another basic block.
+     * 
+     * @param block
+     *            another basic block.
      * @return true if this basic block and the given one belong to a common
      *         subroutine.
      */
@@ -463,9 +464,11 @@ public class Label {
 
     /**
      * Marks this basic block as belonging to the given subroutine.
-     *
-     * @param id a subroutine id.
-     * @param nbSubroutines the total number of subroutines in the method.
+     * 
+     * @param id
+     *            a subroutine id.
+     * @param nbSubroutines
+     *            the total number of subroutines in the method.
      */
     void addToSubroutine(final long id, final int nbSubroutines) {
         if ((status & VISITED) == 0) {
@@ -480,15 +483,17 @@ public class Label {
      * blocks as belonging to this subroutine. This method follows the control
      * flow graph to find all the blocks that are reachable from the current
      * block WITHOUT following any JSR target.
-     *
-     * @param JSR a JSR block that jumps to this subroutine. If this JSR is not
-     *        null it is added to the successor of the RET blocks found in the
-     *        subroutine.
-     * @param id the id of this subroutine.
-     * @param nbSubroutines the total number of subroutines in the method.
-     */
-    void visitSubroutine(final Label JSR, final long id, final int nbSubroutines)
-    {
+     * 
+     * @param JSR
+     *            a JSR block that jumps to this subroutine. If this JSR is not
+     *            null it is added to the successor of the RET blocks found in
+     *            the subroutine.
+     * @param id
+     *            the id of this subroutine.
+     * @param nbSubroutines
+     *            the total number of subroutines in the method.
+     */
+    void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) {
         // user managed stack of labels, to avoid using a recursive method
         // (recursivity can lead to stack overflow with very large methods)
         Label stack = this;
@@ -545,7 +550,7 @@ public class Label {
 
     /**
      * Returns a string representation of this label.
-     *
+     * 
      * @return a string representation of this label.
      */
     @Override


[11/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-frames.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-frames.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-frames.properties
new file mode 100644
index 0000000..ecf580f
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-frames.properties
@@ -0,0 +1,62 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+org/objectweb/asm/Frame/remove=true
+
+# field mappings
+
+org/objectweb/asm/ClassWriter.typeCount=-
+org/objectweb/asm/ClassWriter.typeTable=-
+
+org/objectweb/asm/Label.frame=-
+
+org/objectweb/asm/MethodWriter.frameCount=-
+org/objectweb/asm/MethodWriter.stackMap=-
+org/objectweb/asm/MethodWriter.previousFrameOffset=-
+org/objectweb/asm/MethodWriter.previousFrame=-
+org/objectweb/asm/MethodWriter.frameIndex=-
+org/objectweb/asm/MethodWriter.frame=-
+
+# method mappings
+
+org/objectweb/asm/ClassReader.readFrameType([Ljava/lang/Object;II[C[Lorg/objectweb/asm/Label;)I=-
+
+org/objectweb/asm/ClassWriter.addType(Ljava/lang/String;)I=-
+org/objectweb/asm/ClassWriter.addUninitializedType(Ljava/lang/String;I)I=-
+org/objectweb/asm/ClassWriter.addType(Lorg/objectweb/asm/Item;)Lorg/objectweb/asm/Item;=-
+org/objectweb/asm/ClassWriter.getMergedType(II)I=-
+
+org/objectweb/asm/MethodWriter.startFrame(III)V=-
+org/objectweb/asm/MethodWriter.endFrame()V=-
+org/objectweb/asm/MethodWriter.writeFrame()V=-
+org/objectweb/asm/MethodWriter.writeFrameTypes(II)V=-
+org/objectweb/asm/MethodWriter.writeFrameType(Ljava/lang/Object;)V=-

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-resize.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-resize.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-resize.properties
new file mode 100644
index 0000000..97f7e34
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-resize.properties
@@ -0,0 +1,37 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+# field mappings
+
+# method mappings
+
+org/objectweb/asm/MethodWriter.resizeInstructions()V=-
\ 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/optimizer/shrink-signatures.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-signatures.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-signatures.properties
new file mode 100644
index 0000000..6a48623
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-signatures.properties
@@ -0,0 +1,43 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+org/objectweb/asm/signature/SignatureReader/remove=true
+org/objectweb/asm/signature/SignatureVisitor/remove=true
+org/objectweb/asm/signature/SignatureWriter/remove=true
+
+# field mappings
+
+org/objectweb/asm/ClassWriter.signature=-
+
+org/objectweb/asm/FieldWriter.signature=-
+
+org/objectweb/asm/MethodWriter.signature=-

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-writer.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-writer.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-writer.properties
new file mode 100644
index 0000000..1c83ca2
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-writer.properties
@@ -0,0 +1,66 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+org/objectweb/asm/AnnotationWriter/remove=true
+org/objectweb/asm/ByteVector/remove=true
+org/objectweb/asm/ClassWriter/remove=true
+org/objectweb/asm/Edge/remove=true
+org/objectweb/asm/FieldWriter/remove=true
+org/objectweb/asm/Frame/remove=true
+org/objectweb/asm/Handler/remove=true
+org/objectweb/asm/Item/remove=true
+org/objectweb/asm/MethodWriter/remove=true
+
+# field mappings
+
+org/objectweb/asm/Label.position=-
+org/objectweb/asm/Label.referenceCount=-
+org/objectweb/asm/Label.srcAndRefPositions=-
+org/objectweb/asm/Label.inputStackTop=-
+org/objectweb/asm/Label.outputStackMax=-
+org/objectweb/asm/Label.frame=-
+org/objectweb/asm/Label.successor=-
+org/objectweb/asm/Label.successors=-
+org/objectweb/asm/Label.next=-
+
+# method mappings
+
+org/objectweb/asm/ClassReader.copyPool(Lorg/objectweb/asm/ClassWriter;)V=-
+
+org/objectweb/asm/Label.addReference(II)V=-
+org/objectweb/asm/Label.put(Lorg/objectweb/asm/MethodWriter;Lorg/objectweb/asm/ByteVector;IZ)V=-
+org/objectweb/asm/Label.resolve(Lorg/objectweb/asm/MethodWriter;I[B)Z=-
+org/objectweb/asm/Label.getFirst()Lorg/objectweb/asm/Label;=-
+org/objectweb/asm/Label.inSubroutine(J)Z=-
+org/objectweb/asm/Label.inSameSubroutine(Lorg/objectweb/asm/Label;)Z=-
+org/objectweb/asm/Label.addToSubroutine(JI)V=-
+org/objectweb/asm/Label.visitSubroutine(Lorg/objectweb/asm/Label;JI)V=-

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink.properties
new file mode 100644
index 0000000..6b2a41f
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink.properties
@@ -0,0 +1,380 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+#org/objectweb/asm/Edge=org/objectweb/asm/a
+#org/objectweb/asm/Item=org/objectweb/asm/b
+#org/objectweb/asm/FieldWriter=org/objectweb/asm/c
+#org/objectweb/asm/MethodWriter=org/objectweb/asm/d
+#org/objectweb/asm/AnnotationWriter=org/objectweb/asm/e
+#org/objectweb/asm/Context=org/objectweb/asm/f
+
+java/lang/StringBuilder=java/lang/StringBuffer
+
+
+# field mappings
+
+org/objectweb/asm/AnnotationWriter.cw=a
+org/objectweb/asm/AnnotationWriter.size=b
+org/objectweb/asm/AnnotationWriter.named=c
+org/objectweb/asm/AnnotationWriter.bv=d
+org/objectweb/asm/AnnotationWriter.parent=e
+org/objectweb/asm/AnnotationWriter.offset=f
+org/objectweb/asm/AnnotationWriter.next=g
+org/objectweb/asm/AnnotationWriter.prev=h
+
+org/objectweb/asm/Attribute.next=a
+org/objectweb/asm/Attribute.value=b
+
+org/objectweb/asm/ByteVector.data=a
+org/objectweb/asm/ByteVector.length=b
+
+org/objectweb/asm/ClassReader.items=a
+org/objectweb/asm/ClassReader.strings=c
+org/objectweb/asm/ClassReader.maxStringLength=d
+#org/objectweb/asm/ClassReader.header=e
+
+org/objectweb/asm/Context.attrs=a
+org/objectweb/asm/Context.flags=b
+org/objectweb/asm/Context.buffer=c
+org/objectweb/asm/Context.bootstrapMethods=d
+org/objectweb/asm/Context.access=e
+org/objectweb/asm/Context.name=f
+org/objectweb/asm/Context.desc=g
+org/objectweb/asm/Context.labels=h
+org/objectweb/asm/Context.typeRef=i
+org/objectweb/asm/Context.typePath=j
+org/objectweb/asm/Context.offset=k
+org/objectweb/asm/Context.start=l
+org/objectweb/asm/Context.end=m
+org/objectweb/asm/Context.index=n
+org/objectweb/asm/Context.offset=o
+org/objectweb/asm/Context.mode=p
+org/objectweb/asm/Context.localCount=q
+org/objectweb/asm/Context.localDiff=r
+org/objectweb/asm/Context.local=s
+org/objectweb/asm/Context.stackCount=t
+org/objectweb/asm/Context.stack=u
+
+org/objectweb/asm/ClassWriter.TYPE=a
+org/objectweb/asm/ClassWriter.version=b
+org/objectweb/asm/ClassWriter.index=c
+org/objectweb/asm/ClassWriter.pool=d
+org/objectweb/asm/ClassWriter.items=e
+org/objectweb/asm/ClassWriter.threshold=f
+org/objectweb/asm/ClassWriter.key=g
+org/objectweb/asm/ClassWriter.key2=h
+org/objectweb/asm/ClassWriter.key3=i
+org/objectweb/asm/ClassWriter.key4=j
+org/objectweb/asm/ClassWriter.access=k
+org/objectweb/asm/ClassWriter.name=l
+org/objectweb/asm/ClassWriter.signature=m
+org/objectweb/asm/ClassWriter.superName=n
+org/objectweb/asm/ClassWriter.interfaceCount=o
+org/objectweb/asm/ClassWriter.interfaces=p
+org/objectweb/asm/ClassWriter.sourceFile=q
+org/objectweb/asm/ClassWriter.sourceDebug=r
+org/objectweb/asm/ClassWriter.enclosingMethodOwner=s
+org/objectweb/asm/ClassWriter.enclosingMethod=t
+org/objectweb/asm/ClassWriter.anns=u
+org/objectweb/asm/ClassWriter.ianns=v
+org/objectweb/asm/ClassWriter.tanns=N
+org/objectweb/asm/ClassWriter.itanns=O
+org/objectweb/asm/ClassWriter.attrs=w
+org/objectweb/asm/ClassWriter.innerClassesCount=x
+org/objectweb/asm/ClassWriter.innerClasses=y
+org/objectweb/asm/ClassWriter.bootstrapMethodsCount=z
+org/objectweb/asm/ClassWriter.bootstrapMethods=A
+org/objectweb/asm/ClassWriter.firstField=B
+org/objectweb/asm/ClassWriter.lastField=C
+org/objectweb/asm/ClassWriter.firstMethod=D
+org/objectweb/asm/ClassWriter.lastMethod=E
+org/objectweb/asm/ClassWriter.computeMaxs=F
+org/objectweb/asm/ClassWriter.typeCount=G
+org/objectweb/asm/ClassWriter.typeTable=H
+org/objectweb/asm/ClassWriter.thisName=I
+org/objectweb/asm/ClassWriter.computeFrames=J
+org/objectweb/asm/ClassWriter.computeMaxs=K
+org/objectweb/asm/ClassWriter.invalidFrames=L
+org/objectweb/asm/ClassWriter.cr=M
+    
+org/objectweb/asm/Edge.info=a
+org/objectweb/asm/Edge.successor=b
+org/objectweb/asm/Edge.next=c
+
+org/objectweb/asm/Handler.start=a
+org/objectweb/asm/Handler.end=b
+org/objectweb/asm/Handler.handler=c
+org/objectweb/asm/Handler.desc=d
+org/objectweb/asm/Handler.type=e
+org/objectweb/asm/Handler.next=f
+
+org/objectweb/asm/FieldWriter.cw=b
+org/objectweb/asm/FieldWriter.access=c
+org/objectweb/asm/FieldWriter.name=d
+org/objectweb/asm/FieldWriter.desc=e
+org/objectweb/asm/FieldWriter.signature=f
+org/objectweb/asm/FieldWriter.value=g
+org/objectweb/asm/FieldWriter.anns=h
+org/objectweb/asm/FieldWriter.ianns=i
+org/objectweb/asm/FieldWriter.tanns=k
+org/objectweb/asm/FieldWriter.itanns=l
+org/objectweb/asm/FieldWriter.attrs=j
+
+org/objectweb/asm/Item.index=a
+org/objectweb/asm/Item.type=b
+org/objectweb/asm/Item.intVal=c
+org/objectweb/asm/Item.longVal=d
+org/objectweb/asm/Item.strVal1=g
+org/objectweb/asm/Item.strVal2=h
+org/objectweb/asm/Item.strVal3=i
+org/objectweb/asm/Item.hashCode=j
+org/objectweb/asm/Item.next=k
+
+org/objectweb/asm/Label.status=a
+org/objectweb/asm/Label.line=b
+org/objectweb/asm/Label.position=c
+org/objectweb/asm/Label.referenceCount=d
+org/objectweb/asm/Label.srcAndRefPositions=e
+org/objectweb/asm/Label.inputStackTop=f
+org/objectweb/asm/Label.outputStackMax=g
+org/objectweb/asm/Label.frame=h
+org/objectweb/asm/Label.successor=i
+org/objectweb/asm/Label.successors=j
+org/objectweb/asm/Label.next=k
+
+org/objectweb/asm/Frame.SIZE=a
+org/objectweb/asm/Frame.owner=b
+org/objectweb/asm/Frame.inputLocals=c
+org/objectweb/asm/Frame.inputStack=d
+org/objectweb/asm/Frame.outputLocals=e
+org/objectweb/asm/Frame.outputStack=f
+org/objectweb/asm/Frame.outputStackTop=g
+org/objectweb/asm/Frame.initializationCount=h
+org/objectweb/asm/Frame.initializations=i
+
+org/objectweb/asm/MethodWriter.cw=b
+org/objectweb/asm/MethodWriter.access=c
+org/objectweb/asm/MethodWriter.name=d
+org/objectweb/asm/MethodWriter.desc=e
+org/objectweb/asm/MethodWriter.descriptor=f
+org/objectweb/asm/MethodWriter.signature=g
+org/objectweb/asm/MethodWriter.classReaderOffset=h
+org/objectweb/asm/MethodWriter.classReaderLength=i
+org/objectweb/asm/MethodWriter.exceptionCount=j
+org/objectweb/asm/MethodWriter.exceptions=k
+org/objectweb/asm/MethodWriter.annd=l
+org/objectweb/asm/MethodWriter.anns=m
+org/objectweb/asm/MethodWriter.ianns=n
+org/objectweb/asm/MethodWriter.tanns=U
+org/objectweb/asm/MethodWriter.itanns=V
+org/objectweb/asm/MethodWriter.panns=o
+org/objectweb/asm/MethodWriter.ipanns=p
+org/objectweb/asm/MethodWriter.attrs=q
+org/objectweb/asm/MethodWriter.code=r
+org/objectweb/asm/MethodWriter.maxStack=s
+org/objectweb/asm/MethodWriter.maxLocals=t
+org/objectweb/asm/MethodWriter.currentLocals=T
+org/objectweb/asm/MethodWriter.frameCount=u
+org/objectweb/asm/MethodWriter.stackMap=v
+org/objectweb/asm/MethodWriter.previousFrameOffset=w
+org/objectweb/asm/MethodWriter.previousFrame=x
+#org/objectweb/asm/MethodWriter.frameIndex=y
+org/objectweb/asm/MethodWriter.frame=z
+org/objectweb/asm/MethodWriter.handlerCount=A
+org/objectweb/asm/MethodWriter.firstHandler=B
+org/objectweb/asm/MethodWriter.lastHandler=C
+org/objectweb/asm/MethodWriter.methodParametersCount=Z
+org/objectweb/asm/MethodWriter.methodParameters=$
+org/objectweb/asm/MethodWriter.localVarCount=D
+org/objectweb/asm/MethodWriter.localVar=E
+org/objectweb/asm/MethodWriter.localVarTypeCount=F
+org/objectweb/asm/MethodWriter.localVarType=G
+org/objectweb/asm/MethodWriter.lineNumberCount=H
+org/objectweb/asm/MethodWriter.lineNumber=I
+org/objectweb/asm/MethodWriter.lastCodeOffset=Y
+org/objectweb/asm/MethodWriter.ctanns=W
+org/objectweb/asm/MethodWriter.ictanns=X
+org/objectweb/asm/MethodWriter.cattrs=J
+org/objectweb/asm/MethodWriter.resize=K
+org/objectweb/asm/MethodWriter.subroutines=L
+org/objectweb/asm/MethodWriter.compute=M
+org/objectweb/asm/MethodWriter.labels=N
+org/objectweb/asm/MethodWriter.previousBlock=O
+org/objectweb/asm/MethodWriter.currentBlock=P
+org/objectweb/asm/MethodWriter.stackSize=Q
+org/objectweb/asm/MethodWriter.maxStackSize=R
+org/objectweb/asm/MethodWriter.synthetics=S
+
+org/objectweb/asm/Type.sort=a
+org/objectweb/asm/Type.buf=b
+org/objectweb/asm/Type.off=c
+org/objectweb/asm/Type.len=d
+
+org/objectweb/asm/TypeReference.value=a
+
+org/objectweb/asm/TypePath.b=a
+org/objectweb/asm/TypePath.offset=b
+
+org/objectweb/asm/Handle.tag=a
+org/objectweb/asm/Handle.owner=b
+org/objectweb/asm/Handle.name=c
+org/objectweb/asm/Handle.desc=d
+
+org/objectweb/asm/signature/SignatureReader.signature=a
+
+org/objectweb/asm/signature/SignatureWriter.buf=a
+org/objectweb/asm/signature/SignatureWriter.hasFormals=b
+org/objectweb/asm/signature/SignatureWriter.hasParameters=c
+org/objectweb/asm/signature/SignatureWriter.argumentStack=d
+
+# method mappings
+
+org/objectweb/asm/AnnotationWriter.getSize()I=a
+org/objectweb/asm/AnnotationWriter.put([Lorg/objectweb/asm/AnnotationWriter;ILorg/objectweb/asm/ByteVector;)V=a
+org/objectweb/asm/AnnotationWriter.put(Lorg/objectweb/asm/ByteVector;)V=a
+org/objectweb/asm/AnnotationWriter.putTarget(ILorg/objectweb/asm/TypePath;Lorg/objectweb/asm/ByteVector;)V=a
+
+org/objectweb/asm/Attribute.getCount()I=a
+org/objectweb/asm/Attribute.getSize(Lorg/objectweb/asm/ClassWriter;[BIII)I=a
+org/objectweb/asm/Attribute.put(Lorg/objectweb/asm/ClassWriter;[BIIILorg/objectweb/asm/ByteVector;)V=a
+
+org/objectweb/asm/ByteVector.enlarge(I)V=a
+org/objectweb/asm/ByteVector.put11(II)Lorg/objectweb/asm/ByteVector;=a
+org/objectweb/asm/ByteVector.put12(II)Lorg/objectweb/asm/ByteVector;=b
+
+org/objectweb/asm/ClassReader.copyPool(Lorg/objectweb/asm/ClassWriter;)V=a
+org/objectweb/asm/ClassReader.copyBootstrapMethods(Lorg/objectweb/asm/ClassWriter;[Lorg/objectweb/asm/Item;[C)V=a
+org/objectweb/asm/ClassReader.readField(Lorg/objectweb/asm/ClassVisitor;Lorg/objectweb/asm/Context;I)I=a
+org/objectweb/asm/ClassReader.readMethod(Lorg/objectweb/asm/ClassVisitor;Lorg/objectweb/asm/Context;I)I=b
+org/objectweb/asm/ClassReader.readCode(Lorg/objectweb/asm/MethodVisitor;Lorg/objectweb/asm/Context;I)V=a
+org/objectweb/asm/ClassReader.readTypeAnnotations(Lorg/objectweb/asm/MethodVisitor;Lorg/objectweb/asm/Context;IZ)[I=a
+org/objectweb/asm/ClassReader.readAnnotationTarget(Lorg/objectweb/asm/Context;I)I=a
+org/objectweb/asm/ClassReader.readAnnotationValues(I[CZLorg/objectweb/asm/AnnotationVisitor;)I=a
+org/objectweb/asm/ClassReader.readAnnotationValue(I[CLjava/lang/String;Lorg/objectweb/asm/AnnotationVisitor;)I=a
+org/objectweb/asm/ClassReader.getAttributes()I=a
+org/objectweb/asm/ClassReader.readAttribute([Lorg/objectweb/asm/Attribute;Ljava/lang/String;II[CI[Lorg/objectweb/asm/Label;)Lorg/objectweb/asm/Attribute;=a
+org/objectweb/asm/ClassReader.readClass(Ljava/io/InputStream;Z)[B=a
+org/objectweb/asm/ClassReader.readParameterAnnotations(Lorg/objectweb/asm/MethodVisitor;Lorg/objectweb/asm/Context;IZ)V=b
+org/objectweb/asm/ClassReader.readUTF(II[C)Ljava/lang/String;=a
+org/objectweb/asm/ClassReader.getImplicitFrame(Lorg/objectweb/asm/Context;)V=a
+org/objectweb/asm/ClassReader.readFrame(IZZLorg/objectweb/asm/Context;)I=a
+org/objectweb/asm/ClassReader.readFrameType([Ljava/lang/Object;II[C[Lorg/objectweb/asm/Label;)I=a
+
+org/objectweb/asm/ClassWriter.get(Lorg/objectweb/asm/Item;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newClassItem(Ljava/lang/String;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newConstItem(Ljava/lang/Object;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newDouble(D)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newFloat(F)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newInteger(I)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newLong(J)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newMethodItem(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newString(Ljava/lang/String;)Lorg/objectweb/asm/Item;=b
+org/objectweb/asm/ClassWriter.put122(III)V=a
+org/objectweb/asm/ClassWriter.put112(III)V=b
+org/objectweb/asm/ClassWriter.put(Lorg/objectweb/asm/Item;)V=b
+org/objectweb/asm/ClassWriter.newFieldItem(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.addType(Ljava/lang/String;)I=c
+org/objectweb/asm/ClassWriter.addUninitializedType(Ljava/lang/String;I)I=a
+org/objectweb/asm/ClassWriter.addType(Lorg/objectweb/asm/Item;)Lorg/objectweb/asm/Item;=c
+org/objectweb/asm/ClassWriter.getMergedType(II)I=a
+org/objectweb/asm/ClassWriter.newNameTypeItem(Ljava/lang/String;Ljava/lang/String;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newMethodTypeItem(Ljava/lang/String;)Lorg/objectweb/asm/Item;=c
+org/objectweb/asm/ClassWriter.newHandleItem(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newInvokeDynamicItem(Ljava/lang/String;Ljava/lang/String;Lorg/objectweb/asm/Handle;[Ljava/lang/Object;)Lorg/objectweb/asm/Item;=a
+
+org/objectweb/asm/FieldWriter.getSize()I=a
+org/objectweb/asm/FieldWriter.put(Lorg/objectweb/asm/ByteVector;)V=a
+
+org/objectweb/asm/Item.isEqualTo(Lorg/objectweb/asm/Item;)Z=a
+org/objectweb/asm/Item.set(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V=a
+org/objectweb/asm/Item.set(D)V=a
+org/objectweb/asm/Item.set(F)V=a
+org/objectweb/asm/Item.set(I)V=a
+org/objectweb/asm/Item.set(J)V=a
+org/objectweb/asm/Item.set(Ljava/lang/String;Ljava/lang/String;I)V=a
+org/objectweb/asm/Item.set(II)V=a
+
+org/objectweb/asm/Label.addReference(II)V=a
+org/objectweb/asm/Label.put(Lorg/objectweb/asm/MethodWriter;Lorg/objectweb/asm/ByteVector;IZ)V=a
+org/objectweb/asm/Label.resolve(Lorg/objectweb/asm/MethodWriter;I[B)Z=a
+org/objectweb/asm/Label.getFirst()Lorg/objectweb/asm/Label;=a
+org/objectweb/asm/Label.inSubroutine(J)Z=a
+org/objectweb/asm/Label.inSameSubroutine(Lorg/objectweb/asm/Label;)Z=a
+org/objectweb/asm/Label.addToSubroutine(JI)V=a
+org/objectweb/asm/Label.visitSubroutine(Lorg/objectweb/asm/Label;JI)V=b
+
+org/objectweb/asm/Frame.get(I)I=a
+org/objectweb/asm/Frame.set(II)V=a
+org/objectweb/asm/Frame.push(I)V=b
+org/objectweb/asm/Frame.push(Lorg/objectweb/asm/ClassWriter;Ljava/lang/String;)V=a
+org/objectweb/asm/Frame.type(Lorg/objectweb/asm/ClassWriter;Ljava/lang/String;)I=b
+org/objectweb/asm/Frame.pop()I=a
+org/objectweb/asm/Frame.pop(Ljava/lang/String;)V=a
+org/objectweb/asm/Frame.pop(I)V=c
+org/objectweb/asm/Frame.init(I)V=d
+org/objectweb/asm/Frame.init(Lorg/objectweb/asm/ClassWriter;I)I=a
+org/objectweb/asm/Frame.initInputFrame(Lorg/objectweb/asm/ClassWriter;I[Lorg/objectweb/asm/Type;I)V=a
+org/objectweb/asm/Frame.execute(IILorg/objectweb/asm/ClassWriter;Lorg/objectweb/asm/Item;)V=a
+org/objectweb/asm/Frame.merge(Lorg/objectweb/asm/ClassWriter;Lorg/objectweb/asm/Frame;I)Z=a
+org/objectweb/asm/Frame.merge(Lorg/objectweb/asm/ClassWriter;I[II)Z=a
+
+org/objectweb/asm/Handler.remove(Lorg/objectweb/asm/Handler;Lorg/objectweb/asm/Label;Lorg/objectweb/asm/Label;)Lorg/objectweb/asm/Handler;=a
+
+org/objectweb/asm/MethodWriter.visitSwitchInsn(Lorg/objectweb/asm/Label;[Lorg/objectweb/asm/Label;)V=a
+org/objectweb/asm/MethodWriter.addSuccessor(ILorg/objectweb/asm/Label;)V=a
+org/objectweb/asm/MethodWriter.getNewOffset([I[III)I=a
+org/objectweb/asm/MethodWriter.getSize()I=a
+org/objectweb/asm/MethodWriter.put(Lorg/objectweb/asm/ByteVector;)V=a
+org/objectweb/asm/MethodWriter.readInt([BI)I=a
+org/objectweb/asm/MethodWriter.readShort([BI)S=b
+org/objectweb/asm/MethodWriter.readUnsignedShort([BI)I=c
+org/objectweb/asm/MethodWriter.writeShort([BII)V=a
+org/objectweb/asm/MethodWriter.visitFrame(Lorg/objectweb/asm/Frame;)V=b
+org/objectweb/asm/MethodWriter.visitImplicitFirstFrame()V=f
+org/objectweb/asm/MethodWriter.startFrame(III)I=a
+org/objectweb/asm/MethodWriter.endFrame()V=b
+org/objectweb/asm/MethodWriter.writeFrame()V=c
+org/objectweb/asm/MethodWriter.resizeInstructions()V=d
+org/objectweb/asm/MethodWriter.noSuccessor()V=e
+org/objectweb/asm/MethodWriter.writeFrameTypes(II)V=a
+org/objectweb/asm/MethodWriter.writeFrameType(Ljava/lang/Object;)V=a
+org/objectweb/asm/MethodWriter.getNewOffset([I[ILorg/objectweb/asm/Label;)V=a
+
+org/objectweb/asm/Type.getType([CI)Lorg/objectweb/asm/Type;=a
+org/objectweb/asm/Type.getDescriptor(Ljava/lang/StringBuffer;)V=a
+org/objectweb/asm/Type.getDescriptor(Ljava/lang/StringBuffer;Ljava/lang/Class;)V=a
+
+org/objectweb/asm/signature/SignatureReader.parseType(Ljava/lang/String;ILorg/objectweb/asm/signature/SignatureVisitor;)I=a
+
+org/objectweb/asm/signature/SignatureWriter.endFormals()V=a
+org/objectweb/asm/signature/SignatureWriter.endArguments()V=b
+     
\ 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/signature/SignatureReader.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java
index b72fde6..b5b2c45 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java
@@ -32,7 +32,7 @@ package org.apache.tapestry5.internal.plastic.asm.signature;
 /**
  * A type signature parser to make a signature visitor visit an existing
  * signature.
- *
+ * 
  * @author Thomas Hallgren
  * @author Eric Bruneton
  */
@@ -45,9 +45,10 @@ public class SignatureReader {
 
     /**
      * Constructs a {@link SignatureReader} for the given signature.
-     *
-     * @param signature A <i>ClassSignature</i>, <i>MethodTypeSignature</i>,
-     *        or <i>FieldTypeSignature</i>.
+     * 
+     * @param signature
+     *            A <i>ClassSignature</i>, <i>MethodTypeSignature</i>, or
+     *            <i>FieldTypeSignature</i>.
      */
     public SignatureReader(final String signature) {
         this.signature = signature;
@@ -58,15 +59,15 @@ public class SignatureReader {
      * {@link SignatureReader}. This signature is the one specified in the
      * constructor (see {@link #SignatureReader(String) SignatureReader}). This
      * method is intended to be called on a {@link SignatureReader} that was
-     * created using a <i>ClassSignature</i> (such as the
+     * created using a <i>ClassSignature</i> (such as the <code>signature</code>
+     * parameter of the {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visit
+     * ClassVisitor.visit} method) or a <i>MethodTypeSignature</i> (such as the
      * <code>signature</code> parameter of the
-     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visit ClassVisitor.visit} method)
-     * or a <i>MethodTypeSignature</i> (such as the <code>signature</code>
-     * parameter of the
-     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitMethod ClassVisitor.visitMethod}
-     * method).
-     *
-     * @param v the visitor that must visit this signature.
+     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitMethod
+     * ClassVisitor.visitMethod} method).
+     * 
+     * @param v
+     *            the visitor that must visit this signature.
      */
     public void accept(final SignatureVisitor v) {
         String signature = this.signature;
@@ -118,12 +119,12 @@ public class SignatureReader {
      * method is intended to be called on a {@link SignatureReader} that was
      * created using a <i>FieldTypeSignature</i>, such as the
      * <code>signature</code> parameter of the
-     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitField
-     * ClassVisitor.visitField} or {@link
-     * org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLocalVariable
+     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitField ClassVisitor.visitField}
+     * or {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLocalVariable
      * MethodVisitor.visitLocalVariable} methods.
-     *
-     * @param v the visitor that must visit this signature.
+     * 
+     * @param v
+     *            the visitor that must visit this signature.
      */
     public void acceptType(final SignatureVisitor v) {
         parseType(this.signature, 0, v);
@@ -131,99 +132,97 @@ public class SignatureReader {
 
     /**
      * Parses a field type signature and makes the given visitor visit it.
-     *
-     * @param signature a string containing the signature that must be parsed.
-     * @param pos index of the first character of the signature to parsed.
-     * @param v the visitor that must visit this signature.
+     * 
+     * @param signature
+     *            a string containing the signature that must be parsed.
+     * @param pos
+     *            index of the first character of the signature to parsed.
+     * @param v
+     *            the visitor that must visit this signature.
      * @return the index of the first character after the parsed signature.
      */
-    private static int parseType(
-        final String signature,
-        int pos,
-        final SignatureVisitor v)
-    {
+    private static int parseType(final String signature, int pos,
+            final SignatureVisitor v) {
         char c;
         int start, end;
         boolean visited, inner;
         String name;
 
         switch (c = signature.charAt(pos++)) {
-            case 'Z':
-            case 'C':
-            case 'B':
-            case 'S':
-            case 'I':
-            case 'F':
-            case 'J':
-            case 'D':
-            case 'V':
-                v.visitBaseType(c);
-                return pos;
+        case 'Z':
+        case 'C':
+        case 'B':
+        case 'S':
+        case 'I':
+        case 'F':
+        case 'J':
+        case 'D':
+        case 'V':
+            v.visitBaseType(c);
+            return pos;
 
-            case '[':
-                return parseType(signature, pos, v.visitArrayType());
+        case '[':
+            return parseType(signature, pos, v.visitArrayType());
 
-            case 'T':
-                end = signature.indexOf(';', pos);
-                v.visitTypeVariable(signature.substring(pos, end));
-                return end + 1;
+        case 'T':
+            end = signature.indexOf(';', pos);
+            v.visitTypeVariable(signature.substring(pos, end));
+            return end + 1;
 
-            default: // case 'L':
-                start = pos;
-                visited = false;
-                inner = false;
-                for (;;) {
-                    switch (c = signature.charAt(pos++)) {
-                        case '.':
-                        case ';':
-                            if (!visited) {
-                                name = signature.substring(start, pos - 1);
-                                if (inner) {
-                                    v.visitInnerClassType(name);
-                                } else {
-                                    v.visitClassType(name);
-                                }
-                            }
-                            if (c == ';') {
-                                v.visitEnd();
-                                return pos;
-                            }
-                            start = pos;
-                            visited = false;
-                            inner = true;
-                            break;
+        default: // case 'L':
+            start = pos;
+            visited = false;
+            inner = false;
+            for (;;) {
+                switch (c = signature.charAt(pos++)) {
+                case '.':
+                case ';':
+                    if (!visited) {
+                        name = signature.substring(start, pos - 1);
+                        if (inner) {
+                            v.visitInnerClassType(name);
+                        } else {
+                            v.visitClassType(name);
+                        }
+                    }
+                    if (c == ';') {
+                        v.visitEnd();
+                        return pos;
+                    }
+                    start = pos;
+                    visited = false;
+                    inner = true;
+                    break;
 
-                        case '<':
-                            name = signature.substring(start, pos - 1);
-                            if (inner) {
-                                v.visitInnerClassType(name);
-                            } else {
-                                v.visitClassType(name);
-                            }
-                            visited = true;
-                            top: for (;;) {
-                                switch (c = signature.charAt(pos)) {
-                                    case '>':
-                                        break top;
-                                    case '*':
-                                        ++pos;
-                                        v.visitTypeArgument();
-                                        break;
-                                    case '+':
-                                    case '-':
-                                        pos = parseType(signature,
-                                                pos + 1,
-                                                v.visitTypeArgument(c));
-                                        break;
-                                    default:
-                                        pos = parseType(signature,
-                                                pos,
-                                                v.visitTypeArgument('='));
-                                        break;
-                                }
-                            }
+                case '<':
+                    name = signature.substring(start, pos - 1);
+                    if (inner) {
+                        v.visitInnerClassType(name);
+                    } else {
+                        v.visitClassType(name);
+                    }
+                    visited = true;
+                    top: for (;;) {
+                        switch (c = signature.charAt(pos)) {
+                        case '>':
+                            break top;
+                        case '*':
+                            ++pos;
+                            v.visitTypeArgument();
+                            break;
+                        case '+':
+                        case '-':
+                            pos = parseType(signature, pos + 1,
+                                    v.visitTypeArgument(c));
+                            break;
+                        default:
+                            pos = parseType(signature, pos,
+                                    v.visitTypeArgument('='));
+                            break;
+                        }
                     }
                 }
+            }
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
index 14e9ccb..941980f 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
@@ -35,22 +35,22 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
  * A visitor to visit a generic signature. The methods of this interface must be
  * called in one of the three following orders (the last one is the only valid
  * order for a {@link SignatureVisitor} that is returned by a method of this
- * interface): <ul> <li><i>ClassSignature</i> = (
- * <tt>visitFormalTypeParameter</tt>
- *   <tt>visitClassBound</tt>?
- * <tt>visitInterfaceBound</tt>* )* ( <tt>visitSuperClass</tt>
- *   <tt>visitInterface</tt>* )</li>
+ * interface):
+ * <ul>
+ * <li><i>ClassSignature</i> = ( <tt>visitFormalTypeParameter</tt>
+ * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* (
+ * <tt>visitSuperClass</tt> <tt>visitInterface</tt>* )</li>
  * <li><i>MethodSignature</i> = ( <tt>visitFormalTypeParameter</tt>
- *   <tt>visitClassBound</tt>?
- * <tt>visitInterfaceBound</tt>* )* ( <tt>visitParameterType</tt>*
- * <tt>visitReturnType</tt>
- *   <tt>visitExceptionType</tt>* )</li> <li><i>TypeSignature</i> =
- * <tt>visitBaseType</tt> | <tt>visitTypeVariable</tt> |
- * <tt>visitArrayType</tt> | (
+ * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* (
+ * <tt>visitParameterType</tt>* <tt>visitReturnType</tt>
+ * <tt>visitExceptionType</tt>* )</li>
+ * <li><i>TypeSignature</i> = <tt>visitBaseType</tt> |
+ * <tt>visitTypeVariable</tt> | <tt>visitArrayType</tt> | (
  * <tt>visitClassType</tt> <tt>visitTypeArgument</tt>* (
- * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )*
- * <tt>visitEnd</tt> ) )</li> </ul>
- *
+ * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )* <tt>visitEnd</tt>
+ * ) )</li>
+ * </ul>
+ * 
  * @author Thomas Hallgren
  * @author Eric Bruneton
  */
@@ -73,31 +73,36 @@ public abstract class SignatureVisitor {
 
     /**
      * The ASM API version implemented by this visitor. The value of this field
-     * must be one of {@link Opcodes#ASM4}.
+     * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
      */
     protected final int api;
 
     /**
      * Constructs a new {@link SignatureVisitor}.
-     *
-     * @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 SignatureVisitor(final int api) {
+        if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
+            throw new IllegalArgumentException();
+        }
         this.api = api;
     }
 
     /**
      * Visits a formal type parameter.
-     *
-     * @param name the name of the formal parameter.
+     * 
+     * @param name
+     *            the name of the formal parameter.
      */
     public void visitFormalTypeParameter(String name) {
     }
 
     /**
      * Visits the class bound of the last visited formal type parameter.
-     *
+     * 
      * @return a non null visitor to visit the signature of the class bound.
      */
     public SignatureVisitor visitClassBound() {
@@ -106,7 +111,7 @@ public abstract class SignatureVisitor {
 
     /**
      * Visits an interface bound of the last visited formal type parameter.
-     *
+     * 
      * @return a non null visitor to visit the signature of the interface bound.
      */
     public SignatureVisitor visitInterfaceBound() {
@@ -115,7 +120,7 @@ public abstract class SignatureVisitor {
 
     /**
      * Visits the type of the super class.
-     *
+     * 
      * @return a non null visitor to visit the signature of the super class
      *         type.
      */
@@ -125,7 +130,7 @@ public abstract class SignatureVisitor {
 
     /**
      * Visits the type of an interface implemented by the class.
-     *
+     * 
      * @return a non null visitor to visit the signature of the interface type.
      */
     public SignatureVisitor visitInterface() {
@@ -134,7 +139,7 @@ public abstract class SignatureVisitor {
 
     /**
      * Visits the type of a method parameter.
-     *
+     * 
      * @return a non null visitor to visit the signature of the parameter type.
      */
     public SignatureVisitor visitParameterType() {
@@ -143,7 +148,7 @@ public abstract class SignatureVisitor {
 
     /**
      * Visits the return type of the method.
-     *
+     * 
      * @return a non null visitor to visit the signature of the return type.
      */
     public SignatureVisitor visitReturnType() {
@@ -152,7 +157,7 @@ public abstract class SignatureVisitor {
 
     /**
      * Visits the type of a method exception.
-     *
+     * 
      * @return a non null visitor to visit the signature of the exception type.
      */
     public SignatureVisitor visitExceptionType() {
@@ -161,24 +166,26 @@ public abstract class SignatureVisitor {
 
     /**
      * Visits a signature corresponding to a primitive type.
-     *
-     * @param descriptor the descriptor of the primitive type, or 'V' for
-     *        <tt>void</tt>.
+     * 
+     * @param descriptor
+     *            the descriptor of the primitive type, or 'V' for <tt>void</tt>
+     *            .
      */
     public void visitBaseType(char descriptor) {
     }
 
     /**
      * Visits a signature corresponding to a type variable.
-     *
-     * @param name the name of the type variable.
+     * 
+     * @param name
+     *            the name of the type variable.
      */
     public void visitTypeVariable(String name) {
     }
 
     /**
      * Visits a signature corresponding to an array type.
-     *
+     * 
      * @return a non null visitor to visit the signature of the array element
      *         type.
      */
@@ -189,16 +196,18 @@ public abstract class SignatureVisitor {
     /**
      * Starts the visit of a signature corresponding to a class or interface
      * type.
-     *
-     * @param name the internal name of the class or interface.
+     * 
+     * @param name
+     *            the internal name of the class or interface.
      */
     public void visitClassType(String name) {
     }
 
     /**
      * Visits an inner class.
-     *
-     * @param name the local name of the inner class in its enclosing class.
+     * 
+     * @param name
+     *            the local name of the inner class in its enclosing class.
      */
     public void visitInnerClassType(String name) {
     }
@@ -212,8 +221,9 @@ public abstract class SignatureVisitor {
 
     /**
      * Visits a type argument of the last visited class or inner class type.
-     *
-     * @param wildcard '+', '-' or '='.
+     * 
+     * @param wildcard
+     *            '+', '-' or '='.
      * @return a non null visitor to visit the signature of the type argument.
      */
     public SignatureVisitor visitTypeArgument(char wildcard) {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
index 841fdad..d1e6bac 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
@@ -33,7 +33,7 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
 
 /**
  * A signature visitor that generates signatures in string format.
- *
+ * 
  * @author Thomas Hallgren
  * @author Eric Bruneton
  */
@@ -66,7 +66,7 @@ public class SignatureWriter extends SignatureVisitor {
      * Constructs a new {@link SignatureWriter} object.
      */
     public SignatureWriter() {
-        super(Opcodes.ASM4);
+        super(Opcodes.ASM5);
     }
 
     // ------------------------------------------------------------------------
@@ -193,7 +193,7 @@ public class SignatureWriter extends SignatureVisitor {
 
     /**
      * Returns the signature that was built by this signature writer.
-     *
+     * 
      * @return the signature that was built by this signature writer.
      */
     @Override

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
index 32dc008..a6a01d6 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
@@ -29,15 +29,16 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
 /**
  * A node that represents a bytecode instruction. <i>An instruction can appear
  * at most once in at most one {@link InsnList} at a time</i>.
- *
+ * 
  * @author Eric Bruneton
  */
 public abstract class AbstractInsnNode {
@@ -128,6 +129,28 @@ public abstract class AbstractInsnNode {
     protected int opcode;
 
     /**
+     * The runtime visible type annotations of this instruction. This field is
+     * only used for real instructions (i.e. not for labels, frames, or line
+     * number nodes). 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 instruction. This field is
+     * only used for real instructions (i.e. not for labels, frames, or line
+     * number nodes). 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;
+
+    /**
      * Previous instruction in the list to which this instruction belongs.
      */
     AbstractInsnNode prev;
@@ -147,8 +170,9 @@ public abstract class AbstractInsnNode {
 
     /**
      * Constructs a new {@link AbstractInsnNode}.
-     *
-     * @param opcode the opcode of the instruction to be constructed.
+     * 
+     * @param opcode
+     *            the opcode of the instruction to be constructed.
      */
     protected AbstractInsnNode(final int opcode) {
         this.opcode = opcode;
@@ -157,7 +181,7 @@ public abstract class AbstractInsnNode {
 
     /**
      * Returns the opcode of this instruction.
-     *
+     * 
      * @return the opcode of this instruction.
      */
     public int getOpcode() {
@@ -166,7 +190,7 @@ public abstract class AbstractInsnNode {
 
     /**
      * Returns the type of this instruction.
-     *
+     * 
      * @return the type of this instruction, i.e. one the constants defined in
      *         this class.
      */
@@ -175,7 +199,7 @@ public abstract class AbstractInsnNode {
     /**
      * Returns the previous instruction in the list to which this instruction
      * belongs, if any.
-     *
+     * 
      * @return the previous instruction in the list to which this instruction
      *         belongs, if any. May be <tt>null</tt>.
      */
@@ -186,7 +210,7 @@ public abstract class AbstractInsnNode {
     /**
      * Returns the next instruction in the list to which this instruction
      * belongs, if any.
-     *
+     * 
      * @return the next instruction in the list to which this instruction
      *         belongs, if any. May be <tt>null</tt>.
      */
@@ -196,43 +220,107 @@ public abstract class AbstractInsnNode {
 
     /**
      * Makes the given code visitor visit this instruction.
-     *
-     * @param cv a code visitor.
+     * 
+     * @param cv
+     *            a code visitor.
      */
     public abstract void accept(final MethodVisitor cv);
 
     /**
+     * Makes the given visitor visit the annotations of this instruction.
+     * 
+     * @param mv
+     *            a method visitor.
+     */
+    protected final void acceptAnnotations(final MethodVisitor mv) {
+        int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations
+                .size();
+        for (int i = 0; i < n; ++i) {
+            TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+            an.accept(mv.visitInsnAnnotation(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.visitInsnAnnotation(an.typeRef, an.typePath, an.desc,
+                    false));
+        }
+    }
+
+    /**
      * Returns a copy of this instruction.
-     *
-     * @param labels a map from LabelNodes to cloned LabelNodes.
+     * 
+     * @param labels
+     *            a map from LabelNodes to cloned LabelNodes.
      * @return a copy of this instruction. The returned instruction does not
      *         belong to any {@link InsnList}.
      */
-    public abstract AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels);
+    public abstract AbstractInsnNode clone(
+            final Map<LabelNode, LabelNode> labels);
 
     /**
      * Returns the clone of the given label.
-     *
-     * @param label a label.
-     * @param map a map from LabelNodes to cloned LabelNodes.
+     * 
+     * @param label
+     *            a label.
+     * @param map
+     *            a map from LabelNodes to cloned LabelNodes.
      * @return the clone of the given label.
      */
-    static LabelNode clone(final LabelNode label, final Map<LabelNode, LabelNode> map) {
+    static LabelNode clone(final LabelNode label,
+            final Map<LabelNode, LabelNode> map) {
         return map.get(label);
     }
 
     /**
      * Returns the clones of the given labels.
-     *
-     * @param labels a list of labels.
-     * @param map a map from LabelNodes to cloned LabelNodes.
+     * 
+     * @param labels
+     *            a list of labels.
+     * @param map
+     *            a map from LabelNodes to cloned LabelNodes.
      * @return the clones of the given labels.
      */
-    static LabelNode[] clone(final List<LabelNode> labels, final Map<LabelNode, LabelNode> map) {
+    static LabelNode[] clone(final List<LabelNode> labels,
+            final Map<LabelNode, LabelNode> map) {
         LabelNode[] clones = new LabelNode[labels.size()];
         for (int i = 0; i < clones.length; ++i) {
             clones[i] = map.get(labels.get(i));
         }
         return clones;
     }
+
+    /**
+     * Clones the annotations of the given instruction into this instruction.
+     * 
+     * @param insn
+     *            the source instruction.
+     * @return this instruction.
+     */
+    protected final AbstractInsnNode cloneAnnotations(
+            final AbstractInsnNode insn) {
+        if (insn.visibleTypeAnnotations != null) {
+            this.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>();
+            for (int i = 0; i < insn.visibleTypeAnnotations.size(); ++i) {
+                TypeAnnotationNode src = insn.visibleTypeAnnotations.get(i);
+                TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef,
+                        src.typePath, src.desc);
+                src.accept(ann);
+                this.visibleTypeAnnotations.add(ann);
+            }
+        }
+        if (insn.invisibleTypeAnnotations != null) {
+            this.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>();
+            for (int i = 0; i < insn.invisibleTypeAnnotations.size(); ++i) {
+                TypeAnnotationNode src = insn.invisibleTypeAnnotations.get(i);
+                TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef,
+                        src.typePath, src.desc);
+                src.accept(ann);
+                this.invisibleTypeAnnotations.add(ann);
+            }
+        }
+        return this;
+    }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
index 2fe5b77..9d07669 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
@@ -29,19 +29,18 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
-import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
 /**
  * A node that represents an annotationn.
  *
  * @author Eric Bruneton
  */
-public class AnnotationNode extends AnnotationVisitor
-{
+public class AnnotationNode extends AnnotationVisitor {
 
     /**
      * The class descriptor of the annotation class.
@@ -56,8 +55,8 @@ public class AnnotationNode extends AnnotationVisitor
      * {@link Double}, {@link String} or {@link org.apache.tapestry5.internal.plastic.asm.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. The list may be <tt>null</tt> if there is no name
-     * value pair.
+     * preceding types. The list may be <tt>null</tt> if there is no name value
+     * pair.
      */
     public List<Object> values;
 
@@ -66,18 +65,26 @@ public class AnnotationNode extends AnnotationVisitor
      * constructor</i>. Instead, they must use the
      * {@link #AnnotationNode(int, String)} version.
      *
-     * @param desc the class descriptor of the annotation class.
+     * @param desc
+     *            the class descriptor of the annotation class.
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
      */
     public AnnotationNode(final String desc) {
-        this(Opcodes.ASM4, desc);
+        this(Opcodes.ASM5, desc);
+        if (getClass() != AnnotationNode.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}.
-     * @param desc the class descriptor of the annotation class.
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param desc
+     *            the class descriptor of the annotation class.
      */
     public AnnotationNode(final int api, final String desc) {
         super(api);
@@ -87,10 +94,11 @@ public class AnnotationNode extends AnnotationVisitor
     /**
      * Constructs a new {@link AnnotationNode} to visit an array value.
      *
-     * @param values where the visited values must be stored.
+     * @param values
+     *            where the visited values must be stored.
      */
     AnnotationNode(final List<Object> values) {
-        super(Opcodes.ASM4);
+        super(Opcodes.ASM5);
         this.values = values;
     }
 
@@ -110,11 +118,8 @@ public class AnnotationNode extends AnnotationVisitor
     }
 
     @Override
-    public void visitEnum(
-        final String name,
-        final String desc,
-        final String value)
-    {
+    public void visitEnum(final String name, final String desc,
+            final String value) {
         if (values == null) {
             values = new ArrayList<Object>(this.desc != null ? 2 : 1);
         }
@@ -125,10 +130,8 @@ public class AnnotationNode extends AnnotationVisitor
     }
 
     @Override
-    public AnnotationVisitor visitAnnotation(
-        final String name,
-        final String desc)
-    {
+    public AnnotationVisitor visitAnnotation(final String name,
+            final String desc) {
         if (values == null) {
             values = new ArrayList<Object>(this.desc != null ? 2 : 1);
         }
@@ -167,7 +170,9 @@ public class AnnotationNode extends AnnotationVisitor
      * 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
@@ -176,7 +181,8 @@ public class AnnotationNode extends AnnotationVisitor
     /**
      * Makes the given visitor visit this annotation.
      *
-     * @param av an annotation visitor. Maybe <tt>null</tt>.
+     * @param av
+     *            an annotation visitor. Maybe <tt>null</tt>.
      */
     public void accept(final AnnotationVisitor av) {
         if (av != null) {
@@ -194,15 +200,15 @@ public class AnnotationNode extends AnnotationVisitor
     /**
      * Makes the given visitor visit a given annotation value.
      *
-     * @param av an annotation visitor. Maybe <tt>null</tt>.
-     * @param name the value name.
-     * @param value the actual value.
+     * @param av
+     *            an annotation visitor. Maybe <tt>null</tt>.
+     * @param name
+     *            the value name.
+     * @param value
+     *            the actual value.
      */
-    static void accept(
-        final AnnotationVisitor av,
-        final String name,
-        final Object value)
-    {
+    public static void accept(final AnnotationVisitor av, final String name,
+            final Object value) {
         if (av != null) {
             if (value instanceof String[]) {
                 String[] typeconst = (String[]) value;

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
index 7bda1ab..0bdcc54 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
@@ -29,15 +29,21 @@
  */
 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.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
 /**
  * A node that represents a class.
- *
+ * 
  * @author Eric Bruneton
  */
 public class ClassNode extends ClassVisitor {
@@ -60,15 +66,15 @@ public class ClassNode extends ClassVisitor {
     public String name;
 
     /**
-     * The signature of the class. Mayt be <tt>null</tt>.
+     * The signature of the class. May be <tt>null</tt>.
      */
     public String signature;
 
     /**
      * The internal of name of the super class (see
      * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). For
-     * interfaces, the super class is {@link Object}. May be <tt>null</tt>,
-     * but only for the {@link Object} class.
+     * interfaces, the super class is {@link Object}. May be <tt>null</tt>, but
+     * only for the {@link Object} class.
      */
     public String superName;
 
@@ -86,7 +92,7 @@ public class ClassNode extends ClassVisitor {
     public String sourceFile;
 
     /**
-     * Debug information to compute the correspondance between source and
+     * Debug information to compute the correspondence between source and
      * compiled elements of the class. May be <tt>null</tt>.
      */
     public String sourceDebug;
@@ -104,16 +110,16 @@ public class ClassNode extends ClassVisitor {
     public String outerMethod;
 
     /**
-     * The descriptor of the method that contains the class, or <tt>null</tt>
-     * if the class is not enclosed in a method.
+     * The descriptor of the method that contains the class, or <tt>null</tt> if
+     * the class is not enclosed in a method.
      */
     public String outerMethodDesc;
 
     /**
      * The runtime visible annotations of this class. 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;
@@ -121,41 +127,59 @@ public class ClassNode extends ClassVisitor {
     /**
      * The runtime invisible annotations of this class. 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 class. 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 class. 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 class. This list is a list of
      * {@link Attribute} objects. May be <tt>null</tt>.
-     *
-     * @associates Attribute
+     * 
+     * @associates org.objectweb.asm.Attribute
      */
     public List<Attribute> attrs;
 
     /**
      * Informations about the inner classes of this class. This list is a list
      * of {@link InnerClassNode} objects.
-     *
-     * @associates InnerClassNode
+     * 
+     * @associates org.objectweb.asm.tree.InnerClassNode
      */
     public List<InnerClassNode> innerClasses;
 
     /**
      * The fields of this class. This list is a list of {@link FieldNode}
      * objects.
-     *
-     * @associates FieldNode
+     * 
+     * @associates org.objectweb.asm.tree.FieldNode
      */
     public List<FieldNode> fields;
 
     /**
      * The methods of this class. This list is a list of {@link MethodNode}
      * objects.
-     *
-     * @associates MethodNode
+     * 
+     * @associates org.objectweb.asm.tree.MethodNode
      */
     public List<MethodNode> methods;
 
@@ -163,16 +187,23 @@ public class ClassNode extends ClassVisitor {
      * Constructs a new {@link ClassNode}. <i>Subclasses must not use this
      * constructor</i>. Instead, they must use the {@link #ClassNode(int)}
      * version.
+     * 
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
      */
     public ClassNode() {
-        this(Opcodes.ASM4);
+        this(Opcodes.ASM5);
+        if (getClass() != ClassNode.class) {
+            throw new IllegalStateException();
+        }
     }
 
     /**
      * Constructs a new {@link ClassNode}.
-     *
-     * @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 ClassNode(final int api) {
         super(api);
@@ -187,14 +218,9 @@ public class ClassNode extends ClassVisitor {
     // ------------------------------------------------------------------------
 
     @Override
-    public void visit(
-        final int version,
-        final int access,
-        final String name,
-        final String signature,
-        final String superName,
-        final String[] interfaces)
-    {
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
         this.version = version;
         this.access = access;
         this.name = name;
@@ -212,21 +238,16 @@ public class ClassNode extends ClassVisitor {
     }
 
     @Override
-    public void visitOuterClass(
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    public void visitOuterClass(final String owner, final String name,
+            final String desc) {
         outerClass = owner;
         outerMethod = name;
         outerMethodDesc = desc;
     }
 
     @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) {
@@ -243,6 +264,24 @@ public class ClassNode extends ClassVisitor {
     }
 
     @Override
+    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 void visitAttribute(final Attribute attr) {
         if (attrs == null) {
             attrs = new ArrayList<Attribute>(1);
@@ -251,44 +290,25 @@ public class ClassNode extends ClassVisitor {
     }
 
     @Override
-    public void visitInnerClass(
-        final String name,
-        final String outerName,
-        final String innerName,
-        final int access)
-    {
-        InnerClassNode icn = new InnerClassNode(name,
-                outerName,
-                innerName,
+    public void visitInnerClass(final String name, final String outerName,
+            final String innerName, final int access) {
+        InnerClassNode icn = new InnerClassNode(name, outerName, innerName,
                 access);
         innerClasses.add(icn);
     }
 
     @Override
-    public FieldVisitor visitField(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final Object value)
-    {
+    public FieldVisitor visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
         FieldNode fn = new FieldNode(access, name, desc, signature, value);
         fields.add(fn);
         return fn;
     }
 
     @Override
-    public MethodVisitor visitMethod(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final String[] exceptions)
-    {
-        MethodNode mn = new MethodNode(access,
-                name,
-                desc,
-                signature,
+    public MethodVisitor visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        MethodNode mn = new MethodNode(access, name, desc, signature,
                 exceptions);
         methods.add(mn);
         return mn;
@@ -307,17 +327,35 @@ public class ClassNode extends ClassVisitor {
      * 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();
+            }
+            for (FieldNode f : fields) {
+                f.check(api);
+            }
+            for (MethodNode m : methods) {
+                m.check(api);
+            }
+        }
     }
 
     /**
      * Makes the given class visitor visit this class.
-     *
-     * @param cv a class visitor.
+     * 
+     * @param cv
+     *            a class visitor.
      */
     public void accept(final ClassVisitor cv) {
         // visits header
@@ -344,6 +382,19 @@ public class ClassNode extends ClassVisitor {
             AnnotationNode an = invisibleAnnotations.get(i);
             an.accept(cv.visitAnnotation(an.desc, false));
         }
+        n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
+        for (i = 0; i < n; ++i) {
+            TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+            an.accept(cv.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(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+                    false));
+        }
         n = attrs == null ? 0 : attrs.size();
         for (i = 0; i < n; ++i) {
             cv.visitAttribute(attrs.get(i));

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java
index 265fb1e..848d05d 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.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 field instruction. A field instruction is an
  * instruction that loads or stores the value of a field of an object.
- *
+ * 
  * @author Eric Bruneton
  */
 public class FieldInsnNode extends AbstractInsnNode {
@@ -59,20 +59,21 @@ public class FieldInsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link FieldInsnNode}.
-     *
-     * @param opcode the opcode of the type instruction to be constructed. This
-     *        opcode must be GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
-     * @param owner the internal name of the field's owner class (see
-     *        {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}).
-     * @param name the field's name.
-     * @param desc the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+     * 
+     * @param opcode
+     *            the opcode of the type instruction to be constructed. This
+     *            opcode must be GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
+     * @param owner
+     *            the internal name of the field's owner class (see
+     *            {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+     *            getInternalName}).
+     * @param name
+     *            the field's name.
+     * @param desc
+     *            the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
      */
-    public FieldInsnNode(
-        final int opcode,
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    public FieldInsnNode(final int opcode, final String owner,
+            final String name, final String desc) {
         super(opcode);
         this.owner = owner;
         this.name = name;
@@ -81,9 +82,10 @@ public class FieldInsnNode extends AbstractInsnNode {
 
     /**
      * Sets the opcode of this instruction.
-     *
-     * @param opcode the new instruction opcode. This opcode must be GETSTATIC,
-     *        PUTSTATIC, GETFIELD or PUTFIELD.
+     * 
+     * @param opcode
+     *            the new instruction opcode. This opcode must be GETSTATIC,
+     *            PUTSTATIC, GETFIELD or PUTFIELD.
      */
     public void setOpcode(final int opcode) {
         this.opcode = opcode;
@@ -95,12 +97,14 @@ public class FieldInsnNode extends AbstractInsnNode {
     }
 
     @Override
-    public void accept(final MethodVisitor cv) {
-        cv.visitFieldInsn(opcode, owner, name, desc);
+    public void accept(final MethodVisitor mv) {
+        mv.visitFieldInsn(opcode, owner, name, desc);
+        acceptAnnotations(mv);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new FieldInsnNode(opcode, owner, name, desc);
+        return new FieldInsnNode(opcode, owner, name, desc)
+                .cloneAnnotations(this);
     }
 }


[22/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
index 4801b61..4b9c65e 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
@@ -37,7 +37,7 @@ import java.io.InputStream;
  * This class parses a byte array conforming to the Java class file format and
  * calls the appropriate visit methods of a given class visitor for each field,
  * method and bytecode instruction encountered.
- *
+ * 
  * @author Eric Bruneton
  * @author Eugene Kuleshov
  */
@@ -112,9 +112,8 @@ public class ClassReader {
     public final byte[] b;
 
     /**
-     * The start index of each constant pool item in {@link #b b}, plus one.
-     * The one byte offset skips the constant pool item tag that indicates its
-     * type.
+     * The start index of each constant pool item in {@link #b b}, plus one. The
+     * one byte offset skips the constant pool item tag that indicates its type.
      */
     private final int[] items;
 
@@ -146,8 +145,9 @@ public class ClassReader {
 
     /**
      * Constructs a new {@link ClassReader} object.
-     *
-     * @param b the bytecode of the class to be read.
+     * 
+     * @param b
+     *            the bytecode of the class to be read.
      */
     public ClassReader(final byte[] b) {
         this(b, 0, b.length);
@@ -155,15 +155,18 @@ public class ClassReader {
 
     /**
      * Constructs a new {@link ClassReader} object.
-     *
-     * @param b the bytecode of the class to be read.
-     * @param off the start offset of the class data.
-     * @param len the length of the class data.
+     * 
+     * @param b
+     *            the bytecode of the class to be read.
+     * @param off
+     *            the start offset of the class data.
+     * @param len
+     *            the length of the class data.
      */
     public ClassReader(final byte[] b, final int off, final int len) {
         this.b = b;
         // checks the class version
-        if (readShort(6) > Opcodes.V1_7) {
+        if (readShort(off + 6) > Opcodes.V1_8) {
             throw new IllegalArgumentException();
         }
         // parses the constant pool
@@ -176,35 +179,35 @@ public class ClassReader {
             items[i] = index + 1;
             int size;
             switch (b[index]) {
-                case ClassWriter.FIELD:
-                case ClassWriter.METH:
-                case ClassWriter.IMETH:
-                case ClassWriter.INT:
-                case ClassWriter.FLOAT:
-                case ClassWriter.NAME_TYPE:
-                case ClassWriter.INDY:
-                    size = 5;
-                    break;
-                case ClassWriter.LONG:
-                case ClassWriter.DOUBLE:
-                    size = 9;
-                    ++i;
-                    break;
-                case ClassWriter.UTF8:
-                    size = 3 + readUnsignedShort(index + 1);
-                    if (size > max) {
-                        max = size;
-                    }
-                    break;
-                case ClassWriter.HANDLE:
-                    size = 4;
-                    break;
-                // case ClassWriter.CLASS:
-                // case ClassWriter.STR:
-                // case ClassWriter.MTYPE
-                default:
-                    size = 3;
-                    break;
+            case ClassWriter.FIELD:
+            case ClassWriter.METH:
+            case ClassWriter.IMETH:
+            case ClassWriter.INT:
+            case ClassWriter.FLOAT:
+            case ClassWriter.NAME_TYPE:
+            case ClassWriter.INDY:
+                size = 5;
+                break;
+            case ClassWriter.LONG:
+            case ClassWriter.DOUBLE:
+                size = 9;
+                ++i;
+                break;
+            case ClassWriter.UTF8:
+                size = 3 + readUnsignedShort(index + 1);
+                if (size > max) {
+                    max = size;
+                }
+                break;
+            case ClassWriter.HANDLE:
+                size = 4;
+                break;
+            // case ClassWriter.CLASS:
+            // case ClassWriter.STR:
+            // case ClassWriter.MTYPE
+            default:
+                size = 3;
+                break;
             }
             index += size;
         }
@@ -217,9 +220,9 @@ public class ClassReader {
      * Returns the class's access flags (see {@link Opcodes}). This value may
      * not reflect Deprecated and Synthetic flags when bytecode is before 1.5
      * and those flags are represented by attributes.
-     *
+     * 
      * @return the class access flags
-     *
+     * 
      * @see ClassVisitor#visit(int, int, String, String, String, String[])
      */
     public int getAccess() {
@@ -229,9 +232,9 @@ public class ClassReader {
     /**
      * Returns the internal name of the class (see
      * {@link Type#getInternalName() getInternalName}).
-     *
+     * 
      * @return the internal class name
-     *
+     * 
      * @see ClassVisitor#visit(int, int, String, String, String, String[])
      */
     public String getClassName() {
@@ -242,24 +245,23 @@ public class ClassReader {
      * Returns the internal of name of the super class (see
      * {@link Type#getInternalName() getInternalName}). For interfaces, the
      * super class is {@link Object}.
-     *
+     * 
      * @return the internal name of super class, or <tt>null</tt> for
      *         {@link Object} class.
-     *
+     * 
      * @see ClassVisitor#visit(int, int, String, String, String, String[])
      */
     public String getSuperName() {
-        int n = items[readUnsignedShort(header + 4)];
-        return n == 0 ? null : readUTF8(n, new char[maxStringLength]);
+        return readClass(header + 4, new char[maxStringLength]);
     }
 
     /**
      * Returns the internal names of the class's interfaces (see
      * {@link Type#getInternalName() getInternalName}).
-     *
+     * 
      * @return the array of internal names for all implemented interfaces or
      *         <tt>null</tt>.
-     *
+     * 
      * @see ClassVisitor#visit(int, int, String, String, String, String[])
      */
     public String[] getInterfaces() {
@@ -279,8 +281,9 @@ public class ClassReader {
     /**
      * Copies the constant pool data into the given {@link ClassWriter}. Should
      * be called before the {@link #accept(ClassVisitor,int)} method.
-     *
-     * @param classWriter the {@link ClassWriter} to copy constant pool into.
+     * 
+     * @param classWriter
+     *            the {@link ClassWriter} to copy constant pool into.
      */
     void copyPool(final ClassWriter classWriter) {
         char[] buf = new char[maxStringLength];
@@ -292,82 +295,63 @@ public class ClassReader {
             Item item = new Item(i);
             int nameType;
             switch (tag) {
-                case ClassWriter.FIELD:
-                case ClassWriter.METH:
-                case ClassWriter.IMETH:
-                    nameType = items[readUnsignedShort(index + 2)];
-                    item.set(tag,
-                            readClass(index, buf),
-                            readUTF8(nameType, buf),
-                            readUTF8(nameType + 2, buf));
-                    break;
-
-                case ClassWriter.INT:
-                    item.set(readInt(index));
-                    break;
-
-                case ClassWriter.FLOAT:
-                    item.set(Float.intBitsToFloat(readInt(index)));
-                    break;
-
-                case ClassWriter.NAME_TYPE:
-                    item.set(tag,
-                            readUTF8(index, buf),
-                            readUTF8(index + 2, buf),
-                            null);
-                    break;
-
-                case ClassWriter.LONG:
-                    item.set(readLong(index));
-                    ++i;
-                    break;
-
-                case ClassWriter.DOUBLE:
-                    item.set(Double.longBitsToDouble(readLong(index)));
-                    ++i;
-                    break;
-
-                case ClassWriter.UTF8: {
-                    String s = strings[i];
-                    if (s == null) {
-                        index = items[i];
-                        s = strings[i] = readUTF(index + 2,
-                                readUnsignedShort(index),
-                                buf);
-                    }
-                    item.set(tag, s, null, null);
+            case ClassWriter.FIELD:
+            case ClassWriter.METH:
+            case ClassWriter.IMETH:
+                nameType = items[readUnsignedShort(index + 2)];
+                item.set(tag, readClass(index, buf), readUTF8(nameType, buf),
+                        readUTF8(nameType + 2, buf));
+                break;
+            case ClassWriter.INT:
+                item.set(readInt(index));
+                break;
+            case ClassWriter.FLOAT:
+                item.set(Float.intBitsToFloat(readInt(index)));
+                break;
+            case ClassWriter.NAME_TYPE:
+                item.set(tag, readUTF8(index, buf), readUTF8(index + 2, buf),
+                        null);
+                break;
+            case ClassWriter.LONG:
+                item.set(readLong(index));
+                ++i;
+                break;
+            case ClassWriter.DOUBLE:
+                item.set(Double.longBitsToDouble(readLong(index)));
+                ++i;
+                break;
+            case ClassWriter.UTF8: {
+                String s = strings[i];
+                if (s == null) {
+                    index = items[i];
+                    s = strings[i] = readUTF(index + 2,
+                            readUnsignedShort(index), buf);
                 }
-                    break;
-
-                case ClassWriter.HANDLE: {
-                    int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
-                    nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
-                    item.set(ClassWriter.HANDLE_BASE + readByte(index),
-                            readClass(fieldOrMethodRef, buf),
-                            readUTF8(nameType, buf),
-                            readUTF8(nameType + 2, buf));
-
+                item.set(tag, s, null, null);
+                break;
+            }
+            case ClassWriter.HANDLE: {
+                int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
+                nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
+                item.set(ClassWriter.HANDLE_BASE + readByte(index),
+                        readClass(fieldOrMethodRef, buf),
+                        readUTF8(nameType, buf), readUTF8(nameType + 2, buf));
+                break;
+            }
+            case ClassWriter.INDY:
+                if (classWriter.bootstrapMethods == null) {
+                    copyBootstrapMethods(classWriter, items2, buf);
                 }
-                    break;
-
-
-                case ClassWriter.INDY:
-                    if (classWriter.bootstrapMethods == null) {
-                        copyBootstrapMethods(classWriter, items2, buf);
-                    }
-                    nameType = items[readUnsignedShort(index + 2)];
-                    item.set(readUTF8(nameType, buf),
-                            readUTF8(nameType + 2, buf),
-                            readUnsignedShort(index));
-                    break;
-
-
-                // case ClassWriter.STR:
-                // case ClassWriter.CLASS:
-                // case ClassWriter.MTYPE
-                default:
-                    item.set(tag, readUTF8(index, buf), null, null);
-                    break;
+                nameType = items[readUnsignedShort(index + 2)];
+                item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf),
+                        readUnsignedShort(index));
+                break;
+            // case ClassWriter.STR:
+            // case ClassWriter.CLASS:
+            // case ClassWriter.MTYPE
+            default:
+                item.set(tag, readUTF8(index, buf), null, null);
+                break;
             }
 
             int index2 = item.hashCode % items2.length;
@@ -382,77 +366,59 @@ public class ClassReader {
         classWriter.index = ll;
     }
 
-    private void copyBootstrapMethods(ClassWriter classWriter, Item[] items2, char[] buf) {
-        int i, j, k, u, v;
-
-        // skip class header
-        v = header;
-        v += 8 + (readUnsignedShort(v + 6) << 1);
-
-        // skips fields and methods
-        i = readUnsignedShort(v);
-        v += 2;
-        for (; i > 0; --i) {
-            j = readUnsignedShort(v + 6);
-            v += 8;
-            for (; j > 0; --j) {
-                v += 6 + readInt(v + 2);
+    /**
+     * Copies the bootstrap method data into the given {@link ClassWriter}.
+     * Should be called before the {@link #accept(ClassVisitor,int)} method.
+     * 
+     * @param classWriter
+     *            the {@link ClassWriter} to copy bootstrap methods into.
+     */
+    private void copyBootstrapMethods(final ClassWriter classWriter,
+            final Item[] items, final char[] c) {
+        // finds the "BootstrapMethods" attribute
+        int u = getAttributes();
+        boolean found = false;
+        for (int i = readUnsignedShort(u); i > 0; --i) {
+            String attrName = readUTF8(u + 2, c);
+            if ("BootstrapMethods".equals(attrName)) {
+                found = true;
+                break;
             }
+            u += 6 + readInt(u + 4);
         }
-        i = readUnsignedShort(v);
-        v += 2;
-        for (; i > 0; --i) {
-            j = readUnsignedShort(v + 6);
-            v += 8;
-            for (; j > 0; --j) {
-                v += 6 + readInt(v + 2);
-            }
+        if (!found) {
+            return;
         }
-
-        // read class attributes
-        i = readUnsignedShort(v);
-        v += 2;
-        for (; i > 0; --i) {
-            String attrName = readUTF8(v, buf);
-            int size = readInt(v + 2);
-            if ("BootstrapMethods".equals(attrName)) {
-                int boostrapMethodCount = readUnsignedShort(v + 6);
-                int x = v + 8;
-                for (j = 0; j < boostrapMethodCount; j++) {
-                    int hashCode = readConst(readUnsignedShort(x), buf).hashCode();
-                    k = readUnsignedShort(x + 2);
-                    u = x + 4;
-                    for(; k > 0; --k) {
-                        hashCode ^= readConst(readUnsignedShort(u), buf).hashCode();
-                        u += 2;
-                    }
-                    Item item = new Item(j);
-                    item.set(x - v - 8, hashCode & 0x7FFFFFFF);
-
-                    int index2 = item.hashCode % items2.length;
-                    item.next = items2[index2];
-                    items2[index2] = item;
-
-                    x = u;
-                }
-
-                classWriter.bootstrapMethodsCount = boostrapMethodCount;
-                ByteVector bootstrapMethods = new ByteVector(size + 62);
-                bootstrapMethods.putByteArray(b, v + 8, size - 2);
-                classWriter.bootstrapMethods = bootstrapMethods;
-                return;
+        // copies the bootstrap methods in the class writer
+        int boostrapMethodCount = readUnsignedShort(u + 8);
+        for (int j = 0, v = u + 10; j < boostrapMethodCount; j++) {
+            int position = v - u - 10;
+            int hashCode = readConst(readUnsignedShort(v), c).hashCode();
+            for (int k = readUnsignedShort(v + 2); k > 0; --k) {
+                hashCode ^= readConst(readUnsignedShort(v + 4), c).hashCode();
+                v += 2;
             }
-            v += 6 + size;
+            v += 4;
+            Item item = new Item(j);
+            item.set(position, hashCode & 0x7FFFFFFF);
+            int index = item.hashCode % items.length;
+            item.next = items[index];
+            items[index] = item;
         }
-
-        // we are in trouble !!!
+        int attrSize = readInt(u + 4);
+        ByteVector bootstrapMethods = new ByteVector(attrSize + 62);
+        bootstrapMethods.putByteArray(b, u + 10, attrSize - 2);
+        classWriter.bootstrapMethodsCount = boostrapMethodCount;
+        classWriter.bootstrapMethods = bootstrapMethods;
     }
 
     /**
      * Constructs a new {@link ClassReader} object.
-     *
-     * @param is an input stream from which to read the class.
-     * @throws IOException if a problem occurs during reading.
+     * 
+     * @param is
+     *            an input stream from which to read the class.
+     * @throws IOException
+     *             if a problem occurs during reading.
      */
     public ClassReader(final InputStream is) throws IOException {
         this(readClass(is, false));
@@ -460,26 +426,31 @@ public class ClassReader {
 
     /**
      * Constructs a new {@link ClassReader} object.
-     *
-     * @param name the binary qualified name of the class to be read.
-     * @throws IOException if an exception occurs during reading.
+     * 
+     * @param name
+     *            the binary qualified name of the class to be read.
+     * @throws IOException
+     *             if an exception occurs during reading.
      */
     public ClassReader(final String name) throws IOException {
-        this(readClass(ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
-                + ".class"), true));
+        this(readClass(
+                ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
+                        + ".class"), true));
     }
 
     /**
      * Reads the bytecode of a class.
-     *
-     * @param is an input stream from which to read the class.
-     * @param close true to close the input stream after reading.
+     * 
+     * @param is
+     *            an input stream from which to read the class.
+     * @param close
+     *            true to close the input stream after reading.
      * @return the bytecode read from the given input stream.
-     * @throws IOException if a problem occurs during reading.
+     * @throws IOException
+     *             if a problem occurs during reading.
      */
     private static byte[] readClass(final InputStream is, boolean close)
-            throws IOException
-    {
+            throws IOException {
         if (is == null) {
             throw new IOException("Class not found");
         }
@@ -520,14 +491,16 @@ public class ClassReader {
     // ------------------------------------------------------------------------
 
     /**
-     * Makes the given visitor visit the Java class of this {@link ClassReader}.
-     * This class is the one specified in the constructor (see
+     * Makes the given visitor visit the Java class of this {@link ClassReader}
+     * . This class is the one specified in the constructor (see
      * {@link #ClassReader(byte[]) ClassReader}).
-     *
-     * @param classVisitor the visitor that must visit this class.
-     * @param flags option flags that can be used to modify the default behavior
-     *        of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
-     *        {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+     * 
+     * @param classVisitor
+     *            the visitor that must visit this class.
+     * @param flags
+     *            option flags that can be used to modify the default behavior
+     *            of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}
+     *            , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
      */
     public void accept(final ClassVisitor classVisitor, final int flags) {
         accept(classVisitor, new Attribute[0], flags);
@@ -537,1118 +510,1220 @@ public class ClassReader {
      * Makes the given visitor visit the Java class of this {@link ClassReader}.
      * This class is the one specified in the constructor (see
      * {@link #ClassReader(byte[]) ClassReader}).
-     *
-     * @param classVisitor the visitor that must visit this class.
-     * @param attrs prototypes of the attributes that must be parsed during the
-     *        visit of the class. Any attribute whose type is not equal to the
-     *        type of one the prototypes will not be parsed: its byte array
-     *        value will be passed unchanged to the ClassWriter. <i>This may
-     *        corrupt it if this value contains references to the constant pool,
-     *        or has syntactic or semantic links with a class element that has
-     *        been transformed by a class adapter between the reader and the
-     *        writer</i>.
-     * @param flags option flags that can be used to modify the default behavior
-     *        of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
-     *        {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+     * 
+     * @param classVisitor
+     *            the visitor that must visit this class.
+     * @param attrs
+     *            prototypes of the attributes that must be parsed during the
+     *            visit of the class. Any attribute whose type is not equal to
+     *            the type of one the prototypes will not be parsed: its byte
+     *            array value will be passed unchanged to the ClassWriter.
+     *            <i>This may corrupt it if this value contains references to
+     *            the constant pool, or has syntactic or semantic links with a
+     *            class element that has been transformed by a class adapter
+     *            between the reader and the writer</i>.
+     * @param flags
+     *            option flags that can be used to modify the default behavior
+     *            of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}
+     *            , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
      */
-    public void accept(
-        final ClassVisitor classVisitor,
-        final Attribute[] attrs,
-        final int flags)
-    {
-        byte[] b = this.b; // the bytecode array
+    public void accept(final ClassVisitor classVisitor,
+            final Attribute[] attrs, final int flags) {
+        int u = header; // current offset in the class file
         char[] c = new char[maxStringLength]; // buffer used to read strings
-        int i, j, k; // loop variables
-        int u, v, w; // indexes in b
-        Attribute attr;
-
-        int access;
-        String name;
-        String desc;
-        String attrName;
-        String signature;
-        int anns = 0;
-        int ianns = 0;
-        Attribute cattrs = null;
-
-        // visits the header
-        u = header;
-        access = readUnsignedShort(u);
-        name = readClass(u + 2, c);
-        v = items[readUnsignedShort(u + 4)];
-        String superClassName = v == 0 ? null : readUTF8(v, c);
-        String[] implementedItfs = new String[readUnsignedShort(u + 6)];
-        w = 0;
+
+        Context context = new Context();
+        context.attrs = attrs;
+        context.flags = flags;
+        context.buffer = c;
+
+        // reads the class declaration
+        int access = readUnsignedShort(u);
+        String name = readClass(u + 2, c);
+        String superClass = readClass(u + 4, c);
+        String[] interfaces = new String[readUnsignedShort(u + 6)];
         u += 8;
-        for (i = 0; i < implementedItfs.length; ++i) {
-            implementedItfs[i] = readClass(u, c);
+        for (int i = 0; i < interfaces.length; ++i) {
+            interfaces[i] = readClass(u, c);
             u += 2;
         }
 
-        boolean skipCode = (flags & SKIP_CODE) != 0;
-        boolean skipDebug = (flags & SKIP_DEBUG) != 0;
-        boolean unzip = (flags & EXPAND_FRAMES) != 0;
-
-        // skips fields and methods
-        v = u;
-        i = readUnsignedShort(v);
-        v += 2;
-        for (; i > 0; --i) {
-            j = readUnsignedShort(v + 6);
-            v += 8;
-            for (; j > 0; --j) {
-                v += 6 + readInt(v + 2);
-            }
-        }
-        i = readUnsignedShort(v);
-        v += 2;
-        for (; i > 0; --i) {
-            j = readUnsignedShort(v + 6);
-            v += 8;
-            for (; j > 0; --j) {
-                v += 6 + readInt(v + 2);
-            }
-        }
-        // reads the class's attributes
-        signature = null;
+        // reads the class attributes
+        String signature = null;
         String sourceFile = null;
         String sourceDebug = null;
         String enclosingOwner = null;
         String enclosingName = null;
         String enclosingDesc = null;
-        int[] bootstrapMethods = null;  // start indexed of the bsms
-
-        i = readUnsignedShort(v);
-        v += 2;
-        for (; i > 0; --i) {
-            attrName = readUTF8(v, c);
+        int anns = 0;
+        int ianns = 0;
+        int tanns = 0;
+        int itanns = 0;
+        int innerClasses = 0;
+        Attribute attributes = null;
+
+        u = getAttributes();
+        for (int i = readUnsignedShort(u); i > 0; --i) {
+            String attrName = readUTF8(u + 2, c);
             // tests are sorted in decreasing frequency order
             // (based on frequencies observed on typical classes)
             if ("SourceFile".equals(attrName)) {
-                sourceFile = readUTF8(v + 6, c);
+                sourceFile = readUTF8(u + 8, c);
             } else if ("InnerClasses".equals(attrName)) {
-                w = v + 6;
+                innerClasses = u + 8;
             } else if ("EnclosingMethod".equals(attrName)) {
-                enclosingOwner = readClass(v + 6, c);
-                int item = readUnsignedShort(v + 8);
+                enclosingOwner = readClass(u + 8, c);
+                int item = readUnsignedShort(u + 10);
                 if (item != 0) {
                     enclosingName = readUTF8(items[item], c);
                     enclosingDesc = readUTF8(items[item] + 2, c);
                 }
             } else if (SIGNATURES && "Signature".equals(attrName)) {
-                signature = readUTF8(v + 6, c);
-            } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
-                anns = v + 6;
+                signature = readUTF8(u + 8, c);
+            } else if (ANNOTATIONS
+                    && "RuntimeVisibleAnnotations".equals(attrName)) {
+                anns = u + 8;
+            } else if (ANNOTATIONS
+                    && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+                tanns = u + 8;
             } else if ("Deprecated".equals(attrName)) {
                 access |= Opcodes.ACC_DEPRECATED;
             } else if ("Synthetic".equals(attrName)) {
-                access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+                access |= Opcodes.ACC_SYNTHETIC
+                        | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
             } else if ("SourceDebugExtension".equals(attrName)) {
-                int len = readInt(v + 2);
-                sourceDebug = readUTF(v + 6, len, new char[len]);
-            } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
-                ianns = v + 6;
+                int len = readInt(u + 4);
+                sourceDebug = readUTF(u + 8, len, new char[len]);
+            } else if (ANNOTATIONS
+                    && "RuntimeInvisibleAnnotations".equals(attrName)) {
+                ianns = u + 8;
+            } else if (ANNOTATIONS
+                    && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+                itanns = u + 8;
             } else if ("BootstrapMethods".equals(attrName)) {
-                int boostrapMethodCount = readUnsignedShort(v + 6);
-                bootstrapMethods = new int[boostrapMethodCount];
-                int x = v + 8;
-                for (j = 0; j < boostrapMethodCount; j++) {
-                    bootstrapMethods[j] = x;
-                    x += 2 + readUnsignedShort(x + 2) << 1;
+                int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
+                for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
+                    bootstrapMethods[j] = v;
+                    v += 2 + readUnsignedShort(v + 2) << 1;
                 }
+                context.bootstrapMethods = bootstrapMethods;
             } else {
-                attr = readAttribute(attrs,
-                        attrName,
-                        v + 6,
-                        readInt(v + 2),
-                        c,
-                        -1,
-                        null);
+                Attribute attr = readAttribute(attrs, attrName, u + 8,
+                        readInt(u + 4), c, -1, null);
                 if (attr != null) {
-                    attr.next = cattrs;
-                    cattrs = attr;
+                    attr.next = attributes;
+                    attributes = attr;
                 }
             }
-            v += 6 + readInt(v + 2);
-        }
-        // calls the visit method
-        classVisitor.visit(readInt(4),
-                access,
-                name,
-                signature,
-                superClassName,
-                implementedItfs);
-
-        // calls the visitSource method
-        if (!skipDebug && (sourceFile != null || sourceDebug != null)) {
+            u += 6 + readInt(u + 4);
+        }
+
+        // visits the class declaration
+        classVisitor.visit(readInt(items[1] - 7), access, name, signature,
+                superClass, interfaces);
+
+        // visits the source and debug info
+        if ((flags & SKIP_DEBUG) == 0
+                && (sourceFile != null || sourceDebug != null)) {
             classVisitor.visitSource(sourceFile, sourceDebug);
         }
 
-        // calls the visitOuterClass method
+        // visits the outer class
         if (enclosingOwner != null) {
-            classVisitor.visitOuterClass(enclosingOwner,
-                    enclosingName,
+            classVisitor.visitOuterClass(enclosingOwner, enclosingName,
                     enclosingDesc);
         }
 
-        // visits the class annotations
-        if (ANNOTATIONS) {
-            for (i = 1; i >= 0; --i) {
-                v = i == 0 ? ianns : anns;
-                if (v != 0) {
-                    j = readUnsignedShort(v);
-                    v += 2;
-                    for (; j > 0; --j) {
-                        v = readAnnotationValues(v + 2,
-                                c,
-                                true,
-                                classVisitor.visitAnnotation(readUTF8(v, c), i != 0));
-                    }
-                }
+        // visits the class annotations and type annotations
+        if (ANNOTATIONS && anns != 0) {
+            for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
+                v = readAnnotationValues(v + 2, c, true,
+                        classVisitor.visitAnnotation(readUTF8(v, c), true));
+            }
+        }
+        if (ANNOTATIONS && ianns != 0) {
+            for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
+                v = readAnnotationValues(v + 2, c, true,
+                        classVisitor.visitAnnotation(readUTF8(v, c), false));
+            }
+        }
+        if (ANNOTATIONS && tanns != 0) {
+            for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
+                v = readAnnotationTarget(context, v);
+                v = readAnnotationValues(v + 2, c, true,
+                        classVisitor.visitTypeAnnotation(context.typeRef,
+                                context.typePath, readUTF8(v, c), true));
+            }
+        }
+        if (ANNOTATIONS && itanns != 0) {
+            for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
+                v = readAnnotationTarget(context, v);
+                v = readAnnotationValues(v + 2, c, true,
+                        classVisitor.visitTypeAnnotation(context.typeRef,
+                                context.typePath, readUTF8(v, c), false));
             }
         }
 
-        // visits the class attributes
-        while (cattrs != null) {
-            attr = cattrs.next;
-            cattrs.next = null;
-            classVisitor.visitAttribute(cattrs);
-            cattrs = attr;
+        // visits the attributes
+        while (attributes != null) {
+            Attribute attr = attributes.next;
+            attributes.next = null;
+            classVisitor.visitAttribute(attributes);
+            attributes = attr;
         }
 
-        // calls the visitInnerClass method
-        if (w != 0) {
-            i = readUnsignedShort(w);
-            w += 2;
-            for (; i > 0; --i) {
-                classVisitor.visitInnerClass(readUnsignedShort(w) == 0
-                        ? null
-                        : readClass(w, c), readUnsignedShort(w + 2) == 0
-                        ? null
-                        : readClass(w + 2, c), readUnsignedShort(w + 4) == 0
-                        ? null
-                        : readUTF8(w + 4, c), readUnsignedShort(w + 6));
-                w += 8;
+        // visits the inner classes
+        if (innerClasses != 0) {
+            int v = innerClasses + 2;
+            for (int i = readUnsignedShort(innerClasses); i > 0; --i) {
+                classVisitor.visitInnerClass(readClass(v, c),
+                        readClass(v + 2, c), readUTF8(v + 4, c),
+                        readUnsignedShort(v + 6));
+                v += 8;
             }
         }
 
-        // visits the fields
-        i = readUnsignedShort(u);
+        // visits the fields and methods
+        u = header + 10 + 2 * interfaces.length;
+        for (int i = readUnsignedShort(u - 2); i > 0; --i) {
+            u = readField(classVisitor, context, u);
+        }
         u += 2;
-        for (; i > 0; --i) {
-            access = readUnsignedShort(u);
-            name = readUTF8(u + 2, c);
-            desc = readUTF8(u + 4, c);
-            // visits the field's attributes and looks for a ConstantValue
-            // attribute
-            int fieldValueItem = 0;
-            signature = null;
-            anns = 0;
-            ianns = 0;
-            cattrs = null;
-
-            j = readUnsignedShort(u + 6);
-            u += 8;
-            for (; j > 0; --j) {
-                attrName = readUTF8(u, c);
-                // tests are sorted in decreasing frequency order
-                // (based on frequencies observed on typical classes)
-                if ("ConstantValue".equals(attrName)) {
-                    fieldValueItem = readUnsignedShort(u + 6);
-                } else if (SIGNATURES && "Signature".equals(attrName)) {
-                    signature = readUTF8(u + 6, c);
-                } else if ("Deprecated".equals(attrName)) {
-                    access |= Opcodes.ACC_DEPRECATED;
-                } else if ("Synthetic".equals(attrName)) {
-                    access |= Opcodes.ACC_SYNTHETIC  | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
-                } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
-                    anns = u + 6;
-                } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
-                    ianns = u + 6;
-                } else {
-                    attr = readAttribute(attrs,
-                            attrName,
-                            u + 6,
-                            readInt(u + 2),
-                            c,
-                            -1,
-                            null);
-                    if (attr != null) {
-                        attr.next = cattrs;
-                        cattrs = attr;
-                    }
+        for (int i = readUnsignedShort(u - 2); i > 0; --i) {
+            u = readMethod(classVisitor, context, u);
+        }
+
+        // visits the end of the class
+        classVisitor.visitEnd();
+    }
+
+    /**
+     * Reads a field and makes the given visitor visit it.
+     * 
+     * @param classVisitor
+     *            the visitor that must visit the field.
+     * @param context
+     *            information about the class being parsed.
+     * @param u
+     *            the start offset of the field in the class file.
+     * @return the offset of the first byte following the field in the class.
+     */
+    private int readField(final ClassVisitor classVisitor,
+            final Context context, int u) {
+        // reads the field declaration
+        char[] c = context.buffer;
+        int access = readUnsignedShort(u);
+        String name = readUTF8(u + 2, c);
+        String desc = readUTF8(u + 4, c);
+        u += 6;
+
+        // reads the field attributes
+        String signature = null;
+        int anns = 0;
+        int ianns = 0;
+        int tanns = 0;
+        int itanns = 0;
+        Object value = null;
+        Attribute attributes = null;
+
+        for (int i = readUnsignedShort(u); i > 0; --i) {
+            String attrName = readUTF8(u + 2, c);
+            // tests are sorted in decreasing frequency order
+            // (based on frequencies observed on typical classes)
+            if ("ConstantValue".equals(attrName)) {
+                int item = readUnsignedShort(u + 8);
+                value = item == 0 ? null : readConst(item, c);
+            } else if (SIGNATURES && "Signature".equals(attrName)) {
+                signature = readUTF8(u + 8, c);
+            } else if ("Deprecated".equals(attrName)) {
+                access |= Opcodes.ACC_DEPRECATED;
+            } else if ("Synthetic".equals(attrName)) {
+                access |= Opcodes.ACC_SYNTHETIC
+                        | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+            } else if (ANNOTATIONS
+                    && "RuntimeVisibleAnnotations".equals(attrName)) {
+                anns = u + 8;
+            } else if (ANNOTATIONS
+                    && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+                tanns = u + 8;
+            } else if (ANNOTATIONS
+                    && "RuntimeInvisibleAnnotations".equals(attrName)) {
+                ianns = u + 8;
+            } else if (ANNOTATIONS
+                    && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+                itanns = u + 8;
+            } else {
+                Attribute attr = readAttribute(context.attrs, attrName, u + 8,
+                        readInt(u + 4), c, -1, null);
+                if (attr != null) {
+                    attr.next = attributes;
+                    attributes = attr;
                 }
-                u += 6 + readInt(u + 2);
             }
-            // visits the field
-            FieldVisitor fv = classVisitor.visitField(access,
-                    name,
-                    desc,
-                    signature,
-                    fieldValueItem == 0 ? null : readConst(fieldValueItem, c));
-            // visits the field annotations and attributes
-            if (fv != null) {
-                if (ANNOTATIONS) {
-                    for (j = 1; j >= 0; --j) {
-                        v = j == 0 ? ianns : anns;
-                        if (v != 0) {
-                            k = readUnsignedShort(v);
-                            v += 2;
-                            for (; k > 0; --k) {
-                                v = readAnnotationValues(v + 2,
-                                        c,
-                                        true,
-                                        fv.visitAnnotation(readUTF8(v, c), j != 0));
-                            }
-                        }
-                    }
-                }
-                while (cattrs != null) {
-                    attr = cattrs.next;
-                    cattrs.next = null;
-                    fv.visitAttribute(cattrs);
-                    cattrs = attr;
-                }
-                fv.visitEnd();
+            u += 6 + readInt(u + 4);
+        }
+        u += 2;
+
+        // visits the field declaration
+        FieldVisitor fv = classVisitor.visitField(access, name, desc,
+                signature, value);
+        if (fv == null) {
+            return u;
+        }
+
+        // visits the field annotations and type annotations
+        if (ANNOTATIONS && anns != 0) {
+            for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
+                v = readAnnotationValues(v + 2, c, true,
+                        fv.visitAnnotation(readUTF8(v, c), true));
+            }
+        }
+        if (ANNOTATIONS && ianns != 0) {
+            for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
+                v = readAnnotationValues(v + 2, c, true,
+                        fv.visitAnnotation(readUTF8(v, c), false));
+            }
+        }
+        if (ANNOTATIONS && tanns != 0) {
+            for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
+                v = readAnnotationTarget(context, v);
+                v = readAnnotationValues(v + 2, c, true,
+                        fv.visitTypeAnnotation(context.typeRef,
+                                context.typePath, readUTF8(v, c), true));
+            }
+        }
+        if (ANNOTATIONS && itanns != 0) {
+            for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
+                v = readAnnotationTarget(context, v);
+                v = readAnnotationValues(v + 2, c, true,
+                        fv.visitTypeAnnotation(context.typeRef,
+                                context.typePath, readUTF8(v, c), false));
             }
         }
 
-        // visits the methods
-        i = readUnsignedShort(u);
-        u += 2;
-        for (; i > 0; --i) {
-            int u0 = u + 6;
-            access = readUnsignedShort(u);
-            name = readUTF8(u + 2, c);
-            desc = readUTF8(u + 4, c);
-            signature = null;
-            anns = 0;
-            ianns = 0;
-            int dann = 0;
-            int mpanns = 0;
-            int impanns = 0;
-            cattrs = null;
-            v = 0;
-            w = 0;
-
-            // looks for Code and Exceptions attributes
-            j = readUnsignedShort(u + 6);
-            u += 8;
-            for (; j > 0; --j) {
-                attrName = readUTF8(u, c);
-                int attrSize = readInt(u + 2);
-                u += 6;
-                // tests are sorted in decreasing frequency order
-                // (based on frequencies observed on typical classes)
-                if ("Code".equals(attrName)) {
-                    if (!skipCode) {
-                        v = u;
-                    }
-                } else if ("Exceptions".equals(attrName)) {
-                    w = u;
-                } else if (SIGNATURES && "Signature".equals(attrName)) {
-                    signature = readUTF8(u, c);
-                } else if ("Deprecated".equals(attrName)) {
-                    access |= Opcodes.ACC_DEPRECATED;
-                } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
-                    anns = u;
-                } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
-                    dann = u;
-                } else if ("Synthetic".equals(attrName)) {
-                    access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
-                } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
-                    ianns = u;
-                } else if (ANNOTATIONS && "RuntimeVisibleParameterAnnotations".equals(attrName))
-                {
-                    mpanns = u;
-                } else if (ANNOTATIONS && "RuntimeInvisibleParameterAnnotations".equals(attrName))
-                {
-                    impanns = u;
-                } else {
-                    attr = readAttribute(attrs,
-                            attrName,
-                            u,
-                            attrSize,
-                            c,
-                            -1,
-                            null);
-                    if (attr != null) {
-                        attr.next = cattrs;
-                        cattrs = attr;
-                    }
+        // visits the field attributes
+        while (attributes != null) {
+            Attribute attr = attributes.next;
+            attributes.next = null;
+            fv.visitAttribute(attributes);
+            attributes = attr;
+        }
+
+        // visits the end of the field
+        fv.visitEnd();
+
+        return u;
+    }
+
+    /**
+     * Reads a method and makes the given visitor visit it.
+     * 
+     * @param classVisitor
+     *            the visitor that must visit the method.
+     * @param context
+     *            information about the class being parsed.
+     * @param u
+     *            the start offset of the method in the class file.
+     * @return the offset of the first byte following the method in the class.
+     */
+    private int readMethod(final ClassVisitor classVisitor,
+            final Context context, int u) {
+        // reads the method declaration
+        char[] c = context.buffer;
+        context.access = readUnsignedShort(u);
+        context.name = readUTF8(u + 2, c);
+        context.desc = readUTF8(u + 4, c);
+        u += 6;
+
+        // reads the method attributes
+        int code = 0;
+        int exception = 0;
+        String[] exceptions = null;
+        String signature = null;
+        int methodParameters = 0;
+        int anns = 0;
+        int ianns = 0;
+        int tanns = 0;
+        int itanns = 0;
+        int dann = 0;
+        int mpanns = 0;
+        int impanns = 0;
+        int firstAttribute = u;
+        Attribute attributes = null;
+
+        for (int i = readUnsignedShort(u); i > 0; --i) {
+            String attrName = readUTF8(u + 2, c);
+            // tests are sorted in decreasing frequency order
+            // (based on frequencies observed on typical classes)
+            if ("Code".equals(attrName)) {
+                if ((context.flags & SKIP_CODE) == 0) {
+                    code = u + 8;
                 }
-                u += attrSize;
-            }
-            // reads declared exceptions
-            String[] exceptions;
-            if (w == 0) {
-                exceptions = null;
+            } else if ("Exceptions".equals(attrName)) {
+                exceptions = new String[readUnsignedShort(u + 8)];
+                exception = u + 10;
+                for (int j = 0; j < exceptions.length; ++j) {
+                    exceptions[j] = readClass(exception, c);
+                    exception += 2;
+                }
+            } else if (SIGNATURES && "Signature".equals(attrName)) {
+                signature = readUTF8(u + 8, c);
+            } else if ("Deprecated".equals(attrName)) {
+                context.access |= Opcodes.ACC_DEPRECATED;
+            } else if (ANNOTATIONS
+                    && "RuntimeVisibleAnnotations".equals(attrName)) {
+                anns = u + 8;
+            } else if (ANNOTATIONS
+                    && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+                tanns = u + 8;
+            } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
+                dann = u + 8;
+            } else if ("Synthetic".equals(attrName)) {
+                context.access |= Opcodes.ACC_SYNTHETIC
+                        | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+            } else if (ANNOTATIONS
+                    && "RuntimeInvisibleAnnotations".equals(attrName)) {
+                ianns = u + 8;
+            } else if (ANNOTATIONS
+                    && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+                itanns = u + 8;
+            } else if (ANNOTATIONS
+                    && "RuntimeVisibleParameterAnnotations".equals(attrName)) {
+                mpanns = u + 8;
+            } else if (ANNOTATIONS
+                    && "RuntimeInvisibleParameterAnnotations".equals(attrName)) {
+                impanns = u + 8;
+            } else if ("MethodParameters".equals(attrName)) {
+                methodParameters = u + 8;
             } else {
-                exceptions = new String[readUnsignedShort(w)];
-                w += 2;
-                for (j = 0; j < exceptions.length; ++j) {
-                    exceptions[j] = readClass(w, c);
-                    w += 2;
+                Attribute attr = readAttribute(context.attrs, attrName, u + 8,
+                        readInt(u + 4), c, -1, null);
+                if (attr != null) {
+                    attr.next = attributes;
+                    attributes = attr;
                 }
             }
+            u += 6 + readInt(u + 4);
+        }
+        u += 2;
 
-            // visits the method's code, if any
-            MethodVisitor mv = classVisitor.visitMethod(access,
-                    name,
-                    desc,
-                    signature,
-                    exceptions);
+        // visits the method declaration
+        MethodVisitor mv = classVisitor.visitMethod(context.access,
+                context.name, context.desc, signature, exceptions);
+        if (mv == null) {
+            return u;
+        }
 
-            if (mv != null) {
-                /*
-                 * if the returned MethodVisitor is in fact a MethodWriter, it
-                 * means there is no method adapter between the reader and the
-                 * writer. If, in addition, the writer's constant pool was
-                 * copied from this reader (mw.cw.cr == this), and the signature
-                 * and exceptions of the method have not been changed, then it
-                 * is possible to skip all visit events and just copy the
-                 * original code of the method to the writer (the access, name
-                 * and descriptor can have been changed, this is not important
-                 * since they are not copied as is from the reader).
-                 */
-                if (WRITER && mv instanceof MethodWriter) {
-                    MethodWriter mw = (MethodWriter) mv;
-                    if (mw.cw.cr == this) {
-                        if (signature == mw.signature) {
-                            boolean sameExceptions = false;
-                            if (exceptions == null) {
-                                sameExceptions = mw.exceptionCount == 0;
-                            } else {
-                                if (exceptions.length == mw.exceptionCount) {
-                                    sameExceptions = true;
-                                    for (j = exceptions.length - 1; j >= 0; --j)
-                                    {
-                                        w -= 2;
-                                        if (mw.exceptions[j] != readUnsignedShort(w))
-                                        {
-                                            sameExceptions = false;
-                                            break;
-                                        }
-                                    }
-                                }
-                            }
-                            if (sameExceptions) {
-                                /*
-                                 * we do not copy directly the code into
-                                 * MethodWriter to save a byte array copy
-                                 * operation. The real copy will be done in
-                                 * ClassWriter.toByteArray().
-                                 */
-                                mw.classReaderOffset = u0;
-                                mw.classReaderLength = u - u0;
-                                continue;
-                            }
+        /*
+         * if the returned MethodVisitor is in fact a MethodWriter, it means
+         * there is no method adapter between the reader and the writer. If, in
+         * addition, the writer's constant pool was copied from this reader
+         * (mw.cw.cr == this), and the signature and exceptions of the method
+         * have not been changed, then it is possible to skip all visit events
+         * and just copy the original code of the method to the writer (the
+         * access, name and descriptor can have been changed, this is not
+         * important since they are not copied as is from the reader).
+         */
+        if (WRITER && mv instanceof MethodWriter) {
+            MethodWriter mw = (MethodWriter) mv;
+            if (mw.cw.cr == this && signature == mw.signature) {
+                boolean sameExceptions = false;
+                if (exceptions == null) {
+                    sameExceptions = mw.exceptionCount == 0;
+                } else if (exceptions.length == mw.exceptionCount) {
+                    sameExceptions = true;
+                    for (int j = exceptions.length - 1; j >= 0; --j) {
+                        exception -= 2;
+                        if (mw.exceptions[j] != readUnsignedShort(exception)) {
+                            sameExceptions = false;
+                            break;
                         }
                     }
                 }
-
-                if (ANNOTATIONS && dann != 0) {
-                    AnnotationVisitor dv = mv.visitAnnotationDefault();
-                    readAnnotationValue(dann, c, null, dv);
-                    if (dv != null) {
-                        dv.visitEnd();
-                    }
-                }
-                if (ANNOTATIONS) {
-                    for (j = 1; j >= 0; --j) {
-                        w = j == 0 ? ianns : anns;
-                        if (w != 0) {
-                            k = readUnsignedShort(w);
-                            w += 2;
-                            for (; k > 0; --k) {
-                                w = readAnnotationValues(w + 2,
-                                        c,
-                                        true,
-                                        mv.visitAnnotation(readUTF8(w, c), j != 0));
-                            }
-                        }
-                    }
+                if (sameExceptions) {
+                    /*
+                     * we do not copy directly the code into MethodWriter to
+                     * save a byte array copy operation. The real copy will be
+                     * done in ClassWriter.toByteArray().
+                     */
+                    mw.classReaderOffset = firstAttribute;
+                    mw.classReaderLength = u - firstAttribute;
+                    return u;
                 }
-                if (ANNOTATIONS && mpanns != 0) {
-                    readParameterAnnotations(mpanns, desc, c, true, mv);
+            }
+        }
+
+        // visit the method parameters
+        if (methodParameters != 0) {
+            for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) {
+                mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2));
+            }
+        }
+
+        // visits the method annotations
+        if (ANNOTATIONS && dann != 0) {
+            AnnotationVisitor dv = mv.visitAnnotationDefault();
+            readAnnotationValue(dann, c, null, dv);
+            if (dv != null) {
+                dv.visitEnd();
+            }
+        }
+        if (ANNOTATIONS && anns != 0) {
+            for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
+                v = readAnnotationValues(v + 2, c, true,
+                        mv.visitAnnotation(readUTF8(v, c), true));
+            }
+        }
+        if (ANNOTATIONS && ianns != 0) {
+            for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
+                v = readAnnotationValues(v + 2, c, true,
+                        mv.visitAnnotation(readUTF8(v, c), false));
+            }
+        }
+        if (ANNOTATIONS && tanns != 0) {
+            for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
+                v = readAnnotationTarget(context, v);
+                v = readAnnotationValues(v + 2, c, true,
+                        mv.visitTypeAnnotation(context.typeRef,
+                                context.typePath, readUTF8(v, c), true));
+            }
+        }
+        if (ANNOTATIONS && itanns != 0) {
+            for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
+                v = readAnnotationTarget(context, v);
+                v = readAnnotationValues(v + 2, c, true,
+                        mv.visitTypeAnnotation(context.typeRef,
+                                context.typePath, readUTF8(v, c), false));
+            }
+        }
+        if (ANNOTATIONS && mpanns != 0) {
+            readParameterAnnotations(mv, context, mpanns, true);
+        }
+        if (ANNOTATIONS && impanns != 0) {
+            readParameterAnnotations(mv, context, impanns, false);
+        }
+
+        // visits the method attributes
+        while (attributes != null) {
+            Attribute attr = attributes.next;
+            attributes.next = null;
+            mv.visitAttribute(attributes);
+            attributes = attr;
+        }
+
+        // visits the method code
+        if (code != 0) {
+            mv.visitCode();
+            readCode(mv, context, code);
+        }
+
+        // visits the end of the method
+        mv.visitEnd();
+
+        return u;
+    }
+
+    /**
+     * Reads the bytecode of a method and makes the given visitor visit it.
+     * 
+     * @param mv
+     *            the visitor that must visit the method's code.
+     * @param context
+     *            information about the class being parsed.
+     * @param u
+     *            the start offset of the code attribute in the class file.
+     */
+    private void readCode(final MethodVisitor mv, final Context context, int u) {
+        // reads the header
+        byte[] b = this.b;
+        char[] c = context.buffer;
+        int maxStack = readUnsignedShort(u);
+        int maxLocals = readUnsignedShort(u + 2);
+        int codeLength = readInt(u + 4);
+        u += 8;
+
+        // reads the bytecode to find the labels
+        int codeStart = u;
+        int codeEnd = u + codeLength;
+        Label[] labels = context.labels = new Label[codeLength + 2];
+        readLabel(codeLength + 1, labels);
+        while (u < codeEnd) {
+            int offset = u - codeStart;
+            int opcode = b[u] & 0xFF;
+            switch (ClassWriter.TYPE[opcode]) {
+            case ClassWriter.NOARG_INSN:
+            case ClassWriter.IMPLVAR_INSN:
+                u += 1;
+                break;
+            case ClassWriter.LABEL_INSN:
+                readLabel(offset + readShort(u + 1), labels);
+                u += 3;
+                break;
+            case ClassWriter.LABELW_INSN:
+                readLabel(offset + readInt(u + 1), labels);
+                u += 5;
+                break;
+            case ClassWriter.WIDE_INSN:
+                opcode = b[u + 1] & 0xFF;
+                if (opcode == Opcodes.IINC) {
+                    u += 6;
+                } else {
+                    u += 4;
                 }
-                if (ANNOTATIONS && impanns != 0) {
-                    readParameterAnnotations(impanns, desc, c, false, mv);
+                break;
+            case ClassWriter.TABL_INSN:
+                // skips 0 to 3 padding bytes
+                u = u + 4 - (offset & 3);
+                // reads instruction
+                readLabel(offset + readInt(u), labels);
+                for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) {
+                    readLabel(offset + readInt(u + 12), labels);
+                    u += 4;
                 }
-                while (cattrs != null) {
-                    attr = cattrs.next;
-                    cattrs.next = null;
-                    mv.visitAttribute(cattrs);
-                    cattrs = attr;
+                u += 12;
+                break;
+            case ClassWriter.LOOK_INSN:
+                // skips 0 to 3 padding bytes
+                u = u + 4 - (offset & 3);
+                // reads instruction
+                readLabel(offset + readInt(u), labels);
+                for (int i = readInt(u + 4); i > 0; --i) {
+                    readLabel(offset + readInt(u + 12), labels);
+                    u += 8;
                 }
+                u += 8;
+                break;
+            case ClassWriter.VAR_INSN:
+            case ClassWriter.SBYTE_INSN:
+            case ClassWriter.LDC_INSN:
+                u += 2;
+                break;
+            case ClassWriter.SHORT_INSN:
+            case ClassWriter.LDCW_INSN:
+            case ClassWriter.FIELDORMETH_INSN:
+            case ClassWriter.TYPE_INSN:
+            case ClassWriter.IINC_INSN:
+                u += 3;
+                break;
+            case ClassWriter.ITFMETH_INSN:
+            case ClassWriter.INDYMETH_INSN:
+                u += 5;
+                break;
+            // case MANA_INSN:
+            default:
+                u += 4;
+                break;
             }
+        }
 
-            if (mv != null && v != 0) {
-                int maxStack = readUnsignedShort(v);
-                int maxLocals = readUnsignedShort(v + 2);
-                int codeLength = readInt(v + 4);
-                v += 8;
+        // reads the try catch entries to find the labels, and also visits them
+        for (int i = readUnsignedShort(u); i > 0; --i) {
+            Label start = readLabel(readUnsignedShort(u + 2), labels);
+            Label end = readLabel(readUnsignedShort(u + 4), labels);
+            Label handler = readLabel(readUnsignedShort(u + 6), labels);
+            String type = readUTF8(items[readUnsignedShort(u + 8)], c);
+            mv.visitTryCatchBlock(start, end, handler, type);
+            u += 8;
+        }
+        u += 2;
 
-                int codeStart = v;
-                int codeEnd = v + codeLength;
-
-                mv.visitCode();
-
-                // 1st phase: finds the labels
-                int label;
-                Label[] labels = new Label[codeLength + 2];
-                readLabel(codeLength + 1, labels);
-                while (v < codeEnd) {
-                    w = v - codeStart;
-                    int opcode = b[v] & 0xFF;
-                    switch (ClassWriter.TYPE[opcode]) {
-                        case ClassWriter.NOARG_INSN:
-                        case ClassWriter.IMPLVAR_INSN:
-                            v += 1;
-                            break;
-                        case ClassWriter.LABEL_INSN:
-                            readLabel(w + readShort(v + 1), labels);
-                            v += 3;
-                            break;
-                        case ClassWriter.LABELW_INSN:
-                            readLabel(w + readInt(v + 1), labels);
-                            v += 5;
-                            break;
-                        case ClassWriter.WIDE_INSN:
-                            opcode = b[v + 1] & 0xFF;
-                            if (opcode == Opcodes.IINC) {
-                                v += 6;
-                            } else {
-                                v += 4;
-                            }
-                            break;
-                        case ClassWriter.TABL_INSN:
-                            // skips 0 to 3 padding bytes*
-                            v = v + 4 - (w & 3);
-                            // reads instruction
-                            readLabel(w + readInt(v), labels);
-                            j = readInt(v + 8) - readInt(v + 4) + 1;
-                            v += 12;
-                            for (; j > 0; --j) {
-                                readLabel(w + readInt(v), labels);
-                                v += 4;
-                            }
-                            break;
-                        case ClassWriter.LOOK_INSN:
-                            // skips 0 to 3 padding bytes*
-                            v = v + 4 - (w & 3);
-                            // reads instruction
-                            readLabel(w + readInt(v), labels);
-                            j = readInt(v + 4);
-                            v += 8;
-                            for (; j > 0; --j) {
-                                readLabel(w + readInt(v + 4), labels);
-                                v += 8;
-                            }
-                            break;
-                        case ClassWriter.VAR_INSN:
-                        case ClassWriter.SBYTE_INSN:
-                        case ClassWriter.LDC_INSN:
-                            v += 2;
-                            break;
-                        case ClassWriter.SHORT_INSN:
-                        case ClassWriter.LDCW_INSN:
-                        case ClassWriter.FIELDORMETH_INSN:
-                        case ClassWriter.TYPE_INSN:
-                        case ClassWriter.IINC_INSN:
-                            v += 3;
-                            break;
-                        case ClassWriter.ITFMETH_INSN:
-                        case ClassWriter.INDYMETH_INSN:
-                            v += 5;
-                            break;
-                        // case MANA_INSN:
-                        default:
-                            v += 4;
-                            break;
-                    }
-                }
-                // parses the try catch entries
-                j = readUnsignedShort(v);
-                v += 2;
-                for (; j > 0; --j) {
-                    Label start = readLabel(readUnsignedShort(v), labels);
-                    Label end = readLabel(readUnsignedShort(v + 2), labels);
-                    Label handler = readLabel(readUnsignedShort(v + 4), labels);
-                    int type = readUnsignedShort(v + 6);
-                    if (type == 0) {
-                        mv.visitTryCatchBlock(start, end, handler, null);
-                    } else {
-                        mv.visitTryCatchBlock(start,
-                                end,
-                                handler,
-                                readUTF8(items[type], c));
-                    }
-                    v += 8;
-                }
-                // parses the local variable, line number tables, and code
-                // attributes
-                int varTable = 0;
-                int varTypeTable = 0;
-                int stackMap = 0;
-                int stackMapSize = 0;
-                int frameCount = 0;
-                int frameMode = 0;
-                int frameOffset = 0;
-                int frameLocalCount = 0;
-                int frameLocalDiff = 0;
-                int frameStackCount = 0;
-                Object[] frameLocal = null;
-                Object[] frameStack = null;
-                boolean zip = true;
-                cattrs = null;
-                j = readUnsignedShort(v);
-                v += 2;
-                for (; j > 0; --j) {
-                    attrName = readUTF8(v, c);
-                    if ("LocalVariableTable".equals(attrName)) {
-                        if (!skipDebug) {
-                            varTable = v + 6;
-                            k = readUnsignedShort(v + 6);
-                            w = v + 8;
-                            for (; k > 0; --k) {
-                                label = readUnsignedShort(w);
-                                if (labels[label] == null) {
-                                    readLabel(label, labels).status |= Label.DEBUG;
-                                }
-                                label += readUnsignedShort(w + 2);
-                                if (labels[label] == null) {
-                                    readLabel(label, labels).status |= Label.DEBUG;
-                                }
-                                w += 10;
-                            }
-                        }
-                    } else if ("LocalVariableTypeTable".equals(attrName)) {
-                        varTypeTable = v + 6;
-                    } else if ("LineNumberTable".equals(attrName)) {
-                        if (!skipDebug) {
-                            k = readUnsignedShort(v + 6);
-                            w = v + 8;
-                            for (; k > 0; --k) {
-                                label = readUnsignedShort(w);
-                                if (labels[label] == null) {
-                                    readLabel(label, labels).status |= Label.DEBUG;
-                                }
-                                labels[label].line = readUnsignedShort(w + 2);
-                                w += 4;
-                            }
-                        }
-                    } else if (FRAMES && "StackMapTable".equals(attrName)) {
-                        if ((flags & SKIP_FRAMES) == 0) {
-                            stackMap = v + 8;
-                            stackMapSize = readInt(v + 2);
-                            frameCount = readUnsignedShort(v + 6);
+        // reads the code attributes
+        int[] tanns = null; // start index of each visible type annotation
+        int[] itanns = null; // start index of each invisible type annotation
+        int tann = 0; // current index in tanns array
+        int itann = 0; // current index in itanns array
+        int ntoff = -1; // next visible type annotation code offset
+        int nitoff = -1; // next invisible type annotation code offset
+        int varTable = 0;
+        int varTypeTable = 0;
+        boolean zip = true;
+        boolean unzip = (context.flags & EXPAND_FRAMES) != 0;
+        int stackMap = 0;
+        int stackMapSize = 0;
+        int frameCount = 0;
+        Context frame = null;
+        Attribute attributes = null;
+
+        for (int i = readUnsignedShort(u); i > 0; --i) {
+            String attrName = readUTF8(u + 2, c);
+            if ("LocalVariableTable".equals(attrName)) {
+                if ((context.flags & SKIP_DEBUG) == 0) {
+                    varTable = u + 8;
+                    for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
+                        int label = readUnsignedShort(v + 10);
+                        if (labels[label] == null) {
+                            readLabel(label, labels).status |= Label.DEBUG;
                         }
-                        /*
-                         * here we do not extract the labels corresponding to
-                         * the attribute content. This would require a full
-                         * parsing of the attribute, which would need to be
-                         * repeated in the second phase (see below). Instead the
-                         * content of the attribute is read one frame at a time
-                         * (i.e. after a frame has been visited, the next frame
-                         * is read), and the labels it contains are also
-                         * extracted one frame at a time. Thanks to the ordering
-                         * of frames, having only a "one frame lookahead" is not
-                         * a problem, i.e. it is not possible to see an offset
-                         * smaller than the offset of the current insn and for
-                         * which no Label exist.
-                         */
-                        /*
-                         * This is not true for UNINITIALIZED type offsets. We
-                         * solve this by parsing the stack map table without a
-                         * full decoding (see below).
-                         */
-                    } else if (FRAMES && "StackMap".equals(attrName)) {
-                        if ((flags & SKIP_FRAMES) == 0) {
-                            stackMap = v + 8;
-                            stackMapSize = readInt(v + 2);
-                            frameCount = readUnsignedShort(v + 6);
-                            zip = false;
-                        }
-                        /*
-                         * IMPORTANT! here we assume that the frames are
-                         * ordered, as in the StackMapTable attribute, although
-                         * this is not guaranteed by the attribute format.
-                         */
-                    } else {
-                        for (k = 0; k < attrs.length; ++k) {
-                            if (attrs[k].type.equals(attrName)) {
-                                attr = attrs[k].read(this,
-                                        v + 6,
-                                        readInt(v + 2),
-                                        c,
-                                        codeStart - 8,
-                                        labels);
-                                if (attr != null) {
-                                    attr.next = cattrs;
-                                    cattrs = attr;
-                                }
-                            }
+                        label += readUnsignedShort(v + 12);
+                        if (labels[label] == null) {
+                            readLabel(label, labels).status |= Label.DEBUG;
                         }
+                        v += 10;
                     }
-                    v += 6 + readInt(v + 2);
                 }
-
-                // 2nd phase: visits each instruction
-                if (FRAMES && stackMap != 0) {
-                    // creates the very first (implicit) frame from the method
-                    // descriptor
-                    frameLocal = new Object[maxLocals];
-                    frameStack = new Object[maxStack];
-                    if (unzip) {
-                        int local = 0;
-                        if ((access & Opcodes.ACC_STATIC) == 0) {
-                            if ("<init>".equals(name)) {
-                                frameLocal[local++] = Opcodes.UNINITIALIZED_THIS;
-                            } else {
-                                frameLocal[local++] = readClass(header + 2, c);
-                            }
-                        }
-                        j = 1;
-                        loop: while (true) {
-                            k = j;
-                            switch (desc.charAt(j++)) {
-                                case 'Z':
-                                case 'C':
-                                case 'B':
-                                case 'S':
-                                case 'I':
-                                    frameLocal[local++] = Opcodes.INTEGER;
-                                    break;
-                                case 'F':
-                                    frameLocal[local++] = Opcodes.FLOAT;
-                                    break;
-                                case 'J':
-                                    frameLocal[local++] = Opcodes.LONG;
-                                    break;
-                                case 'D':
-                                    frameLocal[local++] = Opcodes.DOUBLE;
-                                    break;
-                                case '[':
-                                    while (desc.charAt(j) == '[') {
-                                        ++j;
-                                    }
-                                    if (desc.charAt(j) == 'L') {
-                                        ++j;
-                                        while (desc.charAt(j) != ';') {
-                                            ++j;
-                                        }
-                                    }
-                                    frameLocal[local++] = desc.substring(k, ++j);
-                                    break;
-                                case 'L':
-                                    while (desc.charAt(j) != ';') {
-                                        ++j;
-                                    }
-                                    frameLocal[local++] = desc.substring(k + 1,
-                                            j++);
-                                    break;
-                                default:
-                                    break loop;
-                            }
+            } else if ("LocalVariableTypeTable".equals(attrName)) {
+                varTypeTable = u + 8;
+            } else if ("LineNumberTable".equals(attrName)) {
+                if ((context.flags & SKIP_DEBUG) == 0) {
+                    for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
+                        int label = readUnsignedShort(v + 10);
+                        if (labels[label] == null) {
+                            readLabel(label, labels).status |= Label.DEBUG;
                         }
-                        frameLocalCount = local;
+                        labels[label].line = readUnsignedShort(v + 12);
+                        v += 4;
                     }
-                    /*
-                     * for the first explicit frame the offset is not
-                     * offset_delta + 1 but only offset_delta; setting the
-                     * implicit frame offset to -1 allow the use of the
-                     * "offset_delta + 1" rule in all cases
-                     */
-                    frameOffset = -1;
-                    /*
-                     * Finds labels for UNINITIALIZED frame types. Instead of
-                     * decoding each element of the stack map table, we look
-                     * for 3 consecutive bytes that "look like" an UNINITIALIZED
-                     * type (tag 8, offset within code bounds, NEW instruction
-                     * at this offset). We may find false positives (i.e. not
-                     * real UNINITIALIZED types), but this should be rare, and
-                     * the only consequence will be the creation of an unneeded
-                     * label. This is better than creating a label for each NEW
-                     * instruction, and faster than fully decoding the whole
-                     * stack map table.
-                     */
-                    for (j = stackMap; j < stackMap + stackMapSize - 2; ++j) {
-                        if (b[j] == 8) { // UNINITIALIZED FRAME TYPE
-                            k = readUnsignedShort(j + 1);
-                            if (k >= 0 && k < codeLength) { // potential offset
-                                if ((b[codeStart + k] & 0xFF) == Opcodes.NEW) { // NEW at this offset
-                                    readLabel(k, labels);
-                                }
-                            }
+                }
+            } else if (ANNOTATIONS
+                    && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+                tanns = readTypeAnnotations(mv, context, u + 8, true);
+                ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1
+                        : readUnsignedShort(tanns[0] + 1);
+            } else if (ANNOTATIONS
+                    && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+                itanns = readTypeAnnotations(mv, context, u + 8, false);
+                nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1
+                        : readUnsignedShort(itanns[0] + 1);
+            } else if (FRAMES && "StackMapTable".equals(attrName)) {
+                if ((context.flags & SKIP_FRAMES) == 0) {
+                    stackMap = u + 10;
+                    stackMapSize = readInt(u + 4);
+                    frameCount = readUnsignedShort(u + 8);
+                }
+                /*
+                 * here we do not extract the labels corresponding to the
+                 * attribute content. This would require a full parsing of the
+                 * attribute, which would need to be repeated in the second
+                 * phase (see below). Instead the content of the attribute is
+                 * read one frame at a time (i.e. after a frame has been
+                 * visited, the next frame is read), and the labels it contains
+                 * are also extracted one frame at a time. Thanks to the
+                 * ordering of frames, having only a "one frame lookahead" is
+                 * not a problem, i.e. it is not possible to see an offset
+                 * smaller than the offset of the current insn and for which no
+                 * Label exist.
+                 */
+                /*
+                 * This is not true for UNINITIALIZED type offsets. We solve
+                 * this by parsing the stack map table without a full decoding
+                 * (see below).
+                 */
+            } else if (FRAMES && "StackMap".equals(attrName)) {
+                if ((context.flags & SKIP_FRAMES) == 0) {
+                    zip = false;
+                    stackMap = u + 10;
+                    stackMapSize = readInt(u + 4);
+                    frameCount = readUnsignedShort(u + 8);
+                }
+                /*
+                 * IMPORTANT! here we assume that the frames are ordered, as in
+                 * the StackMapTable attribute, although this is not guaranteed
+                 * by the attribute format.
+                 */
+            } else {
+                for (int j = 0; j < context.attrs.length; ++j) {
+                    if (context.attrs[j].type.equals(attrName)) {
+                        Attribute attr = context.attrs[j].read(this, u + 8,
+                                readInt(u + 4), c, codeStart - 8, labels);
+                        if (attr != null) {
+                            attr.next = attributes;
+                            attributes = attr;
                         }
                     }
                 }
-                v = codeStart;
-                Label l;
-                while (v < codeEnd) {
-                    w = v - codeStart;
-
-                    l = labels[w];
-                    if (l != null) {
-                        mv.visitLabel(l);
-                        if (!skipDebug && l.line > 0) {
-                            mv.visitLineNumber(l.line, l);
+            }
+            u += 6 + readInt(u + 4);
+        }
+        u += 2;
+
+        // generates the first (implicit) stack map frame
+        if (FRAMES && stackMap != 0) {
+            /*
+             * for the first explicit frame the offset is not offset_delta + 1
+             * but only offset_delta; setting the implicit frame offset to -1
+             * allow the use of the "offset_delta + 1" rule in all cases
+             */
+            frame = context;
+            frame.offset = -1;
+            frame.mode = 0;
+            frame.localCount = 0;
+            frame.localDiff = 0;
+            frame.stackCount = 0;
+            frame.local = new Object[maxLocals];
+            frame.stack = new Object[maxStack];
+            if (unzip) {
+                getImplicitFrame(context);
+            }
+            /*
+             * Finds labels for UNINITIALIZED frame types. Instead of decoding
+             * each element of the stack map table, we look for 3 consecutive
+             * bytes that "look like" an UNINITIALIZED type (tag 8, offset
+             * within code bounds, NEW instruction at this offset). We may find
+             * false positives (i.e. not real UNINITIALIZED types), but this
+             * should be rare, and the only consequence will be the creation of
+             * an unneeded label. This is better than creating a label for each
+             * NEW instruction, and faster than fully decoding the whole stack
+             * map table.
+             */
+            for (int i = stackMap; i < stackMap + stackMapSize - 2; ++i) {
+                if (b[i] == 8) { // UNINITIALIZED FRAME TYPE
+                    int v = readUnsignedShort(i + 1);
+                    if (v >= 0 && v < codeLength) {
+                        if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) {
+                            readLabel(v, labels);
                         }
                     }
+                }
+            }
+        }
 
-                    while (FRAMES && frameLocal != null
-                            && (frameOffset == w || frameOffset == -1))
-                    {
-                        // if there is a frame for this offset,
-                        // makes the visitor visit it,
-                        // and reads the next frame if there is one.
-                        if (!zip || unzip) {
-                            mv.visitFrame(Opcodes.F_NEW,
-                                    frameLocalCount,
-                                    frameLocal,
-                                    frameStackCount,
-                                    frameStack);
-                        } else if (frameOffset != -1) {
-                            mv.visitFrame(frameMode,
-                                    frameLocalDiff,
-                                    frameLocal,
-                                    frameStackCount,
-                                    frameStack);
-                        }
+        // visits the instructions
+        u = codeStart;
+        while (u < codeEnd) {
+            int offset = u - codeStart;
+
+            // visits the label and line number for this offset, if any
+            Label l = labels[offset];
+            if (l != null) {
+                mv.visitLabel(l);
+                if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) {
+                    mv.visitLineNumber(l.line, l);
+                }
+            }
 
-                        if (frameCount > 0) {
-                            int tag, delta, n;
-                            if (zip) {
-                                tag = b[stackMap++] & 0xFF;
-                            } else {
-                                tag = MethodWriter.FULL_FRAME;
-                                frameOffset = -1;
-                            }
-                            frameLocalDiff = 0;
-                            if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME)
-                            {
-                                delta = tag;
-                                frameMode = Opcodes.F_SAME;
-                                frameStackCount = 0;
-                            } else if (tag < MethodWriter.RESERVED) {
-                                delta = tag
-                                        - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME;
-                                stackMap = readFrameType(frameStack,
-                                        0,
-                                        stackMap,
-                                        c,
-                                        labels);
-                                frameMode = Opcodes.F_SAME1;
-                                frameStackCount = 1;
-                            } else {
-                                delta = readUnsignedShort(stackMap);
-                                stackMap += 2;
-                                if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
-                                {
-                                    stackMap = readFrameType(frameStack,
-                                            0,
-                                            stackMap,
-                                            c,
-                                            labels);
-                                    frameMode = Opcodes.F_SAME1;
-                                    frameStackCount = 1;
-                                } else if (tag >= MethodWriter.CHOP_FRAME
-                                        && tag < MethodWriter.SAME_FRAME_EXTENDED)
-                                {
-                                    frameMode = Opcodes.F_CHOP;
-                                    frameLocalDiff = MethodWriter.SAME_FRAME_EXTENDED
-                                            - tag;
-                                    frameLocalCount -= frameLocalDiff;
-                                    frameStackCount = 0;
-                                } else if (tag == MethodWriter.SAME_FRAME_EXTENDED)
-                                {
-                                    frameMode = Opcodes.F_SAME;
-                                    frameStackCount = 0;
-                                } else if (tag < MethodWriter.FULL_FRAME) {
-                                    j = unzip ? 

<TRUNCATED>

[23/23] git commit: 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?"

Posted by ka...@apache.org.
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?"

Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/a0ac605d
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/a0ac605d
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/a0ac605d

Branch: refs/heads/5.3
Commit: a0ac605dbd89f543b0396d747f5909e1ba38205b
Parents: 1a03c56
Author: kaosko <ka...@apache.org>
Authored: Tue Mar 25 11:29:43 2014 -0700
Committer: kaosko <ka...@apache.org>
Committed: Tue Mar 25 11:29:43 2014 -0700

----------------------------------------------------------------------
 plastic/LICENSE-ASM-3_3_1.txt                   |   29 -
 plastic/LICENSE-ASM-5_0.txt                     |   29 +
 plastic/NOTICE.txt                              |    4 +-
 .../internal/plastic/asm/AnnotationVisitor.java |   82 +-
 .../internal/plastic/asm/AnnotationWriter.java  |  123 +-
 .../internal/plastic/asm/Attribute.java         |  213 +-
 .../internal/plastic/asm/ByteVector.java        |  168 +-
 .../internal/plastic/asm/ClassReader.java       | 3350 ++++++++++--------
 .../internal/plastic/asm/ClassVisitor.java      |  291 +-
 .../internal/plastic/asm/ClassWriter.java       |  694 ++--
 .../tapestry5/internal/plastic/asm/Context.java |  145 +
 .../tapestry5/internal/plastic/asm/Edge.java    |    2 +-
 .../internal/plastic/asm/FieldVisitor.java      |   75 +-
 .../internal/plastic/asm/FieldWriter.java       |  138 +-
 .../tapestry5/internal/plastic/asm/Frame.java   | 1087 +++---
 .../tapestry5/internal/plastic/asm/Handle.java  |   65 +-
 .../tapestry5/internal/plastic/asm/Handler.java |   13 +-
 .../tapestry5/internal/plastic/asm/Item.java    |  188 +-
 .../tapestry5/internal/plastic/asm/Label.java   |  169 +-
 .../internal/plastic/asm/MethodVisitor.java     |  808 +++--
 .../internal/plastic/asm/MethodWriter.java      | 1535 ++++----
 .../tapestry5/internal/plastic/asm/Opcodes.java |    9 +-
 .../tapestry5/internal/plastic/asm/Type.java    |  333 +-
 .../internal/plastic/asm/TypePath.java          |  193 +
 .../internal/plastic/asm/TypeReference.java     |  452 +++
 .../plastic/asm/commons/AdviceAdapter.java      |  646 ++++
 .../plastic/asm/commons/AnalyzerAdapter.java    |  947 +++++
 .../plastic/asm/commons/CodeSizeEvaluator.java  |  238 ++
 .../plastic/asm/commons/GeneratorAdapter.java   | 1628 +++++++++
 .../plastic/asm/commons/InstructionAdapter.java | 1170 ++++++
 .../plastic/asm/commons/JSRInlinerAdapter.java  |  333 +-
 .../asm/commons/LocalVariablesSorter.java       |  381 ++
 .../internal/plastic/asm/commons/Method.java    |  282 ++
 .../internal/plastic/asm/commons/Remapper.java  |  223 ++
 .../asm/commons/RemappingAnnotationAdapter.java |   79 +
 .../asm/commons/RemappingClassAdapter.java      |  135 +
 .../asm/commons/RemappingFieldAdapter.java      |   71 +
 .../asm/commons/RemappingMethodAdapter.java     |  224 ++
 .../asm/commons/RemappingSignatureAdapter.java  |  155 +
 .../asm/commons/SerialVersionUIDAdder.java      |  540 +++
 .../plastic/asm/commons/SimpleRemapper.java     |   69 +
 .../plastic/asm/commons/StaticInitMerger.java   |   97 +
 .../asm/commons/TableSwitchGenerator.java       |   57 +
 .../asm/commons/TryCatchBlockSorter.java        |   96 +
 .../internal/plastic/asm/commons/package.html   |   48 +
 .../optimizer/AnnotationConstantsCollector.java |  147 +
 .../asm/optimizer/ClassConstantsCollector.java  |  198 ++
 .../plastic/asm/optimizer/ClassOptimizer.java   |  260 ++
 .../plastic/asm/optimizer/Constant.java         |  323 ++
 .../plastic/asm/optimizer/ConstantPool.java     |  249 ++
 .../asm/optimizer/FieldConstantsCollector.java  |   89 +
 .../plastic/asm/optimizer/JarOptimizer.java     |  235 ++
 .../asm/optimizer/MethodConstantsCollector.java |  224 ++
 .../plastic/asm/optimizer/MethodOptimizer.java  |  136 +
 .../plastic/asm/optimizer/NameMapping.java      |  114 +
 .../plastic/asm/optimizer/Shrinker.java         |  283 ++
 .../plastic/asm/optimizer/jdk1.2.2_017.txt.gz   |  Bin 0 -> 113814 bytes
 .../plastic/asm/optimizer/jdk1.3.1_19.txt.gz    |  Bin 0 -> 128067 bytes
 .../asm/optimizer/shrink-annotations.properties |   53 +
 .../asm/optimizer/shrink-frames.properties      |   62 +
 .../asm/optimizer/shrink-resize.properties      |   37 +
 .../asm/optimizer/shrink-signatures.properties  |   43 +
 .../asm/optimizer/shrink-writer.properties      |   66 +
 .../plastic/asm/optimizer/shrink.properties     |  380 ++
 .../plastic/asm/signature/SignatureReader.java  |  191 +-
 .../plastic/asm/signature/SignatureVisitor.java |   88 +-
 .../plastic/asm/signature/SignatureWriter.java  |    6 +-
 .../plastic/asm/tree/AbstractInsnNode.java      |  132 +-
 .../plastic/asm/tree/AnnotationNode.java        |   72 +-
 .../internal/plastic/asm/tree/ClassNode.java    |  199 +-
 .../plastic/asm/tree/FieldInsnNode.java         |   48 +-
 .../internal/plastic/asm/tree/FieldNode.java    |  198 +-
 .../internal/plastic/asm/tree/FrameNode.java    |  141 +-
 .../internal/plastic/asm/tree/IincInsnNode.java |   17 +-
 .../plastic/asm/tree/InnerClassNode.java        |   46 +-
 .../internal/plastic/asm/tree/InsnList.java     |  184 +-
 .../internal/plastic/asm/tree/InsnNode.java     |   46 +-
 .../internal/plastic/asm/tree/IntInsnNode.java  |   26 +-
 .../plastic/asm/tree/InvokeDynamicInsnNode.java |   32 +-
 .../internal/plastic/asm/tree/JumpInsnNode.java |   39 +-
 .../internal/plastic/asm/tree/LabelNode.java    |    4 +-
 .../internal/plastic/asm/tree/LdcInsnNode.java  |   18 +-
 .../plastic/asm/tree/LineNumberNode.java        |   16 +-
 .../asm/tree/LocalVariableAnnotationNode.java   |  157 +
 .../plastic/asm/tree/LocalVariableNode.java     |   51 +-
 .../plastic/asm/tree/LookupSwitchInsnNode.java  |   36 +-
 .../plastic/asm/tree/MethodInsnNode.java        |   77 +-
 .../internal/plastic/asm/tree/MethodNode.java   |  542 ++-
 .../asm/tree/MultiANewArrayInsnNode.java        |   17 +-
 .../plastic/asm/tree/ParameterNode.java         |   76 +
 .../plastic/asm/tree/TableSwitchInsnNode.java   |   41 +-
 .../plastic/asm/tree/TryCatchBlockNode.java     |   97 +-
 .../plastic/asm/tree/TypeAnnotationNode.java    |  100 +
 .../internal/plastic/asm/tree/TypeInsnNode.java |   28 +-
 .../internal/plastic/asm/tree/VarInsnNode.java  |   34 +-
 .../plastic/asm/tree/analysis/Analyzer.java     |  549 +++
 .../asm/tree/analysis/AnalyzerException.java    |   61 +
 .../asm/tree/analysis/BasicInterpreter.java     |  358 ++
 .../plastic/asm/tree/analysis/BasicValue.java   |  111 +
 .../asm/tree/analysis/BasicVerifier.java        |  433 +++
 .../plastic/asm/tree/analysis/Frame.java        |  738 ++++
 .../plastic/asm/tree/analysis/Interpreter.java  |  226 ++
 .../asm/tree/analysis/SimpleVerifier.java       |  320 ++
 .../plastic/asm/tree/analysis/SmallSet.java     |  134 +
 .../asm/tree/analysis/SourceInterpreter.java    |  198 ++
 .../plastic/asm/tree/analysis/SourceValue.java  |   97 +
 .../plastic/asm/tree/analysis/Subroutine.java   |   90 +
 .../plastic/asm/tree/analysis/Value.java        |   45 +
 .../plastic/asm/tree/analysis/package.html      |   67 +
 .../internal/plastic/asm/util/ASMifiable.java   |   19 +-
 .../internal/plastic/asm/util/ASMifier.java     | 1285 +++++++
 .../asm/util/CheckAnnotationAdapter.java        |  136 +
 .../plastic/asm/util/CheckClassAdapter.java     | 1009 ++++++
 .../plastic/asm/util/CheckFieldAdapter.java     |  122 +
 .../plastic/asm/util/CheckMethodAdapter.java    | 1542 ++++++++
 .../plastic/asm/util/CheckSignatureAdapter.java |  330 ++
 .../internal/plastic/asm/util/Printer.java      |  421 ++-
 .../internal/plastic/asm/util/Textifiable.java  |   16 +-
 .../internal/plastic/asm/util/Textifier.java    |  732 ++--
 .../asm/util/TraceAnnotationVisitor.java        |   32 +-
 .../plastic/asm/util/TraceClassVisitor.java     |  158 +-
 .../plastic/asm/util/TraceFieldVisitor.java     |   27 +-
 .../plastic/asm/util/TraceMethodVisitor.java    |  172 +-
 .../plastic/asm/util/TraceSignatureVisitor.java |   70 +-
 .../plastic/asm/xml/ASMContentHandler.java      | 1453 ++++++++
 .../internal/plastic/asm/xml/Processor.java     | 1044 ++++++
 .../internal/plastic/asm/xml/SAXAdapter.java    |   89 +
 .../plastic/asm/xml/SAXAnnotationAdapter.java   |  242 ++
 .../plastic/asm/xml/SAXClassAdapter.java        |  335 ++
 .../plastic/asm/xml/SAXCodeAdapter.java         |  415 +++
 .../plastic/asm/xml/SAXFieldAdapter.java        |   71 +
 .../internal/plastic/asm/xml/asm-xml.dtd        |  349 ++
 .../internal/plastic/asm/xml/package.html       |   96 +
 133 files changed, 31009 insertions(+), 5855 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/LICENSE-ASM-3_3_1.txt
----------------------------------------------------------------------
diff --git a/plastic/LICENSE-ASM-3_3_1.txt b/plastic/LICENSE-ASM-3_3_1.txt
deleted file mode 100644
index c5aba7b..0000000
--- a/plastic/LICENSE-ASM-3_3_1.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-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.

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/LICENSE-ASM-5_0.txt
----------------------------------------------------------------------
diff --git a/plastic/LICENSE-ASM-5_0.txt b/plastic/LICENSE-ASM-5_0.txt
new file mode 100644
index 0000000..c5aba7b
--- /dev/null
+++ b/plastic/LICENSE-ASM-5_0.txt
@@ -0,0 +1,29 @@
+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.

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/NOTICE.txt
----------------------------------------------------------------------
diff --git a/plastic/NOTICE.txt b/plastic/NOTICE.txt
index 96158f5..beec8e0 100644
--- a/plastic/NOTICE.txt
+++ b/plastic/NOTICE.txt
@@ -1,6 +1,6 @@
 This product includes software developed by
 The Apache Software Foundation (http://www.apache.org/).
 
-This product imports and repackages ASM 3.3.1 code which is
-released under the BSD License
+This product imports and repackages ASM 5.0.1 code which is
+released under a BSD style License
 http://asm.ow2.org/license.html

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
index 693b355..1102d54 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
@@ -33,7 +33,7 @@ package org.apache.tapestry5.internal.plastic.asm;
  * A visitor to visit a Java annotation. The methods of this class must be
  * called in the following order: ( <tt>visit</tt> | <tt>visitEnum</tt> |
  * <tt>visitAnnotation</tt> | <tt>visitArray</tt> )* <tt>visitEnd</tt>.
- *
+ * 
  * @author Eric Bruneton
  * @author Eugene Kuleshov
  */
@@ -41,7 +41,7 @@ public abstract class AnnotationVisitor {
 
     /**
      * The ASM API version implemented by this visitor. The value of this field
-     * must be one of {@link Opcodes#ASM4}.
+     * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
      */
     protected final int api;
 
@@ -53,9 +53,10 @@ public abstract class AnnotationVisitor {
 
     /**
      * Constructs a new {@link AnnotationVisitor}.
-     *
-     * @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 AnnotationVisitor(final int api) {
         this(api, null);
@@ -63,31 +64,36 @@ public abstract class AnnotationVisitor {
 
     /**
      * Constructs a new {@link AnnotationVisitor}.
-     *
-     * @param api the ASM API version implemented by this visitor. Must be one
-     *        of {@link Opcodes#ASM4}.
-     * @param av the annotation visitor to which this visitor must delegate
-     *        method calls. May be null.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param av
+     *            the annotation visitor to which this visitor must delegate
+     *            method calls. May be null.
      */
     public AnnotationVisitor(final int api, final AnnotationVisitor av) {
-        /*if (api != Opcodes.ASM4) {
+        if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
             throw new IllegalArgumentException();
-        }*/
+        }
         this.api = api;
         this.av = av;
     }
 
     /**
      * Visits a primitive value of the annotation.
-     *
-     * @param name the value name.
-     * @param value the actual value, whose type must be {@link Byte},
-     *        {@link Boolean}, {@link Character}, {@link Short}, {@link Integer}
-     *        , {@link Long}, {@link Float}, {@link Double}, {@link String} or
-     *        {@link Type} or OBJECT or ARRAY sort. This value can also be an
-     *        array of byte, boolean, short, char, int, long, float or double
-     *        values (this is equivalent to using {@link #visitArray visitArray}
-     *        and visiting each array element in turn, but is more convenient).
+     * 
+     * @param name
+     *            the value name.
+     * @param value
+     *            the actual value, whose type must be {@link Byte},
+     *            {@link Boolean}, {@link Character}, {@link Short},
+     *            {@link Integer} , {@link Long}, {@link Float}, {@link Double},
+     *            {@link String} or {@link Type} or OBJECT or ARRAY sort. This
+     *            value can also be an array of byte, boolean, short, char, int,
+     *            long, float or double values (this is equivalent to using
+     *            {@link #visitArray visitArray} and visiting each array element
+     *            in turn, but is more convenient).
      */
     public void visit(String name, Object value) {
         if (av != null) {
@@ -97,10 +103,13 @@ public abstract class AnnotationVisitor {
 
     /**
      * Visits an enumeration value of the annotation.
-     *
-     * @param name the value name.
-     * @param desc the class descriptor of the enumeration class.
-     * @param value the actual enumeration value.
+     * 
+     * @param name
+     *            the value name.
+     * @param desc
+     *            the class descriptor of the enumeration class.
+     * @param value
+     *            the actual enumeration value.
      */
     public void visitEnum(String name, String desc, String value) {
         if (av != null) {
@@ -110,13 +119,15 @@ public abstract class AnnotationVisitor {
 
     /**
      * Visits a nested annotation value of the annotation.
-     *
-     * @param name the value name.
-     * @param desc the class descriptor of the nested annotation class.
+     * 
+     * @param name
+     *            the value name.
+     * @param desc
+     *            the class descriptor of the nested annotation class.
      * @return a visitor to visit the actual nested annotation value, or
-     *         <tt>null</tt> if this visitor is not interested in visiting
-     *         this nested annotation. <i>The nested annotation value must be
-     *         fully visited before calling other methods on this annotation
+     *         <tt>null</tt> if this visitor is not interested in visiting this
+     *         nested annotation. <i>The nested annotation value must be fully
+     *         visited before calling other methods on this annotation
      *         visitor</i>.
      */
     public AnnotationVisitor visitAnnotation(String name, String desc) {
@@ -131,11 +142,12 @@ public abstract class AnnotationVisitor {
      * types (such as byte, boolean, short, char, int, long, float or double)
      * can be passed as value to {@link #visit visit}. This is what
      * {@link ClassReader} does.
-     *
-     * @param name the value name.
+     * 
+     * @param name
+     *            the value name.
      * @return a visitor to visit the actual array value elements, or
-     *         <tt>null</tt> if this visitor is not interested in visiting
-     *         these values. The 'name' parameters passed to the methods of this
+     *         <tt>null</tt> if this visitor is not interested in visiting these
+     *         values. The 'name' parameters passed to the methods of this
      *         visitor are ignored. <i>All the array values must be visited
      *         before calling other methods on this annotation visitor</i>.
      */

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
index a26f5ca..679aa66 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
 
 /**
  * An {@link AnnotationVisitor} that generates annotations in bytecode form.
- *
+ * 
  * @author Eric Bruneton
  * @author Eugene Kuleshov
  */
@@ -89,22 +89,22 @@ final class AnnotationWriter extends AnnotationVisitor {
 
     /**
      * Constructs a new {@link AnnotationWriter}.
-     *
-     * @param cw the class writer to which this annotation must be added.
-     * @param named <tt>true<tt> if values are named, <tt>false</tt> otherwise.
-     * @param bv where the annotation values must be stored.
-     * @param parent where the number of annotation values must be stored.
-     * @param offset where in <tt>parent</tt> the number of annotation values must
-     *      be stored.
+     * 
+     * @param cw
+     *            the class writer to which this annotation must be added.
+     * @param named
+     *            <tt>true<tt> if values are named, <tt>false</tt> otherwise.
+     * @param bv
+     *            where the annotation values must be stored.
+     * @param parent
+     *            where the number of annotation values must be stored.
+     * @param offset
+     *            where in <tt>parent</tt> the number of annotation values must
+     *            be stored.
      */
-    AnnotationWriter(
-        final ClassWriter cw,
-        final boolean named,
-        final ByteVector bv,
-        final ByteVector parent,
-        final int offset)
-    {
-        super(Opcodes.ASM4);
+    AnnotationWriter(final ClassWriter cw, final boolean named,
+            final ByteVector bv, final ByteVector parent, final int offset) {
+        super(Opcodes.ASM5);
         this.cw = cw;
         this.named = named;
         this.bv = bv;
@@ -190,11 +190,8 @@ final class AnnotationWriter extends AnnotationVisitor {
     }
 
     @Override
-    public void visitEnum(
-        final String name,
-        final String desc,
-        final String value)
-    {
+    public void visitEnum(final String name, final String desc,
+            final String value) {
         ++size;
         if (named) {
             bv.putShort(cw.newUTF8(name));
@@ -203,10 +200,8 @@ final class AnnotationWriter extends AnnotationVisitor {
     }
 
     @Override
-    public AnnotationVisitor visitAnnotation(
-        final String name,
-        final String desc)
-    {
+    public AnnotationVisitor visitAnnotation(final String name,
+            final String desc) {
         ++size;
         if (named) {
             bv.putShort(cw.newUTF8(name));
@@ -242,7 +237,7 @@ final class AnnotationWriter extends AnnotationVisitor {
 
     /**
      * Returns the size of this annotation writer list.
-     *
+     * 
      * @return the size of this annotation writer list.
      */
     int getSize() {
@@ -258,8 +253,9 @@ final class AnnotationWriter extends AnnotationVisitor {
     /**
      * Puts the annotations of this annotation writer list into the given byte
      * vector.
-     *
-     * @param out where the annotations must be put.
+     * 
+     * @param out
+     *            where the annotations must be put.
      */
     void put(final ByteVector out) {
         int n = 0;
@@ -285,16 +281,16 @@ final class AnnotationWriter extends AnnotationVisitor {
 
     /**
      * Puts the given annotation lists into the given byte vector.
-     *
-     * @param panns an array of annotation writer lists.
-     * @param off index of the first annotation to be written.
-     * @param out where the annotations must be put.
+     * 
+     * @param panns
+     *            an array of annotation writer lists.
+     * @param off
+     *            index of the first annotation to be written.
+     * @param out
+     *            where the annotations must be put.
      */
-    static void put(
-        final AnnotationWriter[] panns,
-        final int off,
-        final ByteVector out)
-    {
+    static void put(final AnnotationWriter[] panns, final int off,
+            final ByteVector out) {
         int size = 1 + 2 * (panns.length - off);
         for (int i = off; i < panns.length; ++i) {
             size += panns[i] == null ? 0 : panns[i].getSize();
@@ -319,4 +315,57 @@ final class AnnotationWriter extends AnnotationVisitor {
             }
         }
     }
+
+    /**
+     * Puts the given type reference and type path into the given bytevector.
+     * LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported.
+     * 
+     * @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 out
+     *            where the type reference and type path must be put.
+     */
+    static void putTarget(int typeRef, TypePath typePath, ByteVector out) {
+        switch (typeRef >>> 24) {
+        case 0x00: // CLASS_TYPE_PARAMETER
+        case 0x01: // METHOD_TYPE_PARAMETER
+        case 0x16: // METHOD_FORMAL_PARAMETER
+            out.putShort(typeRef >>> 16);
+            break;
+        case 0x13: // FIELD
+        case 0x14: // METHOD_RETURN
+        case 0x15: // METHOD_RECEIVER
+            out.putByte(typeRef >>> 24);
+            break;
+        case 0x47: // CAST
+        case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+        case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
+        case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+        case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
+            out.putInt(typeRef);
+            break;
+        // case 0x10: // CLASS_EXTENDS
+        // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
+        // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
+        // case 0x17: // THROWS
+        // case 0x42: // EXCEPTION_PARAMETER
+        // case 0x43: // INSTANCEOF
+        // case 0x44: // NEW
+        // case 0x45: // CONSTRUCTOR_REFERENCE
+        // case 0x46: // METHOD_REFERENCE
+        default:
+            out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8);
+            break;
+        }
+        if (typePath == null) {
+            out.putByte(0);
+        } else {
+            int length = typePath.b[typePath.offset] * 2 + 1;
+            out.putByteArray(typePath.b, typePath.offset, length);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
index 8f29872..fae580f 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
 
 /**
  * A non standard class, field, method or code attribute.
- *
+ * 
  * @author Eric Bruneton
  * @author Eugene Kuleshov
  */
@@ -54,8 +54,9 @@ public class Attribute {
 
     /**
      * Constructs a new empty attribute.
-     *
-     * @param type the type of the attribute.
+     * 
+     * @param type
+     *            the type of the attribute.
      */
     protected Attribute(final String type) {
         this.type = type;
@@ -64,7 +65,7 @@ public class Attribute {
     /**
      * Returns <tt>true</tt> if this type of attribute is unknown. The default
      * implementation of this method always returns <tt>true</tt>.
-     *
+     * 
      * @return <tt>true</tt> if this type of attribute is unknown.
      */
     public boolean isUnknown() {
@@ -73,7 +74,7 @@ public class Attribute {
 
     /**
      * Returns <tt>true</tt> if this type of attribute is a code attribute.
-     *
+     * 
      * @return <tt>true</tt> if this type of attribute is a code attribute.
      */
     public boolean isCodeAttribute() {
@@ -82,7 +83,7 @@ public class Attribute {
 
     /**
      * Returns the labels corresponding to this attribute.
-     *
+     * 
      * @return the labels corresponding to this attribute, or <tt>null</tt> if
      *         this attribute is not a code attribute that contains labels.
      */
@@ -91,39 +92,39 @@ public class Attribute {
     }
 
     /**
-     * Reads a {@link #type type} attribute. This method must return a <i>new</i>
-     * {@link Attribute} object, of type {@link #type type}, corresponding to
-     * the <tt>len</tt> bytes starting at the given offset, in the given class
-     * reader.
-     *
-     * @param cr the class that contains the attribute to be read.
-     * @param off index of the first byte of the attribute's content in {@link
-     *        ClassReader#b cr.b}. The 6 attribute header bytes, containing the
-     *        type and the length of the attribute, are not taken into account
-     *        here.
-     * @param len the length of the attribute's content.
-     * @param buf buffer to be used to call
-     *        {@link ClassReader#readUTF8 readUTF8},
-     *        {@link ClassReader#readClass(int,char[]) readClass} or
-     *        {@link ClassReader#readConst readConst}.
-     * @param codeOff index of the first byte of code's attribute content in
-     *        {@link ClassReader#b cr.b}, or -1 if the attribute to be read is
-     *        not a code attribute. The 6 attribute header bytes, containing the
-     *        type and the length of the attribute, are not taken into account
-     *        here.
-     * @param labels the labels of the method's code, or <tt>null</tt> if the
-     *        attribute to be read is not a code attribute.
+     * Reads a {@link #type type} attribute. This method must return a
+     * <i>new</i> {@link Attribute} object, of type {@link #type type},
+     * corresponding to the <tt>len</tt> bytes starting at the given offset, in
+     * the given class reader.
+     * 
+     * @param cr
+     *            the class that contains the attribute to be read.
+     * @param off
+     *            index of the first byte of the attribute's content in
+     *            {@link ClassReader#b cr.b}. The 6 attribute header bytes,
+     *            containing the type and the length of the attribute, are not
+     *            taken into account here.
+     * @param len
+     *            the length of the attribute's content.
+     * @param buf
+     *            buffer to be used to call {@link ClassReader#readUTF8
+     *            readUTF8}, {@link ClassReader#readClass(int,char[]) readClass}
+     *            or {@link ClassReader#readConst readConst}.
+     * @param codeOff
+     *            index of the first byte of code's attribute content in
+     *            {@link ClassReader#b cr.b}, or -1 if the attribute to be read
+     *            is not a code attribute. The 6 attribute header bytes,
+     *            containing the type and the length of the attribute, are not
+     *            taken into account here.
+     * @param labels
+     *            the labels of the method's code, or <tt>null</tt> if the
+     *            attribute to be read is not a code attribute.
      * @return a <i>new</i> {@link Attribute} object corresponding to the given
      *         bytes.
      */
-    protected Attribute read(
-        final ClassReader cr,
-        final int off,
-        final int len,
-        final char[] buf,
-        final int codeOff,
-        final Label[] labels)
-    {
+    protected Attribute read(final ClassReader cr, final int off,
+            final int len, final char[] buf, final int codeOff,
+            final Label[] labels) {
         Attribute attr = new Attribute(type);
         attr.value = new byte[len];
         System.arraycopy(cr.b, off, attr.value, 0, len);
@@ -132,31 +133,31 @@ public class Attribute {
 
     /**
      * Returns the byte array form of this attribute.
-     *
-     * @param cw the class to which this attribute must be added. This parameter
-     *        can be used to add to the constant pool of this class the items
-     *        that corresponds to this attribute.
-     * @param code the bytecode of the method corresponding to this code
-     *        attribute, or <tt>null</tt> if this attribute is not a code
-     *        attributes.
-     * @param len the length of the bytecode of the method corresponding to this
-     *        code attribute, or <tt>null</tt> if this attribute is not a code
-     *        attribute.
-     * @param maxStack the maximum stack size of the method corresponding to
-     *        this code attribute, or -1 if this attribute is not a code
-     *        attribute.
-     * @param maxLocals the maximum number of local variables of the method
-     *        corresponding to this code attribute, or -1 if this attribute is
-     *        not a code attribute.
+     * 
+     * @param cw
+     *            the class to which this attribute must be added. This
+     *            parameter can be used to add to the constant pool of this
+     *            class the items that corresponds to this attribute.
+     * @param code
+     *            the bytecode of the method corresponding to this code
+     *            attribute, or <tt>null</tt> if this attribute is not a code
+     *            attributes.
+     * @param len
+     *            the length of the bytecode of the method corresponding to this
+     *            code attribute, or <tt>null</tt> if this attribute is not a
+     *            code attribute.
+     * @param maxStack
+     *            the maximum stack size of the method corresponding to this
+     *            code attribute, or -1 if this attribute is not a code
+     *            attribute.
+     * @param maxLocals
+     *            the maximum number of local variables of the method
+     *            corresponding to this code attribute, or -1 if this attribute
+     *            is not a code attribute.
      * @return the byte array form of this attribute.
      */
-    protected ByteVector write(
-        final ClassWriter cw,
-        final byte[] code,
-        final int len,
-        final int maxStack,
-        final int maxLocals)
-    {
+    protected ByteVector write(final ClassWriter cw, final byte[] code,
+            final int len, final int maxStack, final int maxLocals) {
         ByteVector v = new ByteVector();
         v.data = value;
         v.length = value.length;
@@ -165,7 +166,7 @@ public class Attribute {
 
     /**
      * Returns the length of the attribute list that begins with this attribute.
-     *
+     * 
      * @return the length of the attribute list that begins with this attribute.
      */
     final int getCount() {
@@ -180,31 +181,31 @@ public class Attribute {
 
     /**
      * Returns the size of all the attributes in this attribute list.
-     *
-     * @param cw the class writer to be used to convert the attributes into byte
-     *        arrays, with the {@link #write write} method.
-     * @param code the bytecode of the method corresponding to these code
-     *        attributes, or <tt>null</tt> if these attributes are not code
-     *        attributes.
-     * @param len the length of the bytecode of the method corresponding to
-     *        these code attributes, or <tt>null</tt> if these attributes are
-     *        not code attributes.
-     * @param maxStack the maximum stack size of the method corresponding to
-     *        these code attributes, or -1 if these attributes are not code
-     *        attributes.
-     * @param maxLocals the maximum number of local variables of the method
-     *        corresponding to these code attributes, or -1 if these attributes
-     *        are not code attributes.
+     * 
+     * @param cw
+     *            the class writer to be used to convert the attributes into
+     *            byte arrays, with the {@link #write write} method.
+     * @param code
+     *            the bytecode of the method corresponding to these code
+     *            attributes, or <tt>null</tt> if these attributes are not code
+     *            attributes.
+     * @param len
+     *            the length of the bytecode of the method corresponding to
+     *            these code attributes, or <tt>null</tt> if these attributes
+     *            are not code attributes.
+     * @param maxStack
+     *            the maximum stack size of the method corresponding to these
+     *            code attributes, or -1 if these attributes are not code
+     *            attributes.
+     * @param maxLocals
+     *            the maximum number of local variables of the method
+     *            corresponding to these code attributes, or -1 if these
+     *            attributes are not code attributes.
      * @return the size of all the attributes in this attribute list. This size
      *         includes the size of the attribute headers.
      */
-    final int getSize(
-        final ClassWriter cw,
-        final byte[] code,
-        final int len,
-        final int maxStack,
-        final int maxLocals)
-    {
+    final int getSize(final ClassWriter cw, final byte[] code, final int len,
+            final int maxStack, final int maxLocals) {
         Attribute attr = this;
         int size = 0;
         while (attr != null) {
@@ -218,31 +219,31 @@ public class Attribute {
     /**
      * Writes all the attributes of this attribute list in the given byte
      * vector.
-     *
-     * @param cw the class writer to be used to convert the attributes into byte
-     *        arrays, with the {@link #write write} method.
-     * @param code the bytecode of the method corresponding to these code
-     *        attributes, or <tt>null</tt> if these attributes are not code
-     *        attributes.
-     * @param len the length of the bytecode of the method corresponding to
-     *        these code attributes, or <tt>null</tt> if these attributes are
-     *        not code attributes.
-     * @param maxStack the maximum stack size of the method corresponding to
-     *        these code attributes, or -1 if these attributes are not code
-     *        attributes.
-     * @param maxLocals the maximum number of local variables of the method
-     *        corresponding to these code attributes, or -1 if these attributes
-     *        are not code attributes.
-     * @param out where the attributes must be written.
+     * 
+     * @param cw
+     *            the class writer to be used to convert the attributes into
+     *            byte arrays, with the {@link #write write} method.
+     * @param code
+     *            the bytecode of the method corresponding to these code
+     *            attributes, or <tt>null</tt> if these attributes are not code
+     *            attributes.
+     * @param len
+     *            the length of the bytecode of the method corresponding to
+     *            these code attributes, or <tt>null</tt> if these attributes
+     *            are not code attributes.
+     * @param maxStack
+     *            the maximum stack size of the method corresponding to these
+     *            code attributes, or -1 if these attributes are not code
+     *            attributes.
+     * @param maxLocals
+     *            the maximum number of local variables of the method
+     *            corresponding to these code attributes, or -1 if these
+     *            attributes are not code attributes.
+     * @param out
+     *            where the attributes must be written.
      */
-    final void put(
-        final ClassWriter cw,
-        final byte[] code,
-        final int len,
-        final int maxStack,
-        final int maxLocals,
-        final ByteVector out)
-    {
+    final void put(final ClassWriter cw, final byte[] code, final int len,
+            final int maxStack, final int maxLocals, final ByteVector out) {
         Attribute attr = this;
         while (attr != null) {
             ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
index e689d87..24506f9 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
@@ -32,7 +32,7 @@ package org.apache.tapestry5.internal.plastic.asm;
 /**
  * A dynamically extensible vector of bytes. This class is roughly equivalent to
  * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
- *
+ * 
  * @author Eric Bruneton
  */
 public class ByteVector {
@@ -58,8 +58,9 @@ public class ByteVector {
     /**
      * Constructs a new {@link ByteVector ByteVector} with the given initial
      * size.
-     *
-     * @param initialSize the initial size of the byte vector to be constructed.
+     * 
+     * @param initialSize
+     *            the initial size of the byte vector to be constructed.
      */
     public ByteVector(final int initialSize) {
         data = new byte[initialSize];
@@ -68,8 +69,9 @@ public class ByteVector {
     /**
      * Puts a byte into this byte vector. The byte vector is automatically
      * enlarged if necessary.
-     *
-     * @param b a byte.
+     * 
+     * @param b
+     *            a byte.
      * @return this byte vector.
      */
     public ByteVector putByte(final int b) {
@@ -85,9 +87,11 @@ public class ByteVector {
     /**
      * Puts two bytes into this byte vector. The byte vector is automatically
      * enlarged if necessary.
-     *
-     * @param b1 a byte.
-     * @param b2 another byte.
+     * 
+     * @param b1
+     *            a byte.
+     * @param b2
+     *            another byte.
      * @return this byte vector.
      */
     ByteVector put11(final int b1, final int b2) {
@@ -105,8 +109,9 @@ public class ByteVector {
     /**
      * Puts a short into this byte vector. The byte vector is automatically
      * enlarged if necessary.
-     *
-     * @param s a short.
+     * 
+     * @param s
+     *            a short.
      * @return this byte vector.
      */
     public ByteVector putShort(final int s) {
@@ -124,9 +129,11 @@ public class ByteVector {
     /**
      * Puts a byte and a short into this byte vector. The byte vector is
      * automatically enlarged if necessary.
-     *
-     * @param b a byte.
-     * @param s a short.
+     * 
+     * @param b
+     *            a byte.
+     * @param s
+     *            a short.
      * @return this byte vector.
      */
     ByteVector put12(final int b, final int s) {
@@ -145,8 +152,9 @@ public class ByteVector {
     /**
      * Puts an int into this byte vector. The byte vector is automatically
      * enlarged if necessary.
-     *
-     * @param i an int.
+     * 
+     * @param i
+     *            an int.
      * @return this byte vector.
      */
     public ByteVector putInt(final int i) {
@@ -166,8 +174,9 @@ public class ByteVector {
     /**
      * Puts a long into this byte vector. The byte vector is automatically
      * enlarged if necessary.
-     *
-     * @param l a long.
+     * 
+     * @param l
+     *            a long.
      * @return this byte vector.
      */
     public ByteVector putLong(final long l) {
@@ -193,12 +202,16 @@ public class ByteVector {
     /**
      * Puts an UTF8 string into this byte vector. The byte vector is
      * automatically enlarged if necessary.
-     *
-     * @param s a String.
+     * 
+     * @param s
+     *            a String whose UTF8 encoded length must be less than 65536.
      * @return this byte vector.
      */
     public ByteVector putUTF8(final String s) {
         int charLength = s.length();
+        if (charLength > 65535) {
+            throw new IllegalArgumentException();
+        }
         int len = length;
         if (len + 2 + charLength > data.length) {
             enlarge(2 + charLength);
@@ -217,38 +230,68 @@ public class ByteVector {
             if (c >= '\001' && c <= '\177') {
                 data[len++] = (byte) c;
             } else {
-                int byteLength = i;
-                for (int j = i; j < charLength; ++j) {
-                    c = s.charAt(j);
-                    if (c >= '\001' && c <= '\177') {
-                        byteLength++;
-                    } else if (c > '\u07FF') {
-                        byteLength += 3;
-                    } else {
-                        byteLength += 2;
-                    }
-                }
-                data[length] = (byte) (byteLength >>> 8);
-                data[length + 1] = (byte) byteLength;
-                if (length + 2 + byteLength > data.length) {
-                    length = len;
-                    enlarge(2 + byteLength);
-                    data = this.data;
-                }
-                for (int j = i; j < charLength; ++j) {
-                    c = s.charAt(j);
-                    if (c >= '\001' && c <= '\177') {
-                        data[len++] = (byte) c;
-                    } else if (c > '\u07FF') {
-                        data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
-                        data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
-                        data[len++] = (byte) (0x80 | c & 0x3F);
-                    } else {
-                        data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
-                        data[len++] = (byte) (0x80 | c & 0x3F);
-                    }
-                }
-                break;
+                length = len;
+                return encodeUTF8(s, i, 65535);
+            }
+        }
+        length = len;
+        return this;
+    }
+
+    /**
+     * Puts an UTF8 string into this byte vector. The byte vector is
+     * automatically enlarged if necessary. The string length is encoded in two
+     * bytes before the encoded characters, if there is space for that (i.e. if
+     * this.length - i - 2 >= 0).
+     * 
+     * @param s
+     *            the String to encode.
+     * @param i
+     *            the index of the first character to encode. The previous
+     *            characters are supposed to have already been encoded, using
+     *            only one byte per character.
+     * @param maxByteLength
+     *            the maximum byte length of the encoded string, including the
+     *            already encoded characters.
+     * @return this byte vector.
+     */
+    ByteVector encodeUTF8(final String s, int i, int maxByteLength) {
+        int charLength = s.length();
+        int byteLength = i;
+        char c;
+        for (int j = i; j < charLength; ++j) {
+            c = s.charAt(j);
+            if (c >= '\001' && c <= '\177') {
+                byteLength++;
+            } else if (c > '\u07FF') {
+                byteLength += 3;
+            } else {
+                byteLength += 2;
+            }
+        }
+        if (byteLength > maxByteLength) {
+            throw new IllegalArgumentException();
+        }
+        int start = length - i - 2;
+        if (start >= 0) {
+          data[start] = (byte) (byteLength >>> 8);
+          data[start + 1] = (byte) byteLength;
+        }
+        if (length + byteLength - i > data.length) {
+            enlarge(byteLength - i);
+        }
+        int len = length;
+        for (int j = i; j < charLength; ++j) {
+            c = s.charAt(j);
+            if (c >= '\001' && c <= '\177') {
+                data[len++] = (byte) c;
+            } else if (c > '\u07FF') {
+                data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
+                data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
+                data[len++] = (byte) (0x80 | c & 0x3F);
+            } else {
+                data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
+                data[len++] = (byte) (0x80 | c & 0x3F);
             }
         }
         length = len;
@@ -258,15 +301,17 @@ public class ByteVector {
     /**
      * Puts an array of bytes into this byte vector. The byte vector is
      * automatically enlarged if necessary.
-     *
-     * @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
-     *        null bytes into this byte vector.
-     * @param off index of the fist byte of b that must be copied.
-     * @param len number of bytes of b that must be copied.
+     * 
+     * @param b
+     *            an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
+     *            null bytes into this byte vector.
+     * @param off
+     *            index of the fist byte of b that must be copied.
+     * @param len
+     *            number of bytes of b that must be copied.
      * @return this byte vector.
      */
-    public ByteVector putByteArray(final byte[] b, final int off, final int len)
-    {
+    public ByteVector putByteArray(final byte[] b, final int off, final int len) {
         if (length + len > data.length) {
             enlarge(len);
         }
@@ -279,9 +324,10 @@ public class ByteVector {
 
     /**
      * Enlarge this byte vector so that it can receive n more bytes.
-     *
-     * @param size number of additional bytes that this byte vector should be
-     *        able to receive.
+     * 
+     * @param size
+     *            number of additional bytes that this byte vector should be
+     *            able to receive.
      */
     private void enlarge(final int size) {
         int length1 = 2 * data.length;


[04/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
index c74a17f..a849298 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
@@ -29,18 +29,19 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.util;
 
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.tapestry5.internal.plastic.asm.Attribute;
 import org.apache.tapestry5.internal.plastic.asm.Handle;
 import org.apache.tapestry5.internal.plastic.asm.Label;
 import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
 
 /**
  * An abstract converter from visit events to text.
- *
+ * 
  * @author Eric Bruneton
  */
 public abstract class Printer {
@@ -103,8 +104,8 @@ public abstract class Printer {
         }
 
         s = "H_GETFIELD,H_GETSTATIC,H_PUTFIELD,H_PUTSTATIC,"
-          + "H_INVOKEVIRTUAL,H_INVOKESTATIC,H_INVOKESPECIAL,"
-          + "H_NEWINVOKESPECIAL,H_INVOKEINTERFACE,";
+                + "H_INVOKEVIRTUAL,H_INVOKESTATIC,H_INVOKESPECIAL,"
+                + "H_NEWINVOKESPECIAL,H_INVOKEINTERFACE,";
         HANDLE_TAG = new String[10];
         j = 0;
         i = 1;
@@ -116,7 +117,7 @@ public abstract class Printer {
 
     /**
      * The ASM API version implemented by this class. The value of this field
-     * must be one of {@link Opcodes#ASM4}.
+     * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
      */
     protected final int api;
 
@@ -149,81 +150,67 @@ public abstract class Printer {
     }
 
     /**
-     * Class header.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visit}.
+     * Class header. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visit}.
      */
-    public abstract void visit(
-        final int version,
-        final int access,
-        final String name,
-        final String signature,
-        final String superName,
-        final String[] interfaces);
+    public abstract void visit(final int version, final int access,
+            final String name, final String signature, final String superName,
+            final String[] interfaces);
 
     /**
-     * Class source.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitSource}.
+     * Class source. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitSource}.
      */
     public abstract void visitSource(final String file, final String debug);
 
     /**
-     * Class outer class.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitOuterClass}.
+     * Class outer class. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitOuterClass}.
      */
-    public abstract void visitOuterClass(
-        final String owner,
-        final String name,
-        final String desc);
+    public abstract void visitOuterClass(final String owner, final String name,
+            final String desc);
 
     /**
-     * Class annotation.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitAnnotation}.
+     * Class annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitAnnotation}.
      */
-    public abstract Printer visitClassAnnotation(
-        final String desc,
-        final boolean visible);
+    public abstract Printer visitClassAnnotation(final String desc,
+            final boolean visible);
 
     /**
-     * Class attribute.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitAttribute}.
+     * Class type annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitTypeAnnotation}.
+     */
+    public Printer visitClassTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        throw new RuntimeException("Must be overriden");
+    }
+
+    /**
+     * Class attribute. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitAttribute}.
      */
     public abstract void visitClassAttribute(final Attribute attr);
 
     /**
-     * Class inner name.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitInnerClass}.
+     * Class inner name. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitInnerClass}.
      */
-    public abstract void visitInnerClass(
-        final String name,
-        final String outerName,
-        final String innerName,
-        final int access);
+    public abstract void visitInnerClass(final String name,
+            final String outerName, final String innerName, final int access);
 
     /**
-     * Class field.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitField}.
+     * Class field. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitField}.
      */
-    public abstract Printer visitField(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final Object value);
+    public abstract Printer visitField(final int access, final String name,
+            final String desc, final String signature, final Object value);
 
     /**
-     * Class method.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitMethod}.
+     * Class method. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitMethod}.
      */
-    public abstract Printer visitMethod(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final String[] exceptions);
+    public abstract Printer visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions);
 
     /**
-     * Class end.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitEnd}.
+     * Class end. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitEnd}.
      */
     public abstract void visitClassEnd();
 
@@ -232,37 +219,31 @@ public abstract class Printer {
     // ------------------------------------------------------------------------
 
     /**
-     * Annotation value.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visit}.
+     * Annotation value. See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visit}.
      */
     public abstract void visit(final String name, final Object value);
 
     /**
-     * Annotation enum value.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitEnum}.
+     * Annotation enum value. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitEnum}.
      */
-    public abstract void visitEnum(
-        final String name,
-        final String desc,
-        final String value);
+    public abstract void visitEnum(final String name, final String desc,
+            final String value);
 
     /**
-     * Nested annotation value.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitAnnotation}.
+     * Nested annotation value. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitAnnotation}.
      */
-    public abstract Printer visitAnnotation(
-        final String name,
-        final String desc);
+    public abstract Printer visitAnnotation(final String name, final String desc);
 
     /**
-     * Annotation array value.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitArray}.
+     * Annotation array value. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitArray}.
      */
     public abstract Printer visitArray(final String name);
 
     /**
-     * Annotation end.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitEnd}.
+     * Annotation end. See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitEnd}.
      */
     public abstract void visitAnnotationEnd();
 
@@ -271,22 +252,29 @@ public abstract class Printer {
     // ------------------------------------------------------------------------
 
     /**
-     * Field annotation.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitAnnotation}.
+     * Field annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitAnnotation}.
+     */
+    public abstract Printer visitFieldAnnotation(final String desc,
+            final boolean visible);
+
+    /**
+     * Field type annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitTypeAnnotation}.
      */
-    public abstract Printer visitFieldAnnotation(
-        final String desc,
-        final boolean visible);
+    public Printer visitFieldTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        throw new RuntimeException("Must be overriden");
+    }
 
     /**
-     * Field attribute.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitAttribute}.
+     * Field attribute. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitAttribute}.
      */
     public abstract void visitFieldAttribute(final Attribute attr);
 
     /**
-     * Field end.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitEnd}.
+     * Field end. See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitEnd}.
      */
     public abstract void visitFieldEnd();
 
@@ -295,199 +283,237 @@ public abstract class Printer {
     // ------------------------------------------------------------------------
 
     /**
-     * Method default annotation.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAnnotationDefault}.
+     * Method parameter. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitParameter(String, int)}.
+     */
+    public void visitParameter(String name, int access) {
+        throw new RuntimeException("Must be overriden");
+    }
+
+    /**
+     * Method default annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAnnotationDefault}.
      */
     public abstract Printer visitAnnotationDefault();
 
     /**
-     * Method annotation.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAnnotation}.
+     * Method annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAnnotation}.
      */
-    public abstract Printer visitMethodAnnotation(
-        final String desc,
-        final boolean visible);
+    public abstract Printer visitMethodAnnotation(final String desc,
+            final boolean visible);
 
     /**
-     * Method parameter annotation.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitParameterAnnotation}.
+     * Method type annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTypeAnnotation}.
      */
-    public abstract Printer visitParameterAnnotation(
-        final int parameter,
-        final String desc,
-        final boolean visible);
+    public Printer visitMethodTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        throw new RuntimeException("Must be overriden");
+    }
 
     /**
-     * Method attribute.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAttribute}.
+     * Method parameter annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitParameterAnnotation}.
+     */
+    public abstract Printer visitParameterAnnotation(final int parameter,
+            final String desc, final boolean visible);
+
+    /**
+     * Method attribute. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAttribute}.
      */
     public abstract void visitMethodAttribute(final Attribute attr);
 
     /**
-     * Method start.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitCode}.
+     * Method start. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitCode}.
      */
     public abstract void visitCode();
 
     /**
-     * Method stack frame.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFrame}.
+     * Method stack frame. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFrame}.
      */
-    public abstract void visitFrame(
-        final int type,
-        final int nLocal,
-        final Object[] local,
-        final int nStack,
-        final Object[] stack);
+    public abstract void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInsn}.
+     * Method instruction. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInsn}
+     * .
      */
     public abstract void visitInsn(final int opcode);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitIntInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitIntInsn}.
      */
     public abstract void visitIntInsn(final int opcode, final int operand);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitVarInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitVarInsn}.
      */
     public abstract void visitVarInsn(final int opcode, final int var);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTypeInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTypeInsn}.
      */
     public abstract void visitTypeInsn(final int opcode, final String type);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFieldInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFieldInsn}.
      */
-    public abstract void visitFieldInsn(
-        final int opcode,
-        final String owner,
-        final String name,
-        final String desc);
+    public abstract void visitFieldInsn(final int opcode, final String owner,
+            final String name, final String desc);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMethodInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMethodInsn}.
      */
-    public abstract void visitMethodInsn(
-        final int opcode,
-        final String owner,
-        final String name,
-        final String desc);
+    @Deprecated
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (api >= Opcodes.ASM5) {
+            boolean itf = opcode == Opcodes.INVOKEINTERFACE;
+            visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
+        throw new RuntimeException("Must be overriden");
+    }
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInvokeDynamicInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMethodInsn}.
      */
-    public abstract void visitInvokeDynamicInsn(
-        String name,
-        String desc,
-        Handle bsm,
-        Object... bsmArgs);
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            if (itf != (opcode == Opcodes.INVOKEINTERFACE)) {
+                throw new IllegalArgumentException(
+                        "INVOKESPECIAL/STATIC on interfaces require ASM 5");
+            }
+            visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        throw new RuntimeException("Must be overriden");
+    }
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitJumpInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInvokeDynamicInsn}.
+     */
+    public abstract void visitInvokeDynamicInsn(String name, String desc,
+            Handle bsm, Object... bsmArgs);
+
+    /**
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitJumpInsn}.
      */
     public abstract void visitJumpInsn(final int opcode, final Label label);
 
     /**
-     * Method label.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLabel}.
+     * Method label. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLabel}.
      */
     public abstract void visitLabel(final Label label);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLdcInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLdcInsn}.
      */
     public abstract void visitLdcInsn(final Object cst);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitIincInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitIincInsn}.
      */
     public abstract void visitIincInsn(final int var, final int increment);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTableSwitchInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTableSwitchInsn}.
+     */
+    public abstract void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels);
+
+    /**
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLookupSwitchInsn}.
      */
-    public abstract void visitTableSwitchInsn(
-        final int min,
-        final int max,
-        final Label dflt,
-        final Label... labels);
+    public abstract void visitLookupSwitchInsn(final Label dflt,
+            final int[] keys, final Label[] labels);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLookupSwitchInsn}.
+     * Method instruction. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMultiANewArrayInsn}.
      */
-    public abstract void visitLookupSwitchInsn(
-        final Label dflt,
-        final int[] keys,
-        final Label[] labels);
+    public abstract void visitMultiANewArrayInsn(final String desc,
+            final int dims);
 
     /**
-     * Method instruction.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMultiANewArrayInsn}.
+     * Instruction type annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInsnAnnotation}.
      */
-    public abstract void visitMultiANewArrayInsn(
-        final String desc,
-        final int dims);
+    public Printer visitInsnAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        throw new RuntimeException("Must be overriden");
+    }
 
     /**
-     * Method exception handler.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTryCatchBlock}.
+     * Method exception handler. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTryCatchBlock}.
      */
-    public abstract void visitTryCatchBlock(
-        final Label start,
-        final Label end,
-        final Label handler,
-        final String type);
+    public abstract void visitTryCatchBlock(final Label start, final Label end,
+            final Label handler, final String type);
 
     /**
-     * Method debug info.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLocalVariable}.
+     * Try catch block type annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTryCatchAnnotation}.
      */
-    public abstract void visitLocalVariable(
-        final String name,
-        final String desc,
-        final String signature,
-        final Label start,
-        final Label end,
-        final int index);
+    public Printer visitTryCatchAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        throw new RuntimeException("Must be overriden");
+    }
+
+    /**
+     * Method debug info. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLocalVariable}.
+     */
+    public abstract void visitLocalVariable(final String name,
+            final String desc, final String signature, final Label start,
+            final Label end, final int index);
+
+    /**
+     * Local variable type annotation. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTryCatchAnnotation}.
+     */
+    public Printer visitLocalVariableAnnotation(final int typeRef,
+            final TypePath typePath, final Label[] start, final Label[] end,
+            final int[] index, final String desc, final boolean visible) {
+        throw new RuntimeException("Must be overriden");
+    }
 
     /**
-     * Method debug info.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLineNumber}.
+     * Method debug info. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLineNumber}.
      */
     public abstract void visitLineNumber(final int line, final Label start);
 
     /**
-     * Method max stack and max locals.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMaxs}.
+     * Method max stack and max locals. See
+     * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMaxs}.
      */
     public abstract void visitMaxs(final int maxStack, final int maxLocals);
 
     /**
-     * Method end.
-     * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitEnd}.
+     * Method end. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitEnd}.
      */
     public abstract void visitMethodEnd();
 
     /**
      * Returns the text constructed by this visitor.
-     *
+     * 
      * @return the text constructed by this visitor.
      */
     public List<Object> getText() {
@@ -496,8 +522,9 @@ public abstract class Printer {
 
     /**
      * Prints the text constructed by this visitor.
-     *
-     * @param pw the print writer to be used.
+     * 
+     * @param pw
+     *            the print writer to be used.
      */
     public void print(final PrintWriter pw) {
         printList(pw, text);
@@ -505,9 +532,11 @@ public abstract class Printer {
 
     /**
      * Appends a quoted string to a given buffer.
-     *
-     * @param buf the buffer where the string must be added.
-     * @param s the string to be added.
+     * 
+     * @param buf
+     *            the buffer where the string must be added.
+     * @param s
+     *            the string to be added.
      */
     public static void appendString(final StringBuffer buf, final String s) {
         buf.append('\"');
@@ -540,10 +569,12 @@ public abstract class Printer {
 
     /**
      * Prints the given string tree.
-     *
-     * @param pw the writer to be used to print the tree.
-     * @param l a string tree, i.e., a string list that can contain other string
-     *        lists, and so on recursively.
+     * 
+     * @param pw
+     *            the writer to be used to print the tree.
+     * @param l
+     *            a string tree, i.e., a string list that can contain other
+     *            string lists, and so on recursively.
      */
     static void printList(final PrintWriter pw, final List<?> l) {
         for (int i = 0; i < l.size(); ++i) {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
index 81156fc..dfa5e41 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
@@ -29,26 +29,28 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.util;
 
-import org.apache.tapestry5.internal.plastic.asm.Label;
-
 import java.util.Map;
 
+import org.apache.tapestry5.internal.plastic.asm.Label;
+
 /**
  * An {@link org.apache.tapestry5.internal.plastic.asm.Attribute Attribute} that can print a readable
  * representation of itself.
- *
+ * 
  * Implementations should construct readable output from an attribute data
  * structure. Such representation could be used in unit test assertions.
- *
+ * 
  * @author Eugene Kuleshov
  */
 public interface Textifiable {
 
     /**
      * Build a human readable representation of this attribute.
-     *
-     * @param buf a buffer used for printing Java code.
-     * @param labelNames map of label instances to their names.
+     * 
+     * @param buf
+     *            a buffer used for printing Java code.
+     * @param labelNames
+     *            map of label instances to their names.
      */
     void textify(StringBuffer buf, Map<Label, String> labelNames);
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java
index 3598080..854fe7c 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java
@@ -29,14 +29,21 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.util;
 
-import org.apache.tapestry5.internal.plastic.asm.*;
-import org.apache.tapestry5.internal.plastic.asm.signature.SignatureReader;
-
 import java.io.FileInputStream;
 import java.io.PrintWriter;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureReader;
+
 /**
  * A {@link Printer} that prints a disassembled view of the classes it visits.
  *
@@ -130,36 +137,49 @@ public class Textifier extends Printer {
      */
     protected Map<Label, String> labelNames;
 
+    /**
+     * Class access flags
+     */
+    private int access;
+
     private int valueNumber = 0;
 
     /**
      * Constructs a new {@link Textifier}. <i>Subclasses must not use this
      * constructor</i>. Instead, they must use the {@link #Textifier(int)}
      * version.
+     *
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
      */
     public Textifier() {
-        this(Opcodes.ASM4);
+        this(Opcodes.ASM5);
+        if (getClass() != Textifier.class) {
+            throw new IllegalStateException();
+        }
     }
 
     /**
      * Constructs a new {@link Textifier}.
      *
-     * @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}.
      */
     protected Textifier(final int api) {
         super(api);
     }
 
     /**
-     * Prints a disassembled view of the given class to the standard output. <p>
-     * Usage: Textifier [-debug] &lt;binary class name or class
-     * file name &gt;
+     * Prints a disassembled view of the given class to the standard output.
+     * <p>
+     * Usage: Textifier [-debug] &lt;binary class name or class file name &gt;
      *
-     * @param args the command line arguments.
+     * @param args
+     *            the command line arguments.
      *
-     * @throws Exception if the class cannot be found, or if an IO exception
-     *         occurs.
+     * @throws Exception
+     *             if the class cannot be found, or if an IO exception occurs.
      */
     public static void main(final String[] args) throws Exception {
         int i = 0;
@@ -177,21 +197,20 @@ public class Textifier extends Printer {
             }
         }
         if (!ok) {
-            System.err.println("Prints a disassembled view of the given class.");
+            System.err
+                    .println("Prints a disassembled view of the given class.");
             System.err.println("Usage: Textifier [-debug] "
                     + "<fully qualified class name or class file name>");
             return;
         }
         ClassReader cr;
         if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1
-                || args[i].indexOf('/') > -1)
-        {
+                || args[i].indexOf('/') > -1) {
             cr = new ClassReader(new FileInputStream(args[i]));
         } else {
             cr = new ClassReader(args[i]);
         }
-        cr.accept(new TraceClassVisitor(new PrintWriter(System.out)),
-                flags);
+        cr.accept(new TraceClassVisitor(new PrintWriter(System.out)), flags);
     }
 
     // ------------------------------------------------------------------------
@@ -199,38 +218,28 @@ public class Textifier extends Printer {
     // ------------------------------------------------------------------------
 
     @Override
-    public void visit(
-        final int version,
-        final int access,
-        final String name,
-        final String signature,
-        final String superName,
-        final String[] interfaces)
-    {
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
+        this.access = access;
         int major = version & 0xFFFF;
         int minor = version >>> 16;
         buf.setLength(0);
-        buf.append("// class version ")
-                .append(major)
-                .append('.')
-                .append(minor)
-                .append(" (")
-                .append(version)
-                .append(")\n");
+        buf.append("// class version ").append(major).append('.').append(minor)
+                .append(" (").append(version).append(")\n");
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             buf.append("// DEPRECATED\n");
         }
-        buf.append("// access flags 0x").append(Integer.toHexString(access).toUpperCase()).append('\n');
+        buf.append("// access flags 0x")
+                .append(Integer.toHexString(access).toUpperCase()).append('\n');
 
         appendDescriptor(CLASS_SIGNATURE, signature);
         if (signature != null) {
             TraceSignatureVisitor sv = new TraceSignatureVisitor(access);
             SignatureReader r = new SignatureReader(signature);
             r.accept(sv);
-            buf.append("// declaration: ")
-                    .append(name)
-                    .append(sv.getDeclaration())
-                    .append('\n');
+            buf.append("// declaration: ").append(name)
+                    .append(sv.getDeclaration()).append('\n');
         }
 
         appendAccess(access & ~Opcodes.ACC_SUPER);
@@ -264,15 +273,11 @@ public class Textifier extends Printer {
     public void visitSource(final String file, final String debug) {
         buf.setLength(0);
         if (file != null) {
-            buf.append(tab)
-                    .append("// compiled from: ")
-                    .append(file)
+            buf.append(tab).append("// compiled from: ").append(file)
                     .append('\n');
         }
         if (debug != null) {
-            buf.append(tab)
-                    .append("// debug info: ")
-                    .append(debug)
+            buf.append(tab).append("// debug info: ").append(debug)
                     .append('\n');
         }
         if (buf.length() > 0) {
@@ -281,11 +286,8 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public void visitOuterClass(
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    public void visitOuterClass(final String owner, final String name,
+            final String desc) {
         buf.setLength(0);
         buf.append(tab).append("OUTERCLASS ");
         appendDescriptor(INTERNAL_NAME, owner);
@@ -299,30 +301,33 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public Textifier visitClassAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public Textifier visitClassAnnotation(final String desc,
+            final boolean visible) {
         text.add("\n");
         return visitAnnotation(desc, visible);
     }
 
     @Override
+    public Printer visitClassTypeAnnotation(int typeRef, TypePath typePath,
+            String desc, boolean visible) {
+        text.add("\n");
+        return visitTypeAnnotation(typeRef, typePath, desc, visible);
+    }
+
+    @Override
     public void visitClassAttribute(final Attribute attr) {
         text.add("\n");
         visitAttribute(attr);
     }
 
     @Override
-    public void visitInnerClass(
-        final String name,
-        final String outerName,
-        final String innerName,
-        final int access)
-    {
+    public void visitInnerClass(final String name, final String outerName,
+            final String innerName, final int access) {
         buf.setLength(0);
         buf.append(tab).append("// access flags 0x");
-        buf.append(Integer.toHexString(access & ~Opcodes.ACC_SUPER).toUpperCase()).append('\n');
+        buf.append(
+                Integer.toHexString(access & ~Opcodes.ACC_SUPER).toUpperCase())
+                .append('\n');
         buf.append(tab);
         appendAccess(access);
         buf.append("INNERCLASS ");
@@ -336,19 +341,15 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public Textifier visitField(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final Object value)
-    {
+    public Textifier visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
         buf.setLength(0);
         buf.append('\n');
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             buf.append(tab).append("// DEPRECATED\n");
         }
-        buf.append(tab).append("// access flags 0x").append(Integer.toHexString(access).toUpperCase()).append('\n');
+        buf.append(tab).append("// access flags 0x")
+                .append(Integer.toHexString(access).toUpperCase()).append('\n');
         if (signature != null) {
             buf.append(tab);
             appendDescriptor(FIELD_SIGNATURE, signature);
@@ -356,10 +357,8 @@ public class Textifier extends Printer {
             TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
             SignatureReader r = new SignatureReader(signature);
             r.acceptType(sv);
-            buf.append(tab)
-                    .append("// declaration: ")
-                    .append(sv.getDeclaration())
-                    .append('\n');
+            buf.append(tab).append("// declaration: ")
+                    .append(sv.getDeclaration()).append('\n');
         }
 
         buf.append(tab);
@@ -385,19 +384,15 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public Textifier visitMethod(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final String[] exceptions)
-    {
+    public Textifier visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
         buf.setLength(0);
         buf.append('\n');
         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
             buf.append(tab).append("// DEPRECATED\n");
         }
-        buf.append(tab).append("// access flags 0x").append(Integer.toHexString(access).toUpperCase()).append('\n');
+        buf.append(tab).append("// access flags 0x")
+                .append(Integer.toHexString(access).toUpperCase()).append('\n');
 
         if (signature != null) {
             buf.append(tab);
@@ -410,12 +405,8 @@ public class Textifier extends Printer {
             String genericReturn = v.getReturnType();
             String genericExceptions = v.getExceptions();
 
-            buf.append(tab)
-                    .append("// declaration: ")
-                    .append(genericReturn)
-                    .append(' ')
-                    .append(name)
-                    .append(genericDecl);
+            buf.append(tab).append("// declaration: ").append(genericReturn)
+                    .append(' ').append(name).append(genericDecl);
             if (genericExceptions != null) {
                 buf.append(" throws ").append(genericExceptions);
             }
@@ -433,6 +424,11 @@ public class Textifier extends Printer {
         if ((access & Opcodes.ACC_BRIDGE) != 0) {
             buf.append("bridge ");
         }
+        if ((this.access & Opcodes.ACC_INTERFACE) != 0
+                && (access & Opcodes.ACC_ABSTRACT) == 0
+                && (access & Opcodes.ACC_STATIC) == 0) {
+            buf.append("default ");
+        }
 
         buf.append(name);
         appendDescriptor(METHOD_DESCRIPTOR, desc);
@@ -588,11 +584,8 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public void visitEnum(
-        final String name,
-        final String desc,
-        final String value)
-    {
+    public void visitEnum(final String name, final String desc,
+            final String value) {
         buf.setLength(0);
         appendComa(valueNumber++);
         if (name != null) {
@@ -604,10 +597,7 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public Textifier visitAnnotation(
-        final String name,
-        final String desc)
-    {
+    public Textifier visitAnnotation(final String name, final String desc) {
         buf.setLength(0);
         appendComa(valueNumber++);
         if (name != null) {
@@ -624,9 +614,7 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public Textifier visitArray(
-        final String name)
-    {
+    public Textifier visitArray(final String name) {
         buf.setLength(0);
         appendComa(valueNumber++);
         if (name != null) {
@@ -649,14 +637,18 @@ public class Textifier extends Printer {
     // ------------------------------------------------------------------------
 
     @Override
-    public Textifier visitFieldAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public Textifier visitFieldAnnotation(final String desc,
+            final boolean visible) {
         return visitAnnotation(desc, visible);
     }
 
     @Override
+    public Printer visitFieldTypeAnnotation(int typeRef, TypePath typePath,
+            String desc, boolean visible) {
+        return visitTypeAnnotation(typeRef, typePath, desc, visible);
+    }
+
+    @Override
     public void visitFieldAttribute(final Attribute attr) {
         visitAttribute(attr);
     }
@@ -670,6 +662,16 @@ public class Textifier extends Printer {
     // ------------------------------------------------------------------------
 
     @Override
+    public void visitParameter(final String name, final int access) {
+        buf.setLength(0);
+        buf.append(tab2).append("// parameter ");
+        appendAccess(access);
+        buf.append(' ').append((name == null) ? "<no name>" : name)
+                .append('\n');
+        text.add(buf.toString());
+    }
+
+    @Override
     public Textifier visitAnnotationDefault() {
         text.add(tab2 + "default=");
         Textifier t = createTextifier();
@@ -679,19 +681,20 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public Textifier visitMethodAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public Textifier visitMethodAnnotation(final String desc,
+            final boolean visible) {
         return visitAnnotation(desc, visible);
     }
 
     @Override
-    public Textifier visitParameterAnnotation(
-        final int parameter,
-        final String desc,
-        final boolean visible)
-    {
+    public Printer visitMethodTypeAnnotation(int typeRef, TypePath typePath,
+            String desc, boolean visible) {
+        return visitTypeAnnotation(typeRef, typePath, desc, visible);
+    }
+
+    @Override
+    public Textifier visitParameterAnnotation(final int parameter,
+            final String desc, final boolean visible) {
         buf.setLength(0);
         buf.append(tab2).append('@');
         appendDescriptor(FIELD_DESCRIPTOR, desc);
@@ -725,40 +728,35 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public void visitFrame(
-        final int type,
-        final int nLocal,
-        final Object[] local,
-        final int nStack,
-        final Object[] stack)
-    {
+    public void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack) {
         buf.setLength(0);
         buf.append(ltab);
         buf.append("FRAME ");
         switch (type) {
-            case Opcodes.F_NEW:
-            case Opcodes.F_FULL:
-                buf.append("FULL [");
-                appendFrameTypes(nLocal, local);
-                buf.append("] [");
-                appendFrameTypes(nStack, stack);
-                buf.append(']');
-                break;
-            case Opcodes.F_APPEND:
-                buf.append("APPEND [");
-                appendFrameTypes(nLocal, local);
-                buf.append(']');
-                break;
-            case Opcodes.F_CHOP:
-                buf.append("CHOP ").append(nLocal);
-                break;
-            case Opcodes.F_SAME:
-                buf.append("SAME");
-                break;
-            case Opcodes.F_SAME1:
-                buf.append("SAME1 ");
-                appendFrameTypes(1, stack);
-                break;
+        case Opcodes.F_NEW:
+        case Opcodes.F_FULL:
+            buf.append("FULL [");
+            appendFrameTypes(nLocal, local);
+            buf.append("] [");
+            appendFrameTypes(nStack, stack);
+            buf.append(']');
+            break;
+        case Opcodes.F_APPEND:
+            buf.append("APPEND [");
+            appendFrameTypes(nLocal, local);
+            buf.append(']');
+            break;
+        case Opcodes.F_CHOP:
+            buf.append("CHOP ").append(nLocal);
+            break;
+        case Opcodes.F_SAME:
+            buf.append("SAME");
+            break;
+        case Opcodes.F_SAME1:
+            buf.append("SAME1 ");
+            appendFrameTypes(1, stack);
+            break;
         }
         buf.append('\n');
         text.add(buf.toString());
@@ -777,20 +775,15 @@ public class Textifier extends Printer {
         buf.append(tab2)
                 .append(OPCODES[opcode])
                 .append(' ')
-                .append(opcode == Opcodes.NEWARRAY
-                        ? TYPES[operand]
-                        : Integer.toString(operand))
-                .append('\n');
+                .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer
+                        .toString(operand)).append('\n');
         text.add(buf.toString());
     }
 
     @Override
     public void visitVarInsn(final int opcode, final int var) {
         buf.setLength(0);
-        buf.append(tab2)
-                .append(OPCODES[opcode])
-                .append(' ')
-                .append(var)
+        buf.append(tab2).append(OPCODES[opcode]).append(' ').append(var)
                 .append('\n');
         text.add(buf.toString());
     }
@@ -805,12 +798,8 @@ public class Textifier extends Printer {
     }
 
     @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) {
         buf.setLength(0);
         buf.append(tab2).append(OPCODES[opcode]).append(' ');
         appendDescriptor(INTERNAL_NAME, owner);
@@ -820,13 +809,30 @@ public class Textifier extends Printer {
         text.add(buf.toString());
     }
 
+    @Deprecated
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (api >= Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc,
+                opcode == Opcodes.INVOKEINTERFACE);
+    }
+
     @Override
-    public void visitMethodInsn(
-        final int opcode,
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    private void doVisitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
         buf.setLength(0);
         buf.append(tab2).append(OPCODES[opcode]).append(' ');
         appendDescriptor(INTERNAL_NAME, owner);
@@ -837,37 +843,42 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public void visitInvokeDynamicInsn(
-        String name,
-        String desc,
-        Handle bsm,
-        Object... bsmArgs)
-    {
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
         buf.setLength(0);
         buf.append(tab2).append("INVOKEDYNAMIC").append(' ');
         buf.append(name);
         appendDescriptor(METHOD_DESCRIPTOR, desc);
         buf.append(" [");
+        buf.append('\n');
+        buf.append(tab3);
         appendHandle(bsm);
+        buf.append('\n');
         buf.append(tab3).append("// arguments:");
-        if(bsmArgs.length == 0) {
+        if (bsmArgs.length == 0) {
             buf.append(" none");
         } else {
-            buf.append('\n').append(tab3);
-            for(int i = 0; i < bsmArgs.length; i++) {
+            buf.append('\n');
+            for (int i = 0; i < bsmArgs.length; i++) {
+                buf.append(tab3);
                 Object cst = bsmArgs[i];
                 if (cst instanceof String) {
                     Printer.appendString(buf, (String) cst);
                 } else if (cst instanceof Type) {
-                    buf.append(((Type) cst).getDescriptor()).append(".class");
+                    Type type = (Type) cst;
+                    if(type.getSort() == Type.METHOD){
+                        appendDescriptor(METHOD_DESCRIPTOR, type.getDescriptor());
+                    } else {
+                        buf.append(type.getDescriptor()).append(".class");
+                    }
                 } else if (cst instanceof Handle) {
                     appendHandle((Handle) cst);
                 } else {
                     buf.append(cst);
                 }
-                buf.append(", ");
+                buf.append(", \n");
             }
-            buf.setLength(buf.length() - 2);
+            buf.setLength(buf.length() - 3);
         }
         buf.append('\n');
         buf.append(tab2).append("]\n");
@@ -910,22 +921,14 @@ public class Textifier extends Printer {
     @Override
     public void visitIincInsn(final int var, final int increment) {
         buf.setLength(0);
-        buf.append(tab2)
-                .append("IINC ")
-                .append(var)
-                .append(' ')
-                .append(increment)
-                .append('\n');
+        buf.append(tab2).append("IINC ").append(var).append(' ')
+                .append(increment).append('\n');
         text.add(buf.toString());
     }
 
     @Override
-    public void visitTableSwitchInsn(
-        final int min,
-        final int max,
-        final Label dflt,
-        final Label... labels)
-    {
+    public void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels) {
         buf.setLength(0);
         buf.append(tab2).append("TABLESWITCH\n");
         for (int i = 0; i < labels.length; ++i) {
@@ -940,11 +943,8 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public void visitLookupSwitchInsn(
-        final Label dflt,
-        final int[] keys,
-        final Label[] labels)
-    {
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
         buf.setLength(0);
         buf.append(tab2).append("LOOKUPSWITCH\n");
         for (int i = 0; i < labels.length; ++i) {
@@ -968,12 +968,14 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public void visitTryCatchBlock(
-        final Label start,
-        final Label end,
-        final Label handler,
-        final String type)
-    {
+    public Printer visitInsnAnnotation(int typeRef, TypePath typePath,
+            String desc, boolean visible) {
+        return visitTypeAnnotation(typeRef, typePath, desc, visible);
+    }
+
+    @Override
+    public void visitTryCatchBlock(final Label start, final Label end,
+            final Label handler, final String type) {
         buf.setLength(0);
         buf.append(tab2).append("TRYCATCHBLOCK ");
         appendLabel(start);
@@ -988,14 +990,28 @@ public class Textifier extends Printer {
     }
 
     @Override
-    public void visitLocalVariable(
-        final String name,
-        final String desc,
-        final String signature,
-        final Label start,
-        final Label end,
-        final int index)
-    {
+    public Printer visitTryCatchAnnotation(int typeRef, TypePath typePath,
+            String desc, boolean visible) {
+        buf.setLength(0);
+        buf.append(tab2).append("TRYCATCHBLOCK @");
+        appendDescriptor(FIELD_DESCRIPTOR, desc);
+        buf.append('(');
+        text.add(buf.toString());
+        Textifier t = createTextifier();
+        text.add(t.getText());
+        buf.setLength(0);
+        buf.append(") : ");
+        appendTypeReference(typeRef);
+        buf.append(", ").append(typePath);
+        buf.append(visible ? "\n" : " // invisible\n");
+        text.add(buf.toString());
+        return t;
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
         buf.setLength(0);
         buf.append(tab2).append("LOCALVARIABLE ").append(name).append(' ');
         appendDescriptor(FIELD_DESCRIPTOR, desc);
@@ -1012,12 +1028,37 @@ public class Textifier extends Printer {
             TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
             SignatureReader r = new SignatureReader(signature);
             r.acceptType(sv);
-            buf.append(tab2)
-                    .append("// declaration: ")
-                    .append(sv.getDeclaration())
-                    .append('\n');
+            buf.append(tab2).append("// declaration: ")
+                    .append(sv.getDeclaration()).append('\n');
+        }
+        text.add(buf.toString());
+    }
+
+    @Override
+    public Printer visitLocalVariableAnnotation(int typeRef, TypePath typePath,
+            Label[] start, Label[] end, int[] index, String desc,
+            boolean visible) {
+        buf.setLength(0);
+        buf.append(tab2).append("LOCALVARIABLE @");
+        appendDescriptor(FIELD_DESCRIPTOR, desc);
+        buf.append('(');
+        text.add(buf.toString());
+        Textifier t = createTextifier();
+        text.add(t.getText());
+        buf.setLength(0);
+        buf.append(") : ");
+        appendTypeReference(typeRef);
+        buf.append(", ").append(typePath);
+        for (int i = 0; i < start.length; ++i) {
+            buf.append(" [ ");
+            appendLabel(start[i]);
+            buf.append(" - ");
+            appendLabel(end[i]);
+            buf.append(" - ").append(index[i]).append(" ]");
         }
+        buf.append(visible ? "\n" : " // invisible\n");
         text.add(buf.toString());
+        return t;
     }
 
     @Override
@@ -1051,14 +1092,13 @@ public class Textifier extends Printer {
     /**
      * Prints a disassembled view of the given annotation.
      *
-     * @param desc the class descriptor of the annotation class.
-     * @param visible <tt>true</tt> if the annotation is visible at runtime.
+     * @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.
      */
-    public Textifier visitAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public Textifier visitAnnotation(final String desc, final boolean visible) {
         buf.setLength(0);
         buf.append(tab).append('@');
         appendDescriptor(FIELD_DESCRIPTOR, desc);
@@ -1071,9 +1111,43 @@ public class Textifier extends Printer {
     }
 
     /**
+     * Prints a disassembled view of the given type annotation.
+     *
+     * @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.
+     * @param visible
+     *            <tt>true</tt> if the annotation is visible at runtime.
+     * @return a visitor to visit the annotation values.
+     */
+    public Textifier visitTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        buf.setLength(0);
+        buf.append(tab).append('@');
+        appendDescriptor(FIELD_DESCRIPTOR, desc);
+        buf.append('(');
+        text.add(buf.toString());
+        Textifier t = createTextifier();
+        text.add(t.getText());
+        buf.setLength(0);
+        buf.append(") : ");
+        appendTypeReference(typeRef);
+        buf.append(", ").append(typePath);
+        buf.append(visible ? "\n" : " // invisible\n");
+        text.add(buf.toString());
+        return t;
+    }
+
+    /**
      * Prints a disassembled view of the given attribute.
      *
-     * @param attr an attribute.
+     * @param attr
+     *            an attribute.
      */
     public void visitAttribute(final Attribute attr) {
         buf.setLength(0);
@@ -1106,15 +1180,16 @@ public class Textifier extends Printer {
      * Appends an internal name, a type descriptor or a type signature to
      * {@link #buf buf}.
      *
-     * @param type indicates if desc is an internal name, a field descriptor, a
-     *        method descriptor, a class signature, ...
-     * @param desc an internal name, type descriptor, or type signature. May be
-     *        <tt>null</tt>.
+     * @param type
+     *            indicates if desc is an internal name, a field descriptor, a
+     *            method descriptor, a class signature, ...
+     * @param desc
+     *            an internal name, type descriptor, or type signature. May be
+     *            <tt>null</tt>.
      */
     protected void appendDescriptor(final int type, final String desc) {
         if (type == CLASS_SIGNATURE || type == FIELD_SIGNATURE
-                || type == METHOD_SIGNATURE)
-        {
+                || type == METHOD_SIGNATURE) {
             if (desc != null) {
                 buf.append("// signature ").append(desc).append('\n');
             }
@@ -1127,7 +1202,8 @@ public class Textifier extends Printer {
      * Appends the name of the given label to {@link #buf buf}. Creates a new
      * label name if the given label does not yet have one.
      *
-     * @param l a label.
+     * @param l
+     *            a label.
      */
     protected void appendLabel(final Label l) {
         if (labelNames == null) {
@@ -1144,56 +1220,68 @@ public class Textifier extends Printer {
     /**
      * Appends the information about the given handle to {@link #buf buf}.
      *
-     * @param h a handle, non null.
+     * @param h
+     *            a handle, non null.
      */
     protected void appendHandle(final Handle h) {
-        buf.append('\n').append(tab3);
         int tag = h.getTag();
-        buf.append("// handle kind 0x").append(Integer.toHexString(tag)).append(" : ");
+        buf.append("// handle kind 0x").append(Integer.toHexString(tag))
+                .append(" : ");
+        boolean isMethodHandle = false;
         switch (tag) {
-            case Opcodes.H_GETFIELD:
-                buf.append("GETFIELD");
-                break;
-            case Opcodes.H_GETSTATIC:
-                buf.append("GETSTATIC");
-                break;
-            case Opcodes.H_PUTFIELD:
-                buf.append("PUTFIELD");
-                break;
-            case Opcodes.H_PUTSTATIC:
-                buf.append("PUTSTATIC");
-                break;
-            case Opcodes.H_INVOKEINTERFACE:
-                buf.append("INVOKEINTERFACE");
-                break;
-            case Opcodes.H_INVOKESPECIAL:
-                buf.append("INVOKESPECIAL");
-                break;
-            case Opcodes.H_INVOKESTATIC:
-                buf.append("INVOKESTATIC");
-                break;
-            case Opcodes.H_INVOKEVIRTUAL:
-                buf.append("INVOKEVIRTUAL");
-                break;
-            case Opcodes.H_NEWINVOKESPECIAL:
-                buf.append("NEWINVOKESPECIAL");
-                break;
+        case Opcodes.H_GETFIELD:
+            buf.append("GETFIELD");
+            break;
+        case Opcodes.H_GETSTATIC:
+            buf.append("GETSTATIC");
+            break;
+        case Opcodes.H_PUTFIELD:
+            buf.append("PUTFIELD");
+            break;
+        case Opcodes.H_PUTSTATIC:
+            buf.append("PUTSTATIC");
+            break;
+        case Opcodes.H_INVOKEINTERFACE:
+            buf.append("INVOKEINTERFACE");
+            isMethodHandle = true;
+            break;
+        case Opcodes.H_INVOKESPECIAL:
+            buf.append("INVOKESPECIAL");
+            isMethodHandle = true;
+            break;
+        case Opcodes.H_INVOKESTATIC:
+            buf.append("INVOKESTATIC");
+            isMethodHandle = true;
+            break;
+        case Opcodes.H_INVOKEVIRTUAL:
+            buf.append("INVOKEVIRTUAL");
+            isMethodHandle = true;
+            break;
+        case Opcodes.H_NEWINVOKESPECIAL:
+            buf.append("NEWINVOKESPECIAL");
+            isMethodHandle = true;
+            break;
         }
         buf.append('\n');
         buf.append(tab3);
         appendDescriptor(INTERNAL_NAME, h.getOwner());
         buf.append('.');
         buf.append(h.getName());
-        buf.append('(');
+        if(!isMethodHandle){
+            buf.append('(');
+        }
         appendDescriptor(HANDLE_DESCRIPTOR, h.getDesc());
-        buf.append(')').append('\n');
+        if(!isMethodHandle){
+            buf.append(')');
+        }
     }
 
     /**
-     * Appends a string representation of the given access modifiers to {@link
-     * #buf buf}.
+     * Appends a string representation of the given access modifiers to
+     * {@link #buf buf}.
      *
-     * @param access some access modifiers.
+     * @param access
+     *            some access modifiers.
      */
     private void appendAccess(final int access) {
         if ((access & Opcodes.ACC_PUBLIC) != 0) {
@@ -1226,6 +1314,12 @@ public class Textifier extends Printer {
         if ((access & Opcodes.ACC_STRICT) != 0) {
             buf.append("strictfp ");
         }
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            buf.append("synthetic ");
+        }
+        if ((access & Opcodes.ACC_MANDATED) != 0) {
+            buf.append("mandated ");
+        }
         if ((access & Opcodes.ACC_ENUM) != 0) {
             buf.append("enum ");
         }
@@ -1237,6 +1331,90 @@ public class Textifier extends Printer {
         }
     }
 
+    private void appendTypeReference(final int typeRef) {
+        TypeReference ref = new TypeReference(typeRef);
+        switch (ref.getSort()) {
+        case TypeReference.CLASS_TYPE_PARAMETER:
+            buf.append("CLASS_TYPE_PARAMETER ").append(
+                    ref.getTypeParameterIndex());
+            break;
+        case TypeReference.METHOD_TYPE_PARAMETER:
+            buf.append("METHOD_TYPE_PARAMETER ").append(
+                    ref.getTypeParameterIndex());
+            break;
+        case TypeReference.CLASS_EXTENDS:
+            buf.append("CLASS_EXTENDS ").append(ref.getSuperTypeIndex());
+            break;
+        case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
+            buf.append("CLASS_TYPE_PARAMETER_BOUND ")
+                    .append(ref.getTypeParameterIndex()).append(", ")
+                    .append(ref.getTypeParameterBoundIndex());
+            break;
+        case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
+            buf.append("METHOD_TYPE_PARAMETER_BOUND ")
+                    .append(ref.getTypeParameterIndex()).append(", ")
+                    .append(ref.getTypeParameterBoundIndex());
+            break;
+        case TypeReference.FIELD:
+            buf.append("FIELD");
+            break;
+        case TypeReference.METHOD_RETURN:
+            buf.append("METHOD_RETURN");
+            break;
+        case TypeReference.METHOD_RECEIVER:
+            buf.append("METHOD_RECEIVER");
+            break;
+        case TypeReference.METHOD_FORMAL_PARAMETER:
+            buf.append("METHOD_FORMAL_PARAMETER ").append(
+                    ref.getFormalParameterIndex());
+            break;
+        case TypeReference.THROWS:
+            buf.append("THROWS ").append(ref.getExceptionIndex());
+            break;
+        case TypeReference.LOCAL_VARIABLE:
+            buf.append("LOCAL_VARIABLE");
+            break;
+        case TypeReference.RESOURCE_VARIABLE:
+            buf.append("RESOURCE_VARIABLE");
+            break;
+        case TypeReference.EXCEPTION_PARAMETER:
+            buf.append("EXCEPTION_PARAMETER ").append(
+                    ref.getTryCatchBlockIndex());
+            break;
+        case TypeReference.INSTANCEOF:
+            buf.append("INSTANCEOF");
+            break;
+        case TypeReference.NEW:
+            buf.append("NEW");
+            break;
+        case TypeReference.CONSTRUCTOR_REFERENCE:
+            buf.append("CONSTRUCTOR_REFERENCE");
+            break;
+        case TypeReference.METHOD_REFERENCE:
+            buf.append("METHOD_REFERENCE");
+            break;
+        case TypeReference.CAST:
+            buf.append("CAST ").append(ref.getTypeArgumentIndex());
+            break;
+        case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
+            buf.append("CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT ").append(
+                    ref.getTypeArgumentIndex());
+            break;
+        case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT:
+            buf.append("METHOD_INVOCATION_TYPE_ARGUMENT ").append(
+                    ref.getTypeArgumentIndex());
+            break;
+        case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
+            buf.append("CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT ").append(
+                    ref.getTypeArgumentIndex());
+            break;
+        case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT:
+            buf.append("METHOD_REFERENCE_TYPE_ARGUMENT ").append(
+                    ref.getTypeArgumentIndex());
+            break;
+        }
+    }
+
     private void appendFrameTypes(final int n, final Object[] o) {
         for (int i = 0; i < n; ++i) {
             if (i > 0) {
@@ -1251,27 +1429,27 @@ public class Textifier extends Printer {
                 }
             } else if (o[i] instanceof Integer) {
                 switch (((Integer) o[i]).intValue()) {
-                    case 0:
-                        appendDescriptor(FIELD_DESCRIPTOR, "T");
-                        break;
-                    case 1:
-                        appendDescriptor(FIELD_DESCRIPTOR, "I");
-                        break;
-                    case 2:
-                        appendDescriptor(FIELD_DESCRIPTOR, "F");
-                        break;
-                    case 3:
-                        appendDescriptor(FIELD_DESCRIPTOR, "D");
-                        break;
-                    case 4:
-                        appendDescriptor(FIELD_DESCRIPTOR, "J");
-                        break;
-                    case 5:
-                        appendDescriptor(FIELD_DESCRIPTOR, "N");
-                        break;
-                    case 6:
-                        appendDescriptor(FIELD_DESCRIPTOR, "U");
-                        break;
+                case 0:
+                    appendDescriptor(FIELD_DESCRIPTOR, "T");
+                    break;
+                case 1:
+                    appendDescriptor(FIELD_DESCRIPTOR, "I");
+                    break;
+                case 2:
+                    appendDescriptor(FIELD_DESCRIPTOR, "F");
+                    break;
+                case 3:
+                    appendDescriptor(FIELD_DESCRIPTOR, "D");
+                    break;
+                case 4:
+                    appendDescriptor(FIELD_DESCRIPTOR, "J");
+                    break;
+                case 5:
+                    appendDescriptor(FIELD_DESCRIPTOR, "N");
+                    break;
+                case 6:
+                    appendDescriptor(FIELD_DESCRIPTOR, "U");
+                    break;
                 }
             } else {
                 appendLabel((Label) o[i]);

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
index 84b9750..3af500a 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
@@ -33,13 +33,12 @@ import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
 import org.apache.tapestry5.internal.plastic.asm.Opcodes;
 
 /**
- * An {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor} that prints the annotations it visits with a
+ * An {@link AnnotationVisitor} that prints the annotations it visits with a
  * {@link Printer}.
- *
+ * 
  * @author Eric Bruneton
  */
-public final class TraceAnnotationVisitor extends AnnotationVisitor
-{
+public final class TraceAnnotationVisitor extends AnnotationVisitor {
 
     private final Printer p;
 
@@ -48,7 +47,7 @@ public final class TraceAnnotationVisitor extends AnnotationVisitor
     }
 
     public TraceAnnotationVisitor(final AnnotationVisitor av, final Printer p) {
-        super(Opcodes.ASM4, av);
+        super(Opcodes.ASM5, av);
         this.p = p;
     }
 
@@ -59,33 +58,26 @@ public final class TraceAnnotationVisitor extends AnnotationVisitor
     }
 
     @Override
-    public void visitEnum(
-        final String name,
-        final String desc,
-        final String value)
-    {
+    public void visitEnum(final String name, final String desc,
+            final String value) {
         p.visitEnum(name, desc, value);
         super.visitEnum(name, desc, value);
     }
 
     @Override
-    public AnnotationVisitor visitAnnotation(
-        final String name,
-        final String desc)
-    {
+    public AnnotationVisitor visitAnnotation(final String name,
+            final String desc) {
         Printer p = this.p.visitAnnotation(name, desc);
-        AnnotationVisitor av = this.av == null
-                ? null
-                : this.av.visitAnnotation(name, desc);
+        AnnotationVisitor av = this.av == null ? null : this.av
+                .visitAnnotation(name, desc);
         return new TraceAnnotationVisitor(av, p);
     }
 
     @Override
     public AnnotationVisitor visitArray(final String name) {
         Printer p = this.p.visitArray(name);
-        AnnotationVisitor av = this.av == null
-                ? null
-                : this.av.visitArray(name);
+        AnnotationVisitor av = this.av == null ? null : this.av
+                .visitArray(name);
         return new TraceAnnotationVisitor(av, p);
     }
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java
index ae06852..7c6a775 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.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,18 +29,28 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.util;
 
-import org.apache.tapestry5.internal.plastic.asm.*;
-
 import java.io.PrintWriter;
 
+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.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
 /**
  * A {@link ClassVisitor} that prints the classes it visits with a
  * {@link Printer}. This class visitor can be used in the middle of a class
  * visitor chain to trace the class that is visited at a given point in this
- * chain. This may be useful for debugging purposes. <p> The trace printed when
- * visiting the <tt>Hello</tt> class is the following: <p> <blockquote>
+ * chain. This may be useful for debugging purposes.
+ * <p>
+ * The trace printed when visiting the <tt>Hello</tt> class is the following:
+ * <p>
+ * <blockquote>
  * 
- * <pre> // class version 49.0 (49) // access flags 0x21 public class Hello {
+ * <pre>
+ * // class version 49.0 (49) // access flags 0x21 public class Hello {
  * 
  * // compiled from: Hello.java
  * 
@@ -51,14 +60,21 @@ import java.io.PrintWriter;
  * // access flags 0x9 public static main ([Ljava/lang/String;)V GETSTATIC
  * java/lang/System out Ljava/io/PrintStream; LDC &quot;hello&quot;
  * INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V RETURN
- * MAXSTACK = 2 MAXLOCALS = 1 } </pre>
+ * MAXSTACK = 2 MAXLOCALS = 1 }
+ * </pre>
  * 
- * </blockquote> where <tt>Hello</tt> is defined by: <p> <blockquote>
+ * </blockquote> where <tt>Hello</tt> is defined by:
+ * <p>
+ * <blockquote>
  * 
- * <pre> public class Hello {
+ * <pre>
+ * public class Hello {
  * 
- * public static void main(String[] args) {
- * System.out.println(&quot;hello&quot;); } } </pre>
+ *     public static void main(String[] args) {
+ *         System.out.println(&quot;hello&quot;);
+ *     }
+ * }
+ * </pre>
  * 
  * </blockquote>
  * 
@@ -80,7 +96,8 @@ public final class TraceClassVisitor extends ClassVisitor {
     /**
      * Constructs a new {@link TraceClassVisitor}.
      * 
-     * @param pw the print writer to be used to print the class.
+     * @param pw
+     *            the print writer to be used to print the class.
      */
     public TraceClassVisitor(final PrintWriter pw) {
         this(null, pw);
@@ -89,9 +106,11 @@ public final class TraceClassVisitor extends ClassVisitor {
     /**
      * Constructs a new {@link TraceClassVisitor}.
      * 
-     * @param cv the {@link ClassVisitor} to which this visitor delegates calls.
-     *        May be <tt>null</tt>.
-     * @param pw the print writer to be used to print the class.
+     * @param cv
+     *            the {@link ClassVisitor} to which this visitor delegates
+     *            calls. May be <tt>null</tt>.
+     * @param pw
+     *            the print writer to be used to print the class.
      */
     public TraceClassVisitor(final ClassVisitor cv, final PrintWriter pw) {
         this(cv, new Textifier(), pw);
@@ -100,32 +119,27 @@ public final class TraceClassVisitor extends ClassVisitor {
     /**
      * Constructs a new {@link TraceClassVisitor}.
      * 
-     * @param cv the {@link ClassVisitor} to which this visitor delegates calls.
-     *        May be <tt>null</tt>.
-     * @param p the object that actually converts visit events into text.
-     * @param pw the print writer to be used to print the class. May be null if
-     *        you simply want to use the result via
-     *        {@link Printer#getText()}, instead of printing it.
+     * @param cv
+     *            the {@link ClassVisitor} to which this visitor delegates
+     *            calls. May be <tt>null</tt>.
+     * @param p
+     *            the object that actually converts visit events into text.
+     * @param pw
+     *            the print writer to be used to print the class. May be null if
+     *            you simply want to use the result via
+     *            {@link Printer#getText()}, instead of printing it.
      */
-    public TraceClassVisitor(
-        final ClassVisitor cv,
-        final Printer p,
-        final PrintWriter pw)
-    {
-        super(Opcodes.ASM4, cv);
+    public TraceClassVisitor(final ClassVisitor cv, final Printer p,
+            final PrintWriter pw) {
+        super(Opcodes.ASM5, cv);
         this.pw = pw;
         this.p = p;
     }
 
     @Override
-    public void visit(
-        final int version,
-        final int access,
-        final String name,
-        final String signature,
-        final String superName,
-        final String[] interfaces)
-    {
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
         p.visit(version, access, name, signature, superName, interfaces);
         super.visit(version, access, name, signature, superName, interfaces);
     }
@@ -137,20 +151,15 @@ public final class TraceClassVisitor extends ClassVisitor {
     }
 
     @Override
-    public void visitOuterClass(
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    public void visitOuterClass(final String owner, final String name,
+            final String desc) {
         p.visitOuterClass(owner, name, desc);
         super.visitOuterClass(owner, name, desc);
     }
 
     @Override
-    public AnnotationVisitor visitAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
         Printer p = this.p.visitClassAnnotation(desc, visible);
         AnnotationVisitor av = cv == null ? null : cv.visitAnnotation(desc,
                 visible);
@@ -158,61 +167,44 @@ public final class TraceClassVisitor extends ClassVisitor {
     }
 
     @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        Printer p = this.p.visitClassTypeAnnotation(typeRef, typePath, desc,
+                visible);
+        AnnotationVisitor av = cv == null ? null : cv.visitTypeAnnotation(
+                typeRef, typePath, desc, visible);
+        return new TraceAnnotationVisitor(av, p);
+    }
+
+    @Override
     public void visitAttribute(final Attribute attr) {
         p.visitClassAttribute(attr);
         super.visitAttribute(attr);
     }
 
     @Override
-    public void visitInnerClass(
-        final String name,
-        final String outerName,
-        final String innerName,
-        final int access)
-    {
+    public void visitInnerClass(final String name, final String outerName,
+            final String innerName, final int access) {
         p.visitInnerClass(name, outerName, innerName, access);
         super.visitInnerClass(name, outerName, innerName, access);
     }
 
     @Override
-    public FieldVisitor visitField(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final Object value)
-    {
-        Printer p = this.p.visitField(access,
-                name,
-                desc,
-                signature,
-                value);
-        FieldVisitor fv = cv == null ? null : cv.visitField(access,
-                name,
-                desc,
-                signature,
-                value);
+    public FieldVisitor visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
+        Printer p = this.p.visitField(access, name, desc, signature, value);
+        FieldVisitor fv = cv == null ? null : cv.visitField(access, name, desc,
+                signature, value);
         return new TraceFieldVisitor(fv, p);
     }
 
     @Override
-    public MethodVisitor visitMethod(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final String[] exceptions)
-    {
-        Printer p = this.p.visitMethod(access,
-                name,
-                desc,
-                signature,
-                exceptions);
-        MethodVisitor mv = cv == null ? null : cv.visitMethod(access,
-                name,
-                desc,
-                signature,
+    public MethodVisitor visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        Printer p = this.p.visitMethod(access, name, desc, signature,
                 exceptions);
+        MethodVisitor mv = cv == null ? null : cv.visitMethod(access, name,
+                desc, signature, exceptions);
         return new TraceMethodVisitor(mv, p);
     }
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java
index d75b04b..3fed39e 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.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
@@ -34,15 +33,15 @@ import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
 import org.apache.tapestry5.internal.plastic.asm.Attribute;
 import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
 import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
 
 /**
- * A {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor} that prints the fields it visits with a
+ * A {@link FieldVisitor} that prints the fields it visits with a
  * {@link Printer}.
  * 
  * @author Eric Bruneton
  */
-public final class TraceFieldVisitor extends FieldVisitor
-{
+public final class TraceFieldVisitor extends FieldVisitor {
 
     public final Printer p;
 
@@ -51,15 +50,13 @@ public final class TraceFieldVisitor extends FieldVisitor
     }
 
     public TraceFieldVisitor(final FieldVisitor fv, final Printer p) {
-        super(Opcodes.ASM4, fv);
+        super(Opcodes.ASM5, fv);
         this.p = p;
     }
-        
+
     @Override
-    public AnnotationVisitor visitAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
         Printer p = this.p.visitFieldAnnotation(desc, visible);
         AnnotationVisitor av = fv == null ? null : fv.visitAnnotation(desc,
                 visible);
@@ -67,6 +64,16 @@ public final class TraceFieldVisitor extends FieldVisitor
     }
 
     @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        Printer p = this.p.visitFieldTypeAnnotation(typeRef, typePath, desc,
+                visible);
+        AnnotationVisitor av = fv == null ? null : fv.visitTypeAnnotation(
+                typeRef, typePath, desc, visible);
+        return new TraceAnnotationVisitor(av, p);
+    }
+
+    @Override
     public void visitAttribute(final Attribute attr) {
         p.visitFieldAttribute(attr);
         super.visitAttribute(attr);


[12/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassConstantsCollector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassConstantsCollector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassConstantsCollector.java
new file mode 100644
index 0000000..b907322
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassConstantsCollector.java
@@ -0,0 +1,198 @@
+/***
+ * 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.optimizer;
+
+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.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A {@link ClassVisitor} that collects the {@link Constant}s of the classes it
+ * visits.
+ * 
+ * @author Eric Bruneton
+ */
+public class ClassConstantsCollector extends ClassVisitor {
+
+    private final ConstantPool cp;
+
+    public ClassConstantsCollector(final ClassVisitor cv, final ConstantPool cp) {
+        super(Opcodes.ASM5, cv);
+        this.cp = cp;
+    }
+
+    @Override
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            cp.newUTF8("Deprecated");
+        }
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            cp.newUTF8("Synthetic");
+        }
+        cp.newClass(name);
+        if (signature != null) {
+            cp.newUTF8("Signature");
+            cp.newUTF8(signature);
+        }
+        if (superName != null) {
+            cp.newClass(superName);
+        }
+        if (interfaces != null) {
+            for (int i = 0; i < interfaces.length; ++i) {
+                cp.newClass(interfaces[i]);
+            }
+        }
+        cv.visit(version, access, name, signature, superName, interfaces);
+    }
+
+    @Override
+    public void visitSource(final String source, final String debug) {
+        if (source != null) {
+            cp.newUTF8("SourceFile");
+            cp.newUTF8(source);
+        }
+        if (debug != null) {
+            cp.newUTF8("SourceDebugExtension");
+        }
+        cv.visitSource(source, debug);
+    }
+
+    @Override
+    public void visitOuterClass(final String owner, final String name,
+            final String desc) {
+        cp.newUTF8("EnclosingMethod");
+        cp.newClass(owner);
+        if (name != null && desc != null) {
+            cp.newNameType(name, desc);
+        }
+        cv.visitOuterClass(owner, name, desc);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleAnnotations");
+        }
+        return new AnnotationConstantsCollector(cv.visitAnnotation(desc,
+                visible), cp);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleTypeAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+        }
+        return new AnnotationConstantsCollector(cv.visitAnnotation(desc,
+                visible), cp);
+    }
+
+    @Override
+    public void visitAttribute(final Attribute attr) {
+        // can do nothing
+        cv.visitAttribute(attr);
+    }
+
+    @Override
+    public void visitInnerClass(final String name, final String outerName,
+            final String innerName, final int access) {
+        cp.newUTF8("InnerClasses");
+        if (name != null) {
+            cp.newClass(name);
+        }
+        if (outerName != null) {
+            cp.newClass(outerName);
+        }
+        if (innerName != null) {
+            cp.newUTF8(innerName);
+        }
+        cv.visitInnerClass(name, outerName, innerName, access);
+    }
+
+    @Override
+    public FieldVisitor visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            cp.newUTF8("Synthetic");
+        }
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            cp.newUTF8("Deprecated");
+        }
+        cp.newUTF8(name);
+        cp.newUTF8(desc);
+        if (signature != null) {
+            cp.newUTF8("Signature");
+            cp.newUTF8(signature);
+        }
+        if (value != null) {
+            cp.newConst(value);
+        }
+        return new FieldConstantsCollector(cv.visitField(access, name, desc,
+                signature, value), cp);
+    }
+
+    @Override
+    public MethodVisitor visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            cp.newUTF8("Synthetic");
+        }
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            cp.newUTF8("Deprecated");
+        }
+        cp.newUTF8(name);
+        cp.newUTF8(desc);
+        if (signature != null) {
+            cp.newUTF8("Signature");
+            cp.newUTF8(signature);
+        }
+        if (exceptions != null) {
+            cp.newUTF8("Exceptions");
+            for (int i = 0; i < exceptions.length; ++i) {
+                cp.newClass(exceptions[i]);
+            }
+        }
+        return new MethodConstantsCollector(cv.visitMethod(access, name, desc,
+                signature, exceptions), cp);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java
new file mode 100644
index 0000000..f4a7a22
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java
@@ -0,0 +1,260 @@
+/***
+ * 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.optimizer;
+
+import java.util.ArrayList;
+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.FieldVisitor;
+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.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.commons.Remapper;
+import org.apache.tapestry5.internal.plastic.asm.commons.RemappingClassAdapter;
+
+/**
+ * A {@link ClassVisitor} that renames fields and methods, and removes debug
+ * info.
+ * 
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class ClassOptimizer extends RemappingClassAdapter {
+
+    private String pkgName;
+    String clsName;
+
+    boolean isInterface = false;
+    boolean hasClinitMethod = false;
+    List<String> syntheticClassFields = new ArrayList<String>();
+
+    public ClassOptimizer(final ClassVisitor cv, final Remapper remapper) {
+        super(Opcodes.ASM5, cv, remapper);
+    }
+
+    FieldVisitor syntheticFieldVisitor(final int access, final String name,
+            final String desc) {
+        return super.visitField(access, name, desc, null, null);
+    }
+
+    // ------------------------------------------------------------------------
+    // Overridden methods
+    // ------------------------------------------------------------------------
+
+    @Override
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
+        super.visit(Opcodes.V1_2, access, name, null, superName, interfaces);
+        int index = name.lastIndexOf('/');
+        if (index > 0) {
+            pkgName = name.substring(0, index);
+        } else {
+            pkgName = "";
+        }
+        clsName = name;
+        isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
+    }
+
+    @Override
+    public void visitSource(final String source, final String debug) {
+        // remove debug info
+    }
+
+    @Override
+    public void visitOuterClass(final String owner, final String name,
+            final String desc) {
+        // remove debug info
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        // remove annotations
+        return null;
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        // remove annotations
+        return null;
+    }
+
+    @Override
+    public void visitAttribute(final Attribute attr) {
+        // remove non standard attributes
+    }
+
+    @Override
+    public void visitInnerClass(final String name, final String outerName,
+            final String innerName, final int access) {
+        // remove debug info
+    }
+
+    @Override
+    public FieldVisitor visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
+        String s = remapper.mapFieldName(className, name, desc);
+        if ("-".equals(s)) {
+            return null;
+        }
+        if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
+            if ((access & Opcodes.ACC_FINAL) != 0
+                    && (access & Opcodes.ACC_STATIC) != 0 && desc.length() == 1) {
+                return null;
+            }
+            if ("org/objectweb/asm".equals(pkgName) && s.equals(name)) {
+                System.out.println("INFO: " + clsName + "." + s
+                        + " could be renamed");
+            }
+            super.visitField(access, name, desc, null, value);
+        } else {
+            if (!s.equals(name)) {
+                throw new RuntimeException("The public or protected field "
+                        + className + '.' + name + " must not be renamed.");
+            }
+            super.visitField(access, name, desc, null, value);
+        }
+        return null; // remove debug info
+    }
+
+    @Override
+    public MethodVisitor visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        String s = remapper.mapMethodName(className, name, desc);
+        if ("-".equals(s)) {
+            return null;
+        }
+        if (name.equals("<clinit>") && !isInterface) {
+            hasClinitMethod = true;
+            MethodVisitor mv = super.visitMethod(access, name, desc, null,
+                    exceptions);
+            return new MethodVisitor(Opcodes.ASM5, mv) {
+                @Override
+                public void visitCode() {
+                    super.visitCode();
+                    mv.visitMethodInsn(Opcodes.INVOKESTATIC, clsName,
+                            "_clinit_", "()V", false);
+                }
+            };
+        }
+
+        if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
+            if ("org/objectweb/asm".equals(pkgName) && !name.startsWith("<")
+                    && s.equals(name)) {
+                System.out.println("INFO: " + clsName + "." + s
+                        + " could be renamed");
+            }
+            return super.visitMethod(access, name, desc, null, exceptions);
+        } else {
+            if (!s.equals(name)) {
+                throw new RuntimeException("The public or protected method "
+                        + className + '.' + name + desc
+                        + " must not be renamed.");
+            }
+            return super.visitMethod(access, name, desc, null, exceptions);
+        }
+    }
+
+    @Override
+    protected MethodVisitor createRemappingMethodAdapter(int access,
+            String newDesc, MethodVisitor mv) {
+        return new MethodOptimizer(this, access, newDesc, mv, remapper);
+    }
+
+    @Override
+    public void visitEnd() {
+        if (syntheticClassFields.isEmpty()) {
+            if (hasClinitMethod) {
+                MethodVisitor mv = cv.visitMethod(Opcodes.ACC_STATIC
+                        | Opcodes.ACC_SYNTHETIC, "_clinit_", "()V", null, null);
+                mv.visitCode();
+                mv.visitInsn(Opcodes.RETURN);
+                mv.visitMaxs(0, 0);
+                mv.visitEnd();
+            }
+        } else {
+            MethodVisitor mv = cv.visitMethod(Opcodes.ACC_STATIC
+                    | Opcodes.ACC_SYNTHETIC, "class$",
+                    "(Ljava/lang/String;)Ljava/lang/Class;", null, null);
+            mv.visitCode();
+            Label l0 = new Label();
+            Label l1 = new Label();
+            Label l2 = new Label();
+            mv.visitTryCatchBlock(l0, l1, l2,
+                    "java/lang/ClassNotFoundException");
+            mv.visitLabel(l0);
+            mv.visitVarInsn(Opcodes.ALOAD, 0);
+            mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class",
+                    "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false);
+            mv.visitLabel(l1);
+            mv.visitInsn(Opcodes.ARETURN);
+            mv.visitLabel(l2);
+            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
+                    "java/lang/ClassNotFoundException", "getMessage",
+                    "()Ljava/lang/String;", false);
+            mv.visitVarInsn(Opcodes.ASTORE, 1);
+            mv.visitTypeInsn(Opcodes.NEW, "java/lang/NoClassDefFoundError");
+            mv.visitInsn(Opcodes.DUP);
+            mv.visitVarInsn(Opcodes.ALOAD, 1);
+            mv.visitMethodInsn(Opcodes.INVOKESPECIAL,
+                    "java/lang/NoClassDefFoundError", "<init>",
+                    "(Ljava/lang/String;)V", false);
+            mv.visitInsn(Opcodes.ATHROW);
+            mv.visitMaxs(3, 2);
+            mv.visitEnd();
+
+            if (hasClinitMethod) {
+                mv = cv.visitMethod(Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE,
+                        "_clinit_", "()V", null, null);
+            } else {
+                mv = cv.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V",
+                        null, null);
+            }
+            for (String ldcName : syntheticClassFields) {
+                String fieldName = "class$" + ldcName.replace('/', '$');
+                mv.visitLdcInsn(ldcName.replace('/', '.'));
+                mv.visitMethodInsn(Opcodes.INVOKESTATIC, clsName, "class$",
+                        "(Ljava/lang/String;)Ljava/lang/Class;", false);
+                mv.visitFieldInsn(Opcodes.PUTSTATIC, clsName, fieldName,
+                        "Ljava/lang/Class;");
+            }
+            mv.visitInsn(Opcodes.RETURN);
+            mv.visitMaxs(1, 0);
+            mv.visitEnd();
+        }
+        super.visitEnd();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Constant.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Constant.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Constant.java
new file mode 100644
index 0000000..9c1f306
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Constant.java
@@ -0,0 +1,323 @@
+/***
+ * 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.optimizer;
+
+import java.util.Arrays;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassWriter;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+
+/**
+ * A constant pool item.
+ * 
+ * @author Eric Bruneton
+ */
+class Constant {
+
+    /**
+     * Type of this constant pool item. A single class is used to represent all
+     * constant pool item types, in order to minimize the bytecode size of this
+     * package. The value of this field is I, J, F, D, S, s, C, T, G, M, N, y,
+     * t, [h..p] (for Constant Integer, Long, Float, Double, STR, UTF8, Class,
+     * NameType, Fieldref, Methodref, InterfaceMethodref, InvokeDynamic,
+     * MethodType and MethodHandle constant pool items respectively).
+     * 
+     * The 9 variable of MethodHandle constants are stored between h and p.
+     */
+    char type;
+
+    /**
+     * Value of this item, for an integer item.
+     */
+    int intVal;
+
+    /**
+     * Value of this item, for a long item.
+     */
+    long longVal;
+
+    /**
+     * Value of this item, for a float item.
+     */
+    float floatVal;
+
+    /**
+     * Value of this item, for a double item.
+     */
+    double doubleVal;
+
+    /**
+     * First part of the value of this item, for items that do not hold a
+     * primitive value.
+     */
+    String strVal1;
+
+    /**
+     * Second part of the value of this item, for items that do not hold a
+     * primitive value.
+     */
+    String strVal2;
+
+    /**
+     * Third part of the value of this item, for items that do not hold a
+     * primitive value.
+     */
+    Object objVal3;
+
+    /**
+     * InvokeDynamic's constant values.
+     */
+    Object[] objVals;
+
+    /**
+     * The hash code value of this constant pool item.
+     */
+    int hashCode;
+
+    Constant() {
+    }
+
+    Constant(final Constant i) {
+        type = i.type;
+        intVal = i.intVal;
+        longVal = i.longVal;
+        floatVal = i.floatVal;
+        doubleVal = i.doubleVal;
+        strVal1 = i.strVal1;
+        strVal2 = i.strVal2;
+        objVal3 = i.objVal3;
+        objVals = i.objVals;
+        hashCode = i.hashCode;
+    }
+
+    /**
+     * Sets this item to an integer item.
+     * 
+     * @param intVal
+     *            the value of this item.
+     */
+    void set(final int intVal) {
+        this.type = 'I';
+        this.intVal = intVal;
+        this.hashCode = 0x7FFFFFFF & (type + intVal);
+    }
+
+    /**
+     * Sets this item to a long item.
+     * 
+     * @param longVal
+     *            the value of this item.
+     */
+    void set(final long longVal) {
+        this.type = 'J';
+        this.longVal = longVal;
+        this.hashCode = 0x7FFFFFFF & (type + (int) longVal);
+    }
+
+    /**
+     * Sets this item to a float item.
+     * 
+     * @param floatVal
+     *            the value of this item.
+     */
+    void set(final float floatVal) {
+        this.type = 'F';
+        this.floatVal = floatVal;
+        this.hashCode = 0x7FFFFFFF & (type + (int) floatVal);
+    }
+
+    /**
+     * Sets this item to a double item.
+     * 
+     * @param doubleVal
+     *            the value of this item.
+     */
+    void set(final double doubleVal) {
+        this.type = 'D';
+        this.doubleVal = doubleVal;
+        this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal);
+    }
+
+    /**
+     * Sets this item to an item that do not hold a primitive value.
+     * 
+     * @param type
+     *            the type of this item.
+     * @param strVal1
+     *            first part of the value of this item.
+     * @param strVal2
+     *            second part of the value of this item.
+     * @param strVal3
+     *            third part of the value of this item.
+     */
+    void set(final char type, final String strVal1, final String strVal2,
+            final String strVal3) {
+        this.type = type;
+        this.strVal1 = strVal1;
+        this.strVal2 = strVal2;
+        this.objVal3 = strVal3;
+        switch (type) {
+        case 's':
+        case 'S':
+        case 'C':
+        case 't':
+            hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
+            return;
+        case 'T':
+            hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+                    * strVal2.hashCode());
+            return;
+            // case 'G':
+            // case 'M':
+            // case 'N':
+            // case 'h' ... 'p':
+        default:
+            hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+                    * strVal2.hashCode() * strVal3.hashCode());
+        }
+    }
+
+    /**
+     * Set this item to an InvokeDynamic item.
+     * 
+     * @param name
+     *            invokedynamic's name.
+     * @param desc
+     *            invokedynamic's descriptor.
+     * @param bsm
+     *            bootstrap method.
+     * @param bsmArgs
+     *            bootstrap method constant arguments.
+     */
+    void set(final String name, final String desc, final Handle bsm,
+            final Object[] bsmArgs) {
+        this.type = 'y';
+        this.strVal1 = name;
+        this.strVal2 = desc;
+        this.objVal3 = bsm;
+        this.objVals = bsmArgs;
+
+        int hashCode = 'y' + name.hashCode() * desc.hashCode() * bsm.hashCode();
+        for (int i = 0; i < bsmArgs.length; i++) {
+            hashCode *= bsmArgs[i].hashCode();
+        }
+        this.hashCode = 0x7FFFFFFF & hashCode;
+    }
+
+    void write(final ClassWriter cw) {
+        switch (type) {
+        case 'I':
+            cw.newConst(new Integer(intVal));
+            break;
+        case 'J':
+            cw.newConst(new Long(longVal));
+            break;
+        case 'F':
+            cw.newConst(new Float(floatVal));
+            break;
+        case 'D':
+            cw.newConst(new Double(doubleVal));
+            break;
+        case 'S':
+            cw.newConst(strVal1);
+            break;
+        case 's':
+            cw.newUTF8(strVal1);
+            break;
+        case 'C':
+            cw.newClass(strVal1);
+            break;
+        case 'T':
+            cw.newNameType(strVal1, strVal2);
+            break;
+        case 'G':
+            cw.newField(strVal1, strVal2, (String) objVal3);
+            break;
+        case 'M':
+            cw.newMethod(strVal1, strVal2, (String) objVal3, false);
+            break;
+        case 'N':
+            cw.newMethod(strVal1, strVal2, (String) objVal3, true);
+            break;
+        case 'y':
+            cw.newInvokeDynamic(strVal1, strVal2, (Handle) objVal3, objVals);
+            break;
+        case 't':
+            cw.newMethodType(strVal1);
+            break;
+        default: // 'h' ... 'p': handle
+            cw.newHandle(type - 'h' + 1, strVal1, strVal2, (String) objVal3);
+        }
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (!(o instanceof Constant)) {
+            return false;
+        }
+        Constant c = (Constant) o;
+        if (c.type == type) {
+            switch (type) {
+            case 'I':
+                return c.intVal == intVal;
+            case 'J':
+                return c.longVal == longVal;
+            case 'F':
+                return Float.compare(c.floatVal, floatVal) == 0;
+            case 'D':
+                return Double.compare(c.doubleVal, doubleVal) == 0;
+            case 's':
+            case 'S':
+            case 'C':
+            case 't':
+                return c.strVal1.equals(strVal1);
+            case 'T':
+                return c.strVal1.equals(strVal1) && c.strVal2.equals(strVal2);
+            case 'y':
+                return c.strVal1.equals(strVal1) && c.strVal2.equals(strVal2)
+                        && c.objVal3.equals(objVal3)
+                        && Arrays.equals(c.objVals, objVals);
+                // case 'G':
+                // case 'M':
+                // case 'N':
+                // case 'h' ... 'p':
+            default:
+                return c.strVal1.equals(strVal1) && c.strVal2.equals(strVal2)
+                        && c.objVal3.equals(objVal3);
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return hashCode;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ConstantPool.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ConstantPool.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ConstantPool.java
new file mode 100644
index 0000000..1901387
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ConstantPool.java
@@ -0,0 +1,249 @@
+/***
+ * 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.optimizer;
+
+import java.util.HashMap;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A constant pool.
+ * 
+ * @author Eric Bruneton
+ */
+public class ConstantPool extends HashMap<Constant, Constant> {
+
+    private final Constant key1 = new Constant();
+
+    private final Constant key2 = new Constant();
+
+    private final Constant key3 = new Constant();
+
+    private final Constant key4 = new Constant();
+
+    private final Constant key5 = new Constant();
+
+    public Constant newInteger(final int value) {
+        key1.set(value);
+        Constant result = get(key1);
+        if (result == null) {
+            result = new Constant(key1);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newFloat(final float value) {
+        key1.set(value);
+        Constant result = get(key1);
+        if (result == null) {
+            result = new Constant(key1);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newLong(final long value) {
+        key1.set(value);
+        Constant result = get(key1);
+        if (result == null) {
+            result = new Constant(key1);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newDouble(final double value) {
+        key1.set(value);
+        Constant result = get(key1);
+        if (result == null) {
+            result = new Constant(key1);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newUTF8(final String value) {
+        key1.set('s', value, null, null);
+        Constant result = get(key1);
+        if (result == null) {
+            result = new Constant(key1);
+            put(result);
+        }
+        return result;
+    }
+
+    private Constant newString(final String value) {
+        key2.set('S', value, null, null);
+        Constant result = get(key2);
+        if (result == null) {
+            newUTF8(value);
+            result = new Constant(key2);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newClass(final String value) {
+        key2.set('C', value, null, null);
+        Constant result = get(key2);
+        if (result == null) {
+            newUTF8(value);
+            result = new Constant(key2);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newMethodType(final String methodDescriptor) {
+        key2.set('t', methodDescriptor, null, null);
+        Constant result = get(key2);
+        if (result == null) {
+            newUTF8(methodDescriptor);
+            result = new Constant(key2);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newHandle(final int tag, final String owner,
+            final String name, final String desc) {
+        key4.set((char) ('h' - 1 + tag), owner, name, desc);
+        Constant result = get(key4);
+        if (result == null) {
+            if (tag <= Opcodes.H_PUTSTATIC) {
+                newField(owner, name, desc);
+            } else {
+                newMethod(owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE);
+            }
+            result = new Constant(key4);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newConst(final Object cst) {
+        if (cst instanceof Integer) {
+            int val = ((Integer) cst).intValue();
+            return newInteger(val);
+        } else if (cst instanceof Float) {
+            float val = ((Float) cst).floatValue();
+            return newFloat(val);
+        } else if (cst instanceof Long) {
+            long val = ((Long) cst).longValue();
+            return newLong(val);
+        } else if (cst instanceof Double) {
+            double val = ((Double) cst).doubleValue();
+            return newDouble(val);
+        } else if (cst instanceof String) {
+            return newString((String) cst);
+        } else if (cst instanceof Type) {
+            Type t = (Type) cst;
+            int s = t.getSort();
+            if (s == Type.OBJECT) {
+                return newClass(t.getInternalName());
+            } else if (s == Type.METHOD) {
+                return newMethodType(t.getDescriptor());
+            } else { // s == primitive type or array
+                return newClass(t.getDescriptor());
+            }
+        } else if (cst instanceof Handle) {
+            Handle h = (Handle) cst;
+            return newHandle(h.getTag(), h.getOwner(), h.getName(), h.getDesc());
+        } else {
+            throw new IllegalArgumentException("value " + cst);
+        }
+    }
+
+    public Constant newField(final String owner, final String name,
+            final String desc) {
+        key3.set('G', owner, name, desc);
+        Constant result = get(key3);
+        if (result == null) {
+            newClass(owner);
+            newNameType(name, desc);
+            result = new Constant(key3);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newMethod(final String owner, final String name,
+            final String desc, final boolean itf) {
+        key3.set(itf ? 'N' : 'M', owner, name, desc);
+        Constant result = get(key3);
+        if (result == null) {
+            newClass(owner);
+            newNameType(name, desc);
+            result = new Constant(key3);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newInvokeDynamic(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        key5.set(name, desc, bsm, bsmArgs);
+        Constant result = get(key5);
+        if (result == null) {
+            newNameType(name, desc);
+            newHandle(bsm.getTag(), bsm.getOwner(), bsm.getName(),
+                    bsm.getDesc());
+            for (int i = 0; i < bsmArgs.length; i++) {
+                newConst(bsmArgs[i]);
+            }
+            result = new Constant(key5);
+            put(result);
+        }
+        return result;
+    }
+
+    public Constant newNameType(final String name, final String desc) {
+        key2.set('T', name, desc, null);
+        Constant result = get(key2);
+        if (result == null) {
+            newUTF8(name);
+            newUTF8(desc);
+            result = new Constant(key2);
+            put(result);
+        }
+        return result;
+    }
+
+    private Constant get(final Constant key) {
+        return get((Object) key);
+    }
+
+    private void put(final Constant cst) {
+        put(cst, cst);
+    }
+}
\ 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/optimizer/FieldConstantsCollector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/FieldConstantsCollector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/FieldConstantsCollector.java
new file mode 100644
index 0000000..63ca654
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/FieldConstantsCollector.java
@@ -0,0 +1,89 @@
+/***
+ * 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.optimizer;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A {@link FieldVisitor} that collects the {@link Constant}s of the fields it
+ * visits.
+ * 
+ * @author Eric Bruneton
+ */
+public class FieldConstantsCollector extends FieldVisitor {
+
+    private final ConstantPool cp;
+
+    public FieldConstantsCollector(final FieldVisitor fv, final ConstantPool cp) {
+        super(Opcodes.ASM5, fv);
+        this.cp = cp;
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleAnnotations");
+        }
+        return new AnnotationConstantsCollector(fv.visitAnnotation(desc,
+                visible), cp);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleTypeAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+        }
+        return new AnnotationConstantsCollector(fv.visitAnnotation(desc,
+                visible), cp);
+    }
+
+    @Override
+    public void visitAttribute(final Attribute attr) {
+        // can do nothing
+        fv.visitAttribute(attr);
+    }
+
+    @Override
+    public void visitEnd() {
+        fv.visitEnd();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/JarOptimizer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/JarOptimizer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/JarOptimizer.java
new file mode 100644
index 0000000..e7d93cf
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/JarOptimizer.java
@@ -0,0 +1,235 @@
+/***
+ * 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.optimizer;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
+/**
+ * A Jar file optimizer.
+ * 
+ * @author Eric Bruneton
+ */
+public class JarOptimizer {
+
+    static final Set<String> API = new HashSet<String>();
+    static final Map<String, String> HIERARCHY = new HashMap<String, String>();
+    static boolean nodebug = false;
+
+    public static void main(final String[] args) throws IOException {
+        File f = new File(args[0]);
+        InputStream is = new GZIPInputStream(new FileInputStream(f));
+        BufferedReader lnr = new LineNumberReader(new InputStreamReader(is));
+        while (true) {
+            String line = lnr.readLine();
+            if (line != null) {
+                if (line.startsWith("class")) {
+                    String c = line.substring(6, line.lastIndexOf(' '));
+                    String sc = line.substring(line.lastIndexOf(' ') + 1);
+                    HIERARCHY.put(c, sc);
+                } else {
+                    API.add(line);
+                }
+            } else {
+                break;
+            }
+        }
+
+        int argIndex = 1;
+        if (args[argIndex].equals("-nodebug")) {
+            nodebug = true;
+            argIndex++;
+        }
+
+        optimize(new File(args[argIndex]));
+    }
+
+    static void optimize(final File f) throws IOException {
+        if (nodebug && f.getName().contains("debug")) {
+            return;
+        }
+
+        if (f.isDirectory()) {
+            File[] files = f.listFiles();
+            for (int i = 0; i < files.length; ++i) {
+                optimize(files[i]);
+            }
+        } else if (f.getName().endsWith(".jar")) {
+            File g = new File(f.getParentFile(), f.getName() + ".new");
+            ZipFile zf = new ZipFile(f);
+            ZipOutputStream out = new ZipOutputStream(new FileOutputStream(g));
+            Enumeration<? extends ZipEntry> e = zf.entries();
+            byte[] buf = new byte[10000];
+            while (e.hasMoreElements()) {
+                ZipEntry ze = e.nextElement();
+                if (ze.isDirectory()) {
+                    out.putNextEntry(ze);
+                    continue;
+                }
+                out.putNextEntry(ze);
+                if (ze.getName().endsWith(".class")) {
+                    ClassReader cr = new ClassReader(zf.getInputStream(ze));
+                    // cr.accept(new ClassDump(), 0);
+                    cr.accept(new ClassVerifier(), 0);
+                }
+                InputStream is = zf.getInputStream(ze);
+                int n;
+                do {
+                    n = is.read(buf, 0, buf.length);
+                    if (n != -1) {
+                        out.write(buf, 0, n);
+                    }
+                } while (n != -1);
+                out.closeEntry();
+            }
+            out.close();
+            zf.close();
+            if (!f.delete()) {
+                throw new IOException("Cannot delete file " + f);
+            }
+            if (!g.renameTo(f)) {
+                throw new IOException("Cannot rename file " + g);
+            }
+        }
+    }
+
+    static class ClassDump extends ClassVisitor {
+
+        String owner;
+
+        public ClassDump() {
+            super(Opcodes.ASM5);
+        }
+
+        @Override
+        public void visit(final int version, final int access,
+                final String name, final String signature,
+                final String superName, final String[] interfaces) {
+            owner = name;
+            if (owner.startsWith("java/")) {
+                System.out.println("class " + name + ' ' + superName);
+            }
+        }
+
+        @Override
+        public FieldVisitor visitField(final int access, final String name,
+                final String desc, final String signature, final Object value) {
+            if (owner.startsWith("java/")) {
+                System.out.println(owner + ' ' + name);
+            }
+            return null;
+        }
+
+        @Override
+        public MethodVisitor visitMethod(final int access, final String name,
+                final String desc, final String signature,
+                final String[] exceptions) {
+            if (owner.startsWith("java/")) {
+                System.out.println(owner + ' ' + name + desc);
+            }
+            return null;
+        }
+    }
+
+    static class ClassVerifier extends ClassVisitor {
+
+        String owner;
+
+        String method;
+
+        public ClassVerifier() {
+            super(Opcodes.ASM5);
+        }
+
+        @Override
+        public void visit(final int version, final int access,
+                final String name, final String signature,
+                final String superName, final String[] interfaces) {
+            owner = name;
+        }
+
+        @Override
+        public MethodVisitor visitMethod(final int access, final String name,
+                final String desc, final String signature,
+                final String[] exceptions) {
+            method = name + desc;
+            return new MethodVisitor(Opcodes.ASM5) {
+                @Override
+                public void visitFieldInsn(final int opcode,
+                        final String owner, final String name, final String desc) {
+                    check(owner, name);
+                }
+
+                @Override
+                public void visitMethodInsn(final int opcode,
+                        final String owner, final String name,
+                        final String desc, final boolean itf) {
+                    check(owner, name + desc);
+                }
+            };
+        }
+
+        void check(String owner, String member) {
+            if (owner.startsWith("java/")) {
+                String o = owner;
+                while (o != null) {
+                    if (API.contains(o + ' ' + member)) {
+                        return;
+                    }
+                    o = HIERARCHY.get(o);
+                }
+                System.out.println("WARNING: " + owner + ' ' + member
+                        + " called in " + this.owner + ' ' + method
+                        + " is not defined in JDK 1.3 API");
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodConstantsCollector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodConstantsCollector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodConstantsCollector.java
new file mode 100644
index 0000000..54b3519
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodConstantsCollector.java
@@ -0,0 +1,224 @@
+/***
+ * 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.optimizer;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+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.TypePath;
+
+/**
+ * An {@link MethodVisitor} that collects the {@link Constant}s of the methods
+ * it visits.
+ * 
+ * @author Eric Bruneton
+ */
+public class MethodConstantsCollector extends MethodVisitor {
+
+    private final ConstantPool cp;
+
+    public MethodConstantsCollector(final MethodVisitor mv,
+            final ConstantPool cp) {
+        super(Opcodes.ASM5, mv);
+        this.cp = cp;
+    }
+
+    @Override
+    public void visitParameter(String name, int access) {
+        cp.newUTF8("MethodParameters");
+        if (name != null) {
+            cp.newUTF8(name);
+        }
+        mv.visitParameter(name, access);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotationDefault() {
+        cp.newUTF8("AnnotationDefault");
+        return new AnnotationConstantsCollector(mv.visitAnnotationDefault(), cp);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleAnnotations");
+        }
+        return new AnnotationConstantsCollector(mv.visitAnnotation(desc,
+                visible), cp);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleTypeAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+        }
+        return new AnnotationConstantsCollector(mv.visitAnnotation(desc,
+                visible), cp);
+    }
+
+    @Override
+    public AnnotationVisitor visitParameterAnnotation(final int parameter,
+            final String desc, final boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleParameterAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleParameterAnnotations");
+        }
+        return new AnnotationConstantsCollector(mv.visitParameterAnnotation(
+                parameter, desc, visible), cp);
+    }
+
+    @Override
+    public void visitTypeInsn(final int opcode, final String type) {
+        cp.newClass(type);
+        mv.visitTypeInsn(opcode, type);
+    }
+
+    @Override
+    public void visitFieldInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        cp.newField(owner, name, desc);
+        mv.visitFieldInsn(opcode, owner, name, desc);
+    }
+
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        cp.newMethod(owner, name, desc, itf);
+        mv.visitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        cp.newInvokeDynamic(name, desc, bsm, bsmArgs);
+        mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+    }
+
+    @Override
+    public void visitLdcInsn(final Object cst) {
+        cp.newConst(cst);
+        mv.visitLdcInsn(cst);
+    }
+
+    @Override
+    public void visitMultiANewArrayInsn(final String desc, final int dims) {
+        cp.newClass(desc);
+        mv.visitMultiANewArrayInsn(desc, dims);
+    }
+
+    @Override
+    public AnnotationVisitor visitInsnAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleTypeAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+        }
+        return new AnnotationConstantsCollector(mv.visitInsnAnnotation(typeRef,
+                typePath, desc, visible), cp);
+    }
+
+    @Override
+    public void visitTryCatchBlock(final Label start, final Label end,
+            final Label handler, final String type) {
+        if (type != null) {
+            cp.newClass(type);
+        }
+        mv.visitTryCatchBlock(start, end, handler, type);
+    }
+
+    @Override
+    public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleTypeAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+        }
+        return new AnnotationConstantsCollector(mv.visitTryCatchAnnotation(
+                typeRef, typePath, desc, visible), cp);
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
+        if (signature != null) {
+            cp.newUTF8("LocalVariableTypeTable");
+            cp.newUTF8(name);
+            cp.newUTF8(signature);
+        }
+        cp.newUTF8("LocalVariableTable");
+        cp.newUTF8(name);
+        cp.newUTF8(desc);
+        mv.visitLocalVariable(name, desc, signature, start, end, index);
+    }
+
+    @Override
+    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+            TypePath typePath, Label[] start, Label[] end, int[] index,
+            String desc, boolean visible) {
+        cp.newUTF8(desc);
+        if (visible) {
+            cp.newUTF8("RuntimeVisibleTypeAnnotations");
+        } else {
+            cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+        }
+        return new AnnotationConstantsCollector(
+                mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
+                        index, desc, visible), cp);
+    }
+
+    @Override
+    public void visitLineNumber(final int line, final Label start) {
+        cp.newUTF8("LineNumberTable");
+        mv.visitLineNumber(line, start);
+    }
+
+    @Override
+    public void visitMaxs(final int maxStack, final int maxLocals) {
+        cp.newUTF8("Code");
+        mv.visitMaxs(maxStack, maxLocals);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.java
new file mode 100644
index 0000000..adad6b4
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.java
@@ -0,0 +1,136 @@
+/***
+ * 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.optimizer;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+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;
+import org.apache.tapestry5.internal.plastic.asm.commons.Remapper;
+import org.apache.tapestry5.internal.plastic.asm.commons.RemappingMethodAdapter;
+
+/**
+ * A {@link MethodVisitor} that renames fields and methods, and removes debug
+ * info.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class MethodOptimizer extends RemappingMethodAdapter implements Opcodes {
+
+    private final ClassOptimizer classOptimizer;
+
+    public MethodOptimizer(ClassOptimizer classOptimizer, int access,
+            String desc, MethodVisitor mv, Remapper remapper) {
+        super(Opcodes.ASM5, access, desc, mv, remapper);
+        this.classOptimizer = classOptimizer;
+    }
+
+    // ------------------------------------------------------------------------
+    // Overridden methods
+    // ------------------------------------------------------------------------
+
+    @Override
+    public void visitParameter(String name, int access) {
+        // remove parameter info
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotationDefault() {
+        // remove annotations
+        return null;
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        // remove annotations
+        return null;
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        return null;
+    }
+
+    @Override
+    public AnnotationVisitor visitParameterAnnotation(final int parameter,
+            final String desc, final boolean visible) {
+        // remove annotations
+        return null;
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
+        // remove debug info
+    }
+
+    @Override
+    public void visitLineNumber(final int line, final Label start) {
+        // remove debug info
+    }
+
+    @Override
+    public void visitFrame(int type, int local, Object[] local2, int stack,
+            Object[] stack2) {
+        // remove frame info
+    }
+
+    @Override
+    public void visitAttribute(Attribute attr) {
+        // remove non standard attributes
+    }
+
+    @Override
+    public void visitLdcInsn(Object cst) {
+        if (!(cst instanceof Type)) {
+            super.visitLdcInsn(cst);
+            return;
+        }
+
+        // transform Foo.class for 1.2 compatibility
+        String ldcName = ((Type) cst).getInternalName();
+        String fieldName = "class$" + ldcName.replace('/', '$');
+        if (!classOptimizer.syntheticClassFields.contains(ldcName)) {
+            classOptimizer.syntheticClassFields.add(ldcName);
+            FieldVisitor fv = classOptimizer.syntheticFieldVisitor(ACC_STATIC
+                    | ACC_SYNTHETIC, fieldName, "Ljava/lang/Class;");
+            fv.visitEnd();
+        }
+
+        String clsName = classOptimizer.clsName;
+        mv.visitFieldInsn(GETSTATIC, clsName, fieldName, "Ljava/lang/Class;");
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/NameMapping.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/NameMapping.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/NameMapping.java
new file mode 100644
index 0000000..70d74f7
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/NameMapping.java
@@ -0,0 +1,114 @@
+/***
+ * 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.optimizer;
+
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A MAPPING from names to names, used to rename classes, fields and methods.
+ * 
+ * @author Eric Bruneton
+ */
+public class NameMapping {
+
+    public final Properties mapping;
+
+    public final Set<Object> unused;
+
+    public NameMapping(final String file) throws IOException {
+        mapping = new Properties();
+        InputStream is = null;
+        try {
+            is = new BufferedInputStream(new FileInputStream(file));
+            mapping.load(is);
+            unused = new HashSet<Object>(mapping.keySet());
+        } finally {
+            if (is != null) {
+                is.close();
+            }
+        }
+    }
+
+    public String map(final String name) {
+        String s = (String) mapping.get(name);
+        if (s == null) {
+            int p = name.indexOf('.');
+            if (p == -1) {
+                s = name;
+            } else {
+                int q = name.indexOf('(');
+                if (q == -1) {
+                    s = name.substring(p + 1);
+                } else {
+                    s = name.substring(p + 1, q);
+                }
+            }
+        } else {
+            unused.remove(name);
+        }
+        return s;
+    }
+
+    public String fix(final String desc) {
+        if (desc.startsWith("(")) {
+            Type[] arguments = Type.getArgumentTypes(desc);
+            Type result = Type.getReturnType(desc);
+            for (int i = 0; i < arguments.length; ++i) {
+                arguments[i] = fix(arguments[i]);
+            }
+            result = fix(result);
+            return Type.getMethodDescriptor(result, arguments);
+        } else {
+            return fix(Type.getType(desc)).getDescriptor();
+        }
+    }
+
+    private Type fix(final Type t) {
+        if (t.getSort() == Type.OBJECT) {
+            return Type.getObjectType(map(t.getInternalName()));
+        } else if (t.getSort() == Type.ARRAY) {
+            String s = fix(t.getElementType()).getDescriptor();
+            for (int i = 0; i < t.getDimensions(); ++i) {
+                s = '[' + s;
+            }
+            return Type.getType(s);
+        } else {
+            return t;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Shrinker.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Shrinker.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Shrinker.java
new file mode 100644
index 0000000..e20cf5c
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Shrinker.java
@@ -0,0 +1,283 @@
+/***
+ * 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.optimizer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.ClassWriter;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.commons.Remapper;
+import org.apache.tapestry5.internal.plastic.asm.commons.SimpleRemapper;
+
+/**
+ * A class file shrinker utility.
+ * 
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class Shrinker {
+
+    static final HashMap<String, String> MAPPING = new HashMap<String, String>();
+
+    public static void main(final String[] args) throws IOException {
+        Properties properties = new Properties();
+        int n = args.length - 1;
+        for (int i = 0; i < n - 1; ++i) {
+            properties.load(new FileInputStream(args[i]));
+        }
+
+        for (Map.Entry<Object, Object> entry : properties.entrySet()) {
+            MAPPING.put((String) entry.getKey(), (String) entry.getValue());
+        }
+
+        final Set<String> unused = new HashSet<String>(MAPPING.keySet());
+
+        File f = new File(args[n - 1]);
+        File d = new File(args[n]);
+
+        optimize(f, d, new SimpleRemapper(MAPPING) {
+            @Override
+            public String map(String key) {
+                String s = super.map(key);
+                if (s != null) {
+                    unused.remove(key);
+                }
+                return s;
+            }
+        });
+
+        Iterator<String> i = unused.iterator();
+        while (i.hasNext()) {
+            String s = i.next();
+            if (!s.endsWith("/remove")) {
+                System.out.println("INFO: unused mapping " + s);
+            }
+        }
+    }
+
+    static void optimize(final File f, final File d, final Remapper remapper)
+            throws IOException {
+        if (f.isDirectory()) {
+            File[] files = f.listFiles();
+            for (int i = 0; i < files.length; ++i) {
+                optimize(files[i], d, remapper);
+            }
+        } else if (f.getName().endsWith(".class")) {
+            ConstantPool cp = new ConstantPool();
+            ClassReader cr = new ClassReader(new FileInputStream(f));
+            ClassWriter cw = new ClassWriter(0);
+            ClassConstantsCollector ccc = new ClassConstantsCollector(cw, cp);
+            ClassOptimizer co = new ClassOptimizer(ccc, remapper);
+            cr.accept(co, ClassReader.SKIP_DEBUG);
+
+            Set<Constant> constants = new TreeSet<Constant>(
+                    new ConstantComparator());
+            constants.addAll(cp.values());
+
+            cr = new ClassReader(cw.toByteArray());
+            cw = new ClassWriter(0);
+            Iterator<Constant> i = constants.iterator();
+            while (i.hasNext()) {
+                Constant c = i.next();
+                c.write(cw);
+            }
+            cr.accept(cw, ClassReader.SKIP_DEBUG);
+
+            if (MAPPING.get(cr.getClassName() + "/remove") != null) {
+                return;
+            }
+            String n = remapper.mapType(cr.getClassName());
+            File g = new File(d, n + ".class");
+            if (!g.exists() || g.lastModified() < f.lastModified()) {
+                if (!g.getParentFile().exists() && !g.getParentFile().mkdirs()) {
+                    throw new IOException("Cannot create directory "
+                            + g.getParentFile());
+                }
+                OutputStream os = new FileOutputStream(g);
+                try {
+                    os.write(cw.toByteArray());
+                } finally {
+                    os.close();
+                }
+            }
+        }
+    }
+
+    static class ConstantComparator implements Comparator<Constant> {
+
+        public int compare(final Constant c1, final Constant c2) {
+            int d = getSort(c1) - getSort(c2);
+            if (d == 0) {
+                switch (c1.type) {
+                case 'I':
+                    return new Integer(c1.intVal).compareTo(new Integer(
+                            c2.intVal));
+                case 'J':
+                    return new Long(c1.longVal).compareTo(new Long(c2.longVal));
+                case 'F':
+                    return new Float(c1.floatVal).compareTo(new Float(
+                            c2.floatVal));
+                case 'D':
+                    return new Double(c1.doubleVal).compareTo(new Double(
+                            c2.doubleVal));
+                case 's':
+                case 'S':
+                case 'C':
+                case 't':
+                    return c1.strVal1.compareTo(c2.strVal1);
+                case 'T':
+                    d = c1.strVal1.compareTo(c2.strVal1);
+                    if (d == 0) {
+                        d = c1.strVal2.compareTo(c2.strVal2);
+                    }
+                    break;
+                case 'y':
+                    d = c1.strVal1.compareTo(c2.strVal1);
+                    if (d == 0) {
+                        d = c1.strVal2.compareTo(c2.strVal2);
+                        if (d == 0) {
+                            Handle bsm1 = (Handle) c1.objVal3;
+                            Handle bsm2 = (Handle) c2.objVal3;
+                            d = compareHandle(bsm1, bsm2);
+                            if (d == 0) {
+                                d = compareObjects(c1.objVals, c2.objVals);
+                            }
+                        }
+                    }
+                    break;
+
+                default:
+                    d = c1.strVal1.compareTo(c2.strVal1);
+                    if (d == 0) {
+                        d = c1.strVal2.compareTo(c2.strVal2);
+                        if (d == 0) {
+                            d = ((String) c1.objVal3)
+                                    .compareTo((String) c2.objVal3);
+                        }
+                    }
+                }
+            }
+            return d;
+        }
+
+        private static int compareHandle(Handle h1, Handle h2) {
+            int d = h1.getTag() - h2.getTag();
+            if (d == 0) {
+                d = h1.getOwner().compareTo(h2.getOwner());
+                if (d == 0) {
+                    d = h1.getName().compareTo(h2.getName());
+                    if (d == 0) {
+                        d = h1.getDesc().compareTo(h2.getDesc());
+                    }
+                }
+            }
+            return d;
+        }
+
+        private static int compareType(Type mtype1, Type mtype2) {
+            return mtype1.getDescriptor().compareTo(mtype2.getDescriptor());
+        }
+
+        private static int compareObjects(Object[] objVals1, Object[] objVals2) {
+            int length = objVals1.length;
+            int d = length - objVals2.length;
+            if (d == 0) {
+                for (int i = 0; i < length; i++) {
+                    Object objVal1 = objVals1[i];
+                    Object objVal2 = objVals2[i];
+                    d = objVal1.getClass().getName()
+                            .compareTo(objVal2.getClass().getName());
+                    if (d == 0) {
+                        if (objVal1 instanceof Type) {
+                            d = compareType((Type) objVal1, (Type) objVal2);
+                        } else if (objVal1 instanceof Handle) {
+                            d = compareHandle((Handle) objVal1,
+                                    (Handle) objVal2);
+                        } else {
+                            d = ((Comparable) objVal1).compareTo(objVal2);
+                        }
+                    }
+
+                    if (d != 0) {
+                        return d;
+                    }
+                }
+            }
+            return 0;
+        }
+
+        private static int getSort(final Constant c) {
+            switch (c.type) {
+            case 'I':
+                return 0;
+            case 'J':
+                return 1;
+            case 'F':
+                return 2;
+            case 'D':
+                return 3;
+            case 's':
+                return 4;
+            case 'S':
+                return 5;
+            case 'C':
+                return 6;
+            case 'T':
+                return 7;
+            case 'G':
+                return 8;
+            case 'M':
+                return 9;
+            case 'N':
+                return 10;
+            case 'y':
+                return 11;
+            case 't':
+                return 12;
+            default:
+                return 100 + c.type - 'h';
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.2.2_017.txt.gz
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.2.2_017.txt.gz b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.2.2_017.txt.gz
new file mode 100644
index 0000000..39cdf9d
Binary files /dev/null and b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.2.2_017.txt.gz differ

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.3.1_19.txt.gz
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.3.1_19.txt.gz b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.3.1_19.txt.gz
new file mode 100644
index 0000000..a3c7aa6
Binary files /dev/null and b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.3.1_19.txt.gz differ

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-annotations.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-annotations.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-annotations.properties
new file mode 100644
index 0000000..03fec2e
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-annotations.properties
@@ -0,0 +1,53 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+org/objectweb/asm/AnnotationWriter/remove=true
+
+# field mappings
+
+org/objectweb/asm/ClassWriter.anns=-
+org/objectweb/asm/ClassWriter.ianns=-
+
+org/objectweb/asm/FieldWriter.anns=-
+org/objectweb/asm/FieldWriter.ianns=-
+
+org/objectweb/asm/MethodWriter.annd=-
+org/objectweb/asm/MethodWriter.anns=-
+org/objectweb/asm/MethodWriter.ianns=-
+org/objectweb/asm/MethodWriter.panns=-
+org/objectweb/asm/MethodWriter.ipanns=-
+
+# method mappings
+
+org/objectweb/asm/ClassReader.readAnnotationValue(I[CLjava/lang/String;Lorg/objectweb/asm/AnnotationVisitor;)I=-
+org/objectweb/asm/ClassReader.readAnnotationValues(I[CZLorg/objectweb/asm/AnnotationVisitor;)I=-
+org/objectweb/asm/ClassReader.readParameterAnnotations(I[CZLorg/objectweb/asm/MethodVisitor;)V=-


[02/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java
new file mode 100644
index 0000000..6d5715c
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java
@@ -0,0 +1,1044 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * 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.xml;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.Templates;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.ClassWriter;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/**
+ * Processor is a command line tool that can be used for bytecode waving
+ * directed by XSL transformation.
+ * <p>
+ * In order to use a concrete XSLT engine, system property
+ * <tt>javax.xml.transform.TransformerFactory</tt> must be set to one of the
+ * following values.
+ * 
+ * <blockquote>
+ * <table border="1" cellspacing="0" cellpadding="3">
+ * <tr>
+ * <td>jd.xslt</td>
+ * <td>jd.xml.xslt.trax.TransformerFactoryImpl</td>
+ * </tr>
+ * 
+ * <tr>
+ * <td>Saxon</td>
+ * <td>net.sf.saxon.TransformerFactoryImpl</td>
+ * </tr>
+ * 
+ * <tr>
+ * <td>Caucho</td>
+ * <td>com.caucho.xsl.Xsl</td>
+ * </tr>
+ * 
+ * <tr>
+ * <td>Xalan interpeter</td>
+ * <td>org.apache.xalan.processor.TransformerFactory</td>
+ * </tr>
+ * 
+ * <tr>
+ * <td>Xalan xsltc</td>
+ * <td>org.apache.xalan.xsltc.trax.TransformerFactoryImpl</td>
+ * </tr>
+ * </table>
+ * </blockquote>
+ * 
+ * @author Eugene Kuleshov
+ */
+public class Processor {
+
+    public static final int BYTECODE = 1;
+
+    public static final int MULTI_XML = 2;
+
+    public static final int SINGLE_XML = 3;
+
+    private static final String SINGLE_XML_NAME = "classes.xml";
+
+    private final int inRepresentation;
+
+    private final int outRepresentation;
+
+    private final InputStream input;
+
+    private final OutputStream output;
+
+    private final Source xslt;
+
+    private int n = 0;
+
+    public Processor(final int inRepresenation, final int outRepresentation,
+            final InputStream input, final OutputStream output,
+            final Source xslt) {
+        this.inRepresentation = inRepresenation;
+        this.outRepresentation = outRepresentation;
+        this.input = input;
+        this.output = output;
+        this.xslt = xslt;
+    }
+
+    public int process() throws TransformerException, IOException, SAXException {
+        ZipInputStream zis = new ZipInputStream(input);
+        final ZipOutputStream zos = new ZipOutputStream(output);
+        final OutputStreamWriter osw = new OutputStreamWriter(zos);
+
+        Thread.currentThread().setContextClassLoader(
+                getClass().getClassLoader());
+
+        TransformerFactory tf = TransformerFactory.newInstance();
+        if (!tf.getFeature(SAXSource.FEATURE)
+                || !tf.getFeature(SAXResult.FEATURE)) {
+            return 0;
+        }
+
+        SAXTransformerFactory saxtf = (SAXTransformerFactory) tf;
+        Templates templates = null;
+        if (xslt != null) {
+            templates = saxtf.newTemplates(xslt);
+        }
+
+        // configuring outHandlerFactory
+        // ///////////////////////////////////////////////////////
+
+        EntryElement entryElement = getEntryElement(zos);
+
+        ContentHandler outDocHandler = null;
+        switch (outRepresentation) {
+        case BYTECODE:
+            outDocHandler = new OutputSlicingHandler(
+                    new ASMContentHandlerFactory(zos), entryElement, false);
+            break;
+
+        case MULTI_XML:
+            outDocHandler = new OutputSlicingHandler(new SAXWriterFactory(osw,
+                    true), entryElement, true);
+            break;
+
+        case SINGLE_XML:
+            ZipEntry outputEntry = new ZipEntry(SINGLE_XML_NAME);
+            zos.putNextEntry(outputEntry);
+            outDocHandler = new SAXWriter(osw, false);
+            break;
+
+        }
+
+        // configuring inputDocHandlerFactory
+        // /////////////////////////////////////////////////
+        ContentHandler inDocHandler;
+        if (templates == null) {
+            inDocHandler = outDocHandler;
+        } else {
+            inDocHandler = new InputSlicingHandler("class", outDocHandler,
+                    new TransformerHandlerFactory(saxtf, templates,
+                            outDocHandler));
+        }
+        ContentHandlerFactory inDocHandlerFactory = new SubdocumentHandlerFactory(
+                inDocHandler);
+
+        if (inDocHandler != null && inRepresentation != SINGLE_XML) {
+            inDocHandler.startDocument();
+            inDocHandler.startElement("", "classes", "classes",
+                    new AttributesImpl());
+        }
+
+        int i = 0;
+        ZipEntry ze;
+        while ((ze = zis.getNextEntry()) != null) {
+            update(ze.getName(), n++);
+            if (isClassEntry(ze)) {
+                processEntry(zis, ze, inDocHandlerFactory);
+            } else {
+                OutputStream os = entryElement.openEntry(getName(ze));
+                copyEntry(zis, os);
+                entryElement.closeEntry();
+            }
+
+            i++;
+        }
+
+        if (inDocHandler != null && inRepresentation != SINGLE_XML) {
+            inDocHandler.endElement("", "classes", "classes");
+            inDocHandler.endDocument();
+        }
+
+        if (outRepresentation == SINGLE_XML) {
+            zos.closeEntry();
+        }
+        zos.flush();
+        zos.close();
+
+        return i;
+    }
+
+    private void copyEntry(final InputStream is, final OutputStream os)
+            throws IOException {
+        if (outRepresentation == SINGLE_XML) {
+            return;
+        }
+
+        byte[] buff = new byte[2048];
+        int i;
+        while ((i = is.read(buff)) != -1) {
+            os.write(buff, 0, i);
+        }
+    }
+
+    private boolean isClassEntry(final ZipEntry ze) {
+        String name = ze.getName();
+        return inRepresentation == SINGLE_XML && name.equals(SINGLE_XML_NAME)
+                || name.endsWith(".class") || name.endsWith(".class.xml");
+    }
+
+    private void processEntry(final ZipInputStream zis, final ZipEntry ze,
+            final ContentHandlerFactory handlerFactory) {
+        ContentHandler handler = handlerFactory.createContentHandler();
+        try {
+
+            // if (CODE2ASM.equals(command)) { // read bytecode and process it
+            // // with TraceClassVisitor
+            // ClassReader cr = new ClassReader(readEntry(zis, ze));
+            // cr.accept(new TraceClassVisitor(null, new PrintWriter(os)),
+            // false);
+            // }
+
+            boolean singleInputDocument = inRepresentation == SINGLE_XML;
+            if (inRepresentation == BYTECODE) { // read bytecode and process it
+                // with handler
+                ClassReader cr = new ClassReader(readEntry(zis, ze));
+                cr.accept(new SAXClassAdapter(handler, singleInputDocument), 0);
+
+            } else { // read XML and process it with handler
+                XMLReader reader = XMLReaderFactory.createXMLReader();
+                reader.setContentHandler(handler);
+                reader.parse(new InputSource(
+                        singleInputDocument ? (InputStream) new ProtectedInputStream(
+                                zis) : new ByteArrayInputStream(readEntry(zis,
+                                ze))));
+
+            }
+        } catch (Exception ex) {
+            update(ze.getName(), 0);
+            update(ex, 0);
+        }
+    }
+
+    private EntryElement getEntryElement(final ZipOutputStream zos) {
+        if (outRepresentation == SINGLE_XML) {
+            return new SingleDocElement(zos);
+        }
+        return new ZipEntryElement(zos);
+    }
+
+    // private ContentHandlerFactory getHandlerFactory(
+    // OutputStream os,
+    // SAXTransformerFactory saxtf,
+    // Templates templates)
+    // {
+    // ContentHandlerFactory factory = null;
+    // if (templates == null) {
+    // if (outputRepresentation == BYTECODE) { // factory used to write
+    // // bytecode
+    // factory = new ASMContentHandlerFactory(os, computeMax);
+    // } else { // factory used to write XML
+    // factory = new SAXWriterFactory(os, true);
+    // }
+    // } else {
+    // if (outputRepresentation == BYTECODE) { // factory used to transform
+    // // and then write bytecode
+    // factory = new ASMTransformerHandlerFactory(saxtf,
+    // templates,
+    // os,
+    // computeMax);
+    // } else { // factory used to transformand then write XML
+    // factory = new TransformerHandlerFactory(saxtf,
+    // templates,
+    // os,
+    // outputRepresentation == SINGLE_XML);
+    // }
+    // }
+    // return factory;
+    // }
+
+    private String getName(final ZipEntry ze) {
+        String name = ze.getName();
+        if (isClassEntry(ze)) {
+            if (inRepresentation != BYTECODE && outRepresentation == BYTECODE) {
+                name = name.substring(0, name.length() - 4); // .class.xml to
+                // .class
+            } else if (inRepresentation == BYTECODE
+                    && outRepresentation != BYTECODE) {
+                name += ".xml"; // .class to .class.xml
+            }
+            // } else if( CODE2ASM.equals( command)) {
+            // name = name.substring( 0, name.length()-6).concat( ".asm");
+        }
+        return name;
+    }
+
+    private static byte[] readEntry(final InputStream zis, final ZipEntry ze)
+            throws IOException {
+        long size = ze.getSize();
+        if (size > -1) {
+            byte[] buff = new byte[(int) size];
+            int k = 0;
+            int n;
+            while ((n = zis.read(buff, k, buff.length - k)) > 0) {
+                k += n;
+            }
+            return buff;
+        }
+
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        byte[] buff = new byte[4096];
+        int i;
+        while ((i = zis.read(buff)) != -1) {
+            bos.write(buff, 0, i);
+        }
+        return bos.toByteArray();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
+     */
+    protected void update(final Object arg, final int n) {
+        if (arg instanceof Throwable) {
+            ((Throwable) arg).printStackTrace();
+        } else {
+            if (n % 100 == 0) {
+                System.err.println(n + " " + arg);
+            }
+        }
+    }
+
+    public static void main(final String[] args) throws Exception {
+        if (args.length < 2) {
+            showUsage();
+            return;
+        }
+
+        int inRepresentation = getRepresentation(args[0]);
+        int outRepresentation = getRepresentation(args[1]);
+
+        InputStream is = System.in;
+        OutputStream os = new BufferedOutputStream(System.out);
+
+        Source xslt = null;
+        // boolean computeMax = true;
+
+        for (int i = 2; i < args.length; i++) {
+            if ("-in".equals(args[i])) {
+                is = new FileInputStream(args[++i]);
+
+            } else if ("-out".equals(args[i])) {
+                os = new BufferedOutputStream(new FileOutputStream(args[++i]));
+
+            } else if ("-xslt".equals(args[i])) {
+                xslt = new StreamSource(new FileInputStream(args[++i]));
+
+                // } else if( "-computemax".equals( args[ i].toLowerCase())) {
+                // computeMax = true;
+
+            } else {
+                showUsage();
+                return;
+
+            }
+        }
+
+        if (inRepresentation == 0 || outRepresentation == 0) {
+            showUsage();
+            return;
+        }
+
+        Processor m = new Processor(inRepresentation, outRepresentation, is,
+                os, xslt);
+
+        long l1 = System.currentTimeMillis();
+        int n = m.process();
+        long l2 = System.currentTimeMillis();
+        System.err.println(n);
+        System.err.println((l2 - l1) + "ms  " + 1000f * n / (l2 - l1)
+                + " resources/sec");
+    }
+
+    private static int getRepresentation(final String s) {
+        if ("code".equals(s)) {
+            return BYTECODE;
+        } else if ("xml".equals(s)) {
+            return MULTI_XML;
+        } else if ("singlexml".equals(s)) {
+            return SINGLE_XML;
+        }
+        return 0;
+    }
+
+    private static void showUsage() {
+        System.err
+                .println("Usage: Main <in format> <out format> [-in <input jar>] [-out <output jar>] [-xslt <xslt fiel>]");
+        System.err
+                .println("  when -in or -out is omitted sysin and sysout would be used");
+        System.err
+                .println("  <in format> and <out format> - code | xml | singlexml");
+    }
+
+    /**
+     * IputStream wrapper class used to protect input streams from being closed
+     * by some stupid XML parsers.
+     */
+    private static final class ProtectedInputStream extends InputStream {
+        private final InputStream is;
+
+        ProtectedInputStream(final InputStream is) {
+            this.is = is;
+        }
+
+        @Override
+        public final void close() throws IOException {
+        }
+
+        @Override
+        public final int read() throws IOException {
+            return is.read();
+        }
+
+        @Override
+        public final int read(final byte[] b, final int off, final int len)
+                throws IOException {
+            return is.read(b, off, len);
+        }
+
+        @Override
+        public final int available() throws IOException {
+            return is.available();
+        }
+    }
+
+    /**
+     * A {@link ContentHandlerFactory ContentHandlerFactory} is used to create
+     * {@link org.xml.sax.ContentHandler ContentHandler} instances for concrete
+     * context.
+     */
+    private static interface ContentHandlerFactory {
+
+        /**
+         * Creates an instance of the content handler.
+         * 
+         * @return content handler
+         */
+        ContentHandler createContentHandler();
+
+    }
+
+    /**
+     * SAXWriterFactory
+     */
+    private static final class SAXWriterFactory implements
+            ContentHandlerFactory {
+        private final Writer w;
+
+        private final boolean optimizeEmptyElements;
+
+        SAXWriterFactory(final Writer w, final boolean optimizeEmptyElements) {
+            this.w = w;
+            this.optimizeEmptyElements = optimizeEmptyElements;
+        }
+
+        public final ContentHandler createContentHandler() {
+            return new SAXWriter(w, optimizeEmptyElements);
+        }
+
+    }
+
+    /**
+     * ASMContentHandlerFactory
+     */
+    private static final class ASMContentHandlerFactory implements
+            ContentHandlerFactory {
+        final OutputStream os;
+
+        ASMContentHandlerFactory(final OutputStream os) {
+            this.os = os;
+        }
+
+        public final ContentHandler createContentHandler() {
+            final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+            return new ASMContentHandler(cw) {
+                @Override
+                public void endDocument() throws SAXException {
+                    try {
+                        os.write(cw.toByteArray());
+                    } catch (IOException e) {
+                        throw new SAXException(e);
+                    }
+                }
+            };
+        }
+
+    }
+
+    /**
+     * TransformerHandlerFactory
+     */
+    private static final class TransformerHandlerFactory implements
+            ContentHandlerFactory {
+        private SAXTransformerFactory saxtf;
+
+        private final Templates templates;
+
+        private ContentHandler outputHandler;
+
+        TransformerHandlerFactory(final SAXTransformerFactory saxtf,
+                final Templates templates, final ContentHandler outputHandler) {
+            this.saxtf = saxtf;
+            this.templates = templates;
+            this.outputHandler = outputHandler;
+        }
+
+        public final ContentHandler createContentHandler() {
+            try {
+                TransformerHandler handler = saxtf
+                        .newTransformerHandler(templates);
+                handler.setResult(new SAXResult(outputHandler));
+                return handler;
+            } catch (TransformerConfigurationException ex) {
+                throw new RuntimeException(ex.toString());
+            }
+        }
+    }
+
+    /**
+     * SubdocumentHandlerFactory
+     */
+    private static final class SubdocumentHandlerFactory implements
+            ContentHandlerFactory {
+        private final ContentHandler subdocumentHandler;
+
+        SubdocumentHandlerFactory(final ContentHandler subdocumentHandler) {
+            this.subdocumentHandler = subdocumentHandler;
+        }
+
+        public final ContentHandler createContentHandler() {
+            return subdocumentHandler;
+        }
+
+    }
+
+    /**
+     * A {@link org.xml.sax.ContentHandler ContentHandler} and
+     * {@link org.xml.sax.ext.LexicalHandler LexicalHandler} that serializes XML
+     * from SAX 2.0 events into {@link java.io.Writer Writer}.
+     * 
+     * <i><blockquote> This implementation does not support namespaces, entity
+     * definitions (uncluding DTD), CDATA and text elements. </blockquote></i>
+     */
+    private static final class SAXWriter extends DefaultHandler implements
+            LexicalHandler {
+        private static final char[] OFF = "                                                                                                        "
+                .toCharArray();
+
+        private Writer w;
+
+        private final boolean optimizeEmptyElements;
+
+        private boolean openElement = false;
+
+        private int ident = 0;
+
+        /**
+         * Creates <code>SAXWriter</code>.
+         * 
+         * @param w
+         *            writer
+         * @param optimizeEmptyElements
+         *            if set to <code>true</code>, short XML syntax will be used
+         *            for empty elements
+         */
+        SAXWriter(final Writer w, final boolean optimizeEmptyElements) {
+            this.w = w;
+            this.optimizeEmptyElements = optimizeEmptyElements;
+        }
+
+        @Override
+        public final void startElement(final String ns, final String localName,
+                final String qName, final Attributes atts) throws SAXException {
+            try {
+                closeElement();
+
+                writeIdent();
+                w.write('<' + qName);
+                if (atts != null && atts.getLength() > 0) {
+                    writeAttributes(atts);
+                }
+
+                if (optimizeEmptyElements) {
+                    openElement = true;
+                } else {
+                    w.write(">\n");
+                }
+                ident += 2;
+
+            } catch (IOException ex) {
+                throw new SAXException(ex);
+
+            }
+        }
+
+        @Override
+        public final void endElement(final String ns, final String localName,
+                final String qName) throws SAXException {
+            ident -= 2;
+            try {
+                if (openElement) {
+                    w.write("/>\n");
+                    openElement = false;
+                } else {
+                    writeIdent();
+                    w.write("</" + qName + ">\n");
+                }
+
+            } catch (IOException ex) {
+                throw new SAXException(ex);
+
+            }
+        }
+
+        @Override
+        public final void endDocument() throws SAXException {
+            try {
+                w.flush();
+
+            } catch (IOException ex) {
+                throw new SAXException(ex);
+
+            }
+        }
+
+        public final void comment(final char[] ch, final int off, final int len)
+                throws SAXException {
+            try {
+                closeElement();
+
+                writeIdent();
+                w.write("<!-- ");
+                w.write(ch, off, len);
+                w.write(" -->\n");
+
+            } catch (IOException ex) {
+                throw new SAXException(ex);
+
+            }
+        }
+
+        public final void startDTD(final String arg0, final String arg1,
+                final String arg2) throws SAXException {
+        }
+
+        public final void endDTD() throws SAXException {
+        }
+
+        public final void startEntity(final String arg0) throws SAXException {
+        }
+
+        public final void endEntity(final String arg0) throws SAXException {
+        }
+
+        public final void startCDATA() throws SAXException {
+        }
+
+        public final void endCDATA() throws SAXException {
+        }
+
+        private final void writeAttributes(final Attributes atts)
+                throws IOException {
+            StringBuffer sb = new StringBuffer();
+            int len = atts.getLength();
+            for (int i = 0; i < len; i++) {
+                sb.append(' ').append(atts.getLocalName(i)).append("=\"")
+                        .append(esc(atts.getValue(i))).append('\"');
+            }
+            w.write(sb.toString());
+        }
+
+        /**
+         * Encode string with escaping.
+         * 
+         * @param str
+         *            string to encode.
+         * @return encoded string
+         */
+        private static final String esc(final String str) {
+            StringBuffer sb = new StringBuffer(str.length());
+            for (int i = 0; i < str.length(); i++) {
+                char ch = str.charAt(i);
+                switch (ch) {
+                case '&':
+                    sb.append("&amp;");
+                    break;
+
+                case '<':
+                    sb.append("&lt;");
+                    break;
+
+                case '>':
+                    sb.append("&gt;");
+                    break;
+
+                case '\"':
+                    sb.append("&quot;");
+                    break;
+
+                default:
+                    if (ch > 0x7f) {
+                        sb.append("&#").append(Integer.toString(ch))
+                                .append(';');
+                    } else {
+                        sb.append(ch);
+                    }
+
+                }
+            }
+            return sb.toString();
+        }
+
+        private final void writeIdent() throws IOException {
+            int n = ident;
+            while (n > 0) {
+                if (n > OFF.length) {
+                    w.write(OFF);
+                    n -= OFF.length;
+                } else {
+                    w.write(OFF, 0, n);
+                    n = 0;
+                }
+            }
+        }
+
+        private final void closeElement() throws IOException {
+            if (openElement) {
+                w.write(">\n");
+            }
+            openElement = false;
+        }
+
+    }
+
+    /**
+     * A {@link org.xml.sax.ContentHandler ContentHandler} that splits XML
+     * documents into smaller chunks. Each chunk is processed by the nested
+     * {@link org.xml.sax.ContentHandler ContentHandler} obtained from
+     * {@link java.net.ContentHandlerFactory ContentHandlerFactory}. This is
+     * useful for running XSLT engine against large XML document that will
+     * hardly fit into the memory all together.
+     * <p>
+     * TODO use complete path for subdocumentRoot
+     */
+    private static final class InputSlicingHandler extends DefaultHandler {
+        private String subdocumentRoot;
+
+        private final ContentHandler rootHandler;
+
+        private ContentHandlerFactory subdocumentHandlerFactory;
+
+        private boolean subdocument = false;
+
+        private ContentHandler subdocumentHandler;
+
+        /**
+         * Constructs a new {@link InputSlicingHandler SubdocumentHandler}
+         * object.
+         * 
+         * @param subdocumentRoot
+         *            name/path to the root element of the subdocument
+         * @param rootHandler
+         *            content handler for the entire document (subdocument
+         *            envelope).
+         * @param subdocumentHandlerFactory
+         *            a {@link ContentHandlerFactory ContentHandlerFactory} used
+         *            to create {@link ContentHandler ContentHandler} instances
+         *            for subdocuments.
+         */
+        InputSlicingHandler(final String subdocumentRoot,
+                final ContentHandler rootHandler,
+                final ContentHandlerFactory subdocumentHandlerFactory) {
+            this.subdocumentRoot = subdocumentRoot;
+            this.rootHandler = rootHandler;
+            this.subdocumentHandlerFactory = subdocumentHandlerFactory;
+        }
+
+        @Override
+        public final void startElement(final String namespaceURI,
+                final String localName, final String qName,
+                final Attributes list) throws SAXException {
+            if (subdocument) {
+                subdocumentHandler.startElement(namespaceURI, localName, qName,
+                        list);
+            } else if (localName.equals(subdocumentRoot)) {
+                subdocumentHandler = subdocumentHandlerFactory
+                        .createContentHandler();
+                subdocumentHandler.startDocument();
+                subdocumentHandler.startElement(namespaceURI, localName, qName,
+                        list);
+                subdocument = true;
+            } else if (rootHandler != null) {
+                rootHandler.startElement(namespaceURI, localName, qName, list);
+            }
+        }
+
+        @Override
+        public final void endElement(final String namespaceURI,
+                final String localName, final String qName) throws SAXException {
+            if (subdocument) {
+                subdocumentHandler.endElement(namespaceURI, localName, qName);
+                if (localName.equals(subdocumentRoot)) {
+                    subdocumentHandler.endDocument();
+                    subdocument = false;
+                }
+            } else if (rootHandler != null) {
+                rootHandler.endElement(namespaceURI, localName, qName);
+            }
+        }
+
+        @Override
+        public final void startDocument() throws SAXException {
+            if (rootHandler != null) {
+                rootHandler.startDocument();
+            }
+        }
+
+        @Override
+        public final void endDocument() throws SAXException {
+            if (rootHandler != null) {
+                rootHandler.endDocument();
+
+            }
+        }
+
+        @Override
+        public final void characters(final char[] buff, final int offset,
+                final int size) throws SAXException {
+            if (subdocument) {
+                subdocumentHandler.characters(buff, offset, size);
+            } else if (rootHandler != null) {
+                rootHandler.characters(buff, offset, size);
+            }
+        }
+
+    }
+
+    /**
+     * A {@link org.xml.sax.ContentHandler ContentHandler} that splits XML
+     * documents into smaller chunks. Each chunk is processed by the nested
+     * {@link org.xml.sax.ContentHandler ContentHandler} obtained from
+     * {@link java.net.ContentHandlerFactory ContentHandlerFactory}. This is
+     * useful for running XSLT engine against large XML document that will
+     * hardly fit into the memory all together.
+     * 
+     * <p>
+     * TODO use complete path for subdocumentRoot
+     */
+    private static final class OutputSlicingHandler extends DefaultHandler {
+        private final String subdocumentRoot;
+
+        private ContentHandlerFactory subdocumentHandlerFactory;
+
+        private final EntryElement entryElement;
+
+        private boolean isXml;
+
+        private boolean subdocument = false;
+
+        private ContentHandler subdocumentHandler;
+
+        /**
+         * Constructs a new {@link OutputSlicingHandler SubdocumentHandler}
+         * object.
+         * 
+         * @param subdocumentHandlerFactory
+         *            a {@link ContentHandlerFactory ContentHandlerFactory} used
+         *            to create {@link ContentHandler ContentHandler} instances
+         *            for subdocuments.
+         * @param entryElement
+         *            TODO.
+         * @param isXml
+         *            TODO.
+         */
+        OutputSlicingHandler(
+                final ContentHandlerFactory subdocumentHandlerFactory,
+                final EntryElement entryElement, final boolean isXml) {
+            this.subdocumentRoot = "class";
+            this.subdocumentHandlerFactory = subdocumentHandlerFactory;
+            this.entryElement = entryElement;
+            this.isXml = isXml;
+        }
+
+        @Override
+        public final void startElement(final String namespaceURI,
+                final String localName, final String qName,
+                final Attributes list) throws SAXException {
+            if (subdocument) {
+                subdocumentHandler.startElement(namespaceURI, localName, qName,
+                        list);
+            } else if (localName.equals(subdocumentRoot)) {
+                String name = list.getValue("name");
+                if (name == null || name.length() == 0) {
+                    throw new SAXException(
+                            "Class element without name attribute.");
+                }
+                try {
+                    entryElement.openEntry(isXml ? name + ".class.xml" : name
+                            + ".class");
+                } catch (IOException ex) {
+                    throw new SAXException(ex.toString(), ex);
+                }
+                subdocumentHandler = subdocumentHandlerFactory
+                        .createContentHandler();
+                subdocumentHandler.startDocument();
+                subdocumentHandler.startElement(namespaceURI, localName, qName,
+                        list);
+                subdocument = true;
+            }
+        }
+
+        @Override
+        public final void endElement(final String namespaceURI,
+                final String localName, final String qName) throws SAXException {
+            if (subdocument) {
+                subdocumentHandler.endElement(namespaceURI, localName, qName);
+                if (localName.equals(subdocumentRoot)) {
+                    subdocumentHandler.endDocument();
+                    subdocument = false;
+                    try {
+                        entryElement.closeEntry();
+                    } catch (IOException ex) {
+                        throw new SAXException(ex.toString(), ex);
+                    }
+                }
+            }
+        }
+
+        @Override
+        public final void startDocument() throws SAXException {
+        }
+
+        @Override
+        public final void endDocument() throws SAXException {
+        }
+
+        @Override
+        public final void characters(final char[] buff, final int offset,
+                final int size) throws SAXException {
+            if (subdocument) {
+                subdocumentHandler.characters(buff, offset, size);
+            }
+        }
+
+    }
+
+    private static interface EntryElement {
+
+        OutputStream openEntry(String name) throws IOException;
+
+        void closeEntry() throws IOException;
+
+    }
+
+    private static final class SingleDocElement implements EntryElement {
+        private final OutputStream os;
+
+        SingleDocElement(final OutputStream os) {
+            this.os = os;
+        }
+
+        public OutputStream openEntry(final String name) throws IOException {
+            return os;
+        }
+
+        public void closeEntry() throws IOException {
+            os.flush();
+        }
+
+    }
+
+    private static final class ZipEntryElement implements EntryElement {
+        private ZipOutputStream zos;
+
+        ZipEntryElement(final ZipOutputStream zos) {
+            this.zos = zos;
+        }
+
+        public OutputStream openEntry(final String name) throws IOException {
+            ZipEntry entry = new ZipEntry(name);
+            zos.putNextEntry(entry);
+            return zos;
+        }
+
+        public void closeEntry() throws IOException {
+            zos.flush();
+            zos.closeEntry();
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java
new file mode 100644
index 0000000..2f49c24
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java
@@ -0,0 +1,89 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * 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.xml;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * SAXAdapter
+ * 
+ * @author Eugene Kuleshov
+ */
+public class SAXAdapter {
+
+    private final ContentHandler h;
+
+    protected SAXAdapter(final ContentHandler h) {
+        this.h = h;
+    }
+
+    protected ContentHandler getContentHandler() {
+        return h;
+    }
+
+    protected void addDocumentStart() {
+        try {
+            h.startDocument();
+        } catch (SAXException ex) {
+            throw new RuntimeException(ex.getMessage(), ex.getException());
+        }
+    }
+
+    protected void addDocumentEnd() {
+        try {
+            h.endDocument();
+        } catch (SAXException ex) {
+            throw new RuntimeException(ex.getMessage(), ex.getException());
+        }
+    }
+
+    protected final void addStart(final String name, final Attributes attrs) {
+        try {
+            h.startElement("", name, name, attrs);
+        } catch (SAXException ex) {
+            throw new RuntimeException(ex.getMessage(), ex.getException());
+        }
+    }
+
+    protected final void addEnd(final String name) {
+        try {
+            h.endElement("", name, name);
+        } catch (SAXException ex) {
+            throw new RuntimeException(ex.getMessage(), ex.getException());
+        }
+    }
+
+    protected final void addElement(final String name, final Attributes attrs) {
+        addStart(name, attrs);
+        addEnd(name);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java
new file mode 100644
index 0000000..491c57e
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java
@@ -0,0 +1,242 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * 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.xml;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * SAXAnnotationAdapter
+ * 
+ * @author Eugene Kuleshov
+ */
+public final class SAXAnnotationAdapter extends AnnotationVisitor {
+
+    SAXAdapter sa;
+
+    private final String elementName;
+
+    public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
+            final int visible, final String name, final String desc) {
+        this(Opcodes.ASM5, sa, elementName, visible, desc, name, -1, -1, null,
+                null, null, null);
+    }
+
+    public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
+            final int visible, final int parameter, final String desc) {
+        this(Opcodes.ASM5, sa, elementName, visible, desc, null, parameter, -1,
+                null, null, null, null);
+    }
+
+    public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
+            final int visible, final String name, final String desc,
+            final int typeRef, final TypePath typePath) {
+        this(Opcodes.ASM5, sa, elementName, visible, desc, name, -1, typeRef,
+                typePath, null, null, null);
+    }
+
+    public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
+            final int visible, final String name, final String desc,
+            int typeRef, TypePath typePath, final String[] start,
+            final String[] end, final int[] index) {
+        this(Opcodes.ASM5, sa, elementName, visible, desc, name, -1, typeRef,
+                typePath, start, end, index);
+    }
+
+    protected SAXAnnotationAdapter(final int api, final SAXAdapter sa,
+            final String elementName, final int visible, final String desc,
+            final String name, final int parameter) {
+        this(api, sa, elementName, visible, desc, name, parameter, -1, null,
+                null, null, null);
+    }
+
+    protected SAXAnnotationAdapter(final int api, final SAXAdapter sa,
+            final String elementName, final int visible, final String desc,
+            final String name, final int parameter, final int typeRef,
+            final TypePath typePath, final String[] start, final String[] end,
+            final int[] index) {
+        super(api);
+        this.sa = sa;
+        this.elementName = elementName;
+
+        AttributesImpl att = new AttributesImpl();
+        if (name != null) {
+            att.addAttribute("", "name", "name", "", name);
+        }
+        if (visible != 0) {
+            att.addAttribute("", "visible", "visible", "", visible > 0 ? "true"
+                    : "false");
+        }
+        if (parameter != -1) {
+            att.addAttribute("", "parameter", "parameter", "",
+                    Integer.toString(parameter));
+        }
+        if (desc != null) {
+            att.addAttribute("", "desc", "desc", "", desc);
+        }
+        if (typeRef != -1) {
+            att.addAttribute("", "typeRef", "typeRef", "",
+                    Integer.toString(typeRef));
+        }
+        if (typePath != null) {
+            att.addAttribute("", "typePath", "typePath", "",
+                    typePath.toString());
+        }
+        if (start != null) {
+            StringBuffer value = new StringBuffer(start[0]);
+            for (int i = 1; i < start.length; ++i) {
+                value.append(" ").append(start[i]);
+            }
+            att.addAttribute("", "start", "start", "", value.toString());
+        }
+        if (end != null) {
+            StringBuffer value = new StringBuffer(end[0]);
+            for (int i = 1; i < end.length; ++i) {
+                value.append(" ").append(end[i]);
+            }
+            att.addAttribute("", "end", "end", "", value.toString());
+        }
+        if (index != null) {
+            StringBuffer value = new StringBuffer();
+            value.append(index[0]);
+            for (int i = 1; i < index.length; ++i) {
+                value.append(" ").append(index[i]);
+            }
+            att.addAttribute("", "index", "index", "", value.toString());
+        }
+
+        sa.addStart(elementName, att);
+    }
+
+    @Override
+    public void visit(final String name, final Object value) {
+        Class<?> c = value.getClass();
+        if (c.isArray()) {
+            AnnotationVisitor av = visitArray(name);
+            if (value instanceof byte[]) {
+                byte[] b = (byte[]) value;
+                for (int i = 0; i < b.length; i++) {
+                    av.visit(null, new Byte(b[i]));
+                }
+
+            } else if (value instanceof char[]) {
+                char[] b = (char[]) value;
+                for (int i = 0; i < b.length; i++) {
+                    av.visit(null, new Character(b[i]));
+                }
+
+            } else if (value instanceof short[]) {
+                short[] b = (short[]) value;
+                for (int i = 0; i < b.length; i++) {
+                    av.visit(null, new Short(b[i]));
+                }
+
+            } else if (value instanceof boolean[]) {
+                boolean[] b = (boolean[]) value;
+                for (int i = 0; i < b.length; i++) {
+                    av.visit(null, Boolean.valueOf(b[i]));
+                }
+
+            } else if (value instanceof int[]) {
+                int[] b = (int[]) value;
+                for (int i = 0; i < b.length; i++) {
+                    av.visit(null, new Integer(b[i]));
+                }
+
+            } else if (value instanceof long[]) {
+                long[] b = (long[]) value;
+                for (int i = 0; i < b.length; i++) {
+                    av.visit(null, new Long(b[i]));
+                }
+
+            } else if (value instanceof float[]) {
+                float[] b = (float[]) value;
+                for (int i = 0; i < b.length; i++) {
+                    av.visit(null, new Float(b[i]));
+                }
+
+            } else if (value instanceof double[]) {
+                double[] b = (double[]) value;
+                for (int i = 0; i < b.length; i++) {
+                    av.visit(null, new Double(b[i]));
+                }
+
+            }
+            av.visitEnd();
+        } else {
+            addValueElement("annotationValue", name, Type.getDescriptor(c),
+                    value.toString());
+        }
+    }
+
+    @Override
+    public void visitEnum(final String name, final String desc,
+            final String value) {
+        addValueElement("annotationValueEnum", name, desc, value);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String name,
+            final String desc) {
+        return new SAXAnnotationAdapter(sa, "annotationValueAnnotation", 0,
+                name, desc);
+    }
+
+    @Override
+    public AnnotationVisitor visitArray(final String name) {
+        return new SAXAnnotationAdapter(sa, "annotationValueArray", 0, name,
+                null);
+    }
+
+    @Override
+    public void visitEnd() {
+        sa.addEnd(elementName);
+    }
+
+    private void addValueElement(final String element, final String name,
+            final String desc, final String value) {
+        AttributesImpl att = new AttributesImpl();
+        if (name != null) {
+            att.addAttribute("", "name", "name", "", name);
+        }
+        if (desc != null) {
+            att.addAttribute("", "desc", "desc", "", desc);
+        }
+        if (value != null) {
+            att.addAttribute("", "value", "value", "",
+                    SAXClassAdapter.encode(value));
+        }
+
+        sa.addElement(element, att);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java
new file mode 100644
index 0000000..dc4cb66
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java
@@ -0,0 +1,335 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * 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.xml;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * A {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor ClassVisitor} that generates SAX 2.0
+ * events from the visited class. It can feed any kind of
+ * {@link org.xml.sax.ContentHandler ContentHandler}, e.g. XML serializer, XSLT
+ * or XQuery engines.
+ * 
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.Processor
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.ASMContentHandler
+ * 
+ * @author Eugene Kuleshov
+ */
+public final class SAXClassAdapter extends ClassVisitor {
+
+    SAXAdapter sa;
+
+    private final boolean singleDocument;
+
+    /**
+     * Pseudo access flag used to distinguish class access flags.
+     */
+    private static final int ACCESS_CLASS = 262144;
+
+    /**
+     * Pseudo access flag used to distinguish field access flags.
+     */
+    private static final int ACCESS_FIELD = 524288;
+
+    /**
+     * Pseudo access flag used to distinguish inner class flags.
+     */
+    private static final int ACCESS_INNER = 1048576;
+
+    /**
+     * Constructs a new {@link SAXClassAdapter SAXClassAdapter} object.
+     * 
+     * @param h
+     *            content handler that will be used to send SAX 2.0 events.
+     * @param singleDocument
+     *            if <tt>true</tt> adapter will not produce
+     *            {@link ContentHandler#startDocument() startDocument()} and
+     *            {@link ContentHandler#endDocument() endDocument()} events.
+     */
+    public SAXClassAdapter(final ContentHandler h, boolean singleDocument) {
+        super(Opcodes.ASM5);
+        this.sa = new SAXAdapter(h);
+        this.singleDocument = singleDocument;
+        if (!singleDocument) {
+            sa.addDocumentStart();
+        }
+    }
+
+    @Override
+    public void visitSource(final String source, final String debug) {
+        AttributesImpl att = new AttributesImpl();
+        if (source != null) {
+            att.addAttribute("", "file", "file", "", encode(source));
+        }
+        if (debug != null) {
+            att.addAttribute("", "debug", "debug", "", encode(debug));
+        }
+
+        sa.addElement("source", att);
+    }
+
+    @Override
+    public void visitOuterClass(final String owner, final String name,
+            final String desc) {
+        AttributesImpl att = new AttributesImpl();
+        att.addAttribute("", "owner", "owner", "", owner);
+        if (name != null) {
+            att.addAttribute("", "name", "name", "", name);
+        }
+        if (desc != null) {
+            att.addAttribute("", "desc", "desc", "", desc);
+        }
+
+        sa.addElement("outerclass", att);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        return new SAXAnnotationAdapter(sa, "annotation", visible ? 1 : -1,
+                null, desc);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        return new SAXAnnotationAdapter(sa, "typeAnnotation", visible ? 1 : -1,
+                null, desc, typeRef, typePath);
+    }
+
+    @Override
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
+        StringBuffer sb = new StringBuffer();
+        appendAccess(access | ACCESS_CLASS, sb);
+
+        AttributesImpl att = new AttributesImpl();
+        att.addAttribute("", "access", "access", "", sb.toString());
+        if (name != null) {
+            att.addAttribute("", "name", "name", "", name);
+        }
+        if (signature != null) {
+            att.addAttribute("", "signature", "signature", "",
+                    encode(signature));
+        }
+        if (superName != null) {
+            att.addAttribute("", "parent", "parent", "", superName);
+        }
+        att.addAttribute("", "major", "major", "",
+                Integer.toString(version & 0xFFFF));
+        att.addAttribute("", "minor", "minor", "",
+                Integer.toString(version >>> 16));
+        sa.addStart("class", att);
+
+        sa.addStart("interfaces", new AttributesImpl());
+        if (interfaces != null && interfaces.length > 0) {
+            for (int i = 0; i < interfaces.length; i++) {
+                AttributesImpl att2 = new AttributesImpl();
+                att2.addAttribute("", "name", "name", "", interfaces[i]);
+                sa.addElement("interface", att2);
+            }
+        }
+        sa.addEnd("interfaces");
+    }
+
+    @Override
+    public FieldVisitor visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
+        StringBuffer sb = new StringBuffer();
+        appendAccess(access | ACCESS_FIELD, sb);
+
+        AttributesImpl att = new AttributesImpl();
+        att.addAttribute("", "access", "access", "", sb.toString());
+        att.addAttribute("", "name", "name", "", name);
+        att.addAttribute("", "desc", "desc", "", desc);
+        if (signature != null) {
+            att.addAttribute("", "signature", "signature", "",
+                    encode(signature));
+        }
+        if (value != null) {
+            att.addAttribute("", "value", "value", "", encode(value.toString()));
+        }
+
+        return new SAXFieldAdapter(sa, att);
+    }
+
+    @Override
+    public MethodVisitor visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        StringBuffer sb = new StringBuffer();
+        appendAccess(access, sb);
+
+        AttributesImpl att = new AttributesImpl();
+        att.addAttribute("", "access", "access", "", sb.toString());
+        att.addAttribute("", "name", "name", "", name);
+        att.addAttribute("", "desc", "desc", "", desc);
+        if (signature != null) {
+            att.addAttribute("", "signature", "signature", "", signature);
+        }
+        sa.addStart("method", att);
+
+        sa.addStart("exceptions", new AttributesImpl());
+        if (exceptions != null && exceptions.length > 0) {
+            for (int i = 0; i < exceptions.length; i++) {
+                AttributesImpl att2 = new AttributesImpl();
+                att2.addAttribute("", "name", "name", "", exceptions[i]);
+                sa.addElement("exception", att2);
+            }
+        }
+        sa.addEnd("exceptions");
+
+        return new SAXCodeAdapter(sa, access);
+    }
+
+    @Override
+    public final void visitInnerClass(final String name,
+            final String outerName, final String innerName, final int access) {
+        StringBuffer sb = new StringBuffer();
+        appendAccess(access | ACCESS_INNER, sb);
+
+        AttributesImpl att = new AttributesImpl();
+        att.addAttribute("", "access", "access", "", sb.toString());
+        if (name != null) {
+            att.addAttribute("", "name", "name", "", name);
+        }
+        if (outerName != null) {
+            att.addAttribute("", "outerName", "outerName", "", outerName);
+        }
+        if (innerName != null) {
+            att.addAttribute("", "innerName", "innerName", "", innerName);
+        }
+        sa.addElement("innerclass", att);
+    }
+
+    @Override
+    public final void visitEnd() {
+        sa.addEnd("class");
+        if (!singleDocument) {
+            sa.addDocumentEnd();
+        }
+    }
+
+    static final String encode(final String s) {
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0; i < s.length(); i++) {
+            char c = s.charAt(i);
+            if (c == '\\') {
+                sb.append("\\\\");
+            } else if (c < 0x20 || c > 0x7f) {
+                sb.append("\\u");
+                if (c < 0x10) {
+                    sb.append("000");
+                } else if (c < 0x100) {
+                    sb.append("00");
+                } else if (c < 0x1000) {
+                    sb.append('0');
+                }
+                sb.append(Integer.toString(c, 16));
+            } else {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    static void appendAccess(final int access, final StringBuffer sb) {
+        if ((access & Opcodes.ACC_PUBLIC) != 0) {
+            sb.append("public ");
+        }
+        if ((access & Opcodes.ACC_PRIVATE) != 0) {
+            sb.append("private ");
+        }
+        if ((access & Opcodes.ACC_PROTECTED) != 0) {
+            sb.append("protected ");
+        }
+        if ((access & Opcodes.ACC_FINAL) != 0) {
+            sb.append("final ");
+        }
+        if ((access & Opcodes.ACC_STATIC) != 0) {
+            sb.append("static ");
+        }
+        if ((access & Opcodes.ACC_SUPER) != 0) {
+            if ((access & ACCESS_CLASS) == 0) {
+                sb.append("synchronized ");
+            } else {
+                sb.append("super ");
+            }
+        }
+        if ((access & Opcodes.ACC_VOLATILE) != 0) {
+            if ((access & ACCESS_FIELD) == 0) {
+                sb.append("bridge ");
+            } else {
+                sb.append("volatile ");
+            }
+        }
+        if ((access & Opcodes.ACC_TRANSIENT) != 0) {
+            if ((access & ACCESS_FIELD) == 0) {
+                sb.append("varargs ");
+            } else {
+                sb.append("transient ");
+            }
+        }
+        if ((access & Opcodes.ACC_NATIVE) != 0) {
+            sb.append("native ");
+        }
+        if ((access & Opcodes.ACC_STRICT) != 0) {
+            sb.append("strict ");
+        }
+        if ((access & Opcodes.ACC_INTERFACE) != 0) {
+            sb.append("interface ");
+        }
+        if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+            sb.append("abstract ");
+        }
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            sb.append("synthetic ");
+        }
+        if ((access & Opcodes.ACC_ANNOTATION) != 0) {
+            sb.append("annotation ");
+        }
+        if ((access & Opcodes.ACC_ENUM) != 0) {
+            sb.append("enum ");
+        }
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            sb.append("deprecated ");
+        }
+        if ((access & Opcodes.ACC_MANDATED) != 0) {
+            sb.append("mandated ");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java
new file mode 100644
index 0000000..3ed0a49
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java
@@ -0,0 +1,415 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * 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.xml;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+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;
+import org.apache.tapestry5.internal.plastic.asm.util.Printer;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * A {@link MethodVisitor} that generates SAX 2.0 events from the visited
+ * method.
+ * 
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.SAXClassAdapter
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.Processor
+ * 
+ * @author Eugene Kuleshov
+ */
+public final class SAXCodeAdapter extends MethodVisitor {
+
+    static final String[] TYPES = { "top", "int", "float", "double", "long",
+            "null", "uninitializedThis" };
+
+    SAXAdapter sa;
+
+    int access;
+
+    private final Map<Label, String> labelNames;
+
+    /**
+     * Constructs a new {@link SAXCodeAdapter SAXCodeAdapter} object.
+     * 
+     * @param sa
+     *            content handler that will be used to send SAX 2.0 events.
+     */
+    public SAXCodeAdapter(final SAXAdapter sa, final int access) {
+        super(Opcodes.ASM5);
+        this.sa = sa;
+        this.access = access;
+        this.labelNames = new HashMap<Label, String>();
+    }
+
+    @Override
+    public void visitParameter(String name, int access) {
+        AttributesImpl attrs = new AttributesImpl();
+        if (name != null) {
+            attrs.addAttribute("", "name", "name", "", name);
+        }
+        StringBuffer sb = new StringBuffer();
+        SAXClassAdapter.appendAccess(access, sb);
+        attrs.addAttribute("", "access", "access", "", sb.toString());
+        sa.addElement("parameter", attrs);
+    }
+
+    @Override
+    public final void visitCode() {
+        if ((access & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE | Opcodes.ACC_NATIVE)) == 0) {
+            sa.addStart("code", new AttributesImpl());
+        }
+    }
+
+    @Override
+    public void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack) {
+        AttributesImpl attrs = new AttributesImpl();
+        switch (type) {
+        case Opcodes.F_NEW:
+        case Opcodes.F_FULL:
+            if (type == Opcodes.F_NEW) {
+                attrs.addAttribute("", "type", "type", "", "NEW");
+            } else {
+                attrs.addAttribute("", "type", "type", "", "FULL");
+            }
+            sa.addStart("frame", attrs);
+            appendFrameTypes(true, nLocal, local);
+            appendFrameTypes(false, nStack, stack);
+            break;
+        case Opcodes.F_APPEND:
+            attrs.addAttribute("", "type", "type", "", "APPEND");
+            sa.addStart("frame", attrs);
+            appendFrameTypes(true, nLocal, local);
+            break;
+        case Opcodes.F_CHOP:
+            attrs.addAttribute("", "type", "type", "", "CHOP");
+            attrs.addAttribute("", "count", "count", "",
+                    Integer.toString(nLocal));
+            sa.addStart("frame", attrs);
+            break;
+        case Opcodes.F_SAME:
+            attrs.addAttribute("", "type", "type", "", "SAME");
+            sa.addStart("frame", attrs);
+            break;
+        case Opcodes.F_SAME1:
+            attrs.addAttribute("", "type", "type", "", "SAME1");
+            sa.addStart("frame", attrs);
+            appendFrameTypes(false, 1, stack);
+            break;
+        }
+        sa.addEnd("frame");
+    }
+
+    private void appendFrameTypes(final boolean local, final int n,
+            final Object[] types) {
+        for (int i = 0; i < n; ++i) {
+            Object type = types[i];
+            AttributesImpl attrs = new AttributesImpl();
+            if (type instanceof String) {
+                attrs.addAttribute("", "type", "type", "", (String) type);
+            } else if (type instanceof Integer) {
+                attrs.addAttribute("", "type", "type", "",
+                        TYPES[((Integer) type).intValue()]);
+            } else {
+                attrs.addAttribute("", "type", "type", "", "uninitialized");
+                attrs.addAttribute("", "label", "label", "",
+                        getLabel((Label) type));
+            }
+            sa.addElement(local ? "local" : "stack", attrs);
+        }
+    }
+
+    @Override
+    public final void visitInsn(final int opcode) {
+        sa.addElement(Printer.OPCODES[opcode], new AttributesImpl());
+    }
+
+    @Override
+    public final void visitIntInsn(final int opcode, final int operand) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "value", "value", "", Integer.toString(operand));
+        sa.addElement(Printer.OPCODES[opcode], attrs);
+    }
+
+    @Override
+    public final void visitVarInsn(final int opcode, final int var) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "var", "var", "", Integer.toString(var));
+        sa.addElement(Printer.OPCODES[opcode], attrs);
+    }
+
+    @Override
+    public final void visitTypeInsn(final int opcode, final String type) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "desc", "desc", "", type);
+        sa.addElement(Printer.OPCODES[opcode], attrs);
+    }
+
+    @Override
+    public final void visitFieldInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "owner", "owner", "", owner);
+        attrs.addAttribute("", "name", "name", "", name);
+        attrs.addAttribute("", "desc", "desc", "", desc);
+        sa.addElement(Printer.OPCODES[opcode], attrs);
+    }
+
+    @Override
+    public final void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "owner", "owner", "", owner);
+        attrs.addAttribute("", "name", "name", "", name);
+        attrs.addAttribute("", "desc", "desc", "", desc);
+        attrs.addAttribute("", "itf", "itf", "", itf ? "true" : "false");
+        sa.addElement(Printer.OPCODES[opcode], attrs);
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "name", "name", "", name);
+        attrs.addAttribute("", "desc", "desc", "", desc);
+        attrs.addAttribute("", "bsm", "bsm", "",
+                SAXClassAdapter.encode(bsm.toString()));
+        sa.addStart("INVOKEDYNAMIC", attrs);
+        for (int i = 0; i < bsmArgs.length; i++) {
+            sa.addElement("bsmArg", getConstantAttribute(bsmArgs[i]));
+        }
+        sa.addEnd("INVOKEDYNAMIC");
+    }
+
+    @Override
+    public final void visitJumpInsn(final int opcode, final Label label) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "label", "label", "", getLabel(label));
+        sa.addElement(Printer.OPCODES[opcode], attrs);
+    }
+
+    @Override
+    public final void visitLabel(final Label label) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "name", "name", "", getLabel(label));
+        sa.addElement("Label", attrs);
+    }
+
+    @Override
+    public final void visitLdcInsn(final Object cst) {
+        sa.addElement(Printer.OPCODES[Opcodes.LDC], getConstantAttribute(cst));
+    }
+
+    private static AttributesImpl getConstantAttribute(final Object cst) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "cst", "cst", "",
+                SAXClassAdapter.encode(cst.toString()));
+        attrs.addAttribute("", "desc", "desc", "",
+                Type.getDescriptor(cst.getClass()));
+        return attrs;
+    }
+
+    @Override
+    public final void visitIincInsn(final int var, final int increment) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "var", "var", "", Integer.toString(var));
+        attrs.addAttribute("", "inc", "inc", "", Integer.toString(increment));
+        sa.addElement(Printer.OPCODES[Opcodes.IINC], attrs);
+    }
+
+    @Override
+    public final void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "min", "min", "", Integer.toString(min));
+        attrs.addAttribute("", "max", "max", "", Integer.toString(max));
+        attrs.addAttribute("", "dflt", "dflt", "", getLabel(dflt));
+        String o = Printer.OPCODES[Opcodes.TABLESWITCH];
+        sa.addStart(o, attrs);
+        for (int i = 0; i < labels.length; i++) {
+            AttributesImpl att2 = new AttributesImpl();
+            att2.addAttribute("", "name", "name", "", getLabel(labels[i]));
+            sa.addElement("label", att2);
+        }
+        sa.addEnd(o);
+    }
+
+    @Override
+    public final void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
+        AttributesImpl att = new AttributesImpl();
+        att.addAttribute("", "dflt", "dflt", "", getLabel(dflt));
+        String o = Printer.OPCODES[Opcodes.LOOKUPSWITCH];
+        sa.addStart(o, att);
+        for (int i = 0; i < labels.length; i++) {
+            AttributesImpl att2 = new AttributesImpl();
+            att2.addAttribute("", "name", "name", "", getLabel(labels[i]));
+            att2.addAttribute("", "key", "key", "", Integer.toString(keys[i]));
+            sa.addElement("label", att2);
+        }
+        sa.addEnd(o);
+    }
+
+    @Override
+    public final void visitMultiANewArrayInsn(final String desc, final int dims) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "desc", "desc", "", desc);
+        attrs.addAttribute("", "dims", "dims", "", Integer.toString(dims));
+        sa.addElement(Printer.OPCODES[Opcodes.MULTIANEWARRAY], attrs);
+    }
+
+    @Override
+    public final void visitTryCatchBlock(final Label start, final Label end,
+            final Label handler, final String type) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "start", "start", "", getLabel(start));
+        attrs.addAttribute("", "end", "end", "", getLabel(end));
+        attrs.addAttribute("", "handler", "handler", "", getLabel(handler));
+        if (type != null) {
+            attrs.addAttribute("", "type", "type", "", type);
+        }
+        sa.addElement("TryCatch", attrs);
+    }
+
+    @Override
+    public final void visitMaxs(final int maxStack, final int maxLocals) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "maxStack", "maxStack", "",
+                Integer.toString(maxStack));
+        attrs.addAttribute("", "maxLocals", "maxLocals", "",
+                Integer.toString(maxLocals));
+        sa.addElement("Max", attrs);
+
+        sa.addEnd("code");
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "name", "name", "", name);
+        attrs.addAttribute("", "desc", "desc", "", desc);
+        if (signature != null) {
+            attrs.addAttribute("", "signature", "signature", "",
+                    SAXClassAdapter.encode(signature));
+        }
+        attrs.addAttribute("", "start", "start", "", getLabel(start));
+        attrs.addAttribute("", "end", "end", "", getLabel(end));
+        attrs.addAttribute("", "var", "var", "", Integer.toString(index));
+        sa.addElement("LocalVar", attrs);
+    }
+
+    @Override
+    public final void visitLineNumber(final int line, final Label start) {
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "line", "line", "", Integer.toString(line));
+        attrs.addAttribute("", "start", "start", "", getLabel(start));
+        sa.addElement("LineNumber", attrs);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotationDefault() {
+        return new SAXAnnotationAdapter(sa, "annotationDefault", 0, null, null);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        return new SAXAnnotationAdapter(sa, "annotation", visible ? 1 : -1,
+                null, desc);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        return new SAXAnnotationAdapter(sa, "typeAnnotation", visible ? 1 : -1,
+                null, desc, typeRef, typePath);
+    }
+
+    @Override
+    public AnnotationVisitor visitParameterAnnotation(final int parameter,
+            final String desc, final boolean visible) {
+        return new SAXAnnotationAdapter(sa, "parameterAnnotation", visible ? 1
+                : -1, parameter, desc);
+    }
+
+    @Override
+    public AnnotationVisitor visitInsnAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        return new SAXAnnotationAdapter(sa, "insnAnnotation", visible ? 1 : -1,
+                null, desc, typeRef, typePath);
+    }
+
+    @Override
+    public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        return new SAXAnnotationAdapter(sa, "tryCatchAnnotation", visible ? 1
+                : -1, null, desc, typeRef, typePath);
+    }
+
+    @Override
+    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+            TypePath typePath, Label[] start, Label[] end, int[] index,
+            String desc, boolean visible) {
+        String[] s = new String[start.length];
+        String[] e = new String[end.length];
+        for (int i = 0; i < s.length; ++i) {
+            s[i] = getLabel(start[i]);
+        }
+        for (int i = 0; i < e.length; ++i) {
+            e[i] = getLabel(end[i]);
+        }
+        return new SAXAnnotationAdapter(sa, "localVariableAnnotation",
+                visible ? 1 : -1, null, desc, typeRef, typePath, s, e, index);
+    }
+
+    @Override
+    public void visitEnd() {
+        sa.addEnd("method");
+    }
+
+    private final String getLabel(final Label label) {
+        String name = labelNames.get(label);
+        if (name == null) {
+            name = Integer.toString(labelNames.size());
+            labelNames.put(label, name);
+        }
+        return name;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java
new file mode 100644
index 0000000..4fbc2a5
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java
@@ -0,0 +1,71 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * 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.xml;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.xml.sax.Attributes;
+
+/**
+ * SAXFieldAdapter
+ * 
+ * @author Eugene Kuleshov
+ */
+public final class SAXFieldAdapter extends FieldVisitor {
+
+    SAXAdapter sa;
+
+    public SAXFieldAdapter(final SAXAdapter sa, final Attributes att) {
+        super(Opcodes.ASM5);
+        this.sa = sa;
+        sa.addStart("field", att);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        return new SAXAnnotationAdapter(sa, "annotation", visible ? 1 : -1,
+                null, desc);
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        return new SAXAnnotationAdapter(sa, "typeAnnotation", visible ? 1 : -1,
+                null, desc, typeRef, typePath);
+    }
+
+    @Override
+    public void visitEnd() {
+        sa.addEnd("field");
+    }
+}


[17/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/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 ac7c671..d899c5e 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
@@ -37,7 +37,7 @@ 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
  */
@@ -46,6 +46,7 @@ public interface Opcodes {
     // ASM API versions
 
     int ASM4 = 4 << 16 | 0 << 8 | 0;
+    int ASM5 = 5 << 16 | 0 << 8 | 0;
 
     // versions
 
@@ -56,6 +57,7 @@ public interface Opcodes {
     int V1_5 = 0 << 16 | 49;
     int V1_6 = 0 << 16 | 50;
     int V1_7 = 0 << 16 | 51;
+    int V1_8 = 0 << 16 | 52;
 
     // access flags
 
@@ -63,7 +65,7 @@ public interface Opcodes {
     int ACC_PRIVATE = 0x0002; // class, field, method
     int ACC_PROTECTED = 0x0004; // class, field, method
     int ACC_STATIC = 0x0008; // field, method
-    int ACC_FINAL = 0x0010; // class, field, method
+    int ACC_FINAL = 0x0010; // class, field, method, parameter
     int ACC_SUPER = 0x0020; // class
     int ACC_SYNCHRONIZED = 0x0020; // method
     int ACC_VOLATILE = 0x0040; // field
@@ -74,9 +76,10 @@ public interface Opcodes {
     int ACC_INTERFACE = 0x0200; // class
     int ACC_ABSTRACT = 0x0400; // class, method
     int ACC_STRICT = 0x0800; // method
-    int ACC_SYNTHETIC = 0x1000; // class, field, method
+    int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter
     int ACC_ANNOTATION = 0x2000; // class
     int ACC_ENUM = 0x4000; // class(?) field inner
+    int ACC_MANDATED = 0x8000; // parameter
 
     // ASM specific pseudo access flags
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/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 6011aa4..0b526a0 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
@@ -35,7 +35,7 @@ import java.lang.reflect.Method;
 /**
  * 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
  */
@@ -189,14 +189,17 @@ 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.
-     * @param len the length of this descriptor.
-     */
-    private Type(final int sort, final char[] buf, final int off, final int len)
-    {
+     * 
+     * @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.
+     * @param len
+     *            the length of this descriptor.
+     */
+    private Type(final int sort, final char[] buf, final int off, final int len) {
         this.sort = sort;
         this.buf = buf;
         this.off = off;
@@ -205,8 +208,9 @@ public class Type {
 
     /**
      * Returns the Java type corresponding to the given type descriptor.
-     *
-     * @param typeDescriptor a field or method 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) {
@@ -215,8 +219,9 @@ public class Type {
 
     /**
      * Returns the Java type corresponding to the given internal name.
-     *
-     * @param internalName an internal name.
+     * 
+     * @param internalName
+     *            an internal name.
      * @return the Java type corresponding to the given internal name.
      */
     public static Type getObjectType(final String internalName) {
@@ -227,8 +232,9 @@ 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.
+     * 
+     * @param methodDescriptor
+     *            a method descriptor.
      * @return the Java type corresponding to the given method descriptor.
      */
     public static Type getMethodType(final String methodDescriptor) {
@@ -238,19 +244,24 @@ public class Type {
     /**
      * 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.
+     * 
+     * @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) {
+    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.
+     * 
+     * @param c
+     *            a class.
      * @return the Java type corresponding to the given class.
      */
     public static Type getType(final Class<?> c) {
@@ -281,8 +292,9 @@ public class Type {
 
     /**
      * Returns the Java method type corresponding to the given constructor.
-     *
-     * @param c a {@link Constructor Constructor} object.
+     * 
+     * @param c
+     *            a {@link Constructor Constructor} object.
      * @return the Java method type corresponding to the given constructor.
      */
     public static Type getType(final Constructor<?> c) {
@@ -291,8 +303,9 @@ public class Type {
 
     /**
      * Returns the Java method type corresponding to the given method.
-     *
-     * @param m a {@link Method Method} object.
+     * 
+     * @param m
+     *            a {@link Method Method} object.
      * @return the Java method type corresponding to the given method.
      */
     public static Type getType(final Method m) {
@@ -302,8 +315,9 @@ public class Type {
     /**
      * Returns the Java types corresponding to the argument types of the given
      * method descriptor.
-     *
-     * @param methodDescriptor a method descriptor.
+     * 
+     * @param methodDescriptor
+     *            a method descriptor.
      * @return the Java types corresponding to the argument types of the given
      *         method descriptor.
      */
@@ -337,8 +351,9 @@ public class Type {
     /**
      * Returns the Java types corresponding to the argument types of the given
      * method.
-     *
-     * @param method a method.
+     * 
+     * @param method
+     *            a method.
      * @return the Java types corresponding to the argument types of the given
      *         method.
      */
@@ -354,8 +369,9 @@ public class Type {
     /**
      * Returns the Java type corresponding to the return type of the given
      * method descriptor.
-     *
-     * @param methodDescriptor a method descriptor.
+     * 
+     * @param methodDescriptor
+     *            a method descriptor.
      * @return the Java type corresponding to the return type of the given
      *         method descriptor.
      */
@@ -367,8 +383,9 @@ public class Type {
     /**
      * Returns the Java type corresponding to the return type of the given
      * method.
-     *
-     * @param method a method.
+     * 
+     * @param method
+     *            a method.
      * @return the Java type corresponding to the return type of the given
      *         method.
      */
@@ -378,13 +395,14 @@ public class Type {
 
     /**
      * Computes the size of the arguments and of the return value of a method.
-     *
-     * @param desc the descriptor 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
      *         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>).
+     *         <tt>(argSize &lt;&lt; 2) | retSize</tt> (argSize is therefore equal to
+     *         <tt>i &gt;&gt; 2</tt>, and retSize to <tt>i &amp; 0x03</tt>).
      */
     public static int getArgumentsAndReturnSizes(final String desc) {
         int n = 1;
@@ -418,53 +436,55 @@ public class Type {
      * 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.
+     * 
+     * @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.
      */
     private static Type getType(final char[] buf, final int off) {
         int len;
         switch (buf[off]) {
-            case 'V':
-                return VOID_TYPE;
-            case 'Z':
-                return BOOLEAN_TYPE;
-            case 'C':
-                return CHAR_TYPE;
-            case 'B':
-                return BYTE_TYPE;
-            case 'S':
-                return SHORT_TYPE;
-            case 'I':
-                return INT_TYPE;
-            case 'F':
-                return FLOAT_TYPE;
-            case 'J':
-                return LONG_TYPE;
-            case 'D':
-                return DOUBLE_TYPE;
-            case '[':
-                len = 1;
-                while (buf[off + len] == '[') {
-                    ++len;
-                }
-                if (buf[off + len] == 'L') {
-                    ++len;
-                    while (buf[off + len] != ';') {
-                        ++len;
-                    }
-                }
-                return new Type(ARRAY, buf, off, len + 1);
-            case 'L':
-                len = 1;
+        case 'V':
+            return VOID_TYPE;
+        case 'Z':
+            return BOOLEAN_TYPE;
+        case 'C':
+            return CHAR_TYPE;
+        case 'B':
+            return BYTE_TYPE;
+        case 'S':
+            return SHORT_TYPE;
+        case 'I':
+            return INT_TYPE;
+        case 'F':
+            return FLOAT_TYPE;
+        case 'J':
+            return LONG_TYPE;
+        case 'D':
+            return DOUBLE_TYPE;
+        case '[':
+            len = 1;
+            while (buf[off + len] == '[') {
+                ++len;
+            }
+            if (buf[off + len] == 'L') {
+                ++len;
                 while (buf[off + len] != ';') {
                     ++len;
                 }
-                return new Type(OBJECT, buf, off + 1, len - 1);
+            }
+            return new Type(ARRAY, buf, off, len + 1);
+        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);
+        default:
+            return new Type(METHOD, buf, off, buf.length - off);
         }
     }
 
@@ -474,12 +494,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},
-     *         {@link #OBJECT OBJECT} or {@link #METHOD METHOD}.
+     * 
+     * @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}, {@link #OBJECT OBJECT} or {@link #METHOD
+     *         METHOD}.
      */
     public int getSort() {
         return sort;
@@ -488,7 +508,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() {
@@ -502,7 +522,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() {
@@ -512,39 +532,39 @@ public class 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) {
-            case VOID:
-                return "void";
-            case BOOLEAN:
-                return "boolean";
-            case CHAR:
-                return "char";
-            case BYTE:
-                return "byte";
-            case SHORT:
-                return "short";
-            case INT:
-                return "int";
-            case FLOAT:
-                return "float";
-            case LONG:
-                return "long";
-            case DOUBLE:
-                return "double";
-            case ARRAY:
-                StringBuffer b = new StringBuffer(getElementType().getClassName());
-                for (int i = getDimensions(); i > 0; --i) {
-                    b.append("[]");
-                }
-                return b.toString();
-            case OBJECT:
-                return new String(buf, off, len).replace('/', '.');
-            default:
-                return null;
+        case VOID:
+            return "void";
+        case BOOLEAN:
+            return "boolean";
+        case CHAR:
+            return "char";
+        case BYTE:
+            return "byte";
+        case SHORT:
+            return "short";
+        case INT:
+            return "int";
+        case FLOAT:
+            return "float";
+        case LONG:
+            return "long";
+        case DOUBLE:
+            return "double";
+        case ARRAY:
+            StringBuffer b = new StringBuffer(getElementType().getClassName());
+            for (int i = getDimensions(); i > 0; --i) {
+                b.append("[]");
+            }
+            return b.toString();
+        case OBJECT:
+            return new String(buf, off, len).replace('/', '.');
+        default:
+            return null;
         }
     }
 
@@ -553,7 +573,7 @@ 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() {
@@ -563,7 +583,7 @@ public class Type {
     /**
      * 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() {
@@ -573,7 +593,7 @@ public class Type {
     /**
      * 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() {
@@ -583,12 +603,13 @@ public class Type {
     /**
      * 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>).
+     *         packed into a single
+     *         int i = <tt>(argSize &lt;&lt; 2) | retSize</tt>
+     *         (argSize is therefore equal to <tt>i &gt;&gt; 2</tt>,
+     *         and retSize to <tt>i &amp; 0x03</tt>).
      */
     public int getArgumentsAndReturnSizes() {
         return getArgumentsAndReturnSizes(getDescriptor());
@@ -600,7 +621,7 @@ public class Type {
 
     /**
      * Returns the descriptor corresponding to this Java type.
-     *
+     * 
      * @return the descriptor corresponding to this Java type.
      */
     public String getDescriptor() {
@@ -612,16 +633,16 @@ 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.
+     * 
+     * @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
      *         types.
      */
-    public static String getMethodDescriptor(
-        final Type returnType,
-        final Type... argumentTypes)
-    {
+    public static String getMethodDescriptor(final Type returnType,
+            final Type... argumentTypes) {
         StringBuffer buf = new StringBuffer();
         buf.append('(');
         for (int i = 0; i < argumentTypes.length; ++i) {
@@ -635,12 +656,14 @@ 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.
+     * 
+     * @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)
+            // descriptor is in byte 3 of 'off' for primitive types (buf ==
+            // null)
             buf.append((char) ((off & 0xFF000000) >>> 24));
         } else if (sort == OBJECT) {
             buf.append('L');
@@ -660,8 +683,9 @@ 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.
+     * 
+     * @param c
+     *            an object or array class.
      * @return the internal name of the given class.
      */
     public static String getInternalName(final Class<?> c) {
@@ -670,8 +694,9 @@ public class Type {
 
     /**
      * Returns the descriptor corresponding to the given Java type.
-     *
-     * @param c an object class, a primitive class or an array class.
+     * 
+     * @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) {
@@ -682,8 +707,9 @@ public class Type {
 
     /**
      * Returns the descriptor corresponding to the given constructor.
-     *
-     * @param c a {@link Constructor Constructor} object.
+     * 
+     * @param c
+     *            a {@link Constructor Constructor} object.
      * @return the descriptor of the given constructor.
      */
     public static String getConstructorDescriptor(final Constructor<?> c) {
@@ -698,8 +724,9 @@ public class Type {
 
     /**
      * Returns the descriptor corresponding to the given method.
-     *
-     * @param m a {@link Method Method} object.
+     * 
+     * @param m
+     *            a {@link Method Method} object.
      * @return the descriptor of the given method.
      */
     public static String getMethodDescriptor(final Method m) {
@@ -716,9 +743,11 @@ 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.
+     * 
+     * @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;
@@ -770,7 +799,7 @@ public class 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.
      */
@@ -782,10 +811,11 @@ public class 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.
+     * 
+     * @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.
      * @return an opcode that is similar to the given opcode, but adapted to
      *         this Java type. For example, if this type is <tt>float</tt> and
      *         <tt>opcode</tt> is IRETURN, this method returns FRETURN.
@@ -808,8 +838,9 @@ public class Type {
 
     /**
      * Tests if the given object is equal to this type.
-     *
-     * @param o the object to be compared 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
@@ -839,7 +870,7 @@ public class Type {
 
     /**
      * Returns a hash code value for this type.
-     *
+     * 
      * @return a hash code value for this type.
      */
     @Override
@@ -855,7 +886,7 @@ public class Type {
 
     /**
      * Returns a string representation of this type.
-     *
+     * 
      * @return the descriptor of this type.
      */
     @Override

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java
new file mode 100644
index 0000000..b772d59
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java
@@ -0,0 +1,193 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2013 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;
+
+/**
+ * The path to a type argument, wildcard bound, array element type, or static
+ * inner type within an enclosing type.
+ * 
+ * @author Eric Bruneton
+ */
+public class TypePath {
+
+    /**
+     * A type path step that steps into the element type of an array type. See
+     * {@link #getStep getStep}.
+     */
+    public final static int ARRAY_ELEMENT = 0;
+
+    /**
+     * A type path step that steps into the nested type of a class type. See
+     * {@link #getStep getStep}.
+     */
+    public final static int INNER_TYPE = 1;
+
+    /**
+     * A type path step that steps into the bound of a wildcard type. See
+     * {@link #getStep getStep}.
+     */
+    public final static int WILDCARD_BOUND = 2;
+
+    /**
+     * A type path step that steps into a type argument of a generic type. See
+     * {@link #getStep getStep}.
+     */
+    public final static int TYPE_ARGUMENT = 3;
+
+    /**
+     * The byte array where the path is stored, in Java class file format.
+     */
+    byte[] b;
+
+    /**
+     * The offset of the first byte of the type path in 'b'.
+     */
+    int offset;
+
+    /**
+     * Creates a new type path.
+     * 
+     * @param b
+     *            the byte array containing the type path in Java class file
+     *            format.
+     * @param offset
+     *            the offset of the first byte of the type path in 'b'.
+     */
+    TypePath(byte[] b, int offset) {
+        this.b = b;
+        this.offset = offset;
+    }
+
+    /**
+     * Returns the length of this path.
+     * 
+     * @return the length of this path.
+     */
+    public int getLength() {
+        return b[offset];
+    }
+
+    /**
+     * Returns the value of the given step of this path.
+     * 
+     * @param index
+     *            an index between 0 and {@link #getLength()}, exclusive.
+     * @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE
+     *         INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or
+     *         {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
+     */
+    public int getStep(int index) {
+        return b[offset + 2 * index + 1];
+    }
+
+    /**
+     * Returns the index of the type argument that the given step is stepping
+     * into. This method should only be used for steps whose value is
+     * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
+     * 
+     * @param index
+     *            an index between 0 and {@link #getLength()}, exclusive.
+     * @return the index of the type argument that the given step is stepping
+     *         into.
+     */
+    public int getStepArgument(int index) {
+        return b[offset + 2 * index + 2];
+    }
+
+    /**
+     * Converts a type path in string form, in the format used by
+     * {@link #toString()}, into a TypePath object.
+     * 
+     * @param typePath
+     *            a type path in string form, in the format used by
+     *            {@link #toString()}. May be null or empty.
+     * @return the corresponding TypePath object, or null if the path is empty.
+     */
+    public static TypePath fromString(final String typePath) {
+        if (typePath == null || typePath.length() == 0) {
+            return null;
+        }
+        int n = typePath.length();
+        ByteVector out = new ByteVector(n);
+        out.putByte(0);
+        for (int i = 0; i < n;) {
+            char c = typePath.charAt(i++);
+            if (c == '[') {
+                out.put11(ARRAY_ELEMENT, 0);
+            } else if (c == '.') {
+                out.put11(INNER_TYPE, 0);
+            } else if (c == '*') {
+                out.put11(WILDCARD_BOUND, 0);
+            } else if (c >= '0' && c <= '9') {
+                int typeArg = c - '0';
+                while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') {
+                    typeArg = typeArg * 10 + c - '0';
+                    i += 1;
+                }
+                out.put11(TYPE_ARGUMENT, typeArg);
+            }
+        }
+        out.data[0] = (byte) (out.length / 2);
+        return new TypePath(out.data, 0);
+    }
+
+    /**
+     * Returns a string representation of this type path. {@link #ARRAY_ELEMENT
+     * ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE
+     * INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps
+     * with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type
+     * argument index in decimal form.
+     */
+    @Override
+    public String toString() {
+        int length = getLength();
+        StringBuilder result = new StringBuilder(length * 2);
+        for (int i = 0; i < length; ++i) {
+            switch (getStep(i)) {
+            case ARRAY_ELEMENT:
+                result.append('[');
+                break;
+            case INNER_TYPE:
+                result.append('.');
+                break;
+            case WILDCARD_BOUND:
+                result.append('*');
+                break;
+            case TYPE_ARGUMENT:
+                result.append(getStepArgument(i));
+                break;
+            default:
+                result.append('_');
+            }
+        }
+        return result.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java
new file mode 100644
index 0000000..d518864
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java
@@ -0,0 +1,452 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2013 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;
+
+/**
+ * A reference to a type appearing in a class, field or method declaration, or
+ * on an instruction. Such a reference designates the part of the class where
+ * the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws'
+ * clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable
+ * declaration, etc).
+ * 
+ * @author Eric Bruneton
+ */
+public class TypeReference {
+
+    /**
+     * The sort of type references that target a type parameter of a generic
+     * class. See {@link #getSort getSort}.
+     */
+    public final static int CLASS_TYPE_PARAMETER = 0x00;
+
+    /**
+     * The sort of type references that target a type parameter of a generic
+     * method. See {@link #getSort getSort}.
+     */
+    public final static int METHOD_TYPE_PARAMETER = 0x01;
+
+    /**
+     * The sort of type references that target the super class of a class or one
+     * of the interfaces it implements. See {@link #getSort getSort}.
+     */
+    public final static int CLASS_EXTENDS = 0x10;
+
+    /**
+     * The sort of type references that target a bound of a type parameter of a
+     * generic class. See {@link #getSort getSort}.
+     */
+    public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11;
+
+    /**
+     * The sort of type references that target a bound of a type parameter of a
+     * generic method. See {@link #getSort getSort}.
+     */
+    public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12;
+
+    /**
+     * The sort of type references that target the type of a field. See
+     * {@link #getSort getSort}.
+     */
+    public final static int FIELD = 0x13;
+
+    /**
+     * The sort of type references that target the return type of a method. See
+     * {@link #getSort getSort}.
+     */
+    public final static int METHOD_RETURN = 0x14;
+
+    /**
+     * The sort of type references that target the receiver type of a method.
+     * See {@link #getSort getSort}.
+     */
+    public final static int METHOD_RECEIVER = 0x15;
+
+    /**
+     * The sort of type references that target the type of a formal parameter of
+     * a method. See {@link #getSort getSort}.
+     */
+    public final static int METHOD_FORMAL_PARAMETER = 0x16;
+
+    /**
+     * The sort of type references that target the type of an exception declared
+     * in the throws clause of a method. See {@link #getSort getSort}.
+     */
+    public final static int THROWS = 0x17;
+
+    /**
+     * The sort of type references that target the type of a local variable in a
+     * method. See {@link #getSort getSort}.
+     */
+    public final static int LOCAL_VARIABLE = 0x40;
+
+    /**
+     * The sort of type references that target the type of a resource variable
+     * in a method. See {@link #getSort getSort}.
+     */
+    public final static int RESOURCE_VARIABLE = 0x41;
+
+    /**
+     * The sort of type references that target the type of the exception of a
+     * 'catch' clause in a method. See {@link #getSort getSort}.
+     */
+    public final static int EXCEPTION_PARAMETER = 0x42;
+
+    /**
+     * The sort of type references that target the type declared in an
+     * 'instanceof' instruction. See {@link #getSort getSort}.
+     */
+    public final static int INSTANCEOF = 0x43;
+
+    /**
+     * The sort of type references that target the type of the object created by
+     * a 'new' instruction. See {@link #getSort getSort}.
+     */
+    public final static int NEW = 0x44;
+
+    /**
+     * The sort of type references that target the receiver type of a
+     * constructor reference. See {@link #getSort getSort}.
+     */
+    public final static int CONSTRUCTOR_REFERENCE = 0x45;
+
+    /**
+     * The sort of type references that target the receiver type of a method
+     * reference. See {@link #getSort getSort}.
+     */
+    public final static int METHOD_REFERENCE = 0x46;
+
+    /**
+     * The sort of type references that target the type declared in an explicit
+     * or implicit cast instruction. See {@link #getSort getSort}.
+     */
+    public final static int CAST = 0x47;
+
+    /**
+     * The sort of type references that target a type parameter of a generic
+     * constructor in a constructor call. See {@link #getSort getSort}.
+     */
+    public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
+
+    /**
+     * The sort of type references that target a type parameter of a generic
+     * method in a method call. See {@link #getSort getSort}.
+     */
+    public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
+
+    /**
+     * The sort of type references that target a type parameter of a generic
+     * constructor in a constructor reference. See {@link #getSort getSort}.
+     */
+    public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
+
+    /**
+     * The sort of type references that target a type parameter of a generic
+     * method in a method reference. See {@link #getSort getSort}.
+     */
+    public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
+
+    /**
+     * The type reference value in Java class file format.
+     */
+    private int value;
+
+    /**
+     * Creates a new TypeReference.
+     * 
+     * @param typeRef
+     *            the int encoded value of the type reference, as received in a
+     *            visit method related to type annotations, like
+     *            visitTypeAnnotation.
+     */
+    public TypeReference(int typeRef) {
+        this.value = typeRef;
+    }
+
+    /**
+     * Returns a type reference of the given sort.
+     * 
+     * @param sort
+     *            {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
+     *            {@link #METHOD_RECEIVER METHOD_RECEIVER},
+     *            {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
+     *            {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
+     *            {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
+     *            {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or
+     *            {@link #METHOD_REFERENCE METHOD_REFERENCE}.
+     * @return a type reference of the given sort.
+     */
+    public static TypeReference newTypeReference(int sort) {
+        return new TypeReference(sort << 24);
+    }
+
+    /**
+     * Returns a reference to a type parameter of a generic class or method.
+     * 
+     * @param sort
+     *            {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
+     *            {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
+     * @param paramIndex
+     *            the type parameter index.
+     * @return a reference to the given generic class or method type parameter.
+     */
+    public static TypeReference newTypeParameterReference(int sort,
+            int paramIndex) {
+        return new TypeReference((sort << 24) | (paramIndex << 16));
+    }
+
+    /**
+     * Returns a reference to a type parameter bound of a generic class or
+     * method.
+     * 
+     * @param sort
+     *            {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
+     *            {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
+     * @param paramIndex
+     *            the type parameter index.
+     * @param boundIndex
+     *            the type bound index within the above type parameters.
+     * @return a reference to the given generic class or method type parameter
+     *         bound.
+     */
+    public static TypeReference newTypeParameterBoundReference(int sort,
+            int paramIndex, int boundIndex) {
+        return new TypeReference((sort << 24) | (paramIndex << 16)
+                | (boundIndex << 8));
+    }
+
+    /**
+     * Returns a reference to the super class or to an interface of the
+     * 'implements' clause of a class.
+     * 
+     * @param itfIndex
+     *            the index of an interface in the 'implements' clause of a
+     *            class, or -1 to reference the super class of the class.
+     * @return a reference to the given super type of a class.
+     */
+    public static TypeReference newSuperTypeReference(int itfIndex) {
+        itfIndex &= 0xFFFF;
+        return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8));
+    }
+
+    /**
+     * Returns a reference to the type of a formal parameter of a method.
+     * 
+     * @param paramIndex
+     *            the formal parameter index.
+     * 
+     * @return a reference to the type of the given method formal parameter.
+     */
+    public static TypeReference newFormalParameterReference(int paramIndex) {
+        return new TypeReference((METHOD_FORMAL_PARAMETER << 24)
+                | (paramIndex << 16));
+    }
+
+    /**
+     * Returns a reference to the type of an exception, in a 'throws' clause of
+     * a method.
+     * 
+     * @param exceptionIndex
+     *            the index of an exception in a 'throws' clause of a method.
+     * 
+     * @return a reference to the type of the given exception.
+     */
+    public static TypeReference newExceptionReference(int exceptionIndex) {
+        return new TypeReference((THROWS << 24) | (exceptionIndex << 8));
+    }
+
+    /**
+     * Returns a reference to the type of the exception declared in a 'catch'
+     * clause of a method.
+     * 
+     * @param tryCatchBlockIndex
+     *            the index of a try catch block (using the order in which they
+     *            are visited with visitTryCatchBlock).
+     * 
+     * @return a reference to the type of the given exception.
+     */
+    public static TypeReference newTryCatchReference(int tryCatchBlockIndex) {
+        return new TypeReference((EXCEPTION_PARAMETER << 24)
+                | (tryCatchBlockIndex << 8));
+    }
+
+    /**
+     * Returns a reference to the type of a type argument in a constructor or
+     * method call or reference.
+     * 
+     * @param sort
+     *            {@link #CAST CAST},
+     *            {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+     *            CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+     *            {@link #METHOD_INVOCATION_TYPE_ARGUMENT
+     *            METHOD_INVOCATION_TYPE_ARGUMENT},
+     *            {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+     *            CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+     *            {@link #METHOD_REFERENCE_TYPE_ARGUMENT
+     *            METHOD_REFERENCE_TYPE_ARGUMENT}.
+     * @param argIndex
+     *            the type argument index.
+     * 
+     * @return a reference to the type of the given type argument.
+     */
+    public static TypeReference newTypeArgumentReference(int sort, int argIndex) {
+        return new TypeReference((sort << 24) | argIndex);
+    }
+
+    /**
+     * Returns the sort of this type reference.
+     * 
+     * @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
+     *         {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
+     *         {@link #CLASS_EXTENDS CLASS_EXTENDS},
+     *         {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND},
+     *         {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND},
+     *         {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
+     *         {@link #METHOD_RECEIVER METHOD_RECEIVER},
+     *         {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER},
+     *         {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
+     *         {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
+     *         {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER},
+     *         {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
+     *         {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE},
+     *         {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST},
+     *         {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+     *         CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+     *         {@link #METHOD_INVOCATION_TYPE_ARGUMENT
+     *         METHOD_INVOCATION_TYPE_ARGUMENT},
+     *         {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+     *         CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+     *         {@link #METHOD_REFERENCE_TYPE_ARGUMENT
+     *         METHOD_REFERENCE_TYPE_ARGUMENT}.
+     */
+    public int getSort() {
+        return value >>> 24;
+    }
+
+    /**
+     * Returns the index of the type parameter referenced by this type
+     * reference. This method must only be used for type references whose sort
+     * is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
+     * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
+     * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
+     * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
+     * 
+     * @return a type parameter index.
+     */
+    public int getTypeParameterIndex() {
+        return (value & 0x00FF0000) >> 16;
+    }
+
+    /**
+     * Returns the index of the type parameter bound, within the type parameter
+     * {@link #getTypeParameterIndex}, referenced by this type reference. This
+     * method must only be used for type references whose sort is
+     * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
+     * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
+     * 
+     * @return a type parameter bound index.
+     */
+    public int getTypeParameterBoundIndex() {
+        return (value & 0x0000FF00) >> 8;
+    }
+
+    /**
+     * Returns the index of the "super type" of a class that is referenced by
+     * this type reference. This method must only be used for type references
+     * whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}.
+     * 
+     * @return the index of an interface in the 'implements' clause of a class,
+     *         or -1 if this type reference references the type of the super
+     *         class.
+     */
+    public int getSuperTypeIndex() {
+        return (short) ((value & 0x00FFFF00) >> 8);
+    }
+
+    /**
+     * Returns the index of the formal parameter whose type is referenced by
+     * this type reference. This method must only be used for type references
+     * whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}.
+     * 
+     * @return a formal parameter index.
+     */
+    public int getFormalParameterIndex() {
+        return (value & 0x00FF0000) >> 16;
+    }
+
+    /**
+     * Returns the index of the exception, in a 'throws' clause of a method,
+     * whose type is referenced by this type reference. This method must only be
+     * used for type references whose sort is {@link #THROWS THROWS}.
+     * 
+     * @return the index of an exception in the 'throws' clause of a method.
+     */
+    public int getExceptionIndex() {
+        return (value & 0x00FFFF00) >> 8;
+    }
+
+    /**
+     * Returns the index of the try catch block (using the order in which they
+     * are visited with visitTryCatchBlock), whose 'catch' type is referenced by
+     * this type reference. This method must only be used for type references
+     * whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} .
+     * 
+     * @return the index of an exception in the 'throws' clause of a method.
+     */
+    public int getTryCatchBlockIndex() {
+        return (value & 0x00FFFF00) >> 8;
+    }
+
+    /**
+     * Returns the index of the type argument referenced by this type reference.
+     * This method must only be used for type references whose sort is
+     * {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+     * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+     * {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT},
+     * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+     * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+     * {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}.
+     * 
+     * @return a type parameter index.
+     */
+    public int getTypeArgumentIndex() {
+        return value & 0xFF;
+    }
+
+    /**
+     * Returns the int encoded value of this type reference, suitable for use in
+     * visit methods related to type annotations, like visitTypeAnnotation.
+     * 
+     * @return the int encoded value of this type reference.
+     */
+    public int getValue() {
+        return value;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/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
new file mode 100644
index 0000000..a53995b
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java
@@ -0,0 +1,646 @@
+/***
+ * 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.commons;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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;
+
+/**
+ * A {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor} 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<Object> stackFrame;
+
+    private Map<Label, List<Object>> branches;
+
+    /**
+     * Creates a new {@link AdviceAdapter}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @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 int api, final MethodVisitor mv,
+            final int access, final String name, final String desc) {
+        super(api, mv, access, name, desc);
+        methodAccess = access;
+        methodDesc = desc;
+        constructor = "<init>".equals(name);
+    }
+
+    @Override
+    public void visitCode() {
+        mv.visitCode();
+        if (constructor) {
+            stackFrame = new ArrayList<Object>();
+            branches = new HashMap<Label, List<Object>>();
+        } else {
+            superInitialized = true;
+            onMethodEnter();
+        }
+    }
+
+    @Override
+    public void visitLabel(final Label label) {
+        mv.visitLabel(label);
+        if (constructor && branches != null) {
+            List<Object> frame = branches.get(label);
+            if (frame != null) {
+                stackFrame = frame;
+                branches.remove(label);
+            }
+        }
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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;
+            }
+        }
+    }
+
+    @Override
+    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);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void visitIntInsn(final int opcode, final int operand) {
+        mv.visitIntInsn(opcode, operand);
+        if (constructor && opcode != NEWARRAY) {
+            pushValue(OTHER);
+        }
+    }
+
+    @Override
+    public void visitLdcInsn(final Object cst) {
+        mv.visitLdcInsn(cst);
+        if (constructor) {
+            pushValue(OTHER);
+            if (cst instanceof Double || cst instanceof Long) {
+                pushValue(OTHER);
+            }
+        }
+    }
+
+    @Override
+    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);
+        }
+    }
+
+    @Override
+    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);
+        }
+    }
+
+    @Deprecated
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (api >= Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc,
+                opcode == Opcodes.INVOKEINTERFACE);
+    }
+
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    private void doVisitMethodInsn(int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        mv.visitMethodInsn(opcode, owner, name, desc, itf);
+        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:
+            // 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);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+        if (constructor) {
+            Type[] types = Type.getArgumentTypes(desc);
+            for (int i = 0; i < types.length; i++) {
+                popValue();
+                if (types[i].getSize() == 2) {
+                    popValue();
+                }
+            }
+
+            Type returnType = Type.getReturnType(desc);
+            if (returnType != Type.VOID_TYPE) {
+                pushValue(OTHER);
+                if (returnType.getSize() == 2) {
+                    pushValue(OTHER);
+                }
+            }
+        }
+    }
+
+    @Override
+    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);
+        }
+    }
+
+    @Override
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
+        mv.visitLookupSwitchInsn(dflt, keys, labels);
+        if (constructor) {
+            popValue();
+            addBranches(dflt, labels);
+        }
+    }
+
+    @Override
+    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);
+        }
+    }
+
+    @Override
+    public void visitTryCatchBlock(Label start, Label end, Label handler,
+            String type) {
+        super.visitTryCatchBlock(start, end, handler, type);
+        if (constructor && !branches.containsKey(handler)) {
+            List<Object> stackFrame = new ArrayList<Object>();
+            stackFrame.add(OTHER);
+            branches.put(handler, stackFrame);
+        }
+    }
+
+    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<Object>(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
+}


[19/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/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 f0676b7..4585e67 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
@@ -30,27 +30,33 @@
 package org.apache.tapestry5.internal.plastic.asm;
 
 /**
- * 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>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>
- * must be called <i>before</i> the labels passed as arguments have been
- * 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.
- *
+ * A visitor to visit a Java method. The methods of this class must be called in
+ * the following order: ( <tt>visitParameter</tt> )* [
+ * <tt>visitAnnotationDefault</tt> ] ( <tt>visitAnnotation</tt> |
+ * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* [
+ * <tt>visitCode</tt> ( <tt>visitFrame</tt> | <tt>visit<i>X</i>Insn</tt> |
+ * <tt>visitLabel</tt> | <tt>visitInsnAnnotation</tt> |
+ * <tt>visitTryCatchBlock</tt> | <tt>visitTryCatchBlockAnnotation</tt> |
+ * <tt>visitLocalVariable</tt> | <tt>visitLocalVariableAnnotation</tt> |
+ * <tt>visitLineNumber</tt> )* <tt>visitMaxs</tt> ] <tt>visitEnd</tt>. In
+ * addition, the <tt>visit<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>visitInsnAnnotation</tt> must be called <i>after</i> the annotated
+ * instruction, <tt>visitTryCatchBlock</tt> must be called <i>before</i> the
+ * labels passed as arguments have been visited,
+ * <tt>visitTryCatchBlockAnnotation</tt> must be called <i>after</i> the
+ * corresponding try catch block has been visited, and the
+ * <tt>visitLocalVariable</tt>, <tt>visitLocalVariableAnnotation</tt> and
+ * <tt>visitLineNumber</tt> methods must be called <i>after</i> the labels
+ * passed as arguments have been visited.
+ * 
  * @author Eric Bruneton
  */
 public abstract class MethodVisitor {
 
     /**
      * The ASM API version implemented by this visitor. The value of this field
-     * must be one of {@link Opcodes#ASM4}.
+     * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
      */
     protected final int api;
 
@@ -62,9 +68,10 @@ public abstract class MethodVisitor {
 
     /**
      * Constructs a new {@link MethodVisitor}.
-     *
-     * @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 MethodVisitor(final int api) {
         this(api, null);
@@ -72,30 +79,51 @@ public abstract class MethodVisitor {
 
     /**
      * 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.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @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) {
+        if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
             throw new IllegalArgumentException();
-        }*/
+        }
         this.api = api;
         this.mv = mv;
     }
 
     // -------------------------------------------------------------------------
-    // Annotations and non standard attributes
+    // Parameters, annotations and non standard attributes
     // -------------------------------------------------------------------------
 
     /**
+     * Visits a parameter of this method.
+     * 
+     * @param name
+     *            parameter name or null if none is provided.
+     * @param access
+     *            the parameter's access flags, only <tt>ACC_FINAL</tt>,
+     *            <tt>ACC_SYNTHETIC</tt> or/and <tt>ACC_MANDATED</tt> are
+     *            allowed (see {@link Opcodes}).
+     */
+    public void visitParameter(String name, int access) {
+        if (api < Opcodes.ASM5) {
+            throw new RuntimeException();
+        }
+        if (mv != null) {
+            mv.visitParameter(name, access);
+        }
+    }
+
+    /**
      * 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'
+     *         annotation interface method, or <tt>null</tt> if this visitor is
+     *         not interested in visiting this default value. The 'name'
      *         parameters passed to the methods of this annotation visitor are
      *         ignored. Moreover, exacly one visit method must be called on this
      *         annotation visitor, followed by visitEnd.
@@ -109,9 +137,11 @@ public abstract class MethodVisitor {
 
     /**
      * 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.
+     * 
+     * @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.
      */
@@ -123,19 +153,55 @@ public abstract class MethodVisitor {
     }
 
     /**
+     * Visits an annotation on a type in the method signature.
+     * 
+     * @param typeRef
+     *            a reference to the annotated type. The sort of this type
+     *            reference must be {@link TypeReference#METHOD_TYPE_PARAMETER
+     *            METHOD_TYPE_PARAMETER},
+     *            {@link TypeReference#METHOD_TYPE_PARAMETER_BOUND
+     *            METHOD_TYPE_PARAMETER_BOUND},
+     *            {@link TypeReference#METHOD_RETURN METHOD_RETURN},
+     *            {@link TypeReference#METHOD_RECEIVER METHOD_RECEIVER},
+     *            {@link TypeReference#METHOD_FORMAL_PARAMETER
+     *            METHOD_FORMAL_PARAMETER} or {@link TypeReference#THROWS
+     *            THROWS}. 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.
+     * @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.
+     */
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        if (api < Opcodes.ASM5) {
+            throw new RuntimeException();
+        }
+        if (mv != null) {
+            return mv.visitTypeAnnotation(typeRef, typePath, 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.
+     * 
+     * @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.
      */
-    public AnnotationVisitor visitParameterAnnotation(
-        int parameter,
-        String desc,
-        boolean visible)
-    {
+    public AnnotationVisitor visitParameterAnnotation(int parameter,
+            String desc, boolean visible) {
         if (mv != null) {
             return mv.visitParameterAnnotation(parameter, desc, visible);
         }
@@ -144,8 +210,9 @@ public abstract class MethodVisitor {
 
     /**
      * Visits a non standard attribute of this method.
-     *
-     * @param attr an attribute.
+     * 
+     * @param attr
+     *            an attribute.
      */
     public void visitAttribute(Attribute attr) {
         if (mv != null) {
@@ -169,57 +236,76 @@ public abstract class MethodVisitor {
      * such as GOTO or THROW, that is the target of a jump instruction, or that
      * starts an exception handler block. The visited types must describe the
      * values of the local variables and of the operand stack elements <i>just
-     * before</i> <b>i</b> is executed. <br> <br> (*) this is mandatory only
-     * for classes whose version is greater than or equal to
-     * {@link Opcodes#V1_6 V1_6}. <br> <br> Packed frames are basically
-     * "deltas" from the state of the previous frame (very first frame is
-     * implicitly defined by the method's parameters and access flags): <ul>
+     * before</i> <b>i</b> is executed.<br>
+     * <br>
+     * (*) this is mandatory only for classes whose version is greater than or
+     * equal to {@link Opcodes#V1_6 V1_6}. <br>
+     * <br>
+     * The frames of a method must be given either in expanded form, or in
+     * compressed form (all frames must use the same format, i.e. you must not
+     * mix expanded and compressed frames within a single method):
+     * <ul>
+     * <li>In expanded form, all frames must have the F_NEW type.</li>
+     * <li>In compressed form, frames are basically "deltas" from the state of
+     * the previous frame:
+     * <ul>
      * <li>{@link Opcodes#F_SAME} representing frame with exactly the same
-     * locals as the previous frame and with the empty stack.</li> <li>{@link Opcodes#F_SAME1}
-     * representing frame with exactly the same locals as the previous frame and
-     * with single value on the stack (<code>nStack</code> is 1 and
-     * <code>stack[0]</code> contains value for the type of the stack item).</li>
+     * locals as the previous frame and with the empty stack.</li>
+     * <li>{@link Opcodes#F_SAME1} representing frame with exactly the same
+     * locals as the previous frame and with single value on the stack (
+     * <code>nStack</code> is 1 and <code>stack[0]</code> contains value for the
+     * type of the stack item).</li>
      * <li>{@link Opcodes#F_APPEND} representing frame with current locals are
      * the same as the locals in the previous frame, except that additional
      * locals are defined (<code>nLocal</code> is 1, 2 or 3 and
      * <code>local</code> elements contains values representing added types).</li>
-     * <li>{@link Opcodes#F_CHOP} representing frame with current locals are
-     * the same as the locals in the previous frame, except that the last 1-3
-     * 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},
-     *        {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
-     *        {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed
-     *        frames.
-     * @param nLocal the number of local variables in the visited frame.
-     * @param local the local variable types in this frame. This array must not
-     *        be modified. Primitive types are represented by
-     *        {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
-     *        {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
-     *        {@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
-     *        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.
-     * @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).
-     */
-    public void visitFrame(
-        int type,
-        int nLocal,
-        Object[] local,
-        int nStack,
-        Object[] stack)
-    {
+     * <li>{@link Opcodes#F_CHOP} representing frame with current locals are the
+     * same as the locals in the previous frame, except that the last 1-3 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>
+     * </ul>
+     * </li>
+     * </ul>
+     * <br>
+     * In both cases the first frame, corresponding to the method's parameters
+     * and access flags, is implicit and must not be visited. Also, it is
+     * illegal to visit two or more frames for the same code location (i.e., at
+     * least one instruction must be visited between two calls to visitFrame).
+     * 
+     * @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},
+     *            {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
+     *            {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for
+     *            compressed frames.
+     * @param nLocal
+     *            the number of local variables in the visited frame.
+     * @param local
+     *            the local variable types in this frame. This array must not be
+     *            modified. Primitive types are represented by
+     *            {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
+     *            {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+     *            {@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 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.
+     * @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).
+     */
+    public void visitFrame(int type, int nLocal, Object[] local, int nStack,
+            Object[] stack) {
         if (mv != null) {
             mv.visitFrame(type, nLocal, local, nStack, stack);
         }
@@ -231,21 +317,23 @@ public abstract class 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,
-     *        FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD, FALOAD,
-     *        DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE, FASTORE,
-     *        DASTORE, AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2, DUP,
-     *        DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP, IADD, LADD, FADD,
-     *        DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV,
-     *        FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL,
-     *        LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR,
-     *        I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B,
-     *        I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN,
-     *        FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW,
-     *        MONITORENTER, or MONITOREXIT.
+     * 
+     * @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, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD,
+     *            LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD,
+     *            IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE,
+     *            SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1,
+     *            DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB,
+     *            IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM,
+     *            FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR,
+     *            IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D,
+     *            L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S,
+     *            LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN,
+     *            DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER,
+     *            or MONITOREXIT.
      */
     public void visitInsn(int opcode) {
         if (mv != null) {
@@ -255,18 +343,21 @@ public abstract class MethodVisitor {
 
     /**
      * 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
-     *        opcode is BIPUSH, operand value should be between Byte.MIN_VALUE
-     *        and Byte.MAX_VALUE.<br> When opcode is SIPUSH, operand value
-     *        should be between Short.MIN_VALUE and Short.MAX_VALUE.<br> When
-     *        opcode is NEWARRAY, operand value should be one of
-     *        {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR},
-     *        {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE},
-     *        {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT},
-     *        {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.
+     * 
+     * @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 opcode is BIPUSH, operand value should be between
+     *            Byte.MIN_VALUE and Byte.MAX_VALUE.<br>
+     *            When opcode is SIPUSH, operand value should be between
+     *            Short.MIN_VALUE and Short.MAX_VALUE.<br>
+     *            When opcode is NEWARRAY, operand value should be one of
+     *            {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR},
+     *            {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE},
+     *            {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT},
+     *            {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.
      */
     public void visitIntInsn(int opcode, int operand) {
         if (mv != null) {
@@ -277,12 +368,14 @@ public abstract class MethodVisitor {
     /**
      * 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.
+     * 
+     * @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.
      */
     public void visitVarInsn(int opcode, int var) {
         if (mv != null) {
@@ -293,12 +386,14 @@ public abstract class MethodVisitor {
     /**
      * 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
-     *        Type#getInternalName() getInternalName}).
+     * 
+     * @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 Type#getInternalName() getInternalName}).
      */
     public void visitTypeInsn(int opcode, String type) {
         if (mv != null) {
@@ -309,15 +404,20 @@ public abstract class MethodVisitor {
     /**
      * 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
-     *        Type#getInternalName() getInternalName}).
-     * @param name the field's name.
-     * @param desc the field's descriptor (see {@link Type Type}).
-     */
-    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
+     * 
+     * @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 Type#getInternalName() getInternalName}).
+     * @param name
+     *            the field's name.
+     * @param desc
+     *            the field's descriptor (see {@link Type Type}).
+     */
+    public void visitFieldInsn(int opcode, String owner, String name,
+            String desc) {
         if (mv != null) {
             mv.visitFieldInsn(opcode, owner, name, desc);
         }
@@ -326,34 +426,83 @@ public abstract class MethodVisitor {
     /**
      * 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
-     *        or INVOKEINTERFACE.
-     * @param owner the internal name of the method's owner class (see {@link
-     *        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) {
+     * 
+     * @param opcode
+     *            the opcode of the type instruction to be visited. This opcode
+     *            is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+     *            INVOKEINTERFACE.
+     * @param owner
+     *            the internal name of the method's owner class (see
+     *            {@link Type#getInternalName() getInternalName}).
+     * @param name
+     *            the method's name.
+     * @param desc
+     *            the method's descriptor (see {@link Type Type}).
+     */
+    @Deprecated
+    public void visitMethodInsn(int opcode, String owner, String name,
+            String desc) {
+        if (api >= Opcodes.ASM5) {
+            boolean itf = opcode == Opcodes.INVOKEINTERFACE;
+            visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
         if (mv != null) {
             mv.visitMethodInsn(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 or
+     *            INVOKEINTERFACE.
+     * @param owner
+     *            the internal name of the method's owner class (see
+     *            {@link Type#getInternalName() getInternalName}).
+     * @param name
+     *            the method's name.
+     * @param desc
+     *            the method's descriptor (see {@link Type Type}).
+     * @param itf
+     *            if the method's owner class is an interface.
+     */
+    public void visitMethodInsn(int opcode, String owner, String name,
+            String desc, boolean itf) {
+        if (api < Opcodes.ASM5) {
+            if (itf != (opcode == Opcodes.INVOKEINTERFACE)) {
+                throw new IllegalArgumentException(
+                        "INVOKESPECIAL/STATIC on interfaces require ASM 5");
+            }
+            visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        if (mv != null) {
+            mv.visitMethodInsn(opcode, owner, name, desc, itf);
+        }
+    }
+
+    /**
      * 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.
-     */
-    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
+     * 
+     * @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.
+     */
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
         if (mv != null) {
             mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
         }
@@ -362,14 +511,16 @@ public abstract class MethodVisitor {
     /**
      * 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,
-     *        IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
-     * @param label the operand of the instruction to be visited. This operand
-     *        is a label that designates the instruction to which the jump
-     *        instruction may jump.
+     * 
+     * @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, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
+     * @param label
+     *            the operand of the instruction to be visited. This operand is
+     *            a label that designates the instruction to which the jump
+     *            instruction may jump.
      */
     public void visitJumpInsn(int opcode, Label label) {
         if (mv != null) {
@@ -380,8 +531,9 @@ public abstract class MethodVisitor {
     /**
      * Visits a label. A label designates the instruction that will be visited
      * just after it.
-     *
-     * @param label a {@link Label Label} object.
+     * 
+     * @param label
+     *            a {@link Label Label} object.
      */
     public void visitLabel(Label label) {
         if (mv != null) {
@@ -398,41 +550,44 @@ public abstract class MethodVisitor {
      * 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 (cst instanceof Double) {
      *     // ...
-     *   } else if (sort == Type.METHOD) {
+     * } else if (cst instanceof String) {
      *     // ...
-     *   } else {
-     *     // throw an exception
-     *   }
+     * } 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}, 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.
+     *     // 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}, 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.
      */
     public void visitLdcInsn(Object cst) {
         if (mv != null) {
@@ -442,9 +597,11 @@ public abstract class MethodVisitor {
 
     /**
      * Visits an IINC instruction.
-     *
-     * @param var index of the local variable to be incremented.
-     * @param increment amount to increment the local variable by.
+     * 
+     * @param var
+     *            index of the local variable to be incremented.
+     * @param increment
+     *            amount to increment the local variable by.
      */
     public void visitIincInsn(int var, int increment) {
         if (mv != null) {
@@ -454,14 +611,19 @@ public abstract class MethodVisitor {
 
     /**
      * 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.
-     */
-    public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
+     * 
+     * @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 void visitTableSwitchInsn(int min, int max, Label dflt,
+            Label... labels) {
         if (mv != null) {
             mv.visitTableSwitchInsn(min, max, dflt, labels);
         }
@@ -469,11 +631,14 @@ public abstract class MethodVisitor {
 
     /**
      * 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.
+     * 
+     * @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.
      */
     public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
         if (mv != null) {
@@ -483,9 +648,11 @@ public abstract class MethodVisitor {
 
     /**
      * Visits a MULTIANEWARRAY instruction.
-     *
-     * @param desc an array type descriptor (see {@link Type Type}).
-     * @param dims number of dimensions of the array to allocate.
+     * 
+     * @param desc
+     *            an array type descriptor (see {@link Type Type}).
+     * @param dims
+     *            number of dimensions of the array to allocate.
      */
     public void visitMultiANewArrayInsn(String desc, int dims) {
         if (mv != null) {
@@ -493,68 +660,191 @@ public abstract class MethodVisitor {
         }
     }
 
+    /**
+     * Visits an annotation on an instruction. This method must be called just
+     * <i>after</i> the annotated instruction. It can be called several times
+     * for the same instruction.
+     * 
+     * @param typeRef
+     *            a reference to the annotated type. The sort of this type
+     *            reference must be {@link TypeReference#INSTANCEOF INSTANCEOF},
+     *            {@link TypeReference#NEW NEW},
+     *            {@link TypeReference#CONSTRUCTOR_REFERENCE
+     *            CONSTRUCTOR_REFERENCE}, {@link TypeReference#METHOD_REFERENCE
+     *            METHOD_REFERENCE}, {@link TypeReference#CAST CAST},
+     *            {@link TypeReference#CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+     *            CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+     *            {@link TypeReference#METHOD_INVOCATION_TYPE_ARGUMENT
+     *            METHOD_INVOCATION_TYPE_ARGUMENT},
+     *            {@link TypeReference#CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+     *            CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+     *            {@link TypeReference#METHOD_REFERENCE_TYPE_ARGUMENT
+     *            METHOD_REFERENCE_TYPE_ARGUMENT}. 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.
+     * @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.
+     */
+    public AnnotationVisitor visitInsnAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        if (api < Opcodes.ASM5) {
+            throw new RuntimeException();
+        }
+        if (mv != null) {
+            return mv.visitInsnAnnotation(typeRef, typePath, desc, visible);
+        }
+        return null;
+    }
+
     // -------------------------------------------------------------------------
     // Exceptions table entries, debug information, max stack and max locals
     // -------------------------------------------------------------------------
 
     /**
      * 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.
-     * @param type internal name of the type of exceptions handled by the
-     *        handler, or <tt>null</tt> to catch any exceptions (for "finally"
-     *        blocks).
-     * @throws IllegalArgumentException if one of the labels has already been
-     *         visited by this visitor (by the {@link #visitLabel visitLabel}
-     *         method).
-     */
-    public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
+     * 
+     * @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).
+     * @throws IllegalArgumentException
+     *             if one of the labels has already been visited by this visitor
+     *             (by the {@link #visitLabel visitLabel} method).
+     */
+    public void visitTryCatchBlock(Label start, Label end, Label handler,
+            String type) {
         if (mv != null) {
             mv.visitTryCatchBlock(start, end, handler, type);
         }
     }
 
     /**
+     * Visits an annotation on an exception handler type. This method must be
+     * called <i>after</i> the {@link #visitTryCatchBlock} for the annotated
+     * exception handler. It can be called several times for the same exception
+     * handler.
+     * 
+     * @param typeRef
+     *            a reference to the annotated type. The sort of this type
+     *            reference must be {@link TypeReference#EXCEPTION_PARAMETER
+     *            EXCEPTION_PARAMETER}. 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.
+     * @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.
+     */
+    public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        if (api < Opcodes.ASM5) {
+            throw new RuntimeException();
+        }
+        if (mv != null) {
+            return mv.visitTryCatchAnnotation(typeRef, typePath, desc, visible);
+        }
+        return null;
+    }
+
+    /**
      * 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
-     *        <tt>null</tt> if the local variable type does not use generic
-     *        types.
-     * @param start the first instruction corresponding to the scope of this
-     *        local variable (inclusive).
-     * @param end the last instruction corresponding to the scope of this local
-     *        variable (exclusive).
-     * @param index the local variable's index.
-     * @throws IllegalArgumentException if one of the labels has not already
-     *         been visited by this visitor (by the
-     *         {@link #visitLabel visitLabel} method).
-     */
-    public void visitLocalVariable(
-        String name,
-        String desc,
-        String signature,
-        Label start,
-        Label end,
-        int index)
-    {
+     * 
+     * @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
+     *            <tt>null</tt> if the local variable type does not use generic
+     *            types.
+     * @param start
+     *            the first instruction corresponding to the scope of this local
+     *            variable (inclusive).
+     * @param end
+     *            the last instruction corresponding to the scope of this local
+     *            variable (exclusive).
+     * @param index
+     *            the local variable's index.
+     * @throws IllegalArgumentException
+     *             if one of the labels has not already been visited by this
+     *             visitor (by the {@link #visitLabel visitLabel} method).
+     */
+    public void visitLocalVariable(String name, String desc, String signature,
+            Label start, Label end, int index) {
         if (mv != null) {
             mv.visitLocalVariable(name, desc, signature, start, end, index);
         }
     }
 
     /**
+     * Visits an annotation on a local variable type.
+     * 
+     * @param typeRef
+     *            a reference to the annotated type. The sort of this type
+     *            reference must be {@link TypeReference#LOCAL_VARIABLE
+     *            LOCAL_VARIABLE} or {@link TypeReference#RESOURCE_VARIABLE
+     *            RESOURCE_VARIABLE}. 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 start
+     *            the fist instructions corresponding to the continuous ranges
+     *            that make the scope of this local variable (inclusive).
+     * @param end
+     *            the last instructions corresponding to the continuous ranges
+     *            that make the scope of this local variable (exclusive). This
+     *            array must have the same size as the 'start' array.
+     * @param index
+     *            the local variable's index in each range. This array must have
+     *            the same size as the 'start' array.
+     * @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.
+     */
+    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+            TypePath typePath, Label[] start, Label[] end, int[] index,
+            String desc, boolean visible) {
+        if (api < Opcodes.ASM5) {
+            throw new RuntimeException();
+        }
+        if (mv != null) {
+            return mv.visitLocalVariableAnnotation(typeRef, typePath, start,
+                    end, index, desc, visible);
+        }
+        return null;
+    }
+
+    /**
      * 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.
-     * @throws IllegalArgumentException if <tt>start</tt> has not already been
-     *         visited by this visitor (by the {@link #visitLabel visitLabel}
-     *         method).
+     * 
+     * @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.
+     * @throws IllegalArgumentException
+     *             if <tt>start</tt> has not already been visited by this
+     *             visitor (by the {@link #visitLabel visitLabel} method).
      */
     public void visitLineNumber(int line, Label start) {
         if (mv != null) {
@@ -565,9 +855,11 @@ public abstract class MethodVisitor {
     /**
      * 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.
+     * 
+     * @param maxStack
+     *            maximum stack size of the method.
+     * @param maxLocals
+     *            maximum number of local variables for the method.
      */
     public void visitMaxs(int maxStack, int maxLocals) {
         if (mv != null) {


[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?"

Posted by ka...@apache.org.
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;
+    }
+}


[07/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceInterpreter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceInterpreter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceInterpreter.java
new file mode 100644
index 0000000..284fbef
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceInterpreter.java
@@ -0,0 +1,198 @@
+/***
+ * 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.HashSet;
+import java.util.List;
+import java.util.Set;
+
+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.FieldInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.InvokeDynamicInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LdcInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodInsnNode;
+
+/**
+ * An {@link Interpreter} for {@link SourceValue} values.
+ * 
+ * @author Eric Bruneton
+ */
+public class SourceInterpreter extends Interpreter<SourceValue> implements
+        Opcodes {
+
+    public SourceInterpreter() {
+        super(ASM5);
+    }
+
+    protected SourceInterpreter(final int api) {
+        super(api);
+    }
+
+    @Override
+    public SourceValue newValue(final Type type) {
+        if (type == Type.VOID_TYPE) {
+            return null;
+        }
+        return new SourceValue(type == null ? 1 : type.getSize());
+    }
+
+    @Override
+    public SourceValue newOperation(final AbstractInsnNode insn) {
+        int size;
+        switch (insn.getOpcode()) {
+        case LCONST_0:
+        case LCONST_1:
+        case DCONST_0:
+        case DCONST_1:
+            size = 2;
+            break;
+        case LDC:
+            Object cst = ((LdcInsnNode) insn).cst;
+            size = cst instanceof Long || cst instanceof Double ? 2 : 1;
+            break;
+        case GETSTATIC:
+            size = Type.getType(((FieldInsnNode) insn).desc).getSize();
+            break;
+        default:
+            size = 1;
+        }
+        return new SourceValue(size, insn);
+    }
+
+    @Override
+    public SourceValue copyOperation(final AbstractInsnNode insn,
+            final SourceValue value) {
+        return new SourceValue(value.getSize(), insn);
+    }
+
+    @Override
+    public SourceValue unaryOperation(final AbstractInsnNode insn,
+            final SourceValue value) {
+        int size;
+        switch (insn.getOpcode()) {
+        case LNEG:
+        case DNEG:
+        case I2L:
+        case I2D:
+        case L2D:
+        case F2L:
+        case F2D:
+        case D2L:
+            size = 2;
+            break;
+        case GETFIELD:
+            size = Type.getType(((FieldInsnNode) insn).desc).getSize();
+            break;
+        default:
+            size = 1;
+        }
+        return new SourceValue(size, insn);
+    }
+
+    @Override
+    public SourceValue binaryOperation(final AbstractInsnNode insn,
+            final SourceValue value1, final SourceValue value2) {
+        int size;
+        switch (insn.getOpcode()) {
+        case LALOAD:
+        case DALOAD:
+        case LADD:
+        case DADD:
+        case LSUB:
+        case DSUB:
+        case LMUL:
+        case DMUL:
+        case LDIV:
+        case DDIV:
+        case LREM:
+        case DREM:
+        case LSHL:
+        case LSHR:
+        case LUSHR:
+        case LAND:
+        case LOR:
+        case LXOR:
+            size = 2;
+            break;
+        default:
+            size = 1;
+        }
+        return new SourceValue(size, insn);
+    }
+
+    @Override
+    public SourceValue ternaryOperation(final AbstractInsnNode insn,
+            final SourceValue value1, final SourceValue value2,
+            final SourceValue value3) {
+        return new SourceValue(1, insn);
+    }
+
+    @Override
+    public SourceValue naryOperation(final AbstractInsnNode insn,
+            final List<? extends SourceValue> values) {
+        int size;
+        int opcode = insn.getOpcode();
+        if (opcode == MULTIANEWARRAY) {
+            size = 1;
+        } else {
+            String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc
+                    : ((MethodInsnNode) insn).desc;
+            size = Type.getReturnType(desc).getSize();
+        }
+        return new SourceValue(size, insn);
+    }
+
+    @Override
+    public void returnOperation(final AbstractInsnNode insn,
+            final SourceValue value, final SourceValue expected) {
+    }
+
+    @Override
+    public SourceValue merge(final SourceValue d, final SourceValue w) {
+        if (d.insns instanceof SmallSet && w.insns instanceof SmallSet) {
+            Set<AbstractInsnNode> s = ((SmallSet<AbstractInsnNode>) d.insns)
+                    .union((SmallSet<AbstractInsnNode>) w.insns);
+            if (s == d.insns && d.size == w.size) {
+                return d;
+            } else {
+                return new SourceValue(Math.min(d.size, w.size), s);
+            }
+        }
+        if (d.size != w.size || !d.insns.containsAll(w.insns)) {
+            HashSet<AbstractInsnNode> s = new HashSet<AbstractInsnNode>();
+            s.addAll(d.insns);
+            s.addAll(w.insns);
+            return new SourceValue(Math.min(d.size, w.size), s);
+        }
+        return d;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceValue.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceValue.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceValue.java
new file mode 100644
index 0000000..0cb2f50
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceValue.java
@@ -0,0 +1,97 @@
+/***
+ * 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.Set;
+
+import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
+
+/**
+ * A {@link Value} that is represented by its type in a two types type system.
+ * This type system distinguishes the ONEWORD and TWOWORDS types.
+ * 
+ * @author Eric Bruneton
+ */
+public class SourceValue implements Value {
+
+    /**
+     * The size of this value.
+     */
+    public final int size;
+
+    /**
+     * The instructions that can produce this value. For example, for the Java
+     * code below, the instructions that can produce the value of <tt>i</tt> at
+     * line 5 are the txo ISTORE instructions at line 1 and 3:
+     * 
+     * <pre>
+     * 1: i = 0;
+     * 2: if (...) {
+     * 3:   i = 1;
+     * 4: }
+     * 5: return i;
+     * </pre>
+     * 
+     * This field is a set of {@link AbstractInsnNode} objects.
+     */
+    public final Set<AbstractInsnNode> insns;
+
+    public SourceValue(final int size) {
+        this(size, SmallSet.<AbstractInsnNode> emptySet());
+    }
+
+    public SourceValue(final int size, final AbstractInsnNode insn) {
+        this.size = size;
+        this.insns = new SmallSet<AbstractInsnNode>(insn, null);
+    }
+
+    public SourceValue(final int size, final Set<AbstractInsnNode> insns) {
+        this.size = size;
+        this.insns = insns;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    @Override
+    public boolean equals(final Object value) {
+        if (!(value instanceof SourceValue)) {
+            return false;
+        }
+        SourceValue v = (SourceValue) value;
+        return size == v.size && insns.equals(v.insns);
+    }
+
+    @Override
+    public int hashCode() {
+        return insns.hashCode();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Subroutine.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Subroutine.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Subroutine.java
new file mode 100644
index 0000000..2032d59
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Subroutine.java
@@ -0,0 +1,90 @@
+/***
+ * 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.List;
+
+import org.apache.tapestry5.internal.plastic.asm.tree.JumpInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LabelNode;
+
+/**
+ * A method subroutine (corresponds to a JSR instruction).
+ * 
+ * @author Eric Bruneton
+ */
+class Subroutine {
+
+    LabelNode start;
+
+    boolean[] access;
+
+    List<JumpInsnNode> callers;
+
+    private Subroutine() {
+    }
+
+    Subroutine(final LabelNode start, final int maxLocals,
+            final JumpInsnNode caller) {
+        this.start = start;
+        this.access = new boolean[maxLocals];
+        this.callers = new ArrayList<JumpInsnNode>();
+        callers.add(caller);
+    }
+
+    public Subroutine copy() {
+        Subroutine result = new Subroutine();
+        result.start = start;
+        result.access = new boolean[access.length];
+        System.arraycopy(access, 0, result.access, 0, access.length);
+        result.callers = new ArrayList<JumpInsnNode>(callers);
+        return result;
+    }
+
+    public boolean merge(final Subroutine subroutine) throws AnalyzerException {
+        boolean changes = false;
+        for (int i = 0; i < access.length; ++i) {
+            if (subroutine.access[i] && !access[i]) {
+                access[i] = true;
+                changes = true;
+            }
+        }
+        if (subroutine.start == start) {
+            for (int i = 0; i < subroutine.callers.size(); ++i) {
+                JumpInsnNode caller = subroutine.callers.get(i);
+                if (!callers.contains(caller)) {
+                    callers.add(caller);
+                    changes = true;
+                }
+            }
+        }
+        return changes;
+    }
+}
\ 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/Value.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Value.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Value.java
new file mode 100644
index 0000000..b0d657c
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Value.java
@@ -0,0 +1,45 @@
+/***
+ * 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;
+
+/**
+ * An immutable symbolic value for semantic interpretation of bytecode.
+ * 
+ * @author Eric Bruneton
+ */
+public interface Value {
+
+    /**
+     * Returns the size of this value in words.
+     * 
+     * @return either 1 or 2.
+     */
+    int getSize();
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/package.html
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/package.html b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/package.html
new file mode 100644
index 0000000..228da02
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/package.html
@@ -0,0 +1,67 @@
+<html>
+<!--
+ * 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.
+-->
+<body>
+
+<p>
+Provides a framework for static code analysis based on the asm.tree package.
+</p>
+
+<p>
+Basic usage:
+</p>
+
+<pre>
+ClassReader cr = new ClassReader(bytecode);
+ClassNode cn = new ClassNode();
+cr.accept(cn, ClassReader.SKIP_DEBUG);
+
+List methods = cn.methods;
+for (int i = 0; i < methods.size(); ++i) {
+    MethodNode method = (MethodNode) methods.get(i);
+    if (method.instructions.size() > 0) {
+        Analyzer a = new Analyzer(new BasicInterpreter());
+        a.analyze(cn.name, method);
+        Frame[] frames = a.getFrames();
+        // Elements of the frames arrray now contains info for each instruction
+        // from the analyzed method. BasicInterpreter creates BasicValue, that
+        // is using simplified type system that distinguishes the UNINITIALZED,
+        // INT, FLOAT, LONG, DOUBLE, REFERENCE and RETURNADDRESS types.
+        ...
+    }
+}
+</pre>
+
+<p>
+@since ASM 1.4.3
+</p>
+
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java
index e1fec58..f8b0b0d 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java
@@ -29,25 +29,28 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.util;
 
-import org.apache.tapestry5.internal.plastic.asm.Label;
-
 import java.util.Map;
 
+import org.apache.tapestry5.internal.plastic.asm.Label;
+
 /**
  * An {@link org.apache.tapestry5.internal.plastic.asm.Attribute Attribute} that can print the ASM code
  * to create an equivalent attribute.
- *
+ * 
  * @author Eugene Kuleshov
  */
 public interface ASMifiable {
 
     /**
      * Prints the ASM code to create an attribute equal to this attribute.
-     *
-     * @param buf a buffer used for printing Java code.
-     * @param varName name of the variable in a printed code used to store
-     *        attribute instance.
-     * @param labelNames map of label instances to their names.
+     * 
+     * @param buf
+     *            a buffer used for printing Java code.
+     * @param varName
+     *            name of the variable in a printed code used to store attribute
+     *            instance.
+     * @param labelNames
+     *            map of label instances to their names.
      */
     void asmify(StringBuffer buf, String varName, Map<Label, String> labelNames);
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java
new file mode 100644
index 0000000..34829b0
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java
@@ -0,0 +1,1285 @@
+/***
+ * 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.util;
+
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+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 {@link Printer} that prints the ASM code to generate the classes if visits.
+ * 
+ * @author Eric Bruneton
+ */
+public class ASMifier extends Printer {
+
+    /**
+     * The name of the visitor variable in the produced code.
+     */
+    protected final String name;
+
+    /**
+     * Identifier of the annotation visitor variable in the produced code.
+     */
+    protected final int id;
+
+    /**
+     * The label names. This map associates String values to Label keys. It is
+     * used only in ASMifierMethodVisitor.
+     */
+    protected Map<Label, String> labelNames;
+
+    /**
+     * Pseudo access flag used to distinguish class access flags.
+     */
+    private static final int ACCESS_CLASS = 262144;
+
+    /**
+     * Pseudo access flag used to distinguish field access flags.
+     */
+    private static final int ACCESS_FIELD = 524288;
+
+    /**
+     * Pseudo access flag used to distinguish inner class flags.
+     */
+    private static final int ACCESS_INNER = 1048576;
+
+    /**
+     * Constructs a new {@link ASMifier}. <i>Subclasses must not use this
+     * constructor</i>. Instead, they must use the
+     * {@link #ASMifier(int, String, int)} version.
+     * 
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public ASMifier() {
+        this(Opcodes.ASM5, "cw", 0);
+        if (getClass() != ASMifier.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Constructs a new {@link ASMifier}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this class. Must be one of
+     *            {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param name
+     *            the name of the visitor variable in the produced code.
+     * @param id
+     *            identifier of the annotation visitor variable in the produced
+     *            code.
+     */
+    protected ASMifier(final int api, final String name, final int id) {
+        super(api);
+        this.name = name;
+        this.id = id;
+    }
+
+    /**
+     * Prints the ASM source code to generate the given class to the standard
+     * output.
+     * <p>
+     * Usage: ASMifier [-debug] &lt;binary class name or class file name&gt;
+     * 
+     * @param args
+     *            the command line arguments.
+     * 
+     * @throws Exception
+     *             if the class cannot be found, or if an IO exception occurs.
+     */
+    public static void main(final String[] args) throws Exception {
+        int i = 0;
+        int flags = ClassReader.SKIP_DEBUG;
+
+        boolean ok = true;
+        if (args.length < 1 || args.length > 2) {
+            ok = false;
+        }
+        if (ok && "-debug".equals(args[0])) {
+            i = 1;
+            flags = 0;
+            if (args.length != 2) {
+                ok = false;
+            }
+        }
+        if (!ok) {
+            System.err
+                    .println("Prints the ASM code to generate the given class.");
+            System.err.println("Usage: ASMifier [-debug] "
+                    + "<fully qualified class name or class file name>");
+            return;
+        }
+        ClassReader cr;
+        if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1
+                || args[i].indexOf('/') > -1) {
+            cr = new ClassReader(new FileInputStream(args[i]));
+        } else {
+            cr = new ClassReader(args[i]);
+        }
+        cr.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(
+                System.out)), flags);
+    }
+
+    // ------------------------------------------------------------------------
+    // Classes
+    // ------------------------------------------------------------------------
+
+    @Override
+    public void visit(final int version, final int access, final String name,
+            final String signature, final String superName,
+            final String[] interfaces) {
+        String simpleName;
+        int n = name.lastIndexOf('/');
+        if (n == -1) {
+            simpleName = name;
+        } else {
+            text.add("package asm." + name.substring(0, n).replace('/', '.')
+                    + ";\n");
+            simpleName = name.substring(n + 1);
+        }
+        text.add("import java.util.*;\n");
+        text.add("import org.objectweb.asm.*;\n");
+        text.add("import org.objectweb.asm.attrs.*;\n");
+        text.add("public class " + simpleName + "Dump implements Opcodes {\n\n");
+        text.add("public static byte[] dump () throws Exception {\n\n");
+        text.add("ClassWriter cw = new ClassWriter(0);\n");
+        text.add("FieldVisitor fv;\n");
+        text.add("MethodVisitor mv;\n");
+        text.add("AnnotationVisitor av0;\n\n");
+
+        buf.setLength(0);
+        buf.append("cw.visit(");
+        switch (version) {
+        case Opcodes.V1_1:
+            buf.append("V1_1");
+            break;
+        case Opcodes.V1_2:
+            buf.append("V1_2");
+            break;
+        case Opcodes.V1_3:
+            buf.append("V1_3");
+            break;
+        case Opcodes.V1_4:
+            buf.append("V1_4");
+            break;
+        case Opcodes.V1_5:
+            buf.append("V1_5");
+            break;
+        case Opcodes.V1_6:
+            buf.append("V1_6");
+            break;
+        case Opcodes.V1_7:
+            buf.append("V1_7");
+            break;
+        default:
+            buf.append(version);
+            break;
+        }
+        buf.append(", ");
+        appendAccess(access | ACCESS_CLASS);
+        buf.append(", ");
+        appendConstant(name);
+        buf.append(", ");
+        appendConstant(signature);
+        buf.append(", ");
+        appendConstant(superName);
+        buf.append(", ");
+        if (interfaces != null && interfaces.length > 0) {
+            buf.append("new String[] {");
+            for (int i = 0; i < interfaces.length; ++i) {
+                buf.append(i == 0 ? " " : ", ");
+                appendConstant(interfaces[i]);
+            }
+            buf.append(" }");
+        } else {
+            buf.append("null");
+        }
+        buf.append(");\n\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitSource(final String file, final String debug) {
+        buf.setLength(0);
+        buf.append("cw.visitSource(");
+        appendConstant(file);
+        buf.append(", ");
+        appendConstant(debug);
+        buf.append(");\n\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitOuterClass(final String owner, final String name,
+            final String desc) {
+        buf.setLength(0);
+        buf.append("cw.visitOuterClass(");
+        appendConstant(owner);
+        buf.append(", ");
+        appendConstant(name);
+        buf.append(", ");
+        appendConstant(desc);
+        buf.append(");\n\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public ASMifier visitClassAnnotation(final String desc,
+            final boolean visible) {
+        return visitAnnotation(desc, visible);
+    }
+
+    @Override
+    public ASMifier visitClassTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        return visitTypeAnnotation(typeRef, typePath, desc, visible);
+    }
+
+    @Override
+    public void visitClassAttribute(final Attribute attr) {
+        visitAttribute(attr);
+    }
+
+    @Override
+    public void visitInnerClass(final String name, final String outerName,
+            final String innerName, final int access) {
+        buf.setLength(0);
+        buf.append("cw.visitInnerClass(");
+        appendConstant(name);
+        buf.append(", ");
+        appendConstant(outerName);
+        buf.append(", ");
+        appendConstant(innerName);
+        buf.append(", ");
+        appendAccess(access | ACCESS_INNER);
+        buf.append(");\n\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public ASMifier visitField(final int access, final String name,
+            final String desc, final String signature, final Object value) {
+        buf.setLength(0);
+        buf.append("{\n");
+        buf.append("fv = cw.visitField(");
+        appendAccess(access | ACCESS_FIELD);
+        buf.append(", ");
+        appendConstant(name);
+        buf.append(", ");
+        appendConstant(desc);
+        buf.append(", ");
+        appendConstant(signature);
+        buf.append(", ");
+        appendConstant(value);
+        buf.append(");\n");
+        text.add(buf.toString());
+        ASMifier a = createASMifier("fv", 0);
+        text.add(a.getText());
+        text.add("}\n");
+        return a;
+    }
+
+    @Override
+    public ASMifier visitMethod(final int access, final String name,
+            final String desc, final String signature, final String[] exceptions) {
+        buf.setLength(0);
+        buf.append("{\n");
+        buf.append("mv = cw.visitMethod(");
+        appendAccess(access);
+        buf.append(", ");
+        appendConstant(name);
+        buf.append(", ");
+        appendConstant(desc);
+        buf.append(", ");
+        appendConstant(signature);
+        buf.append(", ");
+        if (exceptions != null && exceptions.length > 0) {
+            buf.append("new String[] {");
+            for (int i = 0; i < exceptions.length; ++i) {
+                buf.append(i == 0 ? " " : ", ");
+                appendConstant(exceptions[i]);
+            }
+            buf.append(" }");
+        } else {
+            buf.append("null");
+        }
+        buf.append(");\n");
+        text.add(buf.toString());
+        ASMifier a = createASMifier("mv", 0);
+        text.add(a.getText());
+        text.add("}\n");
+        return a;
+    }
+
+    @Override
+    public void visitClassEnd() {
+        text.add("cw.visitEnd();\n\n");
+        text.add("return cw.toByteArray();\n");
+        text.add("}\n");
+        text.add("}\n");
+    }
+
+    // ------------------------------------------------------------------------
+    // Annotations
+    // ------------------------------------------------------------------------
+
+    @Override
+    public void visit(final String name, final Object value) {
+        buf.setLength(0);
+        buf.append("av").append(id).append(".visit(");
+        appendConstant(buf, name);
+        buf.append(", ");
+        appendConstant(buf, value);
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitEnum(final String name, final String desc,
+            final String value) {
+        buf.setLength(0);
+        buf.append("av").append(id).append(".visitEnum(");
+        appendConstant(buf, name);
+        buf.append(", ");
+        appendConstant(buf, desc);
+        buf.append(", ");
+        appendConstant(buf, value);
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public ASMifier visitAnnotation(final String name, final String desc) {
+        buf.setLength(0);
+        buf.append("{\n");
+        buf.append("AnnotationVisitor av").append(id + 1).append(" = av");
+        buf.append(id).append(".visitAnnotation(");
+        appendConstant(buf, name);
+        buf.append(", ");
+        appendConstant(buf, desc);
+        buf.append(");\n");
+        text.add(buf.toString());
+        ASMifier a = createASMifier("av", id + 1);
+        text.add(a.getText());
+        text.add("}\n");
+        return a;
+    }
+
+    @Override
+    public ASMifier visitArray(final String name) {
+        buf.setLength(0);
+        buf.append("{\n");
+        buf.append("AnnotationVisitor av").append(id + 1).append(" = av");
+        buf.append(id).append(".visitArray(");
+        appendConstant(buf, name);
+        buf.append(");\n");
+        text.add(buf.toString());
+        ASMifier a = createASMifier("av", id + 1);
+        text.add(a.getText());
+        text.add("}\n");
+        return a;
+    }
+
+    @Override
+    public void visitAnnotationEnd() {
+        buf.setLength(0);
+        buf.append("av").append(id).append(".visitEnd();\n");
+        text.add(buf.toString());
+    }
+
+    // ------------------------------------------------------------------------
+    // Fields
+    // ------------------------------------------------------------------------
+
+    @Override
+    public ASMifier visitFieldAnnotation(final String desc,
+            final boolean visible) {
+        return visitAnnotation(desc, visible);
+    }
+
+    @Override
+    public ASMifier visitFieldTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        return visitTypeAnnotation(typeRef, typePath, desc, visible);
+    }
+
+    @Override
+    public void visitFieldAttribute(final Attribute attr) {
+        visitAttribute(attr);
+    }
+
+    @Override
+    public void visitFieldEnd() {
+        buf.setLength(0);
+        buf.append(name).append(".visitEnd();\n");
+        text.add(buf.toString());
+    }
+
+    // ------------------------------------------------------------------------
+    // Methods
+    // ------------------------------------------------------------------------
+
+    @Override
+    public void visitParameter(String parameterName, int access) {
+        buf.setLength(0);
+        buf.append(name).append(".visitParameter(");
+        appendString(buf, parameterName);
+        buf.append(", ");
+        appendAccess(access);
+        text.add(buf.append(");\n").toString());
+    }
+
+    @Override
+    public ASMifier visitAnnotationDefault() {
+        buf.setLength(0);
+        buf.append("{\n").append("av0 = ").append(name)
+                .append(".visitAnnotationDefault();\n");
+        text.add(buf.toString());
+        ASMifier a = createASMifier("av", 0);
+        text.add(a.getText());
+        text.add("}\n");
+        return a;
+    }
+
+    @Override
+    public ASMifier visitMethodAnnotation(final String desc,
+            final boolean visible) {
+        return visitAnnotation(desc, visible);
+    }
+
+    @Override
+    public ASMifier visitMethodTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        return visitTypeAnnotation(typeRef, typePath, desc, visible);
+    }
+
+    @Override
+    public ASMifier visitParameterAnnotation(final int parameter,
+            final String desc, final boolean visible) {
+        buf.setLength(0);
+        buf.append("{\n").append("av0 = ").append(name)
+                .append(".visitParameterAnnotation(").append(parameter)
+                .append(", ");
+        appendConstant(desc);
+        buf.append(", ").append(visible).append(");\n");
+        text.add(buf.toString());
+        ASMifier a = createASMifier("av", 0);
+        text.add(a.getText());
+        text.add("}\n");
+        return a;
+    }
+
+    @Override
+    public void visitMethodAttribute(final Attribute attr) {
+        visitAttribute(attr);
+    }
+
+    @Override
+    public void visitCode() {
+        text.add(name + ".visitCode();\n");
+    }
+
+    @Override
+    public void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack) {
+        buf.setLength(0);
+        switch (type) {
+        case Opcodes.F_NEW:
+        case Opcodes.F_FULL:
+            declareFrameTypes(nLocal, local);
+            declareFrameTypes(nStack, stack);
+            if (type == Opcodes.F_NEW) {
+                buf.append(name).append(".visitFrame(Opcodes.F_NEW, ");
+            } else {
+                buf.append(name).append(".visitFrame(Opcodes.F_FULL, ");
+            }
+            buf.append(nLocal).append(", new Object[] {");
+            appendFrameTypes(nLocal, local);
+            buf.append("}, ").append(nStack).append(", new Object[] {");
+            appendFrameTypes(nStack, stack);
+            buf.append('}');
+            break;
+        case Opcodes.F_APPEND:
+            declareFrameTypes(nLocal, local);
+            buf.append(name).append(".visitFrame(Opcodes.F_APPEND,")
+                    .append(nLocal).append(", new Object[] {");
+            appendFrameTypes(nLocal, local);
+            buf.append("}, 0, null");
+            break;
+        case Opcodes.F_CHOP:
+            buf.append(name).append(".visitFrame(Opcodes.F_CHOP,")
+                    .append(nLocal).append(", null, 0, null");
+            break;
+        case Opcodes.F_SAME:
+            buf.append(name).append(
+                    ".visitFrame(Opcodes.F_SAME, 0, null, 0, null");
+            break;
+        case Opcodes.F_SAME1:
+            declareFrameTypes(1, stack);
+            buf.append(name).append(
+                    ".visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {");
+            appendFrameTypes(1, stack);
+            buf.append('}');
+            break;
+        }
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitInsn(final int opcode) {
+        buf.setLength(0);
+        buf.append(name).append(".visitInsn(").append(OPCODES[opcode])
+                .append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitIntInsn(final int opcode, final int operand) {
+        buf.setLength(0);
+        buf.append(name)
+                .append(".visitIntInsn(")
+                .append(OPCODES[opcode])
+                .append(", ")
+                .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer
+                        .toString(operand)).append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitVarInsn(final int opcode, final int var) {
+        buf.setLength(0);
+        buf.append(name).append(".visitVarInsn(").append(OPCODES[opcode])
+                .append(", ").append(var).append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitTypeInsn(final int opcode, final String type) {
+        buf.setLength(0);
+        buf.append(name).append(".visitTypeInsn(").append(OPCODES[opcode])
+                .append(", ");
+        appendConstant(type);
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitFieldInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        buf.setLength(0);
+        buf.append(this.name).append(".visitFieldInsn(")
+                .append(OPCODES[opcode]).append(", ");
+        appendConstant(owner);
+        buf.append(", ");
+        appendConstant(name);
+        buf.append(", ");
+        appendConstant(desc);
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Deprecated
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (api >= Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc,
+                opcode == Opcodes.INVOKEINTERFACE);
+    }
+
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    private void doVisitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        buf.setLength(0);
+        buf.append(this.name).append(".visitMethodInsn(")
+                .append(OPCODES[opcode]).append(", ");
+        appendConstant(owner);
+        buf.append(", ");
+        appendConstant(name);
+        buf.append(", ");
+        appendConstant(desc);
+        buf.append(", ");
+        buf.append(itf ? "true" : "false");
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        buf.setLength(0);
+        buf.append(this.name).append(".visitInvokeDynamicInsn(");
+        appendConstant(name);
+        buf.append(", ");
+        appendConstant(desc);
+        buf.append(", ");
+        appendConstant(bsm);
+        buf.append(", new Object[]{");
+        for (int i = 0; i < bsmArgs.length; ++i) {
+            appendConstant(bsmArgs[i]);
+            if (i != bsmArgs.length - 1) {
+                buf.append(", ");
+            }
+        }
+        buf.append("});\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitJumpInsn(final int opcode, final Label label) {
+        buf.setLength(0);
+        declareLabel(label);
+        buf.append(name).append(".visitJumpInsn(").append(OPCODES[opcode])
+                .append(", ");
+        appendLabel(label);
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitLabel(final Label label) {
+        buf.setLength(0);
+        declareLabel(label);
+        buf.append(name).append(".visitLabel(");
+        appendLabel(label);
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitLdcInsn(final Object cst) {
+        buf.setLength(0);
+        buf.append(name).append(".visitLdcInsn(");
+        appendConstant(cst);
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitIincInsn(final int var, final int increment) {
+        buf.setLength(0);
+        buf.append(name).append(".visitIincInsn(").append(var).append(", ")
+                .append(increment).append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels) {
+        buf.setLength(0);
+        for (int i = 0; i < labels.length; ++i) {
+            declareLabel(labels[i]);
+        }
+        declareLabel(dflt);
+
+        buf.append(name).append(".visitTableSwitchInsn(").append(min)
+                .append(", ").append(max).append(", ");
+        appendLabel(dflt);
+        buf.append(", new Label[] {");
+        for (int i = 0; i < labels.length; ++i) {
+            buf.append(i == 0 ? " " : ", ");
+            appendLabel(labels[i]);
+        }
+        buf.append(" });\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
+        buf.setLength(0);
+        for (int i = 0; i < labels.length; ++i) {
+            declareLabel(labels[i]);
+        }
+        declareLabel(dflt);
+
+        buf.append(name).append(".visitLookupSwitchInsn(");
+        appendLabel(dflt);
+        buf.append(", new int[] {");
+        for (int i = 0; i < keys.length; ++i) {
+            buf.append(i == 0 ? " " : ", ").append(keys[i]);
+        }
+        buf.append(" }, new Label[] {");
+        for (int i = 0; i < labels.length; ++i) {
+            buf.append(i == 0 ? " " : ", ");
+            appendLabel(labels[i]);
+        }
+        buf.append(" });\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitMultiANewArrayInsn(final String desc, final int dims) {
+        buf.setLength(0);
+        buf.append(name).append(".visitMultiANewArrayInsn(");
+        appendConstant(desc);
+        buf.append(", ").append(dims).append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public ASMifier visitInsnAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        return visitTypeAnnotation("visitInsnAnnotation", typeRef, typePath,
+                desc, visible);
+    }
+
+    @Override
+    public void visitTryCatchBlock(final Label start, final Label end,
+            final Label handler, final String type) {
+        buf.setLength(0);
+        declareLabel(start);
+        declareLabel(end);
+        declareLabel(handler);
+        buf.append(name).append(".visitTryCatchBlock(");
+        appendLabel(start);
+        buf.append(", ");
+        appendLabel(end);
+        buf.append(", ");
+        appendLabel(handler);
+        buf.append(", ");
+        appendConstant(type);
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public ASMifier visitTryCatchAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        return visitTypeAnnotation("visitTryCatchAnnotation", typeRef,
+                typePath, desc, visible);
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
+        buf.setLength(0);
+        buf.append(this.name).append(".visitLocalVariable(");
+        appendConstant(name);
+        buf.append(", ");
+        appendConstant(desc);
+        buf.append(", ");
+        appendConstant(signature);
+        buf.append(", ");
+        appendLabel(start);
+        buf.append(", ");
+        appendLabel(end);
+        buf.append(", ").append(index).append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public Printer visitLocalVariableAnnotation(int typeRef, TypePath typePath,
+            Label[] start, Label[] end, int[] index, String desc,
+            boolean visible) {
+        buf.setLength(0);
+        buf.append("{\n").append("av0 = ").append(name)
+                .append(".visitLocalVariableAnnotation(");
+        buf.append(typeRef);
+        buf.append(", TypePath.fromString(\"").append(typePath).append("\"), ");
+        buf.append("new Label[] {");
+        for (int i = 0; i < start.length; ++i) {
+            buf.append(i == 0 ? " " : ", ");
+            appendLabel(start[i]);
+        }
+        buf.append(" }, new Label[] {");
+        for (int i = 0; i < end.length; ++i) {
+            buf.append(i == 0 ? " " : ", ");
+            appendLabel(end[i]);
+        }
+        buf.append(" }, new int[] {");
+        for (int i = 0; i < index.length; ++i) {
+            buf.append(i == 0 ? " " : ", ").append(index[i]);
+        }
+        buf.append(" }, ");
+        appendConstant(desc);
+        buf.append(", ").append(visible).append(");\n");
+        text.add(buf.toString());
+        ASMifier a = createASMifier("av", 0);
+        text.add(a.getText());
+        text.add("}\n");
+        return a;
+    }
+
+    @Override
+    public void visitLineNumber(final int line, final Label start) {
+        buf.setLength(0);
+        buf.append(name).append(".visitLineNumber(").append(line).append(", ");
+        appendLabel(start);
+        buf.append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitMaxs(final int maxStack, final int maxLocals) {
+        buf.setLength(0);
+        buf.append(name).append(".visitMaxs(").append(maxStack).append(", ")
+                .append(maxLocals).append(");\n");
+        text.add(buf.toString());
+    }
+
+    @Override
+    public void visitMethodEnd() {
+        buf.setLength(0);
+        buf.append(name).append(".visitEnd();\n");
+        text.add(buf.toString());
+    }
+
+    // ------------------------------------------------------------------------
+    // Common methods
+    // ------------------------------------------------------------------------
+
+    public ASMifier visitAnnotation(final String desc, final boolean visible) {
+        buf.setLength(0);
+        buf.append("{\n").append("av0 = ").append(name)
+                .append(".visitAnnotation(");
+        appendConstant(desc);
+        buf.append(", ").append(visible).append(");\n");
+        text.add(buf.toString());
+        ASMifier a = createASMifier("av", 0);
+        text.add(a.getText());
+        text.add("}\n");
+        return a;
+    }
+
+    public ASMifier visitTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        return visitTypeAnnotation("visitTypeAnnotation", typeRef, typePath,
+                desc, visible);
+    }
+
+    public ASMifier visitTypeAnnotation(final String method, final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        buf.setLength(0);
+        buf.append("{\n").append("av0 = ").append(name).append(".")
+                .append(method).append("(");
+        buf.append(typeRef);
+        buf.append(", TypePath.fromString(\"").append(typePath).append("\"), ");
+        appendConstant(desc);
+        buf.append(", ").append(visible).append(");\n");
+        text.add(buf.toString());
+        ASMifier a = createASMifier("av", 0);
+        text.add(a.getText());
+        text.add("}\n");
+        return a;
+    }
+
+    public void visitAttribute(final Attribute attr) {
+        buf.setLength(0);
+        buf.append("// ATTRIBUTE ").append(attr.type).append('\n');
+        if (attr instanceof ASMifiable) {
+            if (labelNames == null) {
+                labelNames = new HashMap<Label, String>();
+            }
+            buf.append("{\n");
+            ((ASMifiable) attr).asmify(buf, "attr", labelNames);
+            buf.append(name).append(".visitAttribute(attr);\n");
+            buf.append("}\n");
+        }
+        text.add(buf.toString());
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods
+    // ------------------------------------------------------------------------
+
+    protected ASMifier createASMifier(final String name, final int id) {
+        return new ASMifier(Opcodes.ASM5, name, id);
+    }
+
+    /**
+     * Appends a string representation of the given access modifiers to
+     * {@link #buf buf}.
+     * 
+     * @param access
+     *            some access modifiers.
+     */
+    void appendAccess(final int access) {
+        boolean first = true;
+        if ((access & Opcodes.ACC_PUBLIC) != 0) {
+            buf.append("ACC_PUBLIC");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_PRIVATE) != 0) {
+            buf.append("ACC_PRIVATE");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_PROTECTED) != 0) {
+            buf.append("ACC_PROTECTED");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_FINAL) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_FINAL");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_STATIC) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_STATIC");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            if ((access & ACCESS_CLASS) == 0) {
+                buf.append("ACC_SYNCHRONIZED");
+            } else {
+                buf.append("ACC_SUPER");
+            }
+            first = false;
+        }
+        if ((access & Opcodes.ACC_VOLATILE) != 0
+                && (access & ACCESS_FIELD) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_VOLATILE");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_BRIDGE) != 0 && (access & ACCESS_CLASS) == 0
+                && (access & ACCESS_FIELD) == 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_BRIDGE");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_VARARGS) != 0 && (access & ACCESS_CLASS) == 0
+                && (access & ACCESS_FIELD) == 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_VARARGS");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_TRANSIENT) != 0
+                && (access & ACCESS_FIELD) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_TRANSIENT");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_NATIVE) != 0 && (access & ACCESS_CLASS) == 0
+                && (access & ACCESS_FIELD) == 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_NATIVE");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_ENUM) != 0
+                && ((access & ACCESS_CLASS) != 0
+                        || (access & ACCESS_FIELD) != 0 || (access & ACCESS_INNER) != 0)) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_ENUM");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_ANNOTATION) != 0
+                && ((access & ACCESS_CLASS) != 0 || (access & ACCESS_INNER) != 0)) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_ANNOTATION");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_ABSTRACT");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_INTERFACE) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_INTERFACE");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_STRICT) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_STRICT");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_SYNTHETIC");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_DEPRECATED");
+            first = false;
+        }
+        if ((access & Opcodes.ACC_MANDATED) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_MANDATED");
+            first = false;
+        }
+        if (first) {
+            buf.append('0');
+        }
+    }
+
+    /**
+     * Appends a string representation of the given constant to the given
+     * buffer.
+     * 
+     * @param cst
+     *            an {@link Integer}, {@link Float}, {@link Long},
+     *            {@link Double} or {@link String} object. May be <tt>null</tt>.
+     */
+    protected void appendConstant(final Object cst) {
+        appendConstant(buf, cst);
+    }
+
+    /**
+     * Appends a string representation of the given constant to the given
+     * buffer.
+     * 
+     * @param buf
+     *            a string buffer.
+     * @param cst
+     *            an {@link Integer}, {@link Float}, {@link Long},
+     *            {@link Double} or {@link String} object. May be <tt>null</tt>.
+     */
+    static void appendConstant(final StringBuffer buf, final Object cst) {
+        if (cst == null) {
+            buf.append("null");
+        } else if (cst instanceof String) {
+            appendString(buf, (String) cst);
+        } else if (cst instanceof Type) {
+            buf.append("Type.getType(\"");
+            buf.append(((Type) cst).getDescriptor());
+            buf.append("\")");
+        } else if (cst instanceof Handle) {
+            buf.append("new Handle(");
+            Handle h = (Handle) cst;
+            buf.append("Opcodes.").append(HANDLE_TAG[h.getTag()])
+                    .append(", \"");
+            buf.append(h.getOwner()).append("\", \"");
+            buf.append(h.getName()).append("\", \"");
+            buf.append(h.getDesc()).append("\")");
+        } else if (cst instanceof Byte) {
+            buf.append("new Byte((byte)").append(cst).append(')');
+        } else if (cst instanceof Boolean) {
+            buf.append(((Boolean) cst).booleanValue() ? "Boolean.TRUE"
+                    : "Boolean.FALSE");
+        } else if (cst instanceof Short) {
+            buf.append("new Short((short)").append(cst).append(')');
+        } else if (cst instanceof Character) {
+            int c = ((Character) cst).charValue();
+            buf.append("new Character((char)").append(c).append(')');
+        } else if (cst instanceof Integer) {
+            buf.append("new Integer(").append(cst).append(')');
+        } else if (cst instanceof Float) {
+            buf.append("new Float(\"").append(cst).append("\")");
+        } else if (cst instanceof Long) {
+            buf.append("new Long(").append(cst).append("L)");
+        } else if (cst instanceof Double) {
+            buf.append("new Double(\"").append(cst).append("\")");
+        } else if (cst instanceof byte[]) {
+            byte[] v = (byte[]) cst;
+            buf.append("new byte[] {");
+            for (int i = 0; i < v.length; i++) {
+                buf.append(i == 0 ? "" : ",").append(v[i]);
+            }
+            buf.append('}');
+        } else if (cst instanceof boolean[]) {
+            boolean[] v = (boolean[]) cst;
+            buf.append("new boolean[] {");
+            for (int i = 0; i < v.length; i++) {
+                buf.append(i == 0 ? "" : ",").append(v[i]);
+            }
+            buf.append('}');
+        } else if (cst instanceof short[]) {
+            short[] v = (short[]) cst;
+            buf.append("new short[] {");
+            for (int i = 0; i < v.length; i++) {
+                buf.append(i == 0 ? "" : ",").append("(short)").append(v[i]);
+            }
+            buf.append('}');
+        } else if (cst instanceof char[]) {
+            char[] v = (char[]) cst;
+            buf.append("new char[] {");
+            for (int i = 0; i < v.length; i++) {
+                buf.append(i == 0 ? "" : ",").append("(char)")
+                        .append((int) v[i]);
+            }
+            buf.append('}');
+        } else if (cst instanceof int[]) {
+            int[] v = (int[]) cst;
+            buf.append("new int[] {");
+            for (int i = 0; i < v.length; i++) {
+                buf.append(i == 0 ? "" : ",").append(v[i]);
+            }
+            buf.append('}');
+        } else if (cst instanceof long[]) {
+            long[] v = (long[]) cst;
+            buf.append("new long[] {");
+            for (int i = 0; i < v.length; i++) {
+                buf.append(i == 0 ? "" : ",").append(v[i]).append('L');
+            }
+            buf.append('}');
+        } else if (cst instanceof float[]) {
+            float[] v = (float[]) cst;
+            buf.append("new float[] {");
+            for (int i = 0; i < v.length; i++) {
+                buf.append(i == 0 ? "" : ",").append(v[i]).append('f');
+            }
+            buf.append('}');
+        } else if (cst instanceof double[]) {
+            double[] v = (double[]) cst;
+            buf.append("new double[] {");
+            for (int i = 0; i < v.length; i++) {
+                buf.append(i == 0 ? "" : ",").append(v[i]).append('d');
+            }
+            buf.append('}');
+        }
+    }
+
+    private void declareFrameTypes(final int n, final Object[] o) {
+        for (int i = 0; i < n; ++i) {
+            if (o[i] instanceof Label) {
+                declareLabel((Label) o[i]);
+            }
+        }
+    }
+
+    private void appendFrameTypes(final int n, final Object[] o) {
+        for (int i = 0; i < n; ++i) {
+            if (i > 0) {
+                buf.append(", ");
+            }
+            if (o[i] instanceof String) {
+                appendConstant(o[i]);
+            } else if (o[i] instanceof Integer) {
+                switch (((Integer) o[i]).intValue()) {
+                case 0:
+                    buf.append("Opcodes.TOP");
+                    break;
+                case 1:
+                    buf.append("Opcodes.INTEGER");
+                    break;
+                case 2:
+                    buf.append("Opcodes.FLOAT");
+                    break;
+                case 3:
+                    buf.append("Opcodes.DOUBLE");
+                    break;
+                case 4:
+                    buf.append("Opcodes.LONG");
+                    break;
+                case 5:
+                    buf.append("Opcodes.NULL");
+                    break;
+                case 6:
+                    buf.append("Opcodes.UNINITIALIZED_THIS");
+                    break;
+                }
+            } else {
+                appendLabel((Label) o[i]);
+            }
+        }
+    }
+
+    /**
+     * Appends a declaration of the given label to {@link #buf buf}. This
+     * declaration is of the form "Label lXXX = new Label();". Does nothing if
+     * the given label has already been declared.
+     * 
+     * @param l
+     *            a label.
+     */
+    protected void declareLabel(final Label l) {
+        if (labelNames == null) {
+            labelNames = new HashMap<Label, String>();
+        }
+        String name = labelNames.get(l);
+        if (name == null) {
+            name = "l" + labelNames.size();
+            labelNames.put(l, name);
+            buf.append("Label ").append(name).append(" = new Label();\n");
+        }
+    }
+
+    /**
+     * Appends the name of the given label to {@link #buf buf}. The given label
+     * <i>must</i> already have a name. One way to ensure this is to always call
+     * {@link #declareLabel declared} before calling this method.
+     * 
+     * @param l
+     *            a label.
+     */
+    protected void appendLabel(final Label l) {
+        buf.append(labelNames.get(l));
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckAnnotationAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckAnnotationAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckAnnotationAdapter.java
new file mode 100644
index 0000000..56580d1
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckAnnotationAdapter.java
@@ -0,0 +1,136 @@
+/***
+ * 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.util;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * An {@link AnnotationVisitor} that checks that its methods are properly used.
+ * 
+ * @author Eric Bruneton
+ */
+public class CheckAnnotationAdapter extends AnnotationVisitor {
+
+    private final boolean named;
+
+    private boolean end;
+
+    public CheckAnnotationAdapter(final AnnotationVisitor av) {
+        this(av, true);
+    }
+
+    CheckAnnotationAdapter(final AnnotationVisitor av, final boolean named) {
+        super(Opcodes.ASM5, av);
+        this.named = named;
+    }
+
+    @Override
+    public void visit(final String name, final Object value) {
+        checkEnd();
+        checkName(name);
+        if (!(value instanceof Byte || value instanceof Boolean
+                || value instanceof Character || value instanceof Short
+                || value instanceof Integer || value instanceof Long
+                || value instanceof Float || value instanceof Double
+                || value instanceof String || value instanceof Type
+                || value instanceof byte[] || value instanceof boolean[]
+                || value instanceof char[] || value instanceof short[]
+                || value instanceof int[] || value instanceof long[]
+                || value instanceof float[] || value instanceof double[])) {
+            throw new IllegalArgumentException("Invalid annotation value");
+        }
+        if (value instanceof Type) {
+            int sort = ((Type) value).getSort();
+            if (sort == Type.METHOD) {
+                throw new IllegalArgumentException("Invalid annotation value");
+            }
+        }
+        if (av != null) {
+            av.visit(name, value);
+        }
+    }
+
+    @Override
+    public void visitEnum(final String name, final String desc,
+            final String value) {
+        checkEnd();
+        checkName(name);
+        CheckMethodAdapter.checkDesc(desc, false);
+        if (value == null) {
+            throw new IllegalArgumentException("Invalid enum value");
+        }
+        if (av != null) {
+            av.visitEnum(name, desc, value);
+        }
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String name,
+            final String desc) {
+        checkEnd();
+        checkName(name);
+        CheckMethodAdapter.checkDesc(desc, false);
+        return new CheckAnnotationAdapter(av == null ? null
+                : av.visitAnnotation(name, desc));
+    }
+
+    @Override
+    public AnnotationVisitor visitArray(final String name) {
+        checkEnd();
+        checkName(name);
+        return new CheckAnnotationAdapter(av == null ? null
+                : av.visitArray(name), false);
+    }
+
+    @Override
+    public void visitEnd() {
+        checkEnd();
+        end = true;
+        if (av != null) {
+            av.visitEnd();
+        }
+    }
+
+    private void checkEnd() {
+        if (end) {
+            throw new IllegalStateException(
+                    "Cannot call a visit method after visitEnd has been called");
+        }
+    }
+
+    private void checkName(final String name) {
+        if (named && name == null) {
+            throw new IllegalArgumentException(
+                    "Annotation value name must not be null");
+        }
+    }
+}


[14/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
new file mode 100644
index 0000000..fe8400a
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
@@ -0,0 +1,1170 @@
+/***
+ * 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.commons;
+
+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;
+
+/**
+ * A {@link MethodVisitor} providing a more detailed API to generate and
+ * transform instructions.
+ * 
+ * @author Eric Bruneton
+ */
+public class InstructionAdapter extends MethodVisitor {
+
+    public final static Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;");
+
+    /**
+     * Creates a new {@link InstructionAdapter}. <i>Subclasses must not use this
+     * constructor</i>. Instead, they must use the
+     * {@link #InstructionAdapter(int, MethodVisitor)} version.
+     * 
+     * @param mv
+     *            the method visitor to which this adapter delegates calls.
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public InstructionAdapter(final MethodVisitor mv) {
+        this(Opcodes.ASM5, mv);
+        if (getClass() != InstructionAdapter.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Creates a new {@link InstructionAdapter}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param mv
+     *            the method visitor to which this adapter delegates calls.
+     */
+    protected InstructionAdapter(final int api, final MethodVisitor mv) {
+        super(api, mv);
+    }
+
+    @Override
+    public void visitInsn(final int opcode) {
+        switch (opcode) {
+        case Opcodes.NOP:
+            nop();
+            break;
+        case Opcodes.ACONST_NULL:
+            aconst(null);
+            break;
+        case Opcodes.ICONST_M1:
+        case Opcodes.ICONST_0:
+        case Opcodes.ICONST_1:
+        case Opcodes.ICONST_2:
+        case Opcodes.ICONST_3:
+        case Opcodes.ICONST_4:
+        case Opcodes.ICONST_5:
+            iconst(opcode - Opcodes.ICONST_0);
+            break;
+        case Opcodes.LCONST_0:
+        case Opcodes.LCONST_1:
+            lconst(opcode - Opcodes.LCONST_0);
+            break;
+        case Opcodes.FCONST_0:
+        case Opcodes.FCONST_1:
+        case Opcodes.FCONST_2:
+            fconst(opcode - Opcodes.FCONST_0);
+            break;
+        case Opcodes.DCONST_0:
+        case Opcodes.DCONST_1:
+            dconst(opcode - Opcodes.DCONST_0);
+            break;
+        case Opcodes.IALOAD:
+            aload(Type.INT_TYPE);
+            break;
+        case Opcodes.LALOAD:
+            aload(Type.LONG_TYPE);
+            break;
+        case Opcodes.FALOAD:
+            aload(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DALOAD:
+            aload(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.AALOAD:
+            aload(OBJECT_TYPE);
+            break;
+        case Opcodes.BALOAD:
+            aload(Type.BYTE_TYPE);
+            break;
+        case Opcodes.CALOAD:
+            aload(Type.CHAR_TYPE);
+            break;
+        case Opcodes.SALOAD:
+            aload(Type.SHORT_TYPE);
+            break;
+        case Opcodes.IASTORE:
+            astore(Type.INT_TYPE);
+            break;
+        case Opcodes.LASTORE:
+            astore(Type.LONG_TYPE);
+            break;
+        case Opcodes.FASTORE:
+            astore(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DASTORE:
+            astore(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.AASTORE:
+            astore(OBJECT_TYPE);
+            break;
+        case Opcodes.BASTORE:
+            astore(Type.BYTE_TYPE);
+            break;
+        case Opcodes.CASTORE:
+            astore(Type.CHAR_TYPE);
+            break;
+        case Opcodes.SASTORE:
+            astore(Type.SHORT_TYPE);
+            break;
+        case Opcodes.POP:
+            pop();
+            break;
+        case Opcodes.POP2:
+            pop2();
+            break;
+        case Opcodes.DUP:
+            dup();
+            break;
+        case Opcodes.DUP_X1:
+            dupX1();
+            break;
+        case Opcodes.DUP_X2:
+            dupX2();
+            break;
+        case Opcodes.DUP2:
+            dup2();
+            break;
+        case Opcodes.DUP2_X1:
+            dup2X1();
+            break;
+        case Opcodes.DUP2_X2:
+            dup2X2();
+            break;
+        case Opcodes.SWAP:
+            swap();
+            break;
+        case Opcodes.IADD:
+            add(Type.INT_TYPE);
+            break;
+        case Opcodes.LADD:
+            add(Type.LONG_TYPE);
+            break;
+        case Opcodes.FADD:
+            add(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DADD:
+            add(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.ISUB:
+            sub(Type.INT_TYPE);
+            break;
+        case Opcodes.LSUB:
+            sub(Type.LONG_TYPE);
+            break;
+        case Opcodes.FSUB:
+            sub(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DSUB:
+            sub(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.IMUL:
+            mul(Type.INT_TYPE);
+            break;
+        case Opcodes.LMUL:
+            mul(Type.LONG_TYPE);
+            break;
+        case Opcodes.FMUL:
+            mul(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DMUL:
+            mul(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.IDIV:
+            div(Type.INT_TYPE);
+            break;
+        case Opcodes.LDIV:
+            div(Type.LONG_TYPE);
+            break;
+        case Opcodes.FDIV:
+            div(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DDIV:
+            div(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.IREM:
+            rem(Type.INT_TYPE);
+            break;
+        case Opcodes.LREM:
+            rem(Type.LONG_TYPE);
+            break;
+        case Opcodes.FREM:
+            rem(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DREM:
+            rem(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.INEG:
+            neg(Type.INT_TYPE);
+            break;
+        case Opcodes.LNEG:
+            neg(Type.LONG_TYPE);
+            break;
+        case Opcodes.FNEG:
+            neg(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DNEG:
+            neg(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.ISHL:
+            shl(Type.INT_TYPE);
+            break;
+        case Opcodes.LSHL:
+            shl(Type.LONG_TYPE);
+            break;
+        case Opcodes.ISHR:
+            shr(Type.INT_TYPE);
+            break;
+        case Opcodes.LSHR:
+            shr(Type.LONG_TYPE);
+            break;
+        case Opcodes.IUSHR:
+            ushr(Type.INT_TYPE);
+            break;
+        case Opcodes.LUSHR:
+            ushr(Type.LONG_TYPE);
+            break;
+        case Opcodes.IAND:
+            and(Type.INT_TYPE);
+            break;
+        case Opcodes.LAND:
+            and(Type.LONG_TYPE);
+            break;
+        case Opcodes.IOR:
+            or(Type.INT_TYPE);
+            break;
+        case Opcodes.LOR:
+            or(Type.LONG_TYPE);
+            break;
+        case Opcodes.IXOR:
+            xor(Type.INT_TYPE);
+            break;
+        case Opcodes.LXOR:
+            xor(Type.LONG_TYPE);
+            break;
+        case Opcodes.I2L:
+            cast(Type.INT_TYPE, Type.LONG_TYPE);
+            break;
+        case Opcodes.I2F:
+            cast(Type.INT_TYPE, Type.FLOAT_TYPE);
+            break;
+        case Opcodes.I2D:
+            cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.L2I:
+            cast(Type.LONG_TYPE, Type.INT_TYPE);
+            break;
+        case Opcodes.L2F:
+            cast(Type.LONG_TYPE, Type.FLOAT_TYPE);
+            break;
+        case Opcodes.L2D:
+            cast(Type.LONG_TYPE, Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.F2I:
+            cast(Type.FLOAT_TYPE, Type.INT_TYPE);
+            break;
+        case Opcodes.F2L:
+            cast(Type.FLOAT_TYPE, Type.LONG_TYPE);
+            break;
+        case Opcodes.F2D:
+            cast(Type.FLOAT_TYPE, Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.D2I:
+            cast(Type.DOUBLE_TYPE, Type.INT_TYPE);
+            break;
+        case Opcodes.D2L:
+            cast(Type.DOUBLE_TYPE, Type.LONG_TYPE);
+            break;
+        case Opcodes.D2F:
+            cast(Type.DOUBLE_TYPE, Type.FLOAT_TYPE);
+            break;
+        case Opcodes.I2B:
+            cast(Type.INT_TYPE, Type.BYTE_TYPE);
+            break;
+        case Opcodes.I2C:
+            cast(Type.INT_TYPE, Type.CHAR_TYPE);
+            break;
+        case Opcodes.I2S:
+            cast(Type.INT_TYPE, Type.SHORT_TYPE);
+            break;
+        case Opcodes.LCMP:
+            lcmp();
+            break;
+        case Opcodes.FCMPL:
+            cmpl(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.FCMPG:
+            cmpg(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DCMPL:
+            cmpl(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.DCMPG:
+            cmpg(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.IRETURN:
+            areturn(Type.INT_TYPE);
+            break;
+        case Opcodes.LRETURN:
+            areturn(Type.LONG_TYPE);
+            break;
+        case Opcodes.FRETURN:
+            areturn(Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DRETURN:
+            areturn(Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.ARETURN:
+            areturn(OBJECT_TYPE);
+            break;
+        case Opcodes.RETURN:
+            areturn(Type.VOID_TYPE);
+            break;
+        case Opcodes.ARRAYLENGTH:
+            arraylength();
+            break;
+        case Opcodes.ATHROW:
+            athrow();
+            break;
+        case Opcodes.MONITORENTER:
+            monitorenter();
+            break;
+        case Opcodes.MONITOREXIT:
+            monitorexit();
+            break;
+        default:
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public void visitIntInsn(final int opcode, final int operand) {
+        switch (opcode) {
+        case Opcodes.BIPUSH:
+            iconst(operand);
+            break;
+        case Opcodes.SIPUSH:
+            iconst(operand);
+            break;
+        case Opcodes.NEWARRAY:
+            switch (operand) {
+            case Opcodes.T_BOOLEAN:
+                newarray(Type.BOOLEAN_TYPE);
+                break;
+            case Opcodes.T_CHAR:
+                newarray(Type.CHAR_TYPE);
+                break;
+            case Opcodes.T_BYTE:
+                newarray(Type.BYTE_TYPE);
+                break;
+            case Opcodes.T_SHORT:
+                newarray(Type.SHORT_TYPE);
+                break;
+            case Opcodes.T_INT:
+                newarray(Type.INT_TYPE);
+                break;
+            case Opcodes.T_FLOAT:
+                newarray(Type.FLOAT_TYPE);
+                break;
+            case Opcodes.T_LONG:
+                newarray(Type.LONG_TYPE);
+                break;
+            case Opcodes.T_DOUBLE:
+                newarray(Type.DOUBLE_TYPE);
+                break;
+            default:
+                throw new IllegalArgumentException();
+            }
+            break;
+        default:
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public void visitVarInsn(final int opcode, final int var) {
+        switch (opcode) {
+        case Opcodes.ILOAD:
+            load(var, Type.INT_TYPE);
+            break;
+        case Opcodes.LLOAD:
+            load(var, Type.LONG_TYPE);
+            break;
+        case Opcodes.FLOAD:
+            load(var, Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DLOAD:
+            load(var, Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.ALOAD:
+            load(var, OBJECT_TYPE);
+            break;
+        case Opcodes.ISTORE:
+            store(var, Type.INT_TYPE);
+            break;
+        case Opcodes.LSTORE:
+            store(var, Type.LONG_TYPE);
+            break;
+        case Opcodes.FSTORE:
+            store(var, Type.FLOAT_TYPE);
+            break;
+        case Opcodes.DSTORE:
+            store(var, Type.DOUBLE_TYPE);
+            break;
+        case Opcodes.ASTORE:
+            store(var, OBJECT_TYPE);
+            break;
+        case Opcodes.RET:
+            ret(var);
+            break;
+        default:
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public void visitTypeInsn(final int opcode, final String type) {
+        Type t = Type.getObjectType(type);
+        switch (opcode) {
+        case Opcodes.NEW:
+            anew(t);
+            break;
+        case Opcodes.ANEWARRAY:
+            newarray(t);
+            break;
+        case Opcodes.CHECKCAST:
+            checkcast(t);
+            break;
+        case Opcodes.INSTANCEOF:
+            instanceOf(t);
+            break;
+        default:
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public void visitFieldInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        switch (opcode) {
+        case Opcodes.GETSTATIC:
+            getstatic(owner, name, desc);
+            break;
+        case Opcodes.PUTSTATIC:
+            putstatic(owner, name, desc);
+            break;
+        case Opcodes.GETFIELD:
+            getfield(owner, name, desc);
+            break;
+        case Opcodes.PUTFIELD:
+            putfield(owner, name, desc);
+            break;
+        default:
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Deprecated
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (api >= Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc,
+                opcode == Opcodes.INVOKEINTERFACE);
+    }
+
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    private void doVisitMethodInsn(int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        switch (opcode) {
+        case Opcodes.INVOKESPECIAL:
+            invokespecial(owner, name, desc, itf);
+            break;
+        case Opcodes.INVOKEVIRTUAL:
+            invokevirtual(owner, name, desc, itf);
+            break;
+        case Opcodes.INVOKESTATIC:
+            invokestatic(owner, name, desc, itf);
+            break;
+        case Opcodes.INVOKEINTERFACE:
+            invokeinterface(owner, name, desc);
+            break;
+        default:
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        invokedynamic(name, desc, bsm, bsmArgs);
+    }
+
+    @Override
+    public void visitJumpInsn(final int opcode, final Label label) {
+        switch (opcode) {
+        case Opcodes.IFEQ:
+            ifeq(label);
+            break;
+        case Opcodes.IFNE:
+            ifne(label);
+            break;
+        case Opcodes.IFLT:
+            iflt(label);
+            break;
+        case Opcodes.IFGE:
+            ifge(label);
+            break;
+        case Opcodes.IFGT:
+            ifgt(label);
+            break;
+        case Opcodes.IFLE:
+            ifle(label);
+            break;
+        case Opcodes.IF_ICMPEQ:
+            ificmpeq(label);
+            break;
+        case Opcodes.IF_ICMPNE:
+            ificmpne(label);
+            break;
+        case Opcodes.IF_ICMPLT:
+            ificmplt(label);
+            break;
+        case Opcodes.IF_ICMPGE:
+            ificmpge(label);
+            break;
+        case Opcodes.IF_ICMPGT:
+            ificmpgt(label);
+            break;
+        case Opcodes.IF_ICMPLE:
+            ificmple(label);
+            break;
+        case Opcodes.IF_ACMPEQ:
+            ifacmpeq(label);
+            break;
+        case Opcodes.IF_ACMPNE:
+            ifacmpne(label);
+            break;
+        case Opcodes.GOTO:
+            goTo(label);
+            break;
+        case Opcodes.JSR:
+            jsr(label);
+            break;
+        case Opcodes.IFNULL:
+            ifnull(label);
+            break;
+        case Opcodes.IFNONNULL:
+            ifnonnull(label);
+            break;
+        default:
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public void visitLabel(final Label label) {
+        mark(label);
+    }
+
+    @Override
+    public void visitLdcInsn(final Object cst) {
+        if (cst instanceof Integer) {
+            int val = ((Integer) cst).intValue();
+            iconst(val);
+        } else if (cst instanceof Byte) {
+            int val = ((Byte) cst).intValue();
+            iconst(val);
+        } else if (cst instanceof Character) {
+            int val = ((Character) cst).charValue();
+            iconst(val);
+        } else if (cst instanceof Short) {
+            int val = ((Short) cst).intValue();
+            iconst(val);
+        } else if (cst instanceof Boolean) {
+            int val = ((Boolean) cst).booleanValue() ? 1 : 0;
+            iconst(val);
+        } else if (cst instanceof Float) {
+            float val = ((Float) cst).floatValue();
+            fconst(val);
+        } else if (cst instanceof Long) {
+            long val = ((Long) cst).longValue();
+            lconst(val);
+        } else if (cst instanceof Double) {
+            double val = ((Double) cst).doubleValue();
+            dconst(val);
+        } else if (cst instanceof String) {
+            aconst(cst);
+        } else if (cst instanceof Type) {
+            tconst((Type) cst);
+        } else if (cst instanceof Handle) {
+            hconst((Handle) cst);
+        } else {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public void visitIincInsn(final int var, final int increment) {
+        iinc(var, increment);
+    }
+
+    @Override
+    public void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels) {
+        tableswitch(min, max, dflt, labels);
+    }
+
+    @Override
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
+        lookupswitch(dflt, keys, labels);
+    }
+
+    @Override
+    public void visitMultiANewArrayInsn(final String desc, final int dims) {
+        multianewarray(desc, dims);
+    }
+
+    // -----------------------------------------------------------------------
+
+    public void nop() {
+        mv.visitInsn(Opcodes.NOP);
+    }
+
+    public void aconst(final Object cst) {
+        if (cst == null) {
+            mv.visitInsn(Opcodes.ACONST_NULL);
+        } else {
+            mv.visitLdcInsn(cst);
+        }
+    }
+
+    public void iconst(final int cst) {
+        if (cst >= -1 && cst <= 5) {
+            mv.visitInsn(Opcodes.ICONST_0 + cst);
+        } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {
+            mv.visitIntInsn(Opcodes.BIPUSH, cst);
+        } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {
+            mv.visitIntInsn(Opcodes.SIPUSH, cst);
+        } else {
+            mv.visitLdcInsn(new Integer(cst));
+        }
+    }
+
+    public void lconst(final long cst) {
+        if (cst == 0L || cst == 1L) {
+            mv.visitInsn(Opcodes.LCONST_0 + (int) cst);
+        } else {
+            mv.visitLdcInsn(new Long(cst));
+        }
+    }
+
+    public void fconst(final float cst) {
+        int bits = Float.floatToIntBits(cst);
+        if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2
+            mv.visitInsn(Opcodes.FCONST_0 + (int) cst);
+        } else {
+            mv.visitLdcInsn(new Float(cst));
+        }
+    }
+
+    public void dconst(final double cst) {
+        long bits = Double.doubleToLongBits(cst);
+        if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d
+            mv.visitInsn(Opcodes.DCONST_0 + (int) cst);
+        } else {
+            mv.visitLdcInsn(new Double(cst));
+        }
+    }
+
+    public void tconst(final Type type) {
+        mv.visitLdcInsn(type);
+    }
+
+    public void hconst(final Handle handle) {
+        mv.visitLdcInsn(handle);
+    }
+
+    public void load(final int var, final Type type) {
+        mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), var);
+    }
+
+    public void aload(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
+    }
+
+    public void store(final int var, final Type type) {
+        mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), var);
+    }
+
+    public void astore(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
+    }
+
+    public void pop() {
+        mv.visitInsn(Opcodes.POP);
+    }
+
+    public void pop2() {
+        mv.visitInsn(Opcodes.POP2);
+    }
+
+    public void dup() {
+        mv.visitInsn(Opcodes.DUP);
+    }
+
+    public void dup2() {
+        mv.visitInsn(Opcodes.DUP2);
+    }
+
+    public void dupX1() {
+        mv.visitInsn(Opcodes.DUP_X1);
+    }
+
+    public void dupX2() {
+        mv.visitInsn(Opcodes.DUP_X2);
+    }
+
+    public void dup2X1() {
+        mv.visitInsn(Opcodes.DUP2_X1);
+    }
+
+    public void dup2X2() {
+        mv.visitInsn(Opcodes.DUP2_X2);
+    }
+
+    public void swap() {
+        mv.visitInsn(Opcodes.SWAP);
+    }
+
+    public void add(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IADD));
+    }
+
+    public void sub(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.ISUB));
+    }
+
+    public void mul(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IMUL));
+    }
+
+    public void div(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IDIV));
+    }
+
+    public void rem(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IREM));
+    }
+
+    public void neg(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.INEG));
+    }
+
+    public void shl(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.ISHL));
+    }
+
+    public void shr(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.ISHR));
+    }
+
+    public void ushr(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IUSHR));
+    }
+
+    public void and(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IAND));
+    }
+
+    public void or(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IOR));
+    }
+
+    public void xor(final Type type) {
+        mv.visitInsn(type.getOpcode(Opcodes.IXOR));
+    }
+
+    public void iinc(final int var, final int increment) {
+        mv.visitIincInsn(var, increment);
+    }
+
+    public void cast(final Type from, final Type to) {
+        if (from != to) {
+            if (from == Type.DOUBLE_TYPE) {
+                if (to == Type.FLOAT_TYPE) {
+                    mv.visitInsn(Opcodes.D2F);
+                } else if (to == Type.LONG_TYPE) {
+                    mv.visitInsn(Opcodes.D2L);
+                } else {
+                    mv.visitInsn(Opcodes.D2I);
+                    cast(Type.INT_TYPE, to);
+                }
+            } else if (from == Type.FLOAT_TYPE) {
+                if (to == Type.DOUBLE_TYPE) {
+                    mv.visitInsn(Opcodes.F2D);
+                } else if (to == Type.LONG_TYPE) {
+                    mv.visitInsn(Opcodes.F2L);
+                } else {
+                    mv.visitInsn(Opcodes.F2I);
+                    cast(Type.INT_TYPE, to);
+                }
+            } else if (from == Type.LONG_TYPE) {
+                if (to == Type.DOUBLE_TYPE) {
+                    mv.visitInsn(Opcodes.L2D);
+                } else if (to == Type.FLOAT_TYPE) {
+                    mv.visitInsn(Opcodes.L2F);
+                } else {
+                    mv.visitInsn(Opcodes.L2I);
+                    cast(Type.INT_TYPE, to);
+                }
+            } else {
+                if (to == Type.BYTE_TYPE) {
+                    mv.visitInsn(Opcodes.I2B);
+                } else if (to == Type.CHAR_TYPE) {
+                    mv.visitInsn(Opcodes.I2C);
+                } else if (to == Type.DOUBLE_TYPE) {
+                    mv.visitInsn(Opcodes.I2D);
+                } else if (to == Type.FLOAT_TYPE) {
+                    mv.visitInsn(Opcodes.I2F);
+                } else if (to == Type.LONG_TYPE) {
+                    mv.visitInsn(Opcodes.I2L);
+                } else if (to == Type.SHORT_TYPE) {
+                    mv.visitInsn(Opcodes.I2S);
+                }
+            }
+        }
+    }
+
+    public void lcmp() {
+        mv.visitInsn(Opcodes.LCMP);
+    }
+
+    public void cmpl(final Type type) {
+        mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPL : Opcodes.DCMPL);
+    }
+
+    public void cmpg(final Type type) {
+        mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPG : Opcodes.DCMPG);
+    }
+
+    public void ifeq(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFEQ, label);
+    }
+
+    public void ifne(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFNE, label);
+    }
+
+    public void iflt(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFLT, label);
+    }
+
+    public void ifge(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFGE, label);
+    }
+
+    public void ifgt(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFGT, label);
+    }
+
+    public void ifle(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFLE, label);
+    }
+
+    public void ificmpeq(final Label label) {
+        mv.visitJumpInsn(Opcodes.IF_ICMPEQ, label);
+    }
+
+    public void ificmpne(final Label label) {
+        mv.visitJumpInsn(Opcodes.IF_ICMPNE, label);
+    }
+
+    public void ificmplt(final Label label) {
+        mv.visitJumpInsn(Opcodes.IF_ICMPLT, label);
+    }
+
+    public void ificmpge(final Label label) {
+        mv.visitJumpInsn(Opcodes.IF_ICMPGE, label);
+    }
+
+    public void ificmpgt(final Label label) {
+        mv.visitJumpInsn(Opcodes.IF_ICMPGT, label);
+    }
+
+    public void ificmple(final Label label) {
+        mv.visitJumpInsn(Opcodes.IF_ICMPLE, label);
+    }
+
+    public void ifacmpeq(final Label label) {
+        mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
+    }
+
+    public void ifacmpne(final Label label) {
+        mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
+    }
+
+    public void goTo(final Label label) {
+        mv.visitJumpInsn(Opcodes.GOTO, label);
+    }
+
+    public void jsr(final Label label) {
+        mv.visitJumpInsn(Opcodes.JSR, label);
+    }
+
+    public void ret(final int var) {
+        mv.visitVarInsn(Opcodes.RET, var);
+    }
+
+    public void tableswitch(final int min, final int max, final Label dflt,
+            final Label... labels) {
+        mv.visitTableSwitchInsn(min, max, dflt, labels);
+    }
+
+    public void lookupswitch(final Label dflt, final int[] keys,
+            final Label[] labels) {
+        mv.visitLookupSwitchInsn(dflt, keys, labels);
+    }
+
+    public void areturn(final Type t) {
+        mv.visitInsn(t.getOpcode(Opcodes.IRETURN));
+    }
+
+    public void getstatic(final String owner, final String name,
+            final String desc) {
+        mv.visitFieldInsn(Opcodes.GETSTATIC, owner, name, desc);
+    }
+
+    public void putstatic(final String owner, final String name,
+            final String desc) {
+        mv.visitFieldInsn(Opcodes.PUTSTATIC, owner, name, desc);
+    }
+
+    public void getfield(final String owner, final String name,
+            final String desc) {
+        mv.visitFieldInsn(Opcodes.GETFIELD, owner, name, desc);
+    }
+
+    public void putfield(final String owner, final String name,
+            final String desc) {
+        mv.visitFieldInsn(Opcodes.PUTFIELD, owner, name, desc);
+    }
+
+    @Deprecated
+    public void invokevirtual(final String owner, final String name,
+            final String desc) {
+        if (api >= Opcodes.ASM5) {
+            invokevirtual(owner, name, desc, false);
+            return;
+        }
+        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc);
+    }
+
+    public void invokevirtual(final String owner, final String name,
+            final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            if (itf) {
+                throw new IllegalArgumentException(
+                        "INVOKEVIRTUAL on interfaces require ASM 5");
+            }
+            invokevirtual(owner, name, desc);
+            return;
+        }
+        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, itf);
+    }
+
+    @Deprecated
+    public void invokespecial(final String owner, final String name,
+            final String desc) {
+        if (api >= Opcodes.ASM5) {
+            invokespecial(owner, name, desc, false);
+            return;
+        }
+        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, false);
+    }
+
+    public void invokespecial(final String owner, final String name,
+            final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            if (itf) {
+                throw new IllegalArgumentException(
+                        "INVOKESPECIAL on interfaces require ASM 5");
+            }
+            invokespecial(owner, name, desc);
+            return;
+        }
+        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, itf);
+    }
+
+    @Deprecated
+    public void invokestatic(final String owner, final String name,
+            final String desc) {
+        if (api >= Opcodes.ASM5) {
+            invokestatic(owner, name, desc, false);
+            return;
+        }
+        mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, false);
+    }
+
+    public void invokestatic(final String owner, final String name,
+            final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            if (itf) {
+                throw new IllegalArgumentException(
+                        "INVOKESTATIC on interfaces require ASM 5");
+            }
+            invokestatic(owner, name, desc);
+            return;
+        }
+        mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, itf);
+    }
+
+    public void invokeinterface(final String owner, final String name,
+            final String desc) {
+        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, desc, true);
+    }
+
+    public void invokedynamic(String name, String desc, Handle bsm,
+            Object[] bsmArgs) {
+        mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+    }
+
+    public void anew(final Type type) {
+        mv.visitTypeInsn(Opcodes.NEW, type.getInternalName());
+    }
+
+    public void newarray(final Type type) {
+        int typ;
+        switch (type.getSort()) {
+        case Type.BOOLEAN:
+            typ = Opcodes.T_BOOLEAN;
+            break;
+        case Type.CHAR:
+            typ = Opcodes.T_CHAR;
+            break;
+        case Type.BYTE:
+            typ = Opcodes.T_BYTE;
+            break;
+        case Type.SHORT:
+            typ = Opcodes.T_SHORT;
+            break;
+        case Type.INT:
+            typ = Opcodes.T_INT;
+            break;
+        case Type.FLOAT:
+            typ = Opcodes.T_FLOAT;
+            break;
+        case Type.LONG:
+            typ = Opcodes.T_LONG;
+            break;
+        case Type.DOUBLE:
+            typ = Opcodes.T_DOUBLE;
+            break;
+        default:
+            mv.visitTypeInsn(Opcodes.ANEWARRAY, type.getInternalName());
+            return;
+        }
+        mv.visitIntInsn(Opcodes.NEWARRAY, typ);
+    }
+
+    public void arraylength() {
+        mv.visitInsn(Opcodes.ARRAYLENGTH);
+    }
+
+    public void athrow() {
+        mv.visitInsn(Opcodes.ATHROW);
+    }
+
+    public void checkcast(final Type type) {
+        mv.visitTypeInsn(Opcodes.CHECKCAST, type.getInternalName());
+    }
+
+    public void instanceOf(final Type type) {
+        mv.visitTypeInsn(Opcodes.INSTANCEOF, type.getInternalName());
+    }
+
+    public void monitorenter() {
+        mv.visitInsn(Opcodes.MONITORENTER);
+    }
+
+    public void monitorexit() {
+        mv.visitInsn(Opcodes.MONITOREXIT);
+    }
+
+    public void multianewarray(final String desc, final int dims) {
+        mv.visitMultiANewArrayInsn(desc, dims);
+    }
+
+    public void ifnull(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFNULL, label);
+    }
+
+    public void ifnonnull(final Label label) {
+        mv.visitJumpInsn(Opcodes.IFNONNULL, label);
+    }
+
+    public void mark(final Label label) {
+        mv.visitLabel(label);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
index 21f1d68..08e1f3c 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
@@ -29,32 +29,47 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.commons;
 
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 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.tree.*;
-
-import java.util.*;
+import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.InsnList;
+import org.apache.tapestry5.internal.plastic.asm.tree.InsnNode;
+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.LocalVariableNode;
+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;
 
 /**
  * A {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor} that removes JSR instructions and
  * inlines the referenced subroutines.
- *
+ * 
  * <b>Explanation of how it works</b> TODO
- *
+ * 
  * @author Niko Matsakis
  */
-public class JSRInlinerAdapter extends MethodNode implements Opcodes
-{
+public class JSRInlinerAdapter extends MethodNode implements Opcodes {
 
     private static final boolean LOGGING = false;
 
     /**
-     * For each label that is jumped to by a JSR, we create a BitSet
-     * instance.
+     * For each label that is jumped to by a JSR, we create a BitSet instance.
      */
-    private final Map<LabelNode,BitSet> subroutineHeads = new HashMap<LabelNode,BitSet>();
+    private final Map<LabelNode, BitSet> subroutineHeads = new HashMap<LabelNode, BitSet>();
 
     /**
      * This subroutine instance denotes the line of execution that is not
@@ -72,58 +87,65 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
     /**
      * Creates a new JSRInliner. <i>Subclasses must not use this
      * constructor</i>. Instead, they must use the
-     * {@link #JSRInlinerAdapter(int, org.apache.tapestry5.internal.plastic.asm.MethodVisitor, int, String, String, String, String[])}
+     * {@link #JSRInlinerAdapter(int, MethodVisitor, int, String, String, String, String[])}
      * version.
-     *
-     * @param mv the <code>MethodVisitor</code> to send the resulting inlined
-     *        method code to (use <code>null</code> for none).
-     * @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>.
+     * 
+     * @param mv
+     *            the <code>MethodVisitor</code> to send the resulting inlined
+     *            method code to (use <code>null</code> for none).
+     * @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 JSRInlinerAdapter(
-        final MethodVisitor mv,
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final String[] exceptions)
-    {
-        this(Opcodes.ASM4, mv, access, name, desc, signature, exceptions);
+    public JSRInlinerAdapter(final MethodVisitor mv, final int access,
+            final String name, final String desc, final String signature,
+            final String[] exceptions) {
+        this(Opcodes.ASM5, mv, access, name, desc, signature, exceptions);
+        if (getClass() != JSRInlinerAdapter.class) {
+            throw new IllegalStateException();
+        }
     }
 
     /**
      * Creates a new JSRInliner.
-     *
-     * @param api the ASM API version implemented by this visitor. Must be one
-     *        of {@link Opcodes#ASM4}.
-     * @param mv the <code>MethodVisitor</code> to send the resulting inlined
-     *        method code to (use <code>null</code> for none).
-     * @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>.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param mv
+     *            the <code>MethodVisitor</code> to send the resulting inlined
+     *            method code to (use <code>null</code> for none).
+     * @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>.
      */
-    protected JSRInlinerAdapter(
-        final int api,
-        final MethodVisitor mv,
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final String[] exceptions)
-    {
+    protected JSRInlinerAdapter(final int api, final MethodVisitor mv,
+            final int access, final String name, final String desc,
+            final String signature, final String[] exceptions) {
         super(api, access, name, desc, signature, exceptions);
         this.mv = mv;
     }
@@ -179,9 +201,9 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
 
         // Go through the head of each subroutine and find any nodes reachable
         // to that subroutine without following any JSR links.
-        for (Iterator<Map.Entry<LabelNode,BitSet>> it = subroutineHeads.entrySet().iterator(); it.hasNext();)
-        {
-            Map.Entry<LabelNode,BitSet> entry = it.next();
+        for (Iterator<Map.Entry<LabelNode, BitSet>> it = subroutineHeads
+                .entrySet().iterator(); it.hasNext();) {
+            Map.Entry<LabelNode, BitSet> entry = it.next();
             LabelNode lab = entry.getKey();
             BitSet sub = entry.getValue();
             int index = instructions.indexOf(lab);
@@ -191,24 +213,22 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
 
     /**
      * Performs a depth first search walking the normal byte code path starting
-     * at <code>index</code>, and adding each instruction encountered into
-     * the subroutine <code>sub</code>. After this walk is complete, iterates
-     * over the exception handlers to ensure that we also include those byte
-     * codes which are reachable through an exception that may be thrown during
-     * the execution of the subroutine. Invoked from
-     * <code>markSubroutines()</code>.
-     *
-     * @param sub the subroutine whose instructions must be computed.
-     * @param index an instruction of this subroutine.
-     * @param anyvisited indexes of the already visited instructions, i.e.
-     *        marked as part of this subroutine or any previously computed
-     *        subroutine.
+     * at <code>index</code>, and adding each instruction encountered into the
+     * subroutine <code>sub</code>. After this walk is complete, iterates over
+     * the exception handlers to ensure that we also include those byte codes
+     * which are reachable through an exception that may be thrown during the
+     * execution of the subroutine. Invoked from <code>markSubroutines()</code>.
+     * 
+     * @param sub
+     *            the subroutine whose instructions must be computed.
+     * @param index
+     *            an instruction of this subroutine.
+     * @param anyvisited
+     *            indexes of the already visited instructions, i.e. marked as
+     *            part of this subroutine or any previously computed subroutine.
      */
-    private void markSubroutineWalk(
-        final BitSet sub,
-        final int index,
-        final BitSet anyvisited)
-    {
+    private void markSubroutineWalk(final BitSet sub, final int index,
+            final BitSet anyvisited) {
         if (LOGGING) {
             log("markSubroutineWalk: sub=" + sub + " index=" + index);
         }
@@ -220,7 +240,8 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
         boolean loop = true;
         while (loop) {
             loop = false;
-            for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it.hasNext();) {
+            for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it
+                    .hasNext();) {
                 TryCatchBlockNode trycatch = it.next();
 
                 if (LOGGING) {
@@ -252,20 +273,19 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
 
     /**
      * Performs a simple DFS of the instructions, assigning each to the
-     * subroutine <code>sub</code>. Starts from <code>index</code>.
-     * Invoked only by <code>markSubroutineWalk()</code>.
-     *
-     * @param sub the subroutine whose instructions must be computed.
-     * @param index an instruction of this subroutine.
-     * @param anyvisited indexes of the already visited instructions, i.e.
-     *        marked as part of this subroutine or any previously computed
-     *        subroutine.
+     * subroutine <code>sub</code>. Starts from <code>index</code>. Invoked only
+     * by <code>markSubroutineWalk()</code>.
+     * 
+     * @param sub
+     *            the subroutine whose instructions must be computed.
+     * @param index
+     *            an instruction of this subroutine.
+     * @param anyvisited
+     *            indexes of the already visited instructions, i.e. marked as
+     *            part of this subroutine or any previously computed subroutine.
      */
-    private void markSubroutineWalkDFS(
-        final BitSet sub,
-        int index,
-        final BitSet anyvisited)
-    {
+    private void markSubroutineWalkDFS(final BitSet sub, int index,
+            final BitSet anyvisited) {
         while (true) {
             AbstractInsnNode node = instructions.get(index);
 
@@ -285,8 +305,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
             anyvisited.set(index);
 
             if (node.getType() == AbstractInsnNode.JUMP_INSN
-                    && node.getOpcode() != JSR)
-            {
+                    && node.getOpcode() != JSR) {
                 // we do not follow recursively called subroutines here; but any
                 // other sort of branch we do follow
                 JumpInsnNode jnode = (JumpInsnNode) node;
@@ -317,27 +336,38 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
             // check to see if this opcode falls through to the next instruction
             // or not; if not, return.
             switch (instructions.get(index).getOpcode()) {
-                case GOTO:
-                case RET:
-                case TABLESWITCH:
-                case LOOKUPSWITCH:
-                case IRETURN:
-                case LRETURN:
-                case FRETURN:
-                case DRETURN:
-                case ARETURN:
-                case RETURN:
-                case ATHROW:
-                    /*
-                     * note: this either returns from this subroutine, or a
-                     * parent subroutine which invoked it
-                     */
-                    return;
+            case GOTO:
+            case RET:
+            case TABLESWITCH:
+            case LOOKUPSWITCH:
+            case IRETURN:
+            case LRETURN:
+            case FRETURN:
+            case DRETURN:
+            case ARETURN:
+            case RETURN:
+            case ATHROW:
+                /*
+                 * note: this either returns from this subroutine, or a parent
+                 * subroutine which invoked it
+                 */
+                return;
             }
 
             // Use tail recursion here in the form of an outer while loop to
             // avoid our stack growing needlessly:
             index++;
+
+            // We implicitly assumed above that execution can always fall
+            // through to the next instruction after a JSR. But a subroutine may
+            // never return, in which case the code after the JSR is unreachable
+            // and can be anything. In particular, it can seem to fall off the
+            // end of the method, so we must handle this case here (we could
+            // instead detect whether execution can return or not from a JSR,
+            // but this is more complicated).
+            if (index >= instructions.size()) {
+                return;
+            }
         }
     }
 
@@ -358,10 +388,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
         List<LocalVariableNode> newLocalVariables = new ArrayList<LocalVariableNode>();
         while (!worklist.isEmpty()) {
             Instantiation inst = worklist.removeFirst();
-            emitSubroutine(inst,
-                    worklist,
-                    newInstructions,
-                    newTryCatchBlocks,
+            emitSubroutine(inst, worklist, newInstructions, newTryCatchBlocks,
                     newLocalVariables);
         }
         instructions = newInstructions;
@@ -371,24 +398,25 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
 
     /**
      * Emits one instantiation of one subroutine, specified by
-     * <code>instant</code>. May add new instantiations that are invoked by
-     * this one to the <code>worklist</code> parameter, and new try/catch
-     * blocks to <code>newTryCatchBlocks</code>.
-     *
-     * @param instant the instantiation that must be performed.
-     * @param worklist list of the instantiations that remain to be done.
-     * @param newInstructions the instruction list to which the instantiated
-     *        code must be appended.
-     * @param newTryCatchBlocks the exception handler list to which the
-     *        instantiated handlers must be appended.
+     * <code>instant</code>. May add new instantiations that are invoked by this
+     * one to the <code>worklist</code> parameter, and new try/catch blocks to
+     * <code>newTryCatchBlocks</code>.
+     * 
+     * @param instant
+     *            the instantiation that must be performed.
+     * @param worklist
+     *            list of the instantiations that remain to be done.
+     * @param newInstructions
+     *            the instruction list to which the instantiated code must be
+     *            appended.
+     * @param newTryCatchBlocks
+     *            the exception handler list to which the instantiated handlers
+     *            must be appended.
      */
-    private void emitSubroutine(
-        final Instantiation instant,
-        final List<Instantiation> worklist,
-        final InsnList newInstructions,
-        final List<TryCatchBlockNode> newTryCatchBlocks,
-        final List<LocalVariableNode> newLocalVariables)
-    {
+    private void emitSubroutine(final Instantiation instant,
+            final List<Instantiation> worklist, final InsnList newInstructions,
+            final List<TryCatchBlockNode> newTryCatchBlocks,
+            final List<LocalVariableNode> newLocalVariables) {
         LabelNode duplbl = null;
 
         if (LOGGING) {
@@ -485,7 +513,8 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
         }
 
         // Emit try/catch blocks that are relevant to this method.
-        for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it.hasNext();) {
+        for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it
+                .hasNext();) {
             TryCatchBlockNode trycatch = it.next();
 
             if (LOGGING) {
@@ -517,13 +546,12 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
                 throw new RuntimeException("Internal error!");
             }
 
-            newTryCatchBlocks.add(new TryCatchBlockNode(start,
-                    end,
-                    handler,
+            newTryCatchBlocks.add(new TryCatchBlockNode(start, end, handler,
                     trycatch.type));
         }
 
-        for (Iterator<LocalVariableNode> it = localVariables.iterator(); it.hasNext();) {
+        for (Iterator<LocalVariableNode> it = localVariables.iterator(); it
+                .hasNext();) {
             LocalVariableNode lvnode = it.next();
             if (LOGGING) {
                 log("local var " + lvnode.name);
@@ -537,11 +565,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
                 continue;
             }
             newLocalVariables.add(new LocalVariableNode(lvnode.name,
-                    lvnode.desc,
-                    lvnode.signature,
-                    start,
-                    end,
-                    lvnode.index));
+                    lvnode.desc, lvnode.signature, start, end, lvnode.index));
         }
     }
 
@@ -574,14 +598,14 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
          * This table maps Labels from the original source to Labels pointing at
          * code specific to this instantiation, for use in remapping try/catch
          * blocks,as well as gotos.
-         *
+         * 
          * Note that in the presence of dual citizens instructions, that is,
          * instructions which belong to more than one subroutine due to the
          * merging of control flow without a RET instruction, we will map the
          * target label of a GOTO to the label used by the instantiation lowest
          * on the stack. This avoids code duplication during inlining in most
          * cases.
-         *
+         * 
          * @see #findOwner(int)
          */
         public final Map<LabelNode, LabelNode> rangeTable = new HashMap<LabelNode, LabelNode>();
@@ -644,21 +668,22 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
          * Returns the "owner" of a particular instruction relative to this
          * instantiation: the owner referes to the Instantiation which will emit
          * the version of this instruction that we will execute.
-         *
+         * 
          * Typically, the return value is either <code>this</code> or
          * <code>null</code>. <code>this</code> indicates that this
          * instantiation will generate the version of this instruction that we
-         * will execute, and <code>null</code> indicates that this
-         * instantiation never executes the given instruction.
-         *
+         * will execute, and <code>null</code> indicates that this instantiation
+         * never executes the given instruction.
+         * 
          * Sometimes, however, an instruction can belong to multiple
          * subroutines; this is called a "dual citizen" instruction (though it
          * may belong to more than 2 subroutines), and occurs when multiple
          * subroutines branch to common points of control. In this case, the
          * owner is the subroutine that appears lowest on the stack, and which
          * also owns the instruction in question.
-         *
-         * @param i the index of the instruction in the original code
+         * 
+         * @param i
+         *            the index of the instruction in the original code
          * @return the "owner" of a particular instruction relative to this
          *         instantiation.
          */
@@ -679,12 +704,13 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
         }
 
         /**
-         * Looks up the label <code>l</code> in the <code>gotoTable</code>,
-         * thus translating it from a Label in the original code, to a Label in
-         * the inlined code that is appropriate for use by an instruction that
+         * Looks up the label <code>l</code> in the <code>gotoTable</code>, thus
+         * translating it from a Label in the original code, to a Label in the
+         * inlined code that is appropriate for use by an instruction that
          * branched to the original label.
-         *
-         * @param l The label we will be translating
+         * 
+         * @param l
+         *            The label we will be translating
          * @return a label for use by a branch instruction in the inlined code
          * @see #rangeLabel
          */
@@ -700,8 +726,9 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
          * thus translating it from a Label in the original code, to a Label in
          * the inlined code that is appropriate for use by an try/catch or
          * variable use annotation.
-         *
-         * @param l The label we will be translating
+         * 
+         * @param l
+         *            The label we will be translating
          * @return a label for use by a try/catch or variable annotation in the
          *         original code
          * @see #rangeTable

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java
new file mode 100644
index 0000000..3a21047
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java
@@ -0,0 +1,381 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+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 {@link MethodVisitor} that renumbers local variables in their order of
+ * appearance. This adapter allows one to easily add new local variables to a
+ * method. It may be used by inheriting from this class, but the preferred way
+ * of using it is via delegation: the next visitor in the chain can indeed add
+ * new locals when needed by calling {@link #newLocal} on this adapter (this
+ * requires a reference back to this {@link LocalVariablesSorter}).
+ * 
+ * @author Chris Nokleberg
+ * @author Eugene Kuleshov
+ * @author Eric Bruneton
+ */
+public class LocalVariablesSorter extends MethodVisitor {
+
+    private static final Type OBJECT_TYPE = Type
+            .getObjectType("java/lang/Object");
+
+    /**
+     * Mapping from old to new local variable indexes. A local variable at index
+     * i of size 1 is remapped to 'mapping[2*i]', while a local variable at
+     * index i of size 2 is remapped to 'mapping[2*i+1]'.
+     */
+    private int[] mapping = new int[40];
+
+    /**
+     * Array used to store stack map local variable types after remapping.
+     */
+    private Object[] newLocals = new Object[20];
+
+    /**
+     * Index of the first local variable, after formal parameters.
+     */
+    protected final int firstLocal;
+
+    /**
+     * Index of the next local variable to be created by {@link #newLocal}.
+     */
+    protected int nextLocal;
+
+    /**
+     * Indicates if at least one local variable has moved due to remapping.
+     */
+    private boolean changed;
+
+    /**
+     * Creates a new {@link LocalVariablesSorter}. <i>Subclasses must not use
+     * this constructor</i>. Instead, they must use the
+     * {@link #LocalVariablesSorter(int, int, String, MethodVisitor)} version.
+     * 
+     * @param access
+     *            access flags of the adapted method.
+     * @param desc
+     *            the method's descriptor (see {@link Type Type}).
+     * @param mv
+     *            the method visitor to which this adapter delegates calls.
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public LocalVariablesSorter(final int access, final String desc,
+            final MethodVisitor mv) {
+        this(Opcodes.ASM5, access, desc, mv);
+        if (getClass() != LocalVariablesSorter.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Creates a new {@link LocalVariablesSorter}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param access
+     *            access flags of the adapted method.
+     * @param desc
+     *            the method's descriptor (see {@link Type Type}).
+     * @param mv
+     *            the method visitor to which this adapter delegates calls.
+     */
+    protected LocalVariablesSorter(final int api, final int access,
+            final String desc, final MethodVisitor mv) {
+        super(api, mv);
+        Type[] args = Type.getArgumentTypes(desc);
+        nextLocal = (Opcodes.ACC_STATIC & access) == 0 ? 1 : 0;
+        for (int i = 0; i < args.length; i++) {
+            nextLocal += args[i].getSize();
+        }
+        firstLocal = nextLocal;
+    }
+
+    @Override
+    public void visitVarInsn(final int opcode, final int var) {
+        Type type;
+        switch (opcode) {
+        case Opcodes.LLOAD:
+        case Opcodes.LSTORE:
+            type = Type.LONG_TYPE;
+            break;
+
+        case Opcodes.DLOAD:
+        case Opcodes.DSTORE:
+            type = Type.DOUBLE_TYPE;
+            break;
+
+        case Opcodes.FLOAD:
+        case Opcodes.FSTORE:
+            type = Type.FLOAT_TYPE;
+            break;
+
+        case Opcodes.ILOAD:
+        case Opcodes.ISTORE:
+            type = Type.INT_TYPE;
+            break;
+
+        default:
+            // case Opcodes.ALOAD:
+            // case Opcodes.ASTORE:
+            // case RET:
+            type = OBJECT_TYPE;
+            break;
+        }
+        mv.visitVarInsn(opcode, remap(var, type));
+    }
+
+    @Override
+    public void visitIincInsn(final int var, final int increment) {
+        mv.visitIincInsn(remap(var, Type.INT_TYPE), increment);
+    }
+
+    @Override
+    public void visitMaxs(final int maxStack, final int maxLocals) {
+        mv.visitMaxs(maxStack, nextLocal);
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
+        int newIndex = remap(index, Type.getType(desc));
+        mv.visitLocalVariable(name, desc, signature, start, end, newIndex);
+    }
+
+    @Override
+    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+            TypePath typePath, Label[] start, Label[] end, int[] index,
+            String desc, boolean visible) {
+        Type t = Type.getType(desc);
+        int[] newIndex = new int[index.length];
+        for (int i = 0; i < newIndex.length; ++i) {
+            newIndex[i] = remap(index[i], t);
+        }
+        return mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
+                newIndex, desc, visible);
+    }
+
+    @Override
+    public void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack) {
+        if (type != Opcodes.F_NEW) { // uncompressed frame
+            throw new IllegalStateException(
+                    "ClassReader.accept() should be called with EXPAND_FRAMES flag");
+        }
+
+        if (!changed) { // optimization for the case where mapping = identity
+            mv.visitFrame(type, nLocal, local, nStack, stack);
+            return;
+        }
+
+        // creates a copy of newLocals
+        Object[] oldLocals = new Object[newLocals.length];
+        System.arraycopy(newLocals, 0, oldLocals, 0, oldLocals.length);
+
+        updateNewLocals(newLocals);
+
+        // copies types from 'local' to 'newLocals'
+        // 'newLocals' already contains the variables added with 'newLocal'
+
+        int index = 0; // old local variable index
+        int number = 0; // old local variable number
+        for (; number < nLocal; ++number) {
+            Object t = local[number];
+            int size = t == Opcodes.LONG || t == Opcodes.DOUBLE ? 2 : 1;
+            if (t != Opcodes.TOP) {
+                Type typ = OBJECT_TYPE;
+                if (t == Opcodes.INTEGER) {
+                    typ = Type.INT_TYPE;
+                } else if (t == Opcodes.FLOAT) {
+                    typ = Type.FLOAT_TYPE;
+                } else if (t == Opcodes.LONG) {
+                    typ = Type.LONG_TYPE;
+                } else if (t == Opcodes.DOUBLE) {
+                    typ = Type.DOUBLE_TYPE;
+                } else if (t instanceof String) {
+                    typ = Type.getObjectType((String) t);
+                }
+                setFrameLocal(remap(index, typ), t);
+            }
+            index += size;
+        }
+
+        // removes TOP after long and double types as well as trailing TOPs
+
+        index = 0;
+        number = 0;
+        for (int i = 0; index < newLocals.length; ++i) {
+            Object t = newLocals[index++];
+            if (t != null && t != Opcodes.TOP) {
+                newLocals[i] = t;
+                number = i + 1;
+                if (t == Opcodes.LONG || t == Opcodes.DOUBLE) {
+                    index += 1;
+                }
+            } else {
+                newLocals[i] = Opcodes.TOP;
+            }
+        }
+
+        // visits remapped frame
+        mv.visitFrame(type, number, newLocals, nStack, stack);
+
+        // restores original value of 'newLocals'
+        newLocals = oldLocals;
+    }
+
+    // -------------
+
+    /**
+     * Creates a new local variable of the given type.
+     * 
+     * @param type
+     *            the type of the local variable to be created.
+     * @return the identifier of the newly created local variable.
+     */
+    public int newLocal(final Type type) {
+        Object t;
+        switch (type.getSort()) {
+        case Type.BOOLEAN:
+        case Type.CHAR:
+        case Type.BYTE:
+        case Type.SHORT:
+        case Type.INT:
+            t = Opcodes.INTEGER;
+            break;
+        case Type.FLOAT:
+            t = Opcodes.FLOAT;
+            break;
+        case Type.LONG:
+            t = Opcodes.LONG;
+            break;
+        case Type.DOUBLE:
+            t = Opcodes.DOUBLE;
+            break;
+        case Type.ARRAY:
+            t = type.getDescriptor();
+            break;
+        // case Type.OBJECT:
+        default:
+            t = type.getInternalName();
+            break;
+        }
+        int local = newLocalMapping(type);
+        setLocalType(local, type);
+        setFrameLocal(local, t);
+        changed = true;
+        return local;
+    }
+
+    /**
+     * Notifies subclasses that a new stack map frame is being visited. The
+     * array argument contains the stack map frame types corresponding to the
+     * local variables added with {@link #newLocal}. This method can update
+     * these types in place for the stack map frame being visited. The default
+     * implementation of this method does nothing, i.e. a local variable added
+     * with {@link #newLocal} will have the same type in all stack map frames.
+     * But this behavior is not always the desired one, for instance if a local
+     * variable is added in the middle of a try/catch block: the frame for the
+     * exception handler should have a TOP type for this new local.
+     * 
+     * @param newLocals
+     *            the stack map frame types corresponding to the local variables
+     *            added with {@link #newLocal} (and null for the others). The
+     *            format of this array is the same as in
+     *            {@link MethodVisitor#visitFrame}, except that long and double
+     *            types use two slots. The types for the current stack map frame
+     *            must be updated in place in this array.
+     */
+    protected void updateNewLocals(Object[] newLocals) {
+    }
+
+    /**
+     * Notifies subclasses that a local variable has been added or remapped. The
+     * default implementation of this method does nothing.
+     * 
+     * @param local
+     *            a local variable identifier, as returned by {@link #newLocal
+     *            newLocal()}.
+     * @param type
+     *            the type of the value being stored in the local variable.
+     */
+    protected void setLocalType(final int local, final Type type) {
+    }
+
+    private void setFrameLocal(final int local, final Object type) {
+        int l = newLocals.length;
+        if (local >= l) {
+            Object[] a = new Object[Math.max(2 * l, local + 1)];
+            System.arraycopy(newLocals, 0, a, 0, l);
+            newLocals = a;
+        }
+        newLocals[local] = type;
+    }
+
+    private int remap(final int var, final Type type) {
+        if (var + type.getSize() <= firstLocal) {
+            return var;
+        }
+        int key = 2 * var + type.getSize() - 1;
+        int size = mapping.length;
+        if (key >= size) {
+            int[] newMapping = new int[Math.max(2 * size, key + 1)];
+            System.arraycopy(mapping, 0, newMapping, 0, size);
+            mapping = newMapping;
+        }
+        int value = mapping[key];
+        if (value == 0) {
+            value = newLocalMapping(type);
+            setLocalType(value, type);
+            mapping[key] = value + 1;
+        } else {
+            value--;
+        }
+        if (value != var) {
+            changed = true;
+        }
+        return value;
+    }
+
+    protected int newLocalMapping(final Type type) {
+        int local = nextLocal;
+        nextLocal += type.getSize();
+        return local;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java
new file mode 100644
index 0000000..73c3e96
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java
@@ -0,0 +1,282 @@
+/***
+ * 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.commons;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A named method descriptor.
+ * 
+ * @author Juozas Baliuka
+ * @author Chris Nokleberg
+ * @author Eric Bruneton
+ */
+public class Method {
+
+    /**
+     * The method name.
+     */
+    private final String name;
+
+    /**
+     * The method descriptor.
+     */
+    private final String desc;
+
+    /**
+     * Maps primitive Java type names to their descriptors.
+     */
+    private static final Map<String, String> DESCRIPTORS;
+
+    static {
+        DESCRIPTORS = new HashMap<String, String>();
+        DESCRIPTORS.put("void", "V");
+        DESCRIPTORS.put("byte", "B");
+        DESCRIPTORS.put("char", "C");
+        DESCRIPTORS.put("double", "D");
+        DESCRIPTORS.put("float", "F");
+        DESCRIPTORS.put("int", "I");
+        DESCRIPTORS.put("long", "J");
+        DESCRIPTORS.put("short", "S");
+        DESCRIPTORS.put("boolean", "Z");
+    }
+
+    /**
+     * Creates a new {@link Method}.
+     * 
+     * @param name
+     *            the method's name.
+     * @param desc
+     *            the method's descriptor.
+     */
+    public Method(final String name, final String desc) {
+        this.name = name;
+        this.desc = desc;
+    }
+
+    /**
+     * Creates a new {@link Method}.
+     * 
+     * @param name
+     *            the method's name.
+     * @param returnType
+     *            the method's return type.
+     * @param argumentTypes
+     *            the method's argument types.
+     */
+    public Method(final String name, final Type returnType,
+            final Type[] argumentTypes) {
+        this(name, Type.getMethodDescriptor(returnType, argumentTypes));
+    }
+
+    /**
+     * Creates a new {@link Method}.
+     * 
+     * @param m
+     *            a java.lang.reflect method descriptor
+     * @return a {@link Method} corresponding to the given Java method
+     *         declaration.
+     */
+    public static Method getMethod(java.lang.reflect.Method m) {
+        return new Method(m.getName(), Type.getMethodDescriptor(m));
+    }
+
+    /**
+     * Creates a new {@link Method}.
+     * 
+     * @param c
+     *            a java.lang.reflect constructor descriptor
+     * @return a {@link Method} corresponding to the given Java constructor
+     *         declaration.
+     */
+    public static Method getMethod(java.lang.reflect.Constructor<?> c) {
+        return new Method("<init>", Type.getConstructorDescriptor(c));
+    }
+
+    /**
+     * Returns a {@link Method} corresponding to the given Java method
+     * declaration.
+     * 
+     * @param method
+     *            a Java method declaration, without argument names, of the form
+     *            "returnType name (argumentType1, ... argumentTypeN)", where
+     *            the types are in plain Java (e.g. "int", "float",
+     *            "java.util.List", ...). Classes of the java.lang package can
+     *            be specified by their unqualified name; all other classes
+     *            names must be fully qualified.
+     * @return a {@link Method} corresponding to the given Java method
+     *         declaration.
+     * @throws IllegalArgumentException
+     *             if <code>method</code> could not get parsed.
+     */
+    public static Method getMethod(final String method)
+            throws IllegalArgumentException {
+        return getMethod(method, false);
+    }
+
+    /**
+     * Returns a {@link Method} corresponding to the given Java method
+     * declaration.
+     * 
+     * @param method
+     *            a Java method declaration, without argument names, of the form
+     *            "returnType name (argumentType1, ... argumentTypeN)", where
+     *            the types are in plain Java (e.g. "int", "float",
+     *            "java.util.List", ...). Classes of the java.lang package may
+     *            be specified by their unqualified name, depending on the
+     *            defaultPackage argument; all other classes names must be fully
+     *            qualified.
+     * @param defaultPackage
+     *            true if unqualified class names belong to the default package,
+     *            or false if they correspond to java.lang classes. For instance
+     *            "Object" means "Object" if this option is true, or
+     *            "java.lang.Object" otherwise.
+     * @return a {@link Method} corresponding to the given Java method
+     *         declaration.
+     * @throws IllegalArgumentException
+     *             if <code>method</code> could not get parsed.
+     */
+    public static Method getMethod(final String method,
+            final boolean defaultPackage) throws IllegalArgumentException {
+        int space = method.indexOf(' ');
+        int start = method.indexOf('(', space) + 1;
+        int end = method.indexOf(')', start);
+        if (space == -1 || start == -1 || end == -1) {
+            throw new IllegalArgumentException();
+        }
+        String returnType = method.substring(0, space);
+        String methodName = method.substring(space + 1, start - 1).trim();
+        StringBuffer sb = new StringBuffer();
+        sb.append('(');
+        int p;
+        do {
+            String s;
+            p = method.indexOf(',', start);
+            if (p == -1) {
+                s = map(method.substring(start, end).trim(), defaultPackage);
+            } else {
+                s = map(method.substring(start, p).trim(), defaultPackage);
+                start = p + 1;
+            }
+            sb.append(s);
+        } while (p != -1);
+        sb.append(')');
+        sb.append(map(returnType, defaultPackage));
+        return new Method(methodName, sb.toString());
+    }
+
+    private static String map(final String type, final boolean defaultPackage) {
+        if ("".equals(type)) {
+            return type;
+        }
+
+        StringBuffer sb = new StringBuffer();
+        int index = 0;
+        while ((index = type.indexOf("[]", index) + 1) > 0) {
+            sb.append('[');
+        }
+
+        String t = type.substring(0, type.length() - sb.length() * 2);
+        String desc = DESCRIPTORS.get(t);
+        if (desc != null) {
+            sb.append(desc);
+        } else {
+            sb.append('L');
+            if (t.indexOf('.') < 0) {
+                if (!defaultPackage) {
+                    sb.append("java/lang/");
+                }
+                sb.append(t);
+            } else {
+                sb.append(t.replace('.', '/'));
+            }
+            sb.append(';');
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Returns the name of the method described by this object.
+     * 
+     * @return the name of the method described by this object.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns the descriptor of the method described by this object.
+     * 
+     * @return the descriptor of the method described by this object.
+     */
+    public String getDescriptor() {
+        return desc;
+    }
+
+    /**
+     * Returns the return type of the method described by this object.
+     * 
+     * @return the return type of the method described by this object.
+     */
+    public Type getReturnType() {
+        return Type.getReturnType(desc);
+    }
+
+    /**
+     * Returns the argument types of the method described by this object.
+     * 
+     * @return the argument types of the method described by this object.
+     */
+    public Type[] getArgumentTypes() {
+        return Type.getArgumentTypes(desc);
+    }
+
+    @Override
+    public String toString() {
+        return name + desc;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (!(o instanceof Method)) {
+            return false;
+        }
+        Method other = (Method) o;
+        return name.equals(other.name) && desc.equals(other.desc);
+    }
+
+    @Override
+    public int hashCode() {
+        return name.hashCode() ^ desc.hashCode();
+    }
+}
\ No newline at end of file


[03/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java
index 0d7fe3f..859a8d1 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.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,12 +29,18 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.util;
 
-import org.apache.tapestry5.internal.plastic.asm.*;
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+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.TypePath;
 
 /**
  * A {@link MethodVisitor} that prints the methods it visits with a
  * {@link Printer}.
- *
+ * 
  * @author Eric Bruneton
  */
 public final class TraceMethodVisitor extends MethodVisitor {
@@ -47,15 +52,19 @@ public final class TraceMethodVisitor extends MethodVisitor {
     }
 
     public TraceMethodVisitor(final MethodVisitor mv, final Printer p) {
-        super(Opcodes.ASM4, mv);
+        super(Opcodes.ASM5, mv);
         this.p = p;
     }
 
     @Override
-    public AnnotationVisitor visitAnnotation(
-        final String desc,
-        final boolean visible)
-    {
+    public void visitParameter(String name, int access) {
+        p.visitParameter(name, access);
+        super.visitParameter(name, access);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
         Printer p = this.p.visitMethodAnnotation(desc, visible);
         AnnotationVisitor av = mv == null ? null : mv.visitAnnotation(desc,
                 visible);
@@ -63,6 +72,16 @@ public final class TraceMethodVisitor extends MethodVisitor {
     }
 
     @Override
+    public AnnotationVisitor visitTypeAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        Printer p = this.p.visitMethodTypeAnnotation(typeRef, typePath, desc,
+                visible);
+        AnnotationVisitor av = mv == null ? null : mv.visitTypeAnnotation(
+                typeRef, typePath, desc, visible);
+        return new TraceAnnotationVisitor(av, p);
+    }
+
+    @Override
     public void visitAttribute(final Attribute attr) {
         p.visitMethodAttribute(attr);
         super.visitAttribute(attr);
@@ -76,17 +95,11 @@ public final class TraceMethodVisitor extends MethodVisitor {
     }
 
     @Override
-    public AnnotationVisitor visitParameterAnnotation(
-        final int parameter,
-        final String desc,
-        final boolean visible)
-    {
-        Printer p = this.p.visitParameterAnnotation(parameter,
-                desc,
-                visible);
-        AnnotationVisitor av = mv == null
-                ? null
-                : mv.visitParameterAnnotation(parameter, desc, visible);
+    public AnnotationVisitor visitParameterAnnotation(final int parameter,
+            final String desc, final boolean visible) {
+        Printer p = this.p.visitParameterAnnotation(parameter, desc, visible);
+        AnnotationVisitor av = mv == null ? null : mv.visitParameterAnnotation(
+                parameter, desc, visible);
         return new TraceAnnotationVisitor(av, p);
     }
 
@@ -97,13 +110,8 @@ public final class TraceMethodVisitor extends MethodVisitor {
     }
 
     @Override
-    public void visitFrame(
-        final int type,
-        final int nLocal,
-        final Object[] local,
-        final int nStack,
-        final Object[] stack)
-    {
+    public void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack) {
         p.visitFrame(type, nLocal, local, nStack, stack);
         super.visitFrame(type, nLocal, local, nStack, stack);
     }
@@ -133,34 +141,42 @@ public final class TraceMethodVisitor 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) {
         p.visitFieldInsn(opcode, owner, name, desc);
         super.visitFieldInsn(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;
+        }
         p.visitMethodInsn(opcode, owner, name, desc);
-        super.visitMethodInsn(opcode, owner, name, desc);
+        if (mv != null) {
+            mv.visitMethodInsn(opcode, owner, name, desc);
+        }
+    }
+
+    @Override
+    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;
+        }
+        p.visitMethodInsn(opcode, owner, name, desc, itf);
+        if (mv != null) {
+            mv.visitMethodInsn(opcode, owner, name, desc, itf);
+        }
     }
 
     @Override
-    public void visitInvokeDynamicInsn(
-        String name,
-        String desc,
-        Handle bsm,
-        Object... bsmArgs)
-    {
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
         p.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
         super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
     }
@@ -190,22 +206,15 @@ public final class TraceMethodVisitor extends MethodVisitor {
     }
 
     @Override
-    public void visitTableSwitchInsn(
-        final int min,
-        final int max,
-        final Label dflt,
-        final Label... labels)
-    {
+    public void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels) {
         p.visitTableSwitchInsn(min, max, dflt, labels);
         super.visitTableSwitchInsn(min, max, dflt, labels);
     }
 
     @Override
-    public void visitLookupSwitchInsn(
-        final Label dflt,
-        final int[] keys,
-        final Label[] labels)
-    {
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
         p.visitLookupSwitchInsn(dflt, keys, labels);
         super.visitLookupSwitchInsn(dflt, keys, labels);
     }
@@ -217,30 +226,53 @@ public final class TraceMethodVisitor 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) {
+        Printer p = this.p
+                .visitInsnAnnotation(typeRef, typePath, desc, visible);
+        AnnotationVisitor av = mv == null ? null : mv.visitInsnAnnotation(
+                typeRef, typePath, desc, visible);
+        return new TraceAnnotationVisitor(av, p);
+    }
+
+    @Override
+    public void visitTryCatchBlock(final Label start, final Label end,
+            final Label handler, final String type) {
         p.visitTryCatchBlock(start, end, handler, type);
         super.visitTryCatchBlock(start, end, handler, type);
     }
 
     @Override
-    public void visitLocalVariable(
-        final String name,
-        final String desc,
-        final String signature,
-        final Label start,
-        final Label end,
-        final int index)
-    {
+    public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+            TypePath typePath, String desc, boolean visible) {
+        Printer p = this.p.visitTryCatchAnnotation(typeRef, typePath, desc,
+                visible);
+        AnnotationVisitor av = mv == null ? null : mv.visitTryCatchAnnotation(
+                typeRef, typePath, desc, visible);
+        return new TraceAnnotationVisitor(av, p);
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
         p.visitLocalVariable(name, desc, signature, start, end, index);
         super.visitLocalVariable(name, desc, signature, start, end, index);
     }
 
     @Override
+    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+            TypePath typePath, Label[] start, Label[] end, int[] index,
+            String desc, boolean visible) {
+        Printer p = this.p.visitLocalVariableAnnotation(typeRef, typePath,
+                start, end, index, desc, visible);
+        AnnotationVisitor av = mv == null ? null : mv
+                .visitLocalVariableAnnotation(typeRef, typePath, start, end,
+                        index, desc, visible);
+        return new TraceAnnotationVisitor(av, p);
+    }
+
+    @Override
     public void visitLineNumber(final int line, final Label start) {
         p.visitLineNumber(line, start);
         super.visitLineNumber(line, start);

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
index 3b0a178..1e2c9a3 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
@@ -33,14 +33,13 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
 import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
 
 /**
- * A {@link org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor} that prints a disassembled view of the signature
+ * A {@link SignatureVisitor} that prints a disassembled view of the signature
  * it visits.
- *
+ * 
  * @author Eugene Kuleshov
  * @author Eric Bruneton
  */
-public final class TraceSignatureVisitor extends SignatureVisitor
-{
+public final class TraceSignatureVisitor extends SignatureVisitor {
 
     private final StringBuffer declaration;
 
@@ -76,13 +75,13 @@ public final class TraceSignatureVisitor extends SignatureVisitor
     private String separator = "";
 
     public TraceSignatureVisitor(final int access) {
-        super(Opcodes.ASM4);
+        super(Opcodes.ASM5);
         isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
         this.declaration = new StringBuffer();
     }
 
     private TraceSignatureVisitor(final StringBuffer buf) {
-        super(Opcodes.ASM4);
+        super(Opcodes.ASM5);
         this.declaration = buf;
     }
 
@@ -118,8 +117,7 @@ public final class TraceSignatureVisitor extends SignatureVisitor
 
     @Override
     public SignatureVisitor visitInterface() {
-        separator = seenInterface ? ", " : isInterface
-                ? " extends "
+        separator = seenInterface ? ", " : isInterface ? " extends "
                 : " implements ";
         seenInterface = true;
         startType();
@@ -166,34 +164,34 @@ public final class TraceSignatureVisitor extends SignatureVisitor
     @Override
     public void visitBaseType(final char descriptor) {
         switch (descriptor) {
-            case 'V':
-                declaration.append("void");
-                break;
-            case 'B':
-                declaration.append("byte");
-                break;
-            case 'J':
-                declaration.append("long");
-                break;
-            case 'Z':
-                declaration.append("boolean");
-                break;
-            case 'I':
-                declaration.append("int");
-                break;
-            case 'S':
-                declaration.append("short");
-                break;
-            case 'C':
-                declaration.append("char");
-                break;
-            case 'F':
-                declaration.append("float");
-                break;
-            // case 'D':
-            default:
-                declaration.append("double");
-                break;
+        case 'V':
+            declaration.append("void");
+            break;
+        case 'B':
+            declaration.append("byte");
+            break;
+        case 'J':
+            declaration.append("long");
+            break;
+        case 'Z':
+            declaration.append("boolean");
+            break;
+        case 'I':
+            declaration.append("int");
+            break;
+        case 'S':
+            declaration.append("short");
+            break;
+        case 'C':
+            declaration.append("char");
+            break;
+        case 'F':
+            declaration.append("float");
+            break;
+        // case 'D':
+        default:
+            declaration.append("double");
+            break;
         }
         endType();
     }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java
new file mode 100644
index 0000000..88dab5e
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java
@@ -0,0 +1,1453 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * 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.xml;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+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;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * A {@link org.xml.sax.ContentHandler ContentHandler} that transforms XML
+ * document into Java class file. This class can be feeded by any kind of SAX
+ * 2.0 event producers, e.g. XML parser, XSLT or XPath engines, or custom code.
+ * 
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.SAXClassAdapter
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.Processor
+ * 
+ * @author Eugene Kuleshov
+ */
+public class ASMContentHandler extends DefaultHandler implements Opcodes {
+
+    /**
+     * Stack of the intermediate processing contexts.
+     */
+    private final ArrayList<Object> stack = new ArrayList<Object>();
+
+    /**
+     * Complete name of the current element.
+     */
+    String match = "";
+
+    /**
+     * Current instance of the {@link ClassVisitor ClassVisitor} used to visit
+     * classfile bytecode.
+     */
+    protected ClassVisitor cv;
+
+    /**
+     * Map of the active {@link Label Label} instances for current method.
+     */
+    protected Map<Object, Label> labels;
+
+    private static final String BASE = "class";
+
+    private final RuleSet RULES = new RuleSet();
+    {
+        RULES.add(BASE, new ClassRule());
+        RULES.add(BASE + "/interfaces/interface", new InterfaceRule());
+        RULES.add(BASE + "/interfaces", new InterfacesRule());
+        RULES.add(BASE + "/outerclass", new OuterClassRule());
+        RULES.add(BASE + "/innerclass", new InnerClassRule());
+        RULES.add(BASE + "/source", new SourceRule());
+        RULES.add(BASE + "/field", new FieldRule());
+
+        RULES.add(BASE + "/method", new MethodRule());
+        RULES.add(BASE + "/method/exceptions/exception", new ExceptionRule());
+        RULES.add(BASE + "/method/exceptions", new ExceptionsRule());
+
+        RULES.add(BASE + "/method/parameter", new MethodParameterRule());
+        RULES.add(BASE + "/method/annotationDefault",
+                new AnnotationDefaultRule());
+
+        RULES.add(BASE + "/method/code/*", new OpcodesRule()); // opcodes
+
+        RULES.add(BASE + "/method/code/frame", new FrameRule());
+        RULES.add(BASE + "/method/code/frame/local", new FrameTypeRule());
+        RULES.add(BASE + "/method/code/frame/stack", new FrameTypeRule());
+
+        RULES.add(BASE + "/method/code/TABLESWITCH", new TableSwitchRule());
+        RULES.add(BASE + "/method/code/TABLESWITCH/label",
+                new TableSwitchLabelRule());
+        RULES.add(BASE + "/method/code/LOOKUPSWITCH", new LookupSwitchRule());
+        RULES.add(BASE + "/method/code/LOOKUPSWITCH/label",
+                new LookupSwitchLabelRule());
+
+        RULES.add(BASE + "/method/code/INVOKEDYNAMIC", new InvokeDynamicRule());
+        RULES.add(BASE + "/method/code/INVOKEDYNAMIC/bsmArg",
+                new InvokeDynamicBsmArgumentsRule());
+
+        RULES.add(BASE + "/method/code/Label", new LabelRule());
+        RULES.add(BASE + "/method/code/TryCatch", new TryCatchRule());
+        RULES.add(BASE + "/method/code/LineNumber", new LineNumberRule());
+        RULES.add(BASE + "/method/code/LocalVar", new LocalVarRule());
+        RULES.add(BASE + "/method/code/Max", new MaxRule());
+
+        RULES.add("*/annotation", new AnnotationRule());
+        RULES.add("*/typeAnnotation", new TypeAnnotationRule());
+        RULES.add("*/parameterAnnotation", new AnnotationParameterRule());
+        RULES.add("*/insnAnnotation", new InsnAnnotationRule());
+        RULES.add("*/tryCatchAnnotation", new TryCatchAnnotationRule());
+        RULES.add("*/localVariableAnnotation",
+                new LocalVariableAnnotationRule());
+        RULES.add("*/annotationValue", new AnnotationValueRule());
+        RULES.add("*/annotationValueAnnotation",
+                new AnnotationValueAnnotationRule());
+        RULES.add("*/annotationValueEnum", new AnnotationValueEnumRule());
+        RULES.add("*/annotationValueArray", new AnnotationValueArrayRule());
+    }
+
+    private static interface OpcodeGroup {
+        public static final int INSN = 0;
+        public static final int INSN_INT = 1;
+        public static final int INSN_VAR = 2;
+        public static final int INSN_TYPE = 3;
+        public static final int INSN_FIELD = 4;
+        public static final int INSN_METHOD = 5;
+        public static final int INSN_JUMP = 6;
+        public static final int INSN_LDC = 7;
+        public static final int INSN_IINC = 8;
+        public static final int INSN_MULTIANEWARRAY = 9;
+    }
+
+    /**
+     * Map of the opcode names to opcode and opcode group
+     */
+    static final HashMap<String, Opcode> OPCODES = new HashMap<String, Opcode>();
+    static {
+        addOpcode("NOP", NOP, OpcodeGroup.INSN);
+        addOpcode("ACONST_NULL", ACONST_NULL, OpcodeGroup.INSN);
+        addOpcode("ICONST_M1", ICONST_M1, OpcodeGroup.INSN);
+        addOpcode("ICONST_0", ICONST_0, OpcodeGroup.INSN);
+        addOpcode("ICONST_1", ICONST_1, OpcodeGroup.INSN);
+        addOpcode("ICONST_2", ICONST_2, OpcodeGroup.INSN);
+        addOpcode("ICONST_3", ICONST_3, OpcodeGroup.INSN);
+        addOpcode("ICONST_4", ICONST_4, OpcodeGroup.INSN);
+        addOpcode("ICONST_5", ICONST_5, OpcodeGroup.INSN);
+        addOpcode("LCONST_0", LCONST_0, OpcodeGroup.INSN);
+        addOpcode("LCONST_1", LCONST_1, OpcodeGroup.INSN);
+        addOpcode("FCONST_0", FCONST_0, OpcodeGroup.INSN);
+        addOpcode("FCONST_1", FCONST_1, OpcodeGroup.INSN);
+        addOpcode("FCONST_2", FCONST_2, OpcodeGroup.INSN);
+        addOpcode("DCONST_0", DCONST_0, OpcodeGroup.INSN);
+        addOpcode("DCONST_1", DCONST_1, OpcodeGroup.INSN);
+        addOpcode("BIPUSH", BIPUSH, OpcodeGroup.INSN_INT);
+        addOpcode("SIPUSH", SIPUSH, OpcodeGroup.INSN_INT);
+        addOpcode("LDC", LDC, OpcodeGroup.INSN_LDC);
+        addOpcode("ILOAD", ILOAD, OpcodeGroup.INSN_VAR);
+        addOpcode("LLOAD", LLOAD, OpcodeGroup.INSN_VAR);
+        addOpcode("FLOAD", FLOAD, OpcodeGroup.INSN_VAR);
+        addOpcode("DLOAD", DLOAD, OpcodeGroup.INSN_VAR);
+        addOpcode("ALOAD", ALOAD, OpcodeGroup.INSN_VAR);
+        addOpcode("IALOAD", IALOAD, OpcodeGroup.INSN);
+        addOpcode("LALOAD", LALOAD, OpcodeGroup.INSN);
+        addOpcode("FALOAD", FALOAD, OpcodeGroup.INSN);
+        addOpcode("DALOAD", DALOAD, OpcodeGroup.INSN);
+        addOpcode("AALOAD", AALOAD, OpcodeGroup.INSN);
+        addOpcode("BALOAD", BALOAD, OpcodeGroup.INSN);
+        addOpcode("CALOAD", CALOAD, OpcodeGroup.INSN);
+        addOpcode("SALOAD", SALOAD, OpcodeGroup.INSN);
+        addOpcode("ISTORE", ISTORE, OpcodeGroup.INSN_VAR);
+        addOpcode("LSTORE", LSTORE, OpcodeGroup.INSN_VAR);
+        addOpcode("FSTORE", FSTORE, OpcodeGroup.INSN_VAR);
+        addOpcode("DSTORE", DSTORE, OpcodeGroup.INSN_VAR);
+        addOpcode("ASTORE", ASTORE, OpcodeGroup.INSN_VAR);
+        addOpcode("IASTORE", IASTORE, OpcodeGroup.INSN);
+        addOpcode("LASTORE", LASTORE, OpcodeGroup.INSN);
+        addOpcode("FASTORE", FASTORE, OpcodeGroup.INSN);
+        addOpcode("DASTORE", DASTORE, OpcodeGroup.INSN);
+        addOpcode("AASTORE", AASTORE, OpcodeGroup.INSN);
+        addOpcode("BASTORE", BASTORE, OpcodeGroup.INSN);
+        addOpcode("CASTORE", CASTORE, OpcodeGroup.INSN);
+        addOpcode("SASTORE", SASTORE, OpcodeGroup.INSN);
+        addOpcode("POP", POP, OpcodeGroup.INSN);
+        addOpcode("POP2", POP2, OpcodeGroup.INSN);
+        addOpcode("DUP", DUP, OpcodeGroup.INSN);
+        addOpcode("DUP_X1", DUP_X1, OpcodeGroup.INSN);
+        addOpcode("DUP_X2", DUP_X2, OpcodeGroup.INSN);
+        addOpcode("DUP2", DUP2, OpcodeGroup.INSN);
+        addOpcode("DUP2_X1", DUP2_X1, OpcodeGroup.INSN);
+        addOpcode("DUP2_X2", DUP2_X2, OpcodeGroup.INSN);
+        addOpcode("SWAP", SWAP, OpcodeGroup.INSN);
+        addOpcode("IADD", IADD, OpcodeGroup.INSN);
+        addOpcode("LADD", LADD, OpcodeGroup.INSN);
+        addOpcode("FADD", FADD, OpcodeGroup.INSN);
+        addOpcode("DADD", DADD, OpcodeGroup.INSN);
+        addOpcode("ISUB", ISUB, OpcodeGroup.INSN);
+        addOpcode("LSUB", LSUB, OpcodeGroup.INSN);
+        addOpcode("FSUB", FSUB, OpcodeGroup.INSN);
+        addOpcode("DSUB", DSUB, OpcodeGroup.INSN);
+        addOpcode("IMUL", IMUL, OpcodeGroup.INSN);
+        addOpcode("LMUL", LMUL, OpcodeGroup.INSN);
+        addOpcode("FMUL", FMUL, OpcodeGroup.INSN);
+        addOpcode("DMUL", DMUL, OpcodeGroup.INSN);
+        addOpcode("IDIV", IDIV, OpcodeGroup.INSN);
+        addOpcode("LDIV", LDIV, OpcodeGroup.INSN);
+        addOpcode("FDIV", FDIV, OpcodeGroup.INSN);
+        addOpcode("DDIV", DDIV, OpcodeGroup.INSN);
+        addOpcode("IREM", IREM, OpcodeGroup.INSN);
+        addOpcode("LREM", LREM, OpcodeGroup.INSN);
+        addOpcode("FREM", FREM, OpcodeGroup.INSN);
+        addOpcode("DREM", DREM, OpcodeGroup.INSN);
+        addOpcode("INEG", INEG, OpcodeGroup.INSN);
+        addOpcode("LNEG", LNEG, OpcodeGroup.INSN);
+        addOpcode("FNEG", FNEG, OpcodeGroup.INSN);
+        addOpcode("DNEG", DNEG, OpcodeGroup.INSN);
+        addOpcode("ISHL", ISHL, OpcodeGroup.INSN);
+        addOpcode("LSHL", LSHL, OpcodeGroup.INSN);
+        addOpcode("ISHR", ISHR, OpcodeGroup.INSN);
+        addOpcode("LSHR", LSHR, OpcodeGroup.INSN);
+        addOpcode("IUSHR", IUSHR, OpcodeGroup.INSN);
+        addOpcode("LUSHR", LUSHR, OpcodeGroup.INSN);
+        addOpcode("IAND", IAND, OpcodeGroup.INSN);
+        addOpcode("LAND", LAND, OpcodeGroup.INSN);
+        addOpcode("IOR", IOR, OpcodeGroup.INSN);
+        addOpcode("LOR", LOR, OpcodeGroup.INSN);
+        addOpcode("IXOR", IXOR, OpcodeGroup.INSN);
+        addOpcode("LXOR", LXOR, OpcodeGroup.INSN);
+        addOpcode("IINC", IINC, OpcodeGroup.INSN_IINC);
+        addOpcode("I2L", I2L, OpcodeGroup.INSN);
+        addOpcode("I2F", I2F, OpcodeGroup.INSN);
+        addOpcode("I2D", I2D, OpcodeGroup.INSN);
+        addOpcode("L2I", L2I, OpcodeGroup.INSN);
+        addOpcode("L2F", L2F, OpcodeGroup.INSN);
+        addOpcode("L2D", L2D, OpcodeGroup.INSN);
+        addOpcode("F2I", F2I, OpcodeGroup.INSN);
+        addOpcode("F2L", F2L, OpcodeGroup.INSN);
+        addOpcode("F2D", F2D, OpcodeGroup.INSN);
+        addOpcode("D2I", D2I, OpcodeGroup.INSN);
+        addOpcode("D2L", D2L, OpcodeGroup.INSN);
+        addOpcode("D2F", D2F, OpcodeGroup.INSN);
+        addOpcode("I2B", I2B, OpcodeGroup.INSN);
+        addOpcode("I2C", I2C, OpcodeGroup.INSN);
+        addOpcode("I2S", I2S, OpcodeGroup.INSN);
+        addOpcode("LCMP", LCMP, OpcodeGroup.INSN);
+        addOpcode("FCMPL", FCMPL, OpcodeGroup.INSN);
+        addOpcode("FCMPG", FCMPG, OpcodeGroup.INSN);
+        addOpcode("DCMPL", DCMPL, OpcodeGroup.INSN);
+        addOpcode("DCMPG", DCMPG, OpcodeGroup.INSN);
+        addOpcode("IFEQ", IFEQ, OpcodeGroup.INSN_JUMP);
+        addOpcode("IFNE", IFNE, OpcodeGroup.INSN_JUMP);
+        addOpcode("IFLT", IFLT, OpcodeGroup.INSN_JUMP);
+        addOpcode("IFGE", IFGE, OpcodeGroup.INSN_JUMP);
+        addOpcode("IFGT", IFGT, OpcodeGroup.INSN_JUMP);
+        addOpcode("IFLE", IFLE, OpcodeGroup.INSN_JUMP);
+        addOpcode("IF_ICMPEQ", IF_ICMPEQ, OpcodeGroup.INSN_JUMP);
+        addOpcode("IF_ICMPNE", IF_ICMPNE, OpcodeGroup.INSN_JUMP);
+        addOpcode("IF_ICMPLT", IF_ICMPLT, OpcodeGroup.INSN_JUMP);
+        addOpcode("IF_ICMPGE", IF_ICMPGE, OpcodeGroup.INSN_JUMP);
+        addOpcode("IF_ICMPGT", IF_ICMPGT, OpcodeGroup.INSN_JUMP);
+        addOpcode("IF_ICMPLE", IF_ICMPLE, OpcodeGroup.INSN_JUMP);
+        addOpcode("IF_ACMPEQ", IF_ACMPEQ, OpcodeGroup.INSN_JUMP);
+        addOpcode("IF_ACMPNE", IF_ACMPNE, OpcodeGroup.INSN_JUMP);
+        addOpcode("GOTO", GOTO, OpcodeGroup.INSN_JUMP);
+        addOpcode("JSR", JSR, OpcodeGroup.INSN_JUMP);
+        addOpcode("RET", RET, OpcodeGroup.INSN_VAR);
+        addOpcode("IRETURN", IRETURN, OpcodeGroup.INSN);
+        addOpcode("LRETURN", LRETURN, OpcodeGroup.INSN);
+        addOpcode("FRETURN", FRETURN, OpcodeGroup.INSN);
+        addOpcode("DRETURN", DRETURN, OpcodeGroup.INSN);
+        addOpcode("ARETURN", ARETURN, OpcodeGroup.INSN);
+        addOpcode("RETURN", RETURN, OpcodeGroup.INSN);
+        addOpcode("GETSTATIC", GETSTATIC, OpcodeGroup.INSN_FIELD);
+        addOpcode("PUTSTATIC", PUTSTATIC, OpcodeGroup.INSN_FIELD);
+        addOpcode("GETFIELD", GETFIELD, OpcodeGroup.INSN_FIELD);
+        addOpcode("PUTFIELD", PUTFIELD, OpcodeGroup.INSN_FIELD);
+        addOpcode("INVOKEVIRTUAL", INVOKEVIRTUAL, OpcodeGroup.INSN_METHOD);
+        addOpcode("INVOKESPECIAL", INVOKESPECIAL, OpcodeGroup.INSN_METHOD);
+        addOpcode("INVOKESTATIC", INVOKESTATIC, OpcodeGroup.INSN_METHOD);
+        addOpcode("INVOKEINTERFACE", INVOKEINTERFACE, OpcodeGroup.INSN_METHOD);
+        addOpcode("NEW", NEW, OpcodeGroup.INSN_TYPE);
+        addOpcode("NEWARRAY", NEWARRAY, OpcodeGroup.INSN_INT);
+        addOpcode("ANEWARRAY", ANEWARRAY, OpcodeGroup.INSN_TYPE);
+        addOpcode("ARRAYLENGTH", ARRAYLENGTH, OpcodeGroup.INSN);
+        addOpcode("ATHROW", ATHROW, OpcodeGroup.INSN);
+        addOpcode("CHECKCAST", CHECKCAST, OpcodeGroup.INSN_TYPE);
+        addOpcode("INSTANCEOF", INSTANCEOF, OpcodeGroup.INSN_TYPE);
+        addOpcode("MONITORENTER", MONITORENTER, OpcodeGroup.INSN);
+        addOpcode("MONITOREXIT", MONITOREXIT, OpcodeGroup.INSN);
+        addOpcode("MULTIANEWARRAY", MULTIANEWARRAY,
+                OpcodeGroup.INSN_MULTIANEWARRAY);
+        addOpcode("IFNULL", IFNULL, OpcodeGroup.INSN_JUMP);
+        addOpcode("IFNONNULL", IFNONNULL, OpcodeGroup.INSN_JUMP);
+    }
+
+    private static void addOpcode(String operStr, int oper, int group) {
+        OPCODES.put(operStr, new Opcode(oper, group));
+    }
+
+    static final HashMap<String, Integer> TYPES = new HashMap<String, Integer>();
+    static {
+        String[] types = SAXCodeAdapter.TYPES;
+        for (int i = 0; i < types.length; i++) {
+            TYPES.put(types[i], new Integer(i));
+        }
+    }
+
+    /**
+     * Constructs a new {@link ASMContentHandler ASMContentHandler} object.
+     * 
+     * @param cv
+     *            class visitor that will be called to reconstruct the classfile
+     *            using the XML stream.
+     */
+    public ASMContentHandler(final ClassVisitor cv) {
+        this.cv = cv;
+    }
+
+    /**
+     * Process notification of the start of an XML element being reached.
+     * 
+     * @param ns
+     *            - The Namespace URI, or the empty string if the element has no
+     *            Namespace URI or if Namespace processing is not being
+     *            performed.
+     * @param lName
+     *            - The local name (without prefix), or the empty string if
+     *            Namespace processing is not being performed.
+     * @param qName
+     *            - The qualified name (with prefix), or the empty string if
+     *            qualified names are not available.
+     * @param list
+     *            - The attributes attached to the element. If there are no
+     *            attributes, it shall be an empty Attributes object.
+     * @exception SAXException
+     *                if a parsing error is to be reported
+     */
+    @Override
+    public final void startElement(final String ns, final String lName,
+            final String qName, final Attributes list) throws SAXException {
+        // the actual element name is either in lName or qName, depending
+        // on whether the parser is namespace aware
+        String name = lName == null || lName.length() == 0 ? qName : lName;
+
+        // Compute the current matching rule
+        StringBuffer sb = new StringBuffer(match);
+        if (match.length() > 0) {
+            sb.append('/');
+        }
+        sb.append(name);
+        match = sb.toString();
+
+        // Fire "begin" events for all relevant rules
+        Rule r = (Rule) RULES.match(match);
+        if (r != null) {
+            r.begin(name, list);
+        }
+    }
+
+    /**
+     * Process notification of the end of an XML element being reached.
+     * 
+     * @param ns
+     *            - The Namespace URI, or the empty string if the element has no
+     *            Namespace URI or if Namespace processing is not being
+     *            performed.
+     * @param lName
+     *            - The local name (without prefix), or the empty string if
+     *            Namespace processing is not being performed.
+     * @param qName
+     *            - The qualified XML 1.0 name (with prefix), or the empty
+     *            string if qualified names are not available.
+     * 
+     * @exception SAXException
+     *                if a parsing error is to be reported
+     */
+    @Override
+    public final void endElement(final String ns, final String lName,
+            final String qName) throws SAXException {
+        // the actual element name is either in lName or qName, depending
+        // on whether the parser is namespace aware
+        String name = lName == null || lName.length() == 0 ? qName : lName;
+
+        // Fire "end" events for all relevant rules in reverse order
+        Rule r = (Rule) RULES.match(match);
+        if (r != null) {
+            r.end(name);
+        }
+
+        // Recover the previous match expression
+        int slash = match.lastIndexOf('/');
+        if (slash >= 0) {
+            match = match.substring(0, slash);
+        } else {
+            match = "";
+        }
+    }
+
+    /**
+     * Return the top object on the stack without removing it. If there are no
+     * objects on the stack, return <code>null</code>.
+     * 
+     * @return the top object on the stack without removing it.
+     */
+    final Object peek() {
+        int size = stack.size();
+        return size == 0 ? null : stack.get(size - 1);
+    }
+
+    /**
+     * Pop the top object off of the stack, and return it. If there are no
+     * objects on the stack, return <code>null</code>.
+     * 
+     * @return the top object off of the stack.
+     */
+    final Object pop() {
+        int size = stack.size();
+        return size == 0 ? null : stack.remove(size - 1);
+    }
+
+    /**
+     * Push a new object onto the top of the object stack.
+     * 
+     * @param object
+     *            The new object
+     */
+    final void push(final Object object) {
+        stack.add(object);
+    }
+
+    static final class RuleSet {
+
+        private final HashMap<String, Object> rules = new HashMap<String, Object>();
+
+        private final ArrayList<String> lpatterns = new ArrayList<String>();
+
+        private final ArrayList<String> rpatterns = new ArrayList<String>();
+
+        public void add(final String path, final Object rule) {
+            String pattern = path;
+            if (path.startsWith("*/")) {
+                pattern = path.substring(1);
+                lpatterns.add(pattern);
+            } else if (path.endsWith("/*")) {
+                pattern = path.substring(0, path.length() - 1);
+                rpatterns.add(pattern);
+            }
+            rules.put(pattern, rule);
+        }
+
+        public Object match(final String path) {
+            if (rules.containsKey(path)) {
+                return rules.get(path);
+            }
+
+            int n = path.lastIndexOf('/');
+            for (Iterator<String> it = lpatterns.iterator(); it.hasNext();) {
+                String pattern = it.next();
+                if (path.substring(n).endsWith(pattern)) {
+                    return rules.get(pattern);
+                }
+            }
+
+            for (Iterator<String> it = rpatterns.iterator(); it.hasNext();) {
+                String pattern = it.next();
+                if (path.startsWith(pattern)) {
+                    return rules.get(pattern);
+                }
+            }
+
+            return null;
+        }
+    }
+
+    /**
+     * Rule
+     */
+    protected abstract class Rule {
+
+        public void begin(final String name, final Attributes attrs)
+                throws SAXException {
+        }
+
+        public void end(final String name) {
+        }
+
+        protected final Object getValue(final String desc, final String val)
+                throws SAXException {
+            Object value = null;
+            if (val != null) {
+                if ("Ljava/lang/String;".equals(desc)) {
+                    value = decode(val);
+                } else if ("Ljava/lang/Integer;".equals(desc)
+                        || "I".equals(desc) || "S".equals(desc)
+                        || "B".equals(desc) || "C".equals(desc)
+                        || "Z".equals(desc)) {
+                    value = new Integer(val);
+
+                } else if ("Ljava/lang/Short;".equals(desc)) {
+                    value = new Short(val);
+
+                } else if ("Ljava/lang/Byte;".equals(desc)) {
+                    value = new Byte(val);
+
+                } else if ("Ljava/lang/Character;".equals(desc)) {
+                    value = new Character(decode(val).charAt(0));
+
+                } else if ("Ljava/lang/Boolean;".equals(desc)) {
+                    value = Boolean.valueOf(val);
+
+                } else if ("Ljava/lang/Long;".equals(desc) || "J".equals(desc)) {
+                    value = new Long(val);
+                } else if ("Ljava/lang/Float;".equals(desc) || "F".equals(desc)) {
+                    value = new Float(val);
+                } else if ("Ljava/lang/Double;".equals(desc)
+                        || "D".equals(desc)) {
+                    value = new Double(val);
+                } else if (Type.getDescriptor(Type.class).equals(desc)) {
+                    value = Type.getType(val);
+
+                } else if (Type.getDescriptor(Handle.class).equals(desc)) {
+                    value = decodeHandle(val);
+
+                } else {
+                    // TODO use of default toString().
+                    throw new SAXException("Invalid value:" + val + " desc:"
+                            + desc + " ctx:" + this);
+                }
+            }
+            return value;
+        }
+
+        Handle decodeHandle(final String val) throws SAXException {
+            try {
+                int dotIndex = val.indexOf('.');
+                int descIndex = val.indexOf('(', dotIndex + 1);
+                int tagIndex = val.lastIndexOf('(');
+
+                int tag = Integer.parseInt(val.substring(tagIndex + 1,
+                        val.length() - 1));
+                String owner = val.substring(0, dotIndex);
+                String name = val.substring(dotIndex + 1, descIndex);
+                String desc = val.substring(descIndex, tagIndex - 1);
+                return new Handle(tag, owner, name, desc);
+
+            } catch (RuntimeException e) {
+                throw new SAXException("Malformed handle " + val, e);
+            }
+        }
+
+        private final String decode(final String val) throws SAXException {
+            StringBuffer sb = new StringBuffer(val.length());
+            try {
+                int n = 0;
+                while (n < val.length()) {
+                    char c = val.charAt(n);
+                    if (c == '\\') {
+                        n++;
+                        c = val.charAt(n);
+                        if (c == '\\') {
+                            sb.append('\\');
+                        } else {
+                            n++; // skip 'u'
+                            sb.append((char) Integer.parseInt(
+                                    val.substring(n, n + 4), 16));
+                            n += 3;
+                        }
+                    } else {
+                        sb.append(c);
+                    }
+                    n++;
+                }
+
+            } catch (RuntimeException ex) {
+                throw new SAXException(ex);
+            }
+            return sb.toString();
+        }
+
+        protected final Label getLabel(final Object label) {
+            Label lbl = labels.get(label);
+            if (lbl == null) {
+                lbl = new Label();
+                labels.put(label, lbl);
+            }
+            return lbl;
+        }
+
+        // TODO verify move to stack
+        protected final MethodVisitor getCodeVisitor() {
+            return (MethodVisitor) peek();
+        }
+
+        protected final int getAccess(final String s) {
+            int access = 0;
+            if (s.indexOf("public") != -1) {
+                access |= ACC_PUBLIC;
+            }
+            if (s.indexOf("private") != -1) {
+                access |= ACC_PRIVATE;
+            }
+            if (s.indexOf("protected") != -1) {
+                access |= ACC_PROTECTED;
+            }
+            if (s.indexOf("static") != -1) {
+                access |= ACC_STATIC;
+            }
+            if (s.indexOf("final") != -1) {
+                access |= ACC_FINAL;
+            }
+            if (s.indexOf("super") != -1) {
+                access |= ACC_SUPER;
+            }
+            if (s.indexOf("synchronized") != -1) {
+                access |= ACC_SYNCHRONIZED;
+            }
+            if (s.indexOf("volatile") != -1) {
+                access |= ACC_VOLATILE;
+            }
+            if (s.indexOf("bridge") != -1) {
+                access |= ACC_BRIDGE;
+            }
+            if (s.indexOf("varargs") != -1) {
+                access |= ACC_VARARGS;
+            }
+            if (s.indexOf("transient") != -1) {
+                access |= ACC_TRANSIENT;
+            }
+            if (s.indexOf("native") != -1) {
+                access |= ACC_NATIVE;
+            }
+            if (s.indexOf("interface") != -1) {
+                access |= ACC_INTERFACE;
+            }
+            if (s.indexOf("abstract") != -1) {
+                access |= ACC_ABSTRACT;
+            }
+            if (s.indexOf("strict") != -1) {
+                access |= ACC_STRICT;
+            }
+            if (s.indexOf("synthetic") != -1) {
+                access |= ACC_SYNTHETIC;
+            }
+            if (s.indexOf("annotation") != -1) {
+                access |= ACC_ANNOTATION;
+            }
+            if (s.indexOf("enum") != -1) {
+                access |= ACC_ENUM;
+            }
+            if (s.indexOf("deprecated") != -1) {
+                access |= ACC_DEPRECATED;
+            }
+            if (s.indexOf("mandated") != -1) {
+                access |= ACC_MANDATED;
+            }
+            return access;
+        }
+    }
+
+    /**
+     * ClassRule
+     */
+    final class ClassRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            int major = Integer.parseInt(attrs.getValue("major"));
+            int minor = Integer.parseInt(attrs.getValue("minor"));
+            HashMap<String, Object> vals = new HashMap<String, Object>();
+            vals.put("version", new Integer(minor << 16 | major));
+            vals.put("access", attrs.getValue("access"));
+            vals.put("name", attrs.getValue("name"));
+            vals.put("parent", attrs.getValue("parent"));
+            vals.put("source", attrs.getValue("source"));
+            vals.put("signature", attrs.getValue("signature"));
+            vals.put("interfaces", new ArrayList<String>());
+            push(vals);
+            // values will be extracted in InterfacesRule.end();
+        }
+    }
+
+    final class SourceRule extends Rule {
+
+        @Override
+        public void begin(final String name, final Attributes attrs) {
+            String file = attrs.getValue("file");
+            String debug = attrs.getValue("debug");
+            cv.visitSource(file, debug);
+        }
+    }
+
+    /**
+     * InterfaceRule
+     */
+    final class InterfaceRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            ((ArrayList<String>) ((HashMap<?, ?>) peek()).get("interfaces"))
+                    .add(attrs.getValue("name"));
+        }
+    }
+
+    /**
+     * InterfacesRule
+     */
+    final class InterfacesRule extends Rule {
+
+        @Override
+        public final void end(final String element) {
+            HashMap<?, ?> vals = (HashMap<?, ?>) pop();
+            int version = ((Integer) vals.get("version")).intValue();
+            int access = getAccess((String) vals.get("access"));
+            String name = (String) vals.get("name");
+            String signature = (String) vals.get("signature");
+            String parent = (String) vals.get("parent");
+            ArrayList<?> infs = (ArrayList<?>) vals.get("interfaces");
+            String[] interfaces = infs.toArray(new String[infs.size()]);
+            cv.visit(version, access, name, signature, parent, interfaces);
+            push(cv);
+        }
+    }
+
+    /**
+     * OuterClassRule
+     */
+    final class OuterClassRule extends Rule {
+
+        @Override
+        public final void begin(final String element, final Attributes attrs) {
+            String owner = attrs.getValue("owner");
+            String name = attrs.getValue("name");
+            String desc = attrs.getValue("desc");
+            cv.visitOuterClass(owner, name, desc);
+        }
+    }
+
+    /**
+     * InnerClassRule
+     */
+    final class InnerClassRule extends Rule {
+
+        @Override
+        public final void begin(final String element, final Attributes attrs) {
+            int access = getAccess(attrs.getValue("access"));
+            String name = attrs.getValue("name");
+            String outerName = attrs.getValue("outerName");
+            String innerName = attrs.getValue("innerName");
+            cv.visitInnerClass(name, outerName, innerName, access);
+        }
+    }
+
+    /**
+     * FieldRule
+     */
+    final class FieldRule extends Rule {
+
+        @Override
+        public final void begin(final String element, final Attributes attrs)
+                throws SAXException {
+            int access = getAccess(attrs.getValue("access"));
+            String name = attrs.getValue("name");
+            String signature = attrs.getValue("signature");
+            String desc = attrs.getValue("desc");
+            Object value = getValue(desc, attrs.getValue("value"));
+            push(cv.visitField(access, name, desc, signature, value));
+        }
+
+        @Override
+        public void end(final String name) {
+            ((FieldVisitor) pop()).visitEnd();
+        }
+    }
+
+    /**
+     * MethodRule
+     */
+    final class MethodRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            labels = new HashMap<Object, Label>();
+            HashMap<String, Object> vals = new HashMap<String, Object>();
+            vals.put("access", attrs.getValue("access"));
+            vals.put("name", attrs.getValue("name"));
+            vals.put("desc", attrs.getValue("desc"));
+            vals.put("signature", attrs.getValue("signature"));
+            vals.put("exceptions", new ArrayList<String>());
+            push(vals);
+            // values will be extracted in ExceptionsRule.end();
+        }
+
+        @Override
+        public final void end(final String name) {
+            ((MethodVisitor) pop()).visitEnd();
+            labels = null;
+        }
+    }
+
+    /**
+     * ExceptionRule
+     */
+    final class ExceptionRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            ((ArrayList<String>) ((HashMap<?, ?>) peek()).get("exceptions"))
+                    .add(attrs.getValue("name"));
+        }
+    }
+
+    /**
+     * ExceptionsRule
+     */
+    final class ExceptionsRule extends Rule {
+
+        @Override
+        public final void end(final String element) {
+            HashMap<?, ?> vals = (HashMap<?, ?>) pop();
+            int access = getAccess((String) vals.get("access"));
+            String name = (String) vals.get("name");
+            String desc = (String) vals.get("desc");
+            String signature = (String) vals.get("signature");
+            ArrayList<?> excs = (ArrayList<?>) vals.get("exceptions");
+            String[] exceptions = excs.toArray(new String[excs.size()]);
+
+            push(cv.visitMethod(access, name, desc, signature, exceptions));
+        }
+    }
+
+    /**
+     * MethodParameterRule
+     */
+    final class MethodParameterRule extends Rule {
+        @Override
+        public void begin(final String nm, final Attributes attrs) {
+            String name = attrs.getValue("name");
+            int access = getAccess(attrs.getValue("access"));
+            getCodeVisitor().visitParameter(name, access);
+        }
+    }
+
+    /**
+     * TableSwitchRule
+     */
+    final class TableSwitchRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            HashMap<String, Object> vals = new HashMap<String, Object>();
+            vals.put("min", attrs.getValue("min"));
+            vals.put("max", attrs.getValue("max"));
+            vals.put("dflt", attrs.getValue("dflt"));
+            vals.put("labels", new ArrayList<String>());
+            push(vals);
+        }
+
+        @Override
+        public final void end(final String name) {
+            HashMap<?, ?> vals = (HashMap<?, ?>) pop();
+            int min = Integer.parseInt((String) vals.get("min"));
+            int max = Integer.parseInt((String) vals.get("max"));
+            Label dflt = getLabel(vals.get("dflt"));
+            ArrayList<?> lbls = (ArrayList<?>) vals.get("labels");
+            Label[] labels = lbls.toArray(new Label[lbls.size()]);
+            getCodeVisitor().visitTableSwitchInsn(min, max, dflt, labels);
+        }
+    }
+
+    /**
+     * TableSwitchLabelRule
+     */
+    final class TableSwitchLabelRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            ((ArrayList<Label>) ((HashMap<?, ?>) peek()).get("labels"))
+                    .add(getLabel(attrs.getValue("name")));
+        }
+    }
+
+    /**
+     * LookupSwitchRule
+     */
+    final class LookupSwitchRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            HashMap<String, Object> vals = new HashMap<String, Object>();
+            vals.put("dflt", attrs.getValue("dflt"));
+            vals.put("labels", new ArrayList<Label>());
+            vals.put("keys", new ArrayList<String>());
+            push(vals);
+        }
+
+        @Override
+        public final void end(final String name) {
+            HashMap<?, ?> vals = (HashMap<?, ?>) pop();
+            Label dflt = getLabel(vals.get("dflt"));
+            ArrayList<String> keyList = (ArrayList<String>) vals.get("keys");
+            ArrayList<?> lbls = (ArrayList<?>) vals.get("labels");
+            Label[] labels = lbls.toArray(new Label[lbls.size()]);
+            int[] keys = new int[keyList.size()];
+            for (int i = 0; i < keys.length; i++) {
+                keys[i] = Integer.parseInt(keyList.get(i));
+            }
+            getCodeVisitor().visitLookupSwitchInsn(dflt, keys, labels);
+        }
+    }
+
+    /**
+     * LookupSwitchLabelRule
+     */
+    final class LookupSwitchLabelRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            HashMap<?, ?> vals = (HashMap<?, ?>) peek();
+            ((ArrayList<Label>) vals.get("labels")).add(getLabel(attrs
+                    .getValue("name")));
+            ((ArrayList<String>) vals.get("keys")).add(attrs.getValue("key"));
+        }
+    }
+
+    /**
+     * FrameRule
+     */
+    final class FrameRule extends Rule {
+
+        @Override
+        public void begin(final String name, final Attributes attrs) {
+            HashMap<String, Object> typeLists = new HashMap<String, Object>();
+            typeLists.put("local", new ArrayList<Object>());
+            typeLists.put("stack", new ArrayList<Object>());
+            push(attrs.getValue("type"));
+            push(attrs.getValue("count") == null ? "0" : attrs
+                    .getValue("count"));
+            push(typeLists);
+        }
+
+        @Override
+        public void end(final String name) {
+            HashMap<?, ?> typeLists = (HashMap<?, ?>) pop();
+            ArrayList<?> locals = (ArrayList<?>) typeLists.get("local");
+            int nLocal = locals.size();
+            Object[] local = locals.toArray();
+            ArrayList<?> stacks = (ArrayList<?>) typeLists.get("stack");
+            int nStack = stacks.size();
+            Object[] stack = stacks.toArray();
+            String count = (String) pop();
+            String type = (String) pop();
+            if ("NEW".equals(type)) {
+                getCodeVisitor()
+                        .visitFrame(F_NEW, nLocal, local, nStack, stack);
+            } else if ("FULL".equals(type)) {
+                getCodeVisitor().visitFrame(F_FULL, nLocal, local, nStack,
+                        stack);
+            } else if ("APPEND".equals(type)) {
+                getCodeVisitor().visitFrame(F_APPEND, nLocal, local, 0, null);
+            } else if ("CHOP".equals(type)) {
+                getCodeVisitor().visitFrame(F_CHOP, Integer.parseInt(count),
+                        null, 0, null);
+            } else if ("SAME".equals(type)) {
+                getCodeVisitor().visitFrame(F_SAME, 0, null, 0, null);
+            } else if ("SAME1".equals(type)) {
+                getCodeVisitor().visitFrame(F_SAME1, 0, null, nStack, stack);
+            }
+        }
+    }
+
+    final class FrameTypeRule extends Rule {
+
+        @Override
+        public void begin(final String name, final Attributes attrs) {
+            ArrayList<Object> types = (ArrayList<Object>) ((HashMap<?, ?>) peek())
+                    .get(name);
+            String type = attrs.getValue("type");
+            if ("uninitialized".equals(type)) {
+                types.add(getLabel(attrs.getValue("label")));
+            } else {
+                Integer t = TYPES.get(type);
+                if (t == null) {
+                    types.add(type);
+                } else {
+                    types.add(t);
+                }
+            }
+        }
+    }
+
+    /**
+     * LabelRule
+     */
+    final class LabelRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            getCodeVisitor().visitLabel(getLabel(attrs.getValue("name")));
+        }
+    }
+
+    /**
+     * TryCatchRule
+     */
+    final class TryCatchRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            Label start = getLabel(attrs.getValue("start"));
+            Label end = getLabel(attrs.getValue("end"));
+            Label handler = getLabel(attrs.getValue("handler"));
+            String type = attrs.getValue("type");
+            getCodeVisitor().visitTryCatchBlock(start, end, handler, type);
+        }
+    }
+
+    /**
+     * LineNumberRule
+     */
+    final class LineNumberRule extends Rule {
+
+        @Override
+        public final void begin(final String name, final Attributes attrs) {
+            int line = Integer.parseInt(attrs.getValue("line"));
+            Label start = getLabel(attrs.getValue("start"));
+            getCodeVisitor().visitLineNumber(line, start);
+        }
+    }
+
+    /**
+     * LocalVarRule
+     */
+    final class LocalVarRule extends Rule {
+
+        @Override
+        public final void begin(final String element, final Attributes attrs) {
+            String name = attrs.getValue("name");
+            String desc = attrs.getValue("desc");
+            String signature = attrs.getValue("signature");
+            Label start = getLabel(attrs.getValue("start"));
+            Label end = getLabel(attrs.getValue("end"));
+            int var = Integer.parseInt(attrs.getValue("var"));
+            getCodeVisitor().visitLocalVariable(name, desc, signature, start,
+                    end, var);
+        }
+    }
+
+    /**
+     * InvokeDynamicRule
+     */
+    final class InvokeDynamicRule extends Rule {
+        @Override
+        public final void begin(final String element, final Attributes attrs)
+                throws SAXException {
+            push(attrs.getValue("name"));
+            push(attrs.getValue("desc"));
+            push(decodeHandle(attrs.getValue("bsm")));
+            push(new ArrayList<Object>());
+        }
+
+        @Override
+        public final void end(final String element) {
+            ArrayList<?> bsmArgs = (ArrayList<?>) pop();
+            Handle bsm = (Handle) pop();
+            String desc = (String) pop();
+            String name = (String) pop();
+            getCodeVisitor().visitInvokeDynamicInsn(name, desc, bsm,
+                    bsmArgs.toArray());
+        }
+    }
+
+    /**
+     * InvokeDynamicBsmArgumentsRule
+     */
+    final class InvokeDynamicBsmArgumentsRule extends Rule {
+        @Override
+        public final void begin(final String element, final Attributes attrs)
+                throws SAXException {
+            ArrayList<Object> bsmArgs = (ArrayList<Object>) peek();
+            bsmArgs.add(getValue(attrs.getValue("desc"), attrs.getValue("cst")));
+        }
+    }
+
+    /**
+     * OpcodesRule
+     */
+    final class OpcodesRule extends Rule {
+
+        // public boolean match( String match, String element) {
+        // return match.startsWith( path) && OPCODES.containsKey( element);
+        // }
+
+        @Override
+        public final void begin(final String element, final Attributes attrs)
+                throws SAXException {
+            Opcode o = OPCODES.get(element);
+            if (o == null) {
+                throw new SAXException("Invalid element: " + element + " at "
+                        + match);
+            }
+
+            switch (o.type) {
+            case OpcodeGroup.INSN:
+                getCodeVisitor().visitInsn(o.opcode);
+                break;
+
+            case OpcodeGroup.INSN_FIELD:
+                getCodeVisitor().visitFieldInsn(o.opcode,
+                        attrs.getValue("owner"), attrs.getValue("name"),
+                        attrs.getValue("desc"));
+                break;
+
+            case OpcodeGroup.INSN_INT:
+                getCodeVisitor().visitIntInsn(o.opcode,
+                        Integer.parseInt(attrs.getValue("value")));
+                break;
+
+            case OpcodeGroup.INSN_JUMP:
+                getCodeVisitor().visitJumpInsn(o.opcode,
+                        getLabel(attrs.getValue("label")));
+                break;
+
+            case OpcodeGroup.INSN_METHOD:
+                getCodeVisitor().visitMethodInsn(o.opcode,
+                        attrs.getValue("owner"), attrs.getValue("name"),
+                        attrs.getValue("desc"),
+                        attrs.getValue("itf").equals("true"));
+                break;
+
+            case OpcodeGroup.INSN_TYPE:
+                getCodeVisitor()
+                        .visitTypeInsn(o.opcode, attrs.getValue("desc"));
+                break;
+
+            case OpcodeGroup.INSN_VAR:
+                getCodeVisitor().visitVarInsn(o.opcode,
+                        Integer.parseInt(attrs.getValue("var")));
+                break;
+
+            case OpcodeGroup.INSN_IINC:
+                getCodeVisitor().visitIincInsn(
+                        Integer.parseInt(attrs.getValue("var")),
+                        Integer.parseInt(attrs.getValue("inc")));
+                break;
+
+            case OpcodeGroup.INSN_LDC:
+                getCodeVisitor()
+                        .visitLdcInsn(
+                                getValue(attrs.getValue("desc"),
+                                        attrs.getValue("cst")));
+                break;
+
+            case OpcodeGroup.INSN_MULTIANEWARRAY:
+                getCodeVisitor().visitMultiANewArrayInsn(
+                        attrs.getValue("desc"),
+                        Integer.parseInt(attrs.getValue("dims")));
+                break;
+
+            default:
+                throw new Error("Internal error");
+
+            }
+        }
+    }
+
+    /**
+     * MaxRule
+     */
+    final class MaxRule extends Rule {
+
+        @Override
+        public final void begin(final String element, final Attributes attrs) {
+            int maxStack = Integer.parseInt(attrs.getValue("maxStack"));
+            int maxLocals = Integer.parseInt(attrs.getValue("maxLocals"));
+            getCodeVisitor().visitMaxs(maxStack, maxLocals);
+        }
+    }
+
+    final class AnnotationRule extends Rule {
+
+        @Override
+        public void begin(final String name, final Attributes attrs) {
+            String desc = attrs.getValue("desc");
+            boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+                    .booleanValue();
+
+            Object v = peek();
+            if (v instanceof ClassVisitor) {
+                push(((ClassVisitor) v).visitAnnotation(desc, visible));
+            } else if (v instanceof FieldVisitor) {
+                push(((FieldVisitor) v).visitAnnotation(desc, visible));
+            } else if (v instanceof MethodVisitor) {
+                push(((MethodVisitor) v).visitAnnotation(desc, visible));
+            }
+        }
+
+        @Override
+        public void end(final String name) {
+            AnnotationVisitor av = (AnnotationVisitor) pop();
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+    }
+
+    final class TypeAnnotationRule extends Rule {
+
+        @Override
+        public void begin(final String name, final Attributes attrs) {
+            String desc = attrs.getValue("desc");
+            boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+                    .booleanValue();
+            int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
+            TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
+
+            Object v = peek();
+            if (v instanceof ClassVisitor) {
+                push(((ClassVisitor) v).visitTypeAnnotation(typeRef, typePath,
+                        desc, visible));
+            } else if (v instanceof FieldVisitor) {
+                push(((FieldVisitor) v).visitTypeAnnotation(typeRef, typePath,
+                        desc, visible));
+            } else if (v instanceof MethodVisitor) {
+                push(((MethodVisitor) v).visitTypeAnnotation(typeRef, typePath,
+                        desc, visible));
+            }
+        }
+
+        @Override
+        public void end(final String name) {
+            AnnotationVisitor av = (AnnotationVisitor) pop();
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+    }
+
+    final class AnnotationParameterRule extends Rule {
+
+        @Override
+        public void begin(final String name, final Attributes attrs) {
+            int parameter = Integer.parseInt(attrs.getValue("parameter"));
+            String desc = attrs.getValue("desc");
+            boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+                    .booleanValue();
+
+            push(((MethodVisitor) peek()).visitParameterAnnotation(parameter,
+                    desc, visible));
+        }
+
+        @Override
+        public void end(final String name) {
+            AnnotationVisitor av = (AnnotationVisitor) pop();
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+    }
+
+    final class InsnAnnotationRule extends Rule {
+
+        @Override
+        public void begin(final String name, final Attributes attrs) {
+            String desc = attrs.getValue("desc");
+            boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+                    .booleanValue();
+            int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
+            TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
+            push(((MethodVisitor) peek()).visitInsnAnnotation(typeRef,
+                    typePath, desc, visible));
+        }
+
+        @Override
+        public void end(final String name) {
+            AnnotationVisitor av = (AnnotationVisitor) pop();
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+    }
+
+    final class TryCatchAnnotationRule extends Rule {
+
+        @Override
+        public void begin(final String name, final Attributes attrs) {
+            String desc = attrs.getValue("desc");
+            boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+                    .booleanValue();
+            int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
+            TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
+            push(((MethodVisitor) peek()).visitTryCatchAnnotation(typeRef,
+                    typePath, desc, visible));
+        }
+
+        @Override
+        public void end(final String name) {
+            AnnotationVisitor av = (AnnotationVisitor) pop();
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+    }
+
+    final class LocalVariableAnnotationRule extends Rule {
+
+        @Override
+        public void begin(final String name, final Attributes attrs) {
+            String desc = attrs.getValue("desc");
+            boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+                    .booleanValue();
+            int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
+            TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
+            String[] s = attrs.getValue("start").split(" ");
+            Label[] start = new Label[s.length];
+            for (int i = 0; i < start.length; ++i) {
+                start[i] = getLabel(s[i]);
+            }
+            String[] e = attrs.getValue("end").split(" ");
+            Label[] end = new Label[e.length];
+            for (int i = 0; i < end.length; ++i) {
+                end[i] = getLabel(e[i]);
+            }
+            String[] v = attrs.getValue("index").split(" ");
+            int[] index = new int[v.length];
+            for (int i = 0; i < index.length; ++i) {
+                index[i] = Integer.parseInt(v[i]);
+            }
+            push(((MethodVisitor) peek()).visitLocalVariableAnnotation(typeRef,
+                    typePath, start, end, index, desc, visible));
+        }
+
+        @Override
+        public void end(final String name) {
+            AnnotationVisitor av = (AnnotationVisitor) pop();
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+    }
+
+    final class AnnotationValueRule extends Rule {
+
+        @Override
+        public void begin(final String nm, final Attributes attrs)
+                throws SAXException {
+            AnnotationVisitor av = (AnnotationVisitor) peek();
+            if (av != null) {
+                av.visit(
+                        attrs.getValue("name"),
+                        getValue(attrs.getValue("desc"),
+                                attrs.getValue("value")));
+            }
+        }
+    }
+
+    final class AnnotationValueEnumRule extends Rule {
+
+        @Override
+        public void begin(final String nm, final Attributes attrs) {
+            AnnotationVisitor av = (AnnotationVisitor) peek();
+            if (av != null) {
+                av.visitEnum(attrs.getValue("name"), attrs.getValue("desc"),
+                        attrs.getValue("value"));
+            }
+        }
+    }
+
+    final class AnnotationValueAnnotationRule extends Rule {
+
+        @Override
+        public void begin(final String nm, final Attributes attrs) {
+            AnnotationVisitor av = (AnnotationVisitor) peek();
+            push(av == null ? null : av.visitAnnotation(attrs.getValue("name"),
+                    attrs.getValue("desc")));
+        }
+
+        @Override
+        public void end(final String name) {
+            AnnotationVisitor av = (AnnotationVisitor) pop();
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+    }
+
+    final class AnnotationValueArrayRule extends Rule {
+
+        @Override
+        public void begin(final String nm, final Attributes attrs) {
+            AnnotationVisitor av = (AnnotationVisitor) peek();
+            push(av == null ? null : av.visitArray(attrs.getValue("name")));
+        }
+
+        @Override
+        public void end(final String name) {
+            AnnotationVisitor av = (AnnotationVisitor) pop();
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+    }
+
+    final class AnnotationDefaultRule extends Rule {
+
+        @Override
+        public void begin(final String nm, final Attributes attrs) {
+            MethodVisitor av = (MethodVisitor) peek();
+            push(av == null ? null : av.visitAnnotationDefault());
+        }
+
+        @Override
+        public void end(final String name) {
+            AnnotationVisitor av = (AnnotationVisitor) pop();
+            if (av != null) {
+                av.visitEnd();
+            }
+        }
+    }
+
+    /**
+     * Opcode
+     */
+    static final class Opcode {
+
+        public final int opcode;
+
+        public final int type;
+
+        Opcode(final int opcode, final int type) {
+            this.opcode = opcode;
+            this.type = type;
+        }
+    }
+}


[05/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java
new file mode 100644
index 0000000..5770364
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java
@@ -0,0 +1,1542 @@
+/***
+ * 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.util;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+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;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.Analyzer;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicValue;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicVerifier;
+
+/**
+ * A {@link MethodVisitor} that checks that its methods are properly used. More
+ * precisely this method adapter checks each instruction individually, i.e.,
+ * each visit method checks some preconditions based <i>only</i> on its
+ * arguments - such as the fact that the given opcode is correct for a given
+ * visit method. This adapter can also perform some basic data flow checks (more
+ * precisely those that can be performed without the full class hierarchy - see
+ * {@link org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicVerifier}). For instance in a
+ * method whose signature is <tt>void m ()</tt>, the invalid instruction
+ * IRETURN, or the invalid sequence IADD L2I will be detected if the data flow
+ * checks are enabled. These checks are enabled by using the
+ * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)} constructor.
+ * They are not performed if any other constructor is used.
+ * 
+ * @author Eric Bruneton
+ */
+public class CheckMethodAdapter extends MethodVisitor {
+
+    /**
+     * The class version number.
+     */
+    public int version;
+
+    /**
+     * The access flags of the method.
+     */
+    private int access;
+
+    /**
+     * <tt>true</tt> if the visitCode method has been called.
+     */
+    private boolean startCode;
+
+    /**
+     * <tt>true</tt> if the visitMaxs method has been called.
+     */
+    private boolean endCode;
+
+    /**
+     * <tt>true</tt> if the visitEnd method has been called.
+     */
+    private boolean endMethod;
+
+    /**
+     * Number of visited instructions.
+     */
+    private int insnCount;
+
+    /**
+     * The already visited labels. This map associate Integer values to pseudo
+     * code offsets.
+     */
+    private final Map<Label, Integer> labels;
+
+    /**
+     * The labels used in this method. Every used label must be visited with
+     * visitLabel before the end of the method (i.e. should be in #labels).
+     */
+    private Set<Label> usedLabels;
+
+    /**
+     * Number of visited frames in expanded form.
+     */
+    private int expandedFrames;
+
+    /**
+     * Number of visited frames in compressed form.
+     */
+    private int compressedFrames;
+
+    /**
+     * Number of instructions before the last visited frame.
+     */
+    private int lastFrame = -1;
+
+    /**
+     * The exception handler ranges. Each pair of list element contains the
+     * start and end labels of an exception handler block.
+     */
+    private List<Label> handlers;
+
+    /**
+     * Code of the visit method to be used for each opcode.
+     */
+    private static final int[] TYPE;
+
+    /**
+     * The Label.status field.
+     */
+    private static Field labelStatusField;
+
+    static {
+        String s = "BBBBBBBBBBBBBBBBCCIAADDDDDAAAAAAAAAAAAAAAAAAAABBBBBBBBDD"
+                + "DDDAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
+                + "BBBBBBBBBBBBBBBBBBBJBBBBBBBBBBBBBBBBBBBBHHHHHHHHHHHHHHHHD"
+                + "KLBBBBBBFFFFGGGGAECEBBEEBBAMHHAA";
+        TYPE = new int[s.length()];
+        for (int i = 0; i < TYPE.length; ++i) {
+            TYPE[i] = s.charAt(i) - 'A' - 1;
+        }
+    }
+
+    // code to generate the above string
+    // public static void main (String[] args) {
+    // int[] TYPE = new int[] {
+    // 0, //NOP
+    // 0, //ACONST_NULL
+    // 0, //ICONST_M1
+    // 0, //ICONST_0
+    // 0, //ICONST_1
+    // 0, //ICONST_2
+    // 0, //ICONST_3
+    // 0, //ICONST_4
+    // 0, //ICONST_5
+    // 0, //LCONST_0
+    // 0, //LCONST_1
+    // 0, //FCONST_0
+    // 0, //FCONST_1
+    // 0, //FCONST_2
+    // 0, //DCONST_0
+    // 0, //DCONST_1
+    // 1, //BIPUSH
+    // 1, //SIPUSH
+    // 7, //LDC
+    // -1, //LDC_W
+    // -1, //LDC2_W
+    // 2, //ILOAD
+    // 2, //LLOAD
+    // 2, //FLOAD
+    // 2, //DLOAD
+    // 2, //ALOAD
+    // -1, //ILOAD_0
+    // -1, //ILOAD_1
+    // -1, //ILOAD_2
+    // -1, //ILOAD_3
+    // -1, //LLOAD_0
+    // -1, //LLOAD_1
+    // -1, //LLOAD_2
+    // -1, //LLOAD_3
+    // -1, //FLOAD_0
+    // -1, //FLOAD_1
+    // -1, //FLOAD_2
+    // -1, //FLOAD_3
+    // -1, //DLOAD_0
+    // -1, //DLOAD_1
+    // -1, //DLOAD_2
+    // -1, //DLOAD_3
+    // -1, //ALOAD_0
+    // -1, //ALOAD_1
+    // -1, //ALOAD_2
+    // -1, //ALOAD_3
+    // 0, //IALOAD
+    // 0, //LALOAD
+    // 0, //FALOAD
+    // 0, //DALOAD
+    // 0, //AALOAD
+    // 0, //BALOAD
+    // 0, //CALOAD
+    // 0, //SALOAD
+    // 2, //ISTORE
+    // 2, //LSTORE
+    // 2, //FSTORE
+    // 2, //DSTORE
+    // 2, //ASTORE
+    // -1, //ISTORE_0
+    // -1, //ISTORE_1
+    // -1, //ISTORE_2
+    // -1, //ISTORE_3
+    // -1, //LSTORE_0
+    // -1, //LSTORE_1
+    // -1, //LSTORE_2
+    // -1, //LSTORE_3
+    // -1, //FSTORE_0
+    // -1, //FSTORE_1
+    // -1, //FSTORE_2
+    // -1, //FSTORE_3
+    // -1, //DSTORE_0
+    // -1, //DSTORE_1
+    // -1, //DSTORE_2
+    // -1, //DSTORE_3
+    // -1, //ASTORE_0
+    // -1, //ASTORE_1
+    // -1, //ASTORE_2
+    // -1, //ASTORE_3
+    // 0, //IASTORE
+    // 0, //LASTORE
+    // 0, //FASTORE
+    // 0, //DASTORE
+    // 0, //AASTORE
+    // 0, //BASTORE
+    // 0, //CASTORE
+    // 0, //SASTORE
+    // 0, //POP
+    // 0, //POP2
+    // 0, //DUP
+    // 0, //DUP_X1
+    // 0, //DUP_X2
+    // 0, //DUP2
+    // 0, //DUP2_X1
+    // 0, //DUP2_X2
+    // 0, //SWAP
+    // 0, //IADD
+    // 0, //LADD
+    // 0, //FADD
+    // 0, //DADD
+    // 0, //ISUB
+    // 0, //LSUB
+    // 0, //FSUB
+    // 0, //DSUB
+    // 0, //IMUL
+    // 0, //LMUL
+    // 0, //FMUL
+    // 0, //DMUL
+    // 0, //IDIV
+    // 0, //LDIV
+    // 0, //FDIV
+    // 0, //DDIV
+    // 0, //IREM
+    // 0, //LREM
+    // 0, //FREM
+    // 0, //DREM
+    // 0, //INEG
+    // 0, //LNEG
+    // 0, //FNEG
+    // 0, //DNEG
+    // 0, //ISHL
+    // 0, //LSHL
+    // 0, //ISHR
+    // 0, //LSHR
+    // 0, //IUSHR
+    // 0, //LUSHR
+    // 0, //IAND
+    // 0, //LAND
+    // 0, //IOR
+    // 0, //LOR
+    // 0, //IXOR
+    // 0, //LXOR
+    // 8, //IINC
+    // 0, //I2L
+    // 0, //I2F
+    // 0, //I2D
+    // 0, //L2I
+    // 0, //L2F
+    // 0, //L2D
+    // 0, //F2I
+    // 0, //F2L
+    // 0, //F2D
+    // 0, //D2I
+    // 0, //D2L
+    // 0, //D2F
+    // 0, //I2B
+    // 0, //I2C
+    // 0, //I2S
+    // 0, //LCMP
+    // 0, //FCMPL
+    // 0, //FCMPG
+    // 0, //DCMPL
+    // 0, //DCMPG
+    // 6, //IFEQ
+    // 6, //IFNE
+    // 6, //IFLT
+    // 6, //IFGE
+    // 6, //IFGT
+    // 6, //IFLE
+    // 6, //IF_ICMPEQ
+    // 6, //IF_ICMPNE
+    // 6, //IF_ICMPLT
+    // 6, //IF_ICMPGE
+    // 6, //IF_ICMPGT
+    // 6, //IF_ICMPLE
+    // 6, //IF_ACMPEQ
+    // 6, //IF_ACMPNE
+    // 6, //GOTO
+    // 6, //JSR
+    // 2, //RET
+    // 9, //TABLESWITCH
+    // 10, //LOOKUPSWITCH
+    // 0, //IRETURN
+    // 0, //LRETURN
+    // 0, //FRETURN
+    // 0, //DRETURN
+    // 0, //ARETURN
+    // 0, //RETURN
+    // 4, //GETSTATIC
+    // 4, //PUTSTATIC
+    // 4, //GETFIELD
+    // 4, //PUTFIELD
+    // 5, //INVOKEVIRTUAL
+    // 5, //INVOKESPECIAL
+    // 5, //INVOKESTATIC
+    // 5, //INVOKEINTERFACE
+    // -1, //INVOKEDYNAMIC
+    // 3, //NEW
+    // 1, //NEWARRAY
+    // 3, //ANEWARRAY
+    // 0, //ARRAYLENGTH
+    // 0, //ATHROW
+    // 3, //CHECKCAST
+    // 3, //INSTANCEOF
+    // 0, //MONITORENTER
+    // 0, //MONITOREXIT
+    // -1, //WIDE
+    // 11, //MULTIANEWARRAY
+    // 6, //IFNULL
+    // 6, //IFNONNULL
+    // -1, //GOTO_W
+    // -1 //JSR_W
+    // };
+    // for (int i = 0; i < TYPE.length; ++i) {
+    // System.out.print((char)(TYPE[i] + 1 + 'A'));
+    // }
+    // System.out.println();
+    // }
+
+    /**
+     * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+     * will not perform any data flow check (see
+     * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
+     * <i>Subclasses must not use this constructor</i>. Instead, they must use
+     * the {@link #CheckMethodAdapter(int, MethodVisitor, Map)} version.
+     * 
+     * @param mv
+     *            the method visitor to which this adapter must delegate calls.
+     */
+    public CheckMethodAdapter(final MethodVisitor mv) {
+        this(mv, new HashMap<Label, Integer>());
+    }
+
+    /**
+     * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+     * will not perform any data flow check (see
+     * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
+     * <i>Subclasses must not use this constructor</i>. Instead, they must use
+     * the {@link #CheckMethodAdapter(int, MethodVisitor, Map)} version.
+     * 
+     * @param mv
+     *            the method visitor to which this adapter must delegate calls.
+     * @param labels
+     *            a map of already visited labels (in other methods).
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public CheckMethodAdapter(final MethodVisitor mv,
+            final Map<Label, Integer> labels) {
+        this(Opcodes.ASM5, mv, labels);
+        if (getClass() != CheckMethodAdapter.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+     * will not perform any data flow check (see
+     * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
+     * 
+     * @param mv
+     *            the method visitor to which this adapter must delegate calls.
+     * @param labels
+     *            a map of already visited labels (in other methods).
+     */
+    protected CheckMethodAdapter(final int api, final MethodVisitor mv,
+            final Map<Label, Integer> labels) {
+        super(api, mv);
+        this.labels = labels;
+        this.usedLabels = new HashSet<Label>();
+        this.handlers = new ArrayList<Label>();
+    }
+
+    /**
+     * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+     * will perform basic data flow checks. For instance in a method whose
+     * signature is <tt>void m ()</tt>, the invalid instruction IRETURN, or the
+     * invalid sequence IADD L2I will be detected.
+     * 
+     * @param access
+     *            the method's access flags.
+     * @param name
+     *            the method's name.
+     * @param desc
+     *            the method's descriptor (see {@link Type Type}).
+     * @param cmv
+     *            the method visitor to which this adapter must delegate calls.
+     * @param labels
+     *            a map of already visited labels (in other methods).
+     */
+    public CheckMethodAdapter(final int access, final String name,
+            final String desc, final MethodVisitor cmv,
+            final Map<Label, Integer> labels) {
+        this(new MethodNode(Opcodes.ASM5, access, name, desc, null, null) {
+            @Override
+            public void visitEnd() {
+                Analyzer<BasicValue> a = new Analyzer<BasicValue>(
+                        new BasicVerifier());
+                try {
+                    a.analyze("dummy", this);
+                } catch (Exception e) {
+                    if (e instanceof IndexOutOfBoundsException
+                            && maxLocals == 0 && maxStack == 0) {
+                        throw new RuntimeException(
+                                "Data flow checking option requires valid, non zero maxLocals and maxStack values.");
+                    }
+                    e.printStackTrace();
+                    StringWriter sw = new StringWriter();
+                    PrintWriter pw = new PrintWriter(sw, true);
+                    CheckClassAdapter.printAnalyzerResult(this, a, pw);
+                    pw.close();
+                    throw new RuntimeException(e.getMessage() + ' '
+                            + sw.toString());
+                }
+                accept(cmv);
+            }
+        }, labels);
+        this.access = access;
+    }
+
+    @Override
+    public void visitParameter(String name, int access) {
+        if (name != null) {
+            checkUnqualifiedName(version, name, "name");
+        }
+        CheckClassAdapter.checkAccess(access, Opcodes.ACC_FINAL
+                + Opcodes.ACC_MANDATED + Opcodes.ACC_SYNTHETIC);
+        super.visitParameter(name, access);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        checkEndMethod();
+        checkDesc(desc, false);
+        return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        checkEndMethod();
+        int sort = typeRef >>> 24;
+        if (sort != TypeReference.METHOD_TYPE_PARAMETER
+                && sort != TypeReference.METHOD_TYPE_PARAMETER_BOUND
+                && sort != TypeReference.METHOD_RETURN
+                && sort != TypeReference.METHOD_RECEIVER
+                && sort != TypeReference.METHOD_FORMAL_PARAMETER
+                && sort != TypeReference.THROWS) {
+            throw new IllegalArgumentException("Invalid type reference sort 0x"
+                    + Integer.toHexString(sort));
+        }
+        CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+        CheckMethodAdapter.checkDesc(desc, false);
+        return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef,
+                typePath, desc, visible));
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotationDefault() {
+        checkEndMethod();
+        return new CheckAnnotationAdapter(super.visitAnnotationDefault(), false);
+    }
+
+    @Override
+    public AnnotationVisitor visitParameterAnnotation(final int parameter,
+            final String desc, final boolean visible) {
+        checkEndMethod();
+        checkDesc(desc, false);
+        return new CheckAnnotationAdapter(super.visitParameterAnnotation(
+                parameter, desc, visible));
+    }
+
+    @Override
+    public void visitAttribute(final Attribute attr) {
+        checkEndMethod();
+        if (attr == null) {
+            throw new IllegalArgumentException(
+                    "Invalid attribute (must not be null)");
+        }
+        super.visitAttribute(attr);
+    }
+
+    @Override
+    public void visitCode() {
+        if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+            throw new RuntimeException("Abstract methods cannot have code");
+        }
+        startCode = true;
+        super.visitCode();
+    }
+
+    @Override
+    public void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack) {
+        if (insnCount == lastFrame) {
+            throw new IllegalStateException(
+                    "At most one frame can be visited at a given code location.");
+        }
+        lastFrame = insnCount;
+        int mLocal;
+        int mStack;
+        switch (type) {
+        case Opcodes.F_NEW:
+        case Opcodes.F_FULL:
+            mLocal = Integer.MAX_VALUE;
+            mStack = Integer.MAX_VALUE;
+            break;
+
+        case Opcodes.F_SAME:
+            mLocal = 0;
+            mStack = 0;
+            break;
+
+        case Opcodes.F_SAME1:
+            mLocal = 0;
+            mStack = 1;
+            break;
+
+        case Opcodes.F_APPEND:
+        case Opcodes.F_CHOP:
+            mLocal = 3;
+            mStack = 0;
+            break;
+
+        default:
+            throw new IllegalArgumentException("Invalid frame type " + type);
+        }
+
+        if (nLocal > mLocal) {
+            throw new IllegalArgumentException("Invalid nLocal=" + nLocal
+                    + " for frame type " + type);
+        }
+        if (nStack > mStack) {
+            throw new IllegalArgumentException("Invalid nStack=" + nStack
+                    + " for frame type " + type);
+        }
+
+        if (type != Opcodes.F_CHOP) {
+            if (nLocal > 0 && (local == null || local.length < nLocal)) {
+                throw new IllegalArgumentException(
+                        "Array local[] is shorter than nLocal");
+            }
+            for (int i = 0; i < nLocal; ++i) {
+                checkFrameValue(local[i]);
+            }
+        }
+        if (nStack > 0 && (stack == null || stack.length < nStack)) {
+            throw new IllegalArgumentException(
+                    "Array stack[] is shorter than nStack");
+        }
+        for (int i = 0; i < nStack; ++i) {
+            checkFrameValue(stack[i]);
+        }
+        if (type == Opcodes.F_NEW) {
+            ++expandedFrames;
+        } else {
+            ++compressedFrames;
+        }
+        if (expandedFrames > 0 && compressedFrames > 0) {
+            throw new RuntimeException(
+                    "Expanded and compressed frames must not be mixed.");
+        }
+        super.visitFrame(type, nLocal, local, nStack, stack);
+    }
+
+    @Override
+    public void visitInsn(final int opcode) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode(opcode, 0);
+        super.visitInsn(opcode);
+        ++insnCount;
+    }
+
+    @Override
+    public void visitIntInsn(final int opcode, final int operand) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode(opcode, 1);
+        switch (opcode) {
+        case Opcodes.BIPUSH:
+            checkSignedByte(operand, "Invalid operand");
+            break;
+        case Opcodes.SIPUSH:
+            checkSignedShort(operand, "Invalid operand");
+            break;
+        // case Constants.NEWARRAY:
+        default:
+            if (operand < Opcodes.T_BOOLEAN || operand > Opcodes.T_LONG) {
+                throw new IllegalArgumentException(
+                        "Invalid operand (must be an array type code T_...): "
+                                + operand);
+            }
+        }
+        super.visitIntInsn(opcode, operand);
+        ++insnCount;
+    }
+
+    @Override
+    public void visitVarInsn(final int opcode, final int var) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode(opcode, 2);
+        checkUnsignedShort(var, "Invalid variable index");
+        super.visitVarInsn(opcode, var);
+        ++insnCount;
+    }
+
+    @Override
+    public void visitTypeInsn(final int opcode, final String type) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode(opcode, 3);
+        checkInternalName(type, "type");
+        if (opcode == Opcodes.NEW && type.charAt(0) == '[') {
+            throw new IllegalArgumentException(
+                    "NEW cannot be used to create arrays: " + type);
+        }
+        super.visitTypeInsn(opcode, type);
+        ++insnCount;
+    }
+
+    @Override
+    public void visitFieldInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode(opcode, 4);
+        checkInternalName(owner, "owner");
+        checkUnqualifiedName(version, name, "name");
+        checkDesc(desc, false);
+        super.visitFieldInsn(opcode, owner, name, desc);
+        ++insnCount;
+    }
+
+    @Deprecated
+    @Override
+    public void visitMethodInsn(int opcode, String owner, String name,
+            String desc) {
+        if (api >= Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc,
+                opcode == Opcodes.INVOKEINTERFACE);
+    }
+
+    @Override
+    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;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    private void doVisitMethodInsn(int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode(opcode, 5);
+        if (opcode != Opcodes.INVOKESPECIAL || !"<init>".equals(name)) {
+            checkMethodIdentifier(version, name, "name");
+        }
+        checkInternalName(owner, "owner");
+        checkMethodDesc(desc);
+        if (opcode == Opcodes.INVOKEVIRTUAL && itf) {
+            throw new IllegalArgumentException(
+                    "INVOKEVIRTUAL can't be used with interfaces");
+        }
+        if (opcode == Opcodes.INVOKEINTERFACE && !itf) {
+            throw new IllegalArgumentException(
+                    "INVOKEINTERFACE can't be used with classes");
+        }
+        // Calling super.visitMethodInsn requires to call the correct version
+        // depending on this.api (otherwise infinite loops can occur). To
+        // simplify and to make it easier to automatically remove the backward
+        // compatibility code, we inline the code of the overridden method here.
+        if (mv != null) {
+            mv.visitMethodInsn(opcode, owner, name, desc, itf);
+        }
+        ++insnCount;
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        checkStartCode();
+        checkEndCode();
+        checkMethodIdentifier(version, name, "name");
+        checkMethodDesc(desc);
+        if (bsm.getTag() != Opcodes.H_INVOKESTATIC
+                && bsm.getTag() != Opcodes.H_NEWINVOKESPECIAL) {
+            throw new IllegalArgumentException("invalid handle tag "
+                    + bsm.getTag());
+        }
+        for (int i = 0; i < bsmArgs.length; i++) {
+            checkLDCConstant(bsmArgs[i]);
+        }
+        super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+        ++insnCount;
+    }
+
+    @Override
+    public void visitJumpInsn(final int opcode, final Label label) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode(opcode, 6);
+        checkLabel(label, false, "label");
+        checkNonDebugLabel(label);
+        super.visitJumpInsn(opcode, label);
+        usedLabels.add(label);
+        ++insnCount;
+    }
+
+    @Override
+    public void visitLabel(final Label label) {
+        checkStartCode();
+        checkEndCode();
+        checkLabel(label, false, "label");
+        if (labels.get(label) != null) {
+            throw new IllegalArgumentException("Already visited label");
+        }
+        labels.put(label, new Integer(insnCount));
+        super.visitLabel(label);
+    }
+
+    @Override
+    public void visitLdcInsn(final Object cst) {
+        checkStartCode();
+        checkEndCode();
+        checkLDCConstant(cst);
+        super.visitLdcInsn(cst);
+        ++insnCount;
+    }
+
+    @Override
+    public void visitIincInsn(final int var, final int increment) {
+        checkStartCode();
+        checkEndCode();
+        checkUnsignedShort(var, "Invalid variable index");
+        checkSignedShort(increment, "Invalid increment");
+        super.visitIincInsn(var, increment);
+        ++insnCount;
+    }
+
+    @Override
+    public void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels) {
+        checkStartCode();
+        checkEndCode();
+        if (max < min) {
+            throw new IllegalArgumentException("Max = " + max
+                    + " must be greater than or equal to min = " + min);
+        }
+        checkLabel(dflt, false, "default label");
+        checkNonDebugLabel(dflt);
+        if (labels == null || labels.length != max - min + 1) {
+            throw new IllegalArgumentException(
+                    "There must be max - min + 1 labels");
+        }
+        for (int i = 0; i < labels.length; ++i) {
+            checkLabel(labels[i], false, "label at index " + i);
+            checkNonDebugLabel(labels[i]);
+        }
+        super.visitTableSwitchInsn(min, max, dflt, labels);
+        for (int i = 0; i < labels.length; ++i) {
+            usedLabels.add(labels[i]);
+        }
+        ++insnCount;
+    }
+
+    @Override
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
+        checkEndCode();
+        checkStartCode();
+        checkLabel(dflt, false, "default label");
+        checkNonDebugLabel(dflt);
+        if (keys == null || labels == null || keys.length != labels.length) {
+            throw new IllegalArgumentException(
+                    "There must be the same number of keys and labels");
+        }
+        for (int i = 0; i < labels.length; ++i) {
+            checkLabel(labels[i], false, "label at index " + i);
+            checkNonDebugLabel(labels[i]);
+        }
+        super.visitLookupSwitchInsn(dflt, keys, labels);
+        usedLabels.add(dflt);
+        for (int i = 0; i < labels.length; ++i) {
+            usedLabels.add(labels[i]);
+        }
+        ++insnCount;
+    }
+
+    @Override
+    public void visitMultiANewArrayInsn(final String desc, final int dims) {
+        checkStartCode();
+        checkEndCode();
+        checkDesc(desc, false);
+        if (desc.charAt(0) != '[') {
+            throw new IllegalArgumentException(
+                    "Invalid descriptor (must be an array type descriptor): "
+                            + desc);
+        }
+        if (dims < 1) {
+            throw new IllegalArgumentException(
+                    "Invalid dimensions (must be greater than 0): " + dims);
+        }
+        if (dims > desc.lastIndexOf('[') + 1) {
+            throw new IllegalArgumentException(
+                    "Invalid dimensions (must not be greater than dims(desc)): "
+                            + dims);
+        }
+        super.visitMultiANewArrayInsn(desc, dims);
+        ++insnCount;
+    }
+
+    @Override
+    public AnnotationVisitor visitInsnAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        checkStartCode();
+        checkEndCode();
+        int sort = typeRef >>> 24;
+        if (sort != TypeReference.INSTANCEOF && sort != TypeReference.NEW
+                && sort != TypeReference.CONSTRUCTOR_REFERENCE
+                && sort != TypeReference.METHOD_REFERENCE
+                && sort != TypeReference.CAST
+                && sort != TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+                && sort != TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT
+                && sort != TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+                && sort != TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT) {
+            throw new IllegalArgumentException("Invalid type reference sort 0x"
+                    + Integer.toHexString(sort));
+        }
+        CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+        CheckMethodAdapter.checkDesc(desc, false);
+        return new CheckAnnotationAdapter(super.visitInsnAnnotation(typeRef,
+                typePath, desc, visible));
+    }
+
+    @Override
+    public void visitTryCatchBlock(final Label start, final Label end,
+            final Label handler, final String type) {
+        checkStartCode();
+        checkEndCode();
+        checkLabel(start, false, "start label");
+        checkLabel(end, false, "end label");
+        checkLabel(handler, false, "handler label");
+        checkNonDebugLabel(start);
+        checkNonDebugLabel(end);
+        checkNonDebugLabel(handler);
+        if (labels.get(start) != null || labels.get(end) != null
+                || labels.get(handler) != null) {
+            throw new IllegalStateException(
+                    "Try catch blocks must be visited before their labels");
+        }
+        if (type != null) {
+            checkInternalName(type, "type");
+        }
+        super.visitTryCatchBlock(start, end, handler, type);
+        handlers.add(start);
+        handlers.add(end);
+    }
+
+    @Override
+    public AnnotationVisitor visitTryCatchAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        checkStartCode();
+        checkEndCode();
+        int sort = typeRef >>> 24;
+        if (sort != TypeReference.EXCEPTION_PARAMETER) {
+            throw new IllegalArgumentException("Invalid type reference sort 0x"
+                    + Integer.toHexString(sort));
+        }
+        CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+        CheckMethodAdapter.checkDesc(desc, false);
+        return new CheckAnnotationAdapter(super.visitTryCatchAnnotation(
+                typeRef, typePath, desc, visible));
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
+        checkStartCode();
+        checkEndCode();
+        checkUnqualifiedName(version, name, "name");
+        checkDesc(desc, false);
+        checkLabel(start, true, "start label");
+        checkLabel(end, true, "end label");
+        checkUnsignedShort(index, "Invalid variable index");
+        int s = labels.get(start).intValue();
+        int e = labels.get(end).intValue();
+        if (e < s) {
+            throw new IllegalArgumentException(
+                    "Invalid start and end labels (end must be greater than start)");
+        }
+        super.visitLocalVariable(name, desc, signature, start, end, index);
+    }
+
+    @Override
+    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+            TypePath typePath, Label[] start, Label[] end, int[] index,
+            String desc, boolean visible) {
+        checkStartCode();
+        checkEndCode();
+        int sort = typeRef >>> 24;
+        if (sort != TypeReference.LOCAL_VARIABLE
+                && sort != TypeReference.RESOURCE_VARIABLE) {
+            throw new IllegalArgumentException("Invalid type reference sort 0x"
+                    + Integer.toHexString(sort));
+        }
+        CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+        checkDesc(desc, false);
+        if (start == null || end == null || index == null
+                || end.length != start.length || index.length != start.length) {
+            throw new IllegalArgumentException(
+                    "Invalid start, end and index arrays (must be non null and of identical length");
+        }
+        for (int i = 0; i < start.length; ++i) {
+            checkLabel(start[i], true, "start label");
+            checkLabel(end[i], true, "end label");
+            checkUnsignedShort(index[i], "Invalid variable index");
+            int s = labels.get(start[i]).intValue();
+            int e = labels.get(end[i]).intValue();
+            if (e < s) {
+                throw new IllegalArgumentException(
+                        "Invalid start and end labels (end must be greater than start)");
+            }
+        }
+        return super.visitLocalVariableAnnotation(typeRef, typePath, start,
+                end, index, desc, visible);
+    }
+
+    @Override
+    public void visitLineNumber(final int line, final Label start) {
+        checkStartCode();
+        checkEndCode();
+        checkUnsignedShort(line, "Invalid line number");
+        checkLabel(start, true, "start label");
+        super.visitLineNumber(line, start);
+    }
+
+    @Override
+    public void visitMaxs(final int maxStack, final int maxLocals) {
+        checkStartCode();
+        checkEndCode();
+        endCode = true;
+        for (Label l : usedLabels) {
+            if (labels.get(l) == null) {
+                throw new IllegalStateException("Undefined label used");
+            }
+        }
+        for (int i = 0; i < handlers.size();) {
+            Integer start = labels.get(handlers.get(i++));
+            Integer end = labels.get(handlers.get(i++));
+            if (start == null || end == null) {
+                throw new IllegalStateException(
+                        "Undefined try catch block labels");
+            }
+            if (end.intValue() <= start.intValue()) {
+                throw new IllegalStateException(
+                        "Emty try catch block handler range");
+            }
+        }
+        checkUnsignedShort(maxStack, "Invalid max stack");
+        checkUnsignedShort(maxLocals, "Invalid max locals");
+        super.visitMaxs(maxStack, maxLocals);
+    }
+
+    @Override
+    public void visitEnd() {
+        checkEndMethod();
+        endMethod = true;
+        super.visitEnd();
+    }
+
+    // -------------------------------------------------------------------------
+
+    /**
+     * Checks that the visitCode method has been called.
+     */
+    void checkStartCode() {
+        if (!startCode) {
+            throw new IllegalStateException(
+                    "Cannot visit instructions before visitCode has been called.");
+        }
+    }
+
+    /**
+     * Checks that the visitMaxs method has not been called.
+     */
+    void checkEndCode() {
+        if (endCode) {
+            throw new IllegalStateException(
+                    "Cannot visit instructions after visitMaxs has been called.");
+        }
+    }
+
+    /**
+     * Checks that the visitEnd method has not been called.
+     */
+    void checkEndMethod() {
+        if (endMethod) {
+            throw new IllegalStateException(
+                    "Cannot visit elements after visitEnd has been called.");
+        }
+    }
+
+    /**
+     * Checks a stack frame value.
+     * 
+     * @param value
+     *            the value to be checked.
+     */
+    void checkFrameValue(final Object value) {
+        if (value == Opcodes.TOP || value == Opcodes.INTEGER
+                || value == Opcodes.FLOAT || value == Opcodes.LONG
+                || value == Opcodes.DOUBLE || value == Opcodes.NULL
+                || value == Opcodes.UNINITIALIZED_THIS) {
+            return;
+        }
+        if (value instanceof String) {
+            checkInternalName((String) value, "Invalid stack frame value");
+            return;
+        }
+        if (!(value instanceof Label)) {
+            throw new IllegalArgumentException("Invalid stack frame value: "
+                    + value);
+        } else {
+            usedLabels.add((Label) value);
+        }
+    }
+
+    /**
+     * Checks that the type of the given opcode is equal to the given type.
+     * 
+     * @param opcode
+     *            the opcode to be checked.
+     * @param type
+     *            the expected opcode type.
+     */
+    static void checkOpcode(final int opcode, final int type) {
+        if (opcode < 0 || opcode > 199 || TYPE[opcode] != type) {
+            throw new IllegalArgumentException("Invalid opcode: " + opcode);
+        }
+    }
+
+    /**
+     * Checks that the given value is a signed byte.
+     * 
+     * @param value
+     *            the value to be checked.
+     * @param msg
+     *            an message to be used in case of error.
+     */
+    static void checkSignedByte(final int value, final String msg) {
+        if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
+            throw new IllegalArgumentException(msg
+                    + " (must be a signed byte): " + value);
+        }
+    }
+
+    /**
+     * Checks that the given value is a signed short.
+     * 
+     * @param value
+     *            the value to be checked.
+     * @param msg
+     *            an message to be used in case of error.
+     */
+    static void checkSignedShort(final int value, final String msg) {
+        if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
+            throw new IllegalArgumentException(msg
+                    + " (must be a signed short): " + value);
+        }
+    }
+
+    /**
+     * Checks that the given value is an unsigned short.
+     * 
+     * @param value
+     *            the value to be checked.
+     * @param msg
+     *            an message to be used in case of error.
+     */
+    static void checkUnsignedShort(final int value, final String msg) {
+        if (value < 0 || value > 65535) {
+            throw new IllegalArgumentException(msg
+                    + " (must be an unsigned short): " + value);
+        }
+    }
+
+    /**
+     * Checks that the given value is an {@link Integer}, a{@link Float}, a
+     * {@link Long}, a {@link Double} or a {@link String}.
+     * 
+     * @param cst
+     *            the value to be checked.
+     */
+    static void checkConstant(final Object cst) {
+        if (!(cst instanceof Integer) && !(cst instanceof Float)
+                && !(cst instanceof Long) && !(cst instanceof Double)
+                && !(cst instanceof String)) {
+            throw new IllegalArgumentException("Invalid constant: " + cst);
+        }
+    }
+
+    void checkLDCConstant(final Object cst) {
+        if (cst instanceof Type) {
+            int s = ((Type) cst).getSort();
+            if (s != Type.OBJECT && s != Type.ARRAY && s != Type.METHOD) {
+                throw new IllegalArgumentException("Illegal LDC constant value");
+            }
+            if (s != Type.METHOD && (version & 0xFFFF) < Opcodes.V1_5) {
+                throw new IllegalArgumentException(
+                        "ldc of a constant class requires at least version 1.5");
+            }
+            if (s == Type.METHOD && (version & 0xFFFF) < Opcodes.V1_7) {
+                throw new IllegalArgumentException(
+                        "ldc of a method type requires at least version 1.7");
+            }
+        } else if (cst instanceof Handle) {
+            if ((version & 0xFFFF) < Opcodes.V1_7) {
+                throw new IllegalArgumentException(
+                        "ldc of a handle requires at least version 1.7");
+            }
+            int tag = ((Handle) cst).getTag();
+            if (tag < Opcodes.H_GETFIELD || tag > Opcodes.H_INVOKEINTERFACE) {
+                throw new IllegalArgumentException("invalid handle tag " + tag);
+            }
+        } else {
+            checkConstant(cst);
+        }
+    }
+
+    /**
+     * Checks that the given string is a valid unqualified name.
+     * 
+     * @param version
+     *            the class version.
+     * @param name
+     *            the string to be checked.
+     * @param msg
+     *            a message to be used in case of error.
+     */
+    static void checkUnqualifiedName(int version, final String name,
+            final String msg) {
+        if ((version & 0xFFFF) < Opcodes.V1_5) {
+            checkIdentifier(name, msg);
+        } else {
+            for (int i = 0; i < name.length(); ++i) {
+                if (".;[/".indexOf(name.charAt(i)) != -1) {
+                    throw new IllegalArgumentException("Invalid " + msg
+                            + " (must be a valid unqualified name): " + name);
+                }
+            }
+        }
+    }
+
+    /**
+     * Checks that the given string is a valid Java identifier.
+     * 
+     * @param name
+     *            the string to be checked.
+     * @param msg
+     *            a message to be used in case of error.
+     */
+    static void checkIdentifier(final String name, final String msg) {
+        checkIdentifier(name, 0, -1, msg);
+    }
+
+    /**
+     * Checks that the given substring is a valid Java identifier.
+     * 
+     * @param name
+     *            the string to be checked.
+     * @param start
+     *            index of the first character of the identifier (inclusive).
+     * @param end
+     *            index of the last character of the identifier (exclusive). -1
+     *            is equivalent to <tt>name.length()</tt> if name is not
+     *            <tt>null</tt>.
+     * @param msg
+     *            a message to be used in case of error.
+     */
+    static void checkIdentifier(final String name, final int start,
+            final int end, final String msg) {
+        if (name == null || (end == -1 ? name.length() <= start : end <= start)) {
+            throw new IllegalArgumentException("Invalid " + msg
+                    + " (must not be null or empty)");
+        }
+        if (!Character.isJavaIdentifierStart(name.charAt(start))) {
+            throw new IllegalArgumentException("Invalid " + msg
+                    + " (must be a valid Java identifier): " + name);
+        }
+        int max = end == -1 ? name.length() : end;
+        for (int i = start + 1; i < max; ++i) {
+            if (!Character.isJavaIdentifierPart(name.charAt(i))) {
+                throw new IllegalArgumentException("Invalid " + msg
+                        + " (must be a valid Java identifier): " + name);
+            }
+        }
+    }
+
+    /**
+     * Checks that the given string is a valid Java identifier.
+     * 
+     * @param version
+     *            the class version.
+     * @param name
+     *            the string to be checked.
+     * @param msg
+     *            a message to be used in case of error.
+     */
+    static void checkMethodIdentifier(int version, final String name,
+            final String msg) {
+        if (name == null || name.length() == 0) {
+            throw new IllegalArgumentException("Invalid " + msg
+                    + " (must not be null or empty)");
+        }
+        if ((version & 0xFFFF) >= Opcodes.V1_5) {
+            for (int i = 0; i < name.length(); ++i) {
+                if (".;[/<>".indexOf(name.charAt(i)) != -1) {
+                    throw new IllegalArgumentException("Invalid " + msg
+                            + " (must be a valid unqualified name): " + name);
+                }
+            }
+            return;
+        }
+        if (!Character.isJavaIdentifierStart(name.charAt(0))) {
+            throw new IllegalArgumentException(
+                    "Invalid "
+                            + msg
+                            + " (must be a '<init>', '<clinit>' or a valid Java identifier): "
+                            + name);
+        }
+        for (int i = 1; i < name.length(); ++i) {
+            if (!Character.isJavaIdentifierPart(name.charAt(i))) {
+                throw new IllegalArgumentException(
+                        "Invalid "
+                                + msg
+                                + " (must be '<init>' or '<clinit>' or a valid Java identifier): "
+                                + name);
+            }
+        }
+    }
+
+    /**
+     * Checks that the given string is a valid internal class name.
+     * 
+     * @param name
+     *            the string to be checked.
+     * @param msg
+     *            a message to be used in case of error.
+     */
+    static void checkInternalName(final String name, final String msg) {
+        if (name == null || name.length() == 0) {
+            throw new IllegalArgumentException("Invalid " + msg
+                    + " (must not be null or empty)");
+        }
+        if (name.charAt(0) == '[') {
+            checkDesc(name, false);
+        } else {
+            checkInternalName(name, 0, -1, msg);
+        }
+    }
+
+    /**
+     * Checks that the given substring is a valid internal class name.
+     * 
+     * @param name
+     *            the string to be checked.
+     * @param start
+     *            index of the first character of the identifier (inclusive).
+     * @param end
+     *            index of the last character of the identifier (exclusive). -1
+     *            is equivalent to <tt>name.length()</tt> if name is not
+     *            <tt>null</tt>.
+     * @param msg
+     *            a message to be used in case of error.
+     */
+    static void checkInternalName(final String name, final int start,
+            final int end, final String msg) {
+        int max = end == -1 ? name.length() : end;
+        try {
+            int begin = start;
+            int slash;
+            do {
+                slash = name.indexOf('/', begin + 1);
+                if (slash == -1 || slash > max) {
+                    slash = max;
+                }
+                checkIdentifier(name, begin, slash, null);
+                begin = slash + 1;
+            } while (slash != max);
+        } catch (IllegalArgumentException unused) {
+            throw new IllegalArgumentException(
+                    "Invalid "
+                            + msg
+                            + " (must be a fully qualified class name in internal form): "
+                            + name);
+        }
+    }
+
+    /**
+     * Checks that the given string is a valid type descriptor.
+     * 
+     * @param desc
+     *            the string to be checked.
+     * @param canBeVoid
+     *            <tt>true</tt> if <tt>V</tt> can be considered valid.
+     */
+    static void checkDesc(final String desc, final boolean canBeVoid) {
+        int end = checkDesc(desc, 0, canBeVoid);
+        if (end != desc.length()) {
+            throw new IllegalArgumentException("Invalid descriptor: " + desc);
+        }
+    }
+
+    /**
+     * Checks that a the given substring is a valid type descriptor.
+     * 
+     * @param desc
+     *            the string to be checked.
+     * @param start
+     *            index of the first character of the identifier (inclusive).
+     * @param canBeVoid
+     *            <tt>true</tt> if <tt>V</tt> can be considered valid.
+     * @return the index of the last character of the type decriptor, plus one.
+     */
+    static int checkDesc(final String desc, final int start,
+            final boolean canBeVoid) {
+        if (desc == null || start >= desc.length()) {
+            throw new IllegalArgumentException(
+                    "Invalid type descriptor (must not be null or empty)");
+        }
+        int index;
+        switch (desc.charAt(start)) {
+        case 'V':
+            if (canBeVoid) {
+                return start + 1;
+            } else {
+                throw new IllegalArgumentException("Invalid descriptor: "
+                        + desc);
+            }
+        case 'Z':
+        case 'C':
+        case 'B':
+        case 'S':
+        case 'I':
+        case 'F':
+        case 'J':
+        case 'D':
+            return start + 1;
+        case '[':
+            index = start + 1;
+            while (index < desc.length() && desc.charAt(index) == '[') {
+                ++index;
+            }
+            if (index < desc.length()) {
+                return checkDesc(desc, index, false);
+            } else {
+                throw new IllegalArgumentException("Invalid descriptor: "
+                        + desc);
+            }
+        case 'L':
+            index = desc.indexOf(';', start);
+            if (index == -1 || index - start < 2) {
+                throw new IllegalArgumentException("Invalid descriptor: "
+                        + desc);
+            }
+            try {
+                checkInternalName(desc, start + 1, index, null);
+            } catch (IllegalArgumentException unused) {
+                throw new IllegalArgumentException("Invalid descriptor: "
+                        + desc);
+            }
+            return index + 1;
+        default:
+            throw new IllegalArgumentException("Invalid descriptor: " + desc);
+        }
+    }
+
+    /**
+     * Checks that the given string is a valid method descriptor.
+     * 
+     * @param desc
+     *            the string to be checked.
+     */
+    static void checkMethodDesc(final String desc) {
+        if (desc == null || desc.length() == 0) {
+            throw new IllegalArgumentException(
+                    "Invalid method descriptor (must not be null or empty)");
+        }
+        if (desc.charAt(0) != '(' || desc.length() < 3) {
+            throw new IllegalArgumentException("Invalid descriptor: " + desc);
+        }
+        int start = 1;
+        if (desc.charAt(start) != ')') {
+            do {
+                if (desc.charAt(start) == 'V') {
+                    throw new IllegalArgumentException("Invalid descriptor: "
+                            + desc);
+                }
+                start = checkDesc(desc, start, false);
+            } while (start < desc.length() && desc.charAt(start) != ')');
+        }
+        start = checkDesc(desc, start + 1, true);
+        if (start != desc.length()) {
+            throw new IllegalArgumentException("Invalid descriptor: " + desc);
+        }
+    }
+
+    /**
+     * Checks that the given label is not null. This method can also check that
+     * the label has been visited.
+     * 
+     * @param label
+     *            the label to be checked.
+     * @param checkVisited
+     *            <tt>true</tt> to check that the label has been visited.
+     * @param msg
+     *            a message to be used in case of error.
+     */
+    void checkLabel(final Label label, final boolean checkVisited,
+            final String msg) {
+        if (label == null) {
+            throw new IllegalArgumentException("Invalid " + msg
+                    + " (must not be null)");
+        }
+        if (checkVisited && labels.get(label) == null) {
+            throw new IllegalArgumentException("Invalid " + msg
+                    + " (must be visited first)");
+        }
+    }
+
+    /**
+     * Checks that the given label is not a label used only for debug purposes.
+     * 
+     * @param label
+     *            the label to be checked.
+     */
+    private static void checkNonDebugLabel(final Label label) {
+        Field f = getLabelStatusField();
+        int status = 0;
+        try {
+            status = f == null ? 0 : ((Integer) f.get(label)).intValue();
+        } catch (IllegalAccessException e) {
+            throw new Error("Internal error");
+        }
+        if ((status & 0x01) != 0) {
+            throw new IllegalArgumentException(
+                    "Labels used for debug info cannot be reused for control flow");
+        }
+    }
+
+    /**
+     * Returns the Field object corresponding to the Label.status field.
+     * 
+     * @return the Field object corresponding to the Label.status field.
+     */
+    private static Field getLabelStatusField() {
+        if (labelStatusField == null) {
+            labelStatusField = getLabelField("a");
+            if (labelStatusField == null) {
+                labelStatusField = getLabelField("status");
+            }
+        }
+        return labelStatusField;
+    }
+
+    /**
+     * Returns the field of the Label class whose name is given.
+     * 
+     * @param name
+     *            a field name.
+     * @return the field of the Label class whose name is given, or null.
+     */
+    private static Field getLabelField(final String name) {
+        try {
+            Field f = Label.class.getDeclaredField(name);
+            f.setAccessible(true);
+            return f;
+        } catch (NoSuchFieldException e) {
+            return null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
new file mode 100644
index 0000000..cf1f98b
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
@@ -0,0 +1,330 @@
+/***
+ * 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.util;
+
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
+
+/**
+ * A {@link SignatureVisitor} that checks that its methods are properly used.
+ * 
+ * @author Eric Bruneton
+ */
+public class CheckSignatureAdapter extends SignatureVisitor {
+
+    /**
+     * Type to be used to check class signatures. See
+     * {@link #CheckSignatureAdapter(int, SignatureVisitor)
+     * CheckSignatureAdapter}.
+     */
+    public static final int CLASS_SIGNATURE = 0;
+
+    /**
+     * Type to be used to check method signatures. See
+     * {@link #CheckSignatureAdapter(int, SignatureVisitor)
+     * CheckSignatureAdapter}.
+     */
+    public static final int METHOD_SIGNATURE = 1;
+
+    /**
+     * Type to be used to check type signatures.See
+     * {@link #CheckSignatureAdapter(int, SignatureVisitor)
+     * CheckSignatureAdapter}.
+     */
+    public static final int TYPE_SIGNATURE = 2;
+
+    private static final int EMPTY = 1;
+
+    private static final int FORMAL = 2;
+
+    private static final int BOUND = 4;
+
+    private static final int SUPER = 8;
+
+    private static final int PARAM = 16;
+
+    private static final int RETURN = 32;
+
+    private static final int SIMPLE_TYPE = 64;
+
+    private static final int CLASS_TYPE = 128;
+
+    private static final int END = 256;
+
+    /**
+     * Type of the signature to be checked.
+     */
+    private final int type;
+
+    /**
+     * State of the automaton used to check the order of method calls.
+     */
+    private int state;
+
+    /**
+     * <tt>true</tt> if the checked type signature can be 'V'.
+     */
+    private boolean canBeVoid;
+
+    /**
+     * The visitor to which this adapter must delegate calls. May be
+     * <tt>null</tt>.
+     */
+    private final SignatureVisitor sv;
+
+    /**
+     * Creates a new {@link CheckSignatureAdapter} object. <i>Subclasses must
+     * not use this constructor</i>. Instead, they must use the
+     * {@link #CheckSignatureAdapter(int, int, SignatureVisitor)} version.
+     * 
+     * @param type
+     *            the type of signature to be checked. See
+     *            {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and
+     *            {@link #TYPE_SIGNATURE}.
+     * @param sv
+     *            the visitor to which this adapter must delegate calls. May be
+     *            <tt>null</tt>.
+     */
+    public CheckSignatureAdapter(final int type, final SignatureVisitor sv) {
+        this(Opcodes.ASM5, type, sv);
+    }
+
+    /**
+     * Creates a new {@link CheckSignatureAdapter} object.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param type
+     *            the type of signature to be checked. See
+     *            {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and
+     *            {@link #TYPE_SIGNATURE}.
+     * @param sv
+     *            the visitor to which this adapter must delegate calls. May be
+     *            <tt>null</tt>.
+     */
+    protected CheckSignatureAdapter(final int api, final int type,
+            final SignatureVisitor sv) {
+        super(api);
+        this.type = type;
+        this.state = EMPTY;
+        this.sv = sv;
+    }
+
+    // class and method signatures
+
+    @Override
+    public void visitFormalTypeParameter(final String name) {
+        if (type == TYPE_SIGNATURE
+                || (state != EMPTY && state != FORMAL && state != BOUND)) {
+            throw new IllegalStateException();
+        }
+        CheckMethodAdapter.checkIdentifier(name, "formal type parameter");
+        state = FORMAL;
+        if (sv != null) {
+            sv.visitFormalTypeParameter(name);
+        }
+    }
+
+    @Override
+    public SignatureVisitor visitClassBound() {
+        if (state != FORMAL) {
+            throw new IllegalStateException();
+        }
+        state = BOUND;
+        SignatureVisitor v = sv == null ? null : sv.visitClassBound();
+        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+    }
+
+    @Override
+    public SignatureVisitor visitInterfaceBound() {
+        if (state != FORMAL && state != BOUND) {
+            throw new IllegalArgumentException();
+        }
+        SignatureVisitor v = sv == null ? null : sv.visitInterfaceBound();
+        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+    }
+
+    // class signatures
+
+    @Override
+    public SignatureVisitor visitSuperclass() {
+        if (type != CLASS_SIGNATURE || (state & (EMPTY | FORMAL | BOUND)) == 0) {
+            throw new IllegalArgumentException();
+        }
+        state = SUPER;
+        SignatureVisitor v = sv == null ? null : sv.visitSuperclass();
+        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+    }
+
+    @Override
+    public SignatureVisitor visitInterface() {
+        if (state != SUPER) {
+            throw new IllegalStateException();
+        }
+        SignatureVisitor v = sv == null ? null : sv.visitInterface();
+        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+    }
+
+    // method signatures
+
+    @Override
+    public SignatureVisitor visitParameterType() {
+        if (type != METHOD_SIGNATURE
+                || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) {
+            throw new IllegalArgumentException();
+        }
+        state = PARAM;
+        SignatureVisitor v = sv == null ? null : sv.visitParameterType();
+        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+    }
+
+    @Override
+    public SignatureVisitor visitReturnType() {
+        if (type != METHOD_SIGNATURE
+                || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) {
+            throw new IllegalArgumentException();
+        }
+        state = RETURN;
+        SignatureVisitor v = sv == null ? null : sv.visitReturnType();
+        CheckSignatureAdapter cv = new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+        cv.canBeVoid = true;
+        return cv;
+    }
+
+    @Override
+    public SignatureVisitor visitExceptionType() {
+        if (state != RETURN) {
+            throw new IllegalStateException();
+        }
+        SignatureVisitor v = sv == null ? null : sv.visitExceptionType();
+        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+    }
+
+    // type signatures
+
+    @Override
+    public void visitBaseType(final char descriptor) {
+        if (type != TYPE_SIGNATURE || state != EMPTY) {
+            throw new IllegalStateException();
+        }
+        if (descriptor == 'V') {
+            if (!canBeVoid) {
+                throw new IllegalArgumentException();
+            }
+        } else {
+            if ("ZCBSIFJD".indexOf(descriptor) == -1) {
+                throw new IllegalArgumentException();
+            }
+        }
+        state = SIMPLE_TYPE;
+        if (sv != null) {
+            sv.visitBaseType(descriptor);
+        }
+    }
+
+    @Override
+    public void visitTypeVariable(final String name) {
+        if (type != TYPE_SIGNATURE || state != EMPTY) {
+            throw new IllegalStateException();
+        }
+        CheckMethodAdapter.checkIdentifier(name, "type variable");
+        state = SIMPLE_TYPE;
+        if (sv != null) {
+            sv.visitTypeVariable(name);
+        }
+    }
+
+    @Override
+    public SignatureVisitor visitArrayType() {
+        if (type != TYPE_SIGNATURE || state != EMPTY) {
+            throw new IllegalStateException();
+        }
+        state = SIMPLE_TYPE;
+        SignatureVisitor v = sv == null ? null : sv.visitArrayType();
+        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+    }
+
+    @Override
+    public void visitClassType(final String name) {
+        if (type != TYPE_SIGNATURE || state != EMPTY) {
+            throw new IllegalStateException();
+        }
+        CheckMethodAdapter.checkInternalName(name, "class name");
+        state = CLASS_TYPE;
+        if (sv != null) {
+            sv.visitClassType(name);
+        }
+    }
+
+    @Override
+    public void visitInnerClassType(final String name) {
+        if (state != CLASS_TYPE) {
+            throw new IllegalStateException();
+        }
+        CheckMethodAdapter.checkIdentifier(name, "inner class name");
+        if (sv != null) {
+            sv.visitInnerClassType(name);
+        }
+    }
+
+    @Override
+    public void visitTypeArgument() {
+        if (state != CLASS_TYPE) {
+            throw new IllegalStateException();
+        }
+        if (sv != null) {
+            sv.visitTypeArgument();
+        }
+    }
+
+    @Override
+    public SignatureVisitor visitTypeArgument(final char wildcard) {
+        if (state != CLASS_TYPE) {
+            throw new IllegalStateException();
+        }
+        if ("+-=".indexOf(wildcard) == -1) {
+            throw new IllegalArgumentException();
+        }
+        SignatureVisitor v = sv == null ? null : sv.visitTypeArgument(wildcard);
+        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+    }
+
+    @Override
+    public void visitEnd() {
+        if (state != CLASS_TYPE) {
+            throw new IllegalStateException();
+        }
+        state = END;
+        if (sv != null) {
+            sv.visitEnd();
+        }
+    }
+}


[10/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
index a248cdf..d6c9c90 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
@@ -29,14 +29,19 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
-import org.apache.tapestry5.internal.plastic.asm.*;
-
 import java.util.ArrayList;
 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.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
 /**
  * A node that represents a field.
- *
+ * 
  * @author Eric Bruneton
  */
 public class FieldNode extends FieldVisitor {
@@ -63,8 +68,8 @@ public class FieldNode extends FieldVisitor {
     public String signature;
 
     /**
-     * The field's initial value. This field, which may be <tt>null</tt> if
-     * the field does not have an initial value, must be an {@link Integer}, a
+     * The field's initial value. This field, which may be <tt>null</tt> if the
+     * field does not have an initial value, must be an {@link Integer}, a
      * {@link Float}, a {@link Long}, a {@link Double} or a {@link String}.
      */
     public Object value;
@@ -72,8 +77,8 @@ public class FieldNode extends FieldVisitor {
     /**
      * The runtime visible annotations of this field. 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;
@@ -81,17 +86,35 @@ public class FieldNode extends FieldVisitor {
     /**
      * The runtime invisible annotations of this field. 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 field. 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 field. 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 field. 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;
 
@@ -99,56 +122,60 @@ public class FieldNode extends FieldVisitor {
      * Constructs a new {@link FieldNode}. <i>Subclasses must not use this
      * constructor</i>. Instead, they must use the
      * {@link #FieldNode(int, int, String, String, String, Object)} version.
-     *
-     * @param access the field's access flags (see
-     *        {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This parameter also indicates
-     *        if the field is synthetic and/or deprecated.
-     * @param name the field's name.
-     * @param desc the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type
-     *        Type}).
-     * @param signature the field's signature.
-     * @param value the field's initial value. This parameter, which may be
-     *        <tt>null</tt> if the field does not have an initial value, must be
-     *        an {@link Integer}, a {@link Float}, a {@link Long}, a
-     *        {@link Double} or a {@link String}.
+     * 
+     * @param access
+     *            the field's access flags (see
+     *            {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This parameter also
+     *            indicates if the field is synthetic and/or deprecated.
+     * @param name
+     *            the field's name.
+     * @param desc
+     *            the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type
+     *            Type}).
+     * @param signature
+     *            the field's signature.
+     * @param value
+     *            the field's initial value. This parameter, which may be
+     *            <tt>null</tt> if the field does not have an initial value,
+     *            must be an {@link Integer}, a {@link Float}, a {@link Long}, a
+     *            {@link Double} or a {@link String}.
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
      */
-    public FieldNode(
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final Object value)
-    {
-        this(Opcodes.ASM4, access, name, desc, signature, value);
+    public FieldNode(final int access, final String name, final String desc,
+            final String signature, final Object value) {
+        this(Opcodes.ASM5, access, name, desc, signature, value);
+        if (getClass() != FieldNode.class) {
+            throw new IllegalStateException();
+        }
     }
 
     /**
      * Constructs a new {@link FieldNode}. <i>Subclasses must not use this
-     * constructor</i>. Instead, they must use the
-     * {@link #FieldNode(int, int, String, String, String, Object)} version.
-     *
-     * @param api the ASM API version implemented by this visitor. Must be one
-     *        of {@link Opcodes#ASM4}.
-     * @param access the field's access flags (see
-     *        {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This parameter also indicates
-     *        if the field is synthetic and/or deprecated.
-     * @param name the field's name.
-     * @param desc the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type
-     *        Type}).
-     * @param signature the field's signature.
-     * @param value the field's initial value. This parameter, which may be
-     *        <tt>null</tt> if the field does not have an initial value, must be
-     *        an {@link Integer}, a {@link Float}, a {@link Long}, a
-     *        {@link Double} or a {@link String}.
+     * constructor</i>.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param access
+     *            the field's access flags (see
+     *            {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This parameter also
+     *            indicates if the field is synthetic and/or deprecated.
+     * @param name
+     *            the field's name.
+     * @param desc
+     *            the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type
+     *            Type}).
+     * @param signature
+     *            the field's signature.
+     * @param value
+     *            the field's initial value. This parameter, which may be
+     *            <tt>null</tt> if the field does not have an initial value,
+     *            must be an {@link Integer}, a {@link Float}, a {@link Long}, a
+     *            {@link Double} or a {@link String}.
      */
-    public FieldNode(
-        final int api,
-        final int access,
-        final String name,
-        final String desc,
-        final String signature,
-        final Object value)
-    {
+    public FieldNode(final int api, final int access, final String name,
+            final String desc, final String signature, final Object value) {
         super(api);
         this.access = access;
         this.name = name;
@@ -162,10 +189,8 @@ public class FieldNode extends FieldVisitor {
     // ------------------------------------------------------------------------
 
     @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) {
@@ -182,6 +207,24 @@ public class FieldNode extends FieldVisitor {
     }
 
     @Override
+    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 void visitAttribute(final Attribute attr) {
         if (attrs == null) {
             attrs = new ArrayList<Attribute>(1);
@@ -202,17 +245,29 @@ public class FieldNode extends FieldVisitor {
      * 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();
+            }
+        }
     }
 
     /**
      * Makes the given class visitor visit this field.
-     *
-     * @param cv a class visitor.
+     * 
+     * @param cv
+     *            a class visitor.
      */
     public void accept(final ClassVisitor cv) {
         FieldVisitor fv = cv.visitField(access, name, desc, signature, value);
@@ -230,6 +285,19 @@ public class FieldNode extends FieldVisitor {
             AnnotationNode an = invisibleAnnotations.get(i);
             an.accept(fv.visitAnnotation(an.desc, false));
         }
+        n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
+        for (i = 0; i < n; ++i) {
+            TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+            an.accept(fv.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(fv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+                    false));
+        }
         n = attrs == null ? 0 : attrs.size();
         for (i = 0; i < n; ++i) {
             fv.visitAttribute(attrs.get(i));

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
index c2564e3..8600566 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
@@ -29,14 +29,14 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
-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.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
 /**
  * A node that represents a stack map frame. These nodes are pseudo instruction
  * nodes in order to be inserted in an instruction list. In fact these nodes
@@ -45,18 +45,19 @@ import java.util.Map;
  * the target of a jump instruction, or that starts an exception handler block.
  * The stack map frame types must describe the values of the local variables and
  * of the operand stack elements <i>just before</i> <b>i</b> is executed. <br>
- * <br> (*) this is mandatory only for classes whose version is greater than or
- * equal to {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#V1_6 V1_6}.
- *
+ * <br>
+ * (*) this is mandatory only for classes whose version is greater than or equal
+ * to {@link Opcodes#V1_6 V1_6}.
+ * 
  * @author Eric Bruneton
  */
 public class FrameNode extends AbstractInsnNode {
 
     /**
-     * The type of this frame. Must be {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_NEW} for expanded
-     * frames, or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_FULL}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_APPEND},
-     * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_CHOP}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_SAME} or
-     * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_APPEND}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_SAME1} for compressed frames.
+     * The type of this frame. Must be {@link Opcodes#F_NEW} for expanded
+     * frames, or {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
+     * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
+     * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
      */
     public int type;
 
@@ -82,49 +83,49 @@ public class FrameNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link FrameNode}.
-     *
-     * @param type the type of this frame. Must be {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_NEW} for
-     *        expanded frames, or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_FULL},
-     *        {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_APPEND}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_CHOP},
-     *        {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_SAME} or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_APPEND},
-     *        {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_SAME1} for compressed frames.
-     * @param nLocal number of local variables of this stack map frame.
-     * @param local the types of the local variables of this stack map frame.
-     *        Elements of this list can be Integer, String or LabelNode objects
-     *        (for primitive, reference and uninitialized types respectively -
-     *        see {@link MethodVisitor}).
-     * @param nStack number of operand stack elements of this stack map frame.
-     * @param stack the types of the operand stack elements of this stack map
-     *        frame. Elements of this list can be Integer, String or LabelNode
-     *        objects (for primitive, reference and uninitialized types
-     *        respectively - see {@link MethodVisitor}).
+     * 
+     * @param type
+     *            the type of this frame. Must be {@link Opcodes#F_NEW} for
+     *            expanded frames, or {@link Opcodes#F_FULL},
+     *            {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP},
+     *            {@link Opcodes#F_SAME} or {@link Opcodes#F_APPEND},
+     *            {@link Opcodes#F_SAME1} for compressed frames.
+     * @param nLocal
+     *            number of local variables of this stack map frame.
+     * @param local
+     *            the types of the local variables of this stack map frame.
+     *            Elements of this list can be Integer, String or LabelNode
+     *            objects (for primitive, reference and uninitialized types
+     *            respectively - see {@link MethodVisitor}).
+     * @param nStack
+     *            number of operand stack elements of this stack map frame.
+     * @param stack
+     *            the types of the operand stack elements of this stack map
+     *            frame. Elements of this list can be Integer, String or
+     *            LabelNode objects (for primitive, reference and uninitialized
+     *            types respectively - see {@link MethodVisitor}).
      */
-    public FrameNode(
-        final int type,
-        final int nLocal,
-        final Object[] local,
-        final int nStack,
-        final Object[] stack)
-    {
+    public FrameNode(final int type, final int nLocal, final Object[] local,
+            final int nStack, final Object[] stack) {
         super(-1);
         this.type = type;
         switch (type) {
-            case Opcodes.F_NEW:
-            case Opcodes.F_FULL:
-                this.local = asList(nLocal, local);
-                this.stack = asList(nStack, stack);
-                break;
-            case Opcodes.F_APPEND:
-                this.local = asList(nLocal, local);
-                break;
-            case Opcodes.F_CHOP:
-                this.local = Arrays.asList(new Object[nLocal]);
-                break;
-            case Opcodes.F_SAME:
-                break;
-            case Opcodes.F_SAME1:
-                this.stack = asList(1, stack);
-                break;
+        case Opcodes.F_NEW:
+        case Opcodes.F_FULL:
+            this.local = asList(nLocal, local);
+            this.stack = asList(nStack, stack);
+            break;
+        case Opcodes.F_APPEND:
+            this.local = asList(nLocal, local);
+            break;
+        case Opcodes.F_CHOP:
+            this.local = Arrays.asList(new Object[nLocal]);
+            break;
+        case Opcodes.F_SAME:
+            break;
+        case Opcodes.F_SAME1:
+            this.stack = asList(1, stack);
+            break;
         }
     }
 
@@ -135,32 +136,30 @@ public class FrameNode extends AbstractInsnNode {
 
     /**
      * Makes the given visitor visit this stack map frame.
-     *
-     * @param mv a method visitor.
+     * 
+     * @param mv
+     *            a method visitor.
      */
     @Override
     public void accept(final MethodVisitor mv) {
         switch (type) {
-            case Opcodes.F_NEW:
-            case Opcodes.F_FULL:
-                mv.visitFrame(type,
-                        local.size(),
-                        asArray(local),
-                        stack.size(),
-                        asArray(stack));
-                break;
-            case Opcodes.F_APPEND:
-                mv.visitFrame(type, local.size(), asArray(local), 0, null);
-                break;
-            case Opcodes.F_CHOP:
-                mv.visitFrame(type, local.size(), null, 0, null);
-                break;
-            case Opcodes.F_SAME:
-                mv.visitFrame(type, 0, null, 0, null);
-                break;
-            case Opcodes.F_SAME1:
-                mv.visitFrame(type, 0, null, 1, asArray(stack));
-                break;
+        case Opcodes.F_NEW:
+        case Opcodes.F_FULL:
+            mv.visitFrame(type, local.size(), asArray(local), stack.size(),
+                    asArray(stack));
+            break;
+        case Opcodes.F_APPEND:
+            mv.visitFrame(type, local.size(), asArray(local), 0, null);
+            break;
+        case Opcodes.F_CHOP:
+            mv.visitFrame(type, local.size(), null, 0, null);
+            break;
+        case Opcodes.F_SAME:
+            mv.visitFrame(type, 0, null, 0, null);
+            break;
+        case Opcodes.F_SAME1:
+            mv.visitFrame(type, 0, null, 1, asArray(stack));
+            break;
         }
     }
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java
index c1b13dd..729dd3e 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.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 an IINC instruction.
- *
+ * 
  * @author Eric Bruneton
  */
 public class IincInsnNode extends AbstractInsnNode {
@@ -53,9 +53,11 @@ public class IincInsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link IincInsnNode}.
-     *
-     * @param var index of the local variable to be incremented.
-     * @param incr increment amount to increment the local variable by.
+     * 
+     * @param var
+     *            index of the local variable to be incremented.
+     * @param incr
+     *            increment amount to increment the local variable by.
      */
     public IincInsnNode(final int var, final int incr) {
         super(Opcodes.IINC);
@@ -71,10 +73,11 @@ public class IincInsnNode extends AbstractInsnNode {
     @Override
     public void accept(final MethodVisitor mv) {
         mv.visitIincInsn(var, incr);
+        acceptAnnotations(mv);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new IincInsnNode(var, incr);
+        return new IincInsnNode(var, incr).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/InnerClassNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java
index bfc16b0..877430f 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java
@@ -33,7 +33,7 @@ import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
 
 /**
  * A node that represents an inner class.
- *
+ * 
  * @author Eric Bruneton
  */
 public class InnerClassNode {
@@ -46,8 +46,8 @@ public class InnerClassNode {
 
     /**
      * The internal name of the class to which the inner class belongs (see
-     * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). May
-     * be <tt>null</tt>.
+     * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). May be
+     * <tt>null</tt>.
      */
     public String outerName;
 
@@ -65,25 +65,24 @@ public class InnerClassNode {
 
     /**
      * Constructs a new {@link InnerClassNode}.
-     *
-     * @param name the internal name of an inner class (see
-     *        {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}).
-     * @param outerName the internal name of the class to which the inner class
-     *        belongs (see
-     *        {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}).
-     *        May be <tt>null</tt>.
-     * @param innerName the (simple) name of the inner class inside its
-     *        enclosing class. May be <tt>null</tt> for anonymous inner
-     *        classes.
-     * @param access the access flags of the inner class as originally declared
-     *        in the enclosing class.
+     * 
+     * @param name
+     *            the internal name of an inner class (see
+     *            {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+     *            getInternalName}).
+     * @param outerName
+     *            the internal name of the class to which the inner class
+     *            belongs (see {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+     *            getInternalName}). May be <tt>null</tt>.
+     * @param innerName
+     *            the (simple) name of the inner class inside its enclosing
+     *            class. May be <tt>null</tt> for anonymous inner classes.
+     * @param access
+     *            the access flags of the inner class as originally declared in
+     *            the enclosing class.
      */
-    public InnerClassNode(
-        final String name,
-        final String outerName,
-        final String innerName,
-        final int access)
-    {
+    public InnerClassNode(final String name, final String outerName,
+            final String innerName, final int access) {
         this.name = name;
         this.outerName = outerName;
         this.innerName = innerName;
@@ -92,8 +91,9 @@ public class InnerClassNode {
 
     /**
      * Makes the given class visitor visit this inner class.
-     *
-     * @param cv a class visitor.
+     * 
+     * @param cv
+     *            a class visitor.
      */
     public void accept(final ClassVisitor cv) {
         cv.visitInnerClass(name, outerName, innerName, access);

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
index c4fa98a..8eaaf68 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
@@ -29,11 +29,11 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
 import java.util.ListIterator;
 import java.util.NoSuchElementException;
 
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
 /**
  * A doubly linked list of {@link AbstractInsnNode} objects. <i>This
  * implementation is not thread safe</i>.
@@ -63,7 +63,7 @@ public class InsnList {
 
     /**
      * Returns the number of instructions in this list.
-     *
+     * 
      * @return the number of instructions in this list.
      */
     public int size() {
@@ -72,9 +72,9 @@ public class InsnList {
 
     /**
      * Returns the first instruction in this list.
-     *
-     * @return the first instruction in this list, or <tt>null</tt> if the
-     *         list is empty.
+     * 
+     * @return the first instruction in this list, or <tt>null</tt> if the list
+     *         is empty.
      */
     public AbstractInsnNode getFirst() {
         return first;
@@ -82,7 +82,7 @@ public class InsnList {
 
     /**
      * Returns the last instruction in this list.
-     *
+     * 
      * @return the last instruction in this list, or <tt>null</tt> if the list
      *         is empty.
      */
@@ -95,10 +95,12 @@ public class InsnList {
      * of the instructions in this list to avoid scanning the whole list each
      * time it is called. Once the cache is built, this method run in constant
      * time. This cache is invalidated by all the methods that modify the list.
-     *
-     * @param index the index of the instruction that must be returned.
+     * 
+     * @param index
+     *            the index of the instruction that must be returned.
      * @return the instruction whose index is given.
-     * @throws IndexOutOfBoundsException if (index < 0 || index >= size()).
+     * @throws IndexOutOfBoundsException
+     *             if (index &lt; 0 || index &gt;= size()).
      */
     public AbstractInsnNode get(final int index) {
         if (index < 0 || index >= size) {
@@ -111,11 +113,12 @@ public class InsnList {
     }
 
     /**
-     * Returns <tt>true</tt> if the given instruction belongs to this list.
-     * This method always scans the instructions of this list until it finds the
+     * Returns <tt>true</tt> if the given instruction belongs to this list. This
+     * method always scans the instructions of this list until it finds the
      * given instruction or reaches the end of the list.
-     *
-     * @param insn an instruction.
+     * 
+     * @param insn
+     *            an instruction.
      * @return <tt>true</tt> if the given instruction belongs to this list.
      */
     public boolean contains(final AbstractInsnNode insn) {
@@ -132,8 +135,9 @@ public class InsnList {
      * list each time it is called. Once the cache is built, this method run in
      * constant time. The cache is invalidated by all the methods that modify
      * the list.
-     *
-     * @param insn an instruction <i>of this list</i>.
+     * 
+     * @param insn
+     *            an instruction <i>of this list</i>.
      * @return the index of the given instruction in this list. <i>The result of
      *         this method is undefined if the given instruction does not belong
      *         to this list</i>. Use {@link #contains contains} to test if an
@@ -148,8 +152,9 @@ public class InsnList {
 
     /**
      * Makes the given visitor visit all of the instructions in this list.
-     *
-     * @param mv the method visitor that must visit the instructions.
+     * 
+     * @param mv
+     *            the method visitor that must visit the instructions.
      */
     public void accept(final MethodVisitor mv) {
         AbstractInsnNode insn = first;
@@ -161,7 +166,7 @@ public class InsnList {
 
     /**
      * Returns an iterator over the instructions in this list.
-     *
+     * 
      * @return an iterator over the instructions in this list.
      */
     public ListIterator<AbstractInsnNode> iterator() {
@@ -170,7 +175,7 @@ public class InsnList {
 
     /**
      * Returns an iterator over the instructions in this list.
-     *
+     * 
      * @return an iterator over the instructions in this list.
      */
     @SuppressWarnings("unchecked")
@@ -180,7 +185,7 @@ public class InsnList {
 
     /**
      * Returns an array containing all of the instructions in this list.
-     *
+     * 
      * @return an array containing all of the instructions in this list.
      */
     public AbstractInsnNode[] toArray() {
@@ -197,10 +202,12 @@ public class InsnList {
 
     /**
      * Replaces an instruction of this list with another instruction.
-     *
-     * @param location an instruction <i>of this list</i>.
-     * @param insn another instruction, <i>which must not belong to any
-     *        {@link InsnList}</i>.
+     * 
+     * @param location
+     *            an instruction <i>of this list</i>.
+     * @param insn
+     *            another instruction, <i>which must not belong to any
+     *            {@link InsnList}</i>.
      */
     public void set(final AbstractInsnNode location, final AbstractInsnNode insn) {
         AbstractInsnNode next = location.next;
@@ -231,9 +238,10 @@ public class InsnList {
 
     /**
      * Adds the given instruction to the end of this list.
-     *
-     * @param insn an instruction, <i>which must not belong to any
-     *        {@link InsnList}</i>.
+     * 
+     * @param insn
+     *            an instruction, <i>which must not belong to any
+     *            {@link InsnList}</i>.
      */
     public void add(final AbstractInsnNode insn) {
         ++size;
@@ -251,9 +259,10 @@ public class InsnList {
 
     /**
      * Adds the given instructions to the end of this list.
-     *
-     * @param insns an instruction list, which is cleared during the process.
-     *        This list must be different from 'this'.
+     * 
+     * @param insns
+     *            an instruction list, which is cleared during the process. This
+     *            list must be different from 'this'.
      */
     public void add(final InsnList insns) {
         if (insns.size == 0) {
@@ -275,9 +284,10 @@ public class InsnList {
 
     /**
      * Inserts the given instruction at the begining of this list.
-     *
-     * @param insn an instruction, <i>which must not belong to any
-     *        {@link InsnList}</i>.
+     * 
+     * @param insn
+     *            an instruction, <i>which must not belong to any
+     *            {@link InsnList}</i>.
      */
     public void insert(final AbstractInsnNode insn) {
         ++size;
@@ -295,9 +305,10 @@ public class InsnList {
 
     /**
      * Inserts the given instructions at the begining of this list.
-     *
-     * @param insns an instruction list, which is cleared during the process.
-     *        This list must be different from 'this'.
+     * 
+     * @param insns
+     *            an instruction list, which is cleared during the process. This
+     *            list must be different from 'this'.
      */
     public void insert(final InsnList insns) {
         if (insns.size == 0) {
@@ -319,13 +330,16 @@ public class InsnList {
 
     /**
      * Inserts the given instruction after the specified instruction.
-     *
-     * @param location an instruction <i>of this list</i> after which insn must be
-     *        inserted.
-     * @param insn the instruction to be inserted, <i>which must not belong to
-     *        any {@link InsnList}</i>.
+     * 
+     * @param location
+     *            an instruction <i>of this list</i> after which insn must be
+     *            inserted.
+     * @param insn
+     *            the instruction to be inserted, <i>which must not belong to
+     *            any {@link InsnList}</i>.
      */
-    public void insert(final AbstractInsnNode location, final AbstractInsnNode insn) {
+    public void insert(final AbstractInsnNode location,
+            final AbstractInsnNode insn) {
         ++size;
         AbstractInsnNode next = location.next;
         if (next == null) {
@@ -342,11 +356,13 @@ public class InsnList {
 
     /**
      * Inserts the given instructions after the specified instruction.
-     *
-     * @param location an instruction <i>of this list</i> after which the
-     *        instructions must be inserted.
-     * @param insns the instruction list to be inserted, which is cleared during
-     *        the process. This list must be different from 'this'.
+     * 
+     * @param location
+     *            an instruction <i>of this list</i> after which the
+     *            instructions must be inserted.
+     * @param insns
+     *            the instruction list to be inserted, which is cleared during
+     *            the process. This list must be different from 'this'.
      */
     public void insert(final AbstractInsnNode location, final InsnList insns) {
         if (insns.size == 0) {
@@ -370,13 +386,16 @@ public class InsnList {
 
     /**
      * Inserts the given instruction before the specified instruction.
-     *
-     * @param location an instruction <i>of this list</i> before which insn must be
-     *        inserted.
-     * @param insn the instruction to be inserted, <i>which must not belong to
-     *        any {@link InsnList}</i>.
+     * 
+     * @param location
+     *            an instruction <i>of this list</i> before which insn must be
+     *            inserted.
+     * @param insn
+     *            the instruction to be inserted, <i>which must not belong to
+     *            any {@link InsnList}</i>.
      */
-    public void insertBefore(final AbstractInsnNode location, final AbstractInsnNode insn) {
+    public void insertBefore(final AbstractInsnNode location,
+            final AbstractInsnNode insn) {
         ++size;
         AbstractInsnNode prev = location.prev;
         if (prev == null) {
@@ -393,38 +412,40 @@ public class InsnList {
 
     /**
      * Inserts the given instructions before the specified instruction.
-     *
-     * @param location  an instruction <i>of this list</i> before which the instructions
-     *        must be inserted.
-     * @param insns the instruction list to be inserted, which is cleared during
-     *        the process. This list must be different from 'this'.
+     * 
+     * @param location
+     *            an instruction <i>of this list</i> before which the
+     *            instructions must be inserted.
+     * @param insns
+     *            the instruction list to be inserted, which is cleared during
+     *            the process. This list must be different from 'this'.
      */
-    public void insertBefore(final AbstractInsnNode location, final InsnList insns) {
+    public void insertBefore(final AbstractInsnNode location,
+            final InsnList insns) {
         if (insns.size == 0) {
             return;
         }
         size += insns.size;
         AbstractInsnNode ifirst = insns.first;
         AbstractInsnNode ilast = insns.last;
-        AbstractInsnNode prev = location .prev;
+        AbstractInsnNode prev = location.prev;
         if (prev == null) {
             first = ifirst;
         } else {
             prev.next = ifirst;
         }
-        location .prev = ilast;
-        ilast.next = location ;
+        location.prev = ilast;
+        ilast.next = location;
         ifirst.prev = prev;
         cache = null;
         insns.removeAll(false);
     }
 
-
-
     /**
      * Removes the given instruction from this list.
-     *
-     * @param insn the instruction <i>of this list</i> that must be removed.
+     * 
+     * @param insn
+     *            the instruction <i>of this list</i> that must be removed.
      */
     public void remove(final AbstractInsnNode insn) {
         --size;
@@ -455,9 +476,10 @@ public class InsnList {
 
     /**
      * Removes all of the instructions of this list.
-     *
-     * @param mark if the instructions must be marked as no longer belonging to
-     *        any {@link InsnList}.
+     * 
+     * @param mark
+     *            if the instructions must be marked as no longer belonging to
+     *            any {@link InsnList}.
      */
     void removeAll(final boolean mark) {
         if (mark) {
@@ -499,14 +521,16 @@ public class InsnList {
     }
 
     // this class is not generified because it will create bridges
-    private final class InsnListIterator implements ListIterator/*<AbstractInsnNode>*/ {
+    private final class InsnListIterator implements ListIterator {
 
         AbstractInsnNode next;
 
         AbstractInsnNode prev;
 
+        AbstractInsnNode remove;
+
         InsnListIterator(int index) {
-            if(index==size()) {
+            if (index == size()) {
                 next = null;
                 prev = getLast();
             } else {
@@ -526,12 +550,22 @@ public class InsnList {
             AbstractInsnNode result = next;
             prev = result;
             next = result.next;
+            remove = result;
             return result;
         }
 
         public void remove() {
-            InsnList.this.remove(prev);
-            prev = prev.prev;
+            if (remove != null) {
+                if (remove == next) {
+                    next = next.next;
+                } else {
+                    prev = prev.prev;
+                }
+                InsnList.this.remove(remove);
+                remove = null;
+            } else {
+                throw new IllegalStateException();
+            }
         }
 
         public boolean hasPrevious() {
@@ -542,6 +576,7 @@ public class InsnList {
             AbstractInsnNode result = prev;
             next = result;
             prev = result.prev;
+            remove = result;
             return result;
         }
 
@@ -568,6 +603,7 @@ public class InsnList {
         public void add(Object o) {
             InsnList.this.insertBefore(next, (AbstractInsnNode) o);
             prev = (AbstractInsnNode) o;
+            remove = null;
         }
 
         public void set(Object o) {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
index 6abed41..7eb2359 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
@@ -29,34 +29,36 @@
  */
 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 zero operand instruction.
- *
+ * 
  * @author Eric Bruneton
  */
 public class InsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link InsnNode}.
-     *
-     * @param opcode the opcode of the instruction to be constructed. This
-     *        opcode must be NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1,
-     *        ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1,
-     *        FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD,
-     *        FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE,
-     *        FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2,
-     *        DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP, IADD, LADD,
-     *        FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV,
-     *        LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG,
-     *        ISHL, LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR,
-     *        LXOR, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F,
-     *        I2B, I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN,
-     *        FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW,
-     *        MONITORENTER, or MONITOREXIT.
+     * 
+     * @param opcode
+     *            the opcode of the instruction to be constructed. This opcode
+     *            must be NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1,
+     *            ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1,
+     *            FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD,
+     *            LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD,
+     *            IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE,
+     *            SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1,
+     *            DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB,
+     *            IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM,
+     *            FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR,
+     *            IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D,
+     *            L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S,
+     *            LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN,
+     *            DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER,
+     *            or MONITOREXIT.
      */
     public InsnNode(final int opcode) {
         super(opcode);
@@ -69,16 +71,18 @@ public class InsnNode extends AbstractInsnNode {
 
     /**
      * Makes the given visitor visit this instruction.
-     *
-     * @param mv a method visitor.
+     * 
+     * @param mv
+     *            a method visitor.
      */
     @Override
     public void accept(final MethodVisitor mv) {
         mv.visitInsn(opcode);
+        acceptAnnotations(mv);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new InsnNode(opcode);
+        return new InsnNode(opcode).cloneAnnotations(this);
     }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
index 03c0d54..5b0c351 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
@@ -29,13 +29,13 @@
  */
 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 an instruction with a single int operand.
- *
+ * 
  * @author Eric Bruneton
  */
 public class IntInsnNode extends AbstractInsnNode {
@@ -47,10 +47,12 @@ public class IntInsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link IntInsnNode}.
-     *
-     * @param opcode the opcode of the instruction to be constructed. This
-     *        opcode must be BIPUSH, SIPUSH or NEWARRAY.
-     * @param operand the operand of the instruction to be constructed.
+     * 
+     * @param opcode
+     *            the opcode of the instruction to be constructed. This opcode
+     *            must be BIPUSH, SIPUSH or NEWARRAY.
+     * @param operand
+     *            the operand of the instruction to be constructed.
      */
     public IntInsnNode(final int opcode, final int operand) {
         super(opcode);
@@ -59,9 +61,10 @@ public class IntInsnNode extends AbstractInsnNode {
 
     /**
      * Sets the opcode of this instruction.
-     *
-     * @param opcode the new instruction opcode. This opcode must be BIPUSH,
-     *        SIPUSH or NEWARRAY.
+     * 
+     * @param opcode
+     *            the new instruction opcode. This opcode must be BIPUSH, SIPUSH
+     *            or NEWARRAY.
      */
     public void setOpcode(final int opcode) {
         this.opcode = opcode;
@@ -75,10 +78,11 @@ public class IntInsnNode extends AbstractInsnNode {
     @Override
     public void accept(final MethodVisitor mv) {
         mv.visitIntInsn(opcode, operand);
+        acceptAnnotations(mv);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new IntInsnNode(opcode, operand);
+        return new IntInsnNode(opcode, operand).cloneAnnotations(this);
     }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
index d67b72f..2578768 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
@@ -29,15 +29,15 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
+import java.util.Map;
+
 import org.apache.tapestry5.internal.plastic.asm.Handle;
 import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
 import org.apache.tapestry5.internal.plastic.asm.Opcodes;
 
-import java.util.Map;
-
 /**
  * A node that represents an invokedynamic instruction.
- *
+ * 
  * @author Remi Forax
  */
 public class InvokeDynamicInsnNode extends AbstractInsnNode {
@@ -64,18 +64,18 @@ public class InvokeDynamicInsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link InvokeDynamicInsnNode}.
-     *
-     * @param name invokedynamic name.
-     * @param desc invokedynamic descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
-     * @param bsm the bootstrap method.
-     * @param bsmArgs the boostrap constant arguments.
+     * 
+     * @param name
+     *            invokedynamic name.
+     * @param desc
+     *            invokedynamic descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+     * @param bsm
+     *            the bootstrap method.
+     * @param bsmArgs
+     *            the boostrap constant arguments.
      */
-    public InvokeDynamicInsnNode(
-        final String name,
-        final String desc,
-        final Handle bsm,
-        final Object... bsmArgs)
-    {
+    public InvokeDynamicInsnNode(final String name, final String desc,
+            final Handle bsm, final Object... bsmArgs) {
         super(Opcodes.INVOKEDYNAMIC);
         this.name = name;
         this.desc = desc;
@@ -91,10 +91,12 @@ public class InvokeDynamicInsnNode extends AbstractInsnNode {
     @Override
     public void accept(final MethodVisitor mv) {
         mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+        acceptAnnotations(mv);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs);
+        return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs)
+                .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/JumpInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.java
index d0011a2..386c900 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.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 jump instruction. A jump instruction is an
  * instruction that may jump to another instruction.
- *
+ * 
  * @author Eric Bruneton
  */
 public class JumpInsnNode extends AbstractInsnNode {
@@ -49,14 +49,16 @@ public class JumpInsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link JumpInsnNode}.
-     *
-     * @param opcode the opcode of the type instruction to be constructed. This
-     *        opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
-     *        IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ,
-     *        IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
-     * @param label the operand of the instruction to be constructed. This
-     *        operand is a label that designates the instruction to which the
-     *        jump instruction may jump.
+     * 
+     * @param opcode
+     *            the opcode of the type instruction to be constructed. This
+     *            opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
+     *            IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
+     *            IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
+     * @param label
+     *            the operand of the instruction to be constructed. This operand
+     *            is a label that designates the instruction to which the jump
+     *            instruction may jump.
      */
     public JumpInsnNode(final int opcode, final LabelNode label) {
         super(opcode);
@@ -65,11 +67,12 @@ public class JumpInsnNode extends AbstractInsnNode {
 
     /**
      * Sets the opcode of this instruction.
-     *
-     * @param opcode the new instruction opcode. This opcode must be IFEQ, IFNE,
-     *        IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT,
-     *        IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO, JSR,
-     *        IFNULL or IFNONNULL.
+     * 
+     * @param opcode
+     *            the new instruction opcode. This opcode must be IFEQ, IFNE,
+     *            IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT,
+     *            IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO,
+     *            JSR, IFNULL or IFNONNULL.
      */
     public void setOpcode(final int opcode) {
         this.opcode = opcode;
@@ -83,10 +86,12 @@ public class JumpInsnNode extends AbstractInsnNode {
     @Override
     public void accept(final MethodVisitor mv) {
         mv.visitJumpInsn(opcode, label.getLabel());
+        acceptAnnotations(mv);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new JumpInsnNode(opcode, clone(label, labels));
+        return new JumpInsnNode(opcode, clone(label, labels))
+                .cloneAnnotations(this);
     }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
index a21f0d0..39c08ef 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
@@ -29,11 +29,11 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.tree;
 
+import java.util.Map;
+
 import org.apache.tapestry5.internal.plastic.asm.Label;
 import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
 
-import java.util.Map;
-
 /**
  * An {@link AbstractInsnNode} that encapsulates a {@link Label}.
  */

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java
index 82748cb..e048e74 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.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 an LDC instruction.
- *
+ * 
  * @author Eric Bruneton
  */
 public class LdcInsnNode extends AbstractInsnNode {
@@ -50,10 +50,11 @@ public class LdcInsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link LdcInsnNode}.
-     *
-     * @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} or a {@link String}.
+     * 
+     * @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} or a {@link String}.
      */
     public LdcInsnNode(final Object cst) {
         super(Opcodes.LDC);
@@ -68,10 +69,11 @@ public class LdcInsnNode extends AbstractInsnNode {
     @Override
     public void accept(final MethodVisitor mv) {
         mv.visitLdcInsn(cst);
+        acceptAnnotations(mv);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new LdcInsnNode(cst);
+        return new LdcInsnNode(cst).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/LineNumberNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.java
index fe4d39b..c475ee8 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.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 line number declaration. These nodes are pseudo
  * instruction nodes in order to be inserted in an instruction list.
- *
+ * 
  * @author Eric Bruneton
  */
 public class LineNumberNode extends AbstractInsnNode {
@@ -54,10 +54,12 @@ public class LineNumberNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link LineNumberNode}.
-     *
-     * @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.
+     * 
+     * @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.
      */
     public LineNumberNode(final int line, final LabelNode start) {
         super(-1);

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java
new file mode 100644
index 0000000..27f6e09
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java
@@ -0,0 +1,157 @@
+/***
+ * 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 java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+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.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+
+/**
+ * A node that represents a type annotation on a local or resource variable.
+ * 
+ * @author Eric Bruneton
+ */
+public class LocalVariableAnnotationNode extends TypeAnnotationNode {
+
+    /**
+     * The fist instructions corresponding to the continuous ranges that make
+     * the scope of this local variable (inclusive). Must not be <tt>null</tt>.
+     */
+    public List<LabelNode> start;
+
+    /**
+     * The last instructions corresponding to the continuous ranges that make
+     * the scope of this local variable (exclusive). This list must have the
+     * same size as the 'start' list. Must not be <tt>null</tt>.
+     */
+    public List<LabelNode> end;
+
+    /**
+     * The local variable's index in each range. This list must have the same
+     * size as the 'start' list. Must not be <tt>null</tt>.
+     */
+    public List<Integer> index;
+
+    /**
+     * Constructs a new {@link LocalVariableAnnotationNode}. <i>Subclasses must
+     * not use this constructor</i>. Instead, they must use the
+     * {@link #LocalVariableAnnotationNode(int, TypePath, LabelNode[], LabelNode[], int[], 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 start
+     *            the fist instructions corresponding to the continuous ranges
+     *            that make the scope of this local variable (inclusive).
+     * @param end
+     *            the last instructions corresponding to the continuous ranges
+     *            that make the scope of this local variable (exclusive). This
+     *            array must have the same size as the 'start' array.
+     * @param index
+     *            the local variable's index in each range. This array must have
+     *            the same size as the 'start' array.
+     * @param desc
+     *            the class descriptor of the annotation class.
+     */
+    public LocalVariableAnnotationNode(int typeRef, TypePath typePath,
+            LabelNode[] start, LabelNode[] end, int[] index, String desc) {
+        this(Opcodes.ASM5, typeRef, typePath, start, end, index, desc);
+    }
+
+    /**
+     * Constructs a new {@link LocalVariableAnnotationNode}.
+     * 
+     * @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 start
+     *            the fist instructions corresponding to the continuous ranges
+     *            that make the scope of this local variable (inclusive).
+     * @param end
+     *            the last instructions corresponding to the continuous ranges
+     *            that make the scope of this local variable (exclusive). This
+     *            array must have the same size as the 'start' array.
+     * @param index
+     *            the local variable's index in each range. This array must have
+     *            the same size as the 'start' array.
+     * @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 LocalVariableAnnotationNode(int api, int typeRef, TypePath typePath,
+            LabelNode[] start, LabelNode[] end, int[] index, String desc) {
+        super(api, typeRef, typePath, desc);
+        this.start = new ArrayList<LabelNode>(start.length);
+        this.start.addAll(Arrays.asList(start));
+        this.end = new ArrayList<LabelNode>(end.length);
+        this.end.addAll(Arrays.asList(end));
+        this.index = new ArrayList<Integer>(index.length);
+        for (int i : index) {
+            this.index.add(i);
+        }
+    }
+
+    /**
+     * Makes the given visitor visit this type annotation.
+     * 
+     * @param mv
+     *            the visitor that must visit this annotation.
+     * @param visible
+     *            <tt>true</tt> if the annotation is visible at runtime.
+     */
+    public void accept(final MethodVisitor mv, boolean visible) {
+        Label[] start = new Label[this.start.size()];
+        Label[] end = new Label[this.end.size()];
+        int[] index = new int[this.index.size()];
+        for (int i = 0; i < start.length; ++i) {
+            start[i] = this.start.get(i).getLabel();
+            end[i] = this.end.get(i).getLabel();
+            index[i] = this.index.get(i);
+        }
+        accept(mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
+                index, desc, true));
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
index 8494414..775a6e8 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
@@ -33,7 +33,7 @@ import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
 
 /**
  * A node that represents a local variable declaration.
- *
+ * 
  * @author Eric Bruneton
  */
 public class LocalVariableNode {
@@ -72,25 +72,25 @@ public class LocalVariableNode {
 
     /**
      * Constructs a new {@link LocalVariableNode}.
-     *
-     * @param name the name of a local variable.
-     * @param desc the type descriptor of this local variable.
-     * @param signature the signature of this local variable. May be
-     *        <tt>null</tt>.
-     * @param start the first instruction corresponding to the scope of this
-     *        local variable (inclusive).
-     * @param end the last instruction corresponding to the scope of this local
-     *        variable (exclusive).
-     * @param index the local variable's index.
+     * 
+     * @param name
+     *            the name of a local variable.
+     * @param desc
+     *            the type descriptor of this local variable.
+     * @param signature
+     *            the signature of this local variable. May be <tt>null</tt>.
+     * @param start
+     *            the first instruction corresponding to the scope of this local
+     *            variable (inclusive).
+     * @param end
+     *            the last instruction corresponding to the scope of this local
+     *            variable (exclusive).
+     * @param index
+     *            the local variable's index.
      */
-    public LocalVariableNode(
-        final String name,
-        final String desc,
-        final String signature,
-        final LabelNode start,
-        final LabelNode end,
-        final int index)
-    {
+    public LocalVariableNode(final String name, final String desc,
+            final String signature, final LabelNode start, final LabelNode end,
+            final int index) {
         this.name = name;
         this.desc = desc;
         this.signature = signature;
@@ -101,15 +101,12 @@ public class LocalVariableNode {
 
     /**
      * Makes the given visitor visit this local variable declaration.
-     *
-     * @param mv a method visitor.
+     * 
+     * @param mv
+     *            a method visitor.
      */
     public void accept(final MethodVisitor mv) {
-        mv.visitLocalVariable(name,
-                desc,
-                signature,
-                start.getLabel(),
-                end.getLabel(),
-                index);
+        mv.visitLocalVariable(name, desc, signature, start.getLabel(),
+                end.getLabel(), index);
     }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java
index 5beca30..af635d7 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.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 LOOKUPSWITCH instruction.
- *
+ * 
  * @author Eric Bruneton
  */
 public class LookupSwitchInsnNode extends AbstractInsnNode {
@@ -63,21 +63,22 @@ public class LookupSwitchInsnNode extends AbstractInsnNode {
 
     /**
      * Constructs a new {@link LookupSwitchInsnNode}.
-     *
-     * @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.
+     * 
+     * @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.
      */
-    public LookupSwitchInsnNode(
-        final LabelNode dflt,
-        final int[] keys,
-        final LabelNode[] labels)
-    {
+    public LookupSwitchInsnNode(final LabelNode dflt, final int[] keys,
+            final LabelNode[] labels) {
         super(Opcodes.LOOKUPSWITCH);
         this.dflt = dflt;
         this.keys = new ArrayList<Integer>(keys == null ? 0 : keys.length);
-        this.labels = new ArrayList<LabelNode>(labels == null ? 0 : labels.length);
+        this.labels = new ArrayList<LabelNode>(labels == null ? 0
+                : labels.length);
         if (keys != null) {
             for (int i = 0; i < keys.length; ++i) {
                 this.keys.add(new Integer(keys[i]));
@@ -104,6 +105,7 @@ public class LookupSwitchInsnNode extends AbstractInsnNode {
             labels[i] = this.labels.get(i).getLabel();
         }
         mv.visitLookupSwitchInsn(dflt.getLabel(), keys, labels);
+        acceptAnnotations(mv);
     }
 
     @Override
@@ -111,6 +113,6 @@ public class LookupSwitchInsnNode extends AbstractInsnNode {
         LookupSwitchInsnNode clone = new LookupSwitchInsnNode(clone(dflt,
                 labels), null, clone(this.labels, labels));
         clone.keys.addAll(keys);
-        return clone;
+        return clone.cloneAnnotations(this);
     }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
index f87234c..5d0c730 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
@@ -29,14 +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;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
 /**
  * A node that represents a method instruction. A method instruction is an
  * instruction that invokes a method.
- *
+ * 
  * @author Eric Bruneton
  */
 public class MethodInsnNode extends AbstractInsnNode {
@@ -58,33 +59,65 @@ public class MethodInsnNode extends AbstractInsnNode {
     public String desc;
 
     /**
+     * If the method's owner class if an interface.
+     */
+    public boolean itf;
+
+    /**
+     * Constructs a new {@link MethodInsnNode}.
+     * 
+     * @param opcode
+     *            the opcode of the type instruction to be constructed. This
+     *            opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+     *            INVOKEINTERFACE.
+     * @param owner
+     *            the internal name of the method's owner class (see
+     *            {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+     *            getInternalName}).
+     * @param name
+     *            the method's name.
+     * @param desc
+     *            the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+     */
+    @Deprecated
+    public MethodInsnNode(final int opcode, final String owner,
+            final String name, final String desc) {
+        this(opcode, owner, name, desc, opcode == Opcodes.INVOKEINTERFACE);
+    }
+
+    /**
      * Constructs a new {@link MethodInsnNode}.
-     *
-     * @param opcode the opcode of the type instruction to be constructed. This
-     *        opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
-     *        INVOKEINTERFACE.
-     * @param owner the internal name of the method's owner class (see
-     *        {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}).
-     * @param name the method's name.
-     * @param desc the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+     * 
+     * @param opcode
+     *            the opcode of the type instruction to be constructed. This
+     *            opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+     *            INVOKEINTERFACE.
+     * @param owner
+     *            the internal name of the method's owner class (see
+     *            {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+     *            getInternalName}).
+     * @param name
+     *            the method's name.
+     * @param desc
+     *            the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+     * @param itf
+     *            if the method's owner class is an interface.
      */
-    public MethodInsnNode(
-        final int opcode,
-        final String owner,
-        final String name,
-        final String desc)
-    {
+    public MethodInsnNode(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
         super(opcode);
         this.owner = owner;
         this.name = name;
         this.desc = desc;
+        this.itf = itf;
     }
 
     /**
      * Sets the opcode of this instruction.
-     *
-     * @param opcode the new instruction opcode. This opcode must be
-     *        INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
+     * 
+     * @param opcode
+     *            the new instruction opcode. This opcode must be INVOKEVIRTUAL,
+     *            INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
      */
     public void setOpcode(final int opcode) {
         this.opcode = opcode;
@@ -97,11 +130,11 @@ public class MethodInsnNode extends AbstractInsnNode {
 
     @Override
     public void accept(final MethodVisitor mv) {
-        mv.visitMethodInsn(opcode, owner, name, desc);
+        mv.visitMethodInsn(opcode, owner, name, desc, itf);
     }
 
     @Override
     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
-        return new MethodInsnNode(opcode, owner, name, desc);
+        return new MethodInsnNode(opcode, owner, name, desc, itf);
     }
 }
\ No newline at end of file


[08/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java
new file mode 100644
index 0000000..0656c65
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java
@@ -0,0 +1,358 @@
+/***
+ * 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.List;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+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.FieldInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.IntInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.InvokeDynamicInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LdcInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MultiANewArrayInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TypeInsnNode;
+
+/**
+ * An {@link Interpreter} for {@link BasicValue} values.
+ * 
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class BasicInterpreter extends Interpreter<BasicValue> implements
+        Opcodes {
+
+    public BasicInterpreter() {
+        super(ASM5);
+    }
+
+    protected BasicInterpreter(final int api) {
+        super(api);
+    }
+
+    @Override
+    public BasicValue newValue(final Type type) {
+        if (type == null) {
+            return BasicValue.UNINITIALIZED_VALUE;
+        }
+        switch (type.getSort()) {
+        case Type.VOID:
+            return null;
+        case Type.BOOLEAN:
+        case Type.CHAR:
+        case Type.BYTE:
+        case Type.SHORT:
+        case Type.INT:
+            return BasicValue.INT_VALUE;
+        case Type.FLOAT:
+            return BasicValue.FLOAT_VALUE;
+        case Type.LONG:
+            return BasicValue.LONG_VALUE;
+        case Type.DOUBLE:
+            return BasicValue.DOUBLE_VALUE;
+        case Type.ARRAY:
+        case Type.OBJECT:
+            return BasicValue.REFERENCE_VALUE;
+        default:
+            throw new Error("Internal error");
+        }
+    }
+
+    @Override
+    public BasicValue newOperation(final AbstractInsnNode insn)
+            throws AnalyzerException {
+        switch (insn.getOpcode()) {
+        case ACONST_NULL:
+            return newValue(Type.getObjectType("null"));
+        case ICONST_M1:
+        case ICONST_0:
+        case ICONST_1:
+        case ICONST_2:
+        case ICONST_3:
+        case ICONST_4:
+        case ICONST_5:
+            return BasicValue.INT_VALUE;
+        case LCONST_0:
+        case LCONST_1:
+            return BasicValue.LONG_VALUE;
+        case FCONST_0:
+        case FCONST_1:
+        case FCONST_2:
+            return BasicValue.FLOAT_VALUE;
+        case DCONST_0:
+        case DCONST_1:
+            return BasicValue.DOUBLE_VALUE;
+        case BIPUSH:
+        case SIPUSH:
+            return BasicValue.INT_VALUE;
+        case LDC:
+            Object cst = ((LdcInsnNode) insn).cst;
+            if (cst instanceof Integer) {
+                return BasicValue.INT_VALUE;
+            } else if (cst instanceof Float) {
+                return BasicValue.FLOAT_VALUE;
+            } else if (cst instanceof Long) {
+                return BasicValue.LONG_VALUE;
+            } else if (cst instanceof Double) {
+                return BasicValue.DOUBLE_VALUE;
+            } else if (cst instanceof String) {
+                return newValue(Type.getObjectType("java/lang/String"));
+            } else if (cst instanceof Type) {
+                int sort = ((Type) cst).getSort();
+                if (sort == Type.OBJECT || sort == Type.ARRAY) {
+                    return newValue(Type.getObjectType("java/lang/Class"));
+                } else if (sort == Type.METHOD) {
+                    return newValue(Type
+                            .getObjectType("java/lang/invoke/MethodType"));
+                } else {
+                    throw new IllegalArgumentException("Illegal LDC constant "
+                            + cst);
+                }
+            } else if (cst instanceof Handle) {
+                return newValue(Type
+                        .getObjectType("java/lang/invoke/MethodHandle"));
+            } else {
+                throw new IllegalArgumentException("Illegal LDC constant "
+                        + cst);
+            }
+        case JSR:
+            return BasicValue.RETURNADDRESS_VALUE;
+        case GETSTATIC:
+            return newValue(Type.getType(((FieldInsnNode) insn).desc));
+        case NEW:
+            return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
+        default:
+            throw new Error("Internal error.");
+        }
+    }
+
+    @Override
+    public BasicValue copyOperation(final AbstractInsnNode insn,
+            final BasicValue value) throws AnalyzerException {
+        return value;
+    }
+
+    @Override
+    public BasicValue unaryOperation(final AbstractInsnNode insn,
+            final BasicValue value) throws AnalyzerException {
+        switch (insn.getOpcode()) {
+        case INEG:
+        case IINC:
+        case L2I:
+        case F2I:
+        case D2I:
+        case I2B:
+        case I2C:
+        case I2S:
+            return BasicValue.INT_VALUE;
+        case FNEG:
+        case I2F:
+        case L2F:
+        case D2F:
+            return BasicValue.FLOAT_VALUE;
+        case LNEG:
+        case I2L:
+        case F2L:
+        case D2L:
+            return BasicValue.LONG_VALUE;
+        case DNEG:
+        case I2D:
+        case L2D:
+        case F2D:
+            return BasicValue.DOUBLE_VALUE;
+        case IFEQ:
+        case IFNE:
+        case IFLT:
+        case IFGE:
+        case IFGT:
+        case IFLE:
+        case TABLESWITCH:
+        case LOOKUPSWITCH:
+        case IRETURN:
+        case LRETURN:
+        case FRETURN:
+        case DRETURN:
+        case ARETURN:
+        case PUTSTATIC:
+            return null;
+        case GETFIELD:
+            return newValue(Type.getType(((FieldInsnNode) insn).desc));
+        case NEWARRAY:
+            switch (((IntInsnNode) insn).operand) {
+            case T_BOOLEAN:
+                return newValue(Type.getType("[Z"));
+            case T_CHAR:
+                return newValue(Type.getType("[C"));
+            case T_BYTE:
+                return newValue(Type.getType("[B"));
+            case T_SHORT:
+                return newValue(Type.getType("[S"));
+            case T_INT:
+                return newValue(Type.getType("[I"));
+            case T_FLOAT:
+                return newValue(Type.getType("[F"));
+            case T_DOUBLE:
+                return newValue(Type.getType("[D"));
+            case T_LONG:
+                return newValue(Type.getType("[J"));
+            default:
+                throw new AnalyzerException(insn, "Invalid array type");
+            }
+        case ANEWARRAY:
+            String desc = ((TypeInsnNode) insn).desc;
+            return newValue(Type.getType("[" + Type.getObjectType(desc)));
+        case ARRAYLENGTH:
+            return BasicValue.INT_VALUE;
+        case ATHROW:
+            return null;
+        case CHECKCAST:
+            desc = ((TypeInsnNode) insn).desc;
+            return newValue(Type.getObjectType(desc));
+        case INSTANCEOF:
+            return BasicValue.INT_VALUE;
+        case MONITORENTER:
+        case MONITOREXIT:
+        case IFNULL:
+        case IFNONNULL:
+            return null;
+        default:
+            throw new Error("Internal error.");
+        }
+    }
+
+    @Override
+    public BasicValue binaryOperation(final AbstractInsnNode insn,
+            final BasicValue value1, final BasicValue value2)
+            throws AnalyzerException {
+        switch (insn.getOpcode()) {
+        case IALOAD:
+        case BALOAD:
+        case CALOAD:
+        case SALOAD:
+        case IADD:
+        case ISUB:
+        case IMUL:
+        case IDIV:
+        case IREM:
+        case ISHL:
+        case ISHR:
+        case IUSHR:
+        case IAND:
+        case IOR:
+        case IXOR:
+            return BasicValue.INT_VALUE;
+        case FALOAD:
+        case FADD:
+        case FSUB:
+        case FMUL:
+        case FDIV:
+        case FREM:
+            return BasicValue.FLOAT_VALUE;
+        case LALOAD:
+        case LADD:
+        case LSUB:
+        case LMUL:
+        case LDIV:
+        case LREM:
+        case LSHL:
+        case LSHR:
+        case LUSHR:
+        case LAND:
+        case LOR:
+        case LXOR:
+            return BasicValue.LONG_VALUE;
+        case DALOAD:
+        case DADD:
+        case DSUB:
+        case DMUL:
+        case DDIV:
+        case DREM:
+            return BasicValue.DOUBLE_VALUE;
+        case AALOAD:
+            return BasicValue.REFERENCE_VALUE;
+        case LCMP:
+        case FCMPL:
+        case FCMPG:
+        case DCMPL:
+        case DCMPG:
+            return BasicValue.INT_VALUE;
+        case IF_ICMPEQ:
+        case IF_ICMPNE:
+        case IF_ICMPLT:
+        case IF_ICMPGE:
+        case IF_ICMPGT:
+        case IF_ICMPLE:
+        case IF_ACMPEQ:
+        case IF_ACMPNE:
+        case PUTFIELD:
+            return null;
+        default:
+            throw new Error("Internal error.");
+        }
+    }
+
+    @Override
+    public BasicValue ternaryOperation(final AbstractInsnNode insn,
+            final BasicValue value1, final BasicValue value2,
+            final BasicValue value3) throws AnalyzerException {
+        return null;
+    }
+
+    @Override
+    public BasicValue naryOperation(final AbstractInsnNode insn,
+            final List<? extends BasicValue> values) throws AnalyzerException {
+        int opcode = insn.getOpcode();
+        if (opcode == MULTIANEWARRAY) {
+            return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
+        } else if (opcode == INVOKEDYNAMIC) {
+            return newValue(Type
+                    .getReturnType(((InvokeDynamicInsnNode) insn).desc));
+        } else {
+            return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
+        }
+    }
+
+    @Override
+    public void returnOperation(final AbstractInsnNode insn,
+            final BasicValue value, final BasicValue expected)
+            throws AnalyzerException {
+    }
+
+    @Override
+    public BasicValue merge(final BasicValue v, final BasicValue w) {
+        if (!v.equals(w)) {
+            return BasicValue.UNINITIALIZED_VALUE;
+        }
+        return v;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java
new file mode 100644
index 0000000..44b0704
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java
@@ -0,0 +1,111 @@
+/***
+ * 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.Type;
+
+/**
+ * A {@link Value} that is represented by its type in a seven types type system.
+ * This type system distinguishes the UNINITIALZED, INT, FLOAT, LONG, DOUBLE,
+ * REFERENCE and RETURNADDRESS types.
+ * 
+ * @author Eric Bruneton
+ */
+public class BasicValue implements Value {
+
+    public static final BasicValue UNINITIALIZED_VALUE = new BasicValue(null);
+
+    public static final BasicValue INT_VALUE = new BasicValue(Type.INT_TYPE);
+
+    public static final BasicValue FLOAT_VALUE = new BasicValue(Type.FLOAT_TYPE);
+
+    public static final BasicValue LONG_VALUE = new BasicValue(Type.LONG_TYPE);
+
+    public static final BasicValue DOUBLE_VALUE = new BasicValue(
+            Type.DOUBLE_TYPE);
+
+    public static final BasicValue REFERENCE_VALUE = new BasicValue(
+            Type.getObjectType("java/lang/Object"));
+
+    public static final BasicValue RETURNADDRESS_VALUE = new BasicValue(
+            Type.VOID_TYPE);
+
+    private final Type type;
+
+    public BasicValue(final Type type) {
+        this.type = type;
+    }
+
+    public Type getType() {
+        return type;
+    }
+
+    public int getSize() {
+        return type == Type.LONG_TYPE || type == Type.DOUBLE_TYPE ? 2 : 1;
+    }
+
+    public boolean isReference() {
+        return type != null
+                && (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY);
+    }
+
+    @Override
+    public boolean equals(final Object value) {
+        if (value == this) {
+            return true;
+        } else if (value instanceof BasicValue) {
+            if (type == null) {
+                return ((BasicValue) value).type == null;
+            } else {
+                return type.equals(((BasicValue) value).type);
+            }
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return type == null ? 0 : type.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        if (this == UNINITIALIZED_VALUE) {
+            return ".";
+        } else if (this == RETURNADDRESS_VALUE) {
+            return "A";
+        } else if (this == REFERENCE_VALUE) {
+            return "R";
+        } else {
+            return type.getDescriptor();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java
new file mode 100644
index 0000000..50f4a84
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java
@@ -0,0 +1,433 @@
+/***
+ * 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.List;
+
+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.FieldInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.InvokeDynamicInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodInsnNode;
+
+/**
+ * An extended {@link BasicInterpreter} that checks that bytecode instructions
+ * are correctly used.
+ * 
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class BasicVerifier extends BasicInterpreter {
+
+    public BasicVerifier() {
+        super(ASM5);
+    }
+
+    protected BasicVerifier(final int api) {
+        super(api);
+    }
+
+    @Override
+    public BasicValue copyOperation(final AbstractInsnNode insn,
+            final BasicValue value) throws AnalyzerException {
+        Value expected;
+        switch (insn.getOpcode()) {
+        case ILOAD:
+        case ISTORE:
+            expected = BasicValue.INT_VALUE;
+            break;
+        case FLOAD:
+        case FSTORE:
+            expected = BasicValue.FLOAT_VALUE;
+            break;
+        case LLOAD:
+        case LSTORE:
+            expected = BasicValue.LONG_VALUE;
+            break;
+        case DLOAD:
+        case DSTORE:
+            expected = BasicValue.DOUBLE_VALUE;
+            break;
+        case ALOAD:
+            if (!value.isReference()) {
+                throw new AnalyzerException(insn, null, "an object reference",
+                        value);
+            }
+            return value;
+        case ASTORE:
+            if (!value.isReference()
+                    && !BasicValue.RETURNADDRESS_VALUE.equals(value)) {
+                throw new AnalyzerException(insn, null,
+                        "an object reference or a return address", value);
+            }
+            return value;
+        default:
+            return value;
+        }
+        if (!expected.equals(value)) {
+            throw new AnalyzerException(insn, null, expected, value);
+        }
+        return value;
+    }
+
+    @Override
+    public BasicValue unaryOperation(final AbstractInsnNode insn,
+            final BasicValue value) throws AnalyzerException {
+        BasicValue expected;
+        switch (insn.getOpcode()) {
+        case INEG:
+        case IINC:
+        case I2F:
+        case I2L:
+        case I2D:
+        case I2B:
+        case I2C:
+        case I2S:
+        case IFEQ:
+        case IFNE:
+        case IFLT:
+        case IFGE:
+        case IFGT:
+        case IFLE:
+        case TABLESWITCH:
+        case LOOKUPSWITCH:
+        case IRETURN:
+        case NEWARRAY:
+        case ANEWARRAY:
+            expected = BasicValue.INT_VALUE;
+            break;
+        case FNEG:
+        case F2I:
+        case F2L:
+        case F2D:
+        case FRETURN:
+            expected = BasicValue.FLOAT_VALUE;
+            break;
+        case LNEG:
+        case L2I:
+        case L2F:
+        case L2D:
+        case LRETURN:
+            expected = BasicValue.LONG_VALUE;
+            break;
+        case DNEG:
+        case D2I:
+        case D2F:
+        case D2L:
+        case DRETURN:
+            expected = BasicValue.DOUBLE_VALUE;
+            break;
+        case GETFIELD:
+            expected = newValue(Type
+                    .getObjectType(((FieldInsnNode) insn).owner));
+            break;
+        case CHECKCAST:
+            if (!value.isReference()) {
+                throw new AnalyzerException(insn, null, "an object reference",
+                        value);
+            }
+            return super.unaryOperation(insn, value);
+        case ARRAYLENGTH:
+            if (!isArrayValue(value)) {
+                throw new AnalyzerException(insn, null, "an array reference",
+                        value);
+            }
+            return super.unaryOperation(insn, value);
+        case ARETURN:
+        case ATHROW:
+        case INSTANCEOF:
+        case MONITORENTER:
+        case MONITOREXIT:
+        case IFNULL:
+        case IFNONNULL:
+            if (!value.isReference()) {
+                throw new AnalyzerException(insn, null, "an object reference",
+                        value);
+            }
+            return super.unaryOperation(insn, value);
+        case PUTSTATIC:
+            expected = newValue(Type.getType(((FieldInsnNode) insn).desc));
+            break;
+        default:
+            throw new Error("Internal error.");
+        }
+        if (!isSubTypeOf(value, expected)) {
+            throw new AnalyzerException(insn, null, expected, value);
+        }
+        return super.unaryOperation(insn, value);
+    }
+
+    @Override
+    public BasicValue binaryOperation(final AbstractInsnNode insn,
+            final BasicValue value1, final BasicValue value2)
+            throws AnalyzerException {
+        BasicValue expected1;
+        BasicValue expected2;
+        switch (insn.getOpcode()) {
+        case IALOAD:
+            expected1 = newValue(Type.getType("[I"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case BALOAD:
+            if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
+                expected1 = newValue(Type.getType("[Z"));
+            } else {
+                expected1 = newValue(Type.getType("[B"));
+            }
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case CALOAD:
+            expected1 = newValue(Type.getType("[C"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case SALOAD:
+            expected1 = newValue(Type.getType("[S"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case LALOAD:
+            expected1 = newValue(Type.getType("[J"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case FALOAD:
+            expected1 = newValue(Type.getType("[F"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case DALOAD:
+            expected1 = newValue(Type.getType("[D"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case AALOAD:
+            expected1 = newValue(Type.getType("[Ljava/lang/Object;"));
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case IADD:
+        case ISUB:
+        case IMUL:
+        case IDIV:
+        case IREM:
+        case ISHL:
+        case ISHR:
+        case IUSHR:
+        case IAND:
+        case IOR:
+        case IXOR:
+        case IF_ICMPEQ:
+        case IF_ICMPNE:
+        case IF_ICMPLT:
+        case IF_ICMPGE:
+        case IF_ICMPGT:
+        case IF_ICMPLE:
+            expected1 = BasicValue.INT_VALUE;
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case FADD:
+        case FSUB:
+        case FMUL:
+        case FDIV:
+        case FREM:
+        case FCMPL:
+        case FCMPG:
+            expected1 = BasicValue.FLOAT_VALUE;
+            expected2 = BasicValue.FLOAT_VALUE;
+            break;
+        case LADD:
+        case LSUB:
+        case LMUL:
+        case LDIV:
+        case LREM:
+        case LAND:
+        case LOR:
+        case LXOR:
+        case LCMP:
+            expected1 = BasicValue.LONG_VALUE;
+            expected2 = BasicValue.LONG_VALUE;
+            break;
+        case LSHL:
+        case LSHR:
+        case LUSHR:
+            expected1 = BasicValue.LONG_VALUE;
+            expected2 = BasicValue.INT_VALUE;
+            break;
+        case DADD:
+        case DSUB:
+        case DMUL:
+        case DDIV:
+        case DREM:
+        case DCMPL:
+        case DCMPG:
+            expected1 = BasicValue.DOUBLE_VALUE;
+            expected2 = BasicValue.DOUBLE_VALUE;
+            break;
+        case IF_ACMPEQ:
+        case IF_ACMPNE:
+            expected1 = BasicValue.REFERENCE_VALUE;
+            expected2 = BasicValue.REFERENCE_VALUE;
+            break;
+        case PUTFIELD:
+            FieldInsnNode fin = (FieldInsnNode) insn;
+            expected1 = newValue(Type.getObjectType(fin.owner));
+            expected2 = newValue(Type.getType(fin.desc));
+            break;
+        default:
+            throw new Error("Internal error.");
+        }
+        if (!isSubTypeOf(value1, expected1)) {
+            throw new AnalyzerException(insn, "First argument", expected1,
+                    value1);
+        } else if (!isSubTypeOf(value2, expected2)) {
+            throw new AnalyzerException(insn, "Second argument", expected2,
+                    value2);
+        }
+        if (insn.getOpcode() == AALOAD) {
+            return getElementValue(value1);
+        } else {
+            return super.binaryOperation(insn, value1, value2);
+        }
+    }
+
+    @Override
+    public BasicValue ternaryOperation(final AbstractInsnNode insn,
+            final BasicValue value1, final BasicValue value2,
+            final BasicValue value3) throws AnalyzerException {
+        BasicValue expected1;
+        BasicValue expected3;
+        switch (insn.getOpcode()) {
+        case IASTORE:
+            expected1 = newValue(Type.getType("[I"));
+            expected3 = BasicValue.INT_VALUE;
+            break;
+        case BASTORE:
+            if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
+                expected1 = newValue(Type.getType("[Z"));
+            } else {
+                expected1 = newValue(Type.getType("[B"));
+            }
+            expected3 = BasicValue.INT_VALUE;
+            break;
+        case CASTORE:
+            expected1 = newValue(Type.getType("[C"));
+            expected3 = BasicValue.INT_VALUE;
+            break;
+        case SASTORE:
+            expected1 = newValue(Type.getType("[S"));
+            expected3 = BasicValue.INT_VALUE;
+            break;
+        case LASTORE:
+            expected1 = newValue(Type.getType("[J"));
+            expected3 = BasicValue.LONG_VALUE;
+            break;
+        case FASTORE:
+            expected1 = newValue(Type.getType("[F"));
+            expected3 = BasicValue.FLOAT_VALUE;
+            break;
+        case DASTORE:
+            expected1 = newValue(Type.getType("[D"));
+            expected3 = BasicValue.DOUBLE_VALUE;
+            break;
+        case AASTORE:
+            expected1 = value1;
+            expected3 = BasicValue.REFERENCE_VALUE;
+            break;
+        default:
+            throw new Error("Internal error.");
+        }
+        if (!isSubTypeOf(value1, expected1)) {
+            throw new AnalyzerException(insn, "First argument", "a "
+                    + expected1 + " array reference", value1);
+        } else if (!BasicValue.INT_VALUE.equals(value2)) {
+            throw new AnalyzerException(insn, "Second argument",
+                    BasicValue.INT_VALUE, value2);
+        } else if (!isSubTypeOf(value3, expected3)) {
+            throw new AnalyzerException(insn, "Third argument", expected3,
+                    value3);
+        }
+        return null;
+    }
+
+    @Override
+    public BasicValue naryOperation(final AbstractInsnNode insn,
+            final List<? extends BasicValue> values) throws AnalyzerException {
+        int opcode = insn.getOpcode();
+        if (opcode == MULTIANEWARRAY) {
+            for (int i = 0; i < values.size(); ++i) {
+                if (!BasicValue.INT_VALUE.equals(values.get(i))) {
+                    throw new AnalyzerException(insn, null,
+                            BasicValue.INT_VALUE, values.get(i));
+                }
+            }
+        } else {
+            int i = 0;
+            int j = 0;
+            if (opcode != INVOKESTATIC && opcode != INVOKEDYNAMIC) {
+                Type owner = Type.getObjectType(((MethodInsnNode) insn).owner);
+                if (!isSubTypeOf(values.get(i++), newValue(owner))) {
+                    throw new AnalyzerException(insn, "Method owner",
+                            newValue(owner), values.get(0));
+                }
+            }
+            String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc
+                    : ((MethodInsnNode) insn).desc;
+            Type[] args = Type.getArgumentTypes(desc);
+            while (i < values.size()) {
+                BasicValue expected = newValue(args[j++]);
+                BasicValue encountered = values.get(i++);
+                if (!isSubTypeOf(encountered, expected)) {
+                    throw new AnalyzerException(insn, "Argument " + j,
+                            expected, encountered);
+                }
+            }
+        }
+        return super.naryOperation(insn, values);
+    }
+
+    @Override
+    public void returnOperation(final AbstractInsnNode insn,
+            final BasicValue value, final BasicValue expected)
+            throws AnalyzerException {
+        if (!isSubTypeOf(value, expected)) {
+            throw new AnalyzerException(insn, "Incompatible return type",
+                    expected, value);
+        }
+    }
+
+    protected boolean isArrayValue(final BasicValue value) {
+        return value.isReference();
+    }
+
+    protected BasicValue getElementValue(final BasicValue objectArrayValue)
+            throws AnalyzerException {
+        return BasicValue.REFERENCE_VALUE;
+    }
+
+    protected boolean isSubTypeOf(final BasicValue value,
+            final BasicValue expected) {
+        return value.equals(expected);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java
new file mode 100644
index 0000000..fdbb0a9
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java
@@ -0,0 +1,738 @@
+/***
+ * 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.List;
+
+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.InvokeDynamicInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MultiANewArrayInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.VarInsnNode;
+
+/**
+ * A symbolic execution stack frame. A stack frame contains a set of local
+ * variable slots, and an operand stack. Warning: long and double values are
+ * represented by <i>two</i> slots in local variables, and by <i>one</i> slot in
+ * the operand stack.
+ * 
+ * @param <V>
+ *            type of the Value used for the analysis.
+ * 
+ * @author Eric Bruneton
+ */
+public class Frame<V extends Value> {
+
+    /**
+     * The expected return type of the analyzed method, or <tt>null</tt> if the
+     * method returns void.
+     */
+    private V returnValue;
+
+    /**
+     * The local variables and operand stack of this frame.
+     */
+    private V[] values;
+
+    /**
+     * The number of local variables of this frame.
+     */
+    private int locals;
+
+    /**
+     * The number of elements in the operand stack.
+     */
+    private int top;
+
+    /**
+     * 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.
+     */
+    public Frame(final int nLocals, final int nStack) {
+        this.values = (V[]) new Value[nLocals + nStack];
+        this.locals = nLocals;
+    }
+
+    /**
+     * Constructs a new frame that is identical to the given frame.
+     * 
+     * @param src
+     *            a frame.
+     */
+    public Frame(final Frame<? extends V> src) {
+        this(src.locals, src.values.length - src.locals);
+        init(src);
+    }
+
+    /**
+     * Copies the state of the given frame into this frame.
+     * 
+     * @param src
+     *            a frame.
+     * @return this frame.
+     */
+    public Frame<V> init(final Frame<? extends V> src) {
+        returnValue = src.returnValue;
+        System.arraycopy(src.values, 0, values, 0, values.length);
+        top = src.top;
+        return this;
+    }
+
+    /**
+     * Sets the expected return type of the analyzed method.
+     * 
+     * @param v
+     *            the expected return type of the analyzed method, or
+     *            <tt>null</tt> if the method returns void.
+     */
+    public void setReturn(final V v) {
+        returnValue = v;
+    }
+
+    /**
+     * Returns the maximum number of local variables of this frame.
+     * 
+     * @return the maximum number of local variables of this frame.
+     */
+    public int getLocals() {
+        return locals;
+    }
+
+    /**
+     * Returns the maximum stack size of this frame.
+     * 
+     * @return the maximum stack size of this frame.
+     */
+    public int getMaxStackSize() {
+        return values.length - locals;
+    }
+    
+    /**
+     * Returns the value of the given local variable.
+     * 
+     * @param i
+     *            a local variable index.
+     * @return the value of the given local variable.
+     * @throws IndexOutOfBoundsException
+     *             if the variable does not exist.
+     */
+    public V getLocal(final int i) throws IndexOutOfBoundsException {
+        if (i >= locals) {
+            throw new IndexOutOfBoundsException(
+                    "Trying to access an inexistant local variable");
+        }
+        return values[i];
+    }
+
+    /**
+     * Sets the value of the given local variable.
+     * 
+     * @param i
+     *            a local variable index.
+     * @param value
+     *            the new value of this local variable.
+     * @throws IndexOutOfBoundsException
+     *             if the variable does not exist.
+     */
+    public void setLocal(final int i, final V value)
+            throws IndexOutOfBoundsException {
+        if (i >= locals) {
+            throw new IndexOutOfBoundsException(
+                    "Trying to access an inexistant local variable " + i);
+        }
+        values[i] = value;
+    }
+
+    /**
+     * Returns the number of values in the operand stack of this frame. Long and
+     * double values are treated as single values.
+     * 
+     * @return the number of values in the operand stack of this frame.
+     */
+    public int getStackSize() {
+        return top;
+    }
+
+    /**
+     * Returns the value of the given operand stack slot.
+     * 
+     * @param i
+     *            the index of an operand stack slot.
+     * @return the value of the given operand stack slot.
+     * @throws IndexOutOfBoundsException
+     *             if the operand stack slot does not exist.
+     */
+    public V getStack(final int i) throws IndexOutOfBoundsException {
+        return values[i + locals];
+    }
+
+    /**
+     * Clears the operand stack of this frame.
+     */
+    public void clearStack() {
+        top = 0;
+    }
+
+    /**
+     * Pops a value from the operand stack of this frame.
+     * 
+     * @return the value that has been popped from the stack.
+     * @throws IndexOutOfBoundsException
+     *             if the operand stack is empty.
+     */
+    public V pop() throws IndexOutOfBoundsException {
+        if (top == 0) {
+            throw new IndexOutOfBoundsException(
+                    "Cannot pop operand off an empty stack.");
+        }
+        return values[--top + locals];
+    }
+
+    /**
+     * Pushes a value into the operand stack of this frame.
+     * 
+     * @param value
+     *            the value that must be pushed into the stack.
+     * @throws IndexOutOfBoundsException
+     *             if the operand stack is full.
+     */
+    public void push(final V value) throws IndexOutOfBoundsException {
+        if (top + locals >= values.length) {
+            throw new IndexOutOfBoundsException(
+                    "Insufficient maximum stack size.");
+        }
+        values[top++ + locals] = value;
+    }
+
+    public void execute(final AbstractInsnNode insn,
+            final Interpreter<V> interpreter) throws AnalyzerException {
+        V value1, value2, value3, value4;
+        List<V> values;
+        int var;
+
+        switch (insn.getOpcode()) {
+        case Opcodes.NOP:
+            break;
+        case Opcodes.ACONST_NULL:
+        case Opcodes.ICONST_M1:
+        case Opcodes.ICONST_0:
+        case Opcodes.ICONST_1:
+        case Opcodes.ICONST_2:
+        case Opcodes.ICONST_3:
+        case Opcodes.ICONST_4:
+        case Opcodes.ICONST_5:
+        case Opcodes.LCONST_0:
+        case Opcodes.LCONST_1:
+        case Opcodes.FCONST_0:
+        case Opcodes.FCONST_1:
+        case Opcodes.FCONST_2:
+        case Opcodes.DCONST_0:
+        case Opcodes.DCONST_1:
+        case Opcodes.BIPUSH:
+        case Opcodes.SIPUSH:
+        case Opcodes.LDC:
+            push(interpreter.newOperation(insn));
+            break;
+        case Opcodes.ILOAD:
+        case Opcodes.LLOAD:
+        case Opcodes.FLOAD:
+        case Opcodes.DLOAD:
+        case Opcodes.ALOAD:
+            push(interpreter.copyOperation(insn,
+                    getLocal(((VarInsnNode) insn).var)));
+            break;
+        case Opcodes.IALOAD:
+        case Opcodes.LALOAD:
+        case Opcodes.FALOAD:
+        case Opcodes.DALOAD:
+        case Opcodes.AALOAD:
+        case Opcodes.BALOAD:
+        case Opcodes.CALOAD:
+        case Opcodes.SALOAD:
+            value2 = pop();
+            value1 = pop();
+            push(interpreter.binaryOperation(insn, value1, value2));
+            break;
+        case Opcodes.ISTORE:
+        case Opcodes.LSTORE:
+        case Opcodes.FSTORE:
+        case Opcodes.DSTORE:
+        case Opcodes.ASTORE:
+            value1 = interpreter.copyOperation(insn, pop());
+            var = ((VarInsnNode) insn).var;
+            setLocal(var, value1);
+            if (value1.getSize() == 2) {
+                setLocal(var + 1, interpreter.newValue(null));
+            }
+            if (var > 0) {
+                Value local = getLocal(var - 1);
+                if (local != null && local.getSize() == 2) {
+                    setLocal(var - 1, interpreter.newValue(null));
+                }
+            }
+            break;
+        case Opcodes.IASTORE:
+        case Opcodes.LASTORE:
+        case Opcodes.FASTORE:
+        case Opcodes.DASTORE:
+        case Opcodes.AASTORE:
+        case Opcodes.BASTORE:
+        case Opcodes.CASTORE:
+        case Opcodes.SASTORE:
+            value3 = pop();
+            value2 = pop();
+            value1 = pop();
+            interpreter.ternaryOperation(insn, value1, value2, value3);
+            break;
+        case Opcodes.POP:
+            if (pop().getSize() == 2) {
+                throw new AnalyzerException(insn, "Illegal use of POP");
+            }
+            break;
+        case Opcodes.POP2:
+            if (pop().getSize() == 1) {
+                if (pop().getSize() != 1) {
+                    throw new AnalyzerException(insn, "Illegal use of POP2");
+                }
+            }
+            break;
+        case Opcodes.DUP:
+            value1 = pop();
+            if (value1.getSize() != 1) {
+                throw new AnalyzerException(insn, "Illegal use of DUP");
+            }
+            push(value1);
+            push(interpreter.copyOperation(insn, value1));
+            break;
+        case Opcodes.DUP_X1:
+            value1 = pop();
+            value2 = pop();
+            if (value1.getSize() != 1 || value2.getSize() != 1) {
+                throw new AnalyzerException(insn, "Illegal use of DUP_X1");
+            }
+            push(interpreter.copyOperation(insn, value1));
+            push(value2);
+            push(value1);
+            break;
+        case Opcodes.DUP_X2:
+            value1 = pop();
+            if (value1.getSize() == 1) {
+                value2 = pop();
+                if (value2.getSize() == 1) {
+                    value3 = pop();
+                    if (value3.getSize() == 1) {
+                        push(interpreter.copyOperation(insn, value1));
+                        push(value3);
+                        push(value2);
+                        push(value1);
+                        break;
+                    }
+                } else {
+                    push(interpreter.copyOperation(insn, value1));
+                    push(value2);
+                    push(value1);
+                    break;
+                }
+            }
+            throw new AnalyzerException(insn, "Illegal use of DUP_X2");
+        case Opcodes.DUP2:
+            value1 = pop();
+            if (value1.getSize() == 1) {
+                value2 = pop();
+                if (value2.getSize() == 1) {
+                    push(value2);
+                    push(value1);
+                    push(interpreter.copyOperation(insn, value2));
+                    push(interpreter.copyOperation(insn, value1));
+                    break;
+                }
+            } else {
+                push(value1);
+                push(interpreter.copyOperation(insn, value1));
+                break;
+            }
+            throw new AnalyzerException(insn, "Illegal use of DUP2");
+        case Opcodes.DUP2_X1:
+            value1 = pop();
+            if (value1.getSize() == 1) {
+                value2 = pop();
+                if (value2.getSize() == 1) {
+                    value3 = pop();
+                    if (value3.getSize() == 1) {
+                        push(interpreter.copyOperation(insn, value2));
+                        push(interpreter.copyOperation(insn, value1));
+                        push(value3);
+                        push(value2);
+                        push(value1);
+                        break;
+                    }
+                }
+            } else {
+                value2 = pop();
+                if (value2.getSize() == 1) {
+                    push(interpreter.copyOperation(insn, value1));
+                    push(value2);
+                    push(value1);
+                    break;
+                }
+            }
+            throw new AnalyzerException(insn, "Illegal use of DUP2_X1");
+        case Opcodes.DUP2_X2:
+            value1 = pop();
+            if (value1.getSize() == 1) {
+                value2 = pop();
+                if (value2.getSize() == 1) {
+                    value3 = pop();
+                    if (value3.getSize() == 1) {
+                        value4 = pop();
+                        if (value4.getSize() == 1) {
+                            push(interpreter.copyOperation(insn, value2));
+                            push(interpreter.copyOperation(insn, value1));
+                            push(value4);
+                            push(value3);
+                            push(value2);
+                            push(value1);
+                            break;
+                        }
+                    } else {
+                        push(interpreter.copyOperation(insn, value2));
+                        push(interpreter.copyOperation(insn, value1));
+                        push(value3);
+                        push(value2);
+                        push(value1);
+                        break;
+                    }
+                }
+            } else {
+                value2 = pop();
+                if (value2.getSize() == 1) {
+                    value3 = pop();
+                    if (value3.getSize() == 1) {
+                        push(interpreter.copyOperation(insn, value1));
+                        push(value3);
+                        push(value2);
+                        push(value1);
+                        break;
+                    }
+                } else {
+                    push(interpreter.copyOperation(insn, value1));
+                    push(value2);
+                    push(value1);
+                    break;
+                }
+            }
+            throw new AnalyzerException(insn, "Illegal use of DUP2_X2");
+        case Opcodes.SWAP:
+            value2 = pop();
+            value1 = pop();
+            if (value1.getSize() != 1 || value2.getSize() != 1) {
+                throw new AnalyzerException(insn, "Illegal use of SWAP");
+            }
+            push(interpreter.copyOperation(insn, value2));
+            push(interpreter.copyOperation(insn, value1));
+            break;
+        case Opcodes.IADD:
+        case Opcodes.LADD:
+        case Opcodes.FADD:
+        case Opcodes.DADD:
+        case Opcodes.ISUB:
+        case Opcodes.LSUB:
+        case Opcodes.FSUB:
+        case Opcodes.DSUB:
+        case Opcodes.IMUL:
+        case Opcodes.LMUL:
+        case Opcodes.FMUL:
+        case Opcodes.DMUL:
+        case Opcodes.IDIV:
+        case Opcodes.LDIV:
+        case Opcodes.FDIV:
+        case Opcodes.DDIV:
+        case Opcodes.IREM:
+        case Opcodes.LREM:
+        case Opcodes.FREM:
+        case Opcodes.DREM:
+            value2 = pop();
+            value1 = pop();
+            push(interpreter.binaryOperation(insn, value1, value2));
+            break;
+        case Opcodes.INEG:
+        case Opcodes.LNEG:
+        case Opcodes.FNEG:
+        case Opcodes.DNEG:
+            push(interpreter.unaryOperation(insn, pop()));
+            break;
+        case Opcodes.ISHL:
+        case Opcodes.LSHL:
+        case Opcodes.ISHR:
+        case Opcodes.LSHR:
+        case Opcodes.IUSHR:
+        case Opcodes.LUSHR:
+        case Opcodes.IAND:
+        case Opcodes.LAND:
+        case Opcodes.IOR:
+        case Opcodes.LOR:
+        case Opcodes.IXOR:
+        case Opcodes.LXOR:
+            value2 = pop();
+            value1 = pop();
+            push(interpreter.binaryOperation(insn, value1, value2));
+            break;
+        case Opcodes.IINC:
+            var = ((IincInsnNode) insn).var;
+            setLocal(var, interpreter.unaryOperation(insn, getLocal(var)));
+            break;
+        case Opcodes.I2L:
+        case Opcodes.I2F:
+        case Opcodes.I2D:
+        case Opcodes.L2I:
+        case Opcodes.L2F:
+        case Opcodes.L2D:
+        case Opcodes.F2I:
+        case Opcodes.F2L:
+        case Opcodes.F2D:
+        case Opcodes.D2I:
+        case Opcodes.D2L:
+        case Opcodes.D2F:
+        case Opcodes.I2B:
+        case Opcodes.I2C:
+        case Opcodes.I2S:
+            push(interpreter.unaryOperation(insn, pop()));
+            break;
+        case Opcodes.LCMP:
+        case Opcodes.FCMPL:
+        case Opcodes.FCMPG:
+        case Opcodes.DCMPL:
+        case Opcodes.DCMPG:
+            value2 = pop();
+            value1 = pop();
+            push(interpreter.binaryOperation(insn, value1, value2));
+            break;
+        case Opcodes.IFEQ:
+        case Opcodes.IFNE:
+        case Opcodes.IFLT:
+        case Opcodes.IFGE:
+        case Opcodes.IFGT:
+        case Opcodes.IFLE:
+            interpreter.unaryOperation(insn, pop());
+            break;
+        case Opcodes.IF_ICMPEQ:
+        case Opcodes.IF_ICMPNE:
+        case Opcodes.IF_ICMPLT:
+        case Opcodes.IF_ICMPGE:
+        case Opcodes.IF_ICMPGT:
+        case Opcodes.IF_ICMPLE:
+        case Opcodes.IF_ACMPEQ:
+        case Opcodes.IF_ACMPNE:
+            value2 = pop();
+            value1 = pop();
+            interpreter.binaryOperation(insn, value1, value2);
+            break;
+        case Opcodes.GOTO:
+            break;
+        case Opcodes.JSR:
+            push(interpreter.newOperation(insn));
+            break;
+        case Opcodes.RET:
+            break;
+        case Opcodes.TABLESWITCH:
+        case Opcodes.LOOKUPSWITCH:
+            interpreter.unaryOperation(insn, pop());
+            break;
+        case Opcodes.IRETURN:
+        case Opcodes.LRETURN:
+        case Opcodes.FRETURN:
+        case Opcodes.DRETURN:
+        case Opcodes.ARETURN:
+            value1 = pop();
+            interpreter.unaryOperation(insn, value1);
+            interpreter.returnOperation(insn, value1, returnValue);
+            break;
+        case Opcodes.RETURN:
+            if (returnValue != null) {
+                throw new AnalyzerException(insn, "Incompatible return type");
+            }
+            break;
+        case Opcodes.GETSTATIC:
+            push(interpreter.newOperation(insn));
+            break;
+        case Opcodes.PUTSTATIC:
+            interpreter.unaryOperation(insn, pop());
+            break;
+        case Opcodes.GETFIELD:
+            push(interpreter.unaryOperation(insn, pop()));
+            break;
+        case Opcodes.PUTFIELD:
+            value2 = pop();
+            value1 = pop();
+            interpreter.binaryOperation(insn, value1, value2);
+            break;
+        case Opcodes.INVOKEVIRTUAL:
+        case Opcodes.INVOKESPECIAL:
+        case Opcodes.INVOKESTATIC:
+        case Opcodes.INVOKEINTERFACE: {
+            values = new ArrayList<V>();
+            String desc = ((MethodInsnNode) insn).desc;
+            for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) {
+                values.add(0, pop());
+            }
+            if (insn.getOpcode() != Opcodes.INVOKESTATIC) {
+                values.add(0, pop());
+            }
+            if (Type.getReturnType(desc) == Type.VOID_TYPE) {
+                interpreter.naryOperation(insn, values);
+            } else {
+                push(interpreter.naryOperation(insn, values));
+            }
+            break;
+        }
+        case Opcodes.INVOKEDYNAMIC: {
+            values = new ArrayList<V>();
+            String desc = ((InvokeDynamicInsnNode) insn).desc;
+            for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) {
+                values.add(0, pop());
+            }
+            if (Type.getReturnType(desc) == Type.VOID_TYPE) {
+                interpreter.naryOperation(insn, values);
+            } else {
+                push(interpreter.naryOperation(insn, values));
+            }
+            break;
+        }
+        case Opcodes.NEW:
+            push(interpreter.newOperation(insn));
+            break;
+        case Opcodes.NEWARRAY:
+        case Opcodes.ANEWARRAY:
+        case Opcodes.ARRAYLENGTH:
+            push(interpreter.unaryOperation(insn, pop()));
+            break;
+        case Opcodes.ATHROW:
+            interpreter.unaryOperation(insn, pop());
+            break;
+        case Opcodes.CHECKCAST:
+        case Opcodes.INSTANCEOF:
+            push(interpreter.unaryOperation(insn, pop()));
+            break;
+        case Opcodes.MONITORENTER:
+        case Opcodes.MONITOREXIT:
+            interpreter.unaryOperation(insn, pop());
+            break;
+        case Opcodes.MULTIANEWARRAY:
+            values = new ArrayList<V>();
+            for (int i = ((MultiANewArrayInsnNode) insn).dims; i > 0; --i) {
+                values.add(0, pop());
+            }
+            push(interpreter.naryOperation(insn, values));
+            break;
+        case Opcodes.IFNULL:
+        case Opcodes.IFNONNULL:
+            interpreter.unaryOperation(insn, pop());
+            break;
+        default:
+            throw new RuntimeException("Illegal opcode " + insn.getOpcode());
+        }
+    }
+
+    /**
+     * Merges this frame with the given frame.
+     * 
+     * @param frame
+     *            a frame.
+     * @param interpreter
+     *            the interpreter used to merge values.
+     * @return <tt>true</tt> if this frame has been changed as a result of the
+     *         merge operation, or <tt>false</tt> otherwise.
+     * @throws AnalyzerException
+     *             if the frames have incompatible sizes.
+     */
+    public boolean merge(final Frame<? extends V> frame,
+            final Interpreter<V> interpreter) throws AnalyzerException {
+        if (top != frame.top) {
+            throw new AnalyzerException(null, "Incompatible stack heights");
+        }
+        boolean changes = false;
+        for (int i = 0; i < locals + top; ++i) {
+            V v = interpreter.merge(values[i], frame.values[i]);
+            if (!v.equals(values[i])) {
+                values[i] = v;
+                changes = true;
+            }
+        }
+        return changes;
+    }
+
+    /**
+     * Merges this frame with the given frame (case of a RET instruction).
+     * 
+     * @param frame
+     *            a frame
+     * @param access
+     *            the local variables that have been accessed by the subroutine
+     *            to which the RET instruction corresponds.
+     * @return <tt>true</tt> if this frame has been changed as a result of the
+     *         merge operation, or <tt>false</tt> otherwise.
+     */
+    public boolean merge(final Frame<? extends V> frame, final boolean[] access) {
+        boolean changes = false;
+        for (int i = 0; i < locals; ++i) {
+            if (!access[i] && !values[i].equals(frame.values[i])) {
+                values[i] = frame.values[i];
+                changes = true;
+            }
+        }
+        return changes;
+    }
+
+    /**
+     * Returns a string representation of this frame.
+     * 
+     * @return a string representation of this frame.
+     */
+    @Override
+    public String toString() {
+        StringBuffer b = new StringBuffer();
+        for (int i = 0; i < getLocals(); ++i) {
+            b.append(getLocal(i));
+        }
+        b.append(' ');
+        for (int i = 0; i < getStackSize(); ++i) {
+            b.append(getStack(i).toString());
+        }
+        return b.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java
new file mode 100644
index 0000000..b7c94c8
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java
@@ -0,0 +1,226 @@
+/***
+ * 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.List;
+
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
+
+/**
+ * A semantic bytecode interpreter. More precisely, this interpreter only
+ * manages the computation of values from other values: it does not manage the
+ * transfer of values to or from the stack, and to or from the local variables.
+ * This separation allows a generic bytecode {@link Analyzer} to work with
+ * various semantic interpreters, without needing to duplicate the code to
+ * simulate the transfer of values.
+ * 
+ * @param <V>
+ *            type of the Value used for the analysis.
+ * 
+ * @author Eric Bruneton
+ */
+public abstract class Interpreter<V extends Value> {
+
+    protected final int api;
+
+    protected Interpreter(final int api) {
+        this.api = api;
+    }
+
+    /**
+     * Creates a new value that represents the given type.
+     * 
+     * Called for method parameters (including <code>this</code>), exception
+     * handler variable and with <code>null</code> type for variables reserved
+     * by long and double types.
+     * 
+     * @param type
+     *            a primitive or reference type, or <tt>null</tt> to represent
+     *            an uninitialized value.
+     * @return a value that represents the given type. The size of the returned
+     *         value must be equal to the size of the given type.
+     */
+    public abstract V newValue(Type type);
+
+    /**
+     * Interprets a bytecode instruction without arguments. This method is
+     * called for the following opcodes:
+     * 
+     * ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4,
+     * ICONST_5, LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0,
+     * DCONST_1, BIPUSH, SIPUSH, LDC, JSR, GETSTATIC, NEW
+     * 
+     * @param insn
+     *            the bytecode instruction to be interpreted.
+     * @return the result of the interpretation of the given instruction.
+     * @throws AnalyzerException
+     *             if an error occured during the interpretation.
+     */
+    public abstract V newOperation(AbstractInsnNode insn)
+            throws AnalyzerException;
+
+    /**
+     * Interprets a bytecode instruction that moves a value on the stack or to
+     * or from local variables. This method is called for the following opcodes:
+     * 
+     * ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE,
+     * ASTORE, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP
+     * 
+     * @param insn
+     *            the bytecode instruction to be interpreted.
+     * @param value
+     *            the value that must be moved by the instruction.
+     * @return the result of the interpretation of the given instruction. The
+     *         returned value must be <tt>equal</tt> to the given value.
+     * @throws AnalyzerException
+     *             if an error occured during the interpretation.
+     */
+    public abstract V copyOperation(AbstractInsnNode insn, V value)
+            throws AnalyzerException;
+
+    /**
+     * Interprets a bytecode instruction with a single argument. This method is
+     * called for the following opcodes:
+     * 
+     * INEG, LNEG, FNEG, DNEG, IINC, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L,
+     * F2D, D2I, D2L, D2F, I2B, I2C, I2S, IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE,
+     * TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN, FRETURN, DRETURN, ARETURN,
+     * PUTSTATIC, GETFIELD, NEWARRAY, ANEWARRAY, ARRAYLENGTH, ATHROW, CHECKCAST,
+     * INSTANCEOF, MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL
+     * 
+     * @param insn
+     *            the bytecode instruction to be interpreted.
+     * @param value
+     *            the argument of the instruction to be interpreted.
+     * @return the result of the interpretation of the given instruction.
+     * @throws AnalyzerException
+     *             if an error occured during the interpretation.
+     */
+    public abstract V unaryOperation(AbstractInsnNode insn, V value)
+            throws AnalyzerException;
+
+    /**
+     * Interprets a bytecode instruction with two arguments. This method is
+     * called for the following opcodes:
+     * 
+     * IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IADD,
+     * LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV,
+     * LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, ISHL, LSHL, ISHR, LSHR, IUSHR,
+     * LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, LCMP, FCMPL, FCMPG, DCMPL,
+     * DCMPG, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
+     * IF_ACMPEQ, IF_ACMPNE, PUTFIELD
+     * 
+     * @param insn
+     *            the bytecode instruction to be interpreted.
+     * @param value1
+     *            the first argument of the instruction to be interpreted.
+     * @param value2
+     *            the second argument of the instruction to be interpreted.
+     * @return the result of the interpretation of the given instruction.
+     * @throws AnalyzerException
+     *             if an error occured during the interpretation.
+     */
+    public abstract V binaryOperation(AbstractInsnNode insn, V value1, V value2)
+            throws AnalyzerException;
+
+    /**
+     * Interprets a bytecode instruction with three arguments. This method is
+     * called for the following opcodes:
+     * 
+     * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE
+     * 
+     * @param insn
+     *            the bytecode instruction to be interpreted.
+     * @param value1
+     *            the first argument of the instruction to be interpreted.
+     * @param value2
+     *            the second argument of the instruction to be interpreted.
+     * @param value3
+     *            the third argument of the instruction to be interpreted.
+     * @return the result of the interpretation of the given instruction.
+     * @throws AnalyzerException
+     *             if an error occured during the interpretation.
+     */
+    public abstract V ternaryOperation(AbstractInsnNode insn, V value1,
+            V value2, V value3) throws AnalyzerException;
+
+    /**
+     * Interprets a bytecode instruction with a variable number of arguments.
+     * This method is called for the following opcodes:
+     * 
+     * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE,
+     * MULTIANEWARRAY and INVOKEDYNAMIC
+     * 
+     * @param insn
+     *            the bytecode instruction to be interpreted.
+     * @param values
+     *            the arguments of the instruction to be interpreted.
+     * @return the result of the interpretation of the given instruction.
+     * @throws AnalyzerException
+     *             if an error occured during the interpretation.
+     */
+    public abstract V naryOperation(AbstractInsnNode insn,
+            List<? extends V> values) throws AnalyzerException;
+
+    /**
+     * Interprets a bytecode return instruction. This method is called for the
+     * following opcodes:
+     * 
+     * IRETURN, LRETURN, FRETURN, DRETURN, ARETURN
+     * 
+     * @param insn
+     *            the bytecode instruction to be interpreted.
+     * @param value
+     *            the argument of the instruction to be interpreted.
+     * @param expected
+     *            the expected return type of the analyzed method.
+     * @throws AnalyzerException
+     *             if an error occured during the interpretation.
+     */
+    public abstract void returnOperation(AbstractInsnNode insn, V value,
+            V expected) throws AnalyzerException;
+
+    /**
+     * Merges two values. The merge operation must return a value that
+     * represents both values (for instance, if the two values are two types,
+     * the merged value must be a common super type of the two types. If the two
+     * values are integer intervals, the merged value must be an interval that
+     * contains the previous ones. Likewise for other types of values).
+     * 
+     * @param v
+     *            a value.
+     * @param w
+     *            another value.
+     * @return the merged value. If the merged value is equal to <tt>v</tt>,
+     *         this method <i>must</i> return <tt>v</tt>.
+     */
+    public abstract V merge(V v, V w);
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java
new file mode 100644
index 0000000..c53beb4
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java
@@ -0,0 +1,320 @@
+/***
+ * 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.List;
+
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * An extended {@link BasicVerifier} that performs more precise verifications.
+ * This verifier computes exact class types, instead of using a single "object
+ * reference" type (as done in the {@link BasicVerifier}).
+ * 
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class SimpleVerifier extends BasicVerifier {
+
+    /**
+     * The class that is verified.
+     */
+    private final Type currentClass;
+
+    /**
+     * The super class of the class that is verified.
+     */
+    private final Type currentSuperClass;
+
+    /**
+     * The interfaces implemented by the class that is verified.
+     */
+    private final List<Type> currentClassInterfaces;
+
+    /**
+     * If the class that is verified is an interface.
+     */
+    private final boolean isInterface;
+
+    /**
+     * The loader to use for referenced classes.
+     */
+    private ClassLoader loader = getClass().getClassLoader();
+
+    /**
+     * Constructs a new {@link SimpleVerifier}.
+     */
+    public SimpleVerifier() {
+        this(null, null, false);
+    }
+
+    /**
+     * Constructs a new {@link SimpleVerifier} to verify a specific class. This
+     * class will not be loaded into the JVM since it may be incorrect.
+     * 
+     * @param currentClass
+     *            the class that is verified.
+     * @param currentSuperClass
+     *            the super class of the class that is verified.
+     * @param isInterface
+     *            if the class that is verified is an interface.
+     */
+    public SimpleVerifier(final Type currentClass,
+            final Type currentSuperClass, final boolean isInterface) {
+        this(currentClass, currentSuperClass, null, isInterface);
+    }
+
+    /**
+     * Constructs a new {@link SimpleVerifier} to verify a specific class. This
+     * class will not be loaded into the JVM since it may be incorrect.
+     * 
+     * @param currentClass
+     *            the class that is verified.
+     * @param currentSuperClass
+     *            the super class of the class that is verified.
+     * @param currentClassInterfaces
+     *            the interfaces implemented by the class that is verified.
+     * @param isInterface
+     *            if the class that is verified is an interface.
+     */
+    public SimpleVerifier(final Type currentClass,
+            final Type currentSuperClass,
+            final List<Type> currentClassInterfaces, final boolean isInterface) {
+        this(ASM5, currentClass, currentSuperClass, currentClassInterfaces,
+                isInterface);
+    }
+
+    protected SimpleVerifier(final int api, final Type currentClass,
+            final Type currentSuperClass,
+            final List<Type> currentClassInterfaces, final boolean isInterface) {
+        super(api);
+        this.currentClass = currentClass;
+        this.currentSuperClass = currentSuperClass;
+        this.currentClassInterfaces = currentClassInterfaces;
+        this.isInterface = isInterface;
+    }
+
+    /**
+     * Set the <code>ClassLoader</code> which will be used to load referenced
+     * classes. This is useful if you are verifying multiple interdependent
+     * classes.
+     * 
+     * @param loader
+     *            a <code>ClassLoader</code> to use
+     */
+    public void setClassLoader(final ClassLoader loader) {
+        this.loader = loader;
+    }
+
+    @Override
+    public BasicValue newValue(final Type type) {
+        if (type == null) {
+            return BasicValue.UNINITIALIZED_VALUE;
+        }
+
+        boolean isArray = type.getSort() == Type.ARRAY;
+        if (isArray) {
+            switch (type.getElementType().getSort()) {
+            case Type.BOOLEAN:
+            case Type.CHAR:
+            case Type.BYTE:
+            case Type.SHORT:
+                return new BasicValue(type);
+            }
+        }
+
+        BasicValue v = super.newValue(type);
+        if (BasicValue.REFERENCE_VALUE.equals(v)) {
+            if (isArray) {
+                v = newValue(type.getElementType());
+                String desc = v.getType().getDescriptor();
+                for (int i = 0; i < type.getDimensions(); ++i) {
+                    desc = '[' + desc;
+                }
+                v = new BasicValue(Type.getType(desc));
+            } else {
+                v = new BasicValue(type);
+            }
+        }
+        return v;
+    }
+
+    @Override
+    protected boolean isArrayValue(final BasicValue value) {
+        Type t = value.getType();
+        return t != null
+                && ("Lnull;".equals(t.getDescriptor()) || t.getSort() == Type.ARRAY);
+    }
+
+    @Override
+    protected BasicValue getElementValue(final BasicValue objectArrayValue)
+            throws AnalyzerException {
+        Type arrayType = objectArrayValue.getType();
+        if (arrayType != null) {
+            if (arrayType.getSort() == Type.ARRAY) {
+                return newValue(Type.getType(arrayType.getDescriptor()
+                        .substring(1)));
+            } else if ("Lnull;".equals(arrayType.getDescriptor())) {
+                return objectArrayValue;
+            }
+        }
+        throw new Error("Internal error");
+    }
+
+    @Override
+    protected boolean isSubTypeOf(final BasicValue value,
+            final BasicValue expected) {
+        Type expectedType = expected.getType();
+        Type type = value.getType();
+        switch (expectedType.getSort()) {
+        case Type.INT:
+        case Type.FLOAT:
+        case Type.LONG:
+        case Type.DOUBLE:
+            return type.equals(expectedType);
+        case Type.ARRAY:
+        case Type.OBJECT:
+            if ("Lnull;".equals(type.getDescriptor())) {
+                return true;
+            } else if (type.getSort() == Type.OBJECT
+                    || type.getSort() == Type.ARRAY) {
+                return isAssignableFrom(expectedType, type);
+            } else {
+                return false;
+            }
+        default:
+            throw new Error("Internal error");
+        }
+    }
+
+    @Override
+    public BasicValue merge(final BasicValue v, final BasicValue w) {
+        if (!v.equals(w)) {
+            Type t = v.getType();
+            Type u = w.getType();
+            if (t != null
+                    && (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY)) {
+                if (u != null
+                        && (u.getSort() == Type.OBJECT || u.getSort() == Type.ARRAY)) {
+                    if ("Lnull;".equals(t.getDescriptor())) {
+                        return w;
+                    }
+                    if ("Lnull;".equals(u.getDescriptor())) {
+                        return v;
+                    }
+                    if (isAssignableFrom(t, u)) {
+                        return v;
+                    }
+                    if (isAssignableFrom(u, t)) {
+                        return w;
+                    }
+                    // TODO case of array classes of the same dimension
+                    // TODO should we look also for a common super interface?
+                    // problem: there may be several possible common super
+                    // interfaces
+                    do {
+                        if (t == null || isInterface(t)) {
+                            return BasicValue.REFERENCE_VALUE;
+                        }
+                        t = getSuperClass(t);
+                        if (isAssignableFrom(t, u)) {
+                            return newValue(t);
+                        }
+                    } while (true);
+                }
+            }
+            return BasicValue.UNINITIALIZED_VALUE;
+        }
+        return v;
+    }
+
+    protected boolean isInterface(final Type t) {
+        if (currentClass != null && t.equals(currentClass)) {
+            return isInterface;
+        }
+        return getClass(t).isInterface();
+    }
+
+    protected Type getSuperClass(final Type t) {
+        if (currentClass != null && t.equals(currentClass)) {
+            return currentSuperClass;
+        }
+        Class<?> c = getClass(t).getSuperclass();
+        return c == null ? null : Type.getType(c);
+    }
+
+    protected boolean isAssignableFrom(final Type t, final Type u) {
+        if (t.equals(u)) {
+            return true;
+        }
+        if (currentClass != null && t.equals(currentClass)) {
+            if (getSuperClass(u) == null) {
+                return false;
+            } else {
+                if (isInterface) {
+                    return u.getSort() == Type.OBJECT
+                            || u.getSort() == Type.ARRAY;
+                }
+                return isAssignableFrom(t, getSuperClass(u));
+            }
+        }
+        if (currentClass != null && u.equals(currentClass)) {
+            if (isAssignableFrom(t, currentSuperClass)) {
+                return true;
+            }
+            if (currentClassInterfaces != null) {
+                for (int i = 0; i < currentClassInterfaces.size(); ++i) {
+                    Type v = currentClassInterfaces.get(i);
+                    if (isAssignableFrom(t, v)) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+        Class<?> tc = getClass(t);
+        if (tc.isInterface()) {
+            tc = Object.class;
+        }
+        return tc.isAssignableFrom(getClass(u));
+    }
+
+    protected Class<?> getClass(final Type t) {
+        try {
+            if (t.getSort() == Type.ARRAY) {
+                return Class.forName(t.getDescriptor().replace('/', '.'),
+                        false, loader);
+            }
+            return Class.forName(t.getClassName(), false, loader);
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException(e.toString());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java
new file mode 100644
index 0000000..2aacb42
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java
@@ -0,0 +1,134 @@
+/***
+ * 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.AbstractSet;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * A set of at most two elements.
+ * 
+ * @author Eric Bruneton
+ */
+class SmallSet<E> extends AbstractSet<E> implements Iterator<E> {
+
+    // if e1 is null, e2 must be null; otherwise e2 must be different from e1
+
+    E e1, e2;
+
+    static final <T> Set<T> emptySet() {
+        return new SmallSet<T>(null, null);
+    }
+
+    SmallSet(final E e1, final E e2) {
+        this.e1 = e1;
+        this.e2 = e2;
+    }
+
+    // -------------------------------------------------------------------------
+    // Implementation of inherited abstract methods
+    // -------------------------------------------------------------------------
+
+    @Override
+    public Iterator<E> iterator() {
+        return new SmallSet<E>(e1, e2);
+    }
+
+    @Override
+    public int size() {
+        return e1 == null ? 0 : (e2 == null ? 1 : 2);
+    }
+
+    // -------------------------------------------------------------------------
+    // Implementation of the Iterator interface
+    // -------------------------------------------------------------------------
+
+    public boolean hasNext() {
+        return e1 != null;
+    }
+
+    public E next() {
+        if (e1 == null) {
+            throw new NoSuchElementException();
+        }
+        E e = e1;
+        e1 = e2;
+        e2 = null;
+        return e;
+    }
+
+    public void remove() {
+    }
+
+    // -------------------------------------------------------------------------
+    // Utility methods
+    // -------------------------------------------------------------------------
+
+    Set<E> union(final SmallSet<E> s) {
+        if ((s.e1 == e1 && s.e2 == e2) || (s.e1 == e2 && s.e2 == e1)) {
+            return this; // if the two sets are equal, return this
+        }
+        if (s.e1 == null) {
+            return this; // if s is empty, return this
+        }
+        if (e1 == null) {
+            return s; // if this is empty, return s
+        }
+        if (s.e2 == null) { // s contains exactly one element
+            if (e2 == null) {
+                return new SmallSet<E>(e1, s.e1); // necessarily e1 != s.e1
+            } else if (s.e1 == e1 || s.e1 == e2) { // s is included in this
+                return this;
+            }
+        }
+        if (e2 == null) { // this contains exactly one element
+            // if (s.e2 == null) { // cannot happen
+            // return new SmallSet(e1, s.e1); // necessarily e1 != s.e1
+            // } else
+            if (e1 == s.e1 || e1 == s.e2) { // this in included in s
+                return s;
+            }
+        }
+        // here we know that there are at least 3 distinct elements
+        HashSet<E> r = new HashSet<E>(4);
+        r.add(e1);
+        if (e2 != null) {
+            r.add(e2);
+        }
+        r.add(s.e1);
+        if (s.e2 != null) {
+            r.add(s.e2);
+        }
+        return r;
+    }
+}


[05/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?"

Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java
new file mode 100644
index 0000000..5770364
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java
@@ -0,0 +1,1542 @@
+/***
+ * 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.util;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+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;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.Analyzer;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicValue;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicVerifier;
+
+/**
+ * A {@link MethodVisitor} that checks that its methods are properly used. More
+ * precisely this method adapter checks each instruction individually, i.e.,
+ * each visit method checks some preconditions based <i>only</i> on its
+ * arguments - such as the fact that the given opcode is correct for a given
+ * visit method. This adapter can also perform some basic data flow checks (more
+ * precisely those that can be performed without the full class hierarchy - see
+ * {@link org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicVerifier}). For instance in a
+ * method whose signature is <tt>void m ()</tt>, the invalid instruction
+ * IRETURN, or the invalid sequence IADD L2I will be detected if the data flow
+ * checks are enabled. These checks are enabled by using the
+ * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)} constructor.
+ * They are not performed if any other constructor is used.
+ * 
+ * @author Eric Bruneton
+ */
+public class CheckMethodAdapter extends MethodVisitor {
+
+    /**
+     * The class version number.
+     */
+    public int version;
+
+    /**
+     * The access flags of the method.
+     */
+    private int access;
+
+    /**
+     * <tt>true</tt> if the visitCode method has been called.
+     */
+    private boolean startCode;
+
+    /**
+     * <tt>true</tt> if the visitMaxs method has been called.
+     */
+    private boolean endCode;
+
+    /**
+     * <tt>true</tt> if the visitEnd method has been called.
+     */
+    private boolean endMethod;
+
+    /**
+     * Number of visited instructions.
+     */
+    private int insnCount;
+
+    /**
+     * The already visited labels. This map associate Integer values to pseudo
+     * code offsets.
+     */
+    private final Map<Label, Integer> labels;
+
+    /**
+     * The labels used in this method. Every used label must be visited with
+     * visitLabel before the end of the method (i.e. should be in #labels).
+     */
+    private Set<Label> usedLabels;
+
+    /**
+     * Number of visited frames in expanded form.
+     */
+    private int expandedFrames;
+
+    /**
+     * Number of visited frames in compressed form.
+     */
+    private int compressedFrames;
+
+    /**
+     * Number of instructions before the last visited frame.
+     */
+    private int lastFrame = -1;
+
+    /**
+     * The exception handler ranges. Each pair of list element contains the
+     * start and end labels of an exception handler block.
+     */
+    private List<Label> handlers;
+
+    /**
+     * Code of the visit method to be used for each opcode.
+     */
+    private static final int[] TYPE;
+
+    /**
+     * The Label.status field.
+     */
+    private static Field labelStatusField;
+
+    static {
+        String s = "BBBBBBBBBBBBBBBBCCIAADDDDDAAAAAAAAAAAAAAAAAAAABBBBBBBBDD"
+                + "DDDAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
+                + "BBBBBBBBBBBBBBBBBBBJBBBBBBBBBBBBBBBBBBBBHHHHHHHHHHHHHHHHD"
+                + "KLBBBBBBFFFFGGGGAECEBBEEBBAMHHAA";
+        TYPE = new int[s.length()];
+        for (int i = 0; i < TYPE.length; ++i) {
+            TYPE[i] = s.charAt(i) - 'A' - 1;
+        }
+    }
+
+    // code to generate the above string
+    // public static void main (String[] args) {
+    // int[] TYPE = new int[] {
+    // 0, //NOP
+    // 0, //ACONST_NULL
+    // 0, //ICONST_M1
+    // 0, //ICONST_0
+    // 0, //ICONST_1
+    // 0, //ICONST_2
+    // 0, //ICONST_3
+    // 0, //ICONST_4
+    // 0, //ICONST_5
+    // 0, //LCONST_0
+    // 0, //LCONST_1
+    // 0, //FCONST_0
+    // 0, //FCONST_1
+    // 0, //FCONST_2
+    // 0, //DCONST_0
+    // 0, //DCONST_1
+    // 1, //BIPUSH
+    // 1, //SIPUSH
+    // 7, //LDC
+    // -1, //LDC_W
+    // -1, //LDC2_W
+    // 2, //ILOAD
+    // 2, //LLOAD
+    // 2, //FLOAD
+    // 2, //DLOAD
+    // 2, //ALOAD
+    // -1, //ILOAD_0
+    // -1, //ILOAD_1
+    // -1, //ILOAD_2
+    // -1, //ILOAD_3
+    // -1, //LLOAD_0
+    // -1, //LLOAD_1
+    // -1, //LLOAD_2
+    // -1, //LLOAD_3
+    // -1, //FLOAD_0
+    // -1, //FLOAD_1
+    // -1, //FLOAD_2
+    // -1, //FLOAD_3
+    // -1, //DLOAD_0
+    // -1, //DLOAD_1
+    // -1, //DLOAD_2
+    // -1, //DLOAD_3
+    // -1, //ALOAD_0
+    // -1, //ALOAD_1
+    // -1, //ALOAD_2
+    // -1, //ALOAD_3
+    // 0, //IALOAD
+    // 0, //LALOAD
+    // 0, //FALOAD
+    // 0, //DALOAD
+    // 0, //AALOAD
+    // 0, //BALOAD
+    // 0, //CALOAD
+    // 0, //SALOAD
+    // 2, //ISTORE
+    // 2, //LSTORE
+    // 2, //FSTORE
+    // 2, //DSTORE
+    // 2, //ASTORE
+    // -1, //ISTORE_0
+    // -1, //ISTORE_1
+    // -1, //ISTORE_2
+    // -1, //ISTORE_3
+    // -1, //LSTORE_0
+    // -1, //LSTORE_1
+    // -1, //LSTORE_2
+    // -1, //LSTORE_3
+    // -1, //FSTORE_0
+    // -1, //FSTORE_1
+    // -1, //FSTORE_2
+    // -1, //FSTORE_3
+    // -1, //DSTORE_0
+    // -1, //DSTORE_1
+    // -1, //DSTORE_2
+    // -1, //DSTORE_3
+    // -1, //ASTORE_0
+    // -1, //ASTORE_1
+    // -1, //ASTORE_2
+    // -1, //ASTORE_3
+    // 0, //IASTORE
+    // 0, //LASTORE
+    // 0, //FASTORE
+    // 0, //DASTORE
+    // 0, //AASTORE
+    // 0, //BASTORE
+    // 0, //CASTORE
+    // 0, //SASTORE
+    // 0, //POP
+    // 0, //POP2
+    // 0, //DUP
+    // 0, //DUP_X1
+    // 0, //DUP_X2
+    // 0, //DUP2
+    // 0, //DUP2_X1
+    // 0, //DUP2_X2
+    // 0, //SWAP
+    // 0, //IADD
+    // 0, //LADD
+    // 0, //FADD
+    // 0, //DADD
+    // 0, //ISUB
+    // 0, //LSUB
+    // 0, //FSUB
+    // 0, //DSUB
+    // 0, //IMUL
+    // 0, //LMUL
+    // 0, //FMUL
+    // 0, //DMUL
+    // 0, //IDIV
+    // 0, //LDIV
+    // 0, //FDIV
+    // 0, //DDIV
+    // 0, //IREM
+    // 0, //LREM
+    // 0, //FREM
+    // 0, //DREM
+    // 0, //INEG
+    // 0, //LNEG
+    // 0, //FNEG
+    // 0, //DNEG
+    // 0, //ISHL
+    // 0, //LSHL
+    // 0, //ISHR
+    // 0, //LSHR
+    // 0, //IUSHR
+    // 0, //LUSHR
+    // 0, //IAND
+    // 0, //LAND
+    // 0, //IOR
+    // 0, //LOR
+    // 0, //IXOR
+    // 0, //LXOR
+    // 8, //IINC
+    // 0, //I2L
+    // 0, //I2F
+    // 0, //I2D
+    // 0, //L2I
+    // 0, //L2F
+    // 0, //L2D
+    // 0, //F2I
+    // 0, //F2L
+    // 0, //F2D
+    // 0, //D2I
+    // 0, //D2L
+    // 0, //D2F
+    // 0, //I2B
+    // 0, //I2C
+    // 0, //I2S
+    // 0, //LCMP
+    // 0, //FCMPL
+    // 0, //FCMPG
+    // 0, //DCMPL
+    // 0, //DCMPG
+    // 6, //IFEQ
+    // 6, //IFNE
+    // 6, //IFLT
+    // 6, //IFGE
+    // 6, //IFGT
+    // 6, //IFLE
+    // 6, //IF_ICMPEQ
+    // 6, //IF_ICMPNE
+    // 6, //IF_ICMPLT
+    // 6, //IF_ICMPGE
+    // 6, //IF_ICMPGT
+    // 6, //IF_ICMPLE
+    // 6, //IF_ACMPEQ
+    // 6, //IF_ACMPNE
+    // 6, //GOTO
+    // 6, //JSR
+    // 2, //RET
+    // 9, //TABLESWITCH
+    // 10, //LOOKUPSWITCH
+    // 0, //IRETURN
+    // 0, //LRETURN
+    // 0, //FRETURN
+    // 0, //DRETURN
+    // 0, //ARETURN
+    // 0, //RETURN
+    // 4, //GETSTATIC
+    // 4, //PUTSTATIC
+    // 4, //GETFIELD
+    // 4, //PUTFIELD
+    // 5, //INVOKEVIRTUAL
+    // 5, //INVOKESPECIAL
+    // 5, //INVOKESTATIC
+    // 5, //INVOKEINTERFACE
+    // -1, //INVOKEDYNAMIC
+    // 3, //NEW
+    // 1, //NEWARRAY
+    // 3, //ANEWARRAY
+    // 0, //ARRAYLENGTH
+    // 0, //ATHROW
+    // 3, //CHECKCAST
+    // 3, //INSTANCEOF
+    // 0, //MONITORENTER
+    // 0, //MONITOREXIT
+    // -1, //WIDE
+    // 11, //MULTIANEWARRAY
+    // 6, //IFNULL
+    // 6, //IFNONNULL
+    // -1, //GOTO_W
+    // -1 //JSR_W
+    // };
+    // for (int i = 0; i < TYPE.length; ++i) {
+    // System.out.print((char)(TYPE[i] + 1 + 'A'));
+    // }
+    // System.out.println();
+    // }
+
+    /**
+     * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+     * will not perform any data flow check (see
+     * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
+     * <i>Subclasses must not use this constructor</i>. Instead, they must use
+     * the {@link #CheckMethodAdapter(int, MethodVisitor, Map)} version.
+     * 
+     * @param mv
+     *            the method visitor to which this adapter must delegate calls.
+     */
+    public CheckMethodAdapter(final MethodVisitor mv) {
+        this(mv, new HashMap<Label, Integer>());
+    }
+
+    /**
+     * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+     * will not perform any data flow check (see
+     * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
+     * <i>Subclasses must not use this constructor</i>. Instead, they must use
+     * the {@link #CheckMethodAdapter(int, MethodVisitor, Map)} version.
+     * 
+     * @param mv
+     *            the method visitor to which this adapter must delegate calls.
+     * @param labels
+     *            a map of already visited labels (in other methods).
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public CheckMethodAdapter(final MethodVisitor mv,
+            final Map<Label, Integer> labels) {
+        this(Opcodes.ASM5, mv, labels);
+        if (getClass() != CheckMethodAdapter.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+     * will not perform any data flow check (see
+     * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
+     * 
+     * @param mv
+     *            the method visitor to which this adapter must delegate calls.
+     * @param labels
+     *            a map of already visited labels (in other methods).
+     */
+    protected CheckMethodAdapter(final int api, final MethodVisitor mv,
+            final Map<Label, Integer> labels) {
+        super(api, mv);
+        this.labels = labels;
+        this.usedLabels = new HashSet<Label>();
+        this.handlers = new ArrayList<Label>();
+    }
+
+    /**
+     * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+     * will perform basic data flow checks. For instance in a method whose
+     * signature is <tt>void m ()</tt>, the invalid instruction IRETURN, or the
+     * invalid sequence IADD L2I will be detected.
+     * 
+     * @param access
+     *            the method's access flags.
+     * @param name
+     *            the method's name.
+     * @param desc
+     *            the method's descriptor (see {@link Type Type}).
+     * @param cmv
+     *            the method visitor to which this adapter must delegate calls.
+     * @param labels
+     *            a map of already visited labels (in other methods).
+     */
+    public CheckMethodAdapter(final int access, final String name,
+            final String desc, final MethodVisitor cmv,
+            final Map<Label, Integer> labels) {
+        this(new MethodNode(Opcodes.ASM5, access, name, desc, null, null) {
+            @Override
+            public void visitEnd() {
+                Analyzer<BasicValue> a = new Analyzer<BasicValue>(
+                        new BasicVerifier());
+                try {
+                    a.analyze("dummy", this);
+                } catch (Exception e) {
+                    if (e instanceof IndexOutOfBoundsException
+                            && maxLocals == 0 && maxStack == 0) {
+                        throw new RuntimeException(
+                                "Data flow checking option requires valid, non zero maxLocals and maxStack values.");
+                    }
+                    e.printStackTrace();
+                    StringWriter sw = new StringWriter();
+                    PrintWriter pw = new PrintWriter(sw, true);
+                    CheckClassAdapter.printAnalyzerResult(this, a, pw);
+                    pw.close();
+                    throw new RuntimeException(e.getMessage() + ' '
+                            + sw.toString());
+                }
+                accept(cmv);
+            }
+        }, labels);
+        this.access = access;
+    }
+
+    @Override
+    public void visitParameter(String name, int access) {
+        if (name != null) {
+            checkUnqualifiedName(version, name, "name");
+        }
+        CheckClassAdapter.checkAccess(access, Opcodes.ACC_FINAL
+                + Opcodes.ACC_MANDATED + Opcodes.ACC_SYNTHETIC);
+        super.visitParameter(name, access);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc,
+            final boolean visible) {
+        checkEndMethod();
+        checkDesc(desc, false);
+        return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
+    }
+
+    @Override
+    public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        checkEndMethod();
+        int sort = typeRef >>> 24;
+        if (sort != TypeReference.METHOD_TYPE_PARAMETER
+                && sort != TypeReference.METHOD_TYPE_PARAMETER_BOUND
+                && sort != TypeReference.METHOD_RETURN
+                && sort != TypeReference.METHOD_RECEIVER
+                && sort != TypeReference.METHOD_FORMAL_PARAMETER
+                && sort != TypeReference.THROWS) {
+            throw new IllegalArgumentException("Invalid type reference sort 0x"
+                    + Integer.toHexString(sort));
+        }
+        CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+        CheckMethodAdapter.checkDesc(desc, false);
+        return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef,
+                typePath, desc, visible));
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotationDefault() {
+        checkEndMethod();
+        return new CheckAnnotationAdapter(super.visitAnnotationDefault(), false);
+    }
+
+    @Override
+    public AnnotationVisitor visitParameterAnnotation(final int parameter,
+            final String desc, final boolean visible) {
+        checkEndMethod();
+        checkDesc(desc, false);
+        return new CheckAnnotationAdapter(super.visitParameterAnnotation(
+                parameter, desc, visible));
+    }
+
+    @Override
+    public void visitAttribute(final Attribute attr) {
+        checkEndMethod();
+        if (attr == null) {
+            throw new IllegalArgumentException(
+                    "Invalid attribute (must not be null)");
+        }
+        super.visitAttribute(attr);
+    }
+
+    @Override
+    public void visitCode() {
+        if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+            throw new RuntimeException("Abstract methods cannot have code");
+        }
+        startCode = true;
+        super.visitCode();
+    }
+
+    @Override
+    public void visitFrame(final int type, final int nLocal,
+            final Object[] local, final int nStack, final Object[] stack) {
+        if (insnCount == lastFrame) {
+            throw new IllegalStateException(
+                    "At most one frame can be visited at a given code location.");
+        }
+        lastFrame = insnCount;
+        int mLocal;
+        int mStack;
+        switch (type) {
+        case Opcodes.F_NEW:
+        case Opcodes.F_FULL:
+            mLocal = Integer.MAX_VALUE;
+            mStack = Integer.MAX_VALUE;
+            break;
+
+        case Opcodes.F_SAME:
+            mLocal = 0;
+            mStack = 0;
+            break;
+
+        case Opcodes.F_SAME1:
+            mLocal = 0;
+            mStack = 1;
+            break;
+
+        case Opcodes.F_APPEND:
+        case Opcodes.F_CHOP:
+            mLocal = 3;
+            mStack = 0;
+            break;
+
+        default:
+            throw new IllegalArgumentException("Invalid frame type " + type);
+        }
+
+        if (nLocal > mLocal) {
+            throw new IllegalArgumentException("Invalid nLocal=" + nLocal
+                    + " for frame type " + type);
+        }
+        if (nStack > mStack) {
+            throw new IllegalArgumentException("Invalid nStack=" + nStack
+                    + " for frame type " + type);
+        }
+
+        if (type != Opcodes.F_CHOP) {
+            if (nLocal > 0 && (local == null || local.length < nLocal)) {
+                throw new IllegalArgumentException(
+                        "Array local[] is shorter than nLocal");
+            }
+            for (int i = 0; i < nLocal; ++i) {
+                checkFrameValue(local[i]);
+            }
+        }
+        if (nStack > 0 && (stack == null || stack.length < nStack)) {
+            throw new IllegalArgumentException(
+                    "Array stack[] is shorter than nStack");
+        }
+        for (int i = 0; i < nStack; ++i) {
+            checkFrameValue(stack[i]);
+        }
+        if (type == Opcodes.F_NEW) {
+            ++expandedFrames;
+        } else {
+            ++compressedFrames;
+        }
+        if (expandedFrames > 0 && compressedFrames > 0) {
+            throw new RuntimeException(
+                    "Expanded and compressed frames must not be mixed.");
+        }
+        super.visitFrame(type, nLocal, local, nStack, stack);
+    }
+
+    @Override
+    public void visitInsn(final int opcode) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode(opcode, 0);
+        super.visitInsn(opcode);
+        ++insnCount;
+    }
+
+    @Override
+    public void visitIntInsn(final int opcode, final int operand) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode(opcode, 1);
+        switch (opcode) {
+        case Opcodes.BIPUSH:
+            checkSignedByte(operand, "Invalid operand");
+            break;
+        case Opcodes.SIPUSH:
+            checkSignedShort(operand, "Invalid operand");
+            break;
+        // case Constants.NEWARRAY:
+        default:
+            if (operand < Opcodes.T_BOOLEAN || operand > Opcodes.T_LONG) {
+                throw new IllegalArgumentException(
+                        "Invalid operand (must be an array type code T_...): "
+                                + operand);
+            }
+        }
+        super.visitIntInsn(opcode, operand);
+        ++insnCount;
+    }
+
+    @Override
+    public void visitVarInsn(final int opcode, final int var) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode(opcode, 2);
+        checkUnsignedShort(var, "Invalid variable index");
+        super.visitVarInsn(opcode, var);
+        ++insnCount;
+    }
+
+    @Override
+    public void visitTypeInsn(final int opcode, final String type) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode(opcode, 3);
+        checkInternalName(type, "type");
+        if (opcode == Opcodes.NEW && type.charAt(0) == '[') {
+            throw new IllegalArgumentException(
+                    "NEW cannot be used to create arrays: " + type);
+        }
+        super.visitTypeInsn(opcode, type);
+        ++insnCount;
+    }
+
+    @Override
+    public void visitFieldInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode(opcode, 4);
+        checkInternalName(owner, "owner");
+        checkUnqualifiedName(version, name, "name");
+        checkDesc(desc, false);
+        super.visitFieldInsn(opcode, owner, name, desc);
+        ++insnCount;
+    }
+
+    @Deprecated
+    @Override
+    public void visitMethodInsn(int opcode, String owner, String name,
+            String desc) {
+        if (api >= Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc,
+                opcode == Opcodes.INVOKEINTERFACE);
+    }
+
+    @Override
+    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;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    private void doVisitMethodInsn(int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode(opcode, 5);
+        if (opcode != Opcodes.INVOKESPECIAL || !"<init>".equals(name)) {
+            checkMethodIdentifier(version, name, "name");
+        }
+        checkInternalName(owner, "owner");
+        checkMethodDesc(desc);
+        if (opcode == Opcodes.INVOKEVIRTUAL && itf) {
+            throw new IllegalArgumentException(
+                    "INVOKEVIRTUAL can't be used with interfaces");
+        }
+        if (opcode == Opcodes.INVOKEINTERFACE && !itf) {
+            throw new IllegalArgumentException(
+                    "INVOKEINTERFACE can't be used with classes");
+        }
+        // Calling super.visitMethodInsn requires to call the correct version
+        // depending on this.api (otherwise infinite loops can occur). To
+        // simplify and to make it easier to automatically remove the backward
+        // compatibility code, we inline the code of the overridden method here.
+        if (mv != null) {
+            mv.visitMethodInsn(opcode, owner, name, desc, itf);
+        }
+        ++insnCount;
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+            Object... bsmArgs) {
+        checkStartCode();
+        checkEndCode();
+        checkMethodIdentifier(version, name, "name");
+        checkMethodDesc(desc);
+        if (bsm.getTag() != Opcodes.H_INVOKESTATIC
+                && bsm.getTag() != Opcodes.H_NEWINVOKESPECIAL) {
+            throw new IllegalArgumentException("invalid handle tag "
+                    + bsm.getTag());
+        }
+        for (int i = 0; i < bsmArgs.length; i++) {
+            checkLDCConstant(bsmArgs[i]);
+        }
+        super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+        ++insnCount;
+    }
+
+    @Override
+    public void visitJumpInsn(final int opcode, final Label label) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode(opcode, 6);
+        checkLabel(label, false, "label");
+        checkNonDebugLabel(label);
+        super.visitJumpInsn(opcode, label);
+        usedLabels.add(label);
+        ++insnCount;
+    }
+
+    @Override
+    public void visitLabel(final Label label) {
+        checkStartCode();
+        checkEndCode();
+        checkLabel(label, false, "label");
+        if (labels.get(label) != null) {
+            throw new IllegalArgumentException("Already visited label");
+        }
+        labels.put(label, new Integer(insnCount));
+        super.visitLabel(label);
+    }
+
+    @Override
+    public void visitLdcInsn(final Object cst) {
+        checkStartCode();
+        checkEndCode();
+        checkLDCConstant(cst);
+        super.visitLdcInsn(cst);
+        ++insnCount;
+    }
+
+    @Override
+    public void visitIincInsn(final int var, final int increment) {
+        checkStartCode();
+        checkEndCode();
+        checkUnsignedShort(var, "Invalid variable index");
+        checkSignedShort(increment, "Invalid increment");
+        super.visitIincInsn(var, increment);
+        ++insnCount;
+    }
+
+    @Override
+    public void visitTableSwitchInsn(final int min, final int max,
+            final Label dflt, final Label... labels) {
+        checkStartCode();
+        checkEndCode();
+        if (max < min) {
+            throw new IllegalArgumentException("Max = " + max
+                    + " must be greater than or equal to min = " + min);
+        }
+        checkLabel(dflt, false, "default label");
+        checkNonDebugLabel(dflt);
+        if (labels == null || labels.length != max - min + 1) {
+            throw new IllegalArgumentException(
+                    "There must be max - min + 1 labels");
+        }
+        for (int i = 0; i < labels.length; ++i) {
+            checkLabel(labels[i], false, "label at index " + i);
+            checkNonDebugLabel(labels[i]);
+        }
+        super.visitTableSwitchInsn(min, max, dflt, labels);
+        for (int i = 0; i < labels.length; ++i) {
+            usedLabels.add(labels[i]);
+        }
+        ++insnCount;
+    }
+
+    @Override
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+            final Label[] labels) {
+        checkEndCode();
+        checkStartCode();
+        checkLabel(dflt, false, "default label");
+        checkNonDebugLabel(dflt);
+        if (keys == null || labels == null || keys.length != labels.length) {
+            throw new IllegalArgumentException(
+                    "There must be the same number of keys and labels");
+        }
+        for (int i = 0; i < labels.length; ++i) {
+            checkLabel(labels[i], false, "label at index " + i);
+            checkNonDebugLabel(labels[i]);
+        }
+        super.visitLookupSwitchInsn(dflt, keys, labels);
+        usedLabels.add(dflt);
+        for (int i = 0; i < labels.length; ++i) {
+            usedLabels.add(labels[i]);
+        }
+        ++insnCount;
+    }
+
+    @Override
+    public void visitMultiANewArrayInsn(final String desc, final int dims) {
+        checkStartCode();
+        checkEndCode();
+        checkDesc(desc, false);
+        if (desc.charAt(0) != '[') {
+            throw new IllegalArgumentException(
+                    "Invalid descriptor (must be an array type descriptor): "
+                            + desc);
+        }
+        if (dims < 1) {
+            throw new IllegalArgumentException(
+                    "Invalid dimensions (must be greater than 0): " + dims);
+        }
+        if (dims > desc.lastIndexOf('[') + 1) {
+            throw new IllegalArgumentException(
+                    "Invalid dimensions (must not be greater than dims(desc)): "
+                            + dims);
+        }
+        super.visitMultiANewArrayInsn(desc, dims);
+        ++insnCount;
+    }
+
+    @Override
+    public AnnotationVisitor visitInsnAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        checkStartCode();
+        checkEndCode();
+        int sort = typeRef >>> 24;
+        if (sort != TypeReference.INSTANCEOF && sort != TypeReference.NEW
+                && sort != TypeReference.CONSTRUCTOR_REFERENCE
+                && sort != TypeReference.METHOD_REFERENCE
+                && sort != TypeReference.CAST
+                && sort != TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+                && sort != TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT
+                && sort != TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+                && sort != TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT) {
+            throw new IllegalArgumentException("Invalid type reference sort 0x"
+                    + Integer.toHexString(sort));
+        }
+        CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+        CheckMethodAdapter.checkDesc(desc, false);
+        return new CheckAnnotationAdapter(super.visitInsnAnnotation(typeRef,
+                typePath, desc, visible));
+    }
+
+    @Override
+    public void visitTryCatchBlock(final Label start, final Label end,
+            final Label handler, final String type) {
+        checkStartCode();
+        checkEndCode();
+        checkLabel(start, false, "start label");
+        checkLabel(end, false, "end label");
+        checkLabel(handler, false, "handler label");
+        checkNonDebugLabel(start);
+        checkNonDebugLabel(end);
+        checkNonDebugLabel(handler);
+        if (labels.get(start) != null || labels.get(end) != null
+                || labels.get(handler) != null) {
+            throw new IllegalStateException(
+                    "Try catch blocks must be visited before their labels");
+        }
+        if (type != null) {
+            checkInternalName(type, "type");
+        }
+        super.visitTryCatchBlock(start, end, handler, type);
+        handlers.add(start);
+        handlers.add(end);
+    }
+
+    @Override
+    public AnnotationVisitor visitTryCatchAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        checkStartCode();
+        checkEndCode();
+        int sort = typeRef >>> 24;
+        if (sort != TypeReference.EXCEPTION_PARAMETER) {
+            throw new IllegalArgumentException("Invalid type reference sort 0x"
+                    + Integer.toHexString(sort));
+        }
+        CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+        CheckMethodAdapter.checkDesc(desc, false);
+        return new CheckAnnotationAdapter(super.visitTryCatchAnnotation(
+                typeRef, typePath, desc, visible));
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,
+            final String signature, final Label start, final Label end,
+            final int index) {
+        checkStartCode();
+        checkEndCode();
+        checkUnqualifiedName(version, name, "name");
+        checkDesc(desc, false);
+        checkLabel(start, true, "start label");
+        checkLabel(end, true, "end label");
+        checkUnsignedShort(index, "Invalid variable index");
+        int s = labels.get(start).intValue();
+        int e = labels.get(end).intValue();
+        if (e < s) {
+            throw new IllegalArgumentException(
+                    "Invalid start and end labels (end must be greater than start)");
+        }
+        super.visitLocalVariable(name, desc, signature, start, end, index);
+    }
+
+    @Override
+    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+            TypePath typePath, Label[] start, Label[] end, int[] index,
+            String desc, boolean visible) {
+        checkStartCode();
+        checkEndCode();
+        int sort = typeRef >>> 24;
+        if (sort != TypeReference.LOCAL_VARIABLE
+                && sort != TypeReference.RESOURCE_VARIABLE) {
+            throw new IllegalArgumentException("Invalid type reference sort 0x"
+                    + Integer.toHexString(sort));
+        }
+        CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+        checkDesc(desc, false);
+        if (start == null || end == null || index == null
+                || end.length != start.length || index.length != start.length) {
+            throw new IllegalArgumentException(
+                    "Invalid start, end and index arrays (must be non null and of identical length");
+        }
+        for (int i = 0; i < start.length; ++i) {
+            checkLabel(start[i], true, "start label");
+            checkLabel(end[i], true, "end label");
+            checkUnsignedShort(index[i], "Invalid variable index");
+            int s = labels.get(start[i]).intValue();
+            int e = labels.get(end[i]).intValue();
+            if (e < s) {
+                throw new IllegalArgumentException(
+                        "Invalid start and end labels (end must be greater than start)");
+            }
+        }
+        return super.visitLocalVariableAnnotation(typeRef, typePath, start,
+                end, index, desc, visible);
+    }
+
+    @Override
+    public void visitLineNumber(final int line, final Label start) {
+        checkStartCode();
+        checkEndCode();
+        checkUnsignedShort(line, "Invalid line number");
+        checkLabel(start, true, "start label");
+        super.visitLineNumber(line, start);
+    }
+
+    @Override
+    public void visitMaxs(final int maxStack, final int maxLocals) {
+        checkStartCode();
+        checkEndCode();
+        endCode = true;
+        for (Label l : usedLabels) {
+            if (labels.get(l) == null) {
+                throw new IllegalStateException("Undefined label used");
+            }
+        }
+        for (int i = 0; i < handlers.size();) {
+            Integer start = labels.get(handlers.get(i++));
+            Integer end = labels.get(handlers.get(i++));
+            if (start == null || end == null) {
+                throw new IllegalStateException(
+                        "Undefined try catch block labels");
+            }
+            if (end.intValue() <= start.intValue()) {
+                throw new IllegalStateException(
+                        "Emty try catch block handler range");
+            }
+        }
+        checkUnsignedShort(maxStack, "Invalid max stack");
+        checkUnsignedShort(maxLocals, "Invalid max locals");
+        super.visitMaxs(maxStack, maxLocals);
+    }
+
+    @Override
+    public void visitEnd() {
+        checkEndMethod();
+        endMethod = true;
+        super.visitEnd();
+    }
+
+    // -------------------------------------------------------------------------
+
+    /**
+     * Checks that the visitCode method has been called.
+     */
+    void checkStartCode() {
+        if (!startCode) {
+            throw new IllegalStateException(
+                    "Cannot visit instructions before visitCode has been called.");
+        }
+    }
+
+    /**
+     * Checks that the visitMaxs method has not been called.
+     */
+    void checkEndCode() {
+        if (endCode) {
+            throw new IllegalStateException(
+                    "Cannot visit instructions after visitMaxs has been called.");
+        }
+    }
+
+    /**
+     * Checks that the visitEnd method has not been called.
+     */
+    void checkEndMethod() {
+        if (endMethod) {
+            throw new IllegalStateException(
+                    "Cannot visit elements after visitEnd has been called.");
+        }
+    }
+
+    /**
+     * Checks a stack frame value.
+     * 
+     * @param value
+     *            the value to be checked.
+     */
+    void checkFrameValue(final Object value) {
+        if (value == Opcodes.TOP || value == Opcodes.INTEGER
+                || value == Opcodes.FLOAT || value == Opcodes.LONG
+                || value == Opcodes.DOUBLE || value == Opcodes.NULL
+                || value == Opcodes.UNINITIALIZED_THIS) {
+            return;
+        }
+        if (value instanceof String) {
+            checkInternalName((String) value, "Invalid stack frame value");
+            return;
+        }
+        if (!(value instanceof Label)) {
+            throw new IllegalArgumentException("Invalid stack frame value: "
+                    + value);
+        } else {
+            usedLabels.add((Label) value);
+        }
+    }
+
+    /**
+     * Checks that the type of the given opcode is equal to the given type.
+     * 
+     * @param opcode
+     *            the opcode to be checked.
+     * @param type
+     *            the expected opcode type.
+     */
+    static void checkOpcode(final int opcode, final int type) {
+        if (opcode < 0 || opcode > 199 || TYPE[opcode] != type) {
+            throw new IllegalArgumentException("Invalid opcode: " + opcode);
+        }
+    }
+
+    /**
+     * Checks that the given value is a signed byte.
+     * 
+     * @param value
+     *            the value to be checked.
+     * @param msg
+     *            an message to be used in case of error.
+     */
+    static void checkSignedByte(final int value, final String msg) {
+        if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
+            throw new IllegalArgumentException(msg
+                    + " (must be a signed byte): " + value);
+        }
+    }
+
+    /**
+     * Checks that the given value is a signed short.
+     * 
+     * @param value
+     *            the value to be checked.
+     * @param msg
+     *            an message to be used in case of error.
+     */
+    static void checkSignedShort(final int value, final String msg) {
+        if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
+            throw new IllegalArgumentException(msg
+                    + " (must be a signed short): " + value);
+        }
+    }
+
+    /**
+     * Checks that the given value is an unsigned short.
+     * 
+     * @param value
+     *            the value to be checked.
+     * @param msg
+     *            an message to be used in case of error.
+     */
+    static void checkUnsignedShort(final int value, final String msg) {
+        if (value < 0 || value > 65535) {
+            throw new IllegalArgumentException(msg
+                    + " (must be an unsigned short): " + value);
+        }
+    }
+
+    /**
+     * Checks that the given value is an {@link Integer}, a{@link Float}, a
+     * {@link Long}, a {@link Double} or a {@link String}.
+     * 
+     * @param cst
+     *            the value to be checked.
+     */
+    static void checkConstant(final Object cst) {
+        if (!(cst instanceof Integer) && !(cst instanceof Float)
+                && !(cst instanceof Long) && !(cst instanceof Double)
+                && !(cst instanceof String)) {
+            throw new IllegalArgumentException("Invalid constant: " + cst);
+        }
+    }
+
+    void checkLDCConstant(final Object cst) {
+        if (cst instanceof Type) {
+            int s = ((Type) cst).getSort();
+            if (s != Type.OBJECT && s != Type.ARRAY && s != Type.METHOD) {
+                throw new IllegalArgumentException("Illegal LDC constant value");
+            }
+            if (s != Type.METHOD && (version & 0xFFFF) < Opcodes.V1_5) {
+                throw new IllegalArgumentException(
+                        "ldc of a constant class requires at least version 1.5");
+            }
+            if (s == Type.METHOD && (version & 0xFFFF) < Opcodes.V1_7) {
+                throw new IllegalArgumentException(
+                        "ldc of a method type requires at least version 1.7");
+            }
+        } else if (cst instanceof Handle) {
+            if ((version & 0xFFFF) < Opcodes.V1_7) {
+                throw new IllegalArgumentException(
+                        "ldc of a handle requires at least version 1.7");
+            }
+            int tag = ((Handle) cst).getTag();
+            if (tag < Opcodes.H_GETFIELD || tag > Opcodes.H_INVOKEINTERFACE) {
+                throw new IllegalArgumentException("invalid handle tag " + tag);
+            }
+        } else {
+            checkConstant(cst);
+        }
+    }
+
+    /**
+     * Checks that the given string is a valid unqualified name.
+     * 
+     * @param version
+     *            the class version.
+     * @param name
+     *            the string to be checked.
+     * @param msg
+     *            a message to be used in case of error.
+     */
+    static void checkUnqualifiedName(int version, final String name,
+            final String msg) {
+        if ((version & 0xFFFF) < Opcodes.V1_5) {
+            checkIdentifier(name, msg);
+        } else {
+            for (int i = 0; i < name.length(); ++i) {
+                if (".;[/".indexOf(name.charAt(i)) != -1) {
+                    throw new IllegalArgumentException("Invalid " + msg
+                            + " (must be a valid unqualified name): " + name);
+                }
+            }
+        }
+    }
+
+    /**
+     * Checks that the given string is a valid Java identifier.
+     * 
+     * @param name
+     *            the string to be checked.
+     * @param msg
+     *            a message to be used in case of error.
+     */
+    static void checkIdentifier(final String name, final String msg) {
+        checkIdentifier(name, 0, -1, msg);
+    }
+
+    /**
+     * Checks that the given substring is a valid Java identifier.
+     * 
+     * @param name
+     *            the string to be checked.
+     * @param start
+     *            index of the first character of the identifier (inclusive).
+     * @param end
+     *            index of the last character of the identifier (exclusive). -1
+     *            is equivalent to <tt>name.length()</tt> if name is not
+     *            <tt>null</tt>.
+     * @param msg
+     *            a message to be used in case of error.
+     */
+    static void checkIdentifier(final String name, final int start,
+            final int end, final String msg) {
+        if (name == null || (end == -1 ? name.length() <= start : end <= start)) {
+            throw new IllegalArgumentException("Invalid " + msg
+                    + " (must not be null or empty)");
+        }
+        if (!Character.isJavaIdentifierStart(name.charAt(start))) {
+            throw new IllegalArgumentException("Invalid " + msg
+                    + " (must be a valid Java identifier): " + name);
+        }
+        int max = end == -1 ? name.length() : end;
+        for (int i = start + 1; i < max; ++i) {
+            if (!Character.isJavaIdentifierPart(name.charAt(i))) {
+                throw new IllegalArgumentException("Invalid " + msg
+                        + " (must be a valid Java identifier): " + name);
+            }
+        }
+    }
+
+    /**
+     * Checks that the given string is a valid Java identifier.
+     * 
+     * @param version
+     *            the class version.
+     * @param name
+     *            the string to be checked.
+     * @param msg
+     *            a message to be used in case of error.
+     */
+    static void checkMethodIdentifier(int version, final String name,
+            final String msg) {
+        if (name == null || name.length() == 0) {
+            throw new IllegalArgumentException("Invalid " + msg
+                    + " (must not be null or empty)");
+        }
+        if ((version & 0xFFFF) >= Opcodes.V1_5) {
+            for (int i = 0; i < name.length(); ++i) {
+                if (".;[/<>".indexOf(name.charAt(i)) != -1) {
+                    throw new IllegalArgumentException("Invalid " + msg
+                            + " (must be a valid unqualified name): " + name);
+                }
+            }
+            return;
+        }
+        if (!Character.isJavaIdentifierStart(name.charAt(0))) {
+            throw new IllegalArgumentException(
+                    "Invalid "
+                            + msg
+                            + " (must be a '<init>', '<clinit>' or a valid Java identifier): "
+                            + name);
+        }
+        for (int i = 1; i < name.length(); ++i) {
+            if (!Character.isJavaIdentifierPart(name.charAt(i))) {
+                throw new IllegalArgumentException(
+                        "Invalid "
+                                + msg
+                                + " (must be '<init>' or '<clinit>' or a valid Java identifier): "
+                                + name);
+            }
+        }
+    }
+
+    /**
+     * Checks that the given string is a valid internal class name.
+     * 
+     * @param name
+     *            the string to be checked.
+     * @param msg
+     *            a message to be used in case of error.
+     */
+    static void checkInternalName(final String name, final String msg) {
+        if (name == null || name.length() == 0) {
+            throw new IllegalArgumentException("Invalid " + msg
+                    + " (must not be null or empty)");
+        }
+        if (name.charAt(0) == '[') {
+            checkDesc(name, false);
+        } else {
+            checkInternalName(name, 0, -1, msg);
+        }
+    }
+
+    /**
+     * Checks that the given substring is a valid internal class name.
+     * 
+     * @param name
+     *            the string to be checked.
+     * @param start
+     *            index of the first character of the identifier (inclusive).
+     * @param end
+     *            index of the last character of the identifier (exclusive). -1
+     *            is equivalent to <tt>name.length()</tt> if name is not
+     *            <tt>null</tt>.
+     * @param msg
+     *            a message to be used in case of error.
+     */
+    static void checkInternalName(final String name, final int start,
+            final int end, final String msg) {
+        int max = end == -1 ? name.length() : end;
+        try {
+            int begin = start;
+            int slash;
+            do {
+                slash = name.indexOf('/', begin + 1);
+                if (slash == -1 || slash > max) {
+                    slash = max;
+                }
+                checkIdentifier(name, begin, slash, null);
+                begin = slash + 1;
+            } while (slash != max);
+        } catch (IllegalArgumentException unused) {
+            throw new IllegalArgumentException(
+                    "Invalid "
+                            + msg
+                            + " (must be a fully qualified class name in internal form): "
+                            + name);
+        }
+    }
+
+    /**
+     * Checks that the given string is a valid type descriptor.
+     * 
+     * @param desc
+     *            the string to be checked.
+     * @param canBeVoid
+     *            <tt>true</tt> if <tt>V</tt> can be considered valid.
+     */
+    static void checkDesc(final String desc, final boolean canBeVoid) {
+        int end = checkDesc(desc, 0, canBeVoid);
+        if (end != desc.length()) {
+            throw new IllegalArgumentException("Invalid descriptor: " + desc);
+        }
+    }
+
+    /**
+     * Checks that a the given substring is a valid type descriptor.
+     * 
+     * @param desc
+     *            the string to be checked.
+     * @param start
+     *            index of the first character of the identifier (inclusive).
+     * @param canBeVoid
+     *            <tt>true</tt> if <tt>V</tt> can be considered valid.
+     * @return the index of the last character of the type decriptor, plus one.
+     */
+    static int checkDesc(final String desc, final int start,
+            final boolean canBeVoid) {
+        if (desc == null || start >= desc.length()) {
+            throw new IllegalArgumentException(
+                    "Invalid type descriptor (must not be null or empty)");
+        }
+        int index;
+        switch (desc.charAt(start)) {
+        case 'V':
+            if (canBeVoid) {
+                return start + 1;
+            } else {
+                throw new IllegalArgumentException("Invalid descriptor: "
+                        + desc);
+            }
+        case 'Z':
+        case 'C':
+        case 'B':
+        case 'S':
+        case 'I':
+        case 'F':
+        case 'J':
+        case 'D':
+            return start + 1;
+        case '[':
+            index = start + 1;
+            while (index < desc.length() && desc.charAt(index) == '[') {
+                ++index;
+            }
+            if (index < desc.length()) {
+                return checkDesc(desc, index, false);
+            } else {
+                throw new IllegalArgumentException("Invalid descriptor: "
+                        + desc);
+            }
+        case 'L':
+            index = desc.indexOf(';', start);
+            if (index == -1 || index - start < 2) {
+                throw new IllegalArgumentException("Invalid descriptor: "
+                        + desc);
+            }
+            try {
+                checkInternalName(desc, start + 1, index, null);
+            } catch (IllegalArgumentException unused) {
+                throw new IllegalArgumentException("Invalid descriptor: "
+                        + desc);
+            }
+            return index + 1;
+        default:
+            throw new IllegalArgumentException("Invalid descriptor: " + desc);
+        }
+    }
+
+    /**
+     * Checks that the given string is a valid method descriptor.
+     * 
+     * @param desc
+     *            the string to be checked.
+     */
+    static void checkMethodDesc(final String desc) {
+        if (desc == null || desc.length() == 0) {
+            throw new IllegalArgumentException(
+                    "Invalid method descriptor (must not be null or empty)");
+        }
+        if (desc.charAt(0) != '(' || desc.length() < 3) {
+            throw new IllegalArgumentException("Invalid descriptor: " + desc);
+        }
+        int start = 1;
+        if (desc.charAt(start) != ')') {
+            do {
+                if (desc.charAt(start) == 'V') {
+                    throw new IllegalArgumentException("Invalid descriptor: "
+                            + desc);
+                }
+                start = checkDesc(desc, start, false);
+            } while (start < desc.length() && desc.charAt(start) != ')');
+        }
+        start = checkDesc(desc, start + 1, true);
+        if (start != desc.length()) {
+            throw new IllegalArgumentException("Invalid descriptor: " + desc);
+        }
+    }
+
+    /**
+     * Checks that the given label is not null. This method can also check that
+     * the label has been visited.
+     * 
+     * @param label
+     *            the label to be checked.
+     * @param checkVisited
+     *            <tt>true</tt> to check that the label has been visited.
+     * @param msg
+     *            a message to be used in case of error.
+     */
+    void checkLabel(final Label label, final boolean checkVisited,
+            final String msg) {
+        if (label == null) {
+            throw new IllegalArgumentException("Invalid " + msg
+                    + " (must not be null)");
+        }
+        if (checkVisited && labels.get(label) == null) {
+            throw new IllegalArgumentException("Invalid " + msg
+                    + " (must be visited first)");
+        }
+    }
+
+    /**
+     * Checks that the given label is not a label used only for debug purposes.
+     * 
+     * @param label
+     *            the label to be checked.
+     */
+    private static void checkNonDebugLabel(final Label label) {
+        Field f = getLabelStatusField();
+        int status = 0;
+        try {
+            status = f == null ? 0 : ((Integer) f.get(label)).intValue();
+        } catch (IllegalAccessException e) {
+            throw new Error("Internal error");
+        }
+        if ((status & 0x01) != 0) {
+            throw new IllegalArgumentException(
+                    "Labels used for debug info cannot be reused for control flow");
+        }
+    }
+
+    /**
+     * Returns the Field object corresponding to the Label.status field.
+     * 
+     * @return the Field object corresponding to the Label.status field.
+     */
+    private static Field getLabelStatusField() {
+        if (labelStatusField == null) {
+            labelStatusField = getLabelField("a");
+            if (labelStatusField == null) {
+                labelStatusField = getLabelField("status");
+            }
+        }
+        return labelStatusField;
+    }
+
+    /**
+     * Returns the field of the Label class whose name is given.
+     * 
+     * @param name
+     *            a field name.
+     * @return the field of the Label class whose name is given, or null.
+     */
+    private static Field getLabelField(final String name) {
+        try {
+            Field f = Label.class.getDeclaredField(name);
+            f.setAccessible(true);
+            return f;
+        } catch (NoSuchFieldException e) {
+            return null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
new file mode 100644
index 0000000..cf1f98b
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
@@ -0,0 +1,330 @@
+/***
+ * 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.util;
+
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
+
+/**
+ * A {@link SignatureVisitor} that checks that its methods are properly used.
+ * 
+ * @author Eric Bruneton
+ */
+public class CheckSignatureAdapter extends SignatureVisitor {
+
+    /**
+     * Type to be used to check class signatures. See
+     * {@link #CheckSignatureAdapter(int, SignatureVisitor)
+     * CheckSignatureAdapter}.
+     */
+    public static final int CLASS_SIGNATURE = 0;
+
+    /**
+     * Type to be used to check method signatures. See
+     * {@link #CheckSignatureAdapter(int, SignatureVisitor)
+     * CheckSignatureAdapter}.
+     */
+    public static final int METHOD_SIGNATURE = 1;
+
+    /**
+     * Type to be used to check type signatures.See
+     * {@link #CheckSignatureAdapter(int, SignatureVisitor)
+     * CheckSignatureAdapter}.
+     */
+    public static final int TYPE_SIGNATURE = 2;
+
+    private static final int EMPTY = 1;
+
+    private static final int FORMAL = 2;
+
+    private static final int BOUND = 4;
+
+    private static final int SUPER = 8;
+
+    private static final int PARAM = 16;
+
+    private static final int RETURN = 32;
+
+    private static final int SIMPLE_TYPE = 64;
+
+    private static final int CLASS_TYPE = 128;
+
+    private static final int END = 256;
+
+    /**
+     * Type of the signature to be checked.
+     */
+    private final int type;
+
+    /**
+     * State of the automaton used to check the order of method calls.
+     */
+    private int state;
+
+    /**
+     * <tt>true</tt> if the checked type signature can be 'V'.
+     */
+    private boolean canBeVoid;
+
+    /**
+     * The visitor to which this adapter must delegate calls. May be
+     * <tt>null</tt>.
+     */
+    private final SignatureVisitor sv;
+
+    /**
+     * Creates a new {@link CheckSignatureAdapter} object. <i>Subclasses must
+     * not use this constructor</i>. Instead, they must use the
+     * {@link #CheckSignatureAdapter(int, int, SignatureVisitor)} version.
+     * 
+     * @param type
+     *            the type of signature to be checked. See
+     *            {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and
+     *            {@link #TYPE_SIGNATURE}.
+     * @param sv
+     *            the visitor to which this adapter must delegate calls. May be
+     *            <tt>null</tt>.
+     */
+    public CheckSignatureAdapter(final int type, final SignatureVisitor sv) {
+        this(Opcodes.ASM5, type, sv);
+    }
+
+    /**
+     * Creates a new {@link CheckSignatureAdapter} object.
+     * 
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @param type
+     *            the type of signature to be checked. See
+     *            {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and
+     *            {@link #TYPE_SIGNATURE}.
+     * @param sv
+     *            the visitor to which this adapter must delegate calls. May be
+     *            <tt>null</tt>.
+     */
+    protected CheckSignatureAdapter(final int api, final int type,
+            final SignatureVisitor sv) {
+        super(api);
+        this.type = type;
+        this.state = EMPTY;
+        this.sv = sv;
+    }
+
+    // class and method signatures
+
+    @Override
+    public void visitFormalTypeParameter(final String name) {
+        if (type == TYPE_SIGNATURE
+                || (state != EMPTY && state != FORMAL && state != BOUND)) {
+            throw new IllegalStateException();
+        }
+        CheckMethodAdapter.checkIdentifier(name, "formal type parameter");
+        state = FORMAL;
+        if (sv != null) {
+            sv.visitFormalTypeParameter(name);
+        }
+    }
+
+    @Override
+    public SignatureVisitor visitClassBound() {
+        if (state != FORMAL) {
+            throw new IllegalStateException();
+        }
+        state = BOUND;
+        SignatureVisitor v = sv == null ? null : sv.visitClassBound();
+        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+    }
+
+    @Override
+    public SignatureVisitor visitInterfaceBound() {
+        if (state != FORMAL && state != BOUND) {
+            throw new IllegalArgumentException();
+        }
+        SignatureVisitor v = sv == null ? null : sv.visitInterfaceBound();
+        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+    }
+
+    // class signatures
+
+    @Override
+    public SignatureVisitor visitSuperclass() {
+        if (type != CLASS_SIGNATURE || (state & (EMPTY | FORMAL | BOUND)) == 0) {
+            throw new IllegalArgumentException();
+        }
+        state = SUPER;
+        SignatureVisitor v = sv == null ? null : sv.visitSuperclass();
+        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+    }
+
+    @Override
+    public SignatureVisitor visitInterface() {
+        if (state != SUPER) {
+            throw new IllegalStateException();
+        }
+        SignatureVisitor v = sv == null ? null : sv.visitInterface();
+        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+    }
+
+    // method signatures
+
+    @Override
+    public SignatureVisitor visitParameterType() {
+        if (type != METHOD_SIGNATURE
+                || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) {
+            throw new IllegalArgumentException();
+        }
+        state = PARAM;
+        SignatureVisitor v = sv == null ? null : sv.visitParameterType();
+        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+    }
+
+    @Override
+    public SignatureVisitor visitReturnType() {
+        if (type != METHOD_SIGNATURE
+                || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) {
+            throw new IllegalArgumentException();
+        }
+        state = RETURN;
+        SignatureVisitor v = sv == null ? null : sv.visitReturnType();
+        CheckSignatureAdapter cv = new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+        cv.canBeVoid = true;
+        return cv;
+    }
+
+    @Override
+    public SignatureVisitor visitExceptionType() {
+        if (state != RETURN) {
+            throw new IllegalStateException();
+        }
+        SignatureVisitor v = sv == null ? null : sv.visitExceptionType();
+        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+    }
+
+    // type signatures
+
+    @Override
+    public void visitBaseType(final char descriptor) {
+        if (type != TYPE_SIGNATURE || state != EMPTY) {
+            throw new IllegalStateException();
+        }
+        if (descriptor == 'V') {
+            if (!canBeVoid) {
+                throw new IllegalArgumentException();
+            }
+        } else {
+            if ("ZCBSIFJD".indexOf(descriptor) == -1) {
+                throw new IllegalArgumentException();
+            }
+        }
+        state = SIMPLE_TYPE;
+        if (sv != null) {
+            sv.visitBaseType(descriptor);
+        }
+    }
+
+    @Override
+    public void visitTypeVariable(final String name) {
+        if (type != TYPE_SIGNATURE || state != EMPTY) {
+            throw new IllegalStateException();
+        }
+        CheckMethodAdapter.checkIdentifier(name, "type variable");
+        state = SIMPLE_TYPE;
+        if (sv != null) {
+            sv.visitTypeVariable(name);
+        }
+    }
+
+    @Override
+    public SignatureVisitor visitArrayType() {
+        if (type != TYPE_SIGNATURE || state != EMPTY) {
+            throw new IllegalStateException();
+        }
+        state = SIMPLE_TYPE;
+        SignatureVisitor v = sv == null ? null : sv.visitArrayType();
+        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+    }
+
+    @Override
+    public void visitClassType(final String name) {
+        if (type != TYPE_SIGNATURE || state != EMPTY) {
+            throw new IllegalStateException();
+        }
+        CheckMethodAdapter.checkInternalName(name, "class name");
+        state = CLASS_TYPE;
+        if (sv != null) {
+            sv.visitClassType(name);
+        }
+    }
+
+    @Override
+    public void visitInnerClassType(final String name) {
+        if (state != CLASS_TYPE) {
+            throw new IllegalStateException();
+        }
+        CheckMethodAdapter.checkIdentifier(name, "inner class name");
+        if (sv != null) {
+            sv.visitInnerClassType(name);
+        }
+    }
+
+    @Override
+    public void visitTypeArgument() {
+        if (state != CLASS_TYPE) {
+            throw new IllegalStateException();
+        }
+        if (sv != null) {
+            sv.visitTypeArgument();
+        }
+    }
+
+    @Override
+    public SignatureVisitor visitTypeArgument(final char wildcard) {
+        if (state != CLASS_TYPE) {
+            throw new IllegalStateException();
+        }
+        if ("+-=".indexOf(wildcard) == -1) {
+            throw new IllegalArgumentException();
+        }
+        SignatureVisitor v = sv == null ? null : sv.visitTypeArgument(wildcard);
+        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+    }
+
+    @Override
+    public void visitEnd() {
+        if (state != CLASS_TYPE) {
+            throw new IllegalStateException();
+        }
+        state = END;
+        if (sv != null) {
+            sv.visitEnd();
+        }
+    }
+}