1 4 package gnu.bytecode; 5 import java.io.*; 6 7 20 21 public class CodeAttr extends Attribute implements AttrContainer 22 { 23 Attribute attributes; 24 public final Attribute getAttributes () { return attributes; } 25 public final void setAttributes (Attribute attributes) 26 { this.attributes = attributes; } 27 LineNumbersAttr lines; 28 public LocalVarsAttr locals; 29 30 SourceDebugExtAttr sourceDbgExt; 31 32 Type[] stack_types; 36 37 int SP; private int max_stack; 39 private int max_locals; 40 42 int PC; 43 byte[] code; 44 45 48 short[] exception_table; 49 50 52 int exception_table_length; 53 54 55 static final int FIXUP_NONE = 0; 56 57 static final int FIXUP_DEFINE = 1; 58 59 static final int FIXUP_SWITCH = 2; 60 61 static final int FIXUP_CASE = 3; 62 65 static final int FIXUP_GOTO = 4; 66 67 static final int FIXUP_JSR = 5; 68 69 static final int FIXUP_TRANSFER = 6; 70 71 static final int FIXUP_TRANSFER2 = 7; 72 73 static final int FIXUP_DELETE3 = 8; 74 80 static final int FIXUP_MOVE = 9; 81 86 static final int FIXUP_MOVE_TO_END = 10; 87 90 static final int FIXUP_TRY = 11; 91 94 static final int FIXUP_CATCH = 12; 95 97 static final int FIXUP_LINE_PC = 13; 98 100 static final int FIXUP_LINE_NUMBER = 14; 101 int[] fixup_offsets; 102 Label[] fixup_labels; 103 int fixup_count; 104 105 111 public final void fixupChain (Label here, Label target) 112 { 113 fixupAdd(CodeAttr.FIXUP_MOVE, 0, target); 114 here.define(this); 115 } 116 117 120 public final void fixupAdd (int kind, Label label) 121 { 122 fixupAdd(kind, PC, label); 123 } 124 125 final void fixupAdd (int kind, int offset, Label label) 126 { 127 int count = fixup_count; 128 if (count == 0) 129 { 130 fixup_offsets = new int[30]; 131 fixup_labels = new Label[30]; 132 } 133 else if (fixup_count == fixup_offsets.length) 134 { 135 int new_length = 2 * count; 136 Label[] new_labels = new Label[new_length]; 137 System.arraycopy (fixup_labels, 0, new_labels, 0, count); 138 fixup_labels = new_labels; 139 int[] new_offsets = new int[new_length]; 140 System.arraycopy (fixup_offsets, 0, new_offsets, 0, count); 141 fixup_offsets = new_offsets; 142 } 143 fixup_offsets[count] = (offset << 4) | kind; 144 fixup_labels[count] = label; 145 fixup_count = count + 1; 146 } 147 148 private final int fixupOffset(int index) 149 { 150 return fixup_offsets[index] >> 4; 151 } 152 153 private final int fixupKind(int index) 154 { 155 return fixup_offsets[index] & 15; 156 } 157 158 161 public static boolean instructionLineMode = false; 162 163 164 IfState if_stack; 165 166 167 TryState try_stack; 168 169 public final Method getMethod() { return (Method) getContainer(); } 170 171 public final int getPC() { return PC; } 172 173 public final int getSP() { return SP; } 174 175 public final ConstantPool getConstants () 176 { 177 return getMethod().classfile.constants; 178 } 179 180 182 private boolean unreachable_here; 183 184 public final boolean reachableHere () { return !unreachable_here; } 185 public final void setReachable(boolean val) { unreachable_here = !val; } 186 public final void setUnreachable() { unreachable_here = true; } 187 188 189 public int getMaxStack() { return max_stack; } 190 191 public int getMaxLocals() { return max_locals; } 192 193 194 public void setMaxStack(int n) { max_stack = n; } 195 196 public void setMaxLocals(int n) { max_locals = n; } 197 198 200 public byte[] getCode() { return code; } 201 204 public void setCode(byte[] code) { 205 this.code = code; this.PC = code.length; } 206 209 public void setCodeLength(int len) { PC = len;} 210 211 public int getCodeLength() { return PC; } 212 213 public CodeAttr (Method meth) 214 { 215 super ("Code"); 216 addToFrontOf(meth); 217 meth.code = this; 218 } 219 220 public final void reserve (int bytes) 221 { 222 if (code == null) 223 code = new byte[100+bytes]; 224 else if (PC + bytes > code.length) 225 { 226 byte[] new_code = new byte[2 * code.length + bytes]; 227 System.arraycopy (code, 0, new_code, 0, PC); 228 code = new_code; 229 } 230 } 231 232 233 byte invert_opcode (byte opcode) 234 { 235 if ((opcode >= 153 && opcode <= 166) 236 || (opcode >= 198 && opcode <= 199)) 237 return (byte) (opcode ^ 1); 238 throw new Error ("unknown opcode to invert_opcode"); 239 } 240 241 245 public final void put1(int i) 246 { 247 code[PC++] = (byte) i; 248 unreachable_here = false; 249 } 250 251 255 public final void put2(int i) 256 { 257 code[PC++] = (byte) (i >> 8); 258 code[PC++] = (byte) (i); 259 unreachable_here = false; 260 } 261 262 266 public final void put4(int i) 267 { 268 code[PC++] = (byte) (i >> 24); 269 code[PC++] = (byte) (i >> 16); 270 code[PC++] = (byte) (i >> 8); 271 272 code[PC++] = (byte) (i); 273 unreachable_here = false; 274 } 275 276 public final void putIndex2 (CpoolEntry cnst) 277 { 278 put2(cnst.index); 279 } 280 281 public final void putLineNumber (String filename, int linenumber) 282 { 283 getMethod().classfile.setSourceFile(filename); 284 putLineNumber(linenumber); 285 } 286 287 public final void putLineNumber (int linenumber) 288 { 289 if (sourceDbgExt != null) 290 linenumber = sourceDbgExt.fixLine(linenumber); 291 fixupAdd(FIXUP_LINE_PC, null); 292 fixupAdd(FIXUP_LINE_NUMBER, linenumber, null); 293 } 294 295 public final void pushType(Type type) 296 { 297 if (type.size == 0) 298 throw new Error ("pushing void type onto stack"); 299 if (stack_types == null) 300 stack_types = new Type[20]; 301 else if (SP + 1 >= stack_types.length) { 302 Type[] new_array = new Type[2 * stack_types.length]; 303 System.arraycopy (stack_types, 0, new_array, 0, SP); 304 stack_types = new_array; 305 } 306 if (type.size == 8) 307 stack_types[SP++] = Type.void_type; 308 stack_types[SP++] = type; 309 if (SP > max_stack) 310 max_stack = SP; 311 } 312 313 public final Type popType () 314 { 315 if (SP <= 0) 316 throw new Error ("popType called with empty stack "+getMethod()); 317 Type type = stack_types[--SP]; 318 if (type.size == 8) 319 if (! popType().isVoid()) 320 throw new Error ("missing void type on stack"); 321 return type; 322 } 323 324 public final Type topType () 325 { 326 return stack_types[SP - 1]; 327 } 328 329 332 public void emitPop (int nvalues) 333 { 334 for ( ; nvalues > 0; --nvalues) 335 { 336 reserve(1); 337 Type type = popType(); 338 if (type.size > 4) 339 put1(88); else if (nvalues > 1) 341 { Type type2 = popType(); 343 if (type2.size > 4) 344 { 345 put1(87); reserve(1); 347 } 348 put1(88); --nvalues; 350 } 351 else 352 put1(87); } 354 } 355 356 359 public Label getLabel () 360 { 361 boolean unreachable = unreachable_here; 362 Label label = new Label(); 363 label.define(this); 364 unreachable_here = unreachable; 365 return label; 366 } 367 368 public void emitSwap () 369 { 370 reserve(1); 371 Type type1 = popType(); 372 Type type2 = popType(); 373 374 if (type1.size > 4 || type2.size > 4) 375 { 376 pushType(type2); 379 pushType(type1); 380 emitDupX(); 381 emitPop(1); 382 } 383 else 384 { 385 pushType(type1); 386 put1(95); pushType(type2); 388 } 389 } 390 391 392 public void emitDup () 393 { 394 reserve(1); 395 396 Type type = topType(); 397 put1 (type.size <= 4 ? 89 : 92); pushType (type); 399 } 400 401 403 public void emitDupX () 404 { 405 reserve(1); 406 407 Type type = popType(); 408 Type skipedType = popType(); 409 410 if (skipedType.size <= 4) 411 put1 (type.size <= 4 ? 90 : 93); else 413 put1 (type.size <= 4 ? 91 : 94); 415 pushType (type); 416 pushType (skipedType); 417 pushType (type); 418 } 419 420 425 public void emitDup (int size, int offset) 426 { 427 if (size == 0) 428 return; 429 reserve(1); 430 Type copied1 = popType (); 432 Type copied2 = null; 433 if (size == 1) 434 { 435 if (copied1.size > 4) 436 throw new Error ("using dup for 2-word type"); 437 } 438 else if (size != 2) 439 throw new Error ("invalid size to emitDup"); 440 else if (copied1.size <= 4) 441 { 442 copied2 = popType(); 443 if (copied2.size > 4) 444 throw new Error ("dup will cause invalid types on stack"); 445 } 446 447 int kind; 448 Type skipped1 = null; 450 Type skipped2 = null; 451 if (offset == 0) 452 { 453 kind = size == 1 ? 89 : 92; } 455 else if (offset == 1) 456 { 457 kind = size == 1 ? 90 : 93; skipped1 = popType (); 459 if (skipped1.size > 4) 460 throw new Error ("dup will cause invalid types on stack"); 461 } 462 else if (offset == 2) 463 { 464 kind = size == 1 ? 91 : 94; skipped1 = popType(); 466 if (skipped1.size <= 4) 467 { 468 skipped2 = popType(); 469 if (skipped2.size > 4) 470 throw new Error ("dup will cause invalid types on stack"); 471 } 472 } 473 else 474 throw new Error ("emitDup: invalid offset"); 475 476 put1(kind); 477 if (copied2 != null) 478 pushType(copied2); 479 pushType(copied1); 480 if (skipped2 != null) 481 pushType(skipped2); 482 if (skipped1 != null) 483 pushType(skipped1); 484 if (copied2 != null) 485 pushType(copied2); 486 pushType(copied1); 487 } 488 489 493 public void emitDup (int size) 494 { 495 emitDup(size, 0); 496 } 497 498 public void emitDup (Type type) 499 { 500 emitDup(type.size > 4 ? 2 : 1, 0); 501 } 502 503 public void enterScope (Scope scope) 504 { 505 scope.setStartPC(this); 506 locals.enterScope(scope); 507 } 508 509 public Scope pushScope () { 510 Scope scope = new Scope (); 511 if (locals == null) 512 locals = new LocalVarsAttr(getMethod()); 513 enterScope(scope); 514 if (locals.parameter_scope == null) 515 locals.parameter_scope = scope; 516 return scope; 517 } 518 519 public Scope getCurrentScope() 520 { 521 return locals.current_scope; 522 } 523 524 public Scope popScope () { 525 Scope scope = locals.current_scope; 526 locals.current_scope = scope.parent; 527 scope.freeLocals(this); 528 scope.end = getLabel(); 529 return scope; 530 } 531 532 533 public Variable getArg (int index) 534 { 535 return locals.parameter_scope.getVariable(index); 536 } 537 538 543 public Variable lookup (String name) 544 { 545 Scope scope = locals.current_scope; 546 for (; scope != null; scope = scope.parent) 547 { 548 Variable var = scope.lookup (name); 549 if (var != null) 550 return var; 551 } 552 return null; 553 } 554 555 558 public Variable addLocal (Type type) 559 { 560 return locals.current_scope.addVariable(this, type, null); 561 } 562 563 567 public Variable addLocal (Type type, String name) 568 { 569 return locals.current_scope.addVariable (this, type, name); 570 } 571 572 573 public void addParamLocals() 574 { 575 Method method = getMethod(); 576 if ((method.access_flags & Access.STATIC) == 0) 577 addLocal(method.classfile).setParameter(true); 578 int arg_count = method.arg_types.length; 579 for (int i = 0; i < arg_count; i++) 580 addLocal(method.arg_types[i]).setParameter(true); 581 } 582 583 public final void emitPushConstant(int val, Type type) 584 { 585 switch (type.getSignature().charAt(0)) 586 { 587 case 'B': case 'C': case 'I': case 'Z': case 'S': 588 emitPushInt(val); break; 589 case 'J': 590 emitPushLong((long)val); break; 591 case 'F': 592 emitPushFloat((float)val); break; 593 case 'D': 594 emitPushDouble((double)val); break; 595 default: 596 throw new Error ("bad type to emitPushConstant"); 597 } 598 } 599 600 602 public final void emitPushConstant (CpoolEntry cnst) 603 { 604 reserve(3); 605 int index = cnst.index; 606 if (cnst instanceof CpoolValue2) 607 { 608 put1 (20); put2 (index); 610 } 611 else if (index < 256) 612 { 613 put1(18); put1(index); 615 } 616 else 617 { 618 put1(19); put2(index); 620 } 621 } 622 623 public final void emitPushInt(int i) 624 { 625 reserve(3); 626 if (i >= -1 && i <= 5) 627 put1(i + 3); else if (i >= -128 && i < 128) 629 { 630 put1(16); put1(i); 632 } 633 else if (i >= -32768 && i < 32768) 634 { 635 put1(17); put2(i); 637 } 638 else 639 { 640 emitPushConstant(getConstants().addInt(i)); 641 } 642 pushType(Type.int_type); 643 } 644 645 public void emitPushLong (long i) 646 { 647 if (i == 0 || i == 1) 648 { 649 reserve(1); 650 put1 (9 + (int) i); } 652 else if ((long) (int) i == i) 653 { 654 emitPushInt ((int) i); 655 reserve(1); 656 popType(); 657 put1 (133); } 659 else 660 { 661 emitPushConstant(getConstants().addLong(i)); 662 } 663 pushType(Type.long_type); 664 } 665 666 public void emitPushFloat (float x) 667 { 668 int xi = (int) x; 669 if ((float) xi == x && xi >= -128 && xi < 128) 670 { 671 if (xi >= 0 && xi <= 2) 672 { 673 reserve(1); 674 put1(11 + xi); if (xi == 0 && Float.floatToIntBits(x) != 0) { 677 reserve(1); 678 put1(118); } 680 } 681 else 682 { 683 emitPushInt (xi); 686 reserve(1); 687 popType(); 688 put1 (134); } 690 } 691 else 692 { 693 emitPushConstant(getConstants().addFloat(x)); 694 } 695 pushType(Type.float_type); 696 } 697 698 public void emitPushDouble (double x) 699 { 700 int xi = (int) x; 701 if ((double) xi == x && xi >= -128 && xi < 128) 702 { 703 if (xi == 0 || xi == 1) 704 { 705 reserve(1); 706 put1(14+xi); if (xi == 0 && Double.doubleToLongBits(x) != 0L) { 709 reserve(1); 710 put1(119); } 712 } 713 else 714 { 715 emitPushInt (xi); 718 reserve(1); 719 popType(); 720 put1 (135); } 722 } 723 else 724 { 725 emitPushConstant(getConstants().addDouble(x)); 726 } 727 pushType(Type.double_type); 728 } 729 730 735 public static final String calculateSplit (String str) 736 { 737 int strLength = str.length(); 738 StringBuffer sbuf = new StringBuffer (20); 739 int segmentStart = 0; 741 int byteLength = 0; for (int i = 0; i < strLength; i++) 743 { 744 char ch = str.charAt(i); 745 int bytes = ch >= 0x0800 ? 3 : ch >= 0x0080 || ch == 0 ? 2 : 1; 746 if (byteLength + bytes > 0xFFFF) 747 { 748 sbuf.append((char) (i - segmentStart)); 749 segmentStart = i; 750 byteLength = 0; 751 } 752 byteLength += bytes; 753 } 754 sbuf.append((char) (strLength - segmentStart)); 755 return sbuf.toString(); 756 } 757 758 763 public final void emitPushString (String str) 764 { 765 if (str == null) 766 emitPushNull(); 767 else 768 { 769 int length = str.length(); 770 String segments = calculateSplit(str); 771 int numSegments = segments.length(); 772 if (numSegments <= 1) 773 emitPushConstant(getConstants().addString(str)); 774 else 775 { 776 if (numSegments == 2) 777 { 778 int firstSegment = (int) segments.charAt(0); 779 emitPushString(str.substring(0, firstSegment)); 780 emitPushString(str.substring(firstSegment)); 781 Method concatMethod 782 = Type.string_type.getDeclaredMethod("concat", 1); 783 emitInvokeVirtual(concatMethod); 784 } 785 else 786 { 787 ClassType sbufType = ClassType.make("java.lang.StringBuffer"); 788 emitNew(sbufType); 789 emitDup(sbufType); 790 emitPushInt(length); 791 Type[] args1 = { Type.int_type }; 792 emitInvokeSpecial(sbufType.getDeclaredMethod("<init>", args1)); 793 Type[] args2 = { Type.string_type }; 794 Method appendMethod 795 = sbufType.getDeclaredMethod("append", args2); 796 int segStart = 0; 797 for (int seg = 0; seg < numSegments; seg++) 798 { 799 emitDup(sbufType); 800 int segEnd = segStart + (int) segments.charAt(seg); 801 emitPushString(str.substring(segStart, segEnd)); 802 emitInvokeVirtual(appendMethod); 803 segStart = segEnd; 804 } 805 emitInvokeVirtual(Type.toString_method); 806 } 807 if (str == str.intern()) 808 emitInvokeVirtual(Type.string_type.getDeclaredMethod("intern", 0)); 809 return; 810 } 811 pushType(Type.string_type); 812 } 813 } 814 815 817 public final void emitPushClass (String name) 818 { 819 emitPushConstant(getConstants().addClass(name)); 820 pushType(Type.java_lang_Class_type); 821 } 822 823 public void emitPushNull () 824 { 825 reserve(1); 826 put1(1); pushType(Type.pointer_type); 828 } 829 830 public final void emitPushThis() 831 { 832 reserve(1); 833 put1(42); pushType(getMethod().getDeclaringClass()); 835 } 836 837 841 public final void emitPushPrimArray(Object value, ArrayType arrayType) 842 { 843 Type elementType = arrayType.getComponentType(); 844 int len = java.lang.reflect.Array.getLength(value); 845 emitPushInt(len); 846 emitNewArray(elementType); 847 char sig = elementType.getSignature().charAt(0); 848 for (int i = 0; i < len; i++) 849 { 850 long ival = 0; float fval = 0; double dval = 0; 851 switch (sig) 852 { 853 case 'J': 854 ival = ((long[]) value)[i]; 855 if (ival == 0) 856 continue; 857 break; 858 case 'I': 859 ival = ((int[]) value)[i]; 860 if (ival == 0) 861 continue; 862 break; 863 case 'S': 864 ival = ((short[]) value)[i]; 865 if (ival == 0) 866 continue; 867 break; 868 case 'C': 869 ival = ((char[]) value)[i]; 870 if (ival == 0) 871 continue; 872 break; 873 case 'B': 874 ival = ((byte[]) value)[i]; 875 if (ival == 0) 876 continue; 877 break; 878 case 'Z': 879 ival = ((boolean[]) value)[i] ? 1 : 0; 880 if (ival == 0) 881 continue; 882 break; 883 case 'F': 884 fval = ((float[]) value)[i]; 885 if (fval == 0.0) 886 continue; 887 break; 888 case 'D': 889 dval = ((double[]) value)[i]; 890 if (dval == 0.0) 891 continue; 892 break; 893 } 894 emitDup(arrayType); 895 emitPushInt(i); 896 switch (sig) 897 { 898 case 'Z': 899 case 'C': 900 case 'B': 901 case 'S': 902 case 'I': 903 emitPushInt((int) ival); 904 break; 905 case 'J': 906 emitPushLong(ival); 907 break; 908 case 'F': 909 emitPushFloat(fval); 910 break; 911 case 'D': 912 emitPushDouble(dval); 913 break; 914 } 915 emitArrayStore(elementType); 916 } 917 } 918 919 920 921 void emitNewArray (int type_code) 922 { 923 reserve(2); 924 put1(188); put1(type_code); 926 } 927 928 public final void emitArrayLength () 929 { 930 if (! (popType() instanceof ArrayType)) 931 throw new Error ( "non-array type in emitArrayLength" ); 932 933 reserve(1); 934 put1(190); pushType(Type.int_type); 936 } 937 938 941 942 private int adjustTypedOp (char sig) 943 { 944 switch (sig) 945 { 946 case 'I': return 0; case 'J': return 1; case 'F': return 2; case 'D': return 3; default: return 4; case 'B': 952 case 'Z': return 5; case 'C': return 6; case 'S': return 7; } 956 } 957 958 private int adjustTypedOp (Type type) 959 { 960 return adjustTypedOp(type.getSignature().charAt(0)); 961 } 962 963 private void emitTypedOp (int op, Type type) 964 { 965 reserve(1); 966 put1(op + adjustTypedOp(type)); 967 } 968 969 private void emitTypedOp (int op, char sig) 970 { 971 reserve(1); 972 put1(op + adjustTypedOp(sig)); 973 } 974 975 980 public void emitArrayStore (Type element_type) 981 { 982 popType(); popType(); popType(); emitTypedOp(79, element_type); 986 } 987 988 991 public void emitArrayLoad (Type element_type) 992 { 993 popType(); popType(); emitTypedOp(46, element_type); 996 pushType(element_type); 997 } 998 999 1004 public void emitNew (ClassType type) 1005 { 1006 reserve(3); 1007 put1(187); putIndex2(getConstants().addClass(type)); 1009 pushType(type); 1010 } 1011 1012 1016 public void emitNewArray (Type element_type, int dims) 1017 { 1018 if (popType ().promote () != Type.int_type) 1019 throw new Error ("non-int dim. spec. in emitNewArray"); 1020 1021 if (element_type instanceof PrimType) 1022 { 1023 int code; 1024 switch (element_type.getSignature().charAt(0)) 1025 { 1026 case 'B': code = 8; break; 1027 case 'S': code = 9; break; 1028 case 'I': code = 10; break; 1029 case 'J': code = 11; break; 1030 case 'F': code = 6; break; 1031 case 'D': code = 7; break; 1032 case 'Z': code = 4; break; 1033 case 'C': code = 5; break; 1034 default: throw new Error ("bad PrimType in emitNewArray"); 1035 } 1036 emitNewArray(code); 1037 } 1038 else if (element_type instanceof ObjectType) 1039 { 1040 reserve(3); 1041 put1(189); putIndex2(getConstants().addClass((ObjectType) element_type)); 1043 } 1044 else if (element_type instanceof ArrayType) 1045 { 1046 reserve(4); 1047 put1(197); putIndex2 (getConstants ().addClass (new ArrayType (element_type))); 1049 if (dims < 1 || dims > 255) 1050 throw new Error ("dims out of range in emitNewArray"); 1051 put1(dims); 1052 while (-- dims > 0) if (popType ().promote () != Type.int_type) 1054 throw new Error ("non-int dim. spec. in emitNewArray"); 1055 } 1056 else 1057 throw new Error ("unimplemented type in emitNewArray"); 1058 1059 pushType (new ArrayType (element_type)); 1060 } 1061 1062 public void emitNewArray (Type element_type) 1063 { 1064 emitNewArray (element_type, 1); 1065 } 1066 1067 private void emitBinop (int base_code) 1069 { 1070 Type type2 = popType().promote(); 1071 Type type1_raw = popType(); 1072 Type type1 = type1_raw.promote(); 1073 if (type1 != type2 || ! (type1 instanceof PrimType)) 1074 throw new Error ("non-matching or bad types in binary operation"); 1075 emitTypedOp(base_code, type1); 1076 pushType(type1_raw); 1077 } 1078 1079 private void emitBinop (int base_code, char sig) 1080 { 1081 popType(); 1082 popType(); 1083 emitTypedOp(base_code, sig); 1084 pushType(Type.signatureToPrimitive(sig)); 1085 } 1086 1087 private void emitBinop (int base_code, Type type) 1088 { 1089 popType(); 1090 popType(); 1091 emitTypedOp(base_code, type); 1092 pushType(type); 1093 } 1094 1095 1100 public final void emitAdd(char sig) { emitBinop (96, sig); } 1101 public final void emitAdd(PrimType type) { emitBinop (96, type); } 1102 1103 public final void emitAdd () { emitBinop (96); } 1104 1105 public final void emitSub(char sig) { emitBinop (100, sig); } 1106 public final void emitSub(PrimType type) { emitBinop (100, type); } 1107 1108 public final void emitSub () { emitBinop (100); } 1109 1110 public final void emitMul () { emitBinop (104); } 1111 public final void emitDiv () { emitBinop (108); } 1112 public final void emitRem () { emitBinop (112); } 1113 public final void emitAnd () { emitBinop (126); } 1114 public final void emitIOr () { emitBinop (128); } 1115 public final void emitXOr () { emitBinop (130); } 1116 1117 public final void emitShl () { emitShift (120); } 1118 public final void emitShr () { emitShift (122); } 1119 public final void emitUshr() { emitShift (124); } 1120 1121 private void emitShift (int base_code) 1122 { 1123 Type type2 = popType().promote(); 1124 Type type1_raw = popType(); 1125 Type type1 = type1_raw.promote(); 1126 1127 if (type1 != Type.int_type && type1 != Type.long_type) 1128 throw new Error ("the value shifted must be an int or a long"); 1129 1130 if (type2 != Type.int_type) 1131 throw new Error ("the amount of shift must be an int"); 1132 1133 emitTypedOp(base_code, type1); 1134 pushType(type1_raw); 1135 } 1136 1137 public final void emitNot(Type type) 1138 { 1139 emitPushConstant(1, type); 1140 emitAdd(); 1141 emitPushConstant(1, type); 1142 emitAnd(); 1143 } 1144 1145 public void emitPrimop (int opcode, int arg_count, Type retType) 1146 { 1147 reserve(1); 1148 while (-- arg_count >= 0) 1149 popType(); 1150 put1(opcode); 1151 pushType(retType); 1152 } 1153 1154 void emitMaybeWide (int opcode, int index) 1155 { 1156 if (index >= 256) 1157 { 1158 put1(196); put1(opcode); 1160 put2(index); 1161 } 1162 else 1163 { 1164 put1(opcode); 1165 put1(index); 1166 } 1167 } 1168 1169 1173 public final void emitLoad (Variable var) 1174 { 1175 if (var.dead()) 1176 throw new Error ("attempting to push dead variable"); 1177 int offset = var.offset; 1178 if (offset < 0 || !var.isSimple()) 1179 throw new Error ("attempting to load from unassigned variable "+var 1180 +" simple:"+var.isSimple()+", offset: "+offset); 1181 Type type = var.getType().promote(); 1182 reserve(4); 1183 int kind = adjustTypedOp(type); 1184 if (offset <= 3) 1185 put1(26 + 4 * kind + offset); else 1187 emitMaybeWide(21 + kind, offset); pushType(var.getType()); 1189 } 1190 1191 public void emitStore (Variable var) 1192 { 1193 if (var.dead ()) 1194 throw new Error ("attempting to push dead variable"); 1195 int offset = var.offset; 1196 if (offset < 0 || !var.isSimple ()) 1197 throw new Error ("attempting to store in unassigned "+var 1198 +" simple:"+var.isSimple()+", offset: "+offset); 1199 Type type = var.getType().promote (); 1200 reserve(4); 1201 popType(); 1202 int kind = adjustTypedOp(type); 1203 if (offset <= 3) 1204 put1(59 + 4 * kind + offset); else 1206 emitMaybeWide(54 + kind, offset); } 1208 1209 1210 public void emitInc (Variable var, short inc) 1211 { 1212 if (var.dead ()) 1213 throw new Error ("attempting to increment dead variable"); 1214 int offset = var.offset; 1215 if (offset < 0 || !var.isSimple ()) 1216 throw new Error ("attempting to increment unassigned variable"+var.getName() 1217 +" simple:"+var.isSimple()+", offset: "+offset); 1218 Type type = var.getType().promote (); 1219 reserve(6); 1220 if (type != Type.int_type) 1221 throw new Error ("attempting to increment non-int variable"); 1222 1223 boolean wide = offset > 255 || inc > 255 || inc < -256; 1224 1225 if (wide) 1226 { 1227 put1(196); put1(132); put2(offset); 1230 put2(inc); 1231 } 1232 else 1233 { 1234 put1(132); put1(offset); 1236 put1(inc); 1237 } 1238 } 1239 1240 1241 private final void emitFieldop (Field field, int opcode) 1242 { 1243 reserve(3); 1244 put1(opcode); 1245 putIndex2(getConstants().addFieldRef(field)); 1246 } 1247 1248 1250 1251 public final void emitGetStatic(Field field) 1252 { 1253 pushType(field.type); 1254 emitFieldop (field, 178); } 1256 1257 1259 1260 public final void emitGetField(Field field) 1261 { 1262 popType(); 1263 pushType(field.type); 1264 emitFieldop(field, 180); } 1266 1267 1269 1270 public final void emitPutStatic (Field field) 1271 { 1272 popType(); 1273 emitFieldop(field, 179); } 1275 1276 1278 1279 public final void emitPutField (Field field) 1280 { 1281 popType(); 1282 popType(); 1283 emitFieldop(field, 181); } 1285 1286 1287 private int words(Type[] types) 1288 { 1289 int res = 0; 1290 for (int i=types.length; --i >= 0; ) 1291 if (types[i].size > 4) 1292 res+=2; 1293 else 1294 res++; 1295 return res; 1296 } 1297 1298 public void emitInvokeMethod (Method method, int opcode) 1299 { 1300 reserve(opcode == 185 ? 5 : 3); 1301 int arg_count = method.arg_types.length; 1302 boolean is_invokestatic = opcode == 184; 1303 if (is_invokestatic != ((method.access_flags & Access.STATIC) != 0)) 1304 throw new Error 1305 ("emitInvokeXxx static flag mis-match method.flags="+method.access_flags); 1306 if (!is_invokestatic) 1307 arg_count++; 1308 put1(opcode); putIndex2(getConstants().addMethodRef(method)); 1310 if (opcode == 185) { 1312 put1(words(method.arg_types)+1); put1(0); 1314 } 1315 while (--arg_count >= 0) 1316 popType(); 1317 if (method.return_type.size != 0) 1318 pushType(method.return_type); 1319 } 1320 1321 public void emitInvoke (Method method) 1322 { 1323 int opcode; 1324 if ((method.access_flags & Access.STATIC) != 0) 1325 opcode = 184; else if (method.classfile.isInterface()) 1327 opcode = 185; else if ("<init>".equals(method.getName())) 1329 opcode = 183; else 1331 opcode = 182; emitInvokeMethod(method, opcode); 1333 } 1334 1335 1339 public void emitInvokeVirtual (Method method) 1340 { 1341 emitInvokeMethod(method, 182); } 1343 1344 public void emitInvokeSpecial (Method method) 1345 { 1346 emitInvokeMethod(method, 183); } 1348 1349 1353 public void emitInvokeStatic (Method method) 1354 { 1355 emitInvokeMethod(method, 184); } 1357 1358 public void emitInvokeInterface (Method method) 1359 { 1360 emitInvokeMethod(method, 185); } 1362 1363 final void emitTransfer (Label label, int opcode) 1364 { 1365 fixupAdd(FIXUP_TRANSFER, label); 1366 put1(opcode); 1367 PC += 2; 1368 } 1369 1370 1373 public final void emitGoto (Label label) 1374 { 1375 fixupAdd(FIXUP_GOTO, label); 1376 reserve(3); 1377 put1(167); 1378 PC += 2; 1379 setUnreachable(); 1380 } 1381 1382 public final void emitJsr (Label label) 1383 { 1384 fixupAdd(FIXUP_JSR, label); 1385 reserve(3); 1386 put1(168); 1387 PC += 2; 1388 } 1389 1390 public final void emitGotoIfCompare1 (Label label, int opcode) 1391 { 1392 popType(); 1393 reserve(3); 1394 emitTransfer (label, opcode); 1395 } 1396 1397 public final void emitGotoIfIntEqZero(Label label) 1398 { emitGotoIfCompare1(label, 153); } 1399 public final void emitGotoIfIntNeZero(Label label) 1400 { emitGotoIfCompare1(label, 154); } 1401 public final void emitGotoIfIntLtZero(Label label) 1402 { emitGotoIfCompare1(label, 155); } 1403 public final void emitGotoIfIntGeZero(Label label) 1404 { emitGotoIfCompare1(label, 156); } 1405 public final void emitGotoIfIntGtZero(Label label) 1406 { emitGotoIfCompare1(label, 157); } 1407 public final void emitGotoIfIntLeZero(Label label) 1408 { emitGotoIfCompare1(label, 158); } 1409 1410 public final void emitGotoIfCompare2 (Label label, int logop) 1411 { 1412 if( logop < 153 || logop > 158 ) 1413 throw new Error ("emitGotoIfCompare2: logop must be one of ifeq...ifle"); 1414 1415 Type type2 = popType().promote(); 1416 Type type1 = popType().promote(); 1417 reserve(4); 1418 char sig1 = type1.getSignature().charAt(0); 1419 char sig2 = type2.getSignature().charAt(0); 1420 1421 boolean cmpg = (logop == 155 || logop == 158); 1423 if (sig1 == 'I' && sig2 == 'I') 1424 logop += 6; else if (sig1 == 'J' && sig2 == 'J') 1426 put1(148); else if (sig1 == 'F' && sig2 == 'F') 1428 put1(cmpg ? 149 : 150); else if (sig1 == 'D' && sig2 == 'D') 1430 put1(cmpg ? 151 : 152); else if ((sig1 == 'L' || sig1 == '[') 1432 && (sig2 == 'L' || sig2 == '[') 1433 && logop <= 154) 1434 logop += 12; else 1436 throw new Error ("invalid types to emitGotoIfCompare2"); 1437 1438 emitTransfer (label, logop); 1439 } 1440 1441 1443 public final void emitGotoIfEq (Label label, boolean invert) 1444 { 1445 emitGotoIfCompare2(label, invert ? 154 : 153); 1446 } 1447 1448 1449 public final void emitGotoIfEq (Label label) 1450 { 1451 emitGotoIfCompare2(label, 153); 1452 } 1453 1454 1455 public final void emitGotoIfNE (Label label) 1456 { 1457 emitGotoIfCompare2(label, 154); 1458 } 1459 1460 public final void emitGotoIfLt(Label label) 1461 { emitGotoIfCompare2(label, 155); } 1462 public final void emitGotoIfGe(Label label) 1463 { emitGotoIfCompare2(label, 156); } 1464 public final void emitGotoIfGt(Label label) 1465 { emitGotoIfCompare2(label, 157); } 1466 public final void emitGotoIfLe(Label label) 1467 { emitGotoIfCompare2(label, 158); } 1468 1469 1470 1473 public final void emitIfCompare1 (int opcode) 1474 { 1475 IfState new_if = new IfState(this); 1476 if (popType().promote() != Type.int_type) 1477 throw new Error ("non-int type to emitIfCompare1"); 1478 reserve(3); 1479 emitTransfer (new_if.end_label, opcode); 1480 new_if.start_stack_size = SP; 1481 } 1482 1483 1485 public final void emitIfIntNotZero() 1486 { 1487 emitIfCompare1(153); } 1489 1490 1492 public final void emitIfIntEqZero() 1493 { 1494 emitIfCompare1(154); } 1496 1497 1498 public final void emitIfIntLEqZero() 1499 { 1500 emitIfCompare1(157); } 1502 1503 1506 public final void emitIfRefCompare1 (int opcode) 1507 { 1508 IfState new_if = new IfState(this); 1509 if (! (popType() instanceof ObjectType)) 1510 throw new Error ("non-ref type to emitIfRefCompare1"); 1511 reserve(3); 1512 emitTransfer (new_if.end_label, opcode); 1513 new_if.start_stack_size = SP; 1514 } 1515 1516 1517 public final void emitIfNotNull() 1518 { 1519 emitIfRefCompare1(198); } 1521 1522 1523 public final void emitIfNull() 1524 { 1525 emitIfRefCompare1(199); } 1527 1528 1530 public final void emitIfIntCompare(int opcode) 1531 { 1532 IfState new_if = new IfState(this); 1533 popType(); 1534 popType(); 1535 reserve(3); 1536 emitTransfer(new_if.end_label, opcode); 1537 new_if.start_stack_size = SP; 1538 } 1539 1540 1541 public final void emitIfIntLt() 1542 { 1543 emitIfIntCompare(162); } 1545 1546 1548 public final void emitIfNEq () 1549 { 1550 IfState new_if = new IfState (this); 1551 emitGotoIfEq(new_if.end_label); 1552 new_if.start_stack_size = SP; 1553 } 1554 1555 1557 public final void emitIfEq () 1558 { 1559 IfState new_if = new IfState (this); 1560 emitGotoIfNE(new_if.end_label); 1561 new_if.start_stack_size = SP; 1562 } 1563 1564 1566 public final void emitIfLt () 1567 { 1568 IfState new_if = new IfState (this); 1569 emitGotoIfGe(new_if.end_label); 1570 new_if.start_stack_size = SP; 1571 } 1572 1573 1575 public final void emitIfGe () 1576 { 1577 IfState new_if = new IfState (this); 1578 emitGotoIfLt(new_if.end_label); 1579 new_if.start_stack_size = SP; 1580 } 1581 1582 1584 public final void emitIfGt () 1585 { 1586 IfState new_if = new IfState (this); 1587 emitGotoIfLe(new_if.end_label); 1588 new_if.start_stack_size = SP; 1589 } 1590 1591 1593 public final void emitIfLe () 1594 { 1595 IfState new_if = new IfState (this); 1596 emitGotoIfGt(new_if.end_label); 1597 new_if.start_stack_size = SP; 1598 } 1599 1600 1602 public void emitRet (Variable var) 1603 { 1604 int offset = var.offset; 1605 if (offset < 256) 1606 { 1607 reserve(2); 1608 put1(169); put1(offset); 1610 } 1611 else 1612 { 1613 reserve(4); 1614 put1(196); put1(169); put2(offset); 1617 } 1618 } 1619 1620 public final void emitThen() 1621 { 1622 if_stack.start_stack_size = SP; 1623 } 1624 1625 public final void emitIfThen () 1626 { 1627 new IfState(this, null); 1628 } 1629 1630 1631 public final void emitElse () 1632 { 1633 Label else_label = if_stack.end_label; 1634 Label end_label = new Label (this); 1635 if_stack.end_label = end_label; 1636 if (reachableHere ()) 1637 { 1638 int growth = SP-if_stack.start_stack_size; 1639 if_stack.stack_growth = growth; 1640 if (growth > 0) 1641 { 1642 if_stack.then_stacked_types = new Type[growth]; 1643 System.arraycopy (stack_types, if_stack.start_stack_size, 1644 if_stack.then_stacked_types, 0, growth); 1645 } 1646 else 1647 if_stack.then_stacked_types = new Type[0]; emitGoto (end_label); 1649 } 1650 while (SP > if_stack.start_stack_size) 1651 popType(); 1652 SP = if_stack.start_stack_size; 1653 if (else_label != null) 1654 else_label.define (this); 1655 if_stack.doing_else = true; 1656 } 1657 1658 1659 public final void emitFi () 1660 { 1661 boolean make_unreachable = false; 1662 if (! if_stack.doing_else) 1663 { if (reachableHere () 1665 && SP != if_stack.start_stack_size) 1666 throw new Error ("at PC "+PC+" then clause grows stack with no else clause"); 1667 } 1668 else if (if_stack.then_stacked_types != null) 1669 { 1670 int then_clause_stack_size 1671 = if_stack.start_stack_size + if_stack.stack_growth; 1672 if (! reachableHere ()) 1673 { 1674 if (if_stack.stack_growth > 0) 1675 System.arraycopy (if_stack.then_stacked_types, 0, 1676 stack_types, if_stack.start_stack_size, 1677 if_stack.stack_growth); 1678 SP = then_clause_stack_size; 1679 } 1680 else if (SP != then_clause_stack_size) 1681 throw new Error ("at PC "+PC+": SP at end of 'then' was " + 1682 then_clause_stack_size 1683 + " while SP at end of 'else' was " + SP); 1684 } 1685 else if (unreachable_here) 1686 make_unreachable = true; 1687 1688 if (if_stack.end_label != null) 1689 if_stack.end_label.define (this); 1690 if (make_unreachable) 1691 setUnreachable(); 1692 if_stack = if_stack.previous; 1694 } 1695 1696 public final void emitConvert (Type from, Type to) 1697 { 1698 String to_sig = to.getSignature(); 1699 String from_sig = from.getSignature(); 1700 int op = -1; 1701 if (to_sig.length() == 1 || from_sig.length() == 1) 1702 { 1703 char to_sig0 = to_sig.charAt(0); 1704 char from_sig0 = from_sig.charAt(0); 1705 if (from_sig0 == to_sig0) 1706 return; 1707 if (from.size < 4) 1708 from_sig0 = 'I'; 1709 if (to.size < 4) 1710 { 1711 emitConvert(from, Type.int_type); 1712 from_sig0 = 'I'; 1713 } 1714 if (from_sig0 == to_sig0) 1715 return; 1716 switch (from_sig0) 1717 { 1718 case 'I': 1719 switch (to_sig0) 1720 { 1721 case 'B': op = 145; break; case 'C': op = 146; break; case 'S': op = 147; break; case 'J': op = 133; break; case 'F': op = 134; break; case 'D': op = 135; break; } 1728 break; 1729 case 'J': 1730 switch (to_sig0) 1731 { 1732 case 'I': op = 136; break; case 'F': op = 137; break; case 'D': op = 138; break; } 1736 break; 1737 case 'F': 1738 switch (to_sig0) 1739 { 1740 case 'I': op = 139; break; case 'J': op = 140; break; case 'D': op = 141; break; } 1744 break; 1745 case 'D': 1746 switch (to_sig0) 1747 { 1748 case 'I': op = 142; break; case 'J': op = 143; break; case 'F': op = 144; break; } 1752 break; 1753 } 1754 } 1755 if (op < 0) 1756 throw new Error ("unsupported CodeAttr.emitConvert"); 1757 reserve(1); 1758 popType(); 1759 put1(op); 1760 pushType(to); 1761 } 1762 1763 private void emitCheckcast (Type type, int opcode) 1764 { 1765 reserve(3); 1766 popType(); 1767 put1(opcode); 1768 if (type instanceof ArrayType) 1769 { 1770 ArrayType atype = (ArrayType) type; 1771 CpoolUtf8 name = getConstants().addUtf8(atype.signature); 1772 putIndex2(getConstants().addClass(name)); 1773 } 1774 else if (type instanceof ClassType) 1775 { 1776 putIndex2(getConstants().addClass((ClassType) type)); 1777 } 1778 else 1779 throw new Error ("unimplemented type " + type 1780 + " in emitCheckcast/emitInstanceof"); 1781 } 1782 1783 public static boolean castNeeded (Type top, Type required) 1784 { 1785 for (;;) 1786 { 1787 if (required instanceof ClassType 1788 && top instanceof ClassType 1789 && ((ClassType) top).isSubclass((ClassType) required)) 1790 return false; 1791 else if (required instanceof ArrayType 1792 && top instanceof ArrayType) 1793 { 1794 required = ((ArrayType) required).getComponentType(); 1795 top = ((ArrayType) top).getComponentType(); 1796 continue; 1797 } 1798 return true; 1799 } 1800 } 1801 1802 public void emitCheckcast (Type type) 1803 { 1804 if (castNeeded(topType(), type)) 1805 { 1806 emitCheckcast(type, 192); 1807 pushType(type); 1808 } 1809 } 1810 1811 public void emitInstanceof (Type type) 1812 { 1813 emitCheckcast(type, 193); 1814 pushType(Type.boolean_type); 1815 } 1816 1817 public final void emitThrow () 1818 { 1819 popType(); 1820 reserve(1); 1821 put1 (191); setUnreachable(); 1823 } 1824 1825 public final void emitMonitorEnter () 1826 { 1827 popType(); 1828 reserve(1); 1829 put1 (194); } 1831 1832 public final void emitMonitorExit () 1833 { 1834 popType(); 1835 reserve(1); 1836 put1 (195); } 1838 1839 1842 public void doPendingFinalizers (TryState limit) 1843 { 1844 TryState stack = try_stack; 1845 1846 1849 boolean saveResult = ! getMethod().getReturnType().isVoid(); 1850 Variable result = null; 1851 1852 while (stack != limit) 1853 { 1854 if (stack.finally_subr != null && stack.finally_ret_addr == null) { 1857 if (saveResult && result == null) 1858 { 1859 result = addLocal(topType()); 1860 emitStore(result); 1861 } 1862 emitJsr(stack.finally_subr); 1863 } 1864 1865 stack = stack.previous; 1866 } 1867 1868 if (result != null) 1869 emitLoad(result); 1870 } 1875 1876 1882 public final void emitReturn () 1883 { 1884 doPendingFinalizers(null); 1885 if (getMethod().getReturnType().size == 0) 1886 { 1887 reserve(1); 1888 put1(177); } 1890 else 1891 emitTypedOp (172, popType().promote()); 1892 setUnreachable(); 1893 } 1894 1895 1896 public void addHandler (int start_pc, int end_pc, 1897 int handler_pc, int catch_type) 1898 { 1899 int index = 4 * exception_table_length; 1900 if (exception_table == null) 1901 { 1902 exception_table = new short[20]; 1903 } 1904 else if (exception_table.length <= index) 1905 { 1906 short[] new_table = new short[2 * exception_table.length]; 1907 System.arraycopy(exception_table, 0, new_table, 0, index); 1908 exception_table = new_table; 1909 } 1910 exception_table[index++] = (short) start_pc; 1911 exception_table[index++] = (short) end_pc; 1912 exception_table[index++] = (short) handler_pc; 1913 exception_table[index++] = (short) catch_type; 1914 exception_table_length++; 1915 } 1916 1917 1918 public void addHandler (Label start_try, Label end_try, 1919 ClassType catch_type) 1920 { 1921 ConstantPool constants = getConstants(); 1922 int catch_type_index; 1923 if (catch_type == null) 1924 catch_type_index = 0; 1925 else 1926 catch_type_index = constants.addClass(catch_type).index; 1927 fixupAdd(FIXUP_TRY, start_try); 1928 fixupAdd(FIXUP_CATCH, catch_type_index, end_try); 1929 } 1930 1931 1938 public void emitWithCleanupStart () 1939 { 1940 int savedSP = SP; 1941 SP = 0; 1942 emitTryStart(false, null); 1943 SP = savedSP; 1944 } 1945 1946 1949 public void emitWithCleanupCatch (Variable catchVar) 1950 { 1951 emitTryEnd(); 1952 Type[] savedTypes; 1953 if (SP > 0) 1954 { 1955 savedTypes = new Type[SP]; 1956 System.arraycopy(stack_types, 0, savedTypes, 0, SP); 1957 SP = 0; 1958 } 1959 else 1960 savedTypes = null; 1961 try_stack.savedTypes = savedTypes; 1962 1963 try_stack.saved_result = catchVar; 1964 int save_SP = SP; 1965 emitCatchStart(catchVar); 1966 } 1967 1968 1969 1970 public void emitWithCleanupDone () 1971 { 1972 Variable catchVar = try_stack.saved_result; 1973 try_stack.saved_result = null; 1974 if (catchVar != null) 1975 emitLoad(catchVar); 1976 emitThrow(); 1977 emitCatchEnd(); 1978 Type[] savedTypes = try_stack.savedTypes; 1979 emitTryCatchEnd(); 1980 if (savedTypes != null) 1981 { 1982 SP = savedTypes.length; 1983 if (SP >= stack_types.length) 1984 stack_types = savedTypes; 1985 else 1986 System.arraycopy(savedTypes, 0, stack_types, 0, SP); 1987 } 1988 else 1989 SP = 0; 1990 } 1991 1992 1993 public void emitTryStart(boolean has_finally, Type result_type) 1994 { 1995 if (result_type != null && result_type.isVoid()) 1996 result_type = null; 1997 Variable[] savedStack = null; 1998 if (result_type != null || SP > 0) 1999 pushScope(); 2000 if (SP > 0) 2001 { 2002 savedStack = new Variable[SP]; 2003 int i = 0; 2004 while (SP > 0) 2005 { 2006 Variable var = addLocal(topType()); 2007 emitStore(var); 2008 savedStack[i++] = var; 2009 } 2010 } 2011 TryState try_state = new TryState(this); 2012 try_state.savedStack = savedStack; 2013 if (result_type != null) 2014 try_state.saved_result = addLocal(result_type); 2015 if (has_finally) 2016 try_state.finally_subr = new Label(); 2017 } 2018 2019 public void emitTryEnd() 2020 { 2021 if (try_stack.end_label == null) 2022 { 2023 if (try_stack.saved_result != null && reachableHere()) 2024 emitStore(try_stack.saved_result); 2025 try_stack.end_label = new Label(); 2026 if (reachableHere()) 2027 { 2028 if (try_stack.finally_subr != null) 2029 emitJsr(try_stack.finally_subr); 2030 emitGoto(try_stack.end_label); 2031 } 2032 try_stack.end_try = getLabel(); 2033 } 2034 } 2035 2036 public void emitCatchStart(Variable var) 2037 { 2038 emitTryEnd(); 2039 SP = 0; 2040 if (try_stack.try_type != null) 2041 emitCatchEnd(); 2042 ClassType type = var == null ? null : (ClassType) var.getType(); 2043 try_stack.try_type = type; 2044 addHandler(try_stack.start_try, try_stack.end_try, type); 2045 if (var != null) 2046 { 2047 pushType(type); 2048 emitStore(var); 2049 } 2050 else 2051 pushType(Type.throwable_type); 2052 } 2053 2054 public void emitCatchEnd() 2055 { 2056 if (reachableHere()) 2057 { 2058 if (try_stack.saved_result != null) 2059 emitStore(try_stack.saved_result); 2060 if (try_stack.finally_subr != null) 2061 emitJsr(try_stack.finally_subr); 2062 emitGoto(try_stack.end_label); 2063 } 2064 try_stack.try_type = null; 2065 } 2066 2067 public void emitFinallyStart() 2068 { 2069 emitTryEnd(); 2070 if (try_stack.try_type != null) 2071 emitCatchEnd(); 2072 SP = 0; 2073 try_stack.end_try = getLabel(); 2074 2075 pushScope(); 2076 Type except_type = Type.pointer_type; 2077 Variable except = addLocal(except_type); 2078 emitCatchStart(null); 2079 emitStore(except); 2080 emitJsr(try_stack.finally_subr); 2081 emitLoad(except); 2082 emitThrow(); 2083 2084 try_stack.finally_subr.define(this); 2085 Type ret_addr_type = Type.pointer_type; 2086 try_stack.finally_ret_addr = addLocal(ret_addr_type); 2087 pushType(ret_addr_type); 2088 emitStore(try_stack.finally_ret_addr); 2089 } 2090 2091 public void emitFinallyEnd() 2092 { 2093 emitRet(try_stack.finally_ret_addr); 2094 setUnreachable(); 2095 popScope(); 2096 try_stack.finally_subr = null; 2097 } 2098 2099 public void emitTryCatchEnd() 2100 { 2101 if (try_stack.finally_subr != null) 2102 emitFinallyEnd(); 2103 try_stack.end_label.define(this); 2104 Variable[] vars = try_stack.savedStack; 2105 if (vars != null) 2106 { 2107 for (int i = vars.length; --i >= 0; ) 2108 { 2109 Variable v = vars[i]; 2110 if (v != null) { 2111 emitLoad(v); 2112 } 2113 } 2114 } 2115 if (try_stack.saved_result != null) 2116 emitLoad(try_stack.saved_result); 2117 if (try_stack.saved_result != null || vars != null) 2118 popScope(); 2119 try_stack = try_stack.previous; 2120 } 2121 2122 public final TryState getCurrentTry () 2123 { 2124 return try_stack; 2125 } 2126 2127 public final boolean isInTry() 2128 { 2129 return try_stack != null; 2132 } 2133 2134 2137 public void emitTailCall (boolean pop_args, Scope scope) 2138 { 2139 if (pop_args) 2140 { 2141 Method meth = getMethod(); 2142 int arg_slots = ((meth.access_flags & Access.STATIC) != 0) ? 0 : 1; 2143 for (int i = meth.arg_types.length; --i >= 0; ) 2144 arg_slots += meth.arg_types[i].size > 4 ? 2 : 1; 2145 for (int i = meth.arg_types.length; --i >= 0; ) 2146 { 2147 arg_slots -= meth.arg_types[i].size > 4 ? 2 : 1; 2148 emitStore(locals.used [arg_slots]); 2149 } 2150 } 2151 emitGoto(scope.start); 2152 } 2153 2154 public void processFixups () 2155 { 2156 if (fixup_count == 0) 2157 return; 2158 2159 2164 int delta = 0; 2165 int instruction_tail = fixup_count; 2166 fixupAdd(CodeAttr.FIXUP_MOVE, 0, null); 2167 2168 loop1: 2169 for (int i = 0; ; ) 2170 { 2171 int offset = fixup_offsets[i]; 2172 int kind = offset & 15; 2173 offset >>= 4; 2174 Label label = fixup_labels[i]; 2175 switch (kind) 2176 { 2177 case FIXUP_TRY: 2178 case FIXUP_LINE_PC: 2179 i++; 2180 case FIXUP_NONE: 2181 case FIXUP_CASE: 2182 case FIXUP_DELETE3: 2183 break; 2184 case FIXUP_DEFINE: 2185 label.position += delta; 2186 break; 2187 case FIXUP_SWITCH: 2188 delta += 3; break; 2190 case FIXUP_GOTO: 2191 if (label.first_fixup == i + 1 2193 && fixupOffset(i+1) == offset + 3) 2194 { 2195 fixup_offsets[i] = (offset << 4) | FIXUP_DELETE3; 2197 fixup_labels[i] = null; 2198 delta -= 3; 2199 break; 2200 } 2201 case FIXUP_JSR: 2203 if (PC >= 0x8000) 2204 delta += 2; break; 2206 case FIXUP_TRANSFER: 2207 if (PC >= 0x8000) 2208 delta += 5; break; 2210 case FIXUP_MOVE_TO_END: 2211 fixup_labels[instruction_tail] = fixup_labels[i+1]; 2212 instruction_tail = offset; 2213 case FIXUP_MOVE: 2215 int cur_pc = ((i+1) >= fixup_count ? PC 2216 : fixupOffset(fixup_labels[i+1].first_fixup)); 2217 fixup_offsets[i] = (cur_pc << 4) | FIXUP_MOVE; 2218 if (label == null) 2219 break loop1; 2220 else 2221 { 2222 i = label.first_fixup; 2223 int next_pc = fixupOffset(i); 2224 delta = (cur_pc + delta) - next_pc; 2225 continue; 2226 } 2227 default: 2228 throw new Error ("unexpected fixup"); 2229 } 2230 i++; 2231 } 2232 2235 int new_size = PC; 2237 delta = 0; 2239 loop2: 2240 for (int i = 0; i < fixup_count; ) 2241 { 2242 int offset = fixup_offsets[i]; 2243 int kind = offset & 15; 2244 Label label = fixup_labels[i]; 2245 if (label != null && label.position < 0) 2246 throw new Error ("undefined label "+label); 2247 while (label != null 2248 && kind >= FIXUP_GOTO && kind <= FIXUP_TRANSFER2 2249 && label.first_fixup + 1 < fixup_count 2250 && (fixup_offsets[label.first_fixup + 1] 2251 == ((fixup_offsets[label.first_fixup] & 15) | FIXUP_GOTO))) 2252 { 2253 label = fixup_labels[label.first_fixup + 1]; 2257 fixup_labels[i] = label; 2258 } 2259 offset = offset >> 4; 2260 switch (kind) 2261 { 2262 case FIXUP_TRY: 2263 case FIXUP_LINE_PC: 2264 i++; 2265 case FIXUP_NONE: 2266 case FIXUP_CASE: 2267 break; 2268 case FIXUP_DELETE3: 2269 delta -= 3; 2270 new_size -= 3; 2271 break; 2272 case FIXUP_DEFINE: 2273 label.position = offset + delta; 2274 break; 2275 case FIXUP_SWITCH: 2276 int padding = 3 - (offset+delta) & 3; 2277 delta += padding; 2278 new_size += padding; 2279 break; 2280 case FIXUP_GOTO: 2281 case FIXUP_JSR: 2282 case FIXUP_TRANSFER: 2283 int rel = label.position - (offset+delta); 2284 if ((short) rel == rel) 2285 { 2286 fixup_offsets[i] = (offset << 4) | FIXUP_TRANSFER2; 2287 } 2288 else 2289 { 2290 delta += kind == FIXUP_TRANSFER ? 5 : 2; new_size += kind == FIXUP_TRANSFER ? 5 : 2; } 2293 break; 2294 case FIXUP_MOVE: 2295 if (label == null) 2296 break loop2; 2297 else 2298 { 2299 i = label.first_fixup; 2300 int next_pc = fixupOffset(i); 2301 delta = (offset + delta) - next_pc; 2302 continue; 2303 } 2304 default: 2305 throw new Error ("unexpected fixup"); 2306 } 2307 i++; 2308 } 2309 2310 byte[] new_code = new byte[new_size]; 2311 int new_pc = 0; 2312 int next_fixup_index = 0; 2313 int next_fixup_offset = fixupOffset(0); 2314 loop3: 2315 for (int old_pc = 0; ; ) 2316 { 2317 if (old_pc < next_fixup_offset) 2318 { 2319 new_code[new_pc++] = code[old_pc++]; 2320 } 2321 else 2322 { 2323 int kind = fixup_offsets[next_fixup_index] & 15; 2324 Label label = fixup_labels[next_fixup_index]; 2325 switch (kind) 2326 { 2327 case FIXUP_NONE: 2328 case FIXUP_DEFINE: 2329 break; 2330 case FIXUP_DELETE3: 2331 old_pc += 3; 2332 break; 2333 case FIXUP_TRANSFER2: 2334 delta = label.position - new_pc; 2335 new_code[new_pc++] = code[old_pc]; 2336 new_code[new_pc++] = (byte) (delta >> 8); 2337 new_code[new_pc++] = (byte) (delta & 0xFF); 2338 old_pc += 3; 2339 break; 2340 case FIXUP_GOTO: 2341 case FIXUP_JSR: 2342 case FIXUP_TRANSFER: 2343 delta = label.position - new_pc; 2344 byte opcode = code[old_pc]; 2345 if (kind == FIXUP_TRANSFER) 2346 { 2347 opcode = invert_opcode(opcode); 2349 new_code[new_pc++] = opcode; 2350 new_code[new_pc++] = 0; 2351 new_code[new_pc++] = 8; opcode = (byte) 200; } 2354 else 2355 { 2356 opcode = (byte) (opcode + (200-167)); 2358 } 2359 new_code[new_pc++] = opcode; 2360 new_code[new_pc++] = (byte) (delta >> 24); 2361 new_code[new_pc++] = (byte) (delta >> 16); 2362 new_code[new_pc++] = (byte) (delta >> 8); 2363 new_code[new_pc++] = (byte) (delta & 0xFF); 2364 old_pc += 3; 2365 break; 2366 case FIXUP_SWITCH: 2367 int padding = 3 - new_pc & 3; 2368 int switch_start = new_pc; 2369 new_code[new_pc++] = code[old_pc++]; 2370 while (--padding >= 0) 2371 new_code[new_pc++] = 0; 2372 while (next_fixup_index < fixup_count 2373 && fixupKind(next_fixup_index + 1) == FIXUP_CASE) 2374 { 2375 next_fixup_index++; 2376 int offset = fixupOffset(next_fixup_index); 2377 while (old_pc < offset) 2378 new_code[new_pc++] = code[old_pc++]; 2379 delta = (fixup_labels[next_fixup_index].position 2380 - switch_start); 2381 new_code[new_pc++] = (byte) (delta >> 24); 2382 new_code[new_pc++] = (byte) (delta >> 16); 2383 new_code[new_pc++] = (byte) (delta >> 8); 2384 new_code[new_pc++] = (byte) (delta & 0xFF); 2385 old_pc += 4; 2386 } 2387 break; 2388 case FIXUP_TRY: 2389 addHandler(fixup_labels[next_fixup_index].position, 2390 fixup_labels[next_fixup_index+1].position, 2391 new_pc, 2392 fixupOffset(next_fixup_index+1)); 2393 next_fixup_index++; 2394 break; 2395 case FIXUP_LINE_PC: 2396 if (lines == null) 2397 lines = new LineNumbersAttr(this); 2398 next_fixup_index++; 2399 lines.put(fixupOffset(next_fixup_index), new_pc); 2400 break; 2401 case FIXUP_MOVE: 2402 if (label == null) 2403 break loop3; 2404 else 2405 { 2406 next_fixup_index = label.first_fixup; 2407 old_pc = fixupOffset(next_fixup_index); 2408 next_fixup_offset = old_pc; 2409 if (label.position != new_pc) 2410 throw new Error ("bad pc"); 2411 continue; 2412 } 2413 default: 2414 throw new Error ("unexpected fixup"); 2415 } 2416 next_fixup_index++; 2417 next_fixup_offset = fixupOffset(next_fixup_index); 2418 } 2419 } 2420 if (new_size != new_pc) 2421 throw new Error ("PC confusion new_pc:"+new_pc+" new_size:"+new_size); 2422 PC = new_size; 2423 code = new_code; 2424 fixup_count = 0; 2425 fixup_labels = null; 2426 fixup_offsets = null; 2427 } 2428 2429 public void assignConstants (ClassType cl) 2430 { 2431 if (locals != null && locals.container == null && ! locals.isEmpty()) 2432 locals.addToFrontOf(this); 2433 processFixups(); 2434 if (instructionLineMode) 2435 { 2436 if (lines == null) 2439 lines = new LineNumbersAttr(this); 2440 lines.linenumber_count = 0; 2441 int codeLen = getCodeLength(); 2442 for (int i = 0; i < codeLen; i++) 2443 lines.put(i, i); 2444 } 2445 super.assignConstants(cl); 2446 Attribute.assignConstants(this, cl); 2447 } 2448 2449 public final int getLength() 2450 { 2451 return 12 + getCodeLength() + 8 * exception_table_length 2452 + Attribute.getLengthAll(this); 2453 } 2454 2455 public void write (DataOutputStream dstr) throws java.io.IOException 2456 { 2457 dstr.writeShort (max_stack); 2458 dstr.writeShort (max_locals); 2459 dstr.writeInt (PC); 2460 dstr.write (code, 0, PC); 2461 2462 dstr.writeShort (exception_table_length); 2463 int count = exception_table_length; 2464 for (int i = 0; --count >= 0; i += 4) 2465 { 2466 dstr.writeShort(exception_table[i]); 2467 dstr.writeShort(exception_table[i+1]); 2468 dstr.writeShort(exception_table[i+2]); 2469 dstr.writeShort(exception_table[i+3]); 2470 } 2471 2472 Attribute.writeAll(this, dstr); 2473 } 2474 2475 public void print (ClassTypeWriter dst) 2476 { 2477 dst.print("Attribute \""); 2478 dst.print(getName()); 2479 dst.print("\", length:"); 2480 dst.print(getLength()); 2481 dst.print(", max_stack:"); 2482 dst.print(max_stack); 2483 dst.print(", max_locals:"); 2484 dst.print(max_locals); 2485 dst.print(", code_length:"); 2486 int length = getCodeLength(); 2487 dst.println(length); 2488 disAssemble(dst, 0, length); 2489 if (exception_table_length > 0) 2490 { 2491 dst.print("Exceptions (count: "); 2492 dst.print(exception_table_length); 2493 dst.println("):"); 2494 int count = exception_table_length; 2495 for (int i = 0; --count >= 0; i += 4) 2496 { 2497 dst.print(" start: "); 2498 dst.print(exception_table[i] & 0xffff); 2499 dst.print(", end: "); 2500 dst.print(exception_table[i+1] & 0xffff); 2501 dst.print(", handler: "); 2502 dst.print(exception_table[i+2] & 0xffff); 2503 dst.print(", type: "); 2504 int catch_type_index = exception_table[i+3] & 0xffff; 2505 if (catch_type_index == 0) 2506 dst.print("0 /* finally */"); 2507 else 2508 { 2509 dst.printOptionalIndex(catch_type_index); 2510 dst.printConstantTersely(catch_type_index, ConstantPool.CLASS); 2511 } 2512 dst.println(); 2513 } 2514 } 2515 dst.printAttributes(this); 2516 } 2517 2518 2599 2600 public void disAssemble (ClassTypeWriter dst, int start, int limit) 2601 { 2602 boolean wide = false; 2603 for (int i = start; i < limit; ) 2604 { 2605 int oldpc = i++; 2606 int op = code[oldpc] & 0xff; 2607 String str = Integer.toString(oldpc); 2608 int printConstant = 0; 2609 int j = str.length(); 2610 while (++j <= 3) dst.print(' '); 2611 dst.print(str); 2612 dst.print(": "); 2613 if (op < 120) 2615 { 2616 if (op < 87) 2617 { 2618 if (op < 3) print("nop;aconst_null;iconst_m1;", op, dst); 2619 else if (op < 9) { dst.print("iconst_"); dst.print(op-3); } 2620 else if (op < 16) { 2622 char typ; 2623 if (op < 11) { typ = 'l'; op -= 9; } 2624 else if (op < 14) { typ = 'f'; op -= 11; } 2625 else { typ = 'd'; op -= 14; } 2626 dst.print(typ); dst.print("const_"); dst.print(op); 2627 } 2628 else if (op < 21) 2629 { 2630 if (op < 18) { 2632 print("bipush ;sipush ;", op-16, dst); 2633 int constant; 2634 if (op == 16) constant = code[i++]; 2635 else { constant = (short) readUnsignedShort(i); i+=2;} 2636 dst.print(constant); 2637 } 2638 else { 2640 printConstant = op == 18 ? 1 : 2; 2641 print("ldc;ldc_w;ldc2_w;", op-18, dst); 2642 } 2643 } 2644 else { 2646 String load_or_store; 2647 if (op < 54) { load_or_store = "load"; } 2648 else { load_or_store = "store"; op -=(54-21); } 2649 int index; if (op < 26) { index = -1; op -= 21; } 2651 else if (op < 46) { op -= 26; index = op % 4; op >>= 2; } 2652 else { index = -2; op -= 46; } 2653 dst.print("ilfdabcs".charAt(op)); 2654 if (index == -2) dst.write('a'); 2655 dst.print(load_or_store); 2656 if (index >= 0) { dst.write('_'); dst.print(index); } 2657 else if (index == -1) 2658 { 2659 if (wide) { index = readUnsignedShort(i); i += 2; } 2660 else { index = code[i] & 0xff; i++; } 2661 wide = false; 2662 dst.print(' '); 2663 dst.print(index); 2664 } 2665 } 2666 } 2667 else { 2669 if (op < 96) 2670 print("pop;pop2;dup;dup_x1;dup_x2;dup2;dup2_x1;dup2_x2;swap;" 2671 , op-87, dst); 2672 else { 2674 dst.print("ilfda".charAt((op-96) % 4)); 2675 print("add;sub;mul;div;rem;neg;", (op-96)>>2, dst); 2676 } 2677 } 2678 } 2679 else { 2681 if (op < 170) 2682 { 2683 if (op < 132) { 2685 dst.print((op & 1) == 0 ? 'i' : 'l'); 2686 print("shl;shr;ushr;and;or;xor;", (op-120)>>1, dst); 2687 } 2688 else if (op == 132) { 2690 int var_index; 2691 int constant; 2692 dst.print("iinc"); 2693 if (! wide) 2694 { 2695 var_index = 0xff & code[i++]; 2696 constant = code[i++]; 2697 } 2698 else 2699 { 2700 var_index = readUnsignedShort(i); 2701 i += 2; 2702 constant = (short) readUnsignedShort(i); 2703 i += 2; 2704 wide = false; 2705 } 2706 dst.print(' '); dst.print(var_index); 2707 dst.print(' '); dst.print(constant); 2708 } 2709 else if (op < 148) { 2711 dst.print("ilfdi".charAt((op-133) / 3)); 2712 dst.print('2'); 2713 dst.print("lfdifdildilfbcs".charAt(op-133)); 2714 } 2715 else if (op < 153) print("lcmp;fcmpl;fcmpg;dcmpl;dcmpg;", op-148, dst); 2717 else if (op < 169) 2718 { 2719 if (op < 159) 2720 { 2721 dst.print("if"); 2722 print("eq;ne;lt;ge;gt;le;", op-153, dst); 2723 } 2724 else if (op < 167) 2725 { 2726 if (op < 165) { dst.print("if_icmp"); } 2727 else { dst.print("if_acmp"); op -= 165-159; } 2728 print("eq;ne;lt;ge;gt;le;", op-159, dst); 2729 } 2730 else 2731 print("goto;jsr;", op-167, dst); 2732 int delta = (short) readUnsignedShort(i); 2733 i += 2; 2734 dst.print(' '); dst.print(oldpc+delta); 2735 } 2736 else 2737 { 2738 int index; 2739 dst.print("ret "); 2740 if (wide) { index = readUnsignedShort(i); index += 2; } 2741 else { index = code[i] & 0xff; i++; } 2742 wide = false; 2743 dst.print(index); 2744 } 2745 } 2746 else 2747 { 2748 if (op < 172) { 2750 if (fixup_count == 0) 2751 i = (i + 3) & ~3; int code_offset = readInt(i); i += 4; 2753 if (op == 170) 2754 { 2755 dst.print("tableswitch"); 2756 int low = readInt(i); i += 4; 2757 int high = readInt(i); i += 4; 2758 dst.print(" low: "); dst.print(low); 2759 dst.print(" high: "); dst.print(high); 2760 dst.print(" default: "); dst.print(oldpc+code_offset); 2761 for (; low <= high; low++) 2762 { 2763 code_offset = readInt(i); i += 4; 2764 dst.println(); 2765 dst.print(" "); dst.print(low); 2766 dst.print(": "); dst.print(oldpc + code_offset); 2767 } 2768 } 2769 else 2770 { 2771 dst.print("lookupswitch"); 2772 int npairs = readInt(i); i += 4; 2773 dst.print(" npairs: "); dst.print(npairs); 2774 dst.print(" default: "); dst.print(oldpc+code_offset); 2775 while (--npairs >= 0) 2776 { 2777 int match = readInt(i); i += 4; 2778 code_offset = readInt(i); i += 4; 2779 dst.println(); 2780 dst.print(" "); dst.print(match); 2781 dst.print(": "); dst.print(oldpc + code_offset); 2782 } 2783 } 2784 } 2785 else if (op < 178) { 2787 if (op < 177) dst.print("ilfda".charAt(op-172)); 2788 dst.print("return"); 2789 } 2790 else if (op < 182) { 2792 print("getstatic;putstatic;getfield;putfield;", op-178, dst); 2793 printConstant = 2; 2794 } 2795 else if (op < 185) { 2797 dst.print("invoke"); 2798 print("virtual;special;static;", op-182, dst); 2799 printConstant = 2; 2800 } 2801 else if (op == 185) { 2803 dst.print("invokeinterface ("); 2804 int index = readUnsignedShort(i); 2805 i += 2; 2806 int args = 0xff & code[i]; 2807 i += 2; 2808 dst.print(args + " args)"); 2809 dst.printConstantOperand(index); 2810 } 2811 else if (op < 196) 2812 { 2813 print("186;new;newarray;anewarray;arraylength;athrow;checkcast;instanceof;monitorenter;monitorexit;", op-186, dst); 2814 if (op == 187 || op == 189 || op == 192 || op == 193) 2815 printConstant = 2; 2816 else if (op == 188) { 2818 int type = code[i++]; 2819 dst.print(' '); 2820 if (type >= 4 && type <= 11) 2821 print("boolean;char;float;double;byte;short;int;long;", 2822 type-4, dst); 2823 else 2824 dst.print(type); 2825 } 2826 2827 } 2828 else if (op == 196) { 2830 dst.print("wide"); 2831 wide = true; 2832 } 2833 else if (op == 197) 2834 { 2835 dst.print("multianewarray"); 2836 int index = readUnsignedShort(i); 2837 i += 2; 2838 dst.printConstantOperand(index); 2839 int dims = 0xff & code[i++]; 2840 dst.print(' '); 2841 dst.print(dims); 2842 } 2843 else if (op < 200) 2844 { 2845 print("ifnull;ifnonnull;", op-198, dst); 2846 int delta = (short) readUnsignedShort(i); 2847 i += 2; 2848 dst.print(' '); dst.print(oldpc+delta); 2849 } 2850 else if (op < 202) 2851 { 2852 print("goto_w;jsr_w;", op-200, dst); 2853 int delta = readInt(i); 2854 i += 4; 2855 dst.print(' '); dst.print(oldpc+delta); 2856 } 2857 else 2858 dst.print(op); 2859 } 2860 } 2861 if (printConstant > 0) 2862 { 2863 int index; 2864 if (printConstant == 1) index = 0xff & code[i++]; 2865 else { index = readUnsignedShort(i); i += 2; } 2866 dst.printConstantOperand(index); 2867 } 2868 dst.println(); 2869 } 2870 } 2871 2872 private int readUnsignedShort(int offset) 2873 { 2874 return ((0xff & code[offset]) << 8) | (0xff & code[offset+1]); 2875 } 2876 2877 private int readInt(int offset) 2878 { 2879 return (readUnsignedShort(offset) << 16) | readUnsignedShort(offset+2); 2880 } 2881 2882 2894 2895 2896 private void print (String str, int i, PrintWriter dst) 2897 { 2898 int last = 0; 2899 int pos = -1; 2900 for (; i >= 0; i--) 2901 { 2902 last = ++pos; 2903 pos = str.indexOf(';', last); 2904 } 2905 dst.write(str, last, pos-last); 2906 } 2907 2908 2909 public Type[] saveStackTypeState(boolean clear) 2910 { 2911 if (SP == 0) 2912 return null; 2913 Type[] typeState = new Type[SP]; 2914 System.arraycopy(stack_types, 0, typeState, 0, SP); 2915 if (clear) 2916 SP = 0; 2917 return typeState; 2918 } 2919 2920 2921 public void restoreStackTypeState (Type[] save) 2922 { 2923 if (save == null) 2924 SP = 0; 2925 else 2926 { 2927 SP = save.length; 2928 System.arraycopy(save, 0, stack_types, 0, SP); 2929 } 2930 } 2931 2932 public int beginFragment (Label start, Label after) 2933 { 2934 int i = fixup_count; 2935 fixupAdd(FIXUP_MOVE_TO_END, after); 2936 start.define(this); 2937 return i; 2938 } 2939 2940 2943 public void endFragment (int cookie) 2944 { 2945 fixup_offsets[cookie] = (fixup_count << 4) | FIXUP_MOVE_TO_END; 2946 Label after = fixup_labels[cookie]; 2947 fixupAdd(FIXUP_MOVE, 0, null); 2948 after.define(this); 2949 } 2950} 2951 | Popular Tags |