You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2011/04/06 21:11:38 UTC

svn commit: r1089584 [15/21] - in /tapestry/tapestry5/trunk/plastic: ./ src/external/ src/external/java/ src/external/java/org/ src/external/java/org/objectweb/ src/external/java/org/objectweb/asm/ src/external/java/org/objectweb/asm/attrs/ src/externa...

Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/BasicInterpreter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/BasicInterpreter.java?rev=1089584&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/BasicInterpreter.java (added)
+++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/BasicInterpreter.java Wed Apr  6 19:11:34 2011
@@ -0,0 +1,330 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.tree.analysis;
+
+import java.util.List;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.FieldInsnNode;
+import org.objectweb.asm.tree.IntInsnNode;
+import org.objectweb.asm.tree.LdcInsnNode;
+import org.objectweb.asm.tree.MethodInsnNode;
+import org.objectweb.asm.tree.MultiANewArrayInsnNode;
+import org.objectweb.asm.tree.TypeInsnNode;
+
+/**
+ * An {@link Interpreter} for {@link BasicValue} values.
+ * 
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class BasicInterpreter implements Opcodes, Interpreter {
+
+    public Value 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");
+        }
+    }
+
+    public Value 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 Type) {
+                    return newValue(Type.getObjectType("java/lang/Class"));
+                } else {
+                    return newValue(Type.getType(cst.getClass()));
+                }
+            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.");
+        }
+    }
+
+    public Value copyOperation(final AbstractInsnNode insn, final Value value)
+            throws AnalyzerException
+    {
+        return value;
+    }
+
+    public Value unaryOperation(final AbstractInsnNode insn, final Value 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.");
+        }
+    }
+
+    public Value binaryOperation(
+        final AbstractInsnNode insn,
+        final Value value1,
+        final Value 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.");
+        }
+    }
+
+    public Value ternaryOperation(
+        final AbstractInsnNode insn,
+        final Value value1,
+        final Value value2,
+        final Value value3) throws AnalyzerException
+    {
+        return null;
+    }
+
+    public Value naryOperation(final AbstractInsnNode insn, final List values)
+            throws AnalyzerException
+    {
+        if (insn.getOpcode() == MULTIANEWARRAY) {
+            return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
+        } else {
+            return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
+        }
+    }
+
+    public void returnOperation(
+        final AbstractInsnNode insn,
+        final Value value,
+        final Value expected) throws AnalyzerException
+    {
+    }
+    
+    public Value merge(final Value v, final Value w) {
+        if (!v.equals(w)) {
+            return BasicValue.UNINITIALIZED_VALUE;
+        }
+        return v;
+    }
+}

Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/BasicValue.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/BasicValue.java?rev=1089584&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/BasicValue.java (added)
+++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/BasicValue.java Wed Apr  6 19:11:34 2011
@@ -0,0 +1,105 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.tree.analysis;
+
+import org.objectweb.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 Value UNINITIALIZED_VALUE = new BasicValue(null);
+
+    public static final Value INT_VALUE = new BasicValue(Type.INT_TYPE);
+
+    public static final Value FLOAT_VALUE = new BasicValue(Type.FLOAT_TYPE);
+
+    public static final Value LONG_VALUE = new BasicValue(Type.LONG_TYPE);
+
+    public static final Value DOUBLE_VALUE = new BasicValue(Type.DOUBLE_TYPE);
+
+    public static final Value REFERENCE_VALUE = new BasicValue(Type.getObjectType("java/lang/Object"));
+
+    public static final Value 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);
+    }
+
+    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;
+        }
+    }
+
+    public int hashCode() {
+        return type == null ? 0 : type.hashCode();
+    }
+
+    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();
+        }
+    }
+}

Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/BasicVerifier.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/BasicVerifier.java?rev=1089584&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/BasicVerifier.java (added)
+++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/BasicVerifier.java Wed Apr  6 19:11:34 2011
@@ -0,0 +1,441 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.tree.analysis;
+
+import java.util.List;
+
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.FieldInsnNode;
+import org.objectweb.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 Value copyOperation(final AbstractInsnNode insn, final Value 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 (!((BasicValue) value).isReference()) {
+                    throw new AnalyzerException(insn,
+                            null,
+                            "an object reference",
+                            value);
+                }
+                return value;
+            case ASTORE:
+                if (!((BasicValue) 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;
+    }
+
+    public Value unaryOperation(final AbstractInsnNode insn, final Value value)
+            throws AnalyzerException
+    {
+        Value 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 (!((BasicValue) 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 (!((BasicValue) 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);
+    }
+
+    public Value binaryOperation(
+        final AbstractInsnNode insn,
+        final Value value1,
+        final Value value2) throws AnalyzerException
+    {
+        Value expected1;
+        Value 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);
+        }
+    }
+
+    public Value ternaryOperation(
+        final AbstractInsnNode insn,
+        final Value value1,
+        final Value value2,
+        final Value value3) throws AnalyzerException
+    {
+        Value expected1;
+        Value 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;
+    }
+
+    public Value naryOperation(final AbstractInsnNode insn, final List 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,
+                            (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((Value) values.get(i++), newValue(owner))) {
+                    throw new AnalyzerException(insn, "Method owner",
+                            newValue(owner),
+                            (Value) values.get(0));
+                }
+            }
+            Type[] args = Type.getArgumentTypes(((MethodInsnNode) insn).desc);
+            while (i < values.size()) {
+                Value expected = newValue(args[j++]);
+                Value encountered = (Value) values.get(i++);
+                if (!isSubTypeOf(encountered, expected)) {
+                    throw new AnalyzerException(insn,
+                            "Argument " + j,
+                            expected,
+                            encountered);
+                }
+            }
+        }
+        return super.naryOperation(insn, values);
+    }
+
+    public void returnOperation(
+        final AbstractInsnNode insn,
+        final Value value,
+        final Value expected) throws AnalyzerException
+    {
+        if (!isSubTypeOf(value, expected)) {
+            throw new AnalyzerException(insn,
+                    "Incompatible return type",
+                    expected,
+                    value);
+        }
+    }
+
+    protected boolean isArrayValue(final Value value) {
+        return ((BasicValue) value).isReference();
+    }
+
+    protected Value getElementValue(final Value objectArrayValue)
+            throws AnalyzerException
+    {
+        return BasicValue.REFERENCE_VALUE;
+    }
+
+    protected boolean isSubTypeOf(final Value value, final Value expected) {
+        return value.equals(expected);
+    }
+}

Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/Frame.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/Frame.java?rev=1089584&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/Frame.java (added)
+++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/Frame.java Wed Apr  6 19:11:34 2011
@@ -0,0 +1,693 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.tree.analysis;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.IincInsnNode;
+import org.objectweb.asm.tree.MethodInsnNode;
+import org.objectweb.asm.tree.MultiANewArrayInsnNode;
+import org.objectweb.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.
+ * 
+ * @author Eric Bruneton
+ */
+public class Frame {
+
+    /**
+     * The expected return type of the analyzed method, or <tt>null</tt> if the
+     * method returns void.
+     */
+    private Value returnValue;
+
+    /**
+     * The local variables and operand stack of this frame.
+     */
+    private Value[] 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 = 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 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 init(final Frame 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 Value 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 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 Value 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 Value 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 Value 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 Value 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 Value 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 interpreter) throws AnalyzerException
+    {
+        Value value1, value2, value3, value4;
+        List 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:
+            case Opcodes.INVOKEDYNAMIC:
+                values = new ArrayList();
+                String desc = ((MethodInsnNode) insn).desc;
+                for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) {
+                    values.add(0, pop());
+                }
+                if (insn.getOpcode() != Opcodes.INVOKESTATIC &&
+                    insn.getOpcode() != Opcodes.INVOKEDYNAMIC) {
+                    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();
+                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 frame, final Interpreter 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) {
+            Value v = interpreter.merge(values[i], frame.values[i]);
+            if (v != 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 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.
+     */
+    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();
+    }
+}

Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/Interpreter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/Interpreter.java?rev=1089584&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/Interpreter.java (added)
+++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/Interpreter.java Wed Apr  6 19:11:34 2011
@@ -0,0 +1,192 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.tree.analysis;
+
+import java.util.List;
+
+import org.objectweb.asm.Type;
+import org.objectweb.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.
+ * 
+ * @author Eric Bruneton
+ */
+public interface Interpreter {
+
+    /**
+     * 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.
+     */
+    Value 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.
+     */
+    Value 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.
+     */
+    Value copyOperation(AbstractInsnNode insn, Value 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.
+     */
+    Value unaryOperation(AbstractInsnNode insn, Value 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.
+     */
+    Value binaryOperation(AbstractInsnNode insn, Value value1, Value 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.
+     */
+    Value ternaryOperation(
+        AbstractInsnNode insn,
+        Value value1,
+        Value value2,
+        Value 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
+     * 
+     * @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.
+     */
+    Value naryOperation(AbstractInsnNode insn, List 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.
+     */
+    void returnOperation(AbstractInsnNode insn, Value value, Value 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>.
+     */
+    Value merge(Value v, Value w);
+}

Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/SimpleVerifier.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/SimpleVerifier.java?rev=1089584&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/SimpleVerifier.java (added)
+++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/SimpleVerifier.java Wed Apr  6 19:11:34 2011
@@ -0,0 +1,309 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.tree.analysis;
+
+import java.util.List;
+
+import org.objectweb.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 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 currentClassInterfaces,
+        final boolean isInterface)
+    {
+        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;
+    }
+
+    public Value 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);
+            }
+        }
+
+        Value v = super.newValue(type);
+        if (BasicValue.REFERENCE_VALUE.equals(v)) {
+            if (isArray) {
+                v = newValue(type.getElementType());
+                String desc = ((BasicValue) 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;
+    }
+
+    protected boolean isArrayValue(final Value value) {
+        Type t = ((BasicValue) value).getType();
+        return t != null
+                && ("Lnull;".equals(t.getDescriptor()) || t.getSort() == Type.ARRAY);
+    }
+
+    protected Value getElementValue(final Value objectArrayValue)
+            throws AnalyzerException
+    {
+        Type arrayType = ((BasicValue) 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");
+    }
+
+    protected boolean isSubTypeOf(final Value value, final Value expected) {
+        Type expectedType = ((BasicValue) expected).getType();
+        Type type = ((BasicValue) 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");
+        }
+    }
+
+    public Value merge(final Value v, final Value w) {
+        if (!v.equals(w)) {
+            Type t = ((BasicValue) v).getType();
+            Type u = ((BasicValue) 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 = (Type) 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());
+        }
+    }
+}

Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/SmallSet.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/SmallSet.java?rev=1089584&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/SmallSet.java (added)
+++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/tree/analysis/SmallSet.java Wed Apr  6 19:11:34 2011
@@ -0,0 +1,126 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.tree.analysis;
+
+import java.util.AbstractSet;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * A set of at most two elements.
+ * 
+ * @author Eric Bruneton
+ */
+class SmallSet extends AbstractSet implements Iterator {
+
+    // if e1 is null, e2 must be null; otherwise e2 must be different from e1
+
+    Object e1, e2;
+
+    static final Set EMPTY_SET = new SmallSet(null, null);
+
+    SmallSet(final Object e1, final Object e2) {
+        this.e1 = e1;
+        this.e2 = e2;
+    }
+
+    // -------------------------------------------------------------------------
+    // Implementation of inherited abstract methods
+    // -------------------------------------------------------------------------
+
+    public Iterator iterator() {
+        return new SmallSet(e1, e2);
+    }
+
+    public int size() {
+        return e1 == null ? 0 : (e2 == null ? 1 : 2);
+    }
+
+    // -------------------------------------------------------------------------
+    // Implementation of the Iterator interface
+    // -------------------------------------------------------------------------
+
+    public boolean hasNext() {
+        return e1 != null;
+    }
+
+    public Object next() {
+        Object e = e1;
+        e1 = e2;
+        e2 = null;
+        return e;
+    }
+
+    public void remove() {
+    }
+
+    // -------------------------------------------------------------------------
+    // Utility methods
+    // -------------------------------------------------------------------------
+
+    Set union(final SmallSet 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(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 r = new HashSet(4);
+        r.add(e1);
+        if (e2 != null) {
+            r.add(e2);
+        }
+        r.add(s.e1);
+        if (s.e2 != null) {
+            r.add(s.e2);
+        }
+        return r;
+    }
+}