1 /* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.experimental.bytecode; 27 28 import java.lang.invoke.MethodHandle; 29 import java.lang.invoke.MethodType; 30 import java.util.Iterator; 31 import java.util.List; 32 import java.util.function.Function; 33 34 public class CodeBuilder<S, T, E, C extends CodeBuilder<S, T, E, C>> extends AttributeBuilder<S, T, E, C> { 35 36 protected GrowableByteBuffer code = new GrowableByteBuffer(); 37 GrowableByteBuffer catchers = new GrowableByteBuffer(); 38 GrowableByteBuffer stackmaps = new GrowableByteBuffer(); 39 MethodBuilder<S, T, E> methodBuilder; 40 int ncatchers; 41 int stacksize = -1; 42 int localsize = -1; 43 int nstackmaps = 0; 44 45 protected enum JumpMode { 46 NARROW, 47 WIDE; 48 } 49 50 CodeBuilder(MethodBuilder<S, T, E> methodBuilder) { 51 super(methodBuilder.poolHelper, methodBuilder.typeHelper); 52 this.methodBuilder = methodBuilder; 53 } 54 55 public C getstatic(S owner, CharSequence name, T type) { 56 emitOp(Opcode.GETSTATIC, type); 57 code.writeChar(poolHelper.putFieldRef(owner, name, type)); 58 return thisBuilder(); 59 } 60 61 public C putstatic(S owner, CharSequence name, T type) { 62 emitOp(Opcode.PUTSTATIC, type); 63 code.writeChar(poolHelper.putFieldRef(owner, name, type)); 64 return thisBuilder(); 65 } 66 67 public C getfield(S owner, CharSequence name, T type) { 68 emitOp(Opcode.GETFIELD, type); 69 code.writeChar(poolHelper.putFieldRef(owner, name, type)); 70 return thisBuilder(); 71 } 72 73 public C putfield(S owner, CharSequence name, T type) { 74 emitOp(Opcode.PUTFIELD, type); 75 code.writeChar(poolHelper.putFieldRef(owner, name, type)); 76 return thisBuilder(); 77 } 78 79 public C vwithfield(S owner, CharSequence name, T type) { 80 emitOp(Opcode.VWITHFIELD, type); 81 code.writeChar(poolHelper.putFieldRef(owner, name, type)); 82 return thisBuilder(); 83 } 84 85 public C invokevirtual(S owner, CharSequence name, T type, boolean isInterface) { 86 emitOp(Opcode.INVOKEVIRTUAL, type); 87 code.writeChar(poolHelper.putMethodRef(owner, name, type, isInterface)); 88 return thisBuilder(); 89 } 90 91 public C invokespecial(S owner, CharSequence name, T type, boolean isInterface) { 92 emitOp(Opcode.INVOKESPECIAL, type); 93 code.writeChar(poolHelper.putMethodRef(owner, name, type, isInterface)); 94 return thisBuilder(); 95 } 96 97 public C invokestatic(S owner, CharSequence name, T type, boolean isInterface) { 98 emitOp(Opcode.INVOKESTATIC, type); 99 code.writeChar(poolHelper.putMethodRef(owner, name, type, isInterface)); 100 return thisBuilder(); 101 } 102 103 public C invokeinterface(S owner, CharSequence name, T type) { 104 emitOp(Opcode.INVOKEINTERFACE, type); 105 code.writeChar(poolHelper.putMethodRef(owner, name, type, true)); 106 int nargs = 1; 107 Iterator<T> it = typeHelper.parameterTypes(type); 108 while (it.hasNext()) { 109 nargs += typeHelper.tag(it.next()).width; 110 } 111 code.writeByte(nargs); 112 code.writeByte(0); 113 return thisBuilder(); 114 } 115 116 public C invokedynamic(CharSequence invokedName, T invokedType, S bsmClass, CharSequence bsmName, T bsmType, Object... staticArgs) { 117 throw new UnsupportedOperationException("Not supported yet"); 118 } 119 120 public C new_(S clazz) { 121 emitOp(Opcode.NEW, clazz); 122 code.writeChar(poolHelper.putClass(clazz)); 123 return thisBuilder(); 124 } 125 126 public C vdefault(S target) { 127 emitOp(Opcode.VDEFAULT, target); 128 code.writeChar(poolHelper.putClass(target)); 129 return thisBuilder(); 130 } 131 132 public C newarray(TypeTag tag) { 133 emitOp(Opcode.NEWARRAY, tag); 134 int newarraycode = tag.newarraycode; 135 if (newarraycode == -1) { 136 throw new IllegalStateException("Bad tag " + tag); 137 } 138 code.writeByte(newarraycode); 139 return thisBuilder(); 140 } 141 142 public C anewarray(S array) { 143 emitOp(Opcode.ANEWARRAY, array); 144 code.writeChar(poolHelper.putClass(array)); 145 return thisBuilder(); 146 } 147 148 public C checkcast(S target) { 149 emitOp(Opcode.CHECKCAST); 150 code.writeChar(poolHelper.putClass(target)); 151 return thisBuilder(); 152 } 153 154 public C instanceof_(S target) { 155 emitOp(Opcode.INSTANCEOF); 156 code.writeChar(poolHelper.putClass(target)); 157 return thisBuilder(); 158 } 159 160 public C multianewarray(S array, byte dims) { 161 emitOp(Opcode.MULTIANEWARRAY, new Object[]{array, dims}); 162 code.writeChar(poolHelper.putClass(array)).writeByte(dims); 163 return thisBuilder(); 164 } 165 166 public C vbox(S target) { 167 emitOp(Opcode.VBOX, target); 168 code.writeChar(poolHelper.putClass(target)); 169 return thisBuilder(); 170 } 171 172 public C vunbox(S target) { 173 emitOp(Opcode.VUNBOX, target); 174 code.writeChar(poolHelper.putClass(target)); 175 return thisBuilder(); 176 } 177 178 public C ldc(Object o) { 179 emitOp(Opcode.LDC, o); 180 code.writeByte(poolHelper.putValue(o)); 181 return thisBuilder(); 182 } 183 184 public C ldc_w(Object o) { 185 emitOp(Opcode.LDC_W, o); 186 code.writeChar(poolHelper.putValue(o)); 187 return thisBuilder(); 188 } 189 190 public C ldc2_w(Object o) { 191 emitOp(Opcode.LDC2_W, o); 192 code.writeChar(poolHelper.putValue(o)); 193 return thisBuilder(); 194 } 195 196 private C ldc(Object o, boolean fat) { 197 int idx = poolHelper.putValue(o); 198 if (fat) { 199 return ldc2_w(o); 200 } else if (idx > 63) { 201 return ldc_w(o); 202 } else { 203 return ldc(o); 204 } 205 } 206 207 public C ldc(String o) { 208 return ldc(o, false); 209 } 210 211 public C ldc(Class<?> o) { 212 return ldc(o, false); 213 } 214 215 public C ldc(MethodHandle o) { 216 return ldc(o, false); 217 } 218 219 public C ldc(MethodType o) { 220 return ldc(o, false); 221 } 222 223 public C ldc(int i) { 224 return ldc(i, false); 225 } 226 227 public C ldc(float f) { 228 return ldc(f, false); 229 } 230 231 public C ldc(long l) { 232 return ldc(l, true); 233 } 234 235 public C ldc(double l) { 236 return ldc(l, true); 237 } 238 239 //other non-CP dependent opcodes 240 public C areturn() { 241 return emitOp(Opcode.ARETURN); 242 } 243 244 public C ireturn() { 245 return emitOp(Opcode.IRETURN); 246 } 247 248 public C freturn() { 249 return emitOp(Opcode.FRETURN); 250 } 251 252 public C lreturn() { 253 return emitOp(Opcode.LRETURN); 254 } 255 256 public C dreturn() { 257 return emitOp(Opcode.DRETURN); 258 } 259 260 public C return_() { 261 return emitOp(Opcode.RETURN); 262 } 263 264 public C vreturn() { 265 return emitOp(Opcode.VRETURN); 266 } 267 268 protected C emitWideIfNeeded(Opcode opcode, int n) { 269 boolean wide = n > Byte.MAX_VALUE; 270 if (wide) { 271 wide(); 272 } 273 emitOp(opcode, n); 274 if (wide) { 275 code.writeChar(n); 276 } else { 277 code.writeByte(n); 278 } 279 return thisBuilder(); 280 } 281 282 protected C emitWideIfNeeded(Opcode opcode, int n, int v) { 283 boolean wide = n > Byte.MAX_VALUE || v > Byte.MAX_VALUE; 284 if (wide) { 285 wide(); 286 } 287 emitOp(opcode, n); 288 if (wide) { 289 code.writeChar(n).writeChar(v); 290 } else { 291 code.writeByte(n).writeByte(v); 292 } 293 return thisBuilder(); 294 } 295 296 public TypedBuilder typed(TypeTag typeTag) { 297 return typed(typeTag, _unused -> new TypedBuilder()); 298 } 299 300 protected <TB extends TypedBuilder> TB typed(TypeTag typeTag, Function<TypeTag, TB> typedBuilderFunc) { 301 emitOp(Opcode.TYPED); 302 code.writeChar(poolHelper.putType(typeHelper.fromTag(typeTag))); 303 return typedBuilderFunc.apply(typeTag); 304 } 305 306 public class TypedBuilder { 307 public C aload_0() { 308 return CodeBuilder.this.aload_0(); 309 } 310 311 public C aload_1() { 312 return CodeBuilder.this.aload_1(); 313 } 314 315 public C aload_2() { 316 return CodeBuilder.this.aload_2(); 317 } 318 319 public C aload_3() { 320 return CodeBuilder.this.aload_3(); 321 } 322 323 public C aload(int n) { 324 return CodeBuilder.this.aload(n); 325 } 326 327 public C astore_0() { 328 return CodeBuilder.this.astore_0(); 329 } 330 331 public C astore_1() { 332 return CodeBuilder.this.astore_1(); 333 } 334 335 public C astore_2() { 336 return CodeBuilder.this.astore_2(); 337 } 338 339 public C astore_3() { 340 return CodeBuilder.this.astore_3(); 341 } 342 343 public C astore(int n) { 344 return CodeBuilder.this.astore(n); 345 } 346 347 public C aaload() { 348 return CodeBuilder.this.aaload(); 349 } 350 351 public C aastore() { 352 return CodeBuilder.this.aastore(); 353 } 354 355 public C areturn() { 356 return CodeBuilder.this.areturn(); 357 } 358 359 public C anewarray(S s) { 360 return CodeBuilder.this.anewarray(s); 361 } 362 363 public C aconst_null() { 364 return CodeBuilder.this.aconst_null(); 365 } 366 367 public C if_acmpeq(short target) { 368 return CodeBuilder.this.if_acmpeq(target); 369 } 370 371 public C if_acmpne(short target) { 372 return CodeBuilder.this.if_acmpeq(target); 373 } 374 } 375 376 public C vload(int i) { 377 return emitWideIfNeeded(Opcode.VLOAD, i); 378 } 379 380 public C aload(int i) { 381 return emitWideIfNeeded(Opcode.ALOAD, i); 382 } 383 384 public C iload(int i) { 385 return emitWideIfNeeded(Opcode.ILOAD, i); 386 } 387 388 public C fload(int i) { 389 return emitWideIfNeeded(Opcode.FLOAD, i); 390 } 391 392 public C lload(int i) { 393 return emitWideIfNeeded(Opcode.LLOAD, i); 394 } 395 396 public C dload(int i) { 397 return emitWideIfNeeded(Opcode.DLOAD, i); 398 } 399 400 public C aload_0() { 401 return emitOp(Opcode.ALOAD_0); 402 } 403 404 public C iload_0() { 405 return emitOp(Opcode.ILOAD_0); 406 } 407 408 public C fload_0() { 409 return emitOp(Opcode.FLOAD_0); 410 } 411 412 public C lload_0() { 413 return emitOp(Opcode.LLOAD_0); 414 } 415 416 public C dload_0() { 417 return emitOp(Opcode.DLOAD_0); 418 } 419 420 public C aload_1() { 421 return emitOp(Opcode.ALOAD_1); 422 } 423 424 public C iload_1() { 425 return emitOp(Opcode.ILOAD_1); 426 } 427 428 public C fload_1() { 429 return emitOp(Opcode.FLOAD_1); 430 } 431 432 public C lload_1() { 433 return emitOp(Opcode.LLOAD_1); 434 } 435 436 public C dload_1() { 437 return emitOp(Opcode.DLOAD_1); 438 } 439 440 public C aload_2() { 441 return emitOp(Opcode.ALOAD_2); 442 } 443 444 public C iload_2() { 445 return emitOp(Opcode.ILOAD_2); 446 } 447 448 public C fload_2() { 449 return emitOp(Opcode.FLOAD_2); 450 } 451 452 public C lload_2() { 453 return emitOp(Opcode.LLOAD_2); 454 } 455 456 public C dload_2() { 457 return emitOp(Opcode.DLOAD_2); 458 } 459 460 public C aload_3() { 461 return emitOp(Opcode.ALOAD_3); 462 } 463 464 public C iload_3() { 465 return emitOp(Opcode.ILOAD_3); 466 } 467 468 public C fload_3() { 469 return emitOp(Opcode.FLOAD_3); 470 } 471 472 public C lload_3() { 473 return emitOp(Opcode.LLOAD_3); 474 } 475 476 public C dload_3() { 477 return emitOp(Opcode.DLOAD_3); 478 } 479 480 public C vstore(int i) { 481 return emitWideIfNeeded(Opcode.VSTORE, i); 482 } 483 484 public C astore(int i) { 485 return emitWideIfNeeded(Opcode.ASTORE, i); 486 } 487 488 public C istore(int i) { 489 return emitWideIfNeeded(Opcode.ISTORE, i); 490 } 491 492 public C fstore(int i) { 493 return emitWideIfNeeded(Opcode.FSTORE, i); 494 } 495 496 public C lstore(int i) { 497 return emitWideIfNeeded(Opcode.LSTORE, i); 498 } 499 500 public C dstore(int i) { 501 return emitWideIfNeeded(Opcode.DSTORE, i); 502 } 503 504 public C astore_0() { 505 return emitOp(Opcode.ASTORE_0); 506 } 507 508 public C istore_0() { 509 return emitOp(Opcode.ISTORE_0); 510 } 511 512 public C fstore_0() { 513 return emitOp(Opcode.FSTORE_0); 514 } 515 516 public C lstore_0() { 517 return emitOp(Opcode.LSTORE_0); 518 } 519 520 public C dstore_0() { 521 return emitOp(Opcode.DSTORE_0); 522 } 523 524 public C astore_1() { 525 return emitOp(Opcode.ASTORE_1); 526 } 527 528 public C istore_1() { 529 return emitOp(Opcode.ISTORE_1); 530 } 531 532 public C fstore_1() { 533 return emitOp(Opcode.FSTORE_1); 534 } 535 536 public C lstore_1() { 537 return emitOp(Opcode.LSTORE_1); 538 } 539 540 public C dstore_1() { 541 return emitOp(Opcode.DSTORE_1); 542 } 543 544 public C astore_2() { 545 return emitOp(Opcode.ASTORE_2); 546 } 547 548 public C istore_2() { 549 return emitOp(Opcode.ISTORE_2); 550 } 551 552 public C fstore_2() { 553 return emitOp(Opcode.FSTORE_2); 554 } 555 556 public C lstore_2() { 557 return emitOp(Opcode.LSTORE_2); 558 } 559 560 public C dstore_2() { 561 return emitOp(Opcode.DSTORE_2); 562 } 563 564 public C astore_3() { 565 return emitOp(Opcode.ASTORE_3); 566 } 567 568 public C istore_3() { 569 return emitOp(Opcode.ISTORE_3); 570 } 571 572 public C fstore_3() { 573 return emitOp(Opcode.FSTORE_3); 574 } 575 576 public C lstore_3() { 577 return emitOp(Opcode.LSTORE_3); 578 } 579 580 public C dstore_3() { 581 return emitOp(Opcode.DSTORE_3); 582 } 583 584 //... 585 586 public C iaload() { 587 return emitOp(Opcode.IALOAD); 588 } 589 590 public C laload() { 591 return emitOp(Opcode.LALOAD); 592 } 593 594 public C faload() { 595 return emitOp(Opcode.FALOAD); 596 } 597 598 public C daload() { 599 return emitOp(Opcode.DALOAD); 600 } 601 602 public C vaload() { 603 return emitOp(Opcode.VALOAD); 604 } 605 606 public C aaload() { 607 return emitOp(Opcode.AALOAD); 608 } 609 610 public C baload() { 611 return emitOp(Opcode.BALOAD); 612 } 613 614 public C caload() { 615 return emitOp(Opcode.CALOAD); 616 } 617 618 public C saload() { 619 return emitOp(Opcode.SALOAD); 620 } 621 622 public C iastore() { 623 return emitOp(Opcode.IASTORE); 624 } 625 626 public C lastore() { 627 return emitOp(Opcode.LASTORE); 628 } 629 630 public C fastore() { 631 return emitOp(Opcode.FASTORE); 632 } 633 634 public C dastore() { 635 return emitOp(Opcode.DASTORE); 636 } 637 638 public C vastore() { 639 return emitOp(Opcode.VASTORE); 640 } 641 642 public C aastore() { 643 return emitOp(Opcode.AASTORE); 644 } 645 646 public C bastore() { 647 return emitOp(Opcode.BASTORE); 648 } 649 650 public C castore() { 651 return emitOp(Opcode.CASTORE); 652 } 653 654 public C sastore() { 655 return emitOp(Opcode.SASTORE); 656 } 657 658 public C nop() { 659 return emitOp(Opcode.NOP); 660 } 661 662 public C aconst_null() { 663 return emitOp(Opcode.ACONST_NULL); 664 } 665 666 public C iconst_0() { 667 return emitOp(Opcode.ICONST_0); 668 } 669 670 public C iconst_1() { 671 return emitOp(Opcode.ICONST_1); 672 } 673 674 public C iconst_2() { 675 return emitOp(Opcode.ICONST_2); 676 } 677 678 public C iconst_3() { 679 return emitOp(Opcode.ICONST_3); 680 } 681 682 public C iconst_4() { 683 return emitOp(Opcode.ICONST_4); 684 } 685 686 public C iconst_5() { 687 return emitOp(Opcode.ICONST_5); 688 } 689 690 public C iconst_m1() { 691 return emitOp(Opcode.ICONST_M1); 692 } 693 694 public C lconst_0() { 695 return emitOp(Opcode.LCONST_0); 696 } 697 698 public C lconst_1() { 699 return emitOp(Opcode.LCONST_1); 700 } 701 702 public C fconst_0() { 703 return emitOp(Opcode.FCONST_0); 704 } 705 706 public C fconst_1() { 707 return emitOp(Opcode.FCONST_1); 708 } 709 710 public C fconst_2() { 711 return emitOp(Opcode.FCONST_2); 712 } 713 714 public C dconst_0() { 715 return emitOp(Opcode.DCONST_0); 716 } 717 718 public C dconst_1() { 719 return emitOp(Opcode.DCONST_1); 720 } 721 722 public C sipush(int s) { 723 emitOp(Opcode.SIPUSH); 724 code.writeChar(s); 725 return thisBuilder(); 726 } 727 728 public C bipush(int b) { 729 emitOp(Opcode.BIPUSH); 730 code.writeByte(b); 731 return thisBuilder(); 732 } 733 734 public C pop() { 735 return emitOp(Opcode.POP); 736 } 737 738 public C pop2() { 739 return emitOp(Opcode.POP2); 740 } 741 742 public C dup() { 743 return emitOp(Opcode.DUP); 744 } 745 746 public C dup_x1() { 747 return emitOp(Opcode.DUP_X1); 748 } 749 750 public C dup_x2() { 751 return emitOp(Opcode.DUP_X2); 752 } 753 754 public C dup2() { 755 return emitOp(Opcode.DUP2); 756 } 757 758 public C dup2_x1() { 759 return emitOp(Opcode.DUP2_X1); 760 } 761 762 public C dup2_x2() { 763 return emitOp(Opcode.DUP2_X2); 764 } 765 766 public C swap() { 767 return emitOp(Opcode.SWAP); 768 } 769 770 public C iadd() { 771 return emitOp(Opcode.IADD); 772 } 773 774 public C ladd() { 775 return emitOp(Opcode.LADD); 776 } 777 778 public C fadd() { 779 return emitOp(Opcode.FADD); 780 } 781 782 public C dadd() { 783 return emitOp(Opcode.DADD); 784 } 785 786 public C isub() { 787 return emitOp(Opcode.ISUB); 788 } 789 790 public C lsub() { 791 return emitOp(Opcode.LSUB); 792 } 793 794 public C fsub() { 795 return emitOp(Opcode.FSUB); 796 } 797 798 public C dsub() { 799 return emitOp(Opcode.DSUB); 800 } 801 802 public C imul() { 803 return emitOp(Opcode.IMUL); 804 } 805 806 public C lmul() { 807 return emitOp(Opcode.LMUL); 808 } 809 810 public C fmul() { 811 return emitOp(Opcode.FMUL); 812 } 813 814 public C dmul() { 815 return emitOp(Opcode.DMUL); 816 } 817 818 public C idiv() { 819 return emitOp(Opcode.IDIV); 820 } 821 822 public C ldiv() { 823 return emitOp(Opcode.LDIV); 824 } 825 826 public C fdiv() { 827 return emitOp(Opcode.FDIV); 828 } 829 830 public C ddiv() { 831 return emitOp(Opcode.DDIV); 832 } 833 834 public C irem() { 835 return emitOp(Opcode.IREM); 836 } 837 838 public C lrem() { 839 return emitOp(Opcode.LREM); 840 } 841 842 public C frem() { 843 return emitOp(Opcode.FREM); 844 } 845 846 public C drem() { 847 return emitOp(Opcode.DREM); 848 } 849 850 public C ineg() { 851 return emitOp(Opcode.INEG); 852 } 853 854 public C lneg() { 855 return emitOp(Opcode.LNEG); 856 } 857 858 public C fneg() { 859 return emitOp(Opcode.FNEG); 860 } 861 862 public C dneg() { 863 return emitOp(Opcode.DNEG); 864 } 865 866 public C ishl() { 867 return emitOp(Opcode.ISHL); 868 } 869 870 public C lshl() { 871 return emitOp(Opcode.LSHL); 872 } 873 874 public C ishr() { 875 return emitOp(Opcode.ISHR); 876 } 877 878 public C lshr() { 879 return emitOp(Opcode.LSHR); 880 } 881 882 public C iushr() { 883 return emitOp(Opcode.IUSHR); 884 } 885 886 public C lushr() { 887 return emitOp(Opcode.LUSHR); 888 } 889 890 public C iand() { 891 return emitOp(Opcode.IAND); 892 } 893 894 public C land() { 895 return emitOp(Opcode.LAND); 896 } 897 898 public C ior() { 899 return emitOp(Opcode.IOR); 900 } 901 902 public C lor() { 903 return emitOp(Opcode.LOR); 904 } 905 906 public C ixor() { 907 return emitOp(Opcode.IXOR); 908 } 909 910 public C lxor() { 911 return emitOp(Opcode.LXOR); 912 } 913 914 public C iinc(int index, int val) { 915 return emitWideIfNeeded(Opcode.IINC, index, val); 916 } 917 918 public C i2l() { 919 return emitOp(Opcode.I2L); 920 } 921 922 public C i2f() { 923 return emitOp(Opcode.I2F); 924 } 925 926 public C i2d() { 927 return emitOp(Opcode.I2D); 928 } 929 930 public C l2i() { 931 return emitOp(Opcode.L2I); 932 } 933 934 public C l2f() { 935 return emitOp(Opcode.L2F); 936 } 937 938 public C l2d() { 939 return emitOp(Opcode.L2D); 940 } 941 942 public C f2i() { 943 return emitOp(Opcode.F2I); 944 } 945 946 public C f2l() { 947 return emitOp(Opcode.F2L); 948 } 949 950 public C f2d() { 951 return emitOp(Opcode.F2D); 952 } 953 954 public C d2i() { 955 return emitOp(Opcode.D2I); 956 } 957 958 public C d2l() { 959 return emitOp(Opcode.D2L); 960 } 961 962 public C d2f() { 963 return emitOp(Opcode.D2F); 964 } 965 966 public C i2b() { 967 return emitOp(Opcode.I2B); 968 } 969 970 public C i2c() { 971 return emitOp(Opcode.I2C); 972 } 973 974 public C i2s() { 975 return emitOp(Opcode.I2S); 976 } 977 978 public C lcmp() { 979 return emitOp(Opcode.LCMP); 980 } 981 982 public C fcmpl() { 983 return emitOp(Opcode.FCMPL); 984 } 985 986 public C fcmpg() { 987 return emitOp(Opcode.FCMPG); 988 } 989 990 public C dcmpl() { 991 return emitOp(Opcode.DCMPL); 992 } 993 994 public C dcmpg() { 995 return emitOp(Opcode.DCMPG); 996 } 997 998 public C ifeq(short target) { 999 return emitNarrowJumpOp(Opcode.IFEQ, target); 1000 } 1001 1002 public C ifne(short target) { 1003 return emitNarrowJumpOp(Opcode.IFNE, target); 1004 } 1005 1006 public C iflt(short target) { 1007 return emitNarrowJumpOp(Opcode.IFLT, target); 1008 } 1009 1010 public C ifge(short target) { 1011 return emitNarrowJumpOp(Opcode.IFGE, target); 1012 } 1013 1014 public C ifgt(short target) { 1015 return emitNarrowJumpOp(Opcode.IFGT, target); 1016 } 1017 1018 public C ifle(short target) { 1019 return emitNarrowJumpOp(Opcode.IFLE, target); 1020 } 1021 1022 public C if_icmpeq(short target) { 1023 return emitNarrowJumpOp(Opcode.IF_ICMPEQ, target); 1024 } 1025 1026 public C if_icmpne(short target) { 1027 return emitNarrowJumpOp(Opcode.IF_ICMPNE, target); 1028 } 1029 1030 public C if_icmplt(short target) { 1031 return emitNarrowJumpOp(Opcode.IF_ICMPLT, target); 1032 } 1033 1034 public C if_icmpge(short target) { 1035 return emitNarrowJumpOp(Opcode.IF_ICMPGE, target); 1036 } 1037 1038 public C if_icmpgt(short target) { 1039 return emitNarrowJumpOp(Opcode.IF_ICMPGT, target); 1040 } 1041 1042 public C if_icmple(short target) { 1043 return emitNarrowJumpOp(Opcode.IF_ICMPLE, target); 1044 } 1045 1046 public C if_acmpeq(short target) { 1047 return emitNarrowJumpOp(Opcode.IF_ACMPEQ, target); 1048 } 1049 1050 public C if_acmpne(short target) { 1051 return emitNarrowJumpOp(Opcode.IF_ACMPNE, target); 1052 } 1053 1054 public C goto_(short target) { 1055 return emitNarrowJumpOp(Opcode.GOTO_, target); 1056 } 1057 1058 public C jsr(short target) { 1059 return emitNarrowJumpOp(Opcode.JSR, target); 1060 } 1061 1062 public C ret(int index) { 1063 return emitWideIfNeeded(Opcode.RET, index); 1064 } 1065 1066 public C tableswitch(int low, int high, int defaultTarget, int... targets) { 1067 if (high - low + 1 != targets.length) throw new IllegalStateException("Bad targets length"); 1068 emitOp(Opcode.TABLESWITCH); 1069 //padding 1070 int start = code.offset; 1071 if ((start % 4) != 0) { 1072 //add padding 1073 for (int i = 0; i < 4 - (start % 4); i++) { 1074 code.writeByte(0); 1075 } 1076 } 1077 code.writeInt(defaultTarget) 1078 .writeInt(low) 1079 .writeInt(high); 1080 for (int target : targets) { 1081 code.writeInt(target); 1082 } 1083 return thisBuilder(); 1084 } 1085 1086 public C lookupswitch(int defaultTarget, int... npairs) { 1087 if (npairs.length % 2 != 0) throw new IllegalStateException("Bad npairs length"); 1088 emitOp(Opcode.LOOKUPSWITCH); 1089 //padding 1090 int start = code.offset; 1091 for (int i = 0; i < (4 - (start % 4)); i++) { 1092 code.writeByte(0); 1093 } 1094 code.writeInt(defaultTarget) 1095 .writeInt(npairs.length / 2); 1096 for (int i = 0; i < npairs.length; i += 2) { 1097 code.writeInt(npairs[i]); 1098 code.writeInt(npairs[i + 1]); 1099 } 1100 return thisBuilder(); 1101 } 1102 1103 public C invokedynamic() { 1104 throw new UnsupportedOperationException(); 1105 } //TODO: maybe later :-) 1106 1107 public C arraylength() { 1108 return emitOp(Opcode.ARRAYLENGTH); 1109 } 1110 1111 public C athrow() { 1112 return emitOp(Opcode.ATHROW); 1113 } 1114 1115 public C monitorenter() { 1116 return emitOp(Opcode.MONITORENTER); 1117 } 1118 1119 public C monitorexit() { 1120 return emitOp(Opcode.MONITOREXIT); 1121 } 1122 1123 public C wide() { 1124 return emitOp(Opcode.WIDE); 1125 } 1126 1127 public C if_null(short offset) { 1128 return emitNarrowJumpOp(Opcode.IF_NULL, offset); 1129 } 1130 1131 public C if_nonnull(short offset) { 1132 return emitNarrowJumpOp(Opcode.IF_NONNULL, offset); 1133 } 1134 1135 public C goto_w(int target) { 1136 return emitWideJumpOp(Opcode.GOTO_W, target); 1137 } 1138 1139 public C jsr_w(int target) { 1140 return emitWideJumpOp(Opcode.JSR_W, target); 1141 } 1142 1143 public C withCatch(S type, int start, int end, int offset) { 1144 catchers.writeChar(start); 1145 catchers.writeChar(end); 1146 catchers.writeChar(offset); 1147 catchers.writeChar(type != null ? poolHelper.putClass(type) : 0); 1148 ncatchers++; 1149 return thisBuilder(); 1150 } 1151 1152 public C withLocalSize(int localsize) { 1153 this.localsize = localsize; 1154 return thisBuilder(); 1155 } 1156 1157 public C withStackSize(int stacksize) { 1158 this.stacksize = stacksize; 1159 return thisBuilder(); 1160 } 1161 1162 protected int localsize() { 1163 return localsize; 1164 } 1165 1166 void build(GrowableByteBuffer buf) { 1167 buf.writeChar(stacksize); //max stack size 1168 buf.writeChar(localsize()); //max locals 1169 buf.writeInt(code.offset); 1170 buf.writeBytes(code); 1171 buf.writeChar(ncatchers); 1172 buf.writeBytes(catchers); 1173 buf.writeChar(nattrs); //attributes 1174 buf.writeBytes(attributes); 1175 } 1176 1177 byte[] build() { 1178 GrowableByteBuffer buf = new GrowableByteBuffer(); 1179 build(buf); 1180 return buf.bytes(); 1181 } 1182 1183 protected C emitNarrowJumpOp(Opcode opcode, short target) { 1184 emitOp(opcode); 1185 emitOffset(code, JumpMode.NARROW, target); 1186 return thisBuilder(); 1187 } 1188 1189 protected C emitWideJumpOp(Opcode opcode, int target) { 1190 emitOp(opcode); 1191 emitOffset(code, JumpMode.WIDE, target); 1192 return thisBuilder(); 1193 } 1194 1195 protected C emitOp(Opcode opcode) { 1196 return emitOp(opcode, null); 1197 } 1198 1199 protected C emitOp(Opcode opcode, Object optPoolValue) { 1200 code.writeByte(opcode.code); 1201 return thisBuilder(); 1202 } 1203 1204 protected void emitOffset(GrowableByteBuffer buf, JumpMode jumpMode, int offset) { 1205 if (jumpMode == JumpMode.NARROW) { 1206 buf.writeChar((short) offset); 1207 } else { 1208 buf.writeInt(offset); 1209 } 1210 } 1211 1212 int offset() { 1213 return code.offset; 1214 } 1215 1216 /*** stackmap support ***/ 1217 1218 /** 1219 * The tags and constants used in compressed stackmap. 1220 */ 1221 static final int SAME_FRAME_SIZE = 64; 1222 static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247; 1223 static final int SAME_FRAME_EXTENDED = 251; 1224 static final int FULL_FRAME = 255; 1225 static final int MAX_LOCAL_LENGTH_DIFF = 4; 1226 1227 @SuppressWarnings("unchecked") 1228 private void writeStackMapType(T t) { 1229 if (t == null) { 1230 stackmaps.writeByte(0); 1231 } else { 1232 switch (typeHelper.tag(t)) { 1233 case B: 1234 case C: 1235 case S: 1236 case I: 1237 case Z: 1238 stackmaps.writeByte(1); 1239 break; 1240 case F: 1241 stackmaps.writeByte(2); 1242 break; 1243 case D: 1244 stackmaps.writeByte(3); 1245 break; 1246 case J: 1247 stackmaps.writeByte(4); 1248 break; 1249 case Q: 1250 case A: 1251 if (t == typeHelper.nullType()) { 1252 stackmaps.writeByte(5); //null 1253 } else { 1254 //TODO: uninit this, top? 1255 stackmaps.writeByte(7); 1256 stackmaps.writeChar(poolHelper.putClass(typeHelper.symbol(t))); 1257 } 1258 break; 1259 default: 1260 throw new IllegalStateException("Bad type"); 1261 } 1262 } 1263 } 1264 1265 public void sameFrame(int offsetDelta) { 1266 int frameType = (offsetDelta < SAME_FRAME_SIZE) ? 1267 offsetDelta : SAME_FRAME_EXTENDED; 1268 stackmaps.writeByte(frameType); 1269 if (frameType == SAME_FRAME_EXTENDED) { 1270 stackmaps.writeChar(offsetDelta); 1271 } 1272 } 1273 1274 public void sameLocals1StackItemFrame(int offsetDelta, T stackItem) { 1275 int frameType = (offsetDelta < SAME_FRAME_SIZE) ? 1276 (SAME_FRAME_SIZE + offsetDelta) : SAME_LOCALS_1_STACK_ITEM_EXTENDED; 1277 stackmaps.writeByte(frameType); 1278 if (frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED) { 1279 stackmaps.writeChar(offsetDelta); 1280 } 1281 writeStackMapType(stackItem); 1282 } 1283 1284 public void appendFrame(int offsetDelta, int prevLocalsSize, List<T> locals) { 1285 int frameType = SAME_FRAME_EXTENDED + (locals.size() - prevLocalsSize); 1286 stackmaps.writeByte(frameType); 1287 stackmaps.writeChar(offsetDelta); 1288 for (int i = prevLocalsSize; i < locals.size(); i++) { 1289 writeStackMapType(locals.get(i)); 1290 } 1291 } 1292 1293 public void chopFrame(int offsetDelta, int droppedVars) { 1294 int frameType = SAME_FRAME_EXTENDED - droppedVars; 1295 stackmaps.writeByte(frameType); 1296 stackmaps.writeChar(offsetDelta); 1297 } 1298 1299 public void fullFrame(int offsetDelta, List<T> locals, List<T> stackItems) { 1300 stackmaps.writeByte(FULL_FRAME); 1301 stackmaps.writeChar(offsetDelta); 1302 stackmaps.writeChar(locals.size()); 1303 for (T local : locals) { 1304 writeStackMapType(local); 1305 } 1306 1307 stackmaps.writeChar(stackItems.size()); 1308 for (T stackType : stackItems) { 1309 writeStackMapType(stackType); 1310 } 1311 } 1312 }