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