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