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