1 /* 2 * Copyright (c) 1999, 2018, 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 com.sun.tools.javac.jvm; 27 28 import com.sun.tools.javac.code.*; 29 import com.sun.tools.javac.code.Symbol.*; 30 import com.sun.tools.javac.code.Types.UniqueType; 31 import com.sun.tools.javac.resources.CompilerProperties.Errors; 32 import com.sun.tools.javac.tree.JCTree; 33 import com.sun.tools.javac.util.*; 34 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 35 36 import static com.sun.tools.javac.code.TypeTag.BOT; 37 import static com.sun.tools.javac.code.TypeTag.INT; 38 import static com.sun.tools.javac.jvm.ByteCodes.*; 39 import static com.sun.tools.javac.jvm.UninitializedType.*; 40 import static com.sun.tools.javac.jvm.ClassWriter.StackMapTableFrame; 41 42 /** An internal structure that corresponds to the code attribute of 43 * methods in a classfile. The class also provides some utility operations to 44 * generate bytecode instructions. 45 * 46 * <p><b>This is NOT part of any supported API. 47 * If you write code that depends on this, you do so at your own risk. 48 * This code and its internal interfaces are subject to change or 49 * deletion without notice.</b> 50 */ 51 public class Code { 52 53 public final boolean debugCode; 54 public final boolean needStackMap; 55 56 public enum StackMapFormat { 57 NONE, 58 CLDC { 59 Name getAttributeName(Names names) { 60 return names.StackMap; 61 } 62 }, 63 JSR202 { 64 Name getAttributeName(Names names) { 65 return names.StackMapTable; 66 } 67 }; 68 Name getAttributeName(Names names) { 69 return names.empty; 70 } 71 } 72 73 final Types types; 74 final Symtab syms; 75 76 /*---------- classfile fields: --------------- */ 77 78 /** The maximum stack size. 79 */ 80 public int max_stack = 0; 81 82 /** The maximum number of local variable slots. 83 */ 84 public int max_locals = 0; 85 86 /** The code buffer. 87 */ 88 public byte[] code = new byte[64]; 89 90 /** the current code pointer. 91 */ 92 public int cp = 0; 93 94 /** Check the code against VM spec limits; if 95 * problems report them and return true. 96 */ 97 public boolean checkLimits(DiagnosticPosition pos, Log log) { 98 if (cp > ClassFile.MAX_CODE) { 99 log.error(pos, Errors.LimitCode); 100 return true; 101 } 102 if (max_locals > ClassFile.MAX_LOCALS) { 103 log.error(pos, Errors.LimitLocals); 104 return true; 105 } 106 if (max_stack > ClassFile.MAX_STACK) { 107 log.error(pos, Errors.LimitStack); 108 return true; 109 } 110 return false; 111 } 112 113 /** A buffer for expression catch data. Each enter is a vector 114 * of four unsigned shorts. 115 */ 116 ListBuffer<char[]> catchInfo = new ListBuffer<>(); 117 118 /** A buffer for line number information. Each entry is a vector 119 * of two unsigned shorts. 120 */ 121 List<char[]> lineInfo = List.nil(); // handled in stack fashion 122 123 /** The CharacterRangeTable 124 */ 125 public CRTable crt; 126 127 /*---------- internal fields: --------------- */ 128 129 /** Are we generating code with jumps ≥ 32K? 130 */ 131 public boolean fatcode; 132 133 /** Code generation enabled? 134 */ 135 private boolean alive = true; 136 137 /** The current machine state (registers and stack). 138 */ 139 State state; 140 141 /** Is it forbidden to compactify code, because something is 142 * pointing to current location? 143 */ 144 private boolean fixedPc = false; 145 146 /** The next available register. 147 */ 148 public int nextreg = 0; 149 150 /** A chain for jumps to be resolved before the next opcode is emitted. 151 * We do this lazily to avoid jumps to jumps. 152 */ 153 Chain pendingJumps = null; 154 155 /** The position of the currently statement, if we are at the 156 * start of this statement, NOPOS otherwise. 157 * We need this to emit line numbers lazily, which we need to do 158 * because of jump-to-jump optimization. 159 */ 160 int pendingStatPos = Position.NOPOS; 161 162 /** Set true when a stackMap is needed at the current PC. */ 163 boolean pendingStackMap = false; 164 165 /** The stack map format to be generated. */ 166 StackMapFormat stackMap; 167 168 /** Switch: emit variable debug info. 169 */ 170 boolean varDebugInfo; 171 172 /** Switch: emit line number info. 173 */ 174 boolean lineDebugInfo; 175 176 /** Emit line number info if map supplied 177 */ 178 Position.LineMap lineMap; 179 180 /** The constant pool of the current class. 181 */ 182 final Pool pool; 183 184 final MethodSymbol meth; 185 186 /** Construct a code object, given the settings of the fatcode, 187 * debugging info switches and the CharacterRangeTable. 188 */ 189 public Code(MethodSymbol meth, 190 boolean fatcode, 191 Position.LineMap lineMap, 192 boolean varDebugInfo, 193 StackMapFormat stackMap, 194 boolean debugCode, 195 CRTable crt, 196 Symtab syms, 197 Types types, 198 Pool pool) { 199 this.meth = meth; 200 this.fatcode = fatcode; 201 this.lineMap = lineMap; 202 this.lineDebugInfo = lineMap != null; 203 this.varDebugInfo = varDebugInfo; 204 this.crt = crt; 205 this.syms = syms; 206 this.types = types; 207 this.debugCode = debugCode; 208 this.stackMap = stackMap; 209 switch (stackMap) { 210 case CLDC: 211 case JSR202: 212 this.needStackMap = true; 213 break; 214 default: 215 this.needStackMap = false; 216 } 217 state = new State(); 218 lvar = new LocalVar[20]; 219 this.pool = pool; 220 } 221 222 223 /* ************************************************************************** 224 * Typecodes & related stuff 225 ****************************************************************************/ 226 227 /** Given a type, return its type code (used implicitly in the 228 * JVM architecture). 229 */ 230 public static int typecode(Type type) { 231 switch (type.getTag()) { 232 case BYTE: return BYTEcode; 233 case SHORT: return SHORTcode; 234 case CHAR: return CHARcode; 235 case INT: return INTcode; 236 case LONG: return LONGcode; 237 case FLOAT: return FLOATcode; 238 case DOUBLE: return DOUBLEcode; 239 case BOOLEAN: return BYTEcode; 240 case VOID: return VOIDcode; 241 case CLASS: 242 case ARRAY: 243 case METHOD: 244 case BOT: 245 case TYPEVAR: 246 case UNINITIALIZED_THIS: 247 case UNINITIALIZED_OBJECT: 248 return OBJECTcode; 249 default: throw new AssertionError("typecode " + type.getTag()); 250 } 251 } 252 253 /** Collapse type code for subtypes of int to INTcode. 254 */ 255 public static int truncate(int tc) { 256 switch (tc) { 257 case BYTEcode: case SHORTcode: case CHARcode: return INTcode; 258 default: return tc; 259 } 260 } 261 262 /** The width in bytes of objects of the type. 263 */ 264 public static int width(int typecode) { 265 switch (typecode) { 266 case LONGcode: case DOUBLEcode: return 2; 267 case VOIDcode: return 0; 268 default: return 1; 269 } 270 } 271 272 public static int width(Type type) { 273 return type == null ? 1 : width(typecode(type)); 274 } 275 276 /** The total width taken up by a vector of objects. 277 */ 278 public static int width(List<Type> types) { 279 int w = 0; 280 for (List<Type> l = types; l.nonEmpty(); l = l.tail) 281 w = w + width(l.head); 282 return w; 283 } 284 285 /** Given a type, return its code for allocating arrays of that type. 286 */ 287 public static int arraycode(Type type) { 288 switch (type.getTag()) { 289 case BYTE: return 8; 290 case BOOLEAN: return 4; 291 case SHORT: return 9; 292 case CHAR: return 5; 293 case INT: return 10; 294 case LONG: return 11; 295 case FLOAT: return 6; 296 case DOUBLE: return 7; 297 case CLASS: return 0; 298 case ARRAY: return 1; 299 default: throw new AssertionError("arraycode " + type); 300 } 301 } 302 303 304 /* ************************************************************************** 305 * Emit code 306 ****************************************************************************/ 307 308 /** The current output code pointer. 309 */ 310 public int curCP() { 311 /* 312 * This method has side-effects because calling it can indirectly provoke 313 * extra code generation, like goto instructions, depending on the context 314 * where it's called. 315 * Use with care or even better avoid using it. 316 */ 317 if (pendingJumps != null) { 318 resolvePending(); 319 } 320 if (pendingStatPos != Position.NOPOS) { 321 markStatBegin(); 322 } 323 fixedPc = true; 324 return cp; 325 } 326 327 /** Emit a byte of code. 328 */ 329 private void emit1(int od) { 330 if (!alive) return; 331 code = ArrayUtils.ensureCapacity(code, cp); 332 code[cp++] = (byte)od; 333 } 334 335 /** Emit two bytes of code. 336 */ 337 private void emit2(int od) { 338 if (!alive) return; 339 if (cp + 2 > code.length) { 340 emit1(od >> 8); 341 emit1(od); 342 } else { 343 code[cp++] = (byte)(od >> 8); 344 code[cp++] = (byte)od; 345 } 346 } 347 348 /** Emit four bytes of code. 349 */ 350 public void emit4(int od) { 351 if (!alive) return; 352 if (cp + 4 > code.length) { 353 emit1(od >> 24); 354 emit1(od >> 16); 355 emit1(od >> 8); 356 emit1(od); 357 } else { 358 code[cp++] = (byte)(od >> 24); 359 code[cp++] = (byte)(od >> 16); 360 code[cp++] = (byte)(od >> 8); 361 code[cp++] = (byte)od; 362 } 363 } 364 365 /** Emit an opcode. 366 */ 367 private void emitop(int op) { 368 if (pendingJumps != null) resolvePending(); 369 if (alive) { 370 if (pendingStatPos != Position.NOPOS) 371 markStatBegin(); 372 if (pendingStackMap) { 373 pendingStackMap = false; 374 emitStackMap(); 375 } 376 if (debugCode) 377 System.err.println("emit@" + cp + " stack=" + 378 state.stacksize + ": " + 379 mnem(op)); 380 emit1(op); 381 } 382 } 383 384 void postop() { 385 Assert.check(alive || state.stacksize == 0); 386 } 387 388 /** Emit a ldc (or ldc_w) instruction, taking into account operand size 389 */ 390 public void emitLdc(int od) { 391 if (od <= 255) { 392 emitop1(ldc1, od); 393 } 394 else { 395 emitop2(ldc2, od); 396 } 397 } 398 399 /** Emit a multinewarray instruction. 400 */ 401 public void emitMultianewarray(int ndims, int type, Type arrayType) { 402 emitop(multianewarray); 403 if (!alive) return; 404 emit2(type); 405 emit1(ndims); 406 state.pop(ndims); 407 state.push(arrayType); 408 } 409 410 /** Emit newarray. 411 */ 412 public void emitNewarray(int elemcode, Type arrayType) { 413 emitop(newarray); 414 if (!alive) return; 415 emit1(elemcode); 416 state.pop(1); // count 417 state.push(arrayType); 418 } 419 420 /** Emit anewarray. 421 */ 422 public void emitAnewarray(int od, Type arrayType) { 423 emitop(anewarray); 424 if (!alive) return; 425 emit2(od); 426 state.pop(1); 427 state.push(arrayType); 428 } 429 430 /** Emit an invokeinterface instruction. 431 */ 432 public void emitInvokeinterface(int meth, Type mtype) { 433 int argsize = width(mtype.getParameterTypes()); 434 emitop(invokeinterface); 435 if (!alive) return; 436 emit2(meth); 437 emit1(argsize + 1); 438 emit1(0); 439 state.pop(argsize + 1); 440 state.push(mtype.getReturnType()); 441 } 442 443 /** Emit an invokespecial instruction. 444 */ 445 public void emitInvokespecial(int meth, Type mtype) { 446 int argsize = width(mtype.getParameterTypes()); 447 emitop(invokespecial); 448 if (!alive) return; 449 emit2(meth); 450 Symbol sym = (Symbol)pool.pool[meth]; 451 state.pop(argsize); 452 if (sym.isConstructor()) 453 state.markInitialized((UninitializedType)state.peek()); 454 state.pop(1); 455 state.push(mtype.getReturnType()); 456 } 457 458 /** Emit an invokestatic instruction. 459 */ 460 public void emitInvokestatic(int meth, Type mtype) { 461 int argsize = width(mtype.getParameterTypes()); 462 emitop(invokestatic); 463 if (!alive) return; 464 emit2(meth); 465 state.pop(argsize); 466 state.push(mtype.getReturnType()); 467 } 468 469 /** Emit an invokevirtual instruction. 470 */ 471 public void emitInvokevirtual(int meth, Type mtype) { 472 int argsize = width(mtype.getParameterTypes()); 473 emitop(invokevirtual); 474 if (!alive) return; 475 emit2(meth); 476 state.pop(argsize + 1); 477 state.push(mtype.getReturnType()); 478 } 479 480 /** Emit an invokedynamic instruction. 481 */ 482 public void emitInvokedynamic(int desc, Type mtype) { 483 int argsize = width(mtype.getParameterTypes()); 484 emitop(invokedynamic); 485 if (!alive) return; 486 emit2(desc); 487 emit2(0); 488 state.pop(argsize); 489 state.push(mtype.getReturnType()); 490 } 491 492 /** Emit an opcode with no operand field. 493 */ 494 public void emitop0(int op) { 495 emitop(op); 496 if (!alive) return; 497 switch (op) { 498 case aaload: { 499 state.pop(1);// index 500 Type a = state.stack[state.stacksize-1]; 501 Assert.check(!a.hasTag(BOT)); // null type as is cannot be indexed. 502 state.pop(1); 503 state.push(types.erasure(types.elemtype(a))); } 504 break; 505 case goto_: 506 markDead(); 507 break; 508 case nop: 509 case ineg: 510 case lneg: 511 case fneg: 512 case dneg: 513 break; 514 case aconst_null: 515 state.push(syms.botType); 516 break; 517 case iconst_m1: 518 case iconst_0: 519 case iconst_1: 520 case iconst_2: 521 case iconst_3: 522 case iconst_4: 523 case iconst_5: 524 case iload_0: 525 case iload_1: 526 case iload_2: 527 case iload_3: 528 state.push(syms.intType); 529 break; 530 case lconst_0: 531 case lconst_1: 532 case lload_0: 533 case lload_1: 534 case lload_2: 535 case lload_3: 536 state.push(syms.longType); 537 break; 538 case fconst_0: 539 case fconst_1: 540 case fconst_2: 541 case fload_0: 542 case fload_1: 543 case fload_2: 544 case fload_3: 545 state.push(syms.floatType); 546 break; 547 case dconst_0: 548 case dconst_1: 549 case dload_0: 550 case dload_1: 551 case dload_2: 552 case dload_3: 553 state.push(syms.doubleType); 554 break; 555 case aload_0: 556 state.push(lvar[0].sym.type); 557 break; 558 case aload_1: 559 state.push(lvar[1].sym.type); 560 break; 561 case aload_2: 562 state.push(lvar[2].sym.type); 563 break; 564 case aload_3: 565 state.push(lvar[3].sym.type); 566 break; 567 case iaload: 568 case baload: 569 case caload: 570 case saload: 571 state.pop(2); 572 state.push(syms.intType); 573 break; 574 case laload: 575 state.pop(2); 576 state.push(syms.longType); 577 break; 578 case faload: 579 state.pop(2); 580 state.push(syms.floatType); 581 break; 582 case daload: 583 state.pop(2); 584 state.push(syms.doubleType); 585 break; 586 case istore_0: 587 case istore_1: 588 case istore_2: 589 case istore_3: 590 case fstore_0: 591 case fstore_1: 592 case fstore_2: 593 case fstore_3: 594 case astore_0: 595 case astore_1: 596 case astore_2: 597 case astore_3: 598 case pop: 599 case lshr: 600 case lshl: 601 case lushr: 602 state.pop(1); 603 break; 604 case areturn: 605 case ireturn: 606 case freturn: 607 Assert.check(state.nlocks == 0); 608 state.pop(1); 609 markDead(); 610 break; 611 case athrow: 612 state.pop(1); 613 markDead(); 614 break; 615 case lstore_0: 616 case lstore_1: 617 case lstore_2: 618 case lstore_3: 619 case dstore_0: 620 case dstore_1: 621 case dstore_2: 622 case dstore_3: 623 case pop2: 624 state.pop(2); 625 break; 626 case lreturn: 627 case dreturn: 628 Assert.check(state.nlocks == 0); 629 state.pop(2); 630 markDead(); 631 break; 632 case dup: 633 state.push(state.stack[state.stacksize-1]); 634 break; 635 case return_: 636 Assert.check(state.nlocks == 0); 637 markDead(); 638 break; 639 case arraylength: 640 state.pop(1); 641 state.push(syms.intType); 642 break; 643 case isub: 644 case iadd: 645 case imul: 646 case idiv: 647 case imod: 648 case ishl: 649 case ishr: 650 case iushr: 651 case iand: 652 case ior: 653 case ixor: 654 state.pop(1); 655 // state.pop(1); 656 // state.push(syms.intType); 657 break; 658 case aastore: 659 state.pop(3); 660 break; 661 case land: 662 case lor: 663 case lxor: 664 case lmod: 665 case ldiv: 666 case lmul: 667 case lsub: 668 case ladd: 669 state.pop(2); 670 break; 671 case lcmp: 672 state.pop(4); 673 state.push(syms.intType); 674 break; 675 case l2i: 676 state.pop(2); 677 state.push(syms.intType); 678 break; 679 case i2l: 680 state.pop(1); 681 state.push(syms.longType); 682 break; 683 case i2f: 684 state.pop(1); 685 state.push(syms.floatType); 686 break; 687 case i2d: 688 state.pop(1); 689 state.push(syms.doubleType); 690 break; 691 case l2f: 692 state.pop(2); 693 state.push(syms.floatType); 694 break; 695 case l2d: 696 state.pop(2); 697 state.push(syms.doubleType); 698 break; 699 case f2i: 700 state.pop(1); 701 state.push(syms.intType); 702 break; 703 case f2l: 704 state.pop(1); 705 state.push(syms.longType); 706 break; 707 case f2d: 708 state.pop(1); 709 state.push(syms.doubleType); 710 break; 711 case d2i: 712 state.pop(2); 713 state.push(syms.intType); 714 break; 715 case d2l: 716 state.pop(2); 717 state.push(syms.longType); 718 break; 719 case d2f: 720 state.pop(2); 721 state.push(syms.floatType); 722 break; 723 case tableswitch: 724 case lookupswitch: 725 state.pop(1); 726 // the caller is responsible for patching up the state 727 break; 728 case dup_x1: { 729 Type val1 = state.pop1(); 730 Type val2 = state.pop1(); 731 state.push(val1); 732 state.push(val2); 733 state.push(val1); 734 break; 735 } 736 case bastore: 737 state.pop(3); 738 break; 739 case int2byte: 740 case int2char: 741 case int2short: 742 break; 743 case fmul: 744 case fadd: 745 case fsub: 746 case fdiv: 747 case fmod: 748 state.pop(1); 749 break; 750 case castore: 751 case iastore: 752 case fastore: 753 case sastore: 754 state.pop(3); 755 break; 756 case lastore: 757 case dastore: 758 state.pop(4); 759 break; 760 case dup2: 761 if (state.stack[state.stacksize-1] != null) { 762 Type value1 = state.pop1(); 763 Type value2 = state.pop1(); 764 state.push(value2); 765 state.push(value1); 766 state.push(value2); 767 state.push(value1); 768 } else { 769 Type value = state.pop2(); 770 state.push(value); 771 state.push(value); 772 } 773 break; 774 case dup2_x1: 775 if (state.stack[state.stacksize-1] != null) { 776 Type value1 = state.pop1(); 777 Type value2 = state.pop1(); 778 Type value3 = state.pop1(); 779 state.push(value2); 780 state.push(value1); 781 state.push(value3); 782 state.push(value2); 783 state.push(value1); 784 } else { 785 Type value1 = state.pop2(); 786 Type value2 = state.pop1(); 787 state.push(value1); 788 state.push(value2); 789 state.push(value1); 790 } 791 break; 792 case dup2_x2: 793 if (state.stack[state.stacksize-1] != null) { 794 Type value1 = state.pop1(); 795 Type value2 = state.pop1(); 796 if (state.stack[state.stacksize-1] != null) { 797 // form 1 798 Type value3 = state.pop1(); 799 Type value4 = state.pop1(); 800 state.push(value2); 801 state.push(value1); 802 state.push(value4); 803 state.push(value3); 804 state.push(value2); 805 state.push(value1); 806 } else { 807 // form 3 808 Type value3 = state.pop2(); 809 state.push(value2); 810 state.push(value1); 811 state.push(value3); 812 state.push(value2); 813 state.push(value1); 814 } 815 } else { 816 Type value1 = state.pop2(); 817 if (state.stack[state.stacksize-1] != null) { 818 // form 2 819 Type value2 = state.pop1(); 820 Type value3 = state.pop1(); 821 state.push(value1); 822 state.push(value3); 823 state.push(value2); 824 state.push(value1); 825 } else { 826 // form 4 827 Type value2 = state.pop2(); 828 state.push(value1); 829 state.push(value2); 830 state.push(value1); 831 } 832 } 833 break; 834 case dup_x2: { 835 Type value1 = state.pop1(); 836 if (state.stack[state.stacksize-1] != null) { 837 // form 1 838 Type value2 = state.pop1(); 839 Type value3 = state.pop1(); 840 state.push(value1); 841 state.push(value3); 842 state.push(value2); 843 state.push(value1); 844 } else { 845 // form 2 846 Type value2 = state.pop2(); 847 state.push(value1); 848 state.push(value2); 849 state.push(value1); 850 } 851 } 852 break; 853 case fcmpl: 854 case fcmpg: 855 state.pop(2); 856 state.push(syms.intType); 857 break; 858 case dcmpl: 859 case dcmpg: 860 state.pop(4); 861 state.push(syms.intType); 862 break; 863 case swap: { 864 Type value1 = state.pop1(); 865 Type value2 = state.pop1(); 866 state.push(value1); 867 state.push(value2); 868 break; 869 } 870 case dadd: 871 case dsub: 872 case dmul: 873 case ddiv: 874 case dmod: 875 state.pop(2); 876 break; 877 case ret: 878 markDead(); 879 break; 880 case wide: 881 // must be handled by the caller. 882 return; 883 case monitorenter: 884 case monitorexit: 885 state.pop(1); 886 break; 887 888 default: 889 throw new AssertionError(mnem(op)); 890 } 891 postop(); 892 } 893 894 /** Emit an opcode with a one-byte operand field. 895 */ 896 public void emitop1(int op, int od) { 897 emitop(op); 898 if (!alive) return; 899 emit1(od); 900 switch (op) { 901 case bipush: 902 state.push(syms.intType); 903 break; 904 case ldc1: 905 state.push(typeForPool(pool.pool[od])); 906 break; 907 default: 908 throw new AssertionError(mnem(op)); 909 } 910 postop(); 911 } 912 913 /** The type of a constant pool entry. */ 914 private Type typeForPool(Object o) { 915 if (o instanceof Integer) return syms.intType; 916 if (o instanceof Float) return syms.floatType; 917 if (o instanceof String) return syms.stringType; 918 if (o instanceof Long) return syms.longType; 919 if (o instanceof Double) return syms.doubleType; 920 if (o instanceof ClassSymbol) return syms.classType; 921 if (o instanceof Pool.MethodHandle) return syms.methodHandleType; 922 if (o instanceof UniqueType) return typeForPool(((UniqueType)o).type); 923 if (o instanceof Type) { 924 Type ty = (Type) o; 925 926 if (ty instanceof Type.ArrayType) return syms.classType; 927 if (ty instanceof Type.MethodType) return syms.methodTypeType; 928 } 929 throw new AssertionError("Invalid type of constant pool entry: " + o.getClass()); 930 } 931 932 /** Emit an opcode with a one-byte operand field; 933 * widen if field does not fit in a byte. 934 */ 935 public void emitop1w(int op, int od) { 936 if (od > 0xFF) { 937 emitop(wide); 938 emitop(op); 939 emit2(od); 940 } else { 941 emitop(op); 942 emit1(od); 943 } 944 if (!alive) return; 945 switch (op) { 946 case iload: 947 state.push(syms.intType); 948 break; 949 case lload: 950 state.push(syms.longType); 951 break; 952 case fload: 953 state.push(syms.floatType); 954 break; 955 case dload: 956 state.push(syms.doubleType); 957 break; 958 case aload: 959 state.push(lvar[od].sym.type); 960 break; 961 case lstore: 962 case dstore: 963 state.pop(2); 964 break; 965 case istore: 966 case fstore: 967 case astore: 968 state.pop(1); 969 break; 970 case ret: 971 markDead(); 972 break; 973 default: 974 throw new AssertionError(mnem(op)); 975 } 976 postop(); 977 } 978 979 /** Emit an opcode with two one-byte operand fields; 980 * widen if either field does not fit in a byte. 981 */ 982 public void emitop1w(int op, int od1, int od2) { 983 if (od1 > 0xFF || od2 < -128 || od2 > 127) { 984 emitop(wide); 985 emitop(op); 986 emit2(od1); 987 emit2(od2); 988 } else { 989 emitop(op); 990 emit1(od1); 991 emit1(od2); 992 } 993 if (!alive) return; 994 switch (op) { 995 case iinc: 996 break; 997 default: 998 throw new AssertionError(mnem(op)); 999 } 1000 } 1001 1002 /** Emit an opcode with a two-byte operand field. 1003 */ 1004 public void emitop2(int op, int od) { 1005 emitop(op); 1006 if (!alive) return; 1007 emit2(od); 1008 switch (op) { 1009 case getstatic: 1010 state.push(((Symbol)(pool.pool[od])).erasure(types)); 1011 break; 1012 case putstatic: 1013 state.pop(((Symbol)(pool.pool[od])).erasure(types)); 1014 break; 1015 case new_: 1016 Symbol sym; 1017 if (pool.pool[od] instanceof UniqueType) { 1018 // Required by change in Gen.makeRef to allow 1019 // annotated types. 1020 // TODO: is this needed anywhere else? 1021 sym = ((UniqueType)(pool.pool[od])).type.tsym; 1022 } else { 1023 sym = (Symbol)(pool.pool[od]); 1024 } 1025 state.push(uninitializedObject(sym.erasure(types), cp-3)); 1026 break; 1027 case sipush: 1028 state.push(syms.intType); 1029 break; 1030 case if_acmp_null: 1031 case if_acmp_nonnull: 1032 case ifeq: 1033 case ifne: 1034 case iflt: 1035 case ifge: 1036 case ifgt: 1037 case ifle: 1038 state.pop(1); 1039 break; 1040 case if_icmpeq: 1041 case if_icmpne: 1042 case if_icmplt: 1043 case if_icmpge: 1044 case if_icmpgt: 1045 case if_icmple: 1046 case if_acmpeq: 1047 case if_acmpne: 1048 state.pop(2); 1049 break; 1050 case goto_: 1051 markDead(); 1052 break; 1053 case putfield: 1054 state.pop(((Symbol)(pool.pool[od])).erasure(types)); 1055 state.pop(1); // object ref 1056 break; 1057 case getfield: 1058 state.pop(1); // object ref 1059 state.push(((Symbol)(pool.pool[od])).erasure(types)); 1060 break; 1061 case checkcast: { 1062 state.pop(1); // object ref 1063 Object o = pool.pool[od]; 1064 Type t = (o instanceof Symbol) 1065 ? ((Symbol)o).erasure(types) 1066 : types.erasure((((UniqueType)o).type)); 1067 state.push(t); 1068 break; } 1069 case ldc2w: 1070 state.push(typeForPool(pool.pool[od])); 1071 break; 1072 case instanceof_: 1073 state.pop(1); 1074 state.push(syms.intType); 1075 break; 1076 case ldc2: 1077 state.push(typeForPool(pool.pool[od])); 1078 break; 1079 case jsr: 1080 break; 1081 default: 1082 throw new AssertionError(mnem(op)); 1083 } 1084 // postop(); 1085 } 1086 1087 /** Emit an opcode with a four-byte operand field. 1088 */ 1089 public void emitop4(int op, int od) { 1090 emitop(op); 1091 if (!alive) return; 1092 emit4(od); 1093 switch (op) { 1094 case goto_w: 1095 markDead(); 1096 break; 1097 case jsr_w: 1098 break; 1099 default: 1100 throw new AssertionError(mnem(op)); 1101 } 1102 // postop(); 1103 } 1104 1105 /** Align code pointer to next `incr' boundary. 1106 */ 1107 public void align(int incr) { 1108 if (alive) 1109 while (cp % incr != 0) emitop0(nop); 1110 } 1111 1112 /** Place a byte into code at address pc. 1113 * Pre: {@literal pc + 1 <= cp }. 1114 */ 1115 private void put1(int pc, int op) { 1116 code[pc] = (byte)op; 1117 } 1118 1119 /** Place two bytes into code at address pc. 1120 * Pre: {@literal pc + 2 <= cp }. 1121 */ 1122 private void put2(int pc, int od) { 1123 // pre: pc + 2 <= cp 1124 put1(pc, od >> 8); 1125 put1(pc+1, od); 1126 } 1127 1128 /** Place four bytes into code at address pc. 1129 * Pre: {@literal pc + 4 <= cp }. 1130 */ 1131 public void put4(int pc, int od) { 1132 // pre: pc + 4 <= cp 1133 put1(pc , od >> 24); 1134 put1(pc+1, od >> 16); 1135 put1(pc+2, od >> 8); 1136 put1(pc+3, od); 1137 } 1138 1139 /** Return code byte at position pc as an unsigned int. 1140 */ 1141 private int get1(int pc) { 1142 return code[pc] & 0xFF; 1143 } 1144 1145 /** Return two code bytes at position pc as an unsigned int. 1146 */ 1147 private int get2(int pc) { 1148 return (get1(pc) << 8) | get1(pc+1); 1149 } 1150 1151 /** Return four code bytes at position pc as an int. 1152 */ 1153 public int get4(int pc) { 1154 // pre: pc + 4 <= cp 1155 return 1156 (get1(pc) << 24) | 1157 (get1(pc+1) << 16) | 1158 (get1(pc+2) << 8) | 1159 (get1(pc+3)); 1160 } 1161 1162 /** Is code generation currently enabled? 1163 */ 1164 public boolean isAlive() { 1165 return alive || pendingJumps != null; 1166 } 1167 1168 /** Switch code generation on/off. 1169 */ 1170 public void markDead() { 1171 alive = false; 1172 } 1173 1174 /** Declare an entry point; return current code pointer 1175 */ 1176 public int entryPoint() { 1177 int pc = curCP(); 1178 alive = true; 1179 pendingStackMap = needStackMap; 1180 return pc; 1181 } 1182 1183 /** Declare an entry point with initial state; 1184 * return current code pointer 1185 */ 1186 public int entryPoint(State state) { 1187 int pc = curCP(); 1188 alive = true; 1189 State newState = state.dup(); 1190 setDefined(newState.defined); 1191 this.state = newState; 1192 Assert.check(state.stacksize <= max_stack); 1193 if (debugCode) System.err.println("entry point " + state); 1194 pendingStackMap = needStackMap; 1195 return pc; 1196 } 1197 1198 /** Declare an entry point with initial state plus a pushed value; 1199 * return current code pointer 1200 */ 1201 public int entryPoint(State state, Type pushed) { 1202 int pc = curCP(); 1203 alive = true; 1204 State newState = state.dup(); 1205 setDefined(newState.defined); 1206 this.state = newState; 1207 Assert.check(state.stacksize <= max_stack); 1208 this.state.push(pushed); 1209 if (debugCode) System.err.println("entry point " + state); 1210 pendingStackMap = needStackMap; 1211 return pc; 1212 } 1213 1214 1215 /************************************************************************** 1216 * Stack map generation 1217 *************************************************************************/ 1218 1219 /** An entry in the stack map. */ 1220 static class StackMapFrame { 1221 int pc; 1222 Type[] locals; 1223 Type[] stack; 1224 } 1225 1226 /** A buffer of cldc stack map entries. */ 1227 StackMapFrame[] stackMapBuffer = null; 1228 1229 /** A buffer of compressed StackMapTable entries. */ 1230 StackMapTableFrame[] stackMapTableBuffer = null; 1231 int stackMapBufferSize = 0; 1232 1233 /** The last PC at which we generated a stack map. */ 1234 int lastStackMapPC = -1; 1235 1236 /** The last stack map frame in StackMapTable. */ 1237 StackMapFrame lastFrame = null; 1238 1239 /** The stack map frame before the last one. */ 1240 StackMapFrame frameBeforeLast = null; 1241 1242 /** Emit a stack map entry. */ 1243 public void emitStackMap() { 1244 int pc = curCP(); 1245 if (!needStackMap) return; 1246 1247 1248 1249 switch (stackMap) { 1250 case CLDC: 1251 emitCLDCStackMap(pc, getLocalsSize()); 1252 break; 1253 case JSR202: 1254 emitStackMapFrame(pc, getLocalsSize()); 1255 break; 1256 default: 1257 throw new AssertionError("Should have chosen a stackmap format"); 1258 } 1259 // DEBUG code follows 1260 if (debugCode) state.dump(pc); 1261 } 1262 1263 private int getLocalsSize() { 1264 int nextLocal = 0; 1265 for (int i=max_locals-1; i>=0; i--) { 1266 if (state.defined.isMember(i) && lvar[i] != null) { 1267 nextLocal = i + width(lvar[i].sym.erasure(types)); 1268 break; 1269 } 1270 } 1271 return nextLocal; 1272 } 1273 1274 /** Emit a CLDC stack map frame. */ 1275 void emitCLDCStackMap(int pc, int localsSize) { 1276 if (lastStackMapPC == pc) { 1277 // drop existing stackmap at this offset 1278 stackMapBuffer[--stackMapBufferSize] = null; 1279 } 1280 lastStackMapPC = pc; 1281 1282 if (stackMapBuffer == null) { 1283 stackMapBuffer = new StackMapFrame[20]; 1284 } else { 1285 stackMapBuffer = ArrayUtils.ensureCapacity(stackMapBuffer, stackMapBufferSize); 1286 } 1287 StackMapFrame frame = 1288 stackMapBuffer[stackMapBufferSize++] = new StackMapFrame(); 1289 frame.pc = pc; 1290 1291 frame.locals = new Type[localsSize]; 1292 for (int i=0; i<localsSize; i++) { 1293 if (state.defined.isMember(i) && lvar[i] != null) { 1294 Type vtype = lvar[i].sym.type; 1295 if (!(vtype instanceof UninitializedType)) 1296 vtype = types.erasure(vtype); 1297 frame.locals[i] = vtype; 1298 } 1299 } 1300 frame.stack = new Type[state.stacksize]; 1301 for (int i=0; i<state.stacksize; i++) 1302 frame.stack[i] = state.stack[i]; 1303 } 1304 1305 void emitStackMapFrame(int pc, int localsSize) { 1306 if (lastFrame == null) { 1307 // first frame 1308 lastFrame = getInitialFrame(); 1309 } else if (lastFrame.pc == pc) { 1310 // drop existing stackmap at this offset 1311 stackMapTableBuffer[--stackMapBufferSize] = null; 1312 lastFrame = frameBeforeLast; 1313 frameBeforeLast = null; 1314 } 1315 1316 StackMapFrame frame = new StackMapFrame(); 1317 frame.pc = pc; 1318 1319 int localCount = 0; 1320 Type[] locals = new Type[localsSize]; 1321 for (int i=0; i<localsSize; i++, localCount++) { 1322 if (state.defined.isMember(i) && lvar[i] != null) { 1323 Type vtype = lvar[i].sym.type; 1324 if (!(vtype instanceof UninitializedType)) 1325 vtype = types.erasure(vtype); 1326 locals[i] = vtype; 1327 if (width(vtype) > 1) i++; 1328 } 1329 } 1330 frame.locals = new Type[localCount]; 1331 for (int i=0, j=0; i<localsSize; i++, j++) { 1332 Assert.check(j < localCount); 1333 frame.locals[j] = locals[i]; 1334 if (width(locals[i]) > 1) i++; 1335 } 1336 1337 int stackCount = 0; 1338 for (int i=0; i<state.stacksize; i++) { 1339 if (state.stack[i] != null) { 1340 stackCount++; 1341 } 1342 } 1343 frame.stack = new Type[stackCount]; 1344 stackCount = 0; 1345 for (int i=0; i<state.stacksize; i++) { 1346 if (state.stack[i] != null) { 1347 frame.stack[stackCount++] = types.erasure(state.stack[i]); 1348 } 1349 } 1350 1351 if (stackMapTableBuffer == null) { 1352 stackMapTableBuffer = new StackMapTableFrame[20]; 1353 } else { 1354 stackMapTableBuffer = ArrayUtils.ensureCapacity( 1355 stackMapTableBuffer, 1356 stackMapBufferSize); 1357 } 1358 stackMapTableBuffer[stackMapBufferSize++] = 1359 StackMapTableFrame.getInstance(frame, lastFrame.pc, lastFrame.locals, types); 1360 1361 frameBeforeLast = lastFrame; 1362 lastFrame = frame; 1363 } 1364 1365 StackMapFrame getInitialFrame() { 1366 StackMapFrame frame = new StackMapFrame(); 1367 List<Type> arg_types = ((MethodType)meth.externalType(types)).argtypes; 1368 int len = arg_types.length(); 1369 int count = 0; 1370 if (!meth.isStatic()) { 1371 Type thisType = meth.owner.type; 1372 frame.locals = new Type[len+1]; 1373 if (meth.isConstructor() && thisType != syms.objectType) { 1374 frame.locals[count++] = UninitializedType.uninitializedThis(thisType); 1375 } else { 1376 frame.locals[count++] = types.erasure(thisType); 1377 } 1378 } else { 1379 frame.locals = new Type[len]; 1380 } 1381 for (Type arg_type : arg_types) { 1382 frame.locals[count++] = types.erasure(arg_type); 1383 } 1384 frame.pc = -1; 1385 frame.stack = null; 1386 return frame; 1387 } 1388 1389 1390 /************************************************************************** 1391 * Operations having to do with jumps 1392 *************************************************************************/ 1393 1394 /** A chain represents a list of unresolved jumps. Jump locations 1395 * are sorted in decreasing order. 1396 */ 1397 public static class Chain { 1398 1399 /** The position of the jump instruction. 1400 */ 1401 public final int pc; 1402 1403 /** The machine state after the jump instruction. 1404 * Invariant: all elements of a chain list have the same stacksize 1405 * and compatible stack and register contents. 1406 */ 1407 Code.State state; 1408 1409 /** The next jump in the list. 1410 */ 1411 public final Chain next; 1412 1413 /** Construct a chain from its jump position, stacksize, previous 1414 * chain, and machine state. 1415 */ 1416 public Chain(int pc, Chain next, Code.State state) { 1417 this.pc = pc; 1418 this.next = next; 1419 this.state = state; 1420 } 1421 } 1422 1423 /** Negate a branch opcode. 1424 */ 1425 public static int negate(int opcode) { 1426 if (opcode == if_acmp_null) return if_acmp_nonnull; 1427 else if (opcode == if_acmp_nonnull) return if_acmp_null; 1428 else return ((opcode + 1) ^ 1) - 1; 1429 } 1430 1431 /** Emit a jump instruction. 1432 * Return code pointer of instruction to be patched. 1433 */ 1434 public int emitJump(int opcode) { 1435 if (fatcode) { 1436 if (opcode == goto_ || opcode == jsr) { 1437 emitop4(opcode + goto_w - goto_, 0); 1438 } else { 1439 emitop2(negate(opcode), 8); 1440 emitop4(goto_w, 0); 1441 alive = true; 1442 pendingStackMap = needStackMap; 1443 } 1444 return cp - 5; 1445 } else { 1446 emitop2(opcode, 0); 1447 return cp - 3; 1448 } 1449 } 1450 1451 /** Emit a branch with given opcode; return its chain. 1452 * branch differs from jump in that jsr is treated as no-op. 1453 */ 1454 public Chain branch(int opcode) { 1455 Chain result = null; 1456 if (opcode == goto_) { 1457 result = pendingJumps; 1458 pendingJumps = null; 1459 } 1460 if (opcode != dontgoto && isAlive()) { 1461 result = new Chain(emitJump(opcode), 1462 result, 1463 state.dup()); 1464 fixedPc = fatcode; 1465 if (opcode == goto_) alive = false; 1466 } 1467 return result; 1468 } 1469 1470 /** Resolve chain to point to given target. 1471 */ 1472 public void resolve(Chain chain, int target) { 1473 boolean changed = false; 1474 State newState = state; 1475 for (; chain != null; chain = chain.next) { 1476 Assert.check(state != chain.state 1477 && (target > chain.pc || state.stacksize == 0)); 1478 if (target >= cp) { 1479 target = cp; 1480 } else if (get1(target) == goto_) { 1481 if (fatcode) target = target + get4(target + 1); 1482 else target = target + get2(target + 1); 1483 } 1484 if (get1(chain.pc) == goto_ && 1485 chain.pc + 3 == target && target == cp && !fixedPc) { 1486 // If goto the next instruction, the jump is not needed: 1487 // compact the code. 1488 if (varDebugInfo) { 1489 adjustAliveRanges(cp, -3); 1490 } 1491 cp = cp - 3; 1492 target = target - 3; 1493 if (chain.next == null) { 1494 // This is the only jump to the target. Exit the loop 1495 // without setting new state. The code is reachable 1496 // from the instruction before goto_. 1497 alive = true; 1498 break; 1499 } 1500 } else { 1501 if (fatcode) 1502 put4(chain.pc + 1, target - chain.pc); 1503 else if (target - chain.pc < Short.MIN_VALUE || 1504 target - chain.pc > Short.MAX_VALUE) 1505 fatcode = true; 1506 else 1507 put2(chain.pc + 1, target - chain.pc); 1508 Assert.check(!alive || 1509 chain.state.stacksize == newState.stacksize && 1510 chain.state.nlocks == newState.nlocks); 1511 } 1512 fixedPc = true; 1513 if (cp == target) { 1514 changed = true; 1515 if (debugCode) 1516 System.err.println("resolving chain state=" + chain.state); 1517 if (alive) { 1518 newState = chain.state.join(newState); 1519 } else { 1520 newState = chain.state; 1521 alive = true; 1522 } 1523 } 1524 } 1525 Assert.check(!changed || state != newState); 1526 if (state != newState) { 1527 setDefined(newState.defined); 1528 state = newState; 1529 pendingStackMap = needStackMap; 1530 } 1531 } 1532 1533 /** Resolve chain to point to current code pointer. 1534 */ 1535 public void resolve(Chain chain) { 1536 Assert.check( 1537 !alive || 1538 chain==null || 1539 state.stacksize == chain.state.stacksize && 1540 state.nlocks == chain.state.nlocks); 1541 pendingJumps = mergeChains(chain, pendingJumps); 1542 } 1543 1544 /** Resolve any pending jumps. 1545 */ 1546 public void resolvePending() { 1547 Chain x = pendingJumps; 1548 pendingJumps = null; 1549 resolve(x, cp); 1550 } 1551 1552 /** Merge the jumps in of two chains into one. 1553 */ 1554 public static Chain mergeChains(Chain chain1, Chain chain2) { 1555 // recursive merge sort 1556 if (chain2 == null) return chain1; 1557 if (chain1 == null) return chain2; 1558 Assert.check( 1559 chain1.state.stacksize == chain2.state.stacksize && 1560 chain1.state.nlocks == chain2.state.nlocks); 1561 if (chain1.pc < chain2.pc) 1562 return new Chain( 1563 chain2.pc, 1564 mergeChains(chain1, chain2.next), 1565 chain2.state); 1566 return new Chain( 1567 chain1.pc, 1568 mergeChains(chain1.next, chain2), 1569 chain1.state); 1570 } 1571 1572 1573 /* ************************************************************************** 1574 * Catch clauses 1575 ****************************************************************************/ 1576 1577 /** Add a catch clause to code. 1578 */ 1579 public void addCatch(char startPc, char endPc, 1580 char handlerPc, char catchType) { 1581 catchInfo.append(new char[]{startPc, endPc, handlerPc, catchType}); 1582 } 1583 1584 1585 public void compressCatchTable() { 1586 ListBuffer<char[]> compressedCatchInfo = new ListBuffer<>(); 1587 List<Integer> handlerPcs = List.nil(); 1588 for (char[] catchEntry : catchInfo) { 1589 handlerPcs = handlerPcs.prepend((int)catchEntry[2]); 1590 } 1591 for (char[] catchEntry : catchInfo) { 1592 int startpc = catchEntry[0]; 1593 int endpc = catchEntry[1]; 1594 if (startpc == endpc || 1595 (startpc == (endpc - 1) && 1596 handlerPcs.contains(startpc))) { 1597 continue; 1598 } else { 1599 compressedCatchInfo.append(catchEntry); 1600 } 1601 } 1602 catchInfo = compressedCatchInfo; 1603 } 1604 1605 1606 /* ************************************************************************** 1607 * Line numbers 1608 ****************************************************************************/ 1609 1610 /** Add a line number entry. 1611 */ 1612 public void addLineNumber(char startPc, char lineNumber) { 1613 if (lineDebugInfo) { 1614 if (lineInfo.nonEmpty() && lineInfo.head[0] == startPc) 1615 lineInfo = lineInfo.tail; 1616 if (lineInfo.isEmpty() || lineInfo.head[1] != lineNumber) 1617 lineInfo = lineInfo.prepend(new char[]{startPc, lineNumber}); 1618 } 1619 } 1620 1621 /** Mark beginning of statement. 1622 */ 1623 public void statBegin(int pos) { 1624 if (pos != Position.NOPOS) { 1625 pendingStatPos = pos; 1626 } 1627 } 1628 1629 /** Force stat begin eagerly 1630 */ 1631 public void markStatBegin() { 1632 if (alive && lineDebugInfo) { 1633 int line = lineMap.getLineNumber(pendingStatPos); 1634 char cp1 = (char)cp; 1635 char line1 = (char)line; 1636 if (cp1 == cp && line1 == line) 1637 addLineNumber(cp1, line1); 1638 } 1639 pendingStatPos = Position.NOPOS; 1640 } 1641 1642 1643 /* ************************************************************************** 1644 * Simulated VM machine state 1645 ****************************************************************************/ 1646 1647 class State implements Cloneable { 1648 /** The set of registers containing values. */ 1649 Bits defined; 1650 1651 /** The (types of the) contents of the machine stack. */ 1652 Type[] stack; 1653 1654 /** The first stack position currently unused. */ 1655 int stacksize; 1656 1657 /** The numbers of registers containing locked monitors. */ 1658 int[] locks; 1659 int nlocks; 1660 1661 State() { 1662 defined = new Bits(); 1663 stack = new Type[16]; 1664 } 1665 1666 State dup() { 1667 try { 1668 State state = (State)super.clone(); 1669 state.defined = new Bits(defined); 1670 state.stack = stack.clone(); 1671 if (locks != null) state.locks = locks.clone(); 1672 if (debugCode) { 1673 System.err.println("duping state " + this); 1674 dump(); 1675 } 1676 return state; 1677 } catch (CloneNotSupportedException ex) { 1678 throw new AssertionError(ex); 1679 } 1680 } 1681 1682 void lock(int register) { 1683 if (locks == null) { 1684 locks = new int[20]; 1685 } else { 1686 locks = ArrayUtils.ensureCapacity(locks, nlocks); 1687 } 1688 locks[nlocks] = register; 1689 nlocks++; 1690 } 1691 1692 void unlock(int register) { 1693 nlocks--; 1694 Assert.check(locks[nlocks] == register); 1695 locks[nlocks] = -1; 1696 } 1697 1698 void push(Type t) { 1699 if (debugCode) System.err.println(" pushing " + t); 1700 switch (t.getTag()) { 1701 case VOID: 1702 return; 1703 case BYTE: 1704 case CHAR: 1705 case SHORT: 1706 case BOOLEAN: 1707 t = syms.intType; 1708 break; 1709 default: 1710 break; 1711 } 1712 stack = ArrayUtils.ensureCapacity(stack, stacksize+2); 1713 stack[stacksize++] = t; 1714 switch (width(t)) { 1715 case 1: 1716 break; 1717 case 2: 1718 stack[stacksize++] = null; 1719 break; 1720 default: 1721 throw new AssertionError(t); 1722 } 1723 if (stacksize > max_stack) 1724 max_stack = stacksize; 1725 } 1726 1727 Type pop1() { 1728 if (debugCode) System.err.println(" popping " + 1); 1729 stacksize--; 1730 Type result = stack[stacksize]; 1731 stack[stacksize] = null; 1732 Assert.check(result != null && width(result) == 1); 1733 return result; 1734 } 1735 1736 Type peek() { 1737 return stack[stacksize-1]; 1738 } 1739 1740 Type pop2() { 1741 if (debugCode) System.err.println(" popping " + 2); 1742 stacksize -= 2; 1743 Type result = stack[stacksize]; 1744 stack[stacksize] = null; 1745 Assert.check(stack[stacksize+1] == null 1746 && result != null && width(result) == 2); 1747 return result; 1748 } 1749 1750 void pop(int n) { 1751 if (debugCode) System.err.println(" popping " + n); 1752 while (n > 0) { 1753 stack[--stacksize] = null; 1754 n--; 1755 } 1756 } 1757 1758 void pop(Type t) { 1759 pop(width(t)); 1760 } 1761 1762 /** Force the top of the stack to be treated as this supertype 1763 * of its current type. */ 1764 void forceStackTop(Type t) { 1765 if (!alive) return; 1766 switch (t.getTag()) { 1767 case CLASS: 1768 case ARRAY: 1769 int width = width(t); 1770 Type old = stack[stacksize-width]; 1771 Assert.check(types.isSubtype(types.erasure(old), 1772 types.erasure(t))); 1773 stack[stacksize-width] = t; 1774 break; 1775 default: 1776 } 1777 } 1778 1779 void markInitialized(UninitializedType old) { 1780 Type newtype = old.initializedType(); 1781 for (int i=0; i<stacksize; i++) { 1782 if (stack[i] == old) stack[i] = newtype; 1783 } 1784 for (int i=0; i<lvar.length; i++) { 1785 LocalVar lv = lvar[i]; 1786 if (lv != null && lv.sym.type == old) { 1787 VarSymbol sym = lv.sym; 1788 sym = sym.clone(sym.owner); 1789 sym.type = newtype; 1790 LocalVar newlv = lvar[i] = new LocalVar(sym); 1791 newlv.aliveRanges = lv.aliveRanges; 1792 } 1793 } 1794 } 1795 1796 State join(State other) { 1797 defined.andSet(other.defined); 1798 Assert.check(stacksize == other.stacksize 1799 && nlocks == other.nlocks); 1800 for (int i=0; i<stacksize; ) { 1801 Type t = stack[i]; 1802 Type tother = other.stack[i]; 1803 Type result = 1804 t==tother ? t : 1805 types.isSubtype(t, tother) ? tother : 1806 types.isSubtype(tother, t) ? t : 1807 error(); 1808 int w = width(result); 1809 stack[i] = result; 1810 if (w == 2) Assert.checkNull(stack[i+1]); 1811 i += w; 1812 } 1813 return this; 1814 } 1815 1816 Type error() { 1817 throw new AssertionError("inconsistent stack types at join point"); 1818 } 1819 1820 void dump() { 1821 dump(-1); 1822 } 1823 1824 void dump(int pc) { 1825 System.err.print("stackMap for " + meth.owner + "." + meth); 1826 if (pc == -1) 1827 System.out.println(); 1828 else 1829 System.out.println(" at " + pc); 1830 System.err.println(" stack (from bottom):"); 1831 for (int i=0; i<stacksize; i++) 1832 System.err.println(" " + i + ": " + stack[i]); 1833 1834 int lastLocal = 0; 1835 for (int i=max_locals-1; i>=0; i--) { 1836 if (defined.isMember(i)) { 1837 lastLocal = i; 1838 break; 1839 } 1840 } 1841 if (lastLocal >= 0) 1842 System.err.println(" locals:"); 1843 for (int i=0; i<=lastLocal; i++) { 1844 System.err.print(" " + i + ": "); 1845 if (defined.isMember(i)) { 1846 LocalVar var = lvar[i]; 1847 if (var == null) { 1848 System.err.println("(none)"); 1849 } else if (var.sym == null) 1850 System.err.println("UNKNOWN!"); 1851 else 1852 System.err.println("" + var.sym + " of type " + 1853 var.sym.erasure(types)); 1854 } else { 1855 System.err.println("undefined"); 1856 } 1857 } 1858 if (nlocks != 0) { 1859 System.err.print(" locks:"); 1860 for (int i=0; i<nlocks; i++) { 1861 System.err.print(" " + locks[i]); 1862 } 1863 System.err.println(); 1864 } 1865 } 1866 } 1867 1868 static final Type jsrReturnValue = new JCPrimitiveType(INT, null); 1869 1870 1871 /* ************************************************************************** 1872 * Local variables 1873 ****************************************************************************/ 1874 1875 /** A live range of a local variable. */ 1876 static class LocalVar { 1877 final VarSymbol sym; 1878 final char reg; 1879 1880 class Range { 1881 char start_pc = Character.MAX_VALUE; 1882 char length = Character.MAX_VALUE; 1883 1884 Range() {} 1885 1886 Range(char start) { 1887 this.start_pc = start; 1888 } 1889 1890 Range(char start, char length) { 1891 this.start_pc = start; 1892 this.length = length; 1893 } 1894 1895 boolean closed() { 1896 return start_pc != Character.MAX_VALUE && length != Character.MAX_VALUE; 1897 } 1898 1899 @Override 1900 public String toString() { 1901 int currentStartPC = start_pc; 1902 int currentLength = length; 1903 return "startpc = " + currentStartPC + " length " + currentLength; 1904 } 1905 } 1906 1907 java.util.List<Range> aliveRanges = new java.util.ArrayList<>(); 1908 1909 LocalVar(VarSymbol v) { 1910 this.sym = v; 1911 this.reg = (char)v.adr; 1912 } 1913 public LocalVar dup() { 1914 return new LocalVar(sym); 1915 } 1916 1917 Range firstRange() { 1918 return aliveRanges.isEmpty() ? null : aliveRanges.get(0); 1919 } 1920 1921 Range lastRange() { 1922 return aliveRanges.isEmpty() ? null : aliveRanges.get(aliveRanges.size() - 1); 1923 } 1924 1925 void removeLastRange() { 1926 Range lastRange = lastRange(); 1927 if (lastRange != null) { 1928 aliveRanges.remove(lastRange); 1929 } 1930 } 1931 1932 @Override 1933 public String toString() { 1934 if (aliveRanges == null) { 1935 return "empty local var"; 1936 } 1937 StringBuilder sb = new StringBuilder().append(sym) 1938 .append(" in register ").append((int)reg).append(" \n"); 1939 for (Range r : aliveRanges) { 1940 sb.append(" starts at pc=").append(Integer.toString(((int)r.start_pc))) 1941 .append(" length=").append(Integer.toString(((int)r.length))) 1942 .append("\n"); 1943 } 1944 return sb.toString(); 1945 } 1946 1947 public void openRange(char start) { 1948 if (!hasOpenRange()) { 1949 aliveRanges.add(new Range(start)); 1950 } 1951 } 1952 1953 public void closeRange(char length) { 1954 if (isLastRangeInitialized() && length > 0) { 1955 Range range = lastRange(); 1956 if (range != null) { 1957 if (range.length == Character.MAX_VALUE) { 1958 range.length = length; 1959 } 1960 } 1961 } else { 1962 removeLastRange(); 1963 } 1964 } 1965 1966 public boolean hasOpenRange() { 1967 if (aliveRanges.isEmpty()) { 1968 return false; 1969 } 1970 return lastRange().length == Character.MAX_VALUE; 1971 } 1972 1973 public boolean isLastRangeInitialized() { 1974 if (aliveRanges.isEmpty()) { 1975 return false; 1976 } 1977 return lastRange().start_pc != Character.MAX_VALUE; 1978 } 1979 1980 public Range getWidestRange() { 1981 if (aliveRanges.isEmpty()) { 1982 return new Range(); 1983 } else { 1984 Range firstRange = firstRange(); 1985 Range lastRange = lastRange(); 1986 char length = (char)(lastRange.length + (lastRange.start_pc - firstRange.start_pc)); 1987 return new Range(firstRange.start_pc, length); 1988 } 1989 } 1990 1991 } 1992 1993 /** Local variables, indexed by register. */ 1994 LocalVar[] lvar; 1995 1996 /** Add a new local variable. */ 1997 private void addLocalVar(VarSymbol v) { 1998 int adr = v.adr; 1999 lvar = ArrayUtils.ensureCapacity(lvar, adr+1); 2000 Assert.checkNull(lvar[adr]); 2001 if (pendingJumps != null) { 2002 resolvePending(); 2003 } 2004 lvar[adr] = new LocalVar(v); 2005 state.defined.excl(adr); 2006 } 2007 2008 void adjustAliveRanges(int oldCP, int delta) { 2009 for (LocalVar localVar: lvar) { 2010 if (localVar != null) { 2011 for (LocalVar.Range range: localVar.aliveRanges) { 2012 if (range.closed() && range.start_pc + range.length >= oldCP) { 2013 range.length += delta; 2014 } 2015 } 2016 } 2017 } 2018 } 2019 2020 /** 2021 * Calculates the size of the LocalVariableTable. 2022 */ 2023 public int getLVTSize() { 2024 int result = varBufferSize; 2025 for (int i = 0; i < varBufferSize; i++) { 2026 LocalVar var = varBuffer[i]; 2027 result += var.aliveRanges.size() - 1; 2028 } 2029 return result; 2030 } 2031 2032 /** Set the current variable defined state. */ 2033 public void setDefined(Bits newDefined) { 2034 if (alive && newDefined != state.defined) { 2035 Bits diff = new Bits(state.defined).xorSet(newDefined); 2036 for (int adr = diff.nextBit(0); 2037 adr >= 0; 2038 adr = diff.nextBit(adr+1)) { 2039 if (adr >= nextreg) 2040 state.defined.excl(adr); 2041 else if (state.defined.isMember(adr)) 2042 setUndefined(adr); 2043 else 2044 setDefined(adr); 2045 } 2046 } 2047 } 2048 2049 /** Mark a register as being (possibly) defined. */ 2050 public void setDefined(int adr) { 2051 LocalVar v = lvar[adr]; 2052 if (v == null) { 2053 state.defined.excl(adr); 2054 } else { 2055 state.defined.incl(adr); 2056 if (cp < Character.MAX_VALUE) { 2057 v.openRange((char)cp); 2058 } 2059 } 2060 } 2061 2062 /** Mark a register as being undefined. */ 2063 public void setUndefined(int adr) { 2064 state.defined.excl(adr); 2065 if (adr < lvar.length && 2066 lvar[adr] != null && 2067 lvar[adr].isLastRangeInitialized()) { 2068 LocalVar v = lvar[adr]; 2069 char length = (char)(curCP() - v.lastRange().start_pc); 2070 if (length < Character.MAX_VALUE) { 2071 lvar[adr] = v.dup(); 2072 v.closeRange(length); 2073 putVar(v); 2074 } else { 2075 v.removeLastRange(); 2076 } 2077 } 2078 } 2079 2080 /** End the scope of a variable. */ 2081 private void endScope(int adr) { 2082 LocalVar v = lvar[adr]; 2083 if (v != null) { 2084 if (v.isLastRangeInitialized()) { 2085 char length = (char)(curCP() - v.lastRange().start_pc); 2086 if (length < Character.MAX_VALUE) { 2087 v.closeRange(length); 2088 putVar(v); 2089 fillLocalVarPosition(v); 2090 } 2091 } 2092 /** the call to curCP() can implicitly adjust the current cp, if so 2093 * the alive range of local variables may be modified. Thus we need 2094 * all of them. For this reason assigning null to the given address 2095 * should be the last action to do. 2096 */ 2097 lvar[adr] = null; 2098 } 2099 state.defined.excl(adr); 2100 } 2101 2102 private void fillLocalVarPosition(LocalVar lv) { 2103 if (lv == null || lv.sym == null || lv.sym.isExceptionParameter()|| !lv.sym.hasTypeAnnotations()) 2104 return; 2105 LocalVar.Range widestRange = lv.getWidestRange(); 2106 for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) { 2107 TypeAnnotationPosition p = ta.position; 2108 if (widestRange.closed() && widestRange.length > 0) { 2109 p.lvarOffset = new int[] { (int)widestRange.start_pc }; 2110 p.lvarLength = new int[] { (int)widestRange.length }; 2111 p.lvarIndex = new int[] { (int)lv.reg }; 2112 p.isValidOffset = true; 2113 } else { 2114 p.isValidOffset = false; 2115 } 2116 } 2117 } 2118 2119 // Method to be called after compressCatchTable to 2120 // fill in the exception table index for type 2121 // annotations on exception parameters. 2122 public void fillExceptionParameterPositions() { 2123 for (int i = 0; i < varBufferSize; ++i) { 2124 LocalVar lv = varBuffer[i]; 2125 if (lv == null || lv.sym == null 2126 || !lv.sym.hasTypeAnnotations() 2127 || !lv.sym.isExceptionParameter()) 2128 continue; 2129 2130 for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) { 2131 TypeAnnotationPosition p = ta.position; 2132 if (p.hasCatchType()) { 2133 final int idx = findExceptionIndex(p); 2134 if (idx == -1) 2135 Assert.error("Could not find exception index for type annotation " + 2136 ta + " on exception parameter"); 2137 p.setExceptionIndex(idx); 2138 } 2139 } 2140 } 2141 } 2142 2143 private int findExceptionIndex(TypeAnnotationPosition p) { 2144 final int catchType = p.getCatchType(); 2145 final int startPos = p.getStartPos(); 2146 final int len = catchInfo.length(); 2147 List<char[]> iter = catchInfo.toList(); 2148 for (int i = 0; i < len; ++i) { 2149 char[] catchEntry = iter.head; 2150 iter = iter.tail; 2151 int ct = catchEntry[3]; 2152 int sp = catchEntry[0]; 2153 if (catchType == ct && sp == startPos) { 2154 return i; 2155 } 2156 } 2157 return -1; 2158 } 2159 2160 /** Put a live variable range into the buffer to be output to the 2161 * class file. 2162 */ 2163 void putVar(LocalVar var) { 2164 // Keep local variables if 2165 // 1) we need them for debug information 2166 // 2) it is an exception type and it contains type annotations 2167 boolean keepLocalVariables = varDebugInfo || 2168 (var.sym.isExceptionParameter() && var.sym.hasTypeAnnotations()); 2169 if (!keepLocalVariables) return; 2170 //don't keep synthetic vars, unless they are lambda method parameters 2171 boolean ignoredSyntheticVar = (var.sym.flags() & Flags.SYNTHETIC) != 0 && 2172 ((var.sym.owner.flags() & Flags.LAMBDA_METHOD) == 0 || 2173 (var.sym.flags() & Flags.PARAMETER) == 0); 2174 if (ignoredSyntheticVar) return; 2175 if (varBuffer == null) 2176 varBuffer = new LocalVar[20]; 2177 else 2178 varBuffer = ArrayUtils.ensureCapacity(varBuffer, varBufferSize); 2179 varBuffer[varBufferSize++] = var; 2180 } 2181 2182 /** Previously live local variables, to be put into the variable table. */ 2183 LocalVar[] varBuffer; 2184 int varBufferSize; 2185 2186 /** Create a new local variable address and return it. 2187 */ 2188 private int newLocal(int typecode) { 2189 int reg = nextreg; 2190 int w = width(typecode); 2191 nextreg = reg + w; 2192 if (nextreg > max_locals) max_locals = nextreg; 2193 return reg; 2194 } 2195 2196 private int newLocal(Type type) { 2197 return newLocal(typecode(type)); 2198 } 2199 2200 public int newLocal(VarSymbol v) { 2201 int reg = v.adr = newLocal(v.erasure(types)); 2202 addLocalVar(v); 2203 return reg; 2204 } 2205 2206 /** Start a set of fresh registers. 2207 */ 2208 public void newRegSegment() { 2209 nextreg = max_locals; 2210 } 2211 2212 /** End scopes of all variables with registers ≥ first. 2213 */ 2214 public void endScopes(int first) { 2215 int prevNextReg = nextreg; 2216 nextreg = first; 2217 for (int i = nextreg; i < prevNextReg; i++) endScope(i); 2218 } 2219 2220 /************************************************************************** 2221 * static tables 2222 *************************************************************************/ 2223 2224 public static String mnem(int opcode) { 2225 return Mneumonics.mnem[opcode]; 2226 } 2227 2228 private static class Mneumonics { 2229 private final static String[] mnem = new String[ByteCodeCount]; 2230 static { 2231 mnem[nop] = "nop"; 2232 mnem[aconst_null] = "aconst_null"; 2233 mnem[iconst_m1] = "iconst_m1"; 2234 mnem[iconst_0] = "iconst_0"; 2235 mnem[iconst_1] = "iconst_1"; 2236 mnem[iconst_2] = "iconst_2"; 2237 mnem[iconst_3] = "iconst_3"; 2238 mnem[iconst_4] = "iconst_4"; 2239 mnem[iconst_5] = "iconst_5"; 2240 mnem[lconst_0] = "lconst_0"; 2241 mnem[lconst_1] = "lconst_1"; 2242 mnem[fconst_0] = "fconst_0"; 2243 mnem[fconst_1] = "fconst_1"; 2244 mnem[fconst_2] = "fconst_2"; 2245 mnem[dconst_0] = "dconst_0"; 2246 mnem[dconst_1] = "dconst_1"; 2247 mnem[bipush] = "bipush"; 2248 mnem[sipush] = "sipush"; 2249 mnem[ldc1] = "ldc1"; 2250 mnem[ldc2] = "ldc2"; 2251 mnem[ldc2w] = "ldc2w"; 2252 mnem[iload] = "iload"; 2253 mnem[lload] = "lload"; 2254 mnem[fload] = "fload"; 2255 mnem[dload] = "dload"; 2256 mnem[aload] = "aload"; 2257 mnem[iload_0] = "iload_0"; 2258 mnem[lload_0] = "lload_0"; 2259 mnem[fload_0] = "fload_0"; 2260 mnem[dload_0] = "dload_0"; 2261 mnem[aload_0] = "aload_0"; 2262 mnem[iload_1] = "iload_1"; 2263 mnem[lload_1] = "lload_1"; 2264 mnem[fload_1] = "fload_1"; 2265 mnem[dload_1] = "dload_1"; 2266 mnem[aload_1] = "aload_1"; 2267 mnem[iload_2] = "iload_2"; 2268 mnem[lload_2] = "lload_2"; 2269 mnem[fload_2] = "fload_2"; 2270 mnem[dload_2] = "dload_2"; 2271 mnem[aload_2] = "aload_2"; 2272 mnem[iload_3] = "iload_3"; 2273 mnem[lload_3] = "lload_3"; 2274 mnem[fload_3] = "fload_3"; 2275 mnem[dload_3] = "dload_3"; 2276 mnem[aload_3] = "aload_3"; 2277 mnem[iaload] = "iaload"; 2278 mnem[laload] = "laload"; 2279 mnem[faload] = "faload"; 2280 mnem[daload] = "daload"; 2281 mnem[aaload] = "aaload"; 2282 mnem[baload] = "baload"; 2283 mnem[caload] = "caload"; 2284 mnem[saload] = "saload"; 2285 mnem[istore] = "istore"; 2286 mnem[lstore] = "lstore"; 2287 mnem[fstore] = "fstore"; 2288 mnem[dstore] = "dstore"; 2289 mnem[astore] = "astore"; 2290 mnem[istore_0] = "istore_0"; 2291 mnem[lstore_0] = "lstore_0"; 2292 mnem[fstore_0] = "fstore_0"; 2293 mnem[dstore_0] = "dstore_0"; 2294 mnem[astore_0] = "astore_0"; 2295 mnem[istore_1] = "istore_1"; 2296 mnem[lstore_1] = "lstore_1"; 2297 mnem[fstore_1] = "fstore_1"; 2298 mnem[dstore_1] = "dstore_1"; 2299 mnem[astore_1] = "astore_1"; 2300 mnem[istore_2] = "istore_2"; 2301 mnem[lstore_2] = "lstore_2"; 2302 mnem[fstore_2] = "fstore_2"; 2303 mnem[dstore_2] = "dstore_2"; 2304 mnem[astore_2] = "astore_2"; 2305 mnem[istore_3] = "istore_3"; 2306 mnem[lstore_3] = "lstore_3"; 2307 mnem[fstore_3] = "fstore_3"; 2308 mnem[dstore_3] = "dstore_3"; 2309 mnem[astore_3] = "astore_3"; 2310 mnem[iastore] = "iastore"; 2311 mnem[lastore] = "lastore"; 2312 mnem[fastore] = "fastore"; 2313 mnem[dastore] = "dastore"; 2314 mnem[aastore] = "aastore"; 2315 mnem[bastore] = "bastore"; 2316 mnem[castore] = "castore"; 2317 mnem[sastore] = "sastore"; 2318 mnem[pop] = "pop"; 2319 mnem[pop2] = "pop2"; 2320 mnem[dup] = "dup"; 2321 mnem[dup_x1] = "dup_x1"; 2322 mnem[dup_x2] = "dup_x2"; 2323 mnem[dup2] = "dup2"; 2324 mnem[dup2_x1] = "dup2_x1"; 2325 mnem[dup2_x2] = "dup2_x2"; 2326 mnem[swap] = "swap"; 2327 mnem[iadd] = "iadd"; 2328 mnem[ladd] = "ladd"; 2329 mnem[fadd] = "fadd"; 2330 mnem[dadd] = "dadd"; 2331 mnem[isub] = "isub"; 2332 mnem[lsub] = "lsub"; 2333 mnem[fsub] = "fsub"; 2334 mnem[dsub] = "dsub"; 2335 mnem[imul] = "imul"; 2336 mnem[lmul] = "lmul"; 2337 mnem[fmul] = "fmul"; 2338 mnem[dmul] = "dmul"; 2339 mnem[idiv] = "idiv"; 2340 mnem[ldiv] = "ldiv"; 2341 mnem[fdiv] = "fdiv"; 2342 mnem[ddiv] = "ddiv"; 2343 mnem[imod] = "imod"; 2344 mnem[lmod] = "lmod"; 2345 mnem[fmod] = "fmod"; 2346 mnem[dmod] = "dmod"; 2347 mnem[ineg] = "ineg"; 2348 mnem[lneg] = "lneg"; 2349 mnem[fneg] = "fneg"; 2350 mnem[dneg] = "dneg"; 2351 mnem[ishl] = "ishl"; 2352 mnem[lshl] = "lshl"; 2353 mnem[ishr] = "ishr"; 2354 mnem[lshr] = "lshr"; 2355 mnem[iushr] = "iushr"; 2356 mnem[lushr] = "lushr"; 2357 mnem[iand] = "iand"; 2358 mnem[land] = "land"; 2359 mnem[ior] = "ior"; 2360 mnem[lor] = "lor"; 2361 mnem[ixor] = "ixor"; 2362 mnem[lxor] = "lxor"; 2363 mnem[iinc] = "iinc"; 2364 mnem[i2l] = "i2l"; 2365 mnem[i2f] = "i2f"; 2366 mnem[i2d] = "i2d"; 2367 mnem[l2i] = "l2i"; 2368 mnem[l2f] = "l2f"; 2369 mnem[l2d] = "l2d"; 2370 mnem[f2i] = "f2i"; 2371 mnem[f2l] = "f2l"; 2372 mnem[f2d] = "f2d"; 2373 mnem[d2i] = "d2i"; 2374 mnem[d2l] = "d2l"; 2375 mnem[d2f] = "d2f"; 2376 mnem[int2byte] = "int2byte"; 2377 mnem[int2char] = "int2char"; 2378 mnem[int2short] = "int2short"; 2379 mnem[lcmp] = "lcmp"; 2380 mnem[fcmpl] = "fcmpl"; 2381 mnem[fcmpg] = "fcmpg"; 2382 mnem[dcmpl] = "dcmpl"; 2383 mnem[dcmpg] = "dcmpg"; 2384 mnem[ifeq] = "ifeq"; 2385 mnem[ifne] = "ifne"; 2386 mnem[iflt] = "iflt"; 2387 mnem[ifge] = "ifge"; 2388 mnem[ifgt] = "ifgt"; 2389 mnem[ifle] = "ifle"; 2390 mnem[if_icmpeq] = "if_icmpeq"; 2391 mnem[if_icmpne] = "if_icmpne"; 2392 mnem[if_icmplt] = "if_icmplt"; 2393 mnem[if_icmpge] = "if_icmpge"; 2394 mnem[if_icmpgt] = "if_icmpgt"; 2395 mnem[if_icmple] = "if_icmple"; 2396 mnem[if_acmpeq] = "if_acmpeq"; 2397 mnem[if_acmpne] = "if_acmpne"; 2398 mnem[goto_] = "goto_"; 2399 mnem[jsr] = "jsr"; 2400 mnem[ret] = "ret"; 2401 mnem[tableswitch] = "tableswitch"; 2402 mnem[lookupswitch] = "lookupswitch"; 2403 mnem[ireturn] = "ireturn"; 2404 mnem[lreturn] = "lreturn"; 2405 mnem[freturn] = "freturn"; 2406 mnem[dreturn] = "dreturn"; 2407 mnem[areturn] = "areturn"; 2408 mnem[return_] = "return_"; 2409 mnem[getstatic] = "getstatic"; 2410 mnem[putstatic] = "putstatic"; 2411 mnem[getfield] = "getfield"; 2412 mnem[putfield] = "putfield"; 2413 mnem[invokevirtual] = "invokevirtual"; 2414 mnem[invokespecial] = "invokespecial"; 2415 mnem[invokestatic] = "invokestatic"; 2416 mnem[invokeinterface] = "invokeinterface"; 2417 mnem[invokedynamic] = "invokedynamic"; 2418 mnem[new_] = "new_"; 2419 mnem[newarray] = "newarray"; 2420 mnem[anewarray] = "anewarray"; 2421 mnem[arraylength] = "arraylength"; 2422 mnem[athrow] = "athrow"; 2423 mnem[checkcast] = "checkcast"; 2424 mnem[instanceof_] = "instanceof_"; 2425 mnem[monitorenter] = "monitorenter"; 2426 mnem[monitorexit] = "monitorexit"; 2427 mnem[wide] = "wide"; 2428 mnem[multianewarray] = "multianewarray"; 2429 mnem[if_acmp_null] = "if_acmp_null"; 2430 mnem[if_acmp_nonnull] = "if_acmp_nonnull"; 2431 mnem[goto_w] = "goto_w"; 2432 mnem[jsr_w] = "jsr_w"; 2433 mnem[breakpoint] = "breakpoint"; 2434 } 2435 } 2436 }