1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.  Oracle designates this
   7  * particular file as subject to the "Classpath" exception as provided
   8  * by Oracle in the LICENSE file that accompanied this code.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 /*
  26  * This file is available under and governed by the GNU General Public
  27  * License version 2 only, as published by the Free Software Foundation.
  28  * However, the following notice accompanied the original version of this
  29  * file:
  30  *
  31  * ASM: a very small and fast Java bytecode manipulation framework
  32  * Copyright (c) 2000-2011 INRIA, France Telecom
  33  * All rights reserved.
  34  *
  35  * Redistribution and use in source and binary forms, with or without
  36  * modification, are permitted provided that the following conditions
  37  * are met:
  38  * 1. Redistributions of source code must retain the above copyright
  39  *    notice, this list of conditions and the following disclaimer.
  40  * 2. Redistributions in binary form must reproduce the above copyright
  41  *    notice, this list of conditions and the following disclaimer in the
  42  *    documentation and/or other materials provided with the distribution.
  43  * 3. Neither the name of the copyright holders nor the names of its
  44  *    contributors may be used to endorse or promote products derived from
  45  *    this software without specific prior written permission.
  46  *
  47  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  48  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  50  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  51  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  52  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  53  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  54  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  55  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  56  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  57  * THE POSSIBILITY OF SUCH DAMAGE.
  58  */
  59 
  60 package jdk.internal.org.objectweb.asm.commons;
  61 
  62 import jdk.internal.org.objectweb.asm.Handle;
  63 import jdk.internal.org.objectweb.asm.Label;
  64 import jdk.internal.org.objectweb.asm.MethodVisitor;
  65 import jdk.internal.org.objectweb.asm.Opcodes;
  66 import jdk.internal.org.objectweb.asm.Type;
  67 
  68 /**
  69  * A {@link MethodVisitor} providing a more detailed API to generate and
  70  * transform instructions.
  71  *
  72  * @author Eric Bruneton
  73  */
  74 public class InstructionAdapter extends MethodVisitor {
  75 
  76     public static final Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;");
  77 
  78     /**
  79      * Creates a new {@link InstructionAdapter}. <i>Subclasses must not use this
  80      * constructor</i>. Instead, they must use the
  81      * {@link #InstructionAdapter(int, MethodVisitor)} version.
  82      *
  83      * @param mv
  84      *            the method visitor to which this adapter delegates calls.
  85      * @throws IllegalStateException
  86      *             If a subclass calls this constructor.
  87      */
  88     public InstructionAdapter(final MethodVisitor mv) {
  89         this(Opcodes.ASM5, mv);
  90         if (getClass() != InstructionAdapter.class) {
  91             throw new IllegalStateException();
  92         }
  93     }
  94 
  95     /**
  96      * Creates a new {@link InstructionAdapter}.
  97      *
  98      * @param api
  99      *            the ASM API version implemented by this visitor. Must be one
 100      *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
 101      * @param mv
 102      *            the method visitor to which this adapter delegates calls.
 103      */
 104     protected InstructionAdapter(final int api, final MethodVisitor mv) {
 105         super(api, mv);
 106     }
 107 
 108     @Override
 109     public void visitInsn(final int opcode) {
 110         switch (opcode) {
 111         case Opcodes.NOP:
 112             nop();
 113             break;
 114         case Opcodes.ACONST_NULL:
 115             aconst(null);
 116             break;
 117         case Opcodes.ICONST_M1:
 118         case Opcodes.ICONST_0:
 119         case Opcodes.ICONST_1:
 120         case Opcodes.ICONST_2:
 121         case Opcodes.ICONST_3:
 122         case Opcodes.ICONST_4:
 123         case Opcodes.ICONST_5:
 124             iconst(opcode - Opcodes.ICONST_0);
 125             break;
 126         case Opcodes.LCONST_0:
 127         case Opcodes.LCONST_1:
 128             lconst(opcode - Opcodes.LCONST_0);
 129             break;
 130         case Opcodes.FCONST_0:
 131         case Opcodes.FCONST_1:
 132         case Opcodes.FCONST_2:
 133             fconst(opcode - Opcodes.FCONST_0);
 134             break;
 135         case Opcodes.DCONST_0:
 136         case Opcodes.DCONST_1:
 137             dconst(opcode - Opcodes.DCONST_0);
 138             break;
 139         case Opcodes.IALOAD:
 140             aload(Type.INT_TYPE);
 141             break;
 142         case Opcodes.LALOAD:
 143             aload(Type.LONG_TYPE);
 144             break;
 145         case Opcodes.FALOAD:
 146             aload(Type.FLOAT_TYPE);
 147             break;
 148         case Opcodes.DALOAD:
 149             aload(Type.DOUBLE_TYPE);
 150             break;
 151         case Opcodes.AALOAD:
 152             aload(OBJECT_TYPE);
 153             break;
 154         case Opcodes.BALOAD:
 155             aload(Type.BYTE_TYPE);
 156             break;
 157         case Opcodes.CALOAD:
 158             aload(Type.CHAR_TYPE);
 159             break;
 160         case Opcodes.SALOAD:
 161             aload(Type.SHORT_TYPE);
 162             break;
 163         case Opcodes.IASTORE:
 164             astore(Type.INT_TYPE);
 165             break;
 166         case Opcodes.LASTORE:
 167             astore(Type.LONG_TYPE);
 168             break;
 169         case Opcodes.FASTORE:
 170             astore(Type.FLOAT_TYPE);
 171             break;
 172         case Opcodes.DASTORE:
 173             astore(Type.DOUBLE_TYPE);
 174             break;
 175         case Opcodes.AASTORE:
 176             astore(OBJECT_TYPE);
 177             break;
 178         case Opcodes.BASTORE:
 179             astore(Type.BYTE_TYPE);
 180             break;
 181         case Opcodes.CASTORE:
 182             astore(Type.CHAR_TYPE);
 183             break;
 184         case Opcodes.SASTORE:
 185             astore(Type.SHORT_TYPE);
 186             break;
 187         case Opcodes.POP:
 188             pop();
 189             break;
 190         case Opcodes.POP2:
 191             pop2();
 192             break;
 193         case Opcodes.DUP:
 194             dup();
 195             break;
 196         case Opcodes.DUP_X1:
 197             dupX1();
 198             break;
 199         case Opcodes.DUP_X2:
 200             dupX2();
 201             break;
 202         case Opcodes.DUP2:
 203             dup2();
 204             break;
 205         case Opcodes.DUP2_X1:
 206             dup2X1();
 207             break;
 208         case Opcodes.DUP2_X2:
 209             dup2X2();
 210             break;
 211         case Opcodes.SWAP:
 212             swap();
 213             break;
 214         case Opcodes.IADD:
 215             add(Type.INT_TYPE);
 216             break;
 217         case Opcodes.LADD:
 218             add(Type.LONG_TYPE);
 219             break;
 220         case Opcodes.FADD:
 221             add(Type.FLOAT_TYPE);
 222             break;
 223         case Opcodes.DADD:
 224             add(Type.DOUBLE_TYPE);
 225             break;
 226         case Opcodes.ISUB:
 227             sub(Type.INT_TYPE);
 228             break;
 229         case Opcodes.LSUB:
 230             sub(Type.LONG_TYPE);
 231             break;
 232         case Opcodes.FSUB:
 233             sub(Type.FLOAT_TYPE);
 234             break;
 235         case Opcodes.DSUB:
 236             sub(Type.DOUBLE_TYPE);
 237             break;
 238         case Opcodes.IMUL:
 239             mul(Type.INT_TYPE);
 240             break;
 241         case Opcodes.LMUL:
 242             mul(Type.LONG_TYPE);
 243             break;
 244         case Opcodes.FMUL:
 245             mul(Type.FLOAT_TYPE);
 246             break;
 247         case Opcodes.DMUL:
 248             mul(Type.DOUBLE_TYPE);
 249             break;
 250         case Opcodes.IDIV:
 251             div(Type.INT_TYPE);
 252             break;
 253         case Opcodes.LDIV:
 254             div(Type.LONG_TYPE);
 255             break;
 256         case Opcodes.FDIV:
 257             div(Type.FLOAT_TYPE);
 258             break;
 259         case Opcodes.DDIV:
 260             div(Type.DOUBLE_TYPE);
 261             break;
 262         case Opcodes.IREM:
 263             rem(Type.INT_TYPE);
 264             break;
 265         case Opcodes.LREM:
 266             rem(Type.LONG_TYPE);
 267             break;
 268         case Opcodes.FREM:
 269             rem(Type.FLOAT_TYPE);
 270             break;
 271         case Opcodes.DREM:
 272             rem(Type.DOUBLE_TYPE);
 273             break;
 274         case Opcodes.INEG:
 275             neg(Type.INT_TYPE);
 276             break;
 277         case Opcodes.LNEG:
 278             neg(Type.LONG_TYPE);
 279             break;
 280         case Opcodes.FNEG:
 281             neg(Type.FLOAT_TYPE);
 282             break;
 283         case Opcodes.DNEG:
 284             neg(Type.DOUBLE_TYPE);
 285             break;
 286         case Opcodes.ISHL:
 287             shl(Type.INT_TYPE);
 288             break;
 289         case Opcodes.LSHL:
 290             shl(Type.LONG_TYPE);
 291             break;
 292         case Opcodes.ISHR:
 293             shr(Type.INT_TYPE);
 294             break;
 295         case Opcodes.LSHR:
 296             shr(Type.LONG_TYPE);
 297             break;
 298         case Opcodes.IUSHR:
 299             ushr(Type.INT_TYPE);
 300             break;
 301         case Opcodes.LUSHR:
 302             ushr(Type.LONG_TYPE);
 303             break;
 304         case Opcodes.IAND:
 305             and(Type.INT_TYPE);
 306             break;
 307         case Opcodes.LAND:
 308             and(Type.LONG_TYPE);
 309             break;
 310         case Opcodes.IOR:
 311             or(Type.INT_TYPE);
 312             break;
 313         case Opcodes.LOR:
 314             or(Type.LONG_TYPE);
 315             break;
 316         case Opcodes.IXOR:
 317             xor(Type.INT_TYPE);
 318             break;
 319         case Opcodes.LXOR:
 320             xor(Type.LONG_TYPE);
 321             break;
 322         case Opcodes.I2L:
 323             cast(Type.INT_TYPE, Type.LONG_TYPE);
 324             break;
 325         case Opcodes.I2F:
 326             cast(Type.INT_TYPE, Type.FLOAT_TYPE);
 327             break;
 328         case Opcodes.I2D:
 329             cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
 330             break;
 331         case Opcodes.L2I:
 332             cast(Type.LONG_TYPE, Type.INT_TYPE);
 333             break;
 334         case Opcodes.L2F:
 335             cast(Type.LONG_TYPE, Type.FLOAT_TYPE);
 336             break;
 337         case Opcodes.L2D:
 338             cast(Type.LONG_TYPE, Type.DOUBLE_TYPE);
 339             break;
 340         case Opcodes.F2I:
 341             cast(Type.FLOAT_TYPE, Type.INT_TYPE);
 342             break;
 343         case Opcodes.F2L:
 344             cast(Type.FLOAT_TYPE, Type.LONG_TYPE);
 345             break;
 346         case Opcodes.F2D:
 347             cast(Type.FLOAT_TYPE, Type.DOUBLE_TYPE);
 348             break;
 349         case Opcodes.D2I:
 350             cast(Type.DOUBLE_TYPE, Type.INT_TYPE);
 351             break;
 352         case Opcodes.D2L:
 353             cast(Type.DOUBLE_TYPE, Type.LONG_TYPE);
 354             break;
 355         case Opcodes.D2F:
 356             cast(Type.DOUBLE_TYPE, Type.FLOAT_TYPE);
 357             break;
 358         case Opcodes.I2B:
 359             cast(Type.INT_TYPE, Type.BYTE_TYPE);
 360             break;
 361         case Opcodes.I2C:
 362             cast(Type.INT_TYPE, Type.CHAR_TYPE);
 363             break;
 364         case Opcodes.I2S:
 365             cast(Type.INT_TYPE, Type.SHORT_TYPE);
 366             break;
 367         case Opcodes.LCMP:
 368             lcmp();
 369             break;
 370         case Opcodes.FCMPL:
 371             cmpl(Type.FLOAT_TYPE);
 372             break;
 373         case Opcodes.FCMPG:
 374             cmpg(Type.FLOAT_TYPE);
 375             break;
 376         case Opcodes.DCMPL:
 377             cmpl(Type.DOUBLE_TYPE);
 378             break;
 379         case Opcodes.DCMPG:
 380             cmpg(Type.DOUBLE_TYPE);
 381             break;
 382         case Opcodes.IRETURN:
 383             areturn(Type.INT_TYPE);
 384             break;
 385         case Opcodes.LRETURN:
 386             areturn(Type.LONG_TYPE);
 387             break;
 388         case Opcodes.FRETURN:
 389             areturn(Type.FLOAT_TYPE);
 390             break;
 391         case Opcodes.DRETURN:
 392             areturn(Type.DOUBLE_TYPE);
 393             break;
 394         case Opcodes.ARETURN:
 395             areturn(OBJECT_TYPE);
 396             break;
 397         case Opcodes.RETURN:
 398             areturn(Type.VOID_TYPE);
 399             break;
 400         case Opcodes.ARRAYLENGTH:
 401             arraylength();
 402             break;
 403         case Opcodes.ATHROW:
 404             athrow();
 405             break;
 406         case Opcodes.MONITORENTER:
 407             monitorenter();
 408             break;
 409         case Opcodes.MONITOREXIT:
 410             monitorexit();
 411             break;
 412         default:
 413             throw new IllegalArgumentException();
 414         }
 415     }
 416 
 417     @Override
 418     public void visitIntInsn(final int opcode, final int operand) {
 419         switch (opcode) {
 420         case Opcodes.BIPUSH:
 421             iconst(operand);
 422             break;
 423         case Opcodes.SIPUSH:
 424             iconst(operand);
 425             break;
 426         case Opcodes.NEWARRAY:
 427             switch (operand) {
 428             case Opcodes.T_BOOLEAN:
 429                 newarray(Type.BOOLEAN_TYPE);
 430                 break;
 431             case Opcodes.T_CHAR:
 432                 newarray(Type.CHAR_TYPE);
 433                 break;
 434             case Opcodes.T_BYTE:
 435                 newarray(Type.BYTE_TYPE);
 436                 break;
 437             case Opcodes.T_SHORT:
 438                 newarray(Type.SHORT_TYPE);
 439                 break;
 440             case Opcodes.T_INT:
 441                 newarray(Type.INT_TYPE);
 442                 break;
 443             case Opcodes.T_FLOAT:
 444                 newarray(Type.FLOAT_TYPE);
 445                 break;
 446             case Opcodes.T_LONG:
 447                 newarray(Type.LONG_TYPE);
 448                 break;
 449             case Opcodes.T_DOUBLE:
 450                 newarray(Type.DOUBLE_TYPE);
 451                 break;
 452             default:
 453                 throw new IllegalArgumentException();
 454             }
 455             break;
 456         default:
 457             throw new IllegalArgumentException();
 458         }
 459     }
 460 
 461     @Override
 462     public void visitVarInsn(final int opcode, final int var) {
 463         switch (opcode) {
 464         case Opcodes.ILOAD:
 465             load(var, Type.INT_TYPE);
 466             break;
 467         case Opcodes.LLOAD:
 468             load(var, Type.LONG_TYPE);
 469             break;
 470         case Opcodes.FLOAD:
 471             load(var, Type.FLOAT_TYPE);
 472             break;
 473         case Opcodes.DLOAD:
 474             load(var, Type.DOUBLE_TYPE);
 475             break;
 476         case Opcodes.ALOAD:
 477             load(var, OBJECT_TYPE);
 478             break;
 479         case Opcodes.ISTORE:
 480             store(var, Type.INT_TYPE);
 481             break;
 482         case Opcodes.LSTORE:
 483             store(var, Type.LONG_TYPE);
 484             break;
 485         case Opcodes.FSTORE:
 486             store(var, Type.FLOAT_TYPE);
 487             break;
 488         case Opcodes.DSTORE:
 489             store(var, Type.DOUBLE_TYPE);
 490             break;
 491         case Opcodes.ASTORE:
 492             store(var, OBJECT_TYPE);
 493             break;
 494         case Opcodes.RET:
 495             ret(var);
 496             break;
 497         default:
 498             throw new IllegalArgumentException();
 499         }
 500     }
 501 
 502     @Override
 503     public void visitTypeInsn(final int opcode, final String type) {
 504         Type t = Type.getObjectType(type);
 505         switch (opcode) {
 506         case Opcodes.NEW:
 507             anew(t);
 508             break;
 509         case Opcodes.ANEWARRAY:
 510             newarray(t);
 511             break;
 512         case Opcodes.CHECKCAST:
 513             checkcast(t);
 514             break;
 515         case Opcodes.INSTANCEOF:
 516             instanceOf(t);
 517             break;
 518         default:
 519             throw new IllegalArgumentException();
 520         }
 521     }
 522 
 523     @Override
 524     public void visitFieldInsn(final int opcode, final String owner,
 525             final String name, final String desc) {
 526         switch (opcode) {
 527         case Opcodes.GETSTATIC:
 528             getstatic(owner, name, desc);
 529             break;
 530         case Opcodes.PUTSTATIC:
 531             putstatic(owner, name, desc);
 532             break;
 533         case Opcodes.GETFIELD:
 534             getfield(owner, name, desc);
 535             break;
 536         case Opcodes.PUTFIELD:
 537             putfield(owner, name, desc);
 538             break;
 539         default:
 540             throw new IllegalArgumentException();
 541         }
 542     }
 543 
 544     @Deprecated
 545     @Override
 546     public void visitMethodInsn(final int opcode, final String owner,
 547             final String name, final String desc) {
 548         if (api >= Opcodes.ASM5) {
 549             super.visitMethodInsn(opcode, owner, name, desc);
 550             return;
 551         }
 552         doVisitMethodInsn(opcode, owner, name, desc,
 553                 opcode == Opcodes.INVOKEINTERFACE);
 554     }
 555 
 556     @Override
 557     public void visitMethodInsn(final int opcode, final String owner,
 558             final String name, final String desc, final boolean itf) {
 559         if (api < Opcodes.ASM5) {
 560             super.visitMethodInsn(opcode, owner, name, desc, itf);
 561             return;
 562         }
 563         doVisitMethodInsn(opcode, owner, name, desc, itf);
 564     }
 565 
 566     private void doVisitMethodInsn(int opcode, final String owner,
 567             final String name, final String desc, final boolean itf) {
 568         switch (opcode) {
 569         case Opcodes.INVOKESPECIAL:
 570             invokespecial(owner, name, desc, itf);
 571             break;
 572         case Opcodes.INVOKEVIRTUAL:
 573             invokevirtual(owner, name, desc, itf);
 574             break;
 575         case Opcodes.INVOKESTATIC:
 576             invokestatic(owner, name, desc, itf);
 577             break;
 578         case Opcodes.INVOKEINTERFACE:
 579             invokeinterface(owner, name, desc);
 580             break;
 581         default:
 582             throw new IllegalArgumentException();
 583         }
 584     }
 585 
 586     @Override
 587     public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
 588             Object... bsmArgs) {
 589         invokedynamic(name, desc, bsm, bsmArgs);
 590     }
 591 
 592     @Override
 593     public void visitJumpInsn(final int opcode, final Label label) {
 594         switch (opcode) {
 595         case Opcodes.IFEQ:
 596             ifeq(label);
 597             break;
 598         case Opcodes.IFNE:
 599             ifne(label);
 600             break;
 601         case Opcodes.IFLT:
 602             iflt(label);
 603             break;
 604         case Opcodes.IFGE:
 605             ifge(label);
 606             break;
 607         case Opcodes.IFGT:
 608             ifgt(label);
 609             break;
 610         case Opcodes.IFLE:
 611             ifle(label);
 612             break;
 613         case Opcodes.IF_ICMPEQ:
 614             ificmpeq(label);
 615             break;
 616         case Opcodes.IF_ICMPNE:
 617             ificmpne(label);
 618             break;
 619         case Opcodes.IF_ICMPLT:
 620             ificmplt(label);
 621             break;
 622         case Opcodes.IF_ICMPGE:
 623             ificmpge(label);
 624             break;
 625         case Opcodes.IF_ICMPGT:
 626             ificmpgt(label);
 627             break;
 628         case Opcodes.IF_ICMPLE:
 629             ificmple(label);
 630             break;
 631         case Opcodes.IF_ACMPEQ:
 632             ifacmpeq(label);
 633             break;
 634         case Opcodes.IF_ACMPNE:
 635             ifacmpne(label);
 636             break;
 637         case Opcodes.GOTO:
 638             goTo(label);
 639             break;
 640         case Opcodes.JSR:
 641             jsr(label);
 642             break;
 643         case Opcodes.IFNULL:
 644             ifnull(label);
 645             break;
 646         case Opcodes.IFNONNULL:
 647             ifnonnull(label);
 648             break;
 649         default:
 650             throw new IllegalArgumentException();
 651         }
 652     }
 653 
 654     @Override
 655     public void visitLabel(final Label label) {
 656         mark(label);
 657     }
 658 
 659     @Override
 660     public void visitLdcInsn(final Object cst) {
 661         if (cst instanceof Integer) {
 662             int val = ((Integer) cst).intValue();
 663             iconst(val);
 664         } else if (cst instanceof Byte) {
 665             int val = ((Byte) cst).intValue();
 666             iconst(val);
 667         } else if (cst instanceof Character) {
 668             int val = ((Character) cst).charValue();
 669             iconst(val);
 670         } else if (cst instanceof Short) {
 671             int val = ((Short) cst).intValue();
 672             iconst(val);
 673         } else if (cst instanceof Boolean) {
 674             int val = ((Boolean) cst).booleanValue() ? 1 : 0;
 675             iconst(val);
 676         } else if (cst instanceof Float) {
 677             float val = ((Float) cst).floatValue();
 678             fconst(val);
 679         } else if (cst instanceof Long) {
 680             long val = ((Long) cst).longValue();
 681             lconst(val);
 682         } else if (cst instanceof Double) {
 683             double val = ((Double) cst).doubleValue();
 684             dconst(val);
 685         } else if (cst instanceof String) {
 686             aconst(cst);
 687         } else if (cst instanceof Type) {
 688             tconst((Type) cst);
 689         } else if (cst instanceof Handle) {
 690             hconst((Handle) cst);
 691         } else {
 692             throw new IllegalArgumentException();
 693         }
 694     }
 695 
 696     @Override
 697     public void visitIincInsn(final int var, final int increment) {
 698         iinc(var, increment);
 699     }
 700 
 701     @Override
 702     public void visitTableSwitchInsn(final int min, final int max,
 703             final Label dflt, final Label... labels) {
 704         tableswitch(min, max, dflt, labels);
 705     }
 706 
 707     @Override
 708     public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
 709             final Label[] labels) {
 710         lookupswitch(dflt, keys, labels);
 711     }
 712 
 713     @Override
 714     public void visitMultiANewArrayInsn(final String desc, final int dims) {
 715         multianewarray(desc, dims);
 716     }
 717 
 718     // -----------------------------------------------------------------------
 719 
 720     public void nop() {
 721         mv.visitInsn(Opcodes.NOP);
 722     }
 723 
 724     public void aconst(final Object cst) {
 725         if (cst == null) {
 726             mv.visitInsn(Opcodes.ACONST_NULL);
 727         } else {
 728             mv.visitLdcInsn(cst);
 729         }
 730     }
 731 
 732     public void iconst(final int cst) {
 733         if (cst >= -1 && cst <= 5) {
 734             mv.visitInsn(Opcodes.ICONST_0 + cst);
 735         } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {
 736             mv.visitIntInsn(Opcodes.BIPUSH, cst);
 737         } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {
 738             mv.visitIntInsn(Opcodes.SIPUSH, cst);
 739         } else {
 740             mv.visitLdcInsn(cst);
 741         }
 742     }
 743 
 744     public void lconst(final long cst) {
 745         if (cst == 0L || cst == 1L) {
 746             mv.visitInsn(Opcodes.LCONST_0 + (int) cst);
 747         } else {
 748             mv.visitLdcInsn(cst);
 749         }
 750     }
 751 
 752     public void fconst(final float cst) {
 753         int bits = Float.floatToIntBits(cst);
 754         if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2
 755             mv.visitInsn(Opcodes.FCONST_0 + (int) cst);
 756         } else {
 757             mv.visitLdcInsn(cst);
 758         }
 759     }
 760 
 761     public void dconst(final double cst) {
 762         long bits = Double.doubleToLongBits(cst);
 763         if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d
 764             mv.visitInsn(Opcodes.DCONST_0 + (int) cst);
 765         } else {
 766             mv.visitLdcInsn(cst);
 767         }
 768     }
 769 
 770     public void tconst(final Type type) {
 771         mv.visitLdcInsn(type);
 772     }
 773 
 774     public void hconst(final Handle handle) {
 775         mv.visitLdcInsn(handle);
 776     }
 777 
 778     public void load(final int var, final Type type) {
 779         mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), var);
 780     }
 781 
 782     public void aload(final Type type) {
 783         mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
 784     }
 785 
 786     public void store(final int var, final Type type) {
 787         mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), var);
 788     }
 789 
 790     public void astore(final Type type) {
 791         mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
 792     }
 793 
 794     public void pop() {
 795         mv.visitInsn(Opcodes.POP);
 796     }
 797 
 798     public void pop2() {
 799         mv.visitInsn(Opcodes.POP2);
 800     }
 801 
 802     public void dup() {
 803         mv.visitInsn(Opcodes.DUP);
 804     }
 805 
 806     public void dup2() {
 807         mv.visitInsn(Opcodes.DUP2);
 808     }
 809 
 810     public void dupX1() {
 811         mv.visitInsn(Opcodes.DUP_X1);
 812     }
 813 
 814     public void dupX2() {
 815         mv.visitInsn(Opcodes.DUP_X2);
 816     }
 817 
 818     public void dup2X1() {
 819         mv.visitInsn(Opcodes.DUP2_X1);
 820     }
 821 
 822     public void dup2X2() {
 823         mv.visitInsn(Opcodes.DUP2_X2);
 824     }
 825 
 826     public void swap() {
 827         mv.visitInsn(Opcodes.SWAP);
 828     }
 829 
 830     public void add(final Type type) {
 831         mv.visitInsn(type.getOpcode(Opcodes.IADD));
 832     }
 833 
 834     public void sub(final Type type) {
 835         mv.visitInsn(type.getOpcode(Opcodes.ISUB));
 836     }
 837 
 838     public void mul(final Type type) {
 839         mv.visitInsn(type.getOpcode(Opcodes.IMUL));
 840     }
 841 
 842     public void div(final Type type) {
 843         mv.visitInsn(type.getOpcode(Opcodes.IDIV));
 844     }
 845 
 846     public void rem(final Type type) {
 847         mv.visitInsn(type.getOpcode(Opcodes.IREM));
 848     }
 849 
 850     public void neg(final Type type) {
 851         mv.visitInsn(type.getOpcode(Opcodes.INEG));
 852     }
 853 
 854     public void shl(final Type type) {
 855         mv.visitInsn(type.getOpcode(Opcodes.ISHL));
 856     }
 857 
 858     public void shr(final Type type) {
 859         mv.visitInsn(type.getOpcode(Opcodes.ISHR));
 860     }
 861 
 862     public void ushr(final Type type) {
 863         mv.visitInsn(type.getOpcode(Opcodes.IUSHR));
 864     }
 865 
 866     public void and(final Type type) {
 867         mv.visitInsn(type.getOpcode(Opcodes.IAND));
 868     }
 869 
 870     public void or(final Type type) {
 871         mv.visitInsn(type.getOpcode(Opcodes.IOR));
 872     }
 873 
 874     public void xor(final Type type) {
 875         mv.visitInsn(type.getOpcode(Opcodes.IXOR));
 876     }
 877 
 878     public void iinc(final int var, final int increment) {
 879         mv.visitIincInsn(var, increment);
 880     }
 881 
 882     public void cast(final Type from, final Type to) {
 883         if (from != to) {
 884             if (from == Type.DOUBLE_TYPE) {
 885                 if (to == Type.FLOAT_TYPE) {
 886                     mv.visitInsn(Opcodes.D2F);
 887                 } else if (to == Type.LONG_TYPE) {
 888                     mv.visitInsn(Opcodes.D2L);
 889                 } else {
 890                     mv.visitInsn(Opcodes.D2I);
 891                     cast(Type.INT_TYPE, to);
 892                 }
 893             } else if (from == Type.FLOAT_TYPE) {
 894                 if (to == Type.DOUBLE_TYPE) {
 895                     mv.visitInsn(Opcodes.F2D);
 896                 } else if (to == Type.LONG_TYPE) {
 897                     mv.visitInsn(Opcodes.F2L);
 898                 } else {
 899                     mv.visitInsn(Opcodes.F2I);
 900                     cast(Type.INT_TYPE, to);
 901                 }
 902             } else if (from == Type.LONG_TYPE) {
 903                 if (to == Type.DOUBLE_TYPE) {
 904                     mv.visitInsn(Opcodes.L2D);
 905                 } else if (to == Type.FLOAT_TYPE) {
 906                     mv.visitInsn(Opcodes.L2F);
 907                 } else {
 908                     mv.visitInsn(Opcodes.L2I);
 909                     cast(Type.INT_TYPE, to);
 910                 }
 911             } else {
 912                 if (to == Type.BYTE_TYPE) {
 913                     mv.visitInsn(Opcodes.I2B);
 914                 } else if (to == Type.CHAR_TYPE) {
 915                     mv.visitInsn(Opcodes.I2C);
 916                 } else if (to == Type.DOUBLE_TYPE) {
 917                     mv.visitInsn(Opcodes.I2D);
 918                 } else if (to == Type.FLOAT_TYPE) {
 919                     mv.visitInsn(Opcodes.I2F);
 920                 } else if (to == Type.LONG_TYPE) {
 921                     mv.visitInsn(Opcodes.I2L);
 922                 } else if (to == Type.SHORT_TYPE) {
 923                     mv.visitInsn(Opcodes.I2S);
 924                 }
 925             }
 926         }
 927     }
 928 
 929     public void lcmp() {
 930         mv.visitInsn(Opcodes.LCMP);
 931     }
 932 
 933     public void cmpl(final Type type) {
 934         mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPL : Opcodes.DCMPL);
 935     }
 936 
 937     public void cmpg(final Type type) {
 938         mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPG : Opcodes.DCMPG);
 939     }
 940 
 941     public void ifeq(final Label label) {
 942         mv.visitJumpInsn(Opcodes.IFEQ, label);
 943     }
 944 
 945     public void ifne(final Label label) {
 946         mv.visitJumpInsn(Opcodes.IFNE, label);
 947     }
 948 
 949     public void iflt(final Label label) {
 950         mv.visitJumpInsn(Opcodes.IFLT, label);
 951     }
 952 
 953     public void ifge(final Label label) {
 954         mv.visitJumpInsn(Opcodes.IFGE, label);
 955     }
 956 
 957     public void ifgt(final Label label) {
 958         mv.visitJumpInsn(Opcodes.IFGT, label);
 959     }
 960 
 961     public void ifle(final Label label) {
 962         mv.visitJumpInsn(Opcodes.IFLE, label);
 963     }
 964 
 965     public void ificmpeq(final Label label) {
 966         mv.visitJumpInsn(Opcodes.IF_ICMPEQ, label);
 967     }
 968 
 969     public void ificmpne(final Label label) {
 970         mv.visitJumpInsn(Opcodes.IF_ICMPNE, label);
 971     }
 972 
 973     public void ificmplt(final Label label) {
 974         mv.visitJumpInsn(Opcodes.IF_ICMPLT, label);
 975     }
 976 
 977     public void ificmpge(final Label label) {
 978         mv.visitJumpInsn(Opcodes.IF_ICMPGE, label);
 979     }
 980 
 981     public void ificmpgt(final Label label) {
 982         mv.visitJumpInsn(Opcodes.IF_ICMPGT, label);
 983     }
 984 
 985     public void ificmple(final Label label) {
 986         mv.visitJumpInsn(Opcodes.IF_ICMPLE, label);
 987     }
 988 
 989     public void ifacmpeq(final Label label) {
 990         mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
 991     }
 992 
 993     public void ifacmpne(final Label label) {
 994         mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
 995     }
 996 
 997     public void goTo(final Label label) {
 998         mv.visitJumpInsn(Opcodes.GOTO, label);
 999     }
1000 
1001     public void jsr(final Label label) {
1002         mv.visitJumpInsn(Opcodes.JSR, label);
1003     }
1004 
1005     public void ret(final int var) {
1006         mv.visitVarInsn(Opcodes.RET, var);
1007     }
1008 
1009     public void tableswitch(final int min, final int max, final Label dflt,
1010             final Label... labels) {
1011         mv.visitTableSwitchInsn(min, max, dflt, labels);
1012     }
1013 
1014     public void lookupswitch(final Label dflt, final int[] keys,
1015             final Label[] labels) {
1016         mv.visitLookupSwitchInsn(dflt, keys, labels);
1017     }
1018 
1019     public void areturn(final Type t) {
1020         mv.visitInsn(t.getOpcode(Opcodes.IRETURN));
1021     }
1022 
1023     public void getstatic(final String owner, final String name,
1024             final String desc) {
1025         mv.visitFieldInsn(Opcodes.GETSTATIC, owner, name, desc);
1026     }
1027 
1028     public void putstatic(final String owner, final String name,
1029             final String desc) {
1030         mv.visitFieldInsn(Opcodes.PUTSTATIC, owner, name, desc);
1031     }
1032 
1033     public void getfield(final String owner, final String name,
1034             final String desc) {
1035         mv.visitFieldInsn(Opcodes.GETFIELD, owner, name, desc);
1036     }
1037 
1038     public void putfield(final String owner, final String name,
1039             final String desc) {
1040         mv.visitFieldInsn(Opcodes.PUTFIELD, owner, name, desc);
1041     }
1042 
1043     @Deprecated
1044     public void invokevirtual(final String owner, final String name,
1045             final String desc) {
1046         if (api >= Opcodes.ASM5) {
1047             invokevirtual(owner, name, desc, false);
1048             return;
1049         }
1050         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc);
1051     }
1052 
1053     public void invokevirtual(final String owner, final String name,
1054             final String desc, final boolean itf) {
1055         if (api < Opcodes.ASM5) {
1056             if (itf) {
1057                 throw new IllegalArgumentException(
1058                         "INVOKEVIRTUAL on interfaces require ASM 5");
1059             }
1060             invokevirtual(owner, name, desc);
1061             return;
1062         }
1063         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, itf);
1064     }
1065 
1066     @Deprecated
1067     public void invokespecial(final String owner, final String name,
1068             final String desc) {
1069         if (api >= Opcodes.ASM5) {
1070             invokespecial(owner, name, desc, false);
1071             return;
1072         }
1073         mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, false);
1074     }
1075 
1076     public void invokespecial(final String owner, final String name,
1077             final String desc, final boolean itf) {
1078         if (api < Opcodes.ASM5) {
1079             if (itf) {
1080                 throw new IllegalArgumentException(
1081                         "INVOKESPECIAL on interfaces require ASM 5");
1082             }
1083             invokespecial(owner, name, desc);
1084             return;
1085         }
1086         mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, itf);
1087     }
1088 
1089     @Deprecated
1090     public void invokestatic(final String owner, final String name,
1091             final String desc) {
1092         if (api >= Opcodes.ASM5) {
1093             invokestatic(owner, name, desc, false);
1094             return;
1095         }
1096         mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, false);
1097     }
1098 
1099     public void invokestatic(final String owner, final String name,
1100             final String desc, final boolean itf) {
1101         if (api < Opcodes.ASM5) {
1102             if (itf) {
1103                 throw new IllegalArgumentException(
1104                         "INVOKESTATIC on interfaces require ASM 5");
1105             }
1106             invokestatic(owner, name, desc);
1107             return;
1108         }
1109         mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, itf);
1110     }
1111 
1112     public void invokeinterface(final String owner, final String name,
1113             final String desc) {
1114         mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, desc, true);
1115     }
1116 
1117     public void invokedynamic(String name, String desc, Handle bsm,
1118             Object[] bsmArgs) {
1119         mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
1120     }
1121 
1122     public void anew(final Type type) {
1123         mv.visitTypeInsn(Opcodes.NEW, type.getInternalName());
1124     }
1125 
1126     public void newarray(final Type type) {
1127         int typ;
1128         switch (type.getSort()) {
1129         case Type.BOOLEAN:
1130             typ = Opcodes.T_BOOLEAN;
1131             break;
1132         case Type.CHAR:
1133             typ = Opcodes.T_CHAR;
1134             break;
1135         case Type.BYTE:
1136             typ = Opcodes.T_BYTE;
1137             break;
1138         case Type.SHORT:
1139             typ = Opcodes.T_SHORT;
1140             break;
1141         case Type.INT:
1142             typ = Opcodes.T_INT;
1143             break;
1144         case Type.FLOAT:
1145             typ = Opcodes.T_FLOAT;
1146             break;
1147         case Type.LONG:
1148             typ = Opcodes.T_LONG;
1149             break;
1150         case Type.DOUBLE:
1151             typ = Opcodes.T_DOUBLE;
1152             break;
1153         default:
1154             mv.visitTypeInsn(Opcodes.ANEWARRAY, type.getInternalName());
1155             return;
1156         }
1157         mv.visitIntInsn(Opcodes.NEWARRAY, typ);
1158     }
1159 
1160     public void arraylength() {
1161         mv.visitInsn(Opcodes.ARRAYLENGTH);
1162     }
1163 
1164     public void athrow() {
1165         mv.visitInsn(Opcodes.ATHROW);
1166     }
1167 
1168     public void checkcast(final Type type) {
1169         mv.visitTypeInsn(Opcodes.CHECKCAST, type.getInternalName());
1170     }
1171 
1172     public void instanceOf(final Type type) {
1173         mv.visitTypeInsn(Opcodes.INSTANCEOF, type.getInternalName());
1174     }
1175 
1176     public void monitorenter() {
1177         mv.visitInsn(Opcodes.MONITORENTER);
1178     }
1179 
1180     public void monitorexit() {
1181         mv.visitInsn(Opcodes.MONITOREXIT);
1182     }
1183 
1184     public void multianewarray(final String desc, final int dims) {
1185         mv.visitMultiANewArrayInsn(desc, dims);
1186     }
1187 
1188     public void ifnull(final Label label) {
1189         mv.visitJumpInsn(Opcodes.IFNULL, label);
1190     }
1191 
1192     public void ifnonnull(final Label label) {
1193         mv.visitJumpInsn(Opcodes.IFNONNULL, label);
1194     }
1195 
1196     public void mark(final Label label) {
1197         mv.visitLabel(label);
1198     }
1199 }