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(Opcodes.ASM7, 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} or {@link Opcodes#ASM7}. 067 * @param methodVisitor the method visitor to which this adapter delegates calls. 068 */ 069 protected InstructionAdapter(final int api, final MethodVisitor methodVisitor) { 070 super(api, methodVisitor); 071 } 072 073 @Override 074 public void visitInsn(final int opcode) { 075 switch (opcode) { 076 case Opcodes.NOP: 077 nop(); 078 break; 079 case Opcodes.ACONST_NULL: 080 aconst(null); 081 break; 082 case Opcodes.ICONST_M1: 083 case Opcodes.ICONST_0: 084 case Opcodes.ICONST_1: 085 case Opcodes.ICONST_2: 086 case Opcodes.ICONST_3: 087 case Opcodes.ICONST_4: 088 case Opcodes.ICONST_5: 089 iconst(opcode - Opcodes.ICONST_0); 090 break; 091 case Opcodes.LCONST_0: 092 case Opcodes.LCONST_1: 093 lconst((long) (opcode - Opcodes.LCONST_0)); 094 break; 095 case Opcodes.FCONST_0: 096 case Opcodes.FCONST_1: 097 case Opcodes.FCONST_2: 098 fconst((float) (opcode - Opcodes.FCONST_0)); 099 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 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 427 public void visitVarInsn(final int opcode, final int var) { 428 switch (opcode) { 429 case Opcodes.ILOAD: 430 load(var, Type.INT_TYPE); 431 break; 432 case Opcodes.LLOAD: 433 load(var, Type.LONG_TYPE); 434 break; 435 case Opcodes.FLOAD: 436 load(var, Type.FLOAT_TYPE); 437 break; 438 case Opcodes.DLOAD: 439 load(var, Type.DOUBLE_TYPE); 440 break; 441 case Opcodes.ALOAD: 442 load(var, OBJECT_TYPE); 443 break; 444 case Opcodes.ISTORE: 445 store(var, Type.INT_TYPE); 446 break; 447 case Opcodes.LSTORE: 448 store(var, Type.LONG_TYPE); 449 break; 450 case Opcodes.FSTORE: 451 store(var, Type.FLOAT_TYPE); 452 break; 453 case Opcodes.DSTORE: 454 store(var, Type.DOUBLE_TYPE); 455 break; 456 case Opcodes.ASTORE: 457 store(var, OBJECT_TYPE); 458 break; 459 case Opcodes.RET: 460 ret(var); 461 break; 462 default: 463 throw new IllegalArgumentException(); 464 } 465 } 466 467 @Override 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 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 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 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 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 613 public void visitLabel(final Label label) { 614 mark(label); 615 } 616 617 @Override 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 657 public void visitIincInsn(final int var, final int increment) { 658 iinc(var, increment); 659 } 660 661 @Override 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 668 public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) { 669 lookupswitch(dflt, keys, labels); 670 } 671 672 @Override 673 public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) { 674 multianewarray(descriptor, numDimensions); 675 } 676 677 // ----------------------------------------------------------------------------------------------- 678 679 /** Generates a nop instruction. */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 783 public void cconst(final ConstantDynamic constantDynamic) { 784 mv.visitLdcInsn(constantDynamic); 785 } 786 787 public void load(final int var, final Type type) { 788 mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), var); 789 } 790 791 public void aload(final Type type) { 792 mv.visitInsn(type.getOpcode(Opcodes.IALOAD)); 793 } 794 795 public void store(final int var, final Type type) { 796 mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), var); 797 } 798 799 public void astore(final Type type) { 800 mv.visitInsn(type.getOpcode(Opcodes.IASTORE)); 801 } 802 803 public void pop() { 804 mv.visitInsn(Opcodes.POP); 805 } 806 807 public void pop2() { 808 mv.visitInsn(Opcodes.POP2); 809 } 810 811 public void dup() { 812 mv.visitInsn(Opcodes.DUP); 813 } 814 815 public void dup2() { 816 mv.visitInsn(Opcodes.DUP2); 817 } 818 819 public void dupX1() { 820 mv.visitInsn(Opcodes.DUP_X1); 821 } 822 823 public void dupX2() { 824 mv.visitInsn(Opcodes.DUP_X2); 825 } 826 827 public void dup2X1() { 828 mv.visitInsn(Opcodes.DUP2_X1); 829 } 830 831 public void dup2X2() { 832 mv.visitInsn(Opcodes.DUP2_X2); 833 } 834 835 public void swap() { 836 mv.visitInsn(Opcodes.SWAP); 837 } 838 839 public void add(final Type type) { 840 mv.visitInsn(type.getOpcode(Opcodes.IADD)); 841 } 842 843 public void sub(final Type type) { 844 mv.visitInsn(type.getOpcode(Opcodes.ISUB)); 845 } 846 847 public void mul(final Type type) { 848 mv.visitInsn(type.getOpcode(Opcodes.IMUL)); 849 } 850 851 public void div(final Type type) { 852 mv.visitInsn(type.getOpcode(Opcodes.IDIV)); 853 } 854 855 public void rem(final Type type) { 856 mv.visitInsn(type.getOpcode(Opcodes.IREM)); 857 } 858 859 public void neg(final Type type) { 860 mv.visitInsn(type.getOpcode(Opcodes.INEG)); 861 } 862 863 public void shl(final Type type) { 864 mv.visitInsn(type.getOpcode(Opcodes.ISHL)); 865 } 866 867 public void shr(final Type type) { 868 mv.visitInsn(type.getOpcode(Opcodes.ISHR)); 869 } 870 871 public void ushr(final Type type) { 872 mv.visitInsn(type.getOpcode(Opcodes.IUSHR)); 873 } 874 875 public void and(final Type type) { 876 mv.visitInsn(type.getOpcode(Opcodes.IAND)); 877 } 878 879 public void or(final Type type) { 880 mv.visitInsn(type.getOpcode(Opcodes.IOR)); 881 } 882 883 public void xor(final Type type) { 884 mv.visitInsn(type.getOpcode(Opcodes.IXOR)); 885 } 886 887 public void iinc(final int var, final int increment) { 888 mv.visitIincInsn(var, 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 */ 897 public void cast(final Type from, final Type to) { 898 if (from != to) { 899 if (from == Type.DOUBLE_TYPE) { 900 if (to == Type.FLOAT_TYPE) { 901 mv.visitInsn(Opcodes.D2F); 902 } else if (to == Type.LONG_TYPE) { 903 mv.visitInsn(Opcodes.D2L); 904 } else { 905 mv.visitInsn(Opcodes.D2I); 906 cast(Type.INT_TYPE, to); 907 } 908 } else if (from == Type.FLOAT_TYPE) { 909 if (to == Type.DOUBLE_TYPE) { 910 mv.visitInsn(Opcodes.F2D); 911 } else if (to == Type.LONG_TYPE) { 912 mv.visitInsn(Opcodes.F2L); 913 } else { 914 mv.visitInsn(Opcodes.F2I); 915 cast(Type.INT_TYPE, to); 916 } 917 } else if (from == Type.LONG_TYPE) { 918 if (to == Type.DOUBLE_TYPE) { 919 mv.visitInsn(Opcodes.L2D); 920 } else if (to == Type.FLOAT_TYPE) { 921 mv.visitInsn(Opcodes.L2F); 922 } else { 923 mv.visitInsn(Opcodes.L2I); 924 cast(Type.INT_TYPE, to); 925 } 926 } else { 927 if (to == Type.BYTE_TYPE) { 928 mv.visitInsn(Opcodes.I2B); 929 } else if (to == Type.CHAR_TYPE) { 930 mv.visitInsn(Opcodes.I2C); 931 } else if (to == Type.DOUBLE_TYPE) { 932 mv.visitInsn(Opcodes.I2D); 933 } else if (to == Type.FLOAT_TYPE) { 934 mv.visitInsn(Opcodes.I2F); 935 } else if (to == Type.LONG_TYPE) { 936 mv.visitInsn(Opcodes.I2L); 937 } else if (to == Type.SHORT_TYPE) { 938 mv.visitInsn(Opcodes.I2S); 939 } 940 } 941 } 942 } 943 944 public void lcmp() { 945 mv.visitInsn(Opcodes.LCMP); 946 } 947 948 public void cmpl(final Type type) { 949 mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPL : Opcodes.DCMPL); 950 } 951 952 public void cmpg(final Type type) { 953 mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPG : Opcodes.DCMPG); 954 } 955 956 public void ifeq(final Label label) { 957 mv.visitJumpInsn(Opcodes.IFEQ, label); 958 } 959 960 public void ifne(final Label label) { 961 mv.visitJumpInsn(Opcodes.IFNE, label); 962 } 963 964 public void iflt(final Label label) { 965 mv.visitJumpInsn(Opcodes.IFLT, label); 966 } 967 968 public void ifge(final Label label) { 969 mv.visitJumpInsn(Opcodes.IFGE, label); 970 } 971 972 public void ifgt(final Label label) { 973 mv.visitJumpInsn(Opcodes.IFGT, label); 974 } 975 976 public void ifle(final Label label) { 977 mv.visitJumpInsn(Opcodes.IFLE, label); 978 } 979 980 public void ificmpeq(final Label label) { 981 mv.visitJumpInsn(Opcodes.IF_ICMPEQ, label); 982 } 983 984 public void ificmpne(final Label label) { 985 mv.visitJumpInsn(Opcodes.IF_ICMPNE, label); 986 } 987 988 public void ificmplt(final Label label) { 989 mv.visitJumpInsn(Opcodes.IF_ICMPLT, label); 990 } 991 992 public void ificmpge(final Label label) { 993 mv.visitJumpInsn(Opcodes.IF_ICMPGE, label); 994 } 995 996 public void ificmpgt(final Label label) { 997 mv.visitJumpInsn(Opcodes.IF_ICMPGT, label); 998 } 999 1000 public void ificmple(final Label label) { 1001 mv.visitJumpInsn(Opcodes.IF_ICMPLE, label); 1002 } 1003 1004 public void ifacmpeq(final Label label) { 1005 mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label); 1006 } 1007 1008 public void ifacmpne(final Label label) { 1009 mv.visitJumpInsn(Opcodes.IF_ACMPNE, label); 1010 } 1011 1012 public void goTo(final Label label) { 1013 mv.visitJumpInsn(Opcodes.GOTO, label); 1014 } 1015 1016 public void jsr(final Label label) { 1017 mv.visitJumpInsn(Opcodes.JSR, label); 1018 } 1019 1020 public void ret(final int var) { 1021 mv.visitVarInsn(Opcodes.RET, var); 1022 } 1023 1024 public void tableswitch(final int min, final int max, final Label dflt, final Label... labels) { 1025 mv.visitTableSwitchInsn(min, max, dflt, labels); 1026 } 1027 1028 public void lookupswitch(final Label dflt, final int[] keys, final Label[] labels) { 1029 mv.visitLookupSwitchInsn(dflt, keys, labels); 1030 } 1031 1032 public void areturn(final Type type) { 1033 mv.visitInsn(type.getOpcode(Opcodes.IRETURN)); 1034 } 1035 1036 public void getstatic(final String owner, final String name, final String descriptor) { 1037 mv.visitFieldInsn(Opcodes.GETSTATIC, owner, name, descriptor); 1038 } 1039 1040 public void putstatic(final String owner, final String name, final String descriptor) { 1041 mv.visitFieldInsn(Opcodes.PUTSTATIC, owner, name, descriptor); 1042 } 1043 1044 public void getfield(final String owner, final String name, final String descriptor) { 1045 mv.visitFieldInsn(Opcodes.GETFIELD, owner, name, descriptor); 1046 } 1047 1048 public void putfield(final String owner, final String name, final String descriptor) { 1049 mv.visitFieldInsn(Opcodes.PUTFIELD, owner, name, descriptor); 1050 } 1051 1052 /** 1053 * Deprecated. 1054 * 1055 * @param owner the internal name of the method's owner class. 1056 * @param name the method's name. 1057 * @param descriptor the method's descriptor (see {@link Type}). 1058 * @deprecated use {@link #invokevirtual(String, String, String, boolean)} instead. 1059 */ 1060 @Deprecated 1061 public void invokevirtual(final String owner, final String name, final String descriptor) { 1062 if (api >= Opcodes.ASM5) { 1063 invokevirtual(owner, name, descriptor, false); 1064 return; 1065 } 1066 mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, descriptor); 1067 } 1068 1069 /** 1070 * Generates the instruction to call the given virtual method. 1071 * 1072 * @param owner the internal name of the method's owner class (see {@link 1073 * Type#getInternalName()}). 1074 * @param name the method's name. 1075 * @param descriptor the method's descriptor (see {@link Type}). 1076 * @param isInterface if the method's owner class is an interface. 1077 */ 1078 public void invokevirtual( 1079 final String owner, final String name, final String descriptor, final boolean isInterface) { 1080 if (api < Opcodes.ASM5) { 1081 if (isInterface) { 1082 throw new IllegalArgumentException("INVOKEVIRTUAL on interfaces require ASM 5"); 1083 } 1084 invokevirtual(owner, name, descriptor); 1085 return; 1086 } 1087 mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, descriptor, isInterface); 1088 } 1089 1090 /** 1091 * Deprecated. 1092 * 1093 * @param owner the internal name of the method's owner class. 1094 * @param name the method's name. 1095 * @param descriptor the method's descriptor (see {@link Type}). 1096 * @deprecated use {@link #invokespecial(String, String, String, boolean)} instead. 1097 */ 1098 @Deprecated 1099 public void invokespecial(final String owner, final String name, final String descriptor) { 1100 if (api >= Opcodes.ASM5) { 1101 invokespecial(owner, name, descriptor, false); 1102 return; 1103 } 1104 mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, descriptor, false); 1105 } 1106 1107 /** 1108 * Generates the instruction to call the given special method. 1109 * 1110 * @param owner the internal name of the method's owner class (see {@link 1111 * Type#getInternalName()}). 1112 * @param name the method's name. 1113 * @param descriptor the method's descriptor (see {@link Type}). 1114 * @param isInterface if the method's owner class is an interface. 1115 */ 1116 public void invokespecial( 1117 final String owner, final String name, final String descriptor, final boolean isInterface) { 1118 if (api < Opcodes.ASM5) { 1119 if (isInterface) { 1120 throw new IllegalArgumentException("INVOKESPECIAL on interfaces require ASM 5"); 1121 } 1122 invokespecial(owner, name, descriptor); 1123 return; 1124 } 1125 mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, descriptor, isInterface); 1126 } 1127 1128 /** 1129 * Deprecated. 1130 * 1131 * @param owner the internal name of the method's owner class. 1132 * @param name the method's name. 1133 * @param descriptor the method's descriptor (see {@link Type}). 1134 * @deprecated use {@link #invokestatic(String, String, String, boolean)} instead. 1135 */ 1136 @Deprecated 1137 public void invokestatic(final String owner, final String name, final String descriptor) { 1138 if (api >= Opcodes.ASM5) { 1139 invokestatic(owner, name, descriptor, false); 1140 return; 1141 } 1142 mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, descriptor, false); 1143 } 1144 1145 /** 1146 * Generates the instruction to call the given static method. 1147 * 1148 * @param owner the internal name of the method's owner class (see {@link 1149 * Type#getInternalName()}). 1150 * @param name the method's name. 1151 * @param descriptor the method's descriptor (see {@link Type}). 1152 * @param isInterface if the method's owner class is an interface. 1153 */ 1154 public void invokestatic( 1155 final String owner, final String name, final String descriptor, final boolean isInterface) { 1156 if (api < Opcodes.ASM5) { 1157 if (isInterface) { 1158 throw new IllegalArgumentException("INVOKESTATIC on interfaces require ASM 5"); 1159 } 1160 invokestatic(owner, name, descriptor); 1161 return; 1162 } 1163 mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, descriptor, isInterface); 1164 } 1165 1166 /** 1167 * Generates the instruction to call the given interface method. 1168 * 1169 * @param owner the internal name of the method's owner class (see {@link 1170 * Type#getInternalName()}). 1171 * @param name the method's name. 1172 * @param descriptor the method's descriptor (see {@link Type}). 1173 */ 1174 public void invokeinterface(final String owner, final String name, final String descriptor) { 1175 mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, descriptor, true); 1176 } 1177 1178 /** 1179 * Generates the instruction to call the given dynamic method. 1180 * 1181 * @param name the method's name. 1182 * @param descriptor the method's descriptor (see {@link Type}). 1183 * @param bootstrapMethodHandle the bootstrap method. 1184 * @param bootstrapMethodArguments the bootstrap method constant arguments. Each argument must be 1185 * an {@link Integer}, {@link Float}, {@link Long}, {@link Double}, {@link String}, {@link 1186 * Type}, {@link Handle} or {@link ConstantDynamic} value. This method is allowed to modify 1187 * the content of the array so a caller should expect that this array may change. 1188 */ 1189 public void invokedynamic( 1190 final String name, 1191 final String descriptor, 1192 final Handle bootstrapMethodHandle, 1193 final Object[] bootstrapMethodArguments) { 1194 mv.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments); 1195 } 1196 1197 public void anew(final Type type) { 1198 mv.visitTypeInsn(Opcodes.NEW, type.getInternalName()); 1199 } 1200 1201 /** 1202 * Generates the instruction to create and push on the stack an array of the given type. 1203 * 1204 * @param type an array Type. 1205 */ 1206 public void newarray(final Type type) { 1207 int arrayType; 1208 switch (type.getSort()) { 1209 case Type.BOOLEAN: 1210 arrayType = Opcodes.T_BOOLEAN; 1211 break; 1212 case Type.CHAR: 1213 arrayType = Opcodes.T_CHAR; 1214 break; 1215 case Type.BYTE: 1216 arrayType = Opcodes.T_BYTE; 1217 break; 1218 case Type.SHORT: 1219 arrayType = Opcodes.T_SHORT; 1220 break; 1221 case Type.INT: 1222 arrayType = Opcodes.T_INT; 1223 break; 1224 case Type.FLOAT: 1225 arrayType = Opcodes.T_FLOAT; 1226 break; 1227 case Type.LONG: 1228 arrayType = Opcodes.T_LONG; 1229 break; 1230 case Type.DOUBLE: 1231 arrayType = Opcodes.T_DOUBLE; 1232 break; 1233 default: 1234 mv.visitTypeInsn(Opcodes.ANEWARRAY, type.getInternalName()); 1235 return; 1236 } 1237 mv.visitIntInsn(Opcodes.NEWARRAY, arrayType); 1238 } 1239 1240 public void arraylength() { 1241 mv.visitInsn(Opcodes.ARRAYLENGTH); 1242 } 1243 1244 public void athrow() { 1245 mv.visitInsn(Opcodes.ATHROW); 1246 } 1247 1248 public void checkcast(final Type type) { 1249 mv.visitTypeInsn(Opcodes.CHECKCAST, type.getInternalName()); 1250 } 1251 1252 public void instanceOf(final Type type) { 1253 mv.visitTypeInsn(Opcodes.INSTANCEOF, type.getInternalName()); 1254 } 1255 1256 public void monitorenter() { 1257 mv.visitInsn(Opcodes.MONITORENTER); 1258 } 1259 1260 public void monitorexit() { 1261 mv.visitInsn(Opcodes.MONITOREXIT); 1262 } 1263 1264 public void multianewarray(final String descriptor, final int numDimensions) { 1265 mv.visitMultiANewArrayInsn(descriptor, numDimensions); 1266 } 1267 1268 public void ifnull(final Label label) { 1269 mv.visitJumpInsn(Opcodes.IFNULL, label); 1270 } 1271 1272 public void ifnonnull(final Label label) { 1273 mv.visitJumpInsn(Opcodes.IFNONNULL, label); 1274 } 1275 1276 public void mark(final Label label) { 1277 mv.visitLabel(label); 1278 } 1279}