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