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 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.tree.JCTree; 32 import com.sun.tools.javac.util.*; 33 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 34 35 import static com.sun.tools.javac.code.TypeTag.BOT; 36 import static com.sun.tools.javac.code.TypeTag.INT; 37 import static com.sun.tools.javac.jvm.ByteCodes.*; 38 import static com.sun.tools.javac.jvm.UninitializedType.*; 39 import 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 */ 50 public 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 vaload: 498 case aaload: { 499 state.pop(1);// index 500 Type a = state.stack[state.stacksize-1]; 501 Assert.check(!a.hasTag(BOT)); // null type as is cannot be indexed. 502 state.pop(1); 503 state.push(types.erasure(types.elemtype(a))); } 504 break; 505 case goto_: 506 markDead(); 507 break; 508 case nop: 509 case ineg: 510 case lneg: 511 case fneg: 512 case dneg: 513 break; 514 case aconst_null: 515 state.push(syms.botType); 516 break; 517 case iconst_m1: 518 case iconst_0: 519 case iconst_1: 520 case iconst_2: 521 case iconst_3: 522 case iconst_4: 523 case iconst_5: 524 case iload_0: 525 case iload_1: 526 case iload_2: 527 case iload_3: 528 state.push(syms.intType); 529 break; 530 case lconst_0: 531 case lconst_1: 532 case lload_0: 533 case lload_1: 534 case lload_2: 535 case lload_3: 536 state.push(syms.longType); 537 break; 538 case fconst_0: 539 case fconst_1: 540 case fconst_2: 541 case fload_0: 542 case fload_1: 543 case fload_2: 544 case fload_3: 545 state.push(syms.floatType); 546 break; 547 case dconst_0: 548 case dconst_1: 549 case dload_0: 550 case dload_1: 551 case dload_2: 552 case dload_3: 553 state.push(syms.doubleType); 554 break; 555 case aload_0: 556 state.push(lvar[0].sym.type); 557 break; 558 case aload_1: 559 state.push(lvar[1].sym.type); 560 break; 561 case aload_2: 562 state.push(lvar[2].sym.type); 563 break; 564 case aload_3: 565 state.push(lvar[3].sym.type); 566 break; 567 case iaload: 568 case baload: 569 case caload: 570 case saload: 571 state.pop(2); 572 state.push(syms.intType); 573 break; 574 case laload: 575 state.pop(2); 576 state.push(syms.longType); 577 break; 578 case faload: 579 state.pop(2); 580 state.push(syms.floatType); 581 break; 582 case daload: 583 state.pop(2); 584 state.push(syms.doubleType); 585 break; 586 case istore_0: 587 case istore_1: 588 case istore_2: 589 case istore_3: 590 case fstore_0: 591 case fstore_1: 592 case fstore_2: 593 case fstore_3: 594 case astore_0: 595 case astore_1: 596 case astore_2: 597 case astore_3: 598 case pop: 599 case lshr: 600 case lshl: 601 case lushr: 602 state.pop(1); 603 break; 604 case vreturn: 605 case areturn: 606 case ireturn: 607 case freturn: 608 Assert.check(state.nlocks == 0); 609 state.pop(1); 610 markDead(); 611 break; 612 case athrow: 613 state.pop(1); 614 markDead(); 615 break; 616 case lstore_0: 617 case lstore_1: 618 case lstore_2: 619 case lstore_3: 620 case dstore_0: 621 case dstore_1: 622 case dstore_2: 623 case dstore_3: 624 case pop2: 625 state.pop(2); 626 break; 627 case lreturn: 628 case dreturn: 629 Assert.check(state.nlocks == 0); 630 state.pop(2); 631 markDead(); 632 break; 633 case dup: 634 state.push(state.stack[state.stacksize-1]); 635 break; 636 case return_: 637 Assert.check(state.nlocks == 0); 638 markDead(); 639 break; 640 case arraylength: 641 state.pop(1); 642 state.push(syms.intType); 643 break; 644 case isub: 645 case iadd: 646 case imul: 647 case idiv: 648 case imod: 649 case ishl: 650 case ishr: 651 case iushr: 652 case iand: 653 case ior: 654 case ixor: 655 state.pop(1); 656 // state.pop(1); 657 // state.push(syms.intType); 658 break; 659 case vastore: 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 case vload: 962 state.push(lvar[od].sym.type); 963 break; 964 case lstore: 965 case dstore: 966 state.pop(2); 967 break; 968 case istore: 969 case fstore: 970 case astore: 971 case vstore: 972 state.pop(1); 973 break; 974 case ret: 975 markDead(); 976 break; 977 default: 978 throw new AssertionError(mnem(op)); 979 } 980 postop(); 981 } 982 983 /** Emit an opcode with two one-byte operand fields; 984 * widen if either field does not fit in a byte. 985 */ 986 public void emitop1w(int op, int od1, int od2) { 987 if (od1 > 0xFF || od2 < -128 || od2 > 127) { 988 emitop(wide); 989 emitop(op); 990 emit2(od1); 991 emit2(od2); 992 } else { 993 emitop(op); 994 emit1(od1); 995 emit1(od2); 996 } 997 if (!alive) return; 998 switch (op) { 999 case iinc: 1000 break; 1001 default: 1002 throw new AssertionError(mnem(op)); 1003 } 1004 } 1005 1006 /** Emit an opcode with a two-byte operand field. 1007 */ 1008 public void emitop2(int op, int od) { 1009 emitop(op); 1010 if (!alive) return; 1011 emit2(od); 1012 switch (op) { 1013 case getstatic: 1014 state.push(((Symbol)(pool.pool[od])).erasure(types)); 1015 break; 1016 case putstatic: 1017 state.pop(((Symbol)(pool.pool[od])).erasure(types)); 1018 break; 1019 case new_: 1020 Symbol sym; 1021 if (pool.pool[od] instanceof UniqueType) { 1022 // Required by change in Gen.makeRef to allow 1023 // annotated types. 1024 // TODO: is this needed anywhere else? 1025 sym = ((UniqueType)(pool.pool[od])).type.tsym; 1026 } else { 1027 sym = (Symbol)(pool.pool[od]); 1028 } 1029 state.push(uninitializedObject(sym.erasure(types), cp-3)); 1030 break; 1031 case vdefault: 1032 if (pool.pool[od] instanceof UniqueType) { 1033 // Required by change in Gen.makeRef to allow 1034 // annotated types. 1035 // TODO: is this needed anywhere else? 1036 sym = ((UniqueType)(pool.pool[od])).type.tsym; 1037 } else { 1038 sym = (Symbol)(pool.pool[od]); 1039 } 1040 state.push(sym.erasure(types)); 1041 break; 1042 case sipush: 1043 state.push(syms.intType); 1044 break; 1045 case if_acmp_null: 1046 case if_acmp_nonnull: 1047 case ifeq: 1048 case ifne: 1049 case iflt: 1050 case ifge: 1051 case ifgt: 1052 case ifle: 1053 state.pop(1); 1054 break; 1055 case if_icmpeq: 1056 case if_icmpne: 1057 case if_icmplt: 1058 case if_icmpge: 1059 case if_icmpgt: 1060 case if_icmple: 1061 case if_acmpeq: 1062 case if_acmpne: 1063 state.pop(2); 1064 break; 1065 case goto_: 1066 markDead(); 1067 break; 1068 case vwithfield: 1069 state.pop(((Symbol)(pool.pool[od])).erasure(types)); 1070 break; 1071 case putfield: 1072 state.pop(((Symbol)(pool.pool[od])).erasure(types)); 1073 state.pop(1); // object ref 1074 break; 1075 case getfield: 1076 state.pop(1); // object ref 1077 state.push(((Symbol)(pool.pool[od])).erasure(types)); 1078 break; 1079 case checkcast: { 1080 state.pop(1); // object ref 1081 Object o = pool.pool[od]; 1082 Type t = (o instanceof Symbol) 1083 ? ((Symbol)o).erasure(types) 1084 : types.erasure((((UniqueType)o).type)); 1085 state.push(t); 1086 break; } 1087 case ldc2w: 1088 state.push(typeForPool(pool.pool[od])); 1089 break; 1090 case instanceof_: 1091 state.pop(1); 1092 state.push(syms.intType); 1093 break; 1094 case ldc2: 1095 state.push(typeForPool(pool.pool[od])); 1096 break; 1097 case jsr: 1098 break; 1099 default: 1100 throw new AssertionError(mnem(op)); 1101 } 1102 // postop(); 1103 } 1104 1105 /** Emit an opcode with a four-byte operand field. 1106 */ 1107 public void emitop4(int op, int od) { 1108 emitop(op); 1109 if (!alive) return; 1110 emit4(od); 1111 switch (op) { 1112 case goto_w: 1113 markDead(); 1114 break; 1115 case jsr_w: 1116 break; 1117 default: 1118 throw new AssertionError(mnem(op)); 1119 } 1120 // postop(); 1121 } 1122 1123 /** Align code pointer to next `incr' boundary. 1124 */ 1125 public void align(int incr) { 1126 if (alive) 1127 while (cp % incr != 0) emitop0(nop); 1128 } 1129 1130 /** Place a byte into code at address pc. 1131 * Pre: {@literal pc + 1 <= cp }. 1132 */ 1133 private void put1(int pc, int op) { 1134 code[pc] = (byte)op; 1135 } 1136 1137 /** Place two bytes into code at address pc. 1138 * Pre: {@literal pc + 2 <= cp }. 1139 */ 1140 private void put2(int pc, int od) { 1141 // pre: pc + 2 <= cp 1142 put1(pc, od >> 8); 1143 put1(pc+1, od); 1144 } 1145 1146 /** Place four bytes into code at address pc. 1147 * Pre: {@literal pc + 4 <= cp }. 1148 */ 1149 public void put4(int pc, int od) { 1150 // pre: pc + 4 <= cp 1151 put1(pc , od >> 24); 1152 put1(pc+1, od >> 16); 1153 put1(pc+2, od >> 8); 1154 put1(pc+3, od); 1155 } 1156 1157 /** Return code byte at position pc as an unsigned int. 1158 */ 1159 private int get1(int pc) { 1160 return code[pc] & 0xFF; 1161 } 1162 1163 /** Return two code bytes at position pc as an unsigned int. 1164 */ 1165 private int get2(int pc) { 1166 return (get1(pc) << 8) | get1(pc+1); 1167 } 1168 1169 /** Return four code bytes at position pc as an int. 1170 */ 1171 public int get4(int pc) { 1172 // pre: pc + 4 <= cp 1173 return 1174 (get1(pc) << 24) | 1175 (get1(pc+1) << 16) | 1176 (get1(pc+2) << 8) | 1177 (get1(pc+3)); 1178 } 1179 1180 /** Is code generation currently enabled? 1181 */ 1182 public boolean isAlive() { 1183 return alive || pendingJumps != null; 1184 } 1185 1186 /** Switch code generation on/off. 1187 */ 1188 public void markDead() { 1189 alive = false; 1190 } 1191 1192 /** Declare an entry point; return current code pointer 1193 */ 1194 public int entryPoint() { 1195 int pc = curCP(); 1196 alive = true; 1197 pendingStackMap = needStackMap; 1198 return pc; 1199 } 1200 1201 /** Declare an entry point with initial state; 1202 * return current code pointer 1203 */ 1204 public int entryPoint(State state) { 1205 int pc = curCP(); 1206 alive = true; 1207 State newState = state.dup(); 1208 setDefined(newState.defined); 1209 this.state = newState; 1210 Assert.check(state.stacksize <= max_stack); 1211 if (debugCode) System.err.println("entry point " + state); 1212 pendingStackMap = needStackMap; 1213 return pc; 1214 } 1215 1216 /** Declare an entry point with initial state plus a pushed value; 1217 * return current code pointer 1218 */ 1219 public int entryPoint(State state, Type pushed) { 1220 int pc = curCP(); 1221 alive = true; 1222 State newState = state.dup(); 1223 setDefined(newState.defined); 1224 this.state = newState; 1225 Assert.check(state.stacksize <= max_stack); 1226 this.state.push(pushed); 1227 if (debugCode) System.err.println("entry point " + state); 1228 pendingStackMap = needStackMap; 1229 return pc; 1230 } 1231 1232 1233 /************************************************************************** 1234 * Stack map generation 1235 *************************************************************************/ 1236 1237 /** An entry in the stack map. */ 1238 static class StackMapFrame { 1239 int pc; 1240 Type[] locals; 1241 Type[] stack; 1242 } 1243 1244 /** A buffer of cldc stack map entries. */ 1245 StackMapFrame[] stackMapBuffer = null; 1246 1247 /** A buffer of compressed StackMapTable entries. */ 1248 StackMapTableFrame[] stackMapTableBuffer = null; 1249 int stackMapBufferSize = 0; 1250 1251 /** The last PC at which we generated a stack map. */ 1252 int lastStackMapPC = -1; 1253 1254 /** The last stack map frame in StackMapTable. */ 1255 StackMapFrame lastFrame = null; 1256 1257 /** The stack map frame before the last one. */ 1258 StackMapFrame frameBeforeLast = null; 1259 1260 /** Emit a stack map entry. */ 1261 public void emitStackMap() { 1262 int pc = curCP(); 1263 if (!needStackMap) return; 1264 1265 1266 1267 switch (stackMap) { 1268 case CLDC: 1269 emitCLDCStackMap(pc, getLocalsSize()); 1270 break; 1271 case JSR202: 1272 emitStackMapFrame(pc, getLocalsSize()); 1273 break; 1274 default: 1275 throw new AssertionError("Should have chosen a stackmap format"); 1276 } 1277 // DEBUG code follows 1278 if (debugCode) state.dump(pc); 1279 } 1280 1281 private int getLocalsSize() { 1282 int nextLocal = 0; 1283 for (int i=max_locals-1; i>=0; i--) { 1284 if (state.defined.isMember(i) && lvar[i] != null) { 1285 nextLocal = i + width(lvar[i].sym.erasure(types)); 1286 break; 1287 } 1288 } 1289 return nextLocal; 1290 } 1291 1292 /** Emit a CLDC stack map frame. */ 1293 void emitCLDCStackMap(int pc, int localsSize) { 1294 if (lastStackMapPC == pc) { 1295 // drop existing stackmap at this offset 1296 stackMapBuffer[--stackMapBufferSize] = null; 1297 } 1298 lastStackMapPC = pc; 1299 1300 if (stackMapBuffer == null) { 1301 stackMapBuffer = new StackMapFrame[20]; 1302 } else { 1303 stackMapBuffer = ArrayUtils.ensureCapacity(stackMapBuffer, stackMapBufferSize); 1304 } 1305 StackMapFrame frame = 1306 stackMapBuffer[stackMapBufferSize++] = new StackMapFrame(); 1307 frame.pc = pc; 1308 1309 frame.locals = new Type[localsSize]; 1310 for (int i=0; i<localsSize; i++) { 1311 if (state.defined.isMember(i) && lvar[i] != null) { 1312 Type vtype = lvar[i].sym.type; 1313 if (!(vtype instanceof UninitializedType)) 1314 vtype = types.erasure(vtype); 1315 frame.locals[i] = vtype; 1316 } 1317 } 1318 frame.stack = new Type[state.stacksize]; 1319 for (int i=0; i<state.stacksize; i++) 1320 frame.stack[i] = state.stack[i]; 1321 } 1322 1323 void emitStackMapFrame(int pc, int localsSize) { 1324 if (lastFrame == null) { 1325 // first frame 1326 lastFrame = getInitialFrame(); 1327 } else if (lastFrame.pc == pc) { 1328 // drop existing stackmap at this offset 1329 stackMapTableBuffer[--stackMapBufferSize] = null; 1330 lastFrame = frameBeforeLast; 1331 frameBeforeLast = null; 1332 } 1333 1334 StackMapFrame frame = new StackMapFrame(); 1335 frame.pc = pc; 1336 1337 int localCount = 0; 1338 Type[] locals = new Type[localsSize]; 1339 for (int i=0; i<localsSize; i++, localCount++) { 1340 if (state.defined.isMember(i) && lvar[i] != null) { 1341 Type vtype = lvar[i].sym.type; 1342 if (!(vtype instanceof UninitializedType)) 1343 vtype = types.erasure(vtype); 1344 locals[i] = vtype; 1345 if (width(vtype) > 1) i++; 1346 } 1347 } 1348 frame.locals = new Type[localCount]; 1349 for (int i=0, j=0; i<localsSize; i++, j++) { 1350 Assert.check(j < localCount); 1351 frame.locals[j] = locals[i]; 1352 if (width(locals[i]) > 1) i++; 1353 } 1354 1355 int stackCount = 0; 1356 for (int i=0; i<state.stacksize; i++) { 1357 if (state.stack[i] != null) { 1358 stackCount++; 1359 } 1360 } 1361 frame.stack = new Type[stackCount]; 1362 stackCount = 0; 1363 for (int i=0; i<state.stacksize; i++) { 1364 if (state.stack[i] != null) { 1365 frame.stack[stackCount++] = types.erasure(state.stack[i]); 1366 } 1367 } 1368 1369 if (stackMapTableBuffer == null) { 1370 stackMapTableBuffer = new StackMapTableFrame[20]; 1371 } else { 1372 stackMapTableBuffer = ArrayUtils.ensureCapacity( 1373 stackMapTableBuffer, 1374 stackMapBufferSize); 1375 } 1376 stackMapTableBuffer[stackMapBufferSize++] = 1377 StackMapTableFrame.getInstance(frame, lastFrame.pc, lastFrame.locals, types); 1378 1379 frameBeforeLast = lastFrame; 1380 lastFrame = frame; 1381 } 1382 1383 StackMapFrame getInitialFrame() { 1384 StackMapFrame frame = new StackMapFrame(); 1385 List<Type> arg_types = ((MethodType)meth.externalType(types)).argtypes; 1386 int len = arg_types.length(); 1387 int count = 0; 1388 if (!meth.isStatic()) { 1389 Type thisType = meth.owner.type; 1390 frame.locals = new Type[len+1]; 1391 if (meth.isConstructor() && thisType != syms.objectType) { 1392 frame.locals[count++] = UninitializedType.uninitializedThis(thisType); 1393 } else { 1394 frame.locals[count++] = types.erasure(thisType); 1395 } 1396 } else { 1397 frame.locals = new Type[len]; 1398 } 1399 for (Type arg_type : arg_types) { 1400 frame.locals[count++] = types.erasure(arg_type); 1401 } 1402 frame.pc = -1; 1403 frame.stack = null; 1404 return frame; 1405 } 1406 1407 1408 /************************************************************************** 1409 * Operations having to do with jumps 1410 *************************************************************************/ 1411 1412 /** A chain represents a list of unresolved jumps. Jump locations 1413 * are sorted in decreasing order. 1414 */ 1415 public static class Chain { 1416 1417 /** The position of the jump instruction. 1418 */ 1419 public final int pc; 1420 1421 /** The machine state after the jump instruction. 1422 * Invariant: all elements of a chain list have the same stacksize 1423 * and compatible stack and register contents. 1424 */ 1425 Code.State state; 1426 1427 /** The next jump in the list. 1428 */ 1429 public final Chain next; 1430 1431 /** Construct a chain from its jump position, stacksize, previous 1432 * chain, and machine state. 1433 */ 1434 public Chain(int pc, Chain next, Code.State state) { 1435 this.pc = pc; 1436 this.next = next; 1437 this.state = state; 1438 } 1439 } 1440 1441 /** Negate a branch opcode. 1442 */ 1443 public static int negate(int opcode) { 1444 if (opcode == if_acmp_null) return if_acmp_nonnull; 1445 else if (opcode == if_acmp_nonnull) return if_acmp_null; 1446 else return ((opcode + 1) ^ 1) - 1; 1447 } 1448 1449 /** Emit a jump instruction. 1450 * Return code pointer of instruction to be patched. 1451 */ 1452 public int emitJump(int opcode) { 1453 if (fatcode) { 1454 if (opcode == goto_ || opcode == jsr) { 1455 emitop4(opcode + goto_w - goto_, 0); 1456 } else { 1457 emitop2(negate(opcode), 8); 1458 emitop4(goto_w, 0); 1459 alive = true; 1460 pendingStackMap = needStackMap; 1461 } 1462 return cp - 5; 1463 } else { 1464 emitop2(opcode, 0); 1465 return cp - 3; 1466 } 1467 } 1468 1469 /** Emit a branch with given opcode; return its chain. 1470 * branch differs from jump in that jsr is treated as no-op. 1471 */ 1472 public Chain branch(int opcode) { 1473 Chain result = null; 1474 if (opcode == goto_) { 1475 result = pendingJumps; 1476 pendingJumps = null; 1477 } 1478 if (opcode != dontgoto && isAlive()) { 1479 result = new Chain(emitJump(opcode), 1480 result, 1481 state.dup()); 1482 fixedPc = fatcode; 1483 if (opcode == goto_) alive = false; 1484 } 1485 return result; 1486 } 1487 1488 /** Resolve chain to point to given target. 1489 */ 1490 public void resolve(Chain chain, int target) { 1491 boolean changed = false; 1492 State newState = state; 1493 for (; chain != null; chain = chain.next) { 1494 Assert.check(state != chain.state 1495 && (target > chain.pc || state.stacksize == 0)); 1496 if (target >= cp) { 1497 target = cp; 1498 } else if (get1(target) == goto_) { 1499 if (fatcode) target = target + get4(target + 1); 1500 else target = target + get2(target + 1); 1501 } 1502 if (get1(chain.pc) == goto_ && 1503 chain.pc + 3 == target && target == cp && !fixedPc) { 1504 // If goto the next instruction, the jump is not needed: 1505 // compact the code. 1506 if (varDebugInfo) { 1507 adjustAliveRanges(cp, -3); 1508 } 1509 cp = cp - 3; 1510 target = target - 3; 1511 if (chain.next == null) { 1512 // This is the only jump to the target. Exit the loop 1513 // without setting new state. The code is reachable 1514 // from the instruction before goto_. 1515 alive = true; 1516 break; 1517 } 1518 } else { 1519 if (fatcode) 1520 put4(chain.pc + 1, target - chain.pc); 1521 else if (target - chain.pc < Short.MIN_VALUE || 1522 target - chain.pc > Short.MAX_VALUE) 1523 fatcode = true; 1524 else 1525 put2(chain.pc + 1, target - chain.pc); 1526 Assert.check(!alive || 1527 chain.state.stacksize == newState.stacksize && 1528 chain.state.nlocks == newState.nlocks); 1529 } 1530 fixedPc = true; 1531 if (cp == target) { 1532 changed = true; 1533 if (debugCode) 1534 System.err.println("resolving chain state=" + chain.state); 1535 if (alive) { 1536 newState = chain.state.join(newState); 1537 } else { 1538 newState = chain.state; 1539 alive = true; 1540 } 1541 } 1542 } 1543 Assert.check(!changed || state != newState); 1544 if (state != newState) { 1545 setDefined(newState.defined); 1546 state = newState; 1547 pendingStackMap = needStackMap; 1548 } 1549 } 1550 1551 /** Resolve chain to point to current code pointer. 1552 */ 1553 public void resolve(Chain chain) { 1554 Assert.check( 1555 !alive || 1556 chain==null || 1557 state.stacksize == chain.state.stacksize && 1558 state.nlocks == chain.state.nlocks); 1559 pendingJumps = mergeChains(chain, pendingJumps); 1560 } 1561 1562 /** Resolve any pending jumps. 1563 */ 1564 public void resolvePending() { 1565 Chain x = pendingJumps; 1566 pendingJumps = null; 1567 resolve(x, cp); 1568 } 1569 1570 /** Merge the jumps in of two chains into one. 1571 */ 1572 public static Chain mergeChains(Chain chain1, Chain chain2) { 1573 // recursive merge sort 1574 if (chain2 == null) return chain1; 1575 if (chain1 == null) return chain2; 1576 Assert.check( 1577 chain1.state.stacksize == chain2.state.stacksize && 1578 chain1.state.nlocks == chain2.state.nlocks); 1579 if (chain1.pc < chain2.pc) 1580 return new Chain( 1581 chain2.pc, 1582 mergeChains(chain1, chain2.next), 1583 chain2.state); 1584 return new Chain( 1585 chain1.pc, 1586 mergeChains(chain1.next, chain2), 1587 chain1.state); 1588 } 1589 1590 1591 /* ************************************************************************** 1592 * Catch clauses 1593 ****************************************************************************/ 1594 1595 /** Add a catch clause to code. 1596 */ 1597 public void addCatch(char startPc, char endPc, 1598 char handlerPc, char catchType) { 1599 catchInfo.append(new char[]{startPc, endPc, handlerPc, catchType}); 1600 } 1601 1602 1603 public void compressCatchTable() { 1604 ListBuffer<char[]> compressedCatchInfo = new ListBuffer<>(); 1605 List<Integer> handlerPcs = List.nil(); 1606 for (char[] catchEntry : catchInfo) { 1607 handlerPcs = handlerPcs.prepend((int)catchEntry[2]); 1608 } 1609 for (char[] catchEntry : catchInfo) { 1610 int startpc = catchEntry[0]; 1611 int endpc = catchEntry[1]; 1612 if (startpc == endpc || 1613 (startpc == (endpc - 1) && 1614 handlerPcs.contains(startpc))) { 1615 continue; 1616 } else { 1617 compressedCatchInfo.append(catchEntry); 1618 } 1619 } 1620 catchInfo = compressedCatchInfo; 1621 } 1622 1623 1624 /* ************************************************************************** 1625 * Line numbers 1626 ****************************************************************************/ 1627 1628 /** Add a line number entry. 1629 */ 1630 public void addLineNumber(char startPc, char lineNumber) { 1631 if (lineDebugInfo) { 1632 if (lineInfo.nonEmpty() && lineInfo.head[0] == startPc) 1633 lineInfo = lineInfo.tail; 1634 if (lineInfo.isEmpty() || lineInfo.head[1] != lineNumber) 1635 lineInfo = lineInfo.prepend(new char[]{startPc, lineNumber}); 1636 } 1637 } 1638 1639 /** Mark beginning of statement. 1640 */ 1641 public void statBegin(int pos) { 1642 if (pos != Position.NOPOS) { 1643 pendingStatPos = pos; 1644 } 1645 } 1646 1647 /** Force stat begin eagerly 1648 */ 1649 public void markStatBegin() { 1650 if (alive && lineDebugInfo) { 1651 int line = lineMap.getLineNumber(pendingStatPos); 1652 char cp1 = (char)cp; 1653 char line1 = (char)line; 1654 if (cp1 == cp && line1 == line) 1655 addLineNumber(cp1, line1); 1656 } 1657 pendingStatPos = Position.NOPOS; 1658 } 1659 1660 1661 /* ************************************************************************** 1662 * Simulated VM machine state 1663 ****************************************************************************/ 1664 1665 class State implements Cloneable { 1666 /** The set of registers containing values. */ 1667 Bits defined; 1668 1669 /** The (types of the) contents of the machine stack. */ 1670 Type[] stack; 1671 1672 /** The first stack position currently unused. */ 1673 int stacksize; 1674 1675 /** The numbers of registers containing locked monitors. */ 1676 int[] locks; 1677 int nlocks; 1678 1679 State() { 1680 defined = new Bits(); 1681 stack = new Type[16]; 1682 } 1683 1684 State dup() { 1685 try { 1686 State state = (State)super.clone(); 1687 state.defined = new Bits(defined); 1688 state.stack = stack.clone(); 1689 if (locks != null) state.locks = locks.clone(); 1690 if (debugCode) { 1691 System.err.println("duping state " + this); 1692 dump(); 1693 } 1694 return state; 1695 } catch (CloneNotSupportedException ex) { 1696 throw new AssertionError(ex); 1697 } 1698 } 1699 1700 void lock(int register) { 1701 if (locks == null) { 1702 locks = new int[20]; 1703 } else { 1704 locks = ArrayUtils.ensureCapacity(locks, nlocks); 1705 } 1706 locks[nlocks] = register; 1707 nlocks++; 1708 } 1709 1710 void unlock(int register) { 1711 nlocks--; 1712 Assert.check(locks[nlocks] == register); 1713 locks[nlocks] = -1; 1714 } 1715 1716 void push(Type t) { 1717 if (debugCode) System.err.println(" pushing " + t); 1718 switch (t.getTag()) { 1719 case VOID: 1720 return; 1721 case BYTE: 1722 case CHAR: 1723 case SHORT: 1724 case BOOLEAN: 1725 t = syms.intType; 1726 break; 1727 default: 1728 break; 1729 } 1730 stack = ArrayUtils.ensureCapacity(stack, stacksize+2); 1731 stack[stacksize++] = t; 1732 switch (width(t)) { 1733 case 1: 1734 break; 1735 case 2: 1736 stack[stacksize++] = null; 1737 break; 1738 default: 1739 throw new AssertionError(t); 1740 } 1741 if (stacksize > max_stack) 1742 max_stack = stacksize; 1743 } 1744 1745 Type pop1() { 1746 if (debugCode) System.err.println(" popping " + 1); 1747 stacksize--; 1748 Type result = stack[stacksize]; 1749 stack[stacksize] = null; 1750 Assert.check(result != null && width(result) == 1); 1751 return result; 1752 } 1753 1754 Type peek() { 1755 return stack[stacksize-1]; 1756 } 1757 1758 Type pop2() { 1759 if (debugCode) System.err.println(" popping " + 2); 1760 stacksize -= 2; 1761 Type result = stack[stacksize]; 1762 stack[stacksize] = null; 1763 Assert.check(stack[stacksize+1] == null 1764 && result != null && width(result) == 2); 1765 return result; 1766 } 1767 1768 void pop(int n) { 1769 if (debugCode) System.err.println(" popping " + n); 1770 while (n > 0) { 1771 stack[--stacksize] = null; 1772 n--; 1773 } 1774 } 1775 1776 void pop(Type t) { 1777 pop(width(t)); 1778 } 1779 1780 /** Force the top of the stack to be treated as this supertype 1781 * of its current type. */ 1782 void forceStackTop(Type t) { 1783 if (!alive) return; 1784 switch (t.getTag()) { 1785 case CLASS: 1786 case ARRAY: 1787 int width = width(t); 1788 Type old = stack[stacksize-width]; 1789 Assert.check(types.isSubtype(types.erasure(old), 1790 types.erasure(t))); 1791 stack[stacksize-width] = t; 1792 break; 1793 default: 1794 } 1795 } 1796 1797 void markInitialized(UninitializedType old) { 1798 Type newtype = old.initializedType(); 1799 for (int i=0; i<stacksize; i++) { 1800 if (stack[i] == old) stack[i] = newtype; 1801 } 1802 for (int i=0; i<lvar.length; i++) { 1803 LocalVar lv = lvar[i]; 1804 if (lv != null && lv.sym.type == old) { 1805 VarSymbol sym = lv.sym; 1806 sym = sym.clone(sym.owner); 1807 sym.type = newtype; 1808 LocalVar newlv = lvar[i] = new LocalVar(sym); 1809 newlv.aliveRanges = lv.aliveRanges; 1810 } 1811 } 1812 } 1813 1814 State join(State other) { 1815 defined.andSet(other.defined); 1816 Assert.check(stacksize == other.stacksize 1817 && nlocks == other.nlocks); 1818 for (int i=0; i<stacksize; ) { 1819 Type t = stack[i]; 1820 Type tother = other.stack[i]; 1821 Type result = 1822 t==tother ? t : 1823 types.isSubtype(t, tother) ? tother : 1824 types.isSubtype(tother, t) ? t : 1825 error(); 1826 int w = width(result); 1827 stack[i] = result; 1828 if (w == 2) Assert.checkNull(stack[i+1]); 1829 i += w; 1830 } 1831 return this; 1832 } 1833 1834 Type error() { 1835 throw new AssertionError("inconsistent stack types at join point"); 1836 } 1837 1838 void dump() { 1839 dump(-1); 1840 } 1841 1842 void dump(int pc) { 1843 System.err.print("stackMap for " + meth.owner + "." + meth); 1844 if (pc == -1) 1845 System.out.println(); 1846 else 1847 System.out.println(" at " + pc); 1848 System.err.println(" stack (from bottom):"); 1849 for (int i=0; i<stacksize; i++) 1850 System.err.println(" " + i + ": " + stack[i]); 1851 1852 int lastLocal = 0; 1853 for (int i=max_locals-1; i>=0; i--) { 1854 if (defined.isMember(i)) { 1855 lastLocal = i; 1856 break; 1857 } 1858 } 1859 if (lastLocal >= 0) 1860 System.err.println(" locals:"); 1861 for (int i=0; i<=lastLocal; i++) { 1862 System.err.print(" " + i + ": "); 1863 if (defined.isMember(i)) { 1864 LocalVar var = lvar[i]; 1865 if (var == null) { 1866 System.err.println("(none)"); 1867 } else if (var.sym == null) 1868 System.err.println("UNKNOWN!"); 1869 else 1870 System.err.println("" + var.sym + " of type " + 1871 var.sym.erasure(types)); 1872 } else { 1873 System.err.println("undefined"); 1874 } 1875 } 1876 if (nlocks != 0) { 1877 System.err.print(" locks:"); 1878 for (int i=0; i<nlocks; i++) { 1879 System.err.print(" " + locks[i]); 1880 } 1881 System.err.println(); 1882 } 1883 } 1884 } 1885 1886 static final Type jsrReturnValue = new JCPrimitiveType(INT, null); 1887 1888 1889 /* ************************************************************************** 1890 * Local variables 1891 ****************************************************************************/ 1892 1893 /** A live range of a local variable. */ 1894 static class LocalVar { 1895 final VarSymbol sym; 1896 final char reg; 1897 1898 class Range { 1899 char start_pc = Character.MAX_VALUE; 1900 char length = Character.MAX_VALUE; 1901 1902 Range() {} 1903 1904 Range(char start) { 1905 this.start_pc = start; 1906 } 1907 1908 Range(char start, char length) { 1909 this.start_pc = start; 1910 this.length = length; 1911 } 1912 1913 boolean closed() { 1914 return start_pc != Character.MAX_VALUE && length != Character.MAX_VALUE; 1915 } 1916 1917 @Override 1918 public String toString() { 1919 int currentStartPC = start_pc; 1920 int currentLength = length; 1921 return "startpc = " + currentStartPC + " length " + currentLength; 1922 } 1923 } 1924 1925 java.util.List<Range> aliveRanges = new java.util.ArrayList<>(); 1926 1927 LocalVar(VarSymbol v) { 1928 this.sym = v; 1929 this.reg = (char)v.adr; 1930 } 1931 public LocalVar dup() { 1932 return new LocalVar(sym); 1933 } 1934 1935 Range firstRange() { 1936 return aliveRanges.isEmpty() ? null : aliveRanges.get(0); 1937 } 1938 1939 Range lastRange() { 1940 return aliveRanges.isEmpty() ? null : aliveRanges.get(aliveRanges.size() - 1); 1941 } 1942 1943 void removeLastRange() { 1944 Range lastRange = lastRange(); 1945 if (lastRange != null) { 1946 aliveRanges.remove(lastRange); 1947 } 1948 } 1949 1950 @Override 1951 public String toString() { 1952 if (aliveRanges == null) { 1953 return "empty local var"; 1954 } 1955 StringBuilder sb = new StringBuilder().append(sym) 1956 .append(" in register ").append((int)reg).append(" \n"); 1957 for (Range r : aliveRanges) { 1958 sb.append(" starts at pc=").append(Integer.toString(((int)r.start_pc))) 1959 .append(" length=").append(Integer.toString(((int)r.length))) 1960 .append("\n"); 1961 } 1962 return sb.toString(); 1963 } 1964 1965 public void openRange(char start) { 1966 if (!hasOpenRange()) { 1967 aliveRanges.add(new Range(start)); 1968 } 1969 } 1970 1971 public void closeRange(char length) { 1972 if (isLastRangeInitialized() && length > 0) { 1973 Range range = lastRange(); 1974 if (range != null) { 1975 if (range.length == Character.MAX_VALUE) { 1976 range.length = length; 1977 } 1978 } 1979 } else { 1980 removeLastRange(); 1981 } 1982 } 1983 1984 public boolean hasOpenRange() { 1985 if (aliveRanges.isEmpty()) { 1986 return false; 1987 } 1988 return lastRange().length == Character.MAX_VALUE; 1989 } 1990 1991 public boolean isLastRangeInitialized() { 1992 if (aliveRanges.isEmpty()) { 1993 return false; 1994 } 1995 return lastRange().start_pc != Character.MAX_VALUE; 1996 } 1997 1998 public Range getWidestRange() { 1999 if (aliveRanges.isEmpty()) { 2000 return new Range(); 2001 } else { 2002 Range firstRange = firstRange(); 2003 Range lastRange = lastRange(); 2004 char length = (char)(lastRange.length + (lastRange.start_pc - firstRange.start_pc)); 2005 return new Range(firstRange.start_pc, length); 2006 } 2007 } 2008 2009 } 2010 2011 /** Local variables, indexed by register. */ 2012 LocalVar[] lvar; 2013 2014 /** Add a new local variable. */ 2015 private void addLocalVar(VarSymbol v) { 2016 int adr = v.adr; 2017 lvar = ArrayUtils.ensureCapacity(lvar, adr+1); 2018 Assert.checkNull(lvar[adr]); 2019 if (pendingJumps != null) { 2020 resolvePending(); 2021 } 2022 lvar[adr] = new LocalVar(v); 2023 state.defined.excl(adr); 2024 } 2025 2026 void adjustAliveRanges(int oldCP, int delta) { 2027 for (LocalVar localVar: lvar) { 2028 if (localVar != null) { 2029 for (LocalVar.Range range: localVar.aliveRanges) { 2030 if (range.closed() && range.start_pc + range.length >= oldCP) { 2031 range.length += delta; 2032 } 2033 } 2034 } 2035 } 2036 } 2037 2038 /** 2039 * Calculates the size of the LocalVariableTable. 2040 */ 2041 public int getLVTSize() { 2042 int result = varBufferSize; 2043 for (int i = 0; i < varBufferSize; i++) { 2044 LocalVar var = varBuffer[i]; 2045 result += var.aliveRanges.size() - 1; 2046 } 2047 return result; 2048 } 2049 2050 /** Set the current variable defined state. */ 2051 public void setDefined(Bits newDefined) { 2052 if (alive && newDefined != state.defined) { 2053 Bits diff = new Bits(state.defined).xorSet(newDefined); 2054 for (int adr = diff.nextBit(0); 2055 adr >= 0; 2056 adr = diff.nextBit(adr+1)) { 2057 if (adr >= nextreg) 2058 state.defined.excl(adr); 2059 else if (state.defined.isMember(adr)) 2060 setUndefined(adr); 2061 else 2062 setDefined(adr); 2063 } 2064 } 2065 } 2066 2067 /** Mark a register as being (possibly) defined. */ 2068 public void setDefined(int adr) { 2069 LocalVar v = lvar[adr]; 2070 if (v == null) { 2071 state.defined.excl(adr); 2072 } else { 2073 state.defined.incl(adr); 2074 if (cp < Character.MAX_VALUE) { 2075 v.openRange((char)cp); 2076 } 2077 } 2078 } 2079 2080 /** Mark a register as being undefined. */ 2081 public void setUndefined(int adr) { 2082 state.defined.excl(adr); 2083 if (adr < lvar.length && 2084 lvar[adr] != null && 2085 lvar[adr].isLastRangeInitialized()) { 2086 LocalVar v = lvar[adr]; 2087 char length = (char)(curCP() - v.lastRange().start_pc); 2088 if (length < Character.MAX_VALUE) { 2089 lvar[adr] = v.dup(); 2090 v.closeRange(length); 2091 putVar(v); 2092 } else { 2093 v.removeLastRange(); 2094 } 2095 } 2096 } 2097 2098 /** End the scope of a variable. */ 2099 private void endScope(int adr) { 2100 LocalVar v = lvar[adr]; 2101 if (v != null) { 2102 if (v.isLastRangeInitialized()) { 2103 char length = (char)(curCP() - v.lastRange().start_pc); 2104 if (length < Character.MAX_VALUE) { 2105 v.closeRange(length); 2106 putVar(v); 2107 fillLocalVarPosition(v); 2108 } 2109 } 2110 /** the call to curCP() can implicitly adjust the current cp, if so 2111 * the alive range of local variables may be modified. Thus we need 2112 * all of them. For this reason assigning null to the given address 2113 * should be the last action to do. 2114 */ 2115 lvar[adr] = null; 2116 } 2117 state.defined.excl(adr); 2118 } 2119 2120 private void fillLocalVarPosition(LocalVar lv) { 2121 if (lv == null || lv.sym == null || !lv.sym.hasTypeAnnotations()) 2122 return; 2123 for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) { 2124 TypeAnnotationPosition p = ta.position; 2125 LocalVar.Range widestRange = lv.getWidestRange(); 2126 p.lvarOffset = new int[] { (int)widestRange.start_pc }; 2127 p.lvarLength = new int[] { (int)widestRange.length }; 2128 p.lvarIndex = new int[] { (int)lv.reg }; 2129 p.isValidOffset = true; 2130 } 2131 } 2132 2133 // Method to be called after compressCatchTable to 2134 // fill in the exception table index for type 2135 // annotations on exception parameters. 2136 public void fillExceptionParameterPositions() { 2137 for (int i = 0; i < varBufferSize; ++i) { 2138 LocalVar lv = varBuffer[i]; 2139 if (lv == null || lv.sym == null 2140 || !lv.sym.hasTypeAnnotations() 2141 || !lv.sym.isExceptionParameter()) 2142 continue; 2143 2144 for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) { 2145 TypeAnnotationPosition p = ta.position; 2146 if (p.hasCatchType()) { 2147 final int idx = findExceptionIndex(p); 2148 if (idx == -1) 2149 Assert.error("Could not find exception index for type annotation " + 2150 ta + " on exception parameter"); 2151 p.setExceptionIndex(idx); 2152 } 2153 } 2154 } 2155 } 2156 2157 private int findExceptionIndex(TypeAnnotationPosition p) { 2158 final int catchType = p.getCatchType(); 2159 final int startPos = p.getStartPos(); 2160 final int len = catchInfo.length(); 2161 List<char[]> iter = catchInfo.toList(); 2162 for (int i = 0; i < len; ++i) { 2163 char[] catchEntry = iter.head; 2164 iter = iter.tail; 2165 int ct = catchEntry[3]; 2166 int sp = catchEntry[0]; 2167 if (catchType == ct && sp == startPos) { 2168 return i; 2169 } 2170 } 2171 return -1; 2172 } 2173 2174 /** Put a live variable range into the buffer to be output to the 2175 * class file. 2176 */ 2177 void putVar(LocalVar var) { 2178 // Keep local variables if 2179 // 1) we need them for debug information 2180 // 2) it is an exception type and it contains type annotations 2181 boolean keepLocalVariables = varDebugInfo || 2182 (var.sym.isExceptionParameter() && var.sym.hasTypeAnnotations()); 2183 if (!keepLocalVariables) return; 2184 //don't keep synthetic vars, unless they are lambda method parameters 2185 boolean ignoredSyntheticVar = (var.sym.flags() & Flags.SYNTHETIC) != 0 && 2186 ((var.sym.owner.flags() & Flags.LAMBDA_METHOD) == 0 || 2187 (var.sym.flags() & Flags.PARAMETER) == 0); 2188 if (ignoredSyntheticVar) return; 2189 if (varBuffer == null) 2190 varBuffer = new LocalVar[20]; 2191 else 2192 varBuffer = ArrayUtils.ensureCapacity(varBuffer, varBufferSize); 2193 varBuffer[varBufferSize++] = var; 2194 } 2195 2196 /** Previously live local variables, to be put into the variable table. */ 2197 LocalVar[] varBuffer; 2198 int varBufferSize; 2199 2200 /** Create a new local variable address and return it. 2201 */ 2202 private int newLocal(int typecode) { 2203 int reg = nextreg; 2204 int w = width(typecode); 2205 nextreg = reg + w; 2206 if (nextreg > max_locals) max_locals = nextreg; 2207 return reg; 2208 } 2209 2210 private int newLocal(Type type) { 2211 return newLocal(typecode(type)); 2212 } 2213 2214 public int newLocal(VarSymbol v) { 2215 int reg = v.adr = newLocal(v.erasure(types)); 2216 addLocalVar(v); 2217 return reg; 2218 } 2219 2220 /** Start a set of fresh registers. 2221 */ 2222 public void newRegSegment() { 2223 nextreg = max_locals; 2224 } 2225 2226 /** End scopes of all variables with registers ≥ first. 2227 */ 2228 public void endScopes(int first) { 2229 int prevNextReg = nextreg; 2230 nextreg = first; 2231 for (int i = nextreg; i < prevNextReg; i++) endScope(i); 2232 } 2233 2234 /************************************************************************** 2235 * static tables 2236 *************************************************************************/ 2237 2238 public static String mnem(int opcode) { 2239 return Mneumonics.mnem[opcode]; 2240 } 2241 2242 private static class Mneumonics { 2243 private final static String[] mnem = new String[ByteCodeCount]; 2244 static { 2245 mnem[nop] = "nop"; 2246 mnem[aconst_null] = "aconst_null"; 2247 mnem[iconst_m1] = "iconst_m1"; 2248 mnem[iconst_0] = "iconst_0"; 2249 mnem[iconst_1] = "iconst_1"; 2250 mnem[iconst_2] = "iconst_2"; 2251 mnem[iconst_3] = "iconst_3"; 2252 mnem[iconst_4] = "iconst_4"; 2253 mnem[iconst_5] = "iconst_5"; 2254 mnem[lconst_0] = "lconst_0"; 2255 mnem[lconst_1] = "lconst_1"; 2256 mnem[fconst_0] = "fconst_0"; 2257 mnem[fconst_1] = "fconst_1"; 2258 mnem[fconst_2] = "fconst_2"; 2259 mnem[dconst_0] = "dconst_0"; 2260 mnem[dconst_1] = "dconst_1"; 2261 mnem[bipush] = "bipush"; 2262 mnem[sipush] = "sipush"; 2263 mnem[ldc1] = "ldc1"; 2264 mnem[ldc2] = "ldc2"; 2265 mnem[ldc2w] = "ldc2w"; 2266 mnem[iload] = "iload"; 2267 mnem[lload] = "lload"; 2268 mnem[fload] = "fload"; 2269 mnem[dload] = "dload"; 2270 mnem[aload] = "aload"; 2271 mnem[iload_0] = "iload_0"; 2272 mnem[lload_0] = "lload_0"; 2273 mnem[fload_0] = "fload_0"; 2274 mnem[dload_0] = "dload_0"; 2275 mnem[aload_0] = "aload_0"; 2276 mnem[iload_1] = "iload_1"; 2277 mnem[lload_1] = "lload_1"; 2278 mnem[fload_1] = "fload_1"; 2279 mnem[dload_1] = "dload_1"; 2280 mnem[aload_1] = "aload_1"; 2281 mnem[iload_2] = "iload_2"; 2282 mnem[lload_2] = "lload_2"; 2283 mnem[fload_2] = "fload_2"; 2284 mnem[dload_2] = "dload_2"; 2285 mnem[aload_2] = "aload_2"; 2286 mnem[iload_3] = "iload_3"; 2287 mnem[lload_3] = "lload_3"; 2288 mnem[fload_3] = "fload_3"; 2289 mnem[dload_3] = "dload_3"; 2290 mnem[aload_3] = "aload_3"; 2291 mnem[iaload] = "iaload"; 2292 mnem[laload] = "laload"; 2293 mnem[faload] = "faload"; 2294 mnem[daload] = "daload"; 2295 mnem[aaload] = "aaload"; 2296 mnem[baload] = "baload"; 2297 mnem[caload] = "caload"; 2298 mnem[saload] = "saload"; 2299 mnem[istore] = "istore"; 2300 mnem[lstore] = "lstore"; 2301 mnem[fstore] = "fstore"; 2302 mnem[dstore] = "dstore"; 2303 mnem[astore] = "astore"; 2304 mnem[istore_0] = "istore_0"; 2305 mnem[lstore_0] = "lstore_0"; 2306 mnem[fstore_0] = "fstore_0"; 2307 mnem[dstore_0] = "dstore_0"; 2308 mnem[astore_0] = "astore_0"; 2309 mnem[istore_1] = "istore_1"; 2310 mnem[lstore_1] = "lstore_1"; 2311 mnem[fstore_1] = "fstore_1"; 2312 mnem[dstore_1] = "dstore_1"; 2313 mnem[astore_1] = "astore_1"; 2314 mnem[istore_2] = "istore_2"; 2315 mnem[lstore_2] = "lstore_2"; 2316 mnem[fstore_2] = "fstore_2"; 2317 mnem[dstore_2] = "dstore_2"; 2318 mnem[astore_2] = "astore_2"; 2319 mnem[istore_3] = "istore_3"; 2320 mnem[lstore_3] = "lstore_3"; 2321 mnem[fstore_3] = "fstore_3"; 2322 mnem[dstore_3] = "dstore_3"; 2323 mnem[astore_3] = "astore_3"; 2324 mnem[iastore] = "iastore"; 2325 mnem[lastore] = "lastore"; 2326 mnem[fastore] = "fastore"; 2327 mnem[dastore] = "dastore"; 2328 mnem[aastore] = "aastore"; 2329 mnem[bastore] = "bastore"; 2330 mnem[castore] = "castore"; 2331 mnem[sastore] = "sastore"; 2332 mnem[pop] = "pop"; 2333 mnem[pop2] = "pop2"; 2334 mnem[dup] = "dup"; 2335 mnem[dup_x1] = "dup_x1"; 2336 mnem[dup_x2] = "dup_x2"; 2337 mnem[dup2] = "dup2"; 2338 mnem[dup2_x1] = "dup2_x1"; 2339 mnem[dup2_x2] = "dup2_x2"; 2340 mnem[swap] = "swap"; 2341 mnem[iadd] = "iadd"; 2342 mnem[ladd] = "ladd"; 2343 mnem[fadd] = "fadd"; 2344 mnem[dadd] = "dadd"; 2345 mnem[isub] = "isub"; 2346 mnem[lsub] = "lsub"; 2347 mnem[fsub] = "fsub"; 2348 mnem[dsub] = "dsub"; 2349 mnem[imul] = "imul"; 2350 mnem[lmul] = "lmul"; 2351 mnem[fmul] = "fmul"; 2352 mnem[dmul] = "dmul"; 2353 mnem[idiv] = "idiv"; 2354 mnem[ldiv] = "ldiv"; 2355 mnem[fdiv] = "fdiv"; 2356 mnem[ddiv] = "ddiv"; 2357 mnem[imod] = "imod"; 2358 mnem[lmod] = "lmod"; 2359 mnem[fmod] = "fmod"; 2360 mnem[dmod] = "dmod"; 2361 mnem[ineg] = "ineg"; 2362 mnem[lneg] = "lneg"; 2363 mnem[fneg] = "fneg"; 2364 mnem[dneg] = "dneg"; 2365 mnem[ishl] = "ishl"; 2366 mnem[lshl] = "lshl"; 2367 mnem[ishr] = "ishr"; 2368 mnem[lshr] = "lshr"; 2369 mnem[iushr] = "iushr"; 2370 mnem[lushr] = "lushr"; 2371 mnem[iand] = "iand"; 2372 mnem[land] = "land"; 2373 mnem[ior] = "ior"; 2374 mnem[lor] = "lor"; 2375 mnem[ixor] = "ixor"; 2376 mnem[lxor] = "lxor"; 2377 mnem[iinc] = "iinc"; 2378 mnem[i2l] = "i2l"; 2379 mnem[i2f] = "i2f"; 2380 mnem[i2d] = "i2d"; 2381 mnem[l2i] = "l2i"; 2382 mnem[l2f] = "l2f"; 2383 mnem[l2d] = "l2d"; 2384 mnem[f2i] = "f2i"; 2385 mnem[f2l] = "f2l"; 2386 mnem[f2d] = "f2d"; 2387 mnem[d2i] = "d2i"; 2388 mnem[d2l] = "d2l"; 2389 mnem[d2f] = "d2f"; 2390 mnem[int2byte] = "int2byte"; 2391 mnem[int2char] = "int2char"; 2392 mnem[int2short] = "int2short"; 2393 mnem[lcmp] = "lcmp"; 2394 mnem[fcmpl] = "fcmpl"; 2395 mnem[fcmpg] = "fcmpg"; 2396 mnem[dcmpl] = "dcmpl"; 2397 mnem[dcmpg] = "dcmpg"; 2398 mnem[ifeq] = "ifeq"; 2399 mnem[ifne] = "ifne"; 2400 mnem[iflt] = "iflt"; 2401 mnem[ifge] = "ifge"; 2402 mnem[ifgt] = "ifgt"; 2403 mnem[ifle] = "ifle"; 2404 mnem[if_icmpeq] = "if_icmpeq"; 2405 mnem[if_icmpne] = "if_icmpne"; 2406 mnem[if_icmplt] = "if_icmplt"; 2407 mnem[if_icmpge] = "if_icmpge"; 2408 mnem[if_icmpgt] = "if_icmpgt"; 2409 mnem[if_icmple] = "if_icmple"; 2410 mnem[if_acmpeq] = "if_acmpeq"; 2411 mnem[if_acmpne] = "if_acmpne"; 2412 mnem[goto_] = "goto_"; 2413 mnem[jsr] = "jsr"; 2414 mnem[ret] = "ret"; 2415 mnem[tableswitch] = "tableswitch"; 2416 mnem[lookupswitch] = "lookupswitch"; 2417 mnem[ireturn] = "ireturn"; 2418 mnem[lreturn] = "lreturn"; 2419 mnem[freturn] = "freturn"; 2420 mnem[dreturn] = "dreturn"; 2421 mnem[areturn] = "areturn"; 2422 mnem[return_] = "return_"; 2423 mnem[getstatic] = "getstatic"; 2424 mnem[putstatic] = "putstatic"; 2425 mnem[getfield] = "getfield"; 2426 mnem[putfield] = "putfield"; 2427 mnem[invokevirtual] = "invokevirtual"; 2428 mnem[invokespecial] = "invokespecial"; 2429 mnem[invokestatic] = "invokestatic"; 2430 mnem[invokeinterface] = "invokeinterface"; 2431 mnem[invokedynamic] = "invokedynamic"; 2432 mnem[new_] = "new_"; 2433 mnem[newarray] = "newarray"; 2434 mnem[anewarray] = "anewarray"; 2435 mnem[arraylength] = "arraylength"; 2436 mnem[athrow] = "athrow"; 2437 mnem[checkcast] = "checkcast"; 2438 mnem[instanceof_] = "instanceof_"; 2439 mnem[monitorenter] = "monitorenter"; 2440 mnem[monitorexit] = "monitorexit"; 2441 mnem[wide] = "wide"; 2442 mnem[multianewarray] = "multianewarray"; 2443 mnem[if_acmp_null] = "if_acmp_null"; 2444 mnem[if_acmp_nonnull] = "if_acmp_nonnull"; 2445 mnem[goto_w] = "goto_w"; 2446 mnem[jsr_w] = "jsr_w"; 2447 mnem[breakpoint] = "breakpoint"; 2448 mnem[vload] = "vload"; 2449 mnem[vstore] = "vstore"; 2450 mnem[vaload] = "vaload"; 2451 mnem[vastore] = "vastore"; 2452 mnem[vreturn] = "vreturn"; 2453 mnem[vdefault] = "vdefault"; 2454 mnem[vwithfield] = "vwithfield"; 2455 } 2456 } 2457 }