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.Opcodes; 035import io.ebean.enhance.asm.MethodVisitor; 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 the {@code 066 * ASM}<i>x</i> values in {@link Opcodes}. 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 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 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 varIndex, final int increment) { 658 iinc(varIndex, 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 varIndex, final Type type) { 788 mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), varIndex); 789 } 790 791 public void aload(final Type type) { 792 mv.visitInsn(type.getOpcode(Opcodes.IALOAD)); 793 } 794 795 public void store(final int varIndex, final Type type) { 796 mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), varIndex); 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 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 */ 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 */ 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 955 public void lcmp() { 956 mv.visitInsn(Opcodes.LCMP); 957 } 958 959 public void cmpl(final Type type) { 960 mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPL : Opcodes.DCMPL); 961 } 962 963 public void cmpg(final Type type) { 964 mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPG : Opcodes.DCMPG); 965 } 966 967 public void ifeq(final Label label) { 968 mv.visitJumpInsn(Opcodes.IFEQ, label); 969 } 970 971 public void ifne(final Label label) { 972 mv.visitJumpInsn(Opcodes.IFNE, label); 973 } 974 975 public void iflt(final Label label) { 976 mv.visitJumpInsn(Opcodes.IFLT, label); 977 } 978 979 public void ifge(final Label label) { 980 mv.visitJumpInsn(Opcodes.IFGE, label); 981 } 982 983 public void ifgt(final Label label) { 984 mv.visitJumpInsn(Opcodes.IFGT, label); 985 } 986 987 public void ifle(final Label label) { 988 mv.visitJumpInsn(Opcodes.IFLE, label); 989 } 990 991 public void ificmpeq(final Label label) { 992 mv.visitJumpInsn(Opcodes.IF_ICMPEQ, label); 993 } 994 995 public void ificmpne(final Label label) { 996 mv.visitJumpInsn(Opcodes.IF_ICMPNE, label); 997 } 998 999 public void ificmplt(final Label label) { 1000 mv.visitJumpInsn(Opcodes.IF_ICMPLT, label); 1001 } 1002 1003 public void ificmpge(final Label label) { 1004 mv.visitJumpInsn(Opcodes.IF_ICMPGE, label); 1005 } 1006 1007 public void ificmpgt(final Label label) { 1008 mv.visitJumpInsn(Opcodes.IF_ICMPGT, label); 1009 } 1010 1011 public void ificmple(final Label label) { 1012 mv.visitJumpInsn(Opcodes.IF_ICMPLE, label); 1013 } 1014 1015 public void ifacmpeq(final Label label) { 1016 mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label); 1017 } 1018 1019 public void ifacmpne(final Label label) { 1020 mv.visitJumpInsn(Opcodes.IF_ACMPNE, label); 1021 } 1022 1023 public void goTo(final Label label) { 1024 mv.visitJumpInsn(Opcodes.GOTO, label); 1025 } 1026 1027 public void jsr(final Label label) { 1028 mv.visitJumpInsn(Opcodes.JSR, label); 1029 } 1030 1031 public void ret(final int varIndex) { 1032 mv.visitVarInsn(Opcodes.RET, varIndex); 1033 } 1034 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 1039 public void lookupswitch(final Label dflt, final int[] keys, final Label[] labels) { 1040 mv.visitLookupSwitchInsn(dflt, keys, labels); 1041 } 1042 1043 public void areturn(final Type type) { 1044 mv.visitInsn(type.getOpcode(Opcodes.IRETURN)); 1045 } 1046 1047 public void getstatic(final String owner, final String name, final String descriptor) { 1048 mv.visitFieldInsn(Opcodes.GETSTATIC, owner, name, descriptor); 1049 } 1050 1051 public void putstatic(final String owner, final String name, final String descriptor) { 1052 mv.visitFieldInsn(Opcodes.PUTSTATIC, owner, name, descriptor); 1053 } 1054 1055 public void getfield(final String owner, final String name, final String descriptor) { 1056 mv.visitFieldInsn(Opcodes.GETFIELD, owner, name, descriptor); 1057 } 1058 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. 1067 * @param name the method's name. 1068 * @param descriptor the method's descriptor (see {@link Type}). 1069 * @deprecated use {@link #invokevirtual(String, String, String, boolean)} instead. 1070 */ 1071 @Deprecated 1072 public void invokevirtual(final String owner, final String name, final String descriptor) { 1073 if (api >= Opcodes.ASM5) { 1074 invokevirtual(owner, name, descriptor, false); 1075 return; 1076 } 1077 mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, descriptor); 1078 } 1079 1080 /** 1081 * Generates the instruction to call the given virtual method. 1082 * 1083 * @param owner the internal name of the method's owner class (see {@link 1084 * Type#getInternalName()}). 1085 * @param name the method's name. 1086 * @param descriptor the method's descriptor (see {@link Type}). 1087 * @param isInterface if the method's owner class is an interface. 1088 */ 1089 public void invokevirtual( 1090 final String owner, final String name, final String descriptor, final boolean isInterface) { 1091 if (api < Opcodes.ASM5) { 1092 if (isInterface) { 1093 throw new UnsupportedOperationException("INVOKEVIRTUAL on interfaces require ASM 5"); 1094 } 1095 invokevirtual(owner, name, descriptor); 1096 return; 1097 } 1098 mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, descriptor, isInterface); 1099 } 1100 1101 /** 1102 * Deprecated. 1103 * 1104 * @param owner the internal name of the method's owner class. 1105 * @param name the method's name. 1106 * @param descriptor the method's descriptor (see {@link Type}). 1107 * @deprecated use {@link #invokespecial(String, String, String, boolean)} instead. 1108 */ 1109 @Deprecated 1110 public void invokespecial(final String owner, final String name, final String descriptor) { 1111 if (api >= Opcodes.ASM5) { 1112 invokespecial(owner, name, descriptor, false); 1113 return; 1114 } 1115 mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, descriptor, false); 1116 } 1117 1118 /** 1119 * Generates the instruction to call the given special method. 1120 * 1121 * @param owner the internal name of the method's owner class (see {@link 1122 * Type#getInternalName()}). 1123 * @param name the method's name. 1124 * @param descriptor the method's descriptor (see {@link Type}). 1125 * @param isInterface if the method's owner class is an interface. 1126 */ 1127 public void invokespecial( 1128 final String owner, final String name, final String descriptor, final boolean isInterface) { 1129 if (api < Opcodes.ASM5) { 1130 if (isInterface) { 1131 throw new UnsupportedOperationException("INVOKESPECIAL on interfaces require ASM 5"); 1132 } 1133 invokespecial(owner, name, descriptor); 1134 return; 1135 } 1136 mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, descriptor, isInterface); 1137 } 1138 1139 /** 1140 * Deprecated. 1141 * 1142 * @param owner the internal name of the method's owner class. 1143 * @param name the method's name. 1144 * @param descriptor the method's descriptor (see {@link Type}). 1145 * @deprecated use {@link #invokestatic(String, String, String, boolean)} instead. 1146 */ 1147 @Deprecated 1148 public void invokestatic(final String owner, final String name, final String descriptor) { 1149 if (api >= Opcodes.ASM5) { 1150 invokestatic(owner, name, descriptor, false); 1151 return; 1152 } 1153 mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, descriptor, false); 1154 } 1155 1156 /** 1157 * Generates the instruction to call the given static method. 1158 * 1159 * @param owner the internal name of the method's owner class (see {@link 1160 * Type#getInternalName()}). 1161 * @param name the method's name. 1162 * @param descriptor the method's descriptor (see {@link Type}). 1163 * @param isInterface if the method's owner class is an interface. 1164 */ 1165 public void invokestatic( 1166 final String owner, final String name, final String descriptor, final boolean isInterface) { 1167 if (api < Opcodes.ASM5) { 1168 if (isInterface) { 1169 throw new UnsupportedOperationException("INVOKESTATIC on interfaces require ASM 5"); 1170 } 1171 invokestatic(owner, name, descriptor); 1172 return; 1173 } 1174 mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, descriptor, isInterface); 1175 } 1176 1177 /** 1178 * Generates the instruction to call the given interface method. 1179 * 1180 * @param owner the internal name of the method's owner class (see {@link 1181 * Type#getInternalName()}). 1182 * @param name the method's name. 1183 * @param descriptor the method's descriptor (see {@link Type}). 1184 */ 1185 public void invokeinterface(final String owner, final String name, final String descriptor) { 1186 mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, descriptor, true); 1187 } 1188 1189 /** 1190 * Generates the instruction to call the given dynamic method. 1191 * 1192 * @param name the method's name. 1193 * @param descriptor the method's descriptor (see {@link Type}). 1194 * @param bootstrapMethodHandle the bootstrap method. 1195 * @param bootstrapMethodArguments the bootstrap method constant arguments. Each argument must be 1196 * an {@link Integer}, {@link Float}, {@link Long}, {@link Double}, {@link String}, {@link 1197 * Type}, {@link Handle} or {@link ConstantDynamic} value. This method is allowed to modify 1198 * the content of the array so a caller should expect that this array may change. 1199 */ 1200 public void invokedynamic( 1201 final String name, 1202 final String descriptor, 1203 final Handle bootstrapMethodHandle, 1204 final Object[] bootstrapMethodArguments) { 1205 mv.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments); 1206 } 1207 1208 public void anew(final Type type) { 1209 mv.visitTypeInsn(Opcodes.NEW, type.getInternalName()); 1210 } 1211 1212 /** 1213 * Generates the instruction to create and push on the stack an array of the given type. 1214 * 1215 * @param type an array Type. 1216 */ 1217 public void newarray(final Type type) { 1218 newarray(mv, type); 1219 } 1220 1221 /** 1222 * Generates the instruction to create and push on the stack an array of the given type. 1223 * 1224 * @param methodVisitor the method visitor to use to generate the instruction. 1225 * @param type an array Type. 1226 */ 1227 static void newarray(final MethodVisitor methodVisitor, final Type type) { 1228 int arrayType; 1229 switch (type.getSort()) { 1230 case Type.BOOLEAN: 1231 arrayType = Opcodes.T_BOOLEAN; 1232 break; 1233 case Type.CHAR: 1234 arrayType = Opcodes.T_CHAR; 1235 break; 1236 case Type.BYTE: 1237 arrayType = Opcodes.T_BYTE; 1238 break; 1239 case Type.SHORT: 1240 arrayType = Opcodes.T_SHORT; 1241 break; 1242 case Type.INT: 1243 arrayType = Opcodes.T_INT; 1244 break; 1245 case Type.FLOAT: 1246 arrayType = Opcodes.T_FLOAT; 1247 break; 1248 case Type.LONG: 1249 arrayType = Opcodes.T_LONG; 1250 break; 1251 case Type.DOUBLE: 1252 arrayType = Opcodes.T_DOUBLE; 1253 break; 1254 default: 1255 methodVisitor.visitTypeInsn(Opcodes.ANEWARRAY, type.getInternalName()); 1256 return; 1257 } 1258 methodVisitor.visitIntInsn(Opcodes.NEWARRAY, arrayType); 1259 } 1260 1261 public void arraylength() { 1262 mv.visitInsn(Opcodes.ARRAYLENGTH); 1263 } 1264 1265 public void athrow() { 1266 mv.visitInsn(Opcodes.ATHROW); 1267 } 1268 1269 public void checkcast(final Type type) { 1270 mv.visitTypeInsn(Opcodes.CHECKCAST, type.getInternalName()); 1271 } 1272 1273 public void instanceOf(final Type type) { 1274 mv.visitTypeInsn(Opcodes.INSTANCEOF, type.getInternalName()); 1275 } 1276 1277 public void monitorenter() { 1278 mv.visitInsn(Opcodes.MONITORENTER); 1279 } 1280 1281 public void monitorexit() { 1282 mv.visitInsn(Opcodes.MONITOREXIT); 1283 } 1284 1285 public void multianewarray(final String descriptor, final int numDimensions) { 1286 mv.visitMultiANewArrayInsn(descriptor, numDimensions); 1287 } 1288 1289 public void ifnull(final Label label) { 1290 mv.visitJumpInsn(Opcodes.IFNULL, label); 1291 } 1292 1293 public void ifnonnull(final Label label) { 1294 mv.visitJumpInsn(Opcodes.IFNONNULL, label); 1295 } 1296 1297 public void mark(final Label label) { 1298 mv.visitLabel(label); 1299 } 1300}