added InstructionAdapter (requested by users) and TryCatchBlockSorter (provided by Adrian Sampson)
diff --git a/src/org/objectweb/asm/commons/InstructionAdapter.java b/src/org/objectweb/asm/commons/InstructionAdapter.java
new file mode 100644
index 0000000..9f62009
--- /dev/null
+++ b/src/org/objectweb/asm/commons/InstructionAdapter.java
@@ -0,0 +1,1079 @@
+/***

+ * ASM: a very small and fast Java bytecode manipulation framework

+ * Copyright (c) 2000-2005 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.commons;

+

+import org.objectweb.asm.Label;

+import org.objectweb.asm.MethodAdapter;

+import org.objectweb.asm.MethodVisitor;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.Type;

+

+public class InstructionAdapter extends MethodAdapter {

+

+    public final static Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;");

+

+    public InstructionAdapter(MethodVisitor mv) {

+        super(mv);

+    }

+

+    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();

+        }

+    }

+

+    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();

+        }

+    }

+

+    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();

+        }

+    }

+

+    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();

+        }

+    }

+

+    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();

+        }

+    }

+

+    public void visitMethodInsn(

+        final int opcode,

+        final String owner,

+        final String name,

+        final String desc)

+    {

+        switch (opcode) {

+            case Opcodes.INVOKESPECIAL:

+                invokespecial(owner, name, desc);

+                break;

+            case Opcodes.INVOKEVIRTUAL:

+                invokevirtual(owner, name, desc);

+                break;

+            case Opcodes.INVOKESTATIC:

+                invokestatic(owner, name, desc);

+                break;

+            case Opcodes.INVOKEINTERFACE:

+                invokeinterface(owner, name, desc);

+                break;

+            default:

+                throw new IllegalArgumentException();

+        }

+    }

+

+    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();

+        }

+    }

+

+    public void visitLabel(final Label label) {

+        mark(label);

+    }

+

+    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 {

+            throw new IllegalArgumentException();

+        }

+    }

+

+    public void visitIincInsn(final int var, final int increment) {

+        iinc(var, increment);

+    }

+

+    public void visitTableSwitchInsn(

+        final int min,

+        final int max,

+        final Label dflt,

+        final Label[] labels)

+    {

+        tableswitch(min, max, dflt, labels);

+    }

+

+    public void visitLookupSwitchInsn(

+        final Label dflt,

+        final int[] keys,

+        final Label[] labels)

+    {

+        lookupswitch(dflt, keys, labels);

+    }

+

+    public void visitMultiANewArrayInsn(final String desc, final int dims) {

+        multianewarray(desc, dims);

+    }

+

+    // -----------------------------------------------------------------------

+

+    public void nop() {

+        mv.visitInsn(Opcodes.NOP);

+    }

+

+    public void aconst(final Object cst) {

+        if (cst == null) {

+            mv.visitInsn(Opcodes.ACONST_NULL);

+        } else {

+            mv.visitLdcInsn(cst);

+        }

+    }

+

+    public void iconst(final int cst) {

+        if (cst >= -1 && cst <= 5) {

+            mv.visitInsn(Opcodes.ICONST_0 + cst);

+        } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {

+            mv.visitIntInsn(Opcodes.BIPUSH, cst);

+        } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {

+            mv.visitIntInsn(Opcodes.SIPUSH, cst);

+        } else {

+            mv.visitLdcInsn(new Integer(cst));

+        }

+    }

+

+    public void lconst(final long cst) {

+        if (cst == 0L || cst == 1L) {

+            mv.visitInsn(Opcodes.LCONST_0 + (int) cst);

+        } else {

+            mv.visitLdcInsn(new Long(cst));

+        }

+    }

+

+    public void fconst(final float cst) {

+        int bits = Float.floatToIntBits(cst);

+        if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2

+            mv.visitInsn(Opcodes.FCONST_0 + (int) cst);

+        } else {

+            mv.visitLdcInsn(new Float(cst));

+        }

+    }

+

+    public void dconst(final double cst) {

+        long bits = Double.doubleToLongBits(cst);

+        if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d

+            mv.visitInsn(Opcodes.DCONST_0 + (int) cst);

+        } else {

+            mv.visitLdcInsn(new Double(cst));

+        }

+    }

+

+    public void tconst(final Type type) {

+        mv.visitLdcInsn(type);

+    }

+

+    public void 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);

+    }

+

+    public void invokevirtual(

+        final String owner,

+        final String name,

+        final String desc)

+    {

+        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc);

+    }

+

+    public void invokespecial(

+        final String owner,

+        final String name,

+        final String desc)

+    {

+        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc);

+    }

+

+    public void invokestatic(

+        final String owner,

+        final String name,

+        final String desc)

+    {

+        mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc);

+    }

+

+    public void invokeinterface(

+        final String owner,

+        final String name,

+        final String desc)

+    {

+        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, desc);

+    }

+

+    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);

+    }

+}

diff --git a/src/org/objectweb/asm/commons/TryCatchBlockSorter.java b/src/org/objectweb/asm/commons/TryCatchBlockSorter.java
new file mode 100644
index 0000000..0c6b058
--- /dev/null
+++ b/src/org/objectweb/asm/commons/TryCatchBlockSorter.java
@@ -0,0 +1,59 @@
+package org.objectweb.asm.commons;
+
+import java.util.Collections;
+import java.util.Comparator;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.TryCatchBlockNode;
+
+/**
+ * Sorts the exception handlers in a method innermost-to-outermost. This allows
+ * the programmer to add handlers without worrying about ordering them correctly
+ * with respect to existing, in-code handlers.
+ * 
+ * Behavior is only defined for properly-nested handlers. If any "try" blocks
+ * overlap (something that isn't possible in Java code) then this may not do
+ * what you want. In fact, this adapter just sorts by the length of the "try"
+ * block, taking advantage of the fact that a given try block must be larger
+ * than any block it contains).
+ * 
+ * @author Adrian Sampson
+ */
+public class TryCatchBlockSorter extends MethodNode {
+
+    private final MethodVisitor mv;
+
+    public TryCatchBlockSorter(
+        final MethodVisitor mv,
+        final int access,
+        final String name,
+        final String desc,
+        final String signature,
+        final String[] exceptions)
+    {
+        super(access, name, desc, signature, exceptions);
+        this.mv = mv;
+    }
+
+    public void visitEnd() {
+        // Compares TryCatchBlockNodes by the length of their "try" block.
+        Comparator comp = new Comparator() {
+
+            public int compare(Object o1, Object o2) {
+                int len1 = blockLength((TryCatchBlockNode) o1);
+                int len2 = blockLength((TryCatchBlockNode) o2);
+                return len1 - len2;
+            }
+
+            private int blockLength(TryCatchBlockNode block) {
+                int startidx = instructions.indexOf(block.start);
+                int endidx = instructions.indexOf(block.end);
+                return endidx - startidx;
+            }
+        };
+        Collections.sort(tryCatchBlocks, comp);
+        if (mv != null) {
+            accept(mv);
+        }
+    }
+}