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