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