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:15 UTC

[28/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/commons/InstructionAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
old mode 100644
new mode 100755
index 97de573..07d30ee
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
@@ -1,1170 +1,1301 @@
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.apache.tapestry5.internal.plastic.asm.commons;
-
-import org.apache.tapestry5.internal.plastic.asm.Handle;
-import org.apache.tapestry5.internal.plastic.asm.Label;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import org.apache.tapestry5.internal.plastic.asm.Type;
-
-/**
- * A {@link MethodVisitor} providing a more detailed API to generate and
- * transform instructions.
- * 
- * @author Eric Bruneton
- */
-public class InstructionAdapter extends MethodVisitor {
-
-    public final static Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;");
-
-    /**
-     * Creates a new {@link InstructionAdapter}. <i>Subclasses must not use this
-     * constructor</i>. Instead, they must use the
-     * {@link #InstructionAdapter(int, MethodVisitor)} version.
-     * 
-     * @param mv
-     *            the method visitor to which this adapter delegates calls.
-     * @throws IllegalStateException
-     *             If a subclass calls this constructor.
-     */
-    public InstructionAdapter(final MethodVisitor mv) {
-        this(Opcodes.ASM6, mv);
-        if (getClass() != InstructionAdapter.class) {
-            throw new IllegalStateException();
-        }
-    }
-
-    /**
-     * Creates a new {@link InstructionAdapter}.
-     * 
-     * @param api
-     *            the ASM API version implemented by this visitor. Must be one
-     *            of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
-     * @param mv
-     *            the method visitor to which this adapter delegates calls.
-     */
-    protected InstructionAdapter(final int api, final MethodVisitor mv) {
-        super(api, mv);
-    }
-
-    @Override
-    public void visitInsn(final int opcode) {
-        switch (opcode) {
-        case Opcodes.NOP:
-            nop();
-            break;
-        case Opcodes.ACONST_NULL:
-            aconst(null);
-            break;
-        case Opcodes.ICONST_M1:
-        case Opcodes.ICONST_0:
-        case Opcodes.ICONST_1:
-        case Opcodes.ICONST_2:
-        case Opcodes.ICONST_3:
-        case Opcodes.ICONST_4:
-        case Opcodes.ICONST_5:
-            iconst(opcode - Opcodes.ICONST_0);
-            break;
-        case Opcodes.LCONST_0:
-        case Opcodes.LCONST_1:
-            lconst(opcode - Opcodes.LCONST_0);
-            break;
-        case Opcodes.FCONST_0:
-        case Opcodes.FCONST_1:
-        case Opcodes.FCONST_2:
-            fconst(opcode - Opcodes.FCONST_0);
-            break;
-        case Opcodes.DCONST_0:
-        case Opcodes.DCONST_1:
-            dconst(opcode - Opcodes.DCONST_0);
-            break;
-        case Opcodes.IALOAD:
-            aload(Type.INT_TYPE);
-            break;
-        case Opcodes.LALOAD:
-            aload(Type.LONG_TYPE);
-            break;
-        case Opcodes.FALOAD:
-            aload(Type.FLOAT_TYPE);
-            break;
-        case Opcodes.DALOAD:
-            aload(Type.DOUBLE_TYPE);
-            break;
-        case Opcodes.AALOAD:
-            aload(OBJECT_TYPE);
-            break;
-        case Opcodes.BALOAD:
-            aload(Type.BYTE_TYPE);
-            break;
-        case Opcodes.CALOAD:
-            aload(Type.CHAR_TYPE);
-            break;
-        case Opcodes.SALOAD:
-            aload(Type.SHORT_TYPE);
-            break;
-        case Opcodes.IASTORE:
-            astore(Type.INT_TYPE);
-            break;
-        case Opcodes.LASTORE:
-            astore(Type.LONG_TYPE);
-            break;
-        case Opcodes.FASTORE:
-            astore(Type.FLOAT_TYPE);
-            break;
-        case Opcodes.DASTORE:
-            astore(Type.DOUBLE_TYPE);
-            break;
-        case Opcodes.AASTORE:
-            astore(OBJECT_TYPE);
-            break;
-        case Opcodes.BASTORE:
-            astore(Type.BYTE_TYPE);
-            break;
-        case Opcodes.CASTORE:
-            astore(Type.CHAR_TYPE);
-            break;
-        case Opcodes.SASTORE:
-            astore(Type.SHORT_TYPE);
-            break;
-        case Opcodes.POP:
-            pop();
-            break;
-        case Opcodes.POP2:
-            pop2();
-            break;
-        case Opcodes.DUP:
-            dup();
-            break;
-        case Opcodes.DUP_X1:
-            dupX1();
-            break;
-        case Opcodes.DUP_X2:
-            dupX2();
-            break;
-        case Opcodes.DUP2:
-            dup2();
-            break;
-        case Opcodes.DUP2_X1:
-            dup2X1();
-            break;
-        case Opcodes.DUP2_X2:
-            dup2X2();
-            break;
-        case Opcodes.SWAP:
-            swap();
-            break;
-        case Opcodes.IADD:
-            add(Type.INT_TYPE);
-            break;
-        case Opcodes.LADD:
-            add(Type.LONG_TYPE);
-            break;
-        case Opcodes.FADD:
-            add(Type.FLOAT_TYPE);
-            break;
-        case Opcodes.DADD:
-            add(Type.DOUBLE_TYPE);
-            break;
-        case Opcodes.ISUB:
-            sub(Type.INT_TYPE);
-            break;
-        case Opcodes.LSUB:
-            sub(Type.LONG_TYPE);
-            break;
-        case Opcodes.FSUB:
-            sub(Type.FLOAT_TYPE);
-            break;
-        case Opcodes.DSUB:
-            sub(Type.DOUBLE_TYPE);
-            break;
-        case Opcodes.IMUL:
-            mul(Type.INT_TYPE);
-            break;
-        case Opcodes.LMUL:
-            mul(Type.LONG_TYPE);
-            break;
-        case Opcodes.FMUL:
-            mul(Type.FLOAT_TYPE);
-            break;
-        case Opcodes.DMUL:
-            mul(Type.DOUBLE_TYPE);
-            break;
-        case Opcodes.IDIV:
-            div(Type.INT_TYPE);
-            break;
-        case Opcodes.LDIV:
-            div(Type.LONG_TYPE);
-            break;
-        case Opcodes.FDIV:
-            div(Type.FLOAT_TYPE);
-            break;
-        case Opcodes.DDIV:
-            div(Type.DOUBLE_TYPE);
-            break;
-        case Opcodes.IREM:
-            rem(Type.INT_TYPE);
-            break;
-        case Opcodes.LREM:
-            rem(Type.LONG_TYPE);
-            break;
-        case Opcodes.FREM:
-            rem(Type.FLOAT_TYPE);
-            break;
-        case Opcodes.DREM:
-            rem(Type.DOUBLE_TYPE);
-            break;
-        case Opcodes.INEG:
-            neg(Type.INT_TYPE);
-            break;
-        case Opcodes.LNEG:
-            neg(Type.LONG_TYPE);
-            break;
-        case Opcodes.FNEG:
-            neg(Type.FLOAT_TYPE);
-            break;
-        case Opcodes.DNEG:
-            neg(Type.DOUBLE_TYPE);
-            break;
-        case Opcodes.ISHL:
-            shl(Type.INT_TYPE);
-            break;
-        case Opcodes.LSHL:
-            shl(Type.LONG_TYPE);
-            break;
-        case Opcodes.ISHR:
-            shr(Type.INT_TYPE);
-            break;
-        case Opcodes.LSHR:
-            shr(Type.LONG_TYPE);
-            break;
-        case Opcodes.IUSHR:
-            ushr(Type.INT_TYPE);
-            break;
-        case Opcodes.LUSHR:
-            ushr(Type.LONG_TYPE);
-            break;
-        case Opcodes.IAND:
-            and(Type.INT_TYPE);
-            break;
-        case Opcodes.LAND:
-            and(Type.LONG_TYPE);
-            break;
-        case Opcodes.IOR:
-            or(Type.INT_TYPE);
-            break;
-        case Opcodes.LOR:
-            or(Type.LONG_TYPE);
-            break;
-        case Opcodes.IXOR:
-            xor(Type.INT_TYPE);
-            break;
-        case Opcodes.LXOR:
-            xor(Type.LONG_TYPE);
-            break;
-        case Opcodes.I2L:
-            cast(Type.INT_TYPE, Type.LONG_TYPE);
-            break;
-        case Opcodes.I2F:
-            cast(Type.INT_TYPE, Type.FLOAT_TYPE);
-            break;
-        case Opcodes.I2D:
-            cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
-            break;
-        case Opcodes.L2I:
-            cast(Type.LONG_TYPE, Type.INT_TYPE);
-            break;
-        case Opcodes.L2F:
-            cast(Type.LONG_TYPE, Type.FLOAT_TYPE);
-            break;
-        case Opcodes.L2D:
-            cast(Type.LONG_TYPE, Type.DOUBLE_TYPE);
-            break;
-        case Opcodes.F2I:
-            cast(Type.FLOAT_TYPE, Type.INT_TYPE);
-            break;
-        case Opcodes.F2L:
-            cast(Type.FLOAT_TYPE, Type.LONG_TYPE);
-            break;
-        case Opcodes.F2D:
-            cast(Type.FLOAT_TYPE, Type.DOUBLE_TYPE);
-            break;
-        case Opcodes.D2I:
-            cast(Type.DOUBLE_TYPE, Type.INT_TYPE);
-            break;
-        case Opcodes.D2L:
-            cast(Type.DOUBLE_TYPE, Type.LONG_TYPE);
-            break;
-        case Opcodes.D2F:
-            cast(Type.DOUBLE_TYPE, Type.FLOAT_TYPE);
-            break;
-        case Opcodes.I2B:
-            cast(Type.INT_TYPE, Type.BYTE_TYPE);
-            break;
-        case Opcodes.I2C:
-            cast(Type.INT_TYPE, Type.CHAR_TYPE);
-            break;
-        case Opcodes.I2S:
-            cast(Type.INT_TYPE, Type.SHORT_TYPE);
-            break;
-        case Opcodes.LCMP:
-            lcmp();
-            break;
-        case Opcodes.FCMPL:
-            cmpl(Type.FLOAT_TYPE);
-            break;
-        case Opcodes.FCMPG:
-            cmpg(Type.FLOAT_TYPE);
-            break;
-        case Opcodes.DCMPL:
-            cmpl(Type.DOUBLE_TYPE);
-            break;
-        case Opcodes.DCMPG:
-            cmpg(Type.DOUBLE_TYPE);
-            break;
-        case Opcodes.IRETURN:
-            areturn(Type.INT_TYPE);
-            break;
-        case Opcodes.LRETURN:
-            areturn(Type.LONG_TYPE);
-            break;
-        case Opcodes.FRETURN:
-            areturn(Type.FLOAT_TYPE);
-            break;
-        case Opcodes.DRETURN:
-            areturn(Type.DOUBLE_TYPE);
-            break;
-        case Opcodes.ARETURN:
-            areturn(OBJECT_TYPE);
-            break;
-        case Opcodes.RETURN:
-            areturn(Type.VOID_TYPE);
-            break;
-        case Opcodes.ARRAYLENGTH:
-            arraylength();
-            break;
-        case Opcodes.ATHROW:
-            athrow();
-            break;
-        case Opcodes.MONITORENTER:
-            monitorenter();
-            break;
-        case Opcodes.MONITOREXIT:
-            monitorexit();
-            break;
-        default:
-            throw new IllegalArgumentException();
-        }
-    }
-
-    @Override
-    public void visitIntInsn(final int opcode, final int operand) {
-        switch (opcode) {
-        case Opcodes.BIPUSH:
-            iconst(operand);
-            break;
-        case Opcodes.SIPUSH:
-            iconst(operand);
-            break;
-        case Opcodes.NEWARRAY:
-            switch (operand) {
-            case Opcodes.T_BOOLEAN:
-                newarray(Type.BOOLEAN_TYPE);
-                break;
-            case Opcodes.T_CHAR:
-                newarray(Type.CHAR_TYPE);
-                break;
-            case Opcodes.T_BYTE:
-                newarray(Type.BYTE_TYPE);
-                break;
-            case Opcodes.T_SHORT:
-                newarray(Type.SHORT_TYPE);
-                break;
-            case Opcodes.T_INT:
-                newarray(Type.INT_TYPE);
-                break;
-            case Opcodes.T_FLOAT:
-                newarray(Type.FLOAT_TYPE);
-                break;
-            case Opcodes.T_LONG:
-                newarray(Type.LONG_TYPE);
-                break;
-            case Opcodes.T_DOUBLE:
-                newarray(Type.DOUBLE_TYPE);
-                break;
-            default:
-                throw new IllegalArgumentException();
-            }
-            break;
-        default:
-            throw new IllegalArgumentException();
-        }
-    }
-
-    @Override
-    public void visitVarInsn(final int opcode, final int var) {
-        switch (opcode) {
-        case Opcodes.ILOAD:
-            load(var, Type.INT_TYPE);
-            break;
-        case Opcodes.LLOAD:
-            load(var, Type.LONG_TYPE);
-            break;
-        case Opcodes.FLOAD:
-            load(var, Type.FLOAT_TYPE);
-            break;
-        case Opcodes.DLOAD:
-            load(var, Type.DOUBLE_TYPE);
-            break;
-        case Opcodes.ALOAD:
-            load(var, OBJECT_TYPE);
-            break;
-        case Opcodes.ISTORE:
-            store(var, Type.INT_TYPE);
-            break;
-        case Opcodes.LSTORE:
-            store(var, Type.LONG_TYPE);
-            break;
-        case Opcodes.FSTORE:
-            store(var, Type.FLOAT_TYPE);
-            break;
-        case Opcodes.DSTORE:
-            store(var, Type.DOUBLE_TYPE);
-            break;
-        case Opcodes.ASTORE:
-            store(var, OBJECT_TYPE);
-            break;
-        case Opcodes.RET:
-            ret(var);
-            break;
-        default:
-            throw new IllegalArgumentException();
-        }
-    }
-
-    @Override
-    public void visitTypeInsn(final int opcode, final String type) {
-        Type t = Type.getObjectType(type);
-        switch (opcode) {
-        case Opcodes.NEW:
-            anew(t);
-            break;
-        case Opcodes.ANEWARRAY:
-            newarray(t);
-            break;
-        case Opcodes.CHECKCAST:
-            checkcast(t);
-            break;
-        case Opcodes.INSTANCEOF:
-            instanceOf(t);
-            break;
-        default:
-            throw new IllegalArgumentException();
-        }
-    }
-
-    @Override
-    public void visitFieldInsn(final int opcode, final String owner,
-            final String name, final String desc) {
-        switch (opcode) {
-        case Opcodes.GETSTATIC:
-            getstatic(owner, name, desc);
-            break;
-        case Opcodes.PUTSTATIC:
-            putstatic(owner, name, desc);
-            break;
-        case Opcodes.GETFIELD:
-            getfield(owner, name, desc);
-            break;
-        case Opcodes.PUTFIELD:
-            putfield(owner, name, desc);
-            break;
-        default:
-            throw new IllegalArgumentException();
-        }
-    }
-
-    @Deprecated
-    @Override
-    public void visitMethodInsn(final int opcode, final String owner,
-            final String name, final String desc) {
-        if (api >= Opcodes.ASM5) {
-            super.visitMethodInsn(opcode, owner, name, desc);
-            return;
-        }
-        doVisitMethodInsn(opcode, owner, name, desc,
-                opcode == Opcodes.INVOKEINTERFACE);
-    }
-
-    @Override
-    public void visitMethodInsn(final int opcode, final String owner,
-            final String name, final String desc, final boolean itf) {
-        if (api < Opcodes.ASM5) {
-            super.visitMethodInsn(opcode, owner, name, desc, itf);
-            return;
-        }
-        doVisitMethodInsn(opcode, owner, name, desc, itf);
-    }
-
-    private void doVisitMethodInsn(int opcode, final String owner,
-            final String name, final String desc, final boolean itf) {
-        switch (opcode) {
-        case Opcodes.INVOKESPECIAL:
-            invokespecial(owner, name, desc, itf);
-            break;
-        case Opcodes.INVOKEVIRTUAL:
-            invokevirtual(owner, name, desc, itf);
-            break;
-        case Opcodes.INVOKESTATIC:
-            invokestatic(owner, name, desc, itf);
-            break;
-        case Opcodes.INVOKEINTERFACE:
-            invokeinterface(owner, name, desc);
-            break;
-        default:
-            throw new IllegalArgumentException();
-        }
-    }
-
-    @Override
-    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
-            Object... bsmArgs) {
-        invokedynamic(name, desc, bsm, bsmArgs);
-    }
-
-    @Override
-    public void visitJumpInsn(final int opcode, final Label label) {
-        switch (opcode) {
-        case Opcodes.IFEQ:
-            ifeq(label);
-            break;
-        case Opcodes.IFNE:
-            ifne(label);
-            break;
-        case Opcodes.IFLT:
-            iflt(label);
-            break;
-        case Opcodes.IFGE:
-            ifge(label);
-            break;
-        case Opcodes.IFGT:
-            ifgt(label);
-            break;
-        case Opcodes.IFLE:
-            ifle(label);
-            break;
-        case Opcodes.IF_ICMPEQ:
-            ificmpeq(label);
-            break;
-        case Opcodes.IF_ICMPNE:
-            ificmpne(label);
-            break;
-        case Opcodes.IF_ICMPLT:
-            ificmplt(label);
-            break;
-        case Opcodes.IF_ICMPGE:
-            ificmpge(label);
-            break;
-        case Opcodes.IF_ICMPGT:
-            ificmpgt(label);
-            break;
-        case Opcodes.IF_ICMPLE:
-            ificmple(label);
-            break;
-        case Opcodes.IF_ACMPEQ:
-            ifacmpeq(label);
-            break;
-        case Opcodes.IF_ACMPNE:
-            ifacmpne(label);
-            break;
-        case Opcodes.GOTO:
-            goTo(label);
-            break;
-        case Opcodes.JSR:
-            jsr(label);
-            break;
-        case Opcodes.IFNULL:
-            ifnull(label);
-            break;
-        case Opcodes.IFNONNULL:
-            ifnonnull(label);
-            break;
-        default:
-            throw new IllegalArgumentException();
-        }
-    }
-
-    @Override
-    public void visitLabel(final Label label) {
-        mark(label);
-    }
-
-    @Override
-    public void visitLdcInsn(final Object cst) {
-        if (cst instanceof Integer) {
-            int val = ((Integer) cst).intValue();
-            iconst(val);
-        } else if (cst instanceof Byte) {
-            int val = ((Byte) cst).intValue();
-            iconst(val);
-        } else if (cst instanceof Character) {
-            int val = ((Character) cst).charValue();
-            iconst(val);
-        } else if (cst instanceof Short) {
-            int val = ((Short) cst).intValue();
-            iconst(val);
-        } else if (cst instanceof Boolean) {
-            int val = ((Boolean) cst).booleanValue() ? 1 : 0;
-            iconst(val);
-        } else if (cst instanceof Float) {
-            float val = ((Float) cst).floatValue();
-            fconst(val);
-        } else if (cst instanceof Long) {
-            long val = ((Long) cst).longValue();
-            lconst(val);
-        } else if (cst instanceof Double) {
-            double val = ((Double) cst).doubleValue();
-            dconst(val);
-        } else if (cst instanceof String) {
-            aconst(cst);
-        } else if (cst instanceof Type) {
-            tconst((Type) cst);
-        } else if (cst instanceof Handle) {
-            hconst((Handle) cst);
-        } else {
-            throw new IllegalArgumentException();
-        }
-    }
-
-    @Override
-    public void visitIincInsn(final int var, final int increment) {
-        iinc(var, increment);
-    }
-
-    @Override
-    public void visitTableSwitchInsn(final int min, final int max,
-            final Label dflt, final Label... labels) {
-        tableswitch(min, max, dflt, labels);
-    }
-
-    @Override
-    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
-            final Label[] labels) {
-        lookupswitch(dflt, keys, labels);
-    }
-
-    @Override
-    public void visitMultiANewArrayInsn(final String desc, final int dims) {
-        multianewarray(desc, dims);
-    }
-
-    // -----------------------------------------------------------------------
-
-    public void nop() {
-        mv.visitInsn(Opcodes.NOP);
-    }
-
-    public void aconst(final Object cst) {
-        if (cst == null) {
-            mv.visitInsn(Opcodes.ACONST_NULL);
-        } else {
-            mv.visitLdcInsn(cst);
-        }
-    }
-
-    public void iconst(final int cst) {
-        if (cst >= -1 && cst <= 5) {
-            mv.visitInsn(Opcodes.ICONST_0 + cst);
-        } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {
-            mv.visitIntInsn(Opcodes.BIPUSH, cst);
-        } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {
-            mv.visitIntInsn(Opcodes.SIPUSH, cst);
-        } else {
-            mv.visitLdcInsn(cst);
-        }
-    }
-
-    public void lconst(final long cst) {
-        if (cst == 0L || cst == 1L) {
-            mv.visitInsn(Opcodes.LCONST_0 + (int) cst);
-        } else {
-            mv.visitLdcInsn(cst);
-        }
-    }
-
-    public void fconst(final float cst) {
-        int bits = Float.floatToIntBits(cst);
-        if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2
-            mv.visitInsn(Opcodes.FCONST_0 + (int) cst);
-        } else {
-            mv.visitLdcInsn(cst);
-        }
-    }
-
-    public void dconst(final double cst) {
-        long bits = Double.doubleToLongBits(cst);
-        if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d
-            mv.visitInsn(Opcodes.DCONST_0 + (int) cst);
-        } else {
-            mv.visitLdcInsn(cst);
-        }
-    }
-
-    public void tconst(final Type type) {
-        mv.visitLdcInsn(type);
-    }
-
-    public void hconst(final Handle handle) {
-        mv.visitLdcInsn(handle);
-    }
-
-    public void load(final int var, final Type type) {
-        mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), var);
-    }
-
-    public void aload(final Type type) {
-        mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
-    }
-
-    public void store(final int var, final Type type) {
-        mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), var);
-    }
-
-    public void astore(final Type type) {
-        mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
-    }
-
-    public void pop() {
-        mv.visitInsn(Opcodes.POP);
-    }
-
-    public void pop2() {
-        mv.visitInsn(Opcodes.POP2);
-    }
-
-    public void dup() {
-        mv.visitInsn(Opcodes.DUP);
-    }
-
-    public void dup2() {
-        mv.visitInsn(Opcodes.DUP2);
-    }
-
-    public void dupX1() {
-        mv.visitInsn(Opcodes.DUP_X1);
-    }
-
-    public void dupX2() {
-        mv.visitInsn(Opcodes.DUP_X2);
-    }
-
-    public void dup2X1() {
-        mv.visitInsn(Opcodes.DUP2_X1);
-    }
-
-    public void dup2X2() {
-        mv.visitInsn(Opcodes.DUP2_X2);
-    }
-
-    public void swap() {
-        mv.visitInsn(Opcodes.SWAP);
-    }
-
-    public void add(final Type type) {
-        mv.visitInsn(type.getOpcode(Opcodes.IADD));
-    }
-
-    public void sub(final Type type) {
-        mv.visitInsn(type.getOpcode(Opcodes.ISUB));
-    }
-
-    public void mul(final Type type) {
-        mv.visitInsn(type.getOpcode(Opcodes.IMUL));
-    }
-
-    public void div(final Type type) {
-        mv.visitInsn(type.getOpcode(Opcodes.IDIV));
-    }
-
-    public void rem(final Type type) {
-        mv.visitInsn(type.getOpcode(Opcodes.IREM));
-    }
-
-    public void neg(final Type type) {
-        mv.visitInsn(type.getOpcode(Opcodes.INEG));
-    }
-
-    public void shl(final Type type) {
-        mv.visitInsn(type.getOpcode(Opcodes.ISHL));
-    }
-
-    public void shr(final Type type) {
-        mv.visitInsn(type.getOpcode(Opcodes.ISHR));
-    }
-
-    public void ushr(final Type type) {
-        mv.visitInsn(type.getOpcode(Opcodes.IUSHR));
-    }
-
-    public void and(final Type type) {
-        mv.visitInsn(type.getOpcode(Opcodes.IAND));
-    }
-
-    public void or(final Type type) {
-        mv.visitInsn(type.getOpcode(Opcodes.IOR));
-    }
-
-    public void xor(final Type type) {
-        mv.visitInsn(type.getOpcode(Opcodes.IXOR));
-    }
-
-    public void iinc(final int var, final int increment) {
-        mv.visitIincInsn(var, increment);
-    }
-
-    public void cast(final Type from, final Type to) {
-        if (from != to) {
-            if (from == Type.DOUBLE_TYPE) {
-                if (to == Type.FLOAT_TYPE) {
-                    mv.visitInsn(Opcodes.D2F);
-                } else if (to == Type.LONG_TYPE) {
-                    mv.visitInsn(Opcodes.D2L);
-                } else {
-                    mv.visitInsn(Opcodes.D2I);
-                    cast(Type.INT_TYPE, to);
-                }
-            } else if (from == Type.FLOAT_TYPE) {
-                if (to == Type.DOUBLE_TYPE) {
-                    mv.visitInsn(Opcodes.F2D);
-                } else if (to == Type.LONG_TYPE) {
-                    mv.visitInsn(Opcodes.F2L);
-                } else {
-                    mv.visitInsn(Opcodes.F2I);
-                    cast(Type.INT_TYPE, to);
-                }
-            } else if (from == Type.LONG_TYPE) {
-                if (to == Type.DOUBLE_TYPE) {
-                    mv.visitInsn(Opcodes.L2D);
-                } else if (to == Type.FLOAT_TYPE) {
-                    mv.visitInsn(Opcodes.L2F);
-                } else {
-                    mv.visitInsn(Opcodes.L2I);
-                    cast(Type.INT_TYPE, to);
-                }
-            } else {
-                if (to == Type.BYTE_TYPE) {
-                    mv.visitInsn(Opcodes.I2B);
-                } else if (to == Type.CHAR_TYPE) {
-                    mv.visitInsn(Opcodes.I2C);
-                } else if (to == Type.DOUBLE_TYPE) {
-                    mv.visitInsn(Opcodes.I2D);
-                } else if (to == Type.FLOAT_TYPE) {
-                    mv.visitInsn(Opcodes.I2F);
-                } else if (to == Type.LONG_TYPE) {
-                    mv.visitInsn(Opcodes.I2L);
-                } else if (to == Type.SHORT_TYPE) {
-                    mv.visitInsn(Opcodes.I2S);
-                }
-            }
-        }
-    }
-
-    public void lcmp() {
-        mv.visitInsn(Opcodes.LCMP);
-    }
-
-    public void cmpl(final Type type) {
-        mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPL : Opcodes.DCMPL);
-    }
-
-    public void cmpg(final Type type) {
-        mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPG : Opcodes.DCMPG);
-    }
-
-    public void ifeq(final Label label) {
-        mv.visitJumpInsn(Opcodes.IFEQ, label);
-    }
-
-    public void ifne(final Label label) {
-        mv.visitJumpInsn(Opcodes.IFNE, label);
-    }
-
-    public void iflt(final Label label) {
-        mv.visitJumpInsn(Opcodes.IFLT, label);
-    }
-
-    public void ifge(final Label label) {
-        mv.visitJumpInsn(Opcodes.IFGE, label);
-    }
-
-    public void ifgt(final Label label) {
-        mv.visitJumpInsn(Opcodes.IFGT, label);
-    }
-
-    public void ifle(final Label label) {
-        mv.visitJumpInsn(Opcodes.IFLE, label);
-    }
-
-    public void ificmpeq(final Label label) {
-        mv.visitJumpInsn(Opcodes.IF_ICMPEQ, label);
-    }
-
-    public void ificmpne(final Label label) {
-        mv.visitJumpInsn(Opcodes.IF_ICMPNE, label);
-    }
-
-    public void ificmplt(final Label label) {
-        mv.visitJumpInsn(Opcodes.IF_ICMPLT, label);
-    }
-
-    public void ificmpge(final Label label) {
-        mv.visitJumpInsn(Opcodes.IF_ICMPGE, label);
-    }
-
-    public void ificmpgt(final Label label) {
-        mv.visitJumpInsn(Opcodes.IF_ICMPGT, label);
-    }
-
-    public void ificmple(final Label label) {
-        mv.visitJumpInsn(Opcodes.IF_ICMPLE, label);
-    }
-
-    public void ifacmpeq(final Label label) {
-        mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
-    }
-
-    public void ifacmpne(final Label label) {
-        mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
-    }
-
-    public void goTo(final Label label) {
-        mv.visitJumpInsn(Opcodes.GOTO, label);
-    }
-
-    public void jsr(final Label label) {
-        mv.visitJumpInsn(Opcodes.JSR, label);
-    }
-
-    public void ret(final int var) {
-        mv.visitVarInsn(Opcodes.RET, var);
-    }
-
-    public void tableswitch(final int min, final int max, final Label dflt,
-            final Label... labels) {
-        mv.visitTableSwitchInsn(min, max, dflt, labels);
-    }
-
-    public void lookupswitch(final Label dflt, final int[] keys,
-            final Label[] labels) {
-        mv.visitLookupSwitchInsn(dflt, keys, labels);
-    }
-
-    public void areturn(final Type t) {
-        mv.visitInsn(t.getOpcode(Opcodes.IRETURN));
-    }
-
-    public void getstatic(final String owner, final String name,
-            final String desc) {
-        mv.visitFieldInsn(Opcodes.GETSTATIC, owner, name, desc);
-    }
-
-    public void putstatic(final String owner, final String name,
-            final String desc) {
-        mv.visitFieldInsn(Opcodes.PUTSTATIC, owner, name, desc);
-    }
-
-    public void getfield(final String owner, final String name,
-            final String desc) {
-        mv.visitFieldInsn(Opcodes.GETFIELD, owner, name, desc);
-    }
-
-    public void putfield(final String owner, final String name,
-            final String desc) {
-        mv.visitFieldInsn(Opcodes.PUTFIELD, owner, name, desc);
-    }
-
-    @Deprecated
-    public void invokevirtual(final String owner, final String name,
-            final String desc) {
-        if (api >= Opcodes.ASM5) {
-            invokevirtual(owner, name, desc, false);
-            return;
-        }
-        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc);
-    }
-
-    public void invokevirtual(final String owner, final String name,
-            final String desc, final boolean itf) {
-        if (api < Opcodes.ASM5) {
-            if (itf) {
-                throw new IllegalArgumentException(
-                        "INVOKEVIRTUAL on interfaces require ASM 5");
-            }
-            invokevirtual(owner, name, desc);
-            return;
-        }
-        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, itf);
-    }
-
-    @Deprecated
-    public void invokespecial(final String owner, final String name,
-            final String desc) {
-        if (api >= Opcodes.ASM5) {
-            invokespecial(owner, name, desc, false);
-            return;
-        }
-        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, false);
-    }
-
-    public void invokespecial(final String owner, final String name,
-            final String desc, final boolean itf) {
-        if (api < Opcodes.ASM5) {
-            if (itf) {
-                throw new IllegalArgumentException(
-                        "INVOKESPECIAL on interfaces require ASM 5");
-            }
-            invokespecial(owner, name, desc);
-            return;
-        }
-        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, itf);
-    }
-
-    @Deprecated
-    public void invokestatic(final String owner, final String name,
-            final String desc) {
-        if (api >= Opcodes.ASM5) {
-            invokestatic(owner, name, desc, false);
-            return;
-        }
-        mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, false);
-    }
-
-    public void invokestatic(final String owner, final String name,
-            final String desc, final boolean itf) {
-        if (api < Opcodes.ASM5) {
-            if (itf) {
-                throw new IllegalArgumentException(
-                        "INVOKESTATIC on interfaces require ASM 5");
-            }
-            invokestatic(owner, name, desc);
-            return;
-        }
-        mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, itf);
-    }
-
-    public void invokeinterface(final String owner, final String name,
-            final String desc) {
-        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, desc, true);
-    }
-
-    public void invokedynamic(String name, String desc, Handle bsm,
-            Object[] bsmArgs) {
-        mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
-    }
-
-    public void anew(final Type type) {
-        mv.visitTypeInsn(Opcodes.NEW, type.getInternalName());
-    }
-
-    public void newarray(final Type type) {
-        int typ;
-        switch (type.getSort()) {
-        case Type.BOOLEAN:
-            typ = Opcodes.T_BOOLEAN;
-            break;
-        case Type.CHAR:
-            typ = Opcodes.T_CHAR;
-            break;
-        case Type.BYTE:
-            typ = Opcodes.T_BYTE;
-            break;
-        case Type.SHORT:
-            typ = Opcodes.T_SHORT;
-            break;
-        case Type.INT:
-            typ = Opcodes.T_INT;
-            break;
-        case Type.FLOAT:
-            typ = Opcodes.T_FLOAT;
-            break;
-        case Type.LONG:
-            typ = Opcodes.T_LONG;
-            break;
-        case Type.DOUBLE:
-            typ = Opcodes.T_DOUBLE;
-            break;
-        default:
-            mv.visitTypeInsn(Opcodes.ANEWARRAY, type.getInternalName());
-            return;
-        }
-        mv.visitIntInsn(Opcodes.NEWARRAY, typ);
-    }
-
-    public void arraylength() {
-        mv.visitInsn(Opcodes.ARRAYLENGTH);
-    }
-
-    public void athrow() {
-        mv.visitInsn(Opcodes.ATHROW);
-    }
-
-    public void checkcast(final Type type) {
-        mv.visitTypeInsn(Opcodes.CHECKCAST, type.getInternalName());
-    }
-
-    public void instanceOf(final Type type) {
-        mv.visitTypeInsn(Opcodes.INSTANCEOF, type.getInternalName());
-    }
-
-    public void monitorenter() {
-        mv.visitInsn(Opcodes.MONITORENTER);
-    }
-
-    public void monitorexit() {
-        mv.visitInsn(Opcodes.MONITOREXIT);
-    }
-
-    public void multianewarray(final String desc, final int dims) {
-        mv.visitMultiANewArrayInsn(desc, dims);
-    }
-
-    public void ifnull(final Label label) {
-        mv.visitJumpInsn(Opcodes.IFNULL, label);
-    }
-
-    public void ifnonnull(final Label label) {
-        mv.visitJumpInsn(Opcodes.IFNONNULL, label);
-    }
-
-    public void mark(final Label label) {
-        mv.visitLabel(label);
-    }
-}
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the copyright holders nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.apache.tapestry5.internal.plastic.asm.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.ConstantDynamic;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A {@link MethodVisitor} providing a more detailed API to generate and transform instructions.
+ *
+ * @author Eric Bruneton
+ */
+public class InstructionAdapter extends MethodVisitor {
+
+  /** The type of the java.lang.Object class. */
+  public static final Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;");
+
+  /**
+   * Constructs a new {@link InstructionAdapter}. <i>Subclasses must not use this constructor</i>.
+   * Instead, they must use the {@link #InstructionAdapter(int, MethodVisitor)} version.
+   *
+   * @param methodVisitor the method visitor to which this adapter delegates calls.
+   * @throws IllegalStateException If a subclass calls this constructor.
+   */
+  public InstructionAdapter(final MethodVisitor methodVisitor) {
+    this(Opcodes.ASM7, methodVisitor);
+    if (getClass() != InstructionAdapter.class) {
+      throw new IllegalStateException();
+    }
+  }
+
+  /**
+   * Constructs a new {@link InstructionAdapter}.
+   *
+   * @param api the ASM API version implemented by this visitor. Must be one of {@link
+   *     Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
+   * @param methodVisitor the method visitor to which this adapter delegates calls.
+   */
+  protected InstructionAdapter(final int api, final MethodVisitor methodVisitor) {
+    super(api, methodVisitor);
+  }
+
+  @Override
+  public void visitInsn(final int opcode) {
+    switch (opcode) {
+      case Opcodes.NOP:
+        nop();
+        break;
+      case Opcodes.ACONST_NULL:
+        aconst(null);
+        break;
+      case Opcodes.ICONST_M1:
+      case Opcodes.ICONST_0:
+      case Opcodes.ICONST_1:
+      case Opcodes.ICONST_2:
+      case Opcodes.ICONST_3:
+      case Opcodes.ICONST_4:
+      case Opcodes.ICONST_5:
+        iconst(opcode - Opcodes.ICONST_0);
+        break;
+      case Opcodes.LCONST_0:
+      case Opcodes.LCONST_1:
+        lconst((long) (opcode - Opcodes.LCONST_0));
+        break;
+      case Opcodes.FCONST_0:
+      case Opcodes.FCONST_1:
+      case Opcodes.FCONST_2:
+        fconst((float) (opcode - Opcodes.FCONST_0));
+        break;
+      case Opcodes.DCONST_0:
+      case Opcodes.DCONST_1:
+        dconst((double) (opcode - Opcodes.DCONST_0));
+        break;
+      case Opcodes.IALOAD:
+        aload(Type.INT_TYPE);
+        break;
+      case Opcodes.LALOAD:
+        aload(Type.LONG_TYPE);
+        break;
+      case Opcodes.FALOAD:
+        aload(Type.FLOAT_TYPE);
+        break;
+      case Opcodes.DALOAD:
+        aload(Type.DOUBLE_TYPE);
+        break;
+      case Opcodes.AALOAD:
+        aload(OBJECT_TYPE);
+        break;
+      case Opcodes.BALOAD:
+        aload(Type.BYTE_TYPE);
+        break;
+      case Opcodes.CALOAD:
+        aload(Type.CHAR_TYPE);
+        break;
+      case Opcodes.SALOAD:
+        aload(Type.SHORT_TYPE);
+        break;
+      case Opcodes.IASTORE:
+        astore(Type.INT_TYPE);
+        break;
+      case Opcodes.LASTORE:
+        astore(Type.LONG_TYPE);
+        break;
+      case Opcodes.FASTORE:
+        astore(Type.FLOAT_TYPE);
+        break;
+      case Opcodes.DASTORE:
+        astore(Type.DOUBLE_TYPE);
+        break;
+      case Opcodes.AASTORE:
+        astore(OBJECT_TYPE);
+        break;
+      case Opcodes.BASTORE:
+        astore(Type.BYTE_TYPE);
+        break;
+      case Opcodes.CASTORE:
+        astore(Type.CHAR_TYPE);
+        break;
+      case Opcodes.SASTORE:
+        astore(Type.SHORT_TYPE);
+        break;
+      case Opcodes.POP:
+        pop();
+        break;
+      case Opcodes.POP2:
+        pop2();
+        break;
+      case Opcodes.DUP:
+        dup();
+        break;
+      case Opcodes.DUP_X1:
+        dupX1();
+        break;
+      case Opcodes.DUP_X2:
+        dupX2();
+        break;
+      case Opcodes.DUP2:
+        dup2();
+        break;
+      case Opcodes.DUP2_X1:
+        dup2X1();
+        break;
+      case Opcodes.DUP2_X2:
+        dup2X2();
+        break;
+      case Opcodes.SWAP:
+        swap();
+        break;
+      case Opcodes.IADD:
+        add(Type.INT_TYPE);
+        break;
+      case Opcodes.LADD:
+        add(Type.LONG_TYPE);
+        break;
+      case Opcodes.FADD:
+        add(Type.FLOAT_TYPE);
+        break;
+      case Opcodes.DADD:
+        add(Type.DOUBLE_TYPE);
+        break;
+      case Opcodes.ISUB:
+        sub(Type.INT_TYPE);
+        break;
+      case Opcodes.LSUB:
+        sub(Type.LONG_TYPE);
+        break;
+      case Opcodes.FSUB:
+        sub(Type.FLOAT_TYPE);
+        break;
+      case Opcodes.DSUB:
+        sub(Type.DOUBLE_TYPE);
+        break;
+      case Opcodes.IMUL:
+        mul(Type.INT_TYPE);
+        break;
+      case Opcodes.LMUL:
+        mul(Type.LONG_TYPE);
+        break;
+      case Opcodes.FMUL:
+        mul(Type.FLOAT_TYPE);
+        break;
+      case Opcodes.DMUL:
+        mul(Type.DOUBLE_TYPE);
+        break;
+      case Opcodes.IDIV:
+        div(Type.INT_TYPE);
+        break;
+      case Opcodes.LDIV:
+        div(Type.LONG_TYPE);
+        break;
+      case Opcodes.FDIV:
+        div(Type.FLOAT_TYPE);
+        break;
+      case Opcodes.DDIV:
+        div(Type.DOUBLE_TYPE);
+        break;
+      case Opcodes.IREM:
+        rem(Type.INT_TYPE);
+        break;
+      case Opcodes.LREM:
+        rem(Type.LONG_TYPE);
+        break;
+      case Opcodes.FREM:
+        rem(Type.FLOAT_TYPE);
+        break;
+      case Opcodes.DREM:
+        rem(Type.DOUBLE_TYPE);
+        break;
+      case Opcodes.INEG:
+        neg(Type.INT_TYPE);
+        break;
+      case Opcodes.LNEG:
+        neg(Type.LONG_TYPE);
+        break;
+      case Opcodes.FNEG:
+        neg(Type.FLOAT_TYPE);
+        break;
+      case Opcodes.DNEG:
+        neg(Type.DOUBLE_TYPE);
+        break;
+      case Opcodes.ISHL:
+        shl(Type.INT_TYPE);
+        break;
+      case Opcodes.LSHL:
+        shl(Type.LONG_TYPE);
+        break;
+      case Opcodes.ISHR:
+        shr(Type.INT_TYPE);
+        break;
+      case Opcodes.LSHR:
+        shr(Type.LONG_TYPE);
+        break;
+      case Opcodes.IUSHR:
+        ushr(Type.INT_TYPE);
+        break;
+      case Opcodes.LUSHR:
+        ushr(Type.LONG_TYPE);
+        break;
+      case Opcodes.IAND:
+        and(Type.INT_TYPE);
+        break;
+      case Opcodes.LAND:
+        and(Type.LONG_TYPE);
+        break;
+      case Opcodes.IOR:
+        or(Type.INT_TYPE);
+        break;
+      case Opcodes.LOR:
+        or(Type.LONG_TYPE);
+        break;
+      case Opcodes.IXOR:
+        xor(Type.INT_TYPE);
+        break;
+      case Opcodes.LXOR:
+        xor(Type.LONG_TYPE);
+        break;
+      case Opcodes.I2L:
+        cast(Type.INT_TYPE, Type.LONG_TYPE);
+        break;
+      case Opcodes.I2F:
+        cast(Type.INT_TYPE, Type.FLOAT_TYPE);
+        break;
+      case Opcodes.I2D:
+        cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
+        break;
+      case Opcodes.L2I:
+        cast(Type.LONG_TYPE, Type.INT_TYPE);
+        break;
+      case Opcodes.L2F:
+        cast(Type.LONG_TYPE, Type.FLOAT_TYPE);
+        break;
+      case Opcodes.L2D:
+        cast(Type.LONG_TYPE, Type.DOUBLE_TYPE);
+        break;
+      case Opcodes.F2I:
+        cast(Type.FLOAT_TYPE, Type.INT_TYPE);
+        break;
+      case Opcodes.F2L:
+        cast(Type.FLOAT_TYPE, Type.LONG_TYPE);
+        break;
+      case Opcodes.F2D:
+        cast(Type.FLOAT_TYPE, Type.DOUBLE_TYPE);
+        break;
+      case Opcodes.D2I:
+        cast(Type.DOUBLE_TYPE, Type.INT_TYPE);
+        break;
+      case Opcodes.D2L:
+        cast(Type.DOUBLE_TYPE, Type.LONG_TYPE);
+        break;
+      case Opcodes.D2F:
+        cast(Type.DOUBLE_TYPE, Type.FLOAT_TYPE);
+        break;
+      case Opcodes.I2B:
+        cast(Type.INT_TYPE, Type.BYTE_TYPE);
+        break;
+      case Opcodes.I2C:
+        cast(Type.INT_TYPE, Type.CHAR_TYPE);
+        break;
+      case Opcodes.I2S:
+        cast(Type.INT_TYPE, Type.SHORT_TYPE);
+        break;
+      case Opcodes.LCMP:
+        lcmp();
+        break;
+      case Opcodes.FCMPL:
+        cmpl(Type.FLOAT_TYPE);
+        break;
+      case Opcodes.FCMPG:
+        cmpg(Type.FLOAT_TYPE);
+        break;
+      case Opcodes.DCMPL:
+        cmpl(Type.DOUBLE_TYPE);
+        break;
+      case Opcodes.DCMPG:
+        cmpg(Type.DOUBLE_TYPE);
+        break;
+      case Opcodes.IRETURN:
+        areturn(Type.INT_TYPE);
+        break;
+      case Opcodes.LRETURN:
+        areturn(Type.LONG_TYPE);
+        break;
+      case Opcodes.FRETURN:
+        areturn(Type.FLOAT_TYPE);
+        break;
+      case Opcodes.DRETURN:
+        areturn(Type.DOUBLE_TYPE);
+        break;
+      case Opcodes.ARETURN:
+        areturn(OBJECT_TYPE);
+        break;
+      case Opcodes.RETURN:
+        areturn(Type.VOID_TYPE);
+        break;
+      case Opcodes.ARRAYLENGTH:
+        arraylength();
+        break;
+      case Opcodes.ATHROW:
+        athrow();
+        break;
+      case Opcodes.MONITORENTER:
+        monitorenter();
+        break;
+      case Opcodes.MONITOREXIT:
+        monitorexit();
+        break;
+      default:
+        throw new IllegalArgumentException();
+    }
+  }
+
+  @Override
+  public void visitIntInsn(final int opcode, final int operand) {
+    switch (opcode) {
+      case Opcodes.BIPUSH:
+        iconst(operand);
+        break;
+      case Opcodes.SIPUSH:
+        iconst(operand);
+        break;
+      case Opcodes.NEWARRAY:
+        switch (operand) {
+          case Opcodes.T_BOOLEAN:
+            newarray(Type.BOOLEAN_TYPE);
+            break;
+          case Opcodes.T_CHAR:
+            newarray(Type.CHAR_TYPE);
+            break;
+          case Opcodes.T_BYTE:
+            newarray(Type.BYTE_TYPE);
+            break;
+          case Opcodes.T_SHORT:
+            newarray(Type.SHORT_TYPE);
+            break;
+          case Opcodes.T_INT:
+            newarray(Type.INT_TYPE);
+            break;
+          case Opcodes.T_FLOAT:
+            newarray(Type.FLOAT_TYPE);
+            break;
+          case Opcodes.T_LONG:
+            newarray(Type.LONG_TYPE);
+            break;
+          case Opcodes.T_DOUBLE:
+            newarray(Type.DOUBLE_TYPE);
+            break;
+          default:
+            throw new IllegalArgumentException();
+        }
+        break;
+      default:
+        throw new IllegalArgumentException();
+    }
+  }
+
+  @Override
+  public void visitVarInsn(final int opcode, final int var) {
+    switch (opcode) {
+      case Opcodes.ILOAD:
+        load(var, Type.INT_TYPE);
+        break;
+      case Opcodes.LLOAD:
+        load(var, Type.LONG_TYPE);
+        break;
+      case Opcodes.FLOAD:
+        load(var, Type.FLOAT_TYPE);
+        break;
+      case Opcodes.DLOAD:
+        load(var, Type.DOUBLE_TYPE);
+        break;
+      case Opcodes.ALOAD:
+        load(var, OBJECT_TYPE);
+        break;
+      case Opcodes.ISTORE:
+        store(var, Type.INT_TYPE);
+        break;
+      case Opcodes.LSTORE:
+        store(var, Type.LONG_TYPE);
+        break;
+      case Opcodes.FSTORE:
+        store(var, Type.FLOAT_TYPE);
+        break;
+      case Opcodes.DSTORE:
+        store(var, Type.DOUBLE_TYPE);
+        break;
+      case Opcodes.ASTORE:
+        store(var, OBJECT_TYPE);
+        break;
+      case Opcodes.RET:
+        ret(var);
+        break;
+      default:
+        throw new IllegalArgumentException();
+    }
+  }
+
+  @Override
+  public void visitTypeInsn(final int opcode, final String type) {
+    Type objectType = Type.getObjectType(type);
+    switch (opcode) {
+      case Opcodes.NEW:
+        anew(objectType);
+        break;
+      case Opcodes.ANEWARRAY:
+        newarray(objectType);
+        break;
+      case Opcodes.CHECKCAST:
+        checkcast(objectType);
+        break;
+      case Opcodes.INSTANCEOF:
+        instanceOf(objectType);
+        break;
+      default:
+        throw new IllegalArgumentException();
+    }
+  }
+
+  @Override
+  public void visitFieldInsn(
+      final int opcode, final String owner, final String name, final String descriptor) {
+    switch (opcode) {
+      case Opcodes.GETSTATIC:
+        getstatic(owner, name, descriptor);
+        break;
+      case Opcodes.PUTSTATIC:
+        putstatic(owner, name, descriptor);
+        break;
+      case Opcodes.GETFIELD:
+        getfield(owner, name, descriptor);
+        break;
+      case Opcodes.PUTFIELD:
+        putfield(owner, name, descriptor);
+        break;
+      default:
+        throw new IllegalArgumentException();
+    }
+  }
+
+  /**
+   * Deprecated.
+   *
+   * @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead.
+   */
+  @Deprecated
+  @Override
+  public void visitMethodInsn(
+      final int opcode, final String owner, final String name, final String descriptor) {
+    if (api >= Opcodes.ASM5) {
+      super.visitMethodInsn(opcode, owner, name, descriptor);
+      return;
+    }
+    doVisitMethodInsn(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE);
+  }
+
+  @Override
+  public void visitMethodInsn(
+      final int opcode,
+      final String owner,
+      final String name,
+      final String descriptor,
+      final boolean isInterface) {
+    if (api < Opcodes.ASM5) {
+      super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+      return;
+    }
+    doVisitMethodInsn(opcode, owner, name, descriptor, isInterface);
+  }
+
+  private void doVisitMethodInsn(
+      final int opcode,
+      final String owner,
+      final String name,
+      final String descriptor,
+      final boolean isInterface) {
+    switch (opcode) {
+      case Opcodes.INVOKESPECIAL:
+        invokespecial(owner, name, descriptor, isInterface);
+        break;
+      case Opcodes.INVOKEVIRTUAL:
+        invokevirtual(owner, name, descriptor, isInterface);
+        break;
+      case Opcodes.INVOKESTATIC:
+        invokestatic(owner, name, descriptor, isInterface);
+        break;
+      case Opcodes.INVOKEINTERFACE:
+        invokeinterface(owner, name, descriptor);
+        break;
+      default:
+        throw new IllegalArgumentException();
+    }
+  }
+
+  @Override
+  public void visitInvokeDynamicInsn(
+      final String name,
+      final String descriptor,
+      final Handle bootstrapMethodHandle,
+      final Object... bootstrapMethodArguments) {
+    invokedynamic(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
+  }
+
+  @Override
+  public void visitJumpInsn(final int opcode, final Label label) {
+    switch (opcode) {
+      case Opcodes.IFEQ:
+        ifeq(label);
+        break;
+      case Opcodes.IFNE:
+        ifne(label);
+        break;
+      case Opcodes.IFLT:
+        iflt(label);
+        break;
+      case Opcodes.IFGE:
+        ifge(label);
+        break;
+      case Opcodes.IFGT:
+        ifgt(label);
+        break;
+      case Opcodes.IFLE:
+        ifle(label);
+        break;
+      case Opcodes.IF_ICMPEQ:
+        ificmpeq(label);
+        break;
+      case Opcodes.IF_ICMPNE:
+        ificmpne(label);
+        break;
+      case Opcodes.IF_ICMPLT:
+        ificmplt(label);
+        break;
+      case Opcodes.IF_ICMPGE:
+        ificmpge(label);
+        break;
+      case Opcodes.IF_ICMPGT:
+        ificmpgt(label);
+        break;
+      case Opcodes.IF_ICMPLE:
+        ificmple(label);
+        break;
+      case Opcodes.IF_ACMPEQ:
+        ifacmpeq(label);
+        break;
+      case Opcodes.IF_ACMPNE:
+        ifacmpne(label);
+        break;
+      case Opcodes.GOTO:
+        goTo(label);
+        break;
+      case Opcodes.JSR:
+        jsr(label);
+        break;
+      case Opcodes.IFNULL:
+        ifnull(label);
+        break;
+      case Opcodes.IFNONNULL:
+        ifnonnull(label);
+        break;
+      default:
+        throw new IllegalArgumentException();
+    }
+  }
+
+  @Override
+  public void visitLabel(final Label label) {
+    mark(label);
+  }
+
+  @Override
+  public void visitLdcInsn(final Object value) {
+    if (api < Opcodes.ASM5
+        && (value instanceof Handle
+            || (value instanceof Type && ((Type) value).getSort() == Type.METHOD))) {
+      throw new UnsupportedOperationException("This feature requires ASM5");
+    }
+    if (api != Opcodes.ASM7 && value instanceof ConstantDynamic) {
+      throw new UnsupportedOperationException("This feature requires ASM7");
+    }
+    if (value instanceof Integer) {
+      iconst((Integer) value);
+    } else if (value instanceof Byte) {
+      iconst(((Byte) value).intValue());
+    } else if (value instanceof Character) {
+      iconst(((Character) value).charValue());
+    } else if (value instanceof Short) {
+      iconst(((Short) value).intValue());
+    } else if (value instanceof Boolean) {
+      iconst(((Boolean) value).booleanValue() ? 1 : 0);
+    } else if (value instanceof Float) {
+      fconst((Float) value);
+    } else if (value instanceof Long) {
+      lconst((Long) value);
+    } else if (value instanceof Double) {
+      dconst((Double) value);
+    } else if (value instanceof String) {
+      aconst(value);
+    } else if (value instanceof Type) {
+      tconst((Type) value);
+    } else if (value instanceof Handle) {
+      hconst((Handle) value);
+    } else if (value instanceof ConstantDynamic) {
+      cconst((ConstantDynamic) value);
+    } else {
+      throw new IllegalArgumentException();
+    }
+  }
+
+  @Override
+  public void visitIincInsn(final int var, final int increment) {
+    iinc(var, increment);
+  }
+
+  @Override
+  public void visitTableSwitchInsn(
+      final int min, final int max, final Label dflt, final Label... labels) {
+    tableswitch(min, max, dflt, labels);
+  }
+
+  @Override
+  public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
+    lookupswitch(dflt, keys, labels);
+  }
+
+  @Override
+  public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
+    multianewarray(descriptor, numDimensions);
+  }
+
+  // -----------------------------------------------------------------------------------------------
+
+  /** Generates a nop instruction. */
+  public void nop() {
+    mv.visitInsn(Opcodes.NOP);
+  }
+
+  /**
+   * Generates the instruction to push the given value on the stack.
+   *
+   * @param value the constant to be pushed on the stack. This parameter must be an {@link Integer},
+   *     a {@link Float}, a {@link Long}, a {@link Double}, a {@link String}, a {@link Type} of
+   *     OBJECT or ARRAY sort for {@code .class} constants, for classes whose version is 49, a
+   *     {@link Type} of METHOD sort for MethodType, a {@link Handle} for MethodHandle constants,
+   *     for classes whose version is 51 or a {@link ConstantDynamic} for a constant dynamic for
+   *     classes whose version is 55.
+   */
+  public void aconst(final Object value) {
+    if (value == null) {
+      mv.visitInsn(Opcodes.ACONST_NULL);
+    } else {
+      mv.visitLdcInsn(value);
+    }
+  }
+
+  /**
+   * Generates the instruction to push the given value on the stack.
+   *
+   * @param intValue the constant to be pushed on the stack.
+   */
+  public void iconst(final int intValue) {
+    if (intValue >= -1 && intValue <= 5) {
+      mv.visitInsn(Opcodes.ICONST_0 + intValue);
+    } else if (intValue >= Byte.MIN_VALUE && intValue <= Byte.MAX_VALUE) {
+      mv.visitIntInsn(Opcodes.BIPUSH, intValue);
+    } else if (intValue >= Short.MIN_VALUE && intValue <= Short.MAX_VALUE) {
+      mv.visitIntInsn(Opcodes.SIPUSH, intValue);
+    } else {
+      mv.visitLdcInsn(intValue);
+    }
+  }
+
+  /**
+   * Generates the instruction to push the given value on the stack.
+   *
+   * @param longValue the constant to be pushed on the stack.
+   */
+  public void lconst(final long longValue) {
+    if (longValue == 0L || longValue == 1L) {
+      mv.visitInsn(Opcodes.LCONST_0 + (int) longValue);
+    } else {
+      mv.visitLdcInsn(longValue);
+    }
+  }
+
+  /**
+   * Generates the instruction to push the given value on the stack.
+   *
+   * @param floatValue the constant to be pushed on the stack.
+   */
+  public void fconst(final float floatValue) {
+    int bits = Float.floatToIntBits(floatValue);
+    if (bits == 0L || bits == 0x3F800000 || bits == 0x40000000) { // 0..2
+      mv.visitInsn(Opcodes.FCONST_0 + (int) floatValue);
+    } else {
+      mv.visitLdcInsn(floatValue);
+    }
+  }
+
+  /**
+   * Generates the instruction to push the given value on the stack.
+   *
+   * @param doubleValue the constant to be pushed on the stack.
+   */
+  public void dconst(final double doubleValue) {
+    long bits = Double.doubleToLongBits(doubleValue);
+    if (bits == 0L || bits == 0x3FF0000000000000L) { // +0.0d and 1.0d
+      mv.visitInsn(Opcodes.DCONST_0 + (int) doubleValue);
+    } else {
+      mv.visitLdcInsn(doubleValue);
+    }
+  }
+
+  /**
+   * Generates the instruction to push the given type on the stack.
+   *
+   * @param type the type to be pushed on the stack.
+   */
+  public void tconst(final Type type) {
+    mv.visitLdcInsn(type);
+  }
+
+  /**
+   * Generates the instruction to push the given handle on the stack.
+   *
+   * @param handle the handle to be pushed on the stack.
+   */
+  public void hconst(final Handle handle) {
+    mv.visitLdcInsn(handle);
+  }
+
+  /**
+   * Generates the instruction to push the given constant dynamic on the stack.
+   *
+   * @param constantDynamic the constant dynamic to be pushed on the stack.
+   */
+  public void cconst(final ConstantDynamic constantDynamic) {
+    mv.visitLdcInsn(constantDynamic);
+  }
+
+  public void load(final int var, final Type type) {
+    mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), var);
+  }
+
+  public void aload(final Type type) {
+    mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
+  }
+
+  public void store(final int var, final Type type) {
+    mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), var);
+  }
+
+  public void astore(final Type type) {
+    mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
+  }
+
+  public void pop() {
+    mv.visitInsn(Opcodes.POP);
+  }
+
+  public void pop2() {
+    mv.visitInsn(Opcodes.POP2);
+  }
+
+  public void dup() {
+    mv.visitInsn(Opcodes.DUP);
+  }
+
+  public void dup2() {
+    mv.visitInsn(Opcodes.DUP2);
+  }
+
+  public void dupX1() {
+    mv.visitInsn(Opcodes.DUP_X1);
+  }
+
+  public void dupX2() {
+    mv.visitInsn(Opcodes.DUP_X2);
+  }
+
+  public void dup2X1() {
+    mv.visitInsn(Opcodes.DUP2_X1);
+  }
+
+  public void dup2X2() {
+    mv.visitInsn(Opcodes.DUP2_X2);
+  }
+
+  public void swap() {
+    mv.visitInsn(Opcodes.SWAP);
+  }
+
+  public void add(final Type type) {
+    mv.visitInsn(type.getOpcode(Opcodes.IADD));
+  }
+
+  public void sub(final Type type) {
+    mv.visitInsn(type.getOpcode(Opcodes.ISUB));
+  }
+
+  public void mul(final Type type) {
+    mv.visitInsn(type.getOpcode(Opcodes.IMUL));
+  }
+
+  public void div(final Type type) {
+    mv.visitInsn(type.getOpcode(Opcodes.IDIV));
+  }
+
+  public void rem(final Type type) {
+    mv.visitInsn(type.getOpcode(Opcodes.IREM));
+  }
+
+  public void neg(final Type type) {
+    mv.visitInsn(type.getOpcode(Opcodes.INEG));
+  }
+
+  public void shl(final Type type) {
+    mv.visitInsn(type.getOpcode(Opcodes.ISHL));
+  }
+
+  public void shr(final Type type) {
+    mv.visitInsn(type.getOpcode(Opcodes.ISHR));
+  }
+
+  public void ushr(final Type type) {
+    mv.visitInsn(type.getOpcode(Opcodes.IUSHR));
+  }
+
+  public void and(final Type type) {
+    mv.visitInsn(type.getOpcode(Opcodes.IAND));
+  }
+
+  public void or(final Type type) {
+    mv.visitInsn(type.getOpcode(Opcodes.IOR));
+  }
+
+  public void xor(final Type type) {
+    mv.visitInsn(type.getOpcode(Opcodes.IXOR));
+  }
+
+  public void iinc(final int var, final int increment) {
+    mv.visitIincInsn(var, increment);
+  }
+
+  /**
+   * Generates the instruction to cast from the first given type to the other.
+   *
+   * @param from a Type.
+   * @param to a Type.
+   */
+  public void cast(final Type from, final Type to) {
+    if (from != to) {
+      if (from == Type.DOUBLE_TYPE) {
+        if (to == Type.FLOAT_TYPE) {
+          mv.visitInsn(Opcodes.D2F);
+        } else if (to == Type.LONG_TYPE) {
+          mv.visitInsn(Opcodes.D2L);
+        } else {
+          mv.visitInsn(Opcodes.D2I);
+          cast(Type.INT_TYPE, to);
+        }
+      } else if (from == Type.FLOAT_TYPE) {
+        if (to == Type.DOUBLE_TYPE) {
+          mv.visitInsn(Opcodes.F2D);
+        } else if (to == Type.LONG_TYPE) {
+          mv.visitInsn(Opcodes.F2L);
+        } else {
+          mv.visitInsn(Opcodes.F2I);
+          cast(Type.INT_TYPE, to);
+        }
+      } else if (from == Type.LONG_TYPE) {
+        if (to == Type.DOUBLE_TYPE) {
+          mv.visitInsn(Opcodes.L2D);
+        } else if (to == Type.FLOAT_TYPE) {
+          mv.visitInsn(Opcodes.L2F);
+        } else {
+          mv.visitInsn(Opcodes.L2I);
+          cast(Type.INT_TYPE, to);
+        }
+      } else {
+        if (to == Type.BYTE_TYPE) {
+          mv.visitInsn(Opcodes.I2B);
+        } else if (to == Type.CHAR_TYPE) {
+          mv.visitInsn(Opcodes.I2C);
+        } else if (to == Type.DOUBLE_TYPE) {
+          mv.visitInsn(Opcodes.I2D);
+        } else if (to == Type.FLOAT_TYPE) {
+          mv.visitInsn(Opcodes.I2F);
+        } else if (to == Type.LONG_TYPE) {
+          mv.visitInsn(Opcodes.I2L);
+        } else if (to == Type.SHORT_TYPE) {
+          mv.visitInsn(Opcodes.I2S);
+        }
+      }
+    }
+  }
+
+  public void lcmp() {
+    mv.visitInsn(Opcodes.LCMP);
+  }
+
+  public void cmpl(final Type type) {
+    mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPL : Opcodes.DCMPL);
+  }
+
+  public void cmpg(final Type type) {
+    mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPG : Opcodes.DCMPG);
+  }
+
+  public void ifeq(final Label label) {
+    mv.visitJumpInsn(Opcodes.IFEQ, label);
+  }
+
+  public void ifne(final Label label) {
+    mv.visitJumpInsn(Opcodes.IFNE, label);
+  }
+
+  public void iflt(final Label label) {
+    mv.visitJumpInsn(Opcodes.IFLT, label);
+  }
+
+  public void ifge(final Label label) {
+    mv.visitJumpInsn(Opcodes.IFGE, label);
+  }
+
+  public void ifgt(final Label label) {
+    mv.visitJumpInsn(Opcodes.IFGT, label);
+  }
+
+  public void ifle(final Label label) {
+    mv.visitJumpInsn(Opcodes.IFLE, label);
+  }
+
+  public void ificmpeq(final Label label) {
+    mv.visitJumpInsn(Opcodes.IF_ICMPEQ, label);
+  }
+
+  public void ificmpne(final Label label) {
+    mv.visitJumpInsn(Opcodes.IF_ICMPNE, label);
+  }
+
+  public void ificmplt(final Label label) {
+    mv.visitJumpInsn(Opcodes.IF_ICMPLT, label);
+  }
+
+  public void ificmpge(final Label label) {
+    mv.visitJumpInsn(Opcodes.IF_ICMPGE, label);
+  }
+
+  public void ificmpgt(final Label label) {
+    mv.visitJumpInsn(Opcodes.IF_ICMPGT, label);
+  }
+
+  public void ificmple(final Label label) {
+    mv.visitJumpInsn(Opcodes.IF_ICMPLE, label);
+  }
+
+  public void ifacmpeq(final Label label) {
+    mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
+  }
+
+  public void ifacmpne(final Label label) {
+    mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
+  }
+
+  public void goTo(final Label label) {
+    mv.visitJumpInsn(Opcodes.GOTO, label);
+  }
+
+  public void jsr(final Label label) {
+    mv.visitJumpInsn(Opcodes.JSR, label);
+  }
+
+  public void ret(final int var) {
+    mv.visitVarInsn(Opcodes.RET, var);
+  }
+
+  public void tableswitch(final int min, final int max, final Label dflt, final Label... labels) {
+    mv.visitTableSwitchInsn(min, max, dflt, labels);
+  }
+
+  public void lookupswitch(final Label dflt, final int[] keys, final Label[] labels) {
+    mv.visitLookupSwitchInsn(dflt, keys, labels);
+  }
+
+  public void areturn(final Type type) {
+    mv.visitInsn(type.getOpcode(Opcodes.IRETURN));
+  }
+
+  public void getstatic(final String owner, final String name, final String descriptor) {
+    mv.visitFieldInsn(Opcodes.GETSTATIC, owner, name, descriptor);
+  }
+
+  public void putstatic(final String owner, final String name, final String descriptor) {
+    mv.visitFieldInsn(Opcodes.PUTSTATIC, owner, name, descriptor);
+  }
+
+  public void getfield(final String owner, final String name, final String descriptor) {
+    mv.visitFieldInsn(Opcodes.GETFIELD, owner, name, descriptor);
+  }
+
+  public void putfield(final String owner, final String name, final String descriptor) {
+    mv.visitFieldInsn(Opcodes.PUTFIELD, owner, name, descriptor);
+  }
+
+  /**
+   * Deprecated.
+   *
+   * @param owner the internal name of the method's owner class.
+   * @param name the method's name.
+   * @param descriptor the method's descriptor (see {@link Type}).
+   * @deprecated use {@link #invokevirtual(String, String, String, boolean)} instead.
+   */
+  @Deprecated
+  public void invokevirtual(final String owner, final String name, final String descriptor) {
+    if (api >= Opcodes.ASM5) {
+      invokevirtual(owner, name, descriptor, false);
+      return;
+    }
+    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, descriptor);
+  }
+
+  /**
+   * Generates the instruction to call the given virtual method.
+   *
+   * @param owner the internal name of the method's owner class (see {@link
+   *     Type#getInternalName()}).
+   * @param name the method's name.
+   * @param descriptor the method's descriptor (see {@link Type}).
+   * @param isInterface if the method's owner class is an interface.
+   */
+  public void invokevirtual(
+      final String owner, final String name, final String descriptor, final boolean isInterface) {
+    if (api < Opcodes.ASM5) {
+      if (isInterface) {
+        throw new IllegalArgumentException("INVOKEVIRTUAL on interfaces require ASM 5");
+      }
+      invokevirtual(owner, name, descriptor);
+      return;
+    }
+    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, descriptor, isInterface);
+  }
+
+  /**
+   * Deprecated.
+   *
+   * @param owner the internal name of the method's owner class.
+   * @param name the method's name.
+   * @param descriptor the method's descriptor (see {@link Type}).
+   * @deprecated use {@link #invokespecial(String, String, String, boolean)} instead.
+   */
+  @Deprecated
+  public void invokespecial(final String owner, final String name, final String descriptor) {
+    if (api >= Opcodes.ASM5) {
+      invokespecial(owner, name, descriptor, false);
+      return;
+    }
+    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, descriptor, false);
+  }
+
+  /**
+   * Generates the instruction to call the given special method.
+   *
+   * @param owner the internal name of the method's owner class (see {@link
+   *     Type#getInternalName()}).
+   * @param name the method's name.
+   * @param descriptor the method's descriptor (see {@link Type}).
+   * @param isInterface if the method's owner class is an interface.
+   */
+  public void invokespecial(
+      final String owner, final String name, final String descriptor, final boolean isInterface) {
+    if (api < Opcodes.ASM5) {
+      if (isInterface) {
+        throw new IllegalArgumentException("INVOKESPECIAL on interfaces require ASM 5");
+      }
+      invokespecial(owner, name, descriptor);
+      return;
+    }
+    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, descriptor, isInterface);
+  }
+
+  /**
+   * Deprecated.
+   *
+   * @param owner the internal name of the method's owner class.
+   * @param name the method's name.
+   * @param descriptor the method's descriptor (see {@link Type}).
+   * @deprecated use {@link #invokestatic(String, String, String, boolean)} instead.
+   */
+  @Deprecated
+  public void invokestatic(final String owner, final String name, final String descriptor) {
+    if (api >= Opcodes.ASM5) {
+      invokestatic(owner, name, descriptor, false);
+      return;
+    }
+    mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, descriptor, false);
+  }
+
+  /**
+   * Generates the instruction to call the given static method.
+   *
+   * @param owner the internal name of the method's owner class (see {@link
+   *     Type#getInternalName()}).
+   * @param name the method's name.
+   * @param descriptor the method's descriptor (see {@link Type}).
+   * @param isInterface if the method's owner class is an interface.
+   */
+  public void invokestatic(
+      final String owner, final String name, final String descriptor, final boolean isInterface) {
+    if (api < Opcodes.ASM5) {
+      if (isInterface) {
+        throw new IllegalArgumentException("INVOKESTATIC on interfaces require ASM 5");
+      }
+      invokestatic(owner, name, descriptor);
+      return;
+    }
+    mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, descriptor, isInterface);
+  }
+
+  /**
+   * Generates the instruction to call the given interface method.
+   *
+   * @param owner the internal name of the method's owner class (see {@link
+   *     Type#getInternalName()}).
+   * @param name the method's name.
+   * @param descriptor the method's descriptor (see {@link Type}).
+   */
+  public void invokeinterface(final String owner, final String name, final String descriptor) {
+    mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, descriptor, true);
+  }
+
+  /**
+   * Generates the instruction to call the given dynamic method.
+   *
+   * @param name the method's name.
+   * @param descriptor the method's descriptor (see {@link Type}).
+   * @param bootstrapMethodHandle the bootstrap method.
+   * @param bootstrapMethodArguments the bootstrap method constant arguments. Each argument must be
+   *     an {@link Integer}, {@link Float}, {@link Long}, {@link Double}, {@link String}, {@link
+   *     Type}, {@link Handle} or {@link ConstantDynamic} value. This method is allowed to modify
+   *     the content of the array so a caller should expect that this array may change.
+   */
+  public void invokedynamic(
+      final String name,
+      final String descriptor,
+      final Handle bootstrapMethodHandle,
+      final Object[] bootstrapMethodArguments) {
+    mv.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
+  }
+
+  public void anew(final Type type) {
+    mv.visitTypeInsn(Opcodes.NEW, type.getInternalName());
+  }
+
+  /**
+   * Generates the instruction to create and push on the stack an array of the given type.
+   *
+   * @param type an array Type.
+   */
+  public void newarray(final Type type) {
+    int arrayType;
+    switch (type.getSort()) {
+      case Type.BOOLEAN:
+        arrayType = Opcodes.T_BOOLEAN;
+        break;
+      case Type.CHAR:
+        arrayType = Opcodes.T_CHAR;
+        break;
+      case Type.BYTE:
+        arrayType = Opcodes.T_BYTE;
+        break;
+      case Type.SHORT:
+        arrayType = Opcodes.T_SHORT;
+        break;
+      case Type.INT:
+        arrayType = Opcodes.T_INT;
+        break;
+      case Type.FLOAT:
+        arrayType = Opcodes.T_FLOAT;
+        break;
+      case Type.LONG:
+        arrayType = Opcodes.T_LONG;
+        break;
+      case Type.DOUBLE:
+        arrayType = Opcodes.T_DOUBLE;
+        break;
+      default:
+        mv.visitTypeInsn(Opcodes.ANEWARRAY, type.getInternalName());
+        return;
+    }
+    mv.visitIntInsn(Opcodes.NEWARRAY, arrayType);
+  }
+
+  public void arraylength() {
+    mv.visitInsn(Opcodes.ARRAYLENGTH);
+  }
+
+  public void athrow() {
+    mv.visitInsn(Opcodes.ATHROW);
+  }
+
+  public void checkcast(final Type type) {
+    mv.visitTypeInsn(Opcodes.CHECKCAST, type.getInternalName());
+  }
+
+  public void instanceOf(final Type type) {
+    mv.visitTypeInsn(Opcodes.INSTANCEOF, type.getInternalName());
+  }
+
+  public void monitorenter() {
+    mv.visitInsn(Opcodes.MONITORENTER);
+  }
+
+  public void monitorexit() {
+    mv.visitInsn(Opcodes.MONITOREXIT);
+  }
+
+  public void multianewarray(final String descriptor, final int numDimensions) {
+    mv.visitMultiANewArrayInsn(descriptor, numDimensions);
+  }
+
+  public void ifnull(final Label label) {
+    mv.visitJumpInsn(Opcodes.IFNULL, label);
+  }
+
+  public void ifnonnull(final Label label) {
+    mv.visitJumpInsn(Opcodes.IFNONNULL, label);
+  }
+
+  public void mark(final Label label) {
+    mv.visitLabel(label);
+  }
+}