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