Code.java revision 2772:3bdbc3b8aa14
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 state.pop(1); 501 //sometimes 'null type' is treated as a one-dimensional array type 502 //see Gen.visitLiteral - we should handle this case accordingly 503 Type stackType = a.hasTag(BOT) ? 504 syms.objectType : 505 types.erasure(types.elemtype(a)); 506 state.push(stackType); } 507 break; 508 case goto_: 509 markDead(); 510 break; 511 case nop: 512 case ineg: 513 case lneg: 514 case fneg: 515 case dneg: 516 break; 517 case aconst_null: 518 state.push(syms.botType); 519 break; 520 case iconst_m1: 521 case iconst_0: 522 case iconst_1: 523 case iconst_2: 524 case iconst_3: 525 case iconst_4: 526 case iconst_5: 527 case iload_0: 528 case iload_1: 529 case iload_2: 530 case iload_3: 531 state.push(syms.intType); 532 break; 533 case lconst_0: 534 case lconst_1: 535 case lload_0: 536 case lload_1: 537 case lload_2: 538 case lload_3: 539 state.push(syms.longType); 540 break; 541 case fconst_0: 542 case fconst_1: 543 case fconst_2: 544 case fload_0: 545 case fload_1: 546 case fload_2: 547 case fload_3: 548 state.push(syms.floatType); 549 break; 550 case dconst_0: 551 case dconst_1: 552 case dload_0: 553 case dload_1: 554 case dload_2: 555 case dload_3: 556 state.push(syms.doubleType); 557 break; 558 case aload_0: 559 state.push(lvar[0].sym.type); 560 break; 561 case aload_1: 562 state.push(lvar[1].sym.type); 563 break; 564 case aload_2: 565 state.push(lvar[2].sym.type); 566 break; 567 case aload_3: 568 state.push(lvar[3].sym.type); 569 break; 570 case iaload: 571 case baload: 572 case caload: 573 case saload: 574 state.pop(2); 575 state.push(syms.intType); 576 break; 577 case laload: 578 state.pop(2); 579 state.push(syms.longType); 580 break; 581 case faload: 582 state.pop(2); 583 state.push(syms.floatType); 584 break; 585 case daload: 586 state.pop(2); 587 state.push(syms.doubleType); 588 break; 589 case istore_0: 590 case istore_1: 591 case istore_2: 592 case istore_3: 593 case fstore_0: 594 case fstore_1: 595 case fstore_2: 596 case fstore_3: 597 case astore_0: 598 case astore_1: 599 case astore_2: 600 case astore_3: 601 case pop: 602 case lshr: 603 case lshl: 604 case lushr: 605 state.pop(1); 606 break; 607 case areturn: 608 case ireturn: 609 case freturn: 610 Assert.check(state.nlocks == 0); 611 state.pop(1); 612 markDead(); 613 break; 614 case athrow: 615 state.pop(1); 616 markDead(); 617 break; 618 case lstore_0: 619 case lstore_1: 620 case lstore_2: 621 case lstore_3: 622 case dstore_0: 623 case dstore_1: 624 case dstore_2: 625 case dstore_3: 626 case pop2: 627 state.pop(2); 628 break; 629 case lreturn: 630 case dreturn: 631 Assert.check(state.nlocks == 0); 632 state.pop(2); 633 markDead(); 634 break; 635 case dup: 636 state.push(state.stack[state.stacksize-1]); 637 break; 638 case return_: 639 Assert.check(state.nlocks == 0); 640 markDead(); 641 break; 642 case arraylength: 643 state.pop(1); 644 state.push(syms.intType); 645 break; 646 case isub: 647 case iadd: 648 case imul: 649 case idiv: 650 case imod: 651 case ishl: 652 case ishr: 653 case iushr: 654 case iand: 655 case ior: 656 case ixor: 657 state.pop(1); 658 // state.pop(1); 659 // state.push(syms.intType); 660 break; 661 case aastore: 662 state.pop(3); 663 break; 664 case land: 665 case lor: 666 case lxor: 667 case lmod: 668 case ldiv: 669 case lmul: 670 case lsub: 671 case ladd: 672 state.pop(2); 673 break; 674 case lcmp: 675 state.pop(4); 676 state.push(syms.intType); 677 break; 678 case l2i: 679 state.pop(2); 680 state.push(syms.intType); 681 break; 682 case i2l: 683 state.pop(1); 684 state.push(syms.longType); 685 break; 686 case i2f: 687 state.pop(1); 688 state.push(syms.floatType); 689 break; 690 case i2d: 691 state.pop(1); 692 state.push(syms.doubleType); 693 break; 694 case l2f: 695 state.pop(2); 696 state.push(syms.floatType); 697 break; 698 case l2d: 699 state.pop(2); 700 state.push(syms.doubleType); 701 break; 702 case f2i: 703 state.pop(1); 704 state.push(syms.intType); 705 break; 706 case f2l: 707 state.pop(1); 708 state.push(syms.longType); 709 break; 710 case f2d: 711 state.pop(1); 712 state.push(syms.doubleType); 713 break; 714 case d2i: 715 state.pop(2); 716 state.push(syms.intType); 717 break; 718 case d2l: 719 state.pop(2); 720 state.push(syms.longType); 721 break; 722 case d2f: 723 state.pop(2); 724 state.push(syms.floatType); 725 break; 726 case tableswitch: 727 case lookupswitch: 728 state.pop(1); 729 // the caller is responsible for patching up the state 730 break; 731 case dup_x1: { 732 Type val1 = state.pop1(); 733 Type val2 = state.pop1(); 734 state.push(val1); 735 state.push(val2); 736 state.push(val1); 737 break; 738 } 739 case bastore: 740 state.pop(3); 741 break; 742 case int2byte: 743 case int2char: 744 case int2short: 745 break; 746 case fmul: 747 case fadd: 748 case fsub: 749 case fdiv: 750 case fmod: 751 state.pop(1); 752 break; 753 case castore: 754 case iastore: 755 case fastore: 756 case sastore: 757 state.pop(3); 758 break; 759 case lastore: 760 case dastore: 761 state.pop(4); 762 break; 763 case dup2: 764 if (state.stack[state.stacksize-1] != null) { 765 Type value1 = state.pop1(); 766 Type value2 = state.pop1(); 767 state.push(value2); 768 state.push(value1); 769 state.push(value2); 770 state.push(value1); 771 } else { 772 Type value = state.pop2(); 773 state.push(value); 774 state.push(value); 775 } 776 break; 777 case dup2_x1: 778 if (state.stack[state.stacksize-1] != null) { 779 Type value1 = state.pop1(); 780 Type value2 = state.pop1(); 781 Type value3 = state.pop1(); 782 state.push(value2); 783 state.push(value1); 784 state.push(value3); 785 state.push(value2); 786 state.push(value1); 787 } else { 788 Type value1 = state.pop2(); 789 Type value2 = state.pop1(); 790 state.push(value1); 791 state.push(value2); 792 state.push(value1); 793 } 794 break; 795 case dup2_x2: 796 if (state.stack[state.stacksize-1] != null) { 797 Type value1 = state.pop1(); 798 Type value2 = state.pop1(); 799 if (state.stack[state.stacksize-1] != null) { 800 // form 1 801 Type value3 = state.pop1(); 802 Type value4 = state.pop1(); 803 state.push(value2); 804 state.push(value1); 805 state.push(value4); 806 state.push(value3); 807 state.push(value2); 808 state.push(value1); 809 } else { 810 // form 3 811 Type value3 = state.pop2(); 812 state.push(value2); 813 state.push(value1); 814 state.push(value3); 815 state.push(value2); 816 state.push(value1); 817 } 818 } else { 819 Type value1 = state.pop2(); 820 if (state.stack[state.stacksize-1] != null) { 821 // form 2 822 Type value2 = state.pop1(); 823 Type value3 = state.pop1(); 824 state.push(value1); 825 state.push(value3); 826 state.push(value2); 827 state.push(value1); 828 } else { 829 // form 4 830 Type value2 = state.pop2(); 831 state.push(value1); 832 state.push(value2); 833 state.push(value1); 834 } 835 } 836 break; 837 case dup_x2: { 838 Type value1 = state.pop1(); 839 if (state.stack[state.stacksize-1] != null) { 840 // form 1 841 Type value2 = state.pop1(); 842 Type value3 = state.pop1(); 843 state.push(value1); 844 state.push(value3); 845 state.push(value2); 846 state.push(value1); 847 } else { 848 // form 2 849 Type value2 = state.pop2(); 850 state.push(value1); 851 state.push(value2); 852 state.push(value1); 853 } 854 } 855 break; 856 case fcmpl: 857 case fcmpg: 858 state.pop(2); 859 state.push(syms.intType); 860 break; 861 case dcmpl: 862 case dcmpg: 863 state.pop(4); 864 state.push(syms.intType); 865 break; 866 case swap: { 867 Type value1 = state.pop1(); 868 Type value2 = state.pop1(); 869 state.push(value1); 870 state.push(value2); 871 break; 872 } 873 case dadd: 874 case dsub: 875 case dmul: 876 case ddiv: 877 case dmod: 878 state.pop(2); 879 break; 880 case ret: 881 markDead(); 882 break; 883 case wide: 884 // must be handled by the caller. 885 return; 886 case monitorenter: 887 case monitorexit: 888 state.pop(1); 889 break; 890 891 default: 892 throw new AssertionError(mnem(op)); 893 } 894 postop(); 895 } 896 897 /** Emit an opcode with a one-byte operand field. 898 */ 899 public void emitop1(int op, int od) { 900 emitop(op); 901 if (!alive) return; 902 emit1(od); 903 switch (op) { 904 case bipush: 905 state.push(syms.intType); 906 break; 907 case ldc1: 908 state.push(typeForPool(pool.pool[od])); 909 break; 910 default: 911 throw new AssertionError(mnem(op)); 912 } 913 postop(); 914 } 915 916 /** The type of a constant pool entry. */ 917 private Type typeForPool(Object o) { 918 if (o instanceof Integer) return syms.intType; 919 if (o instanceof Float) return syms.floatType; 920 if (o instanceof String) return syms.stringType; 921 if (o instanceof Long) return syms.longType; 922 if (o instanceof Double) return syms.doubleType; 923 if (o instanceof ClassSymbol) return syms.classType; 924 if (o instanceof Pool.MethodHandle) return syms.methodHandleType; 925 if (o instanceof UniqueType) return typeForPool(((UniqueType)o).type); 926 if (o instanceof Type) { 927 Type ty = (Type) o; 928 929 if (ty instanceof Type.ArrayType) return syms.classType; 930 if (ty instanceof Type.MethodType) return syms.methodTypeType; 931 } 932 throw new AssertionError("Invalid type of constant pool entry: " + o.getClass()); 933 } 934 935 /** Emit an opcode with a one-byte operand field; 936 * widen if field does not fit in a byte. 937 */ 938 public void emitop1w(int op, int od) { 939 if (od > 0xFF) { 940 emitop(wide); 941 emitop(op); 942 emit2(od); 943 } else { 944 emitop(op); 945 emit1(od); 946 } 947 if (!alive) return; 948 switch (op) { 949 case iload: 950 state.push(syms.intType); 951 break; 952 case lload: 953 state.push(syms.longType); 954 break; 955 case fload: 956 state.push(syms.floatType); 957 break; 958 case dload: 959 state.push(syms.doubleType); 960 break; 961 case aload: 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 state.pop(1); 972 break; 973 case ret: 974 markDead(); 975 break; 976 default: 977 throw new AssertionError(mnem(op)); 978 } 979 postop(); 980 } 981 982 /** Emit an opcode with two one-byte operand fields; 983 * widen if either field does not fit in a byte. 984 */ 985 public void emitop1w(int op, int od1, int od2) { 986 if (od1 > 0xFF || od2 < -128 || od2 > 127) { 987 emitop(wide); 988 emitop(op); 989 emit2(od1); 990 emit2(od2); 991 } else { 992 emitop(op); 993 emit1(od1); 994 emit1(od2); 995 } 996 if (!alive) return; 997 switch (op) { 998 case iinc: 999 break; 1000 default: 1001 throw new AssertionError(mnem(op)); 1002 } 1003 } 1004 1005 /** Emit an opcode with a two-byte operand field. 1006 */ 1007 public void emitop2(int op, int od) { 1008 emitop(op); 1009 if (!alive) return; 1010 emit2(od); 1011 switch (op) { 1012 case getstatic: 1013 state.push(((Symbol)(pool.pool[od])).erasure(types)); 1014 break; 1015 case putstatic: 1016 state.pop(((Symbol)(pool.pool[od])).erasure(types)); 1017 break; 1018 case new_: 1019 Symbol sym; 1020 if (pool.pool[od] instanceof UniqueType) { 1021 // Required by change in Gen.makeRef to allow 1022 // annotated types. 1023 // TODO: is this needed anywhere else? 1024 sym = ((UniqueType)(pool.pool[od])).type.tsym; 1025 } else { 1026 sym = (Symbol)(pool.pool[od]); 1027 } 1028 state.push(uninitializedObject(sym.erasure(types), cp-3)); 1029 break; 1030 case sipush: 1031 state.push(syms.intType); 1032 break; 1033 case if_acmp_null: 1034 case if_acmp_nonnull: 1035 case ifeq: 1036 case ifne: 1037 case iflt: 1038 case ifge: 1039 case ifgt: 1040 case ifle: 1041 state.pop(1); 1042 break; 1043 case if_icmpeq: 1044 case if_icmpne: 1045 case if_icmplt: 1046 case if_icmpge: 1047 case if_icmpgt: 1048 case if_icmple: 1049 case if_acmpeq: 1050 case if_acmpne: 1051 state.pop(2); 1052 break; 1053 case goto_: 1054 markDead(); 1055 break; 1056 case putfield: 1057 state.pop(((Symbol)(pool.pool[od])).erasure(types)); 1058 state.pop(1); // object ref 1059 break; 1060 case getfield: 1061 state.pop(1); // object ref 1062 state.push(((Symbol)(pool.pool[od])).erasure(types)); 1063 break; 1064 case checkcast: { 1065 state.pop(1); // object ref 1066 Object o = pool.pool[od]; 1067 Type t = (o instanceof Symbol) 1068 ? ((Symbol)o).erasure(types) 1069 : types.erasure((((UniqueType)o).type)); 1070 state.push(t); 1071 break; } 1072 case ldc2w: 1073 state.push(typeForPool(pool.pool[od])); 1074 break; 1075 case instanceof_: 1076 state.pop(1); 1077 state.push(syms.intType); 1078 break; 1079 case ldc2: 1080 state.push(typeForPool(pool.pool[od])); 1081 break; 1082 case jsr: 1083 break; 1084 default: 1085 throw new AssertionError(mnem(op)); 1086 } 1087 // postop(); 1088 } 1089 1090 /** Emit an opcode with a four-byte operand field. 1091 */ 1092 public void emitop4(int op, int od) { 1093 emitop(op); 1094 if (!alive) return; 1095 emit4(od); 1096 switch (op) { 1097 case goto_w: 1098 markDead(); 1099 break; 1100 case jsr_w: 1101 break; 1102 default: 1103 throw new AssertionError(mnem(op)); 1104 } 1105 // postop(); 1106 } 1107 1108 /** Align code pointer to next `incr' boundary. 1109 */ 1110 public void align(int incr) { 1111 if (alive) 1112 while (cp % incr != 0) emitop0(nop); 1113 } 1114 1115 /** Place a byte into code at address pc. 1116 * Pre: {@literal pc + 1 <= cp }. 1117 */ 1118 private void put1(int pc, int op) { 1119 code[pc] = (byte)op; 1120 } 1121 1122 /** Place two bytes into code at address pc. 1123 * Pre: {@literal pc + 2 <= cp }. 1124 */ 1125 private void put2(int pc, int od) { 1126 // pre: pc + 2 <= cp 1127 put1(pc, od >> 8); 1128 put1(pc+1, od); 1129 } 1130 1131 /** Place four bytes into code at address pc. 1132 * Pre: {@literal pc + 4 <= cp }. 1133 */ 1134 public void put4(int pc, int od) { 1135 // pre: pc + 4 <= cp 1136 put1(pc , od >> 24); 1137 put1(pc+1, od >> 16); 1138 put1(pc+2, od >> 8); 1139 put1(pc+3, od); 1140 } 1141 1142 /** Return code byte at position pc as an unsigned int. 1143 */ 1144 private int get1(int pc) { 1145 return code[pc] & 0xFF; 1146 } 1147 1148 /** Return two code bytes at position pc as an unsigned int. 1149 */ 1150 private int get2(int pc) { 1151 return (get1(pc) << 8) | get1(pc+1); 1152 } 1153 1154 /** Return four code bytes at position pc as an int. 1155 */ 1156 public int get4(int pc) { 1157 // pre: pc + 4 <= cp 1158 return 1159 (get1(pc) << 24) | 1160 (get1(pc+1) << 16) | 1161 (get1(pc+2) << 8) | 1162 (get1(pc+3)); 1163 } 1164 1165 /** Is code generation currently enabled? 1166 */ 1167 public boolean isAlive() { 1168 return alive || pendingJumps != null; 1169 } 1170 1171 /** Switch code generation on/off. 1172 */ 1173 public void markDead() { 1174 alive = false; 1175 } 1176 1177 /** Declare an entry point; return current code pointer 1178 */ 1179 public int entryPoint() { 1180 int pc = curCP(); 1181 alive = true; 1182 pendingStackMap = needStackMap; 1183 return pc; 1184 } 1185 1186 /** Declare an entry point with initial state; 1187 * return current code pointer 1188 */ 1189 public int entryPoint(State state) { 1190 int pc = curCP(); 1191 alive = true; 1192 State newState = state.dup(); 1193 setDefined(newState.defined); 1194 this.state = newState; 1195 Assert.check(state.stacksize <= max_stack); 1196 if (debugCode) System.err.println("entry point " + state); 1197 pendingStackMap = needStackMap; 1198 return pc; 1199 } 1200 1201 /** Declare an entry point with initial state plus a pushed value; 1202 * return current code pointer 1203 */ 1204 public int entryPoint(State state, Type pushed) { 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 this.state.push(pushed); 1212 if (debugCode) System.err.println("entry point " + state); 1213 pendingStackMap = needStackMap; 1214 return pc; 1215 } 1216 1217 1218/************************************************************************** 1219 * Stack map generation 1220 *************************************************************************/ 1221 1222 /** An entry in the stack map. */ 1223 static class StackMapFrame { 1224 int pc; 1225 Type[] locals; 1226 Type[] stack; 1227 } 1228 1229 /** A buffer of cldc stack map entries. */ 1230 StackMapFrame[] stackMapBuffer = null; 1231 1232 /** A buffer of compressed StackMapTable entries. */ 1233 StackMapTableFrame[] stackMapTableBuffer = null; 1234 int stackMapBufferSize = 0; 1235 1236 /** The last PC at which we generated a stack map. */ 1237 int lastStackMapPC = -1; 1238 1239 /** The last stack map frame in StackMapTable. */ 1240 StackMapFrame lastFrame = null; 1241 1242 /** The stack map frame before the last one. */ 1243 StackMapFrame frameBeforeLast = null; 1244 1245 /** Emit a stack map entry. */ 1246 public void emitStackMap() { 1247 int pc = curCP(); 1248 if (!needStackMap) return; 1249 1250 1251 1252 switch (stackMap) { 1253 case CLDC: 1254 emitCLDCStackMap(pc, getLocalsSize()); 1255 break; 1256 case JSR202: 1257 emitStackMapFrame(pc, getLocalsSize()); 1258 break; 1259 default: 1260 throw new AssertionError("Should have chosen a stackmap format"); 1261 } 1262 // DEBUG code follows 1263 if (debugCode) state.dump(pc); 1264 } 1265 1266 private int getLocalsSize() { 1267 int nextLocal = 0; 1268 for (int i=max_locals-1; i>=0; i--) { 1269 if (state.defined.isMember(i) && lvar[i] != null) { 1270 nextLocal = i + width(lvar[i].sym.erasure(types)); 1271 break; 1272 } 1273 } 1274 return nextLocal; 1275 } 1276 1277 /** Emit a CLDC stack map frame. */ 1278 void emitCLDCStackMap(int pc, int localsSize) { 1279 if (lastStackMapPC == pc) { 1280 // drop existing stackmap at this offset 1281 stackMapBuffer[--stackMapBufferSize] = null; 1282 } 1283 lastStackMapPC = pc; 1284 1285 if (stackMapBuffer == null) { 1286 stackMapBuffer = new StackMapFrame[20]; 1287 } else { 1288 stackMapBuffer = ArrayUtils.ensureCapacity(stackMapBuffer, stackMapBufferSize); 1289 } 1290 StackMapFrame frame = 1291 stackMapBuffer[stackMapBufferSize++] = new StackMapFrame(); 1292 frame.pc = pc; 1293 1294 frame.locals = new Type[localsSize]; 1295 for (int i=0; i<localsSize; i++) { 1296 if (state.defined.isMember(i) && lvar[i] != null) { 1297 Type vtype = lvar[i].sym.type; 1298 if (!(vtype instanceof UninitializedType)) 1299 vtype = types.erasure(vtype); 1300 frame.locals[i] = vtype; 1301 } 1302 } 1303 frame.stack = new Type[state.stacksize]; 1304 for (int i=0; i<state.stacksize; i++) 1305 frame.stack[i] = state.stack[i]; 1306 } 1307 1308 void emitStackMapFrame(int pc, int localsSize) { 1309 if (lastFrame == null) { 1310 // first frame 1311 lastFrame = getInitialFrame(); 1312 } else if (lastFrame.pc == pc) { 1313 // drop existing stackmap at this offset 1314 stackMapTableBuffer[--stackMapBufferSize] = null; 1315 lastFrame = frameBeforeLast; 1316 frameBeforeLast = null; 1317 } 1318 1319 StackMapFrame frame = new StackMapFrame(); 1320 frame.pc = pc; 1321 1322 int localCount = 0; 1323 Type[] locals = new Type[localsSize]; 1324 for (int i=0; i<localsSize; i++, localCount++) { 1325 if (state.defined.isMember(i) && lvar[i] != null) { 1326 Type vtype = lvar[i].sym.type; 1327 if (!(vtype instanceof UninitializedType)) 1328 vtype = types.erasure(vtype); 1329 locals[i] = vtype; 1330 if (width(vtype) > 1) i++; 1331 } 1332 } 1333 frame.locals = new Type[localCount]; 1334 for (int i=0, j=0; i<localsSize; i++, j++) { 1335 Assert.check(j < localCount); 1336 frame.locals[j] = locals[i]; 1337 if (width(locals[i]) > 1) i++; 1338 } 1339 1340 int stackCount = 0; 1341 for (int i=0; i<state.stacksize; i++) { 1342 if (state.stack[i] != null) { 1343 stackCount++; 1344 } 1345 } 1346 frame.stack = new Type[stackCount]; 1347 stackCount = 0; 1348 for (int i=0; i<state.stacksize; i++) { 1349 if (state.stack[i] != null) { 1350 frame.stack[stackCount++] = types.erasure(state.stack[i]); 1351 } 1352 } 1353 1354 if (stackMapTableBuffer == null) { 1355 stackMapTableBuffer = new StackMapTableFrame[20]; 1356 } else { 1357 stackMapTableBuffer = ArrayUtils.ensureCapacity( 1358 stackMapTableBuffer, 1359 stackMapBufferSize); 1360 } 1361 stackMapTableBuffer[stackMapBufferSize++] = 1362 StackMapTableFrame.getInstance(frame, lastFrame.pc, lastFrame.locals, types); 1363 1364 frameBeforeLast = lastFrame; 1365 lastFrame = frame; 1366 } 1367 1368 StackMapFrame getInitialFrame() { 1369 StackMapFrame frame = new StackMapFrame(); 1370 List<Type> arg_types = ((MethodType)meth.externalType(types)).argtypes; 1371 int len = arg_types.length(); 1372 int count = 0; 1373 if (!meth.isStatic()) { 1374 Type thisType = meth.owner.type; 1375 frame.locals = new Type[len+1]; 1376 if (meth.isConstructor() && thisType != syms.objectType) { 1377 frame.locals[count++] = UninitializedType.uninitializedThis(thisType); 1378 } else { 1379 frame.locals[count++] = types.erasure(thisType); 1380 } 1381 } else { 1382 frame.locals = new Type[len]; 1383 } 1384 for (Type arg_type : arg_types) { 1385 frame.locals[count++] = types.erasure(arg_type); 1386 } 1387 frame.pc = -1; 1388 frame.stack = null; 1389 return frame; 1390 } 1391 1392 1393/************************************************************************** 1394 * Operations having to do with jumps 1395 *************************************************************************/ 1396 1397 /** A chain represents a list of unresolved jumps. Jump locations 1398 * are sorted in decreasing order. 1399 */ 1400 public static class Chain { 1401 1402 /** The position of the jump instruction. 1403 */ 1404 public final int pc; 1405 1406 /** The machine state after the jump instruction. 1407 * Invariant: all elements of a chain list have the same stacksize 1408 * and compatible stack and register contents. 1409 */ 1410 Code.State state; 1411 1412 /** The next jump in the list. 1413 */ 1414 public final Chain next; 1415 1416 /** Construct a chain from its jump position, stacksize, previous 1417 * chain, and machine state. 1418 */ 1419 public Chain(int pc, Chain next, Code.State state) { 1420 this.pc = pc; 1421 this.next = next; 1422 this.state = state; 1423 } 1424 } 1425 1426 /** Negate a branch opcode. 1427 */ 1428 public static int negate(int opcode) { 1429 if (opcode == if_acmp_null) return if_acmp_nonnull; 1430 else if (opcode == if_acmp_nonnull) return if_acmp_null; 1431 else return ((opcode + 1) ^ 1) - 1; 1432 } 1433 1434 /** Emit a jump instruction. 1435 * Return code pointer of instruction to be patched. 1436 */ 1437 public int emitJump(int opcode) { 1438 if (fatcode) { 1439 if (opcode == goto_ || opcode == jsr) { 1440 emitop4(opcode + goto_w - goto_, 0); 1441 } else { 1442 emitop2(negate(opcode), 8); 1443 emitop4(goto_w, 0); 1444 alive = true; 1445 pendingStackMap = needStackMap; 1446 } 1447 return cp - 5; 1448 } else { 1449 emitop2(opcode, 0); 1450 return cp - 3; 1451 } 1452 } 1453 1454 /** Emit a branch with given opcode; return its chain. 1455 * branch differs from jump in that jsr is treated as no-op. 1456 */ 1457 public Chain branch(int opcode) { 1458 Chain result = null; 1459 if (opcode == goto_) { 1460 result = pendingJumps; 1461 pendingJumps = null; 1462 } 1463 if (opcode != dontgoto && isAlive()) { 1464 result = new Chain(emitJump(opcode), 1465 result, 1466 state.dup()); 1467 fixedPc = fatcode; 1468 if (opcode == goto_) alive = false; 1469 } 1470 return result; 1471 } 1472 1473 /** Resolve chain to point to given target. 1474 */ 1475 public void resolve(Chain chain, int target) { 1476 boolean changed = false; 1477 State newState = state; 1478 for (; chain != null; chain = chain.next) { 1479 Assert.check(state != chain.state 1480 && (target > chain.pc || state.stacksize == 0)); 1481 if (target >= cp) { 1482 target = cp; 1483 } else if (get1(target) == goto_) { 1484 if (fatcode) target = target + get4(target + 1); 1485 else target = target + get2(target + 1); 1486 } 1487 if (get1(chain.pc) == goto_ && 1488 chain.pc + 3 == target && target == cp && !fixedPc) { 1489 // If goto the next instruction, the jump is not needed: 1490 // compact the code. 1491 if (varDebugInfo) { 1492 adjustAliveRanges(cp, -3); 1493 } 1494 cp = cp - 3; 1495 target = target - 3; 1496 if (chain.next == null) { 1497 // This is the only jump to the target. Exit the loop 1498 // without setting new state. The code is reachable 1499 // from the instruction before goto_. 1500 alive = true; 1501 break; 1502 } 1503 } else { 1504 if (fatcode) 1505 put4(chain.pc + 1, target - chain.pc); 1506 else if (target - chain.pc < Short.MIN_VALUE || 1507 target - chain.pc > Short.MAX_VALUE) 1508 fatcode = true; 1509 else 1510 put2(chain.pc + 1, target - chain.pc); 1511 Assert.check(!alive || 1512 chain.state.stacksize == newState.stacksize && 1513 chain.state.nlocks == newState.nlocks); 1514 } 1515 fixedPc = true; 1516 if (cp == target) { 1517 changed = true; 1518 if (debugCode) 1519 System.err.println("resolving chain state=" + chain.state); 1520 if (alive) { 1521 newState = chain.state.join(newState); 1522 } else { 1523 newState = chain.state; 1524 alive = true; 1525 } 1526 } 1527 } 1528 Assert.check(!changed || state != newState); 1529 if (state != newState) { 1530 setDefined(newState.defined); 1531 state = newState; 1532 pendingStackMap = needStackMap; 1533 } 1534 } 1535 1536 /** Resolve chain to point to current code pointer. 1537 */ 1538 public void resolve(Chain chain) { 1539 Assert.check( 1540 !alive || 1541 chain==null || 1542 state.stacksize == chain.state.stacksize && 1543 state.nlocks == chain.state.nlocks); 1544 pendingJumps = mergeChains(chain, pendingJumps); 1545 } 1546 1547 /** Resolve any pending jumps. 1548 */ 1549 public void resolvePending() { 1550 Chain x = pendingJumps; 1551 pendingJumps = null; 1552 resolve(x, cp); 1553 } 1554 1555 /** Merge the jumps in of two chains into one. 1556 */ 1557 public static Chain mergeChains(Chain chain1, Chain chain2) { 1558 // recursive merge sort 1559 if (chain2 == null) return chain1; 1560 if (chain1 == null) return chain2; 1561 Assert.check( 1562 chain1.state.stacksize == chain2.state.stacksize && 1563 chain1.state.nlocks == chain2.state.nlocks); 1564 if (chain1.pc < chain2.pc) 1565 return new Chain( 1566 chain2.pc, 1567 mergeChains(chain1, chain2.next), 1568 chain2.state); 1569 return new Chain( 1570 chain1.pc, 1571 mergeChains(chain1.next, chain2), 1572 chain1.state); 1573 } 1574 1575 1576/* ************************************************************************** 1577 * Catch clauses 1578 ****************************************************************************/ 1579 1580 /** Add a catch clause to code. 1581 */ 1582 public void addCatch(char startPc, char endPc, 1583 char handlerPc, char catchType) { 1584 catchInfo.append(new char[]{startPc, endPc, handlerPc, catchType}); 1585 } 1586 1587 1588 public void compressCatchTable() { 1589 ListBuffer<char[]> compressedCatchInfo = new ListBuffer<>(); 1590 List<Integer> handlerPcs = List.nil(); 1591 for (char[] catchEntry : catchInfo) { 1592 handlerPcs = handlerPcs.prepend((int)catchEntry[2]); 1593 } 1594 for (char[] catchEntry : catchInfo) { 1595 int startpc = catchEntry[0]; 1596 int endpc = catchEntry[1]; 1597 if (startpc == endpc || 1598 (startpc == (endpc - 1) && 1599 handlerPcs.contains(startpc))) { 1600 continue; 1601 } else { 1602 compressedCatchInfo.append(catchEntry); 1603 } 1604 } 1605 catchInfo = compressedCatchInfo; 1606 } 1607 1608 1609/* ************************************************************************** 1610 * Line numbers 1611 ****************************************************************************/ 1612 1613 /** Add a line number entry. 1614 */ 1615 public void addLineNumber(char startPc, char lineNumber) { 1616 if (lineDebugInfo) { 1617 if (lineInfo.nonEmpty() && lineInfo.head[0] == startPc) 1618 lineInfo = lineInfo.tail; 1619 if (lineInfo.isEmpty() || lineInfo.head[1] != lineNumber) 1620 lineInfo = lineInfo.prepend(new char[]{startPc, lineNumber}); 1621 } 1622 } 1623 1624 /** Mark beginning of statement. 1625 */ 1626 public void statBegin(int pos) { 1627 if (pos != Position.NOPOS) { 1628 pendingStatPos = pos; 1629 } 1630 } 1631 1632 /** Force stat begin eagerly 1633 */ 1634 public void markStatBegin() { 1635 if (alive && lineDebugInfo) { 1636 int line = lineMap.getLineNumber(pendingStatPos); 1637 char cp1 = (char)cp; 1638 char line1 = (char)line; 1639 if (cp1 == cp && line1 == line) 1640 addLineNumber(cp1, line1); 1641 } 1642 pendingStatPos = Position.NOPOS; 1643 } 1644 1645 1646/* ************************************************************************** 1647 * Simulated VM machine state 1648 ****************************************************************************/ 1649 1650 class State implements Cloneable { 1651 /** The set of registers containing values. */ 1652 Bits defined; 1653 1654 /** The (types of the) contents of the machine stack. */ 1655 Type[] stack; 1656 1657 /** The first stack position currently unused. */ 1658 int stacksize; 1659 1660 /** The numbers of registers containing locked monitors. */ 1661 int[] locks; 1662 int nlocks; 1663 1664 State() { 1665 defined = new Bits(); 1666 stack = new Type[16]; 1667 } 1668 1669 State dup() { 1670 try { 1671 State state = (State)super.clone(); 1672 state.defined = new Bits(defined); 1673 state.stack = stack.clone(); 1674 if (locks != null) state.locks = locks.clone(); 1675 if (debugCode) { 1676 System.err.println("duping state " + this); 1677 dump(); 1678 } 1679 return state; 1680 } catch (CloneNotSupportedException ex) { 1681 throw new AssertionError(ex); 1682 } 1683 } 1684 1685 void lock(int register) { 1686 if (locks == null) { 1687 locks = new int[20]; 1688 } else { 1689 locks = ArrayUtils.ensureCapacity(locks, nlocks); 1690 } 1691 locks[nlocks] = register; 1692 nlocks++; 1693 } 1694 1695 void unlock(int register) { 1696 nlocks--; 1697 Assert.check(locks[nlocks] == register); 1698 locks[nlocks] = -1; 1699 } 1700 1701 void push(Type t) { 1702 if (debugCode) System.err.println(" pushing " + t); 1703 switch (t.getTag()) { 1704 case VOID: 1705 return; 1706 case BYTE: 1707 case CHAR: 1708 case SHORT: 1709 case BOOLEAN: 1710 t = syms.intType; 1711 break; 1712 default: 1713 break; 1714 } 1715 stack = ArrayUtils.ensureCapacity(stack, stacksize+2); 1716 stack[stacksize++] = t; 1717 switch (width(t)) { 1718 case 1: 1719 break; 1720 case 2: 1721 stack[stacksize++] = null; 1722 break; 1723 default: 1724 throw new AssertionError(t); 1725 } 1726 if (stacksize > max_stack) 1727 max_stack = stacksize; 1728 } 1729 1730 Type pop1() { 1731 if (debugCode) System.err.println(" popping " + 1); 1732 stacksize--; 1733 Type result = stack[stacksize]; 1734 stack[stacksize] = null; 1735 Assert.check(result != null && width(result) == 1); 1736 return result; 1737 } 1738 1739 Type peek() { 1740 return stack[stacksize-1]; 1741 } 1742 1743 Type pop2() { 1744 if (debugCode) System.err.println(" popping " + 2); 1745 stacksize -= 2; 1746 Type result = stack[stacksize]; 1747 stack[stacksize] = null; 1748 Assert.check(stack[stacksize+1] == null 1749 && result != null && width(result) == 2); 1750 return result; 1751 } 1752 1753 void pop(int n) { 1754 if (debugCode) System.err.println(" popping " + n); 1755 while (n > 0) { 1756 stack[--stacksize] = null; 1757 n--; 1758 } 1759 } 1760 1761 void pop(Type t) { 1762 pop(width(t)); 1763 } 1764 1765 /** Force the top of the stack to be treated as this supertype 1766 * of its current type. */ 1767 void forceStackTop(Type t) { 1768 if (!alive) return; 1769 switch (t.getTag()) { 1770 case CLASS: 1771 case ARRAY: 1772 int width = width(t); 1773 Type old = stack[stacksize-width]; 1774 Assert.check(types.isSubtype(types.erasure(old), 1775 types.erasure(t))); 1776 stack[stacksize-width] = t; 1777 break; 1778 default: 1779 } 1780 } 1781 1782 void markInitialized(UninitializedType old) { 1783 Type newtype = old.initializedType(); 1784 for (int i=0; i<stacksize; i++) { 1785 if (stack[i] == old) stack[i] = newtype; 1786 } 1787 for (int i=0; i<lvar.length; i++) { 1788 LocalVar lv = lvar[i]; 1789 if (lv != null && lv.sym.type == old) { 1790 VarSymbol sym = lv.sym; 1791 sym = sym.clone(sym.owner); 1792 sym.type = newtype; 1793 LocalVar newlv = lvar[i] = new LocalVar(sym); 1794 newlv.aliveRanges = lv.aliveRanges; 1795 } 1796 } 1797 } 1798 1799 State join(State other) { 1800 defined.andSet(other.defined); 1801 Assert.check(stacksize == other.stacksize 1802 && nlocks == other.nlocks); 1803 for (int i=0; i<stacksize; ) { 1804 Type t = stack[i]; 1805 Type tother = other.stack[i]; 1806 Type result = 1807 t==tother ? t : 1808 types.isSubtype(t, tother) ? tother : 1809 types.isSubtype(tother, t) ? t : 1810 error(); 1811 int w = width(result); 1812 stack[i] = result; 1813 if (w == 2) Assert.checkNull(stack[i+1]); 1814 i += w; 1815 } 1816 return this; 1817 } 1818 1819 Type error() { 1820 throw new AssertionError("inconsistent stack types at join point"); 1821 } 1822 1823 void dump() { 1824 dump(-1); 1825 } 1826 1827 void dump(int pc) { 1828 System.err.print("stackMap for " + meth.owner + "." + meth); 1829 if (pc == -1) 1830 System.out.println(); 1831 else 1832 System.out.println(" at " + pc); 1833 System.err.println(" stack (from bottom):"); 1834 for (int i=0; i<stacksize; i++) 1835 System.err.println(" " + i + ": " + stack[i]); 1836 1837 int lastLocal = 0; 1838 for (int i=max_locals-1; i>=0; i--) { 1839 if (defined.isMember(i)) { 1840 lastLocal = i; 1841 break; 1842 } 1843 } 1844 if (lastLocal >= 0) 1845 System.err.println(" locals:"); 1846 for (int i=0; i<=lastLocal; i++) { 1847 System.err.print(" " + i + ": "); 1848 if (defined.isMember(i)) { 1849 LocalVar var = lvar[i]; 1850 if (var == null) { 1851 System.err.println("(none)"); 1852 } else if (var.sym == null) 1853 System.err.println("UNKNOWN!"); 1854 else 1855 System.err.println("" + var.sym + " of type " + 1856 var.sym.erasure(types)); 1857 } else { 1858 System.err.println("undefined"); 1859 } 1860 } 1861 if (nlocks != 0) { 1862 System.err.print(" locks:"); 1863 for (int i=0; i<nlocks; i++) { 1864 System.err.print(" " + locks[i]); 1865 } 1866 System.err.println(); 1867 } 1868 } 1869 } 1870 1871 static final Type jsrReturnValue = new JCPrimitiveType(INT, null); 1872 1873 1874/* ************************************************************************** 1875 * Local variables 1876 ****************************************************************************/ 1877 1878 /** A live range of a local variable. */ 1879 static class LocalVar { 1880 final VarSymbol sym; 1881 final char reg; 1882 1883 class Range { 1884 char start_pc = Character.MAX_VALUE; 1885 char length = Character.MAX_VALUE; 1886 1887 Range() {} 1888 1889 Range(char start) { 1890 this.start_pc = start; 1891 } 1892 1893 Range(char start, char length) { 1894 this.start_pc = start; 1895 this.length = length; 1896 } 1897 1898 boolean closed() { 1899 return start_pc != Character.MAX_VALUE && length != Character.MAX_VALUE; 1900 } 1901 1902 @Override 1903 public String toString() { 1904 int currentStartPC = start_pc; 1905 int currentLength = length; 1906 return "startpc = " + currentStartPC + " length " + currentLength; 1907 } 1908 } 1909 1910 java.util.List<Range> aliveRanges = new java.util.ArrayList<>(); 1911 1912 LocalVar(VarSymbol v) { 1913 this.sym = v; 1914 this.reg = (char)v.adr; 1915 } 1916 public LocalVar dup() { 1917 return new LocalVar(sym); 1918 } 1919 1920 Range firstRange() { 1921 return aliveRanges.isEmpty() ? null : aliveRanges.get(0); 1922 } 1923 1924 Range lastRange() { 1925 return aliveRanges.isEmpty() ? null : aliveRanges.get(aliveRanges.size() - 1); 1926 } 1927 1928 void removeLastRange() { 1929 Range lastRange = lastRange(); 1930 if (lastRange != null) { 1931 aliveRanges.remove(lastRange); 1932 } 1933 } 1934 1935 @Override 1936 public String toString() { 1937 if (aliveRanges == null) { 1938 return "empty local var"; 1939 } 1940 StringBuilder sb = new StringBuilder().append(sym) 1941 .append(" in register ").append((int)reg).append(" \n"); 1942 for (Range r : aliveRanges) { 1943 sb.append(" starts at pc=").append(Integer.toString(((int)r.start_pc))) 1944 .append(" length=").append(Integer.toString(((int)r.length))) 1945 .append("\n"); 1946 } 1947 return sb.toString(); 1948 } 1949 1950 public void openRange(char start) { 1951 if (!hasOpenRange()) { 1952 aliveRanges.add(new Range(start)); 1953 } 1954 } 1955 1956 public void closeRange(char length) { 1957 if (isLastRangeInitialized() && length > 0) { 1958 Range range = lastRange(); 1959 if (range != null) { 1960 if (range.length == Character.MAX_VALUE) { 1961 range.length = length; 1962 } 1963 } 1964 } else { 1965 removeLastRange(); 1966 } 1967 } 1968 1969 public boolean hasOpenRange() { 1970 if (aliveRanges.isEmpty()) { 1971 return false; 1972 } 1973 return lastRange().length == Character.MAX_VALUE; 1974 } 1975 1976 public boolean isLastRangeInitialized() { 1977 if (aliveRanges.isEmpty()) { 1978 return false; 1979 } 1980 return lastRange().start_pc != Character.MAX_VALUE; 1981 } 1982 1983 public Range getWidestRange() { 1984 if (aliveRanges.isEmpty()) { 1985 return new Range(); 1986 } else { 1987 Range firstRange = firstRange(); 1988 Range lastRange = lastRange(); 1989 char length = (char)(lastRange.length + (lastRange.start_pc - firstRange.start_pc)); 1990 return new Range(firstRange.start_pc, length); 1991 } 1992 } 1993 1994 } 1995 1996 /** Local variables, indexed by register. */ 1997 LocalVar[] lvar; 1998 1999 /** Add a new local variable. */ 2000 private void addLocalVar(VarSymbol v) { 2001 int adr = v.adr; 2002 lvar = ArrayUtils.ensureCapacity(lvar, adr+1); 2003 Assert.checkNull(lvar[adr]); 2004 if (pendingJumps != null) { 2005 resolvePending(); 2006 } 2007 lvar[adr] = new LocalVar(v); 2008 state.defined.excl(adr); 2009 } 2010 2011 void adjustAliveRanges(int oldCP, int delta) { 2012 for (LocalVar localVar: lvar) { 2013 if (localVar != null) { 2014 for (LocalVar.Range range: localVar.aliveRanges) { 2015 if (range.closed() && range.start_pc + range.length >= oldCP) { 2016 range.length += delta; 2017 } 2018 } 2019 } 2020 } 2021 } 2022 2023 /** 2024 * Calculates the size of the LocalVariableTable. 2025 */ 2026 public int getLVTSize() { 2027 int result = varBufferSize; 2028 for (int i = 0; i < varBufferSize; i++) { 2029 LocalVar var = varBuffer[i]; 2030 result += var.aliveRanges.size() - 1; 2031 } 2032 return result; 2033 } 2034 2035 /** Set the current variable defined state. */ 2036 public void setDefined(Bits newDefined) { 2037 if (alive && newDefined != state.defined) { 2038 Bits diff = new Bits(state.defined).xorSet(newDefined); 2039 for (int adr = diff.nextBit(0); 2040 adr >= 0; 2041 adr = diff.nextBit(adr+1)) { 2042 if (adr >= nextreg) 2043 state.defined.excl(adr); 2044 else if (state.defined.isMember(adr)) 2045 setUndefined(adr); 2046 else 2047 setDefined(adr); 2048 } 2049 } 2050 } 2051 2052 /** Mark a register as being (possibly) defined. */ 2053 public void setDefined(int adr) { 2054 LocalVar v = lvar[adr]; 2055 if (v == null) { 2056 state.defined.excl(adr); 2057 } else { 2058 state.defined.incl(adr); 2059 if (cp < Character.MAX_VALUE) { 2060 v.openRange((char)cp); 2061 } 2062 } 2063 } 2064 2065 /** Mark a register as being undefined. */ 2066 public void setUndefined(int adr) { 2067 state.defined.excl(adr); 2068 if (adr < lvar.length && 2069 lvar[adr] != null && 2070 lvar[adr].isLastRangeInitialized()) { 2071 LocalVar v = lvar[adr]; 2072 char length = (char)(curCP() - v.lastRange().start_pc); 2073 if (length < Character.MAX_VALUE) { 2074 lvar[adr] = v.dup(); 2075 v.closeRange(length); 2076 putVar(v); 2077 } else { 2078 v.removeLastRange(); 2079 } 2080 } 2081 } 2082 2083 /** End the scope of a variable. */ 2084 private void endScope(int adr) { 2085 LocalVar v = lvar[adr]; 2086 if (v != null) { 2087 if (v.isLastRangeInitialized()) { 2088 char length = (char)(curCP() - v.lastRange().start_pc); 2089 if (length < Character.MAX_VALUE) { 2090 v.closeRange(length); 2091 putVar(v); 2092 fillLocalVarPosition(v); 2093 } 2094 } 2095 /** the call to curCP() can implicitly adjust the current cp, if so 2096 * the alive range of local variables may be modified. Thus we need 2097 * all of them. For this reason assigning null to the given address 2098 * should be the last action to do. 2099 */ 2100 lvar[adr] = null; 2101 } 2102 state.defined.excl(adr); 2103 } 2104 2105 private void fillLocalVarPosition(LocalVar lv) { 2106 if (lv == null || lv.sym == null || !lv.sym.hasTypeAnnotations()) 2107 return; 2108 for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) { 2109 TypeAnnotationPosition p = ta.position; 2110 LocalVar.Range widestRange = lv.getWidestRange(); 2111 p.lvarOffset = new int[] { (int)widestRange.start_pc }; 2112 p.lvarLength = new int[] { (int)widestRange.length }; 2113 p.lvarIndex = new int[] { (int)lv.reg }; 2114 p.isValidOffset = true; 2115 } 2116 } 2117 2118 // Method to be called after compressCatchTable to 2119 // fill in the exception table index for type 2120 // annotations on exception parameters. 2121 public void fillExceptionParameterPositions() { 2122 for (int i = 0; i < varBufferSize; ++i) { 2123 LocalVar lv = varBuffer[i]; 2124 if (lv == null || lv.sym == null 2125 || !lv.sym.hasTypeAnnotations() 2126 || !lv.sym.isExceptionParameter()) 2127 continue; 2128 2129 for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) { 2130 TypeAnnotationPosition p = ta.position; 2131 if (p.hasCatchType()) { 2132 final int idx = findExceptionIndex(p); 2133 if (idx == -1) 2134 Assert.error("Could not find exception index for type annotation " + 2135 ta + " on exception parameter"); 2136 p.setExceptionIndex(idx); 2137 } 2138 } 2139 } 2140 } 2141 2142 private int findExceptionIndex(TypeAnnotationPosition p) { 2143 final int catchType = p.getCatchType(); 2144 final int startPos = p.getStartPos(); 2145 final int len = catchInfo.length(); 2146 List<char[]> iter = catchInfo.toList(); 2147 for (int i = 0; i < len; ++i) { 2148 char[] catchEntry = iter.head; 2149 iter = iter.tail; 2150 int ct = catchEntry[3]; 2151 int sp = catchEntry[0]; 2152 if (catchType == ct && sp == startPos) { 2153 return i; 2154 } 2155 } 2156 return -1; 2157 } 2158 2159 /** Put a live variable range into the buffer to be output to the 2160 * class file. 2161 */ 2162 void putVar(LocalVar var) { 2163 // Keep local variables if 2164 // 1) we need them for debug information 2165 // 2) it is an exception type and it contains type annotations 2166 boolean keepLocalVariables = varDebugInfo || 2167 (var.sym.isExceptionParameter() && var.sym.hasTypeAnnotations()); 2168 if (!keepLocalVariables) return; 2169 if ((var.sym.flags() & Flags.SYNTHETIC) != 0) 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