You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by th...@apache.org on 2018/11/29 00:34:02 UTC

[15/46] tapestry-5 git commit: TAP5-2588: upgrading from ASM 6 to 7 for Java 9+ support

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/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
old mode 100644
new mode 100755
index b7c94c8..afe4d78
--- 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
@@ -1,226 +1,268 @@
-/***
- * 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.
- */
+// 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.TryCatchBlockNode;
 
 /**
- * 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.
- * 
+ * 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);
+  /**
+   * The ASM API version supported by this interpreter. The value of this field must be one of
+   * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM4}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM5}, {@link
+   * org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM6} or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM7}.
+   */
+  protected final int api;
+
+  /**
+   * Constructs a new {@link Interpreter}.
+   *
+   * @param api the ASM API version supported by this interpreter. Must be one of {@link
+   *     org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM4}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM5}, {@link
+   *     org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM6} or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM7}.
+   */
+  protected Interpreter(final int api) {
+    this.api = api;
+  }
+
+  /**
+   * Creates a new value that represents the given type.
+   *
+   * <p>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.
+   *
+   * <p>An interpreter may choose to implement one or more of {@link
+   * Interpreter#newReturnTypeValue(Type)}, {@link Interpreter#newParameterValue(boolean, int,
+   * Type)}, {@link Interpreter#newEmptyValue(int)}, {@link
+   * Interpreter#newExceptionValue(TryCatchBlockNode, Frame, Type)} to distinguish different types
+   * of new value.
+   *
+   * @param type a primitive or reference type, or {@literal null} 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);
+
+  /**
+   * Creates a new value that represents the given parameter type. This method is called to
+   * initialize the value of a local corresponding to a method parameter in a frame.
+   *
+   * <p>By default, calls <code>newValue(type)</code>.
+   *
+   * @param isInstanceMethod {@literal true} if the method is non-static.
+   * @param local the local variable index.
+   * @param type a primitive or reference type.
+   * @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 V newParameterValue(final boolean isInstanceMethod, final int local, final Type type) {
+    return newValue(type);
+  }
+
+  /**
+   * Creates a new value that represents the given return type. This method is called to initialize
+   * the return type value of a frame.
+   *
+   * <p>By default, calls <code>newValue(type)</code>.
+   *
+   * @param type a primitive or reference type.
+   * @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 V newReturnTypeValue(final Type type) {
+    return newValue(type);
+  }
+
+  /**
+   * Creates a new uninitialized value for a local variable. This method is called to initialize the
+   * value of a local that does not correspond to a method parameter, and to reset one half of a
+   * size-2 value when the other half is assigned a size-1 value.
+   *
+   * <p>By default, calls <code>newValue(null)</code>.
+   *
+   * @param local the local variable index.
+   * @return a value representing an uninitialized value. The size of the returned value must be
+   *     equal to 1.
+   */
+  public V newEmptyValue(final int local) {
+    return newValue(null);
+  }
+
+  /**
+   * Creates a new value that represents the given exception type. This method is called to
+   * initialize the exception value on the call stack at the entry of an exception handler.
+   *
+   * <p>By default, calls <code>newValue(exceptionType)</code>.
+   *
+   * @param tryCatchBlockNode the exception handler.
+   * @param handlerFrame the exception handler frame.
+   * @param exceptionType the exception type handled by this handler.
+   * @return a value that represents the given {@code exceptionType}. The size of the returned value
+   *     must be equal to 1.
+   */
+  public V newExceptionValue(
+      final TryCatchBlockNode tryCatchBlockNode,
+      final Frame<V> handlerFrame,
+      final Type exceptionType) {
+    return newValue(exceptionType);
+  }
+
+  /**
+   * Interprets a bytecode instruction without arguments. This method is called for the following
+   * opcodes:
+   *
+   * <p>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 occurred 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:
+   *
+   * <p>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
+   *     {@code equal} to the given value.
+   * @throws AnalyzerException if an error occurred 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:
+   *
+   * <p>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 occurred 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:
+   *
+   * <p>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 occurred 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:
+   *
+   * <p>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 occurred 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:
+   *
+   * <p>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 occurred 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:
+   *
+   * <p>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 occurred 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 value1 a value.
+   * @param value2 another value.
+   * @return the merged value. If the merged value is equal to {@code value1}, this method
+   *     <i>must</i> return {@code value1}.
+   */
+  public abstract V merge(V value1, V value2);
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/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
old mode 100644
new mode 100755
index 0cc2f28..90487a4
--- 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
@@ -1,320 +1,376 @@
-/***
- * 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.
- */
+// 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}).
- * 
+ * 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 {@link
+ * BasicVerifier}).
+ *
  * @author Eric Bruneton
  * @author Bing Ran
  */
 public class SimpleVerifier extends BasicVerifier {
 
-    /**
-     * The class that is verified.
-     */
-    private final Type currentClass;
+  /** The type of the class that is verified. */
+  private final Type currentClass;
 
-    /**
-     * The super class of the class that is verified.
-     */
-    private final Type currentSuperClass;
+  /** The type of 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;
+  /** The types of the interfaces directly 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;
+  /** Whether the class that is verified is an interface. */
+  private final boolean isInterface;
 
-    /**
-     * The loader to use for referenced classes.
-     */
-    private ClassLoader loader = getClass().getClassLoader();
+  /** The loader to use to load the referenced classes. */
+  private ClassLoader loader = getClass().getClassLoader();
 
-    /**
-     * Constructs a new {@link SimpleVerifier}.
-     */
-    public SimpleVerifier() {
-        this(null, null, false);
-    }
+  /**
+   * Constructs a new {@link SimpleVerifier}. <i>Subclasses must not use this constructor</i>.
+   * Instead, they must use the {@link #SimpleVerifier(int, Type, Type, List, boolean)} version.
+   */
+  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. <i>Subclasses must not use this constructor</i>.
+   * Instead, they must use the {@link #SimpleVerifier(int, Type, Type, List, boolean)} version.
+   *
+   * @param currentClass the type of the class to be verified.
+   * @param currentSuperClass the type of the super class of the class to be verified.
+   * @param isInterface whether the class to be verifier 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(ASM6, currentClass, currentSuperClass, currentClassInterfaces,
-                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. <i>Subclasses must not use this constructor</i>.
+   * Instead, they must use the {@link #SimpleVerifier(int, Type, Type, List, boolean)} version.
+   *
+   * @param currentClass the type of the class to be verified.
+   * @param currentSuperClass the type of the super class of the class to be verified.
+   * @param currentClassInterfaces the types of the interfaces directly implemented by the class to
+   *     be verified.
+   * @param isInterface whether the class to be verifier is an interface.
+   */
+  public SimpleVerifier(
+      final Type currentClass,
+      final Type currentSuperClass,
+      final List<Type> currentClassInterfaces,
+      final boolean isInterface) {
+    this(ASM7, currentClass, currentSuperClass, currentClassInterfaces, isInterface);
+    if (getClass() != SimpleVerifier.class) {
+      throw new IllegalStateException();
     }
+  }
+
+  /**
+   * 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 api the ASM API version supported by this verifier. Must be one of {@link
+   *     org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM4}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM5}, {@link
+   *     org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM6} or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM7}.
+   * @param currentClass the type of the class to be verified.
+   * @param currentSuperClass the type of the super class of the class to be verified.
+   * @param currentClassInterfaces the types of the interfaces directly implemented by the class to
+   *     be verified.
+   * @param isInterface whether the class to be verifier is an interface.
+   */
+  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;
+  }
 
-    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;
+  /**
+   * Sets the <code>ClassLoader</code> to be used in {@link #getClass}.
+   *
+   * @param loader the <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;
     }
 
-    /**
-     * 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;
+    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);
+        default:
+          break;
+      }
     }
 
-    @Override
-    public BasicValue newValue(final Type type) {
-        if (type == null) {
-            return BasicValue.UNINITIALIZED_VALUE;
+    BasicValue value = super.newValue(type);
+    if (BasicValue.REFERENCE_VALUE.equals(value)) {
+      if (isArray) {
+        value = newValue(type.getElementType());
+        StringBuilder descriptor = new StringBuilder();
+        for (int i = 0; i < type.getDimensions(); ++i) {
+          descriptor.append('[');
         }
+        descriptor.append(value.getType().getDescriptor());
+        value = new BasicValue(Type.getType(descriptor.toString()));
+      } else {
+        value = new BasicValue(type);
+      }
+    }
+    return 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);
-            }
-        }
+  @Override
+  protected boolean isArrayValue(final BasicValue value) {
+    Type type = value.getType();
+    return type != null && (type.getSort() == Type.ARRAY || type.equals(NULL_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 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 (arrayType.equals(NULL_TYPE)) {
+        return objectArrayValue;
+      }
     }
+    throw new AssertionError();
+  }
 
-    @Override
-    protected boolean isArrayValue(final BasicValue value) {
-        Type t = value.getType();
-        return t != null
-                && ("Lnull;".equals(t.getDescriptor()) || t.getSort() == Type.ARRAY);
+  @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 (type.equals(NULL_TYPE)) {
+          return true;
+        } else if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
+          if (isAssignableFrom(expectedType, type)) {
+            return true;
+          } else if (getClass(expectedType).isInterface()) {
+            // The merge of class or interface types can only yield class types (because it is not
+            // possible in general to find an unambiguous common super interface, due to multiple
+            // inheritance). Because of this limitation, we need to relax the subtyping check here
+            // if 'value' is an interface.
+            return Object.class.isAssignableFrom(getClass(type));
+          } else {
+            return false;
+          }
+        } else {
+          return false;
+        }
+      default:
+        throw new AssertionError();
     }
+  }
 
-    @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;
-            }
+  @Override
+  public BasicValue merge(final BasicValue value1, final BasicValue value2) {
+    if (!value1.equals(value2)) {
+      Type type1 = value1.getType();
+      Type type2 = value2.getType();
+      if (type1 != null
+          && (type1.getSort() == Type.OBJECT || type1.getSort() == Type.ARRAY)
+          && type2 != null
+          && (type2.getSort() == Type.OBJECT || type2.getSort() == Type.ARRAY)) {
+        if (type1.equals(NULL_TYPE)) {
+          return value2;
         }
-        throw new Error("Internal error");
+        if (type2.equals(NULL_TYPE)) {
+          return value1;
+        }
+        if (isAssignableFrom(type1, type2)) {
+          return value1;
+        }
+        if (isAssignableFrom(type2, type1)) {
+          return value2;
+        }
+        int numDimensions = 0;
+        if (type1.getSort() == Type.ARRAY
+            && type2.getSort() == Type.ARRAY
+            && type1.getDimensions() == type2.getDimensions()
+            && type1.getElementType().getSort() == Type.OBJECT
+            && type2.getElementType().getSort() == Type.OBJECT) {
+          numDimensions = type1.getDimensions();
+          type1 = type1.getElementType();
+          type2 = type2.getElementType();
+        }
+        do {
+          if (type1 == null || isInterface(type1)) {
+            return newArrayValue(Type.getObjectType("java/lang/Object"), numDimensions);
+          }
+          type1 = getSuperClass(type1);
+          if (isAssignableFrom(type1, type2)) {
+            return newArrayValue(type1, numDimensions);
+          }
+        } while (true);
+      }
+      return BasicValue.UNINITIALIZED_VALUE;
     }
+    return value1;
+  }
 
-    @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");
-        }
+  private BasicValue newArrayValue(final Type type, final int dimensions) {
+    if (dimensions == 0) {
+      return newValue(type);
+    } else {
+      StringBuilder descriptor = new StringBuilder();
+      for (int i = 0; i < dimensions; ++i) {
+        descriptor.append('[');
+      }
+      descriptor.append(type.getDescriptor());
+      return newValue(Type.getType(descriptor.toString()));
     }
+  }
 
-    @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;
+  /**
+   * Returns whether the given type corresponds to the type of an interface. The default
+   * implementation of this method loads the class and uses the reflection API to return its result
+   * (unless the given type corresponds to the class being verified).
+   *
+   * @param type a type.
+   * @return whether 'type' corresponds to an interface.
+   */
+  protected boolean isInterface(final Type type) {
+    if (currentClass != null && currentClass.equals(type)) {
+      return isInterface;
     }
+    return getClass(type).isInterface();
+  }
 
-    protected boolean isInterface(final Type t) {
-        if (currentClass != null && t.equals(currentClass)) {
-            return isInterface;
-        }
-        return getClass(t).isInterface();
+  /**
+   * Returns the type corresponding to the super class of the given type. The default implementation
+   * of this method loads the class and uses the reflection API to return its result (unless the
+   * given type corresponds to the class being verified).
+   *
+   * @param type a type.
+   * @return the type corresponding to the super class of 'type'.
+   */
+  protected Type getSuperClass(final Type type) {
+    if (currentClass != null && currentClass.equals(type)) {
+      return currentSuperClass;
     }
+    Class<?> superClass = getClass(type).getSuperclass();
+    return superClass == null ? null : Type.getType(superClass);
+  }
 
-    protected Type getSuperClass(final Type t) {
-        if (currentClass != null && t.equals(currentClass)) {
-            return currentSuperClass;
+  /**
+   * Returns whether the class corresponding to the first argument is either the same as, or is a
+   * superclass or superinterface of the class corresponding to the second argument. The default
+   * implementation of this method loads the classes and uses the reflection API to return its
+   * result (unless the result can be computed from the class being verified, and the types of its
+   * super classes and implemented interfaces).
+   *
+   * @param type1 a type.
+   * @param type2 another type.
+   * @return whether the class corresponding to 'type1' is either the same as, or is a superclass or
+   *     superinterface of the class corresponding to 'type2'.
+   */
+  protected boolean isAssignableFrom(final Type type1, final Type type2) {
+    if (type1.equals(type2)) {
+      return true;
+    }
+    if (currentClass != null && currentClass.equals(type1)) {
+      if (getSuperClass(type2) == null) {
+        return false;
+      } else {
+        if (isInterface) {
+          return type2.getSort() == Type.OBJECT || type2.getSort() == Type.ARRAY;
         }
-        Class<?> c = getClass(t).getSuperclass();
-        return c == null ? null : Type.getType(c);
+        return isAssignableFrom(type1, getSuperClass(type2));
+      }
     }
-
-    protected boolean isAssignableFrom(final Type t, final Type u) {
-        if (t.equals(u)) {
+    if (currentClass != null && currentClass.equals(type2)) {
+      if (isAssignableFrom(type1, currentSuperClass)) {
+        return true;
+      }
+      if (currentClassInterfaces != null) {
+        for (Type currentClassInterface : currentClassInterfaces) {
+          if (isAssignableFrom(type1, currentClassInterface)) {
             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));
+      }
+      return false;
     }
+    return getClass(type1).isAssignableFrom(getClass(type2));
+  }
 
-    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());
-        }
+  /**
+   * Loads the class corresponding to the given type. The class is loaded with the class loader
+   * specified with {@link #setClassLoader}, or with the class loader of this class if no class
+   * loader was specified.
+   *
+   * @param type a type.
+   * @return the class corresponding to 'type'.
+   */
+  protected Class<?> getClass(final Type type) {
+    try {
+      if (type.getSort() == Type.ARRAY) {
+        return Class.forName(type.getDescriptor().replace('/', '.'), false, loader);
+      }
+      return Class.forName(type.getClassName(), false, loader);
+    } catch (ClassNotFoundException e) {
+      throw new TypeNotPresentException(e.toString(), e);
     }
+  }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/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
old mode 100644
new mode 100755
index 2aacb42..45df958
--- 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
@@ -1,32 +1,30 @@
-/***
- * 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.
- */
+// 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;
@@ -36,99 +34,159 @@ import java.util.NoSuchElementException;
 import java.util.Set;
 
 /**
- * A set of at most two elements.
- * 
+ * An immutable set of at most two elements, optimized for speed compared to a generic set
+ * implementation.
+ *
  * @author Eric Bruneton
  */
-class SmallSet<E> extends AbstractSet<E> implements Iterator<E> {
+final class SmallSet<T> extends AbstractSet<T> {
 
-    // if e1 is null, e2 must be null; otherwise e2 must be different from e1
+  /** The first element of this set, maybe {@literal null}. */
+  private final T element1;
 
-    E e1, e2;
+  /**
+   * The second element of this set, maybe {@literal null}. If {@link #element1} is {@literal null}
+   * then this field must be {@literal null}, otherwise it must be different from {@link #element1}.
+   */
+  private final T element2;
 
-    static final <T> Set<T> emptySet() {
-        return new SmallSet<T>(null, null);
-    }
+  // -----------------------------------------------------------------------------------------------
+  // Constructors
+  // -----------------------------------------------------------------------------------------------
 
-    SmallSet(final E e1, final E e2) {
-        this.e1 = e1;
-        this.e2 = e2;
-    }
+  /** Constructs an empty set. */
+  SmallSet() {
+    this.element1 = null;
+    this.element2 = null;
+  }
 
-    // -------------------------------------------------------------------------
-    // Implementation of inherited abstract methods
-    // -------------------------------------------------------------------------
+  /**
+   * Constructs a set with exactly one element.
+   *
+   * @param element the unique set element.
+   */
+  SmallSet(final T element) {
+    this.element1 = element;
+    this.element2 = null;
+  }
 
-    @Override
-    public Iterator<E> iterator() {
-        return new SmallSet<E>(e1, e2);
+  /**
+   * Constructs a new {@link SmallSet}.
+   *
+   * @param element1 see {@link #element1}.
+   * @param element2 see {@link #element2}.
+   */
+  private SmallSet(final T element1, final T element2) {
+    this.element1 = element1;
+    this.element2 = element2;
+  }
+
+  // -----------------------------------------------------------------------------------------------
+  // Implementation of the inherited abstract methods
+  // -----------------------------------------------------------------------------------------------
+
+  @Override
+  public Iterator<T> iterator() {
+    return new IteratorImpl<T>(element1, element2);
+  }
+
+  @Override
+  public int size() {
+    return element1 == null ? 0 : (element2 == null ? 1 : 2);
+  }
+
+  // -----------------------------------------------------------------------------------------------
+  // Utility methods
+  // -----------------------------------------------------------------------------------------------
+
+  /**
+   * Returns the union of this set and of the given set.
+   *
+   * @param otherSet another small set.
+   * @return the union of this set and of otherSet.
+   */
+  Set<T> union(final SmallSet<T> otherSet) {
+    // If the two sets are equal, return this set.
+    if ((otherSet.element1 == element1 && otherSet.element2 == element2)
+        || (otherSet.element1 == element2 && otherSet.element2 == element1)) {
+      return this;
+    }
+    // If one set is empty, return the other.
+    if (otherSet.element1 == null) {
+      return this;
+    }
+    if (element1 == null) {
+      return otherSet;
     }
 
-    @Override
-    public int size() {
-        return e1 == null ? 0 : (e2 == null ? 1 : 2);
+    // At this point we know that the two sets are non empty and are different.
+    // If otherSet contains exactly one element:
+    if (otherSet.element2 == null) {
+      // If this set also contains exactly one element, we have two distinct elements.
+      if (element2 == null) {
+        return new SmallSet<T>(element1, otherSet.element1);
+      }
+      // If otherSet is included in this set, return this set.
+      if (otherSet.element1 == element1 || otherSet.element1 == element2) {
+        return this;
+      }
+    }
+    // If this set contains exactly one element, then otherSet contains two elements (because of the
+    // above tests). Thus, if otherSet contains this set, return otherSet:
+    if (element2 == null && (element1 == otherSet.element1 || element1 == otherSet.element2)) {
+      return otherSet;
     }
 
-    // -------------------------------------------------------------------------
-    // Implementation of the Iterator interface
-    // -------------------------------------------------------------------------
+    // At this point we know that there are at least 3 distinct elements, so we need a generic set
+    // to store the result.
+    HashSet<T> result = new HashSet<T>(4);
+    result.add(element1);
+    if (element2 != null) {
+      result.add(element2);
+    }
+    result.add(otherSet.element1);
+    if (otherSet.element2 != null) {
+      result.add(otherSet.element2);
+    }
+    return result;
+  }
 
-    public boolean hasNext() {
-        return e1 != null;
+  static class IteratorImpl<T> implements Iterator<T> {
+
+    /** The next element to return in {@link #next}. Maybe {@literal null}. */
+    private T firstElement;
+
+    /**
+     * The element to return in {@link #next}, after {@link #firstElement} is returned. If {@link
+     * #firstElement} is {@literal null} then this field must be {@literal null}, otherwise it must
+     * be different from {@link #firstElement}.
+     */
+    private T secondElement;
+
+    IteratorImpl(final T firstElement, final T secondElement) {
+      this.firstElement = firstElement;
+      this.secondElement = secondElement;
     }
 
-    public E next() {
-        if (e1 == null) {
-            throw new NoSuchElementException();
-        }
-        E e = e1;
-        e1 = e2;
-        e2 = null;
-        return e;
+    @Override
+    public boolean hasNext() {
+      return firstElement != null;
     }
 
-    public void remove() {
+    @Override
+    public T next() {
+      if (firstElement == null) {
+        throw new NoSuchElementException();
+      }
+      T element = firstElement;
+      firstElement = secondElement;
+      secondElement = null;
+      return element;
     }
 
-    // -------------------------------------------------------------------------
-    // 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;
+    @Override
+    public void remove() {
+      throw new UnsupportedOperationException();
     }
+  }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/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
old mode 100644
new mode 100755
index 7a257e7..a84b44a
--- 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
@@ -1,38 +1,35 @@
-/***
- * 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.
- */
+// 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;
@@ -43,156 +40,182 @@ 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 class SourceInterpreter extends Interpreter<SourceValue> implements Opcodes {
 
-    public SourceInterpreter() {
-        super(ASM6);
+  /**
+   * Constructs a new {@link SourceInterpreter} for the latest ASM API version. <i>Subclasses must
+   * not use this constructor</i>. Instead, they must use the {@link #SourceInterpreter(int)}
+   * version.
+   */
+  public SourceInterpreter() {
+    super(ASM7);
+    if (getClass() != SourceInterpreter.class) {
+      throw new IllegalStateException();
     }
+  }
 
-    protected SourceInterpreter(final int api) {
-        super(api);
-    }
+  /**
+   * Constructs a new {@link SourceInterpreter}.
+   *
+   * @param api the ASM API version supported by this interpreter. Must be one of {@link
+   *     org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM4}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM5}, {@link
+   *     org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM6} or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#ASM7}.
+   */
+  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 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 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 value = ((LdcInsnNode) insn).cst;
+        size = value instanceof Long || value instanceof Double ? 2 : 1;
+        break;
+      case GETSTATIC:
+        size = Type.getType(((FieldInsnNode) insn).desc).getSize();
+        break;
+      default:
+        size = 1;
+        break;
     }
+    return new SourceValue(size, insn);
+  }
 
-    @Override
-    public SourceValue copyOperation(final AbstractInsnNode insn,
-            final SourceValue value) {
-        return new SourceValue(value.getSize(), 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 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;
+        break;
     }
+    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 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;
+        break;
     }
+    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 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 SourceValue naryOperation(
+      final AbstractInsnNode insn, final List<? extends SourceValue> values) {
+    int size;
+    int opcode = insn.getOpcode();
+    if (opcode == MULTIANEWARRAY) {
+      size = 1;
+    } else if (opcode == INVOKEDYNAMIC) {
+      size = Type.getReturnType(((InvokeDynamicInsnNode) insn).desc).getSize();
+    } else {
+      size = Type.getReturnType(((MethodInsnNode) insn).desc).getSize();
     }
+    return new SourceValue(size, insn);
+  }
 
-    @Override
-    public void returnOperation(final AbstractInsnNode insn,
-            final SourceValue value, final SourceValue expected) {
+  @Override
+  public void returnOperation(
+      final AbstractInsnNode insn, final SourceValue value, final SourceValue expected) {
+    // Nothing to do.
+  }
+
+  @Override
+  public SourceValue merge(final SourceValue value1, final SourceValue value2) {
+    if (value1.insns instanceof SmallSet && value2.insns instanceof SmallSet) {
+      Set<AbstractInsnNode> setUnion =
+          ((SmallSet<AbstractInsnNode>) value1.insns)
+              .union((SmallSet<AbstractInsnNode>) value2.insns);
+      if (setUnion == value1.insns && value1.size == value2.size) {
+        return value1;
+      } else {
+        return new SourceValue(Math.min(value1.size, value2.size), setUnion);
+      }
+    }
+    if (value1.size != value2.size || !containsAll(value1.insns, value2.insns)) {
+      HashSet<AbstractInsnNode> setUnion = new HashSet<AbstractInsnNode>();
+      setUnion.addAll(value1.insns);
+      setUnion.addAll(value2.insns);
+      return new SourceValue(Math.min(value1.size, value2.size), setUnion);
     }
+    return value1;
+  }
 
-    @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;
+  private static <E> boolean containsAll(final Set<E> self, final Set<E> other) {
+    if (self.size() < other.size()) {
+      return false;
     }
+    return self.containsAll(other);
+  }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/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
old mode 100644
new mode 100755
index 0cb2f50..3b68854
--- 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
@@ -1,97 +1,119 @@
-/***
- * 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.
- */
+// 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.
- * 
+ * A {@link Value} which keeps track of the bytecode instructions that can produce it.
+ *
  * @author Eric Bruneton
  */
 public class SourceValue implements Value {
 
-    /**
-     * The size of this value.
-     */
-    public final int size;
+  /**
+   * The size of this value, in 32 bits words. This size is 1 for byte, boolean, char, short, int,
+   * float, object and array types, and 2 for long and double.
+   */
+  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;
+  /**
+   * The instructions that can produce this value. For example, for the Java code below, the
+   * instructions that can produce the value of {@code i} at line 5 are the two ISTORE instructions
+   * at line 1 and 3:
+   *
+   * <pre>
+   * 1: i = 0;
+   * 2: if (...) {
+   * 3:   i = 1;
+   * 4: }
+   * 5: return i;
+   * </pre>
+   */
+  public final Set<AbstractInsnNode> insns;
 
-    public SourceValue(final int size) {
-        this(size, SmallSet.<AbstractInsnNode> emptySet());
-    }
+  /**
+   * Constructs a new {@link SourceValue}.
+   *
+   * @param size the size of this value, in 32 bits words. This size is 1 for byte, boolean, char,
+   *     short, int, float, object and array types, and 2 for long and double.
+   */
+  public SourceValue(final int size) {
+    this(size, new SmallSet<AbstractInsnNode>());
+  }
 
-    public SourceValue(final int size, final AbstractInsnNode insn) {
-        this.size = size;
-        this.insns = new SmallSet<AbstractInsnNode>(insn, null);
-    }
+  /**
+   * Constructs a new {@link SourceValue}.
+   *
+   * @param size the size of this value, in 32 bits words. This size is 1 for byte, boolean, char,
+   *     short, int, float, object and array types, and 2 for long and double.
+   * @param insnNode an instruction that can produce this value.
+   */
+  public SourceValue(final int size, final AbstractInsnNode insnNode) {
+    this.size = size;
+    this.insns = new SmallSet<AbstractInsnNode>(insnNode);
+  }
 
-    public SourceValue(final int size, final Set<AbstractInsnNode> insns) {
-        this.size = size;
-        this.insns = insns;
-    }
+  /**
+   * Constructs a new {@link SourceValue}.
+   *
+   * @param size the size of this value, in 32 bits words. This size is 1 for byte, boolean, char,
+   *     short, int, float, object and array types, and 2 for long and double.
+   * @param insnSet the instructions that can produce this value.
+   */
+  public SourceValue(final int size, final Set<AbstractInsnNode> insnSet) {
+    this.size = size;
+    this.insns = insnSet;
+  }
 
-    public int getSize() {
-        return size;
-    }
+  /**
+   * Returns the size of this value.
+   *
+   * @return the size of this value, in 32 bits words. This size is 1 for byte, boolean, char,
+   *     short, int, float, object and array types, and 2 for long and double.
+   */
+  @Override
+  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 boolean equals(final Object value) {
+    if (!(value instanceof SourceValue)) {
+      return false;
     }
+    SourceValue sourceValue = (SourceValue) value;
+    return size == sourceValue.size && insns.equals(sourceValue.insns);
+  }
 
-    @Override
-    public int hashCode() {
-        return insns.hashCode();
-    }
+  @Override
+  public int hashCode() {
+    return insns.hashCode();
+  }
 }