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