1 30 package com.tc.asm; 31 32 39 class MethodWriter implements MethodVisitor { 40 41 44 MethodWriter next; 45 46 49 ClassWriter cw; 50 51 54 private int access; 55 56 60 private int name; 61 62 66 private int desc; 67 68 71 private String descriptor; 72 73 79 int classReaderOffset; 80 81 87 int classReaderLength; 88 89 92 String signature; 93 94 97 int exceptionCount; 98 99 104 int[] exceptions; 105 106 109 private ByteVector annd; 110 111 114 private AnnotationWriter anns; 115 116 119 private AnnotationWriter ianns; 120 121 125 private AnnotationWriter[] panns; 126 127 131 private AnnotationWriter[] ipanns; 132 133 136 private Attribute attrs; 137 138 141 private ByteVector code = new ByteVector(); 142 143 146 private int maxStack; 147 148 151 private int maxLocals; 152 153 156 private int catchCount; 157 158 161 private Handler catchTable; 162 163 166 private Handler lastHandler; 167 168 171 private int localVarCount; 172 173 176 private ByteVector localVar; 177 178 181 private int localVarTypeCount; 182 183 186 private ByteVector localVarType; 187 188 191 private int lineNumberCount; 192 193 196 private ByteVector lineNumber; 197 198 201 private Attribute cattrs; 202 203 206 private boolean resize; 207 208 217 218 222 private final boolean computeMaxs; 223 224 231 private int stackSize; 232 233 240 private int maxStackSize; 241 242 246 private Label currentBlock; 247 248 254 private Label blockStack; 255 256 261 private final static int[] SIZE; 262 263 267 270 static { 271 int i; 272 int[] b = new int[202]; 273 String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD" 274 + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD" 275 + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED" 276 + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE"; 277 for (i = 0; i < b.length; ++i) { 278 b[i] = s.charAt(i) - 'E'; 279 } 280 SIZE = b; 281 282 } 495 496 500 513 MethodWriter( 514 final ClassWriter cw, 515 final int access, 516 final String name, 517 final String desc, 518 final String signature, 519 final String [] exceptions, 520 final boolean computeMaxs) 521 { 522 if (cw.firstMethod == null) { 523 cw.firstMethod = this; 524 } else { 525 cw.lastMethod.next = this; 526 } 527 cw.lastMethod = this; 528 this.cw = cw; 529 this.access = access; 530 this.name = cw.newUTF8(name); 531 this.desc = cw.newUTF8(desc); 532 this.descriptor = desc; 533 this.signature = signature; 534 if (exceptions != null && exceptions.length > 0) { 535 exceptionCount = exceptions.length; 536 this.exceptions = new int[exceptionCount]; 537 for (int i = 0; i < exceptionCount; ++i) { 538 this.exceptions[i] = cw.newClass(exceptions[i]); 539 } 540 } 541 this.computeMaxs = computeMaxs; 542 if (computeMaxs) { 543 int size = getArgumentsAndReturnSizes(desc) >> 2; 545 if ((access & Opcodes.ACC_STATIC) != 0) { 546 --size; 547 } 548 maxLocals = size; 549 currentBlock = new Label(); 551 currentBlock.pushed = true; 552 blockStack = currentBlock; 553 } 554 } 555 556 560 public AnnotationVisitor visitAnnotationDefault() { 561 annd = new ByteVector(); 562 return new AnnotationWriter(cw, false, annd, null, 0); 563 } 564 565 public AnnotationVisitor visitAnnotation( 566 final String desc, 567 final boolean visible) 568 { 569 ByteVector bv = new ByteVector(); 570 bv.putShort(cw.newUTF8(desc)).putShort(0); 572 AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); 573 if (visible) { 574 aw.next = anns; 575 anns = aw; 576 } else { 577 aw.next = ianns; 578 ianns = aw; 579 } 580 return aw; 581 } 582 583 public AnnotationVisitor visitParameterAnnotation( 584 final int parameter, 585 final String desc, 586 final boolean visible) 587 { 588 ByteVector bv = new ByteVector(); 589 bv.putShort(cw.newUTF8(desc)).putShort(0); 591 AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); 592 if (visible) { 593 if (panns == null) { 594 panns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length]; 595 } 596 aw.next = panns[parameter]; 597 panns[parameter] = aw; 598 } else { 599 if (ipanns == null) { 600 ipanns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length]; 601 } 602 aw.next = ipanns[parameter]; 603 ipanns[parameter] = aw; 604 } 605 return aw; 606 } 607 608 public void visitAttribute(final Attribute attr) { 609 if (attr.isCodeAttribute()) { 610 attr.next = cattrs; 611 cattrs = attr; 612 } else { 613 attr.next = attrs; 614 attrs = attr; 615 } 616 } 617 618 public void visitCode() { 619 } 620 621 public void visitInsn(final int opcode) { 622 if (computeMaxs) { 623 int size = stackSize + SIZE[opcode]; 625 if (size > maxStackSize) { 626 maxStackSize = size; 627 } 628 stackSize = size; 629 if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) 631 || opcode == Opcodes.ATHROW) 632 { 633 if (currentBlock != null) { 634 currentBlock.maxStackSize = maxStackSize; 635 currentBlock = null; 636 } 637 } 638 } 639 code.putByte(opcode); 641 } 642 643 public void visitIntInsn(final int opcode, final int operand) { 644 if (computeMaxs && opcode != Opcodes.NEWARRAY) { 645 int size = stackSize + 1; 648 if (size > maxStackSize) { 649 maxStackSize = size; 650 } 651 stackSize = size; 652 } 653 if (opcode == Opcodes.SIPUSH) { 655 code.put12(opcode, operand); 656 } else { code.put11(opcode, operand); 658 } 659 } 660 661 public void visitVarInsn(final int opcode, final int var) { 662 if (computeMaxs) { 663 if (opcode == Opcodes.RET) { 665 if (currentBlock != null) { 667 currentBlock.maxStackSize = maxStackSize; 668 currentBlock = null; 669 } 670 } else { int size = stackSize + SIZE[opcode]; 672 if (size > maxStackSize) { 673 maxStackSize = size; 674 } 675 stackSize = size; 676 } 677 int n; 679 if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD 680 || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) 681 { 682 n = var + 2; 683 } else { 684 n = var + 1; 685 } 686 if (n > maxLocals) { 687 maxLocals = n; 688 } 689 } 690 if (var < 4 && opcode != Opcodes.RET) { 692 int opt; 693 if (opcode < Opcodes.ISTORE) { 694 695 opt = 26 + ((opcode - Opcodes.ILOAD) << 2) + var; 696 } else { 697 698 opt = 59 + ((opcode - Opcodes.ISTORE) << 2) + var; 699 } 700 code.putByte(opt); 701 } else if (var >= 256) { 702 code.putByte(196 ).put12(opcode, var); 703 } else { 704 code.put11(opcode, var); 705 } 706 } 707 708 public void visitTypeInsn(final int opcode, final String desc) { 709 if (computeMaxs && opcode == Opcodes.NEW) { 710 int size = stackSize + 1; 713 if (size > maxStackSize) { 714 maxStackSize = size; 715 } 716 stackSize = size; 717 } 718 code.put12(opcode, cw.newClass(desc)); 720 } 721 722 public void visitFieldInsn( 723 final int opcode, 724 final String owner, 725 final String name, 726 final String desc) 727 { 728 if (computeMaxs) { 729 int size; 730 char c = desc.charAt(0); 732 switch (opcode) { 733 case Opcodes.GETSTATIC: 734 size = stackSize + (c == 'D' || c == 'J' ? 2 : 1); 735 break; 736 case Opcodes.PUTSTATIC: 737 size = stackSize + (c == 'D' || c == 'J' ? -2 : -1); 738 break; 739 case Opcodes.GETFIELD: 740 size = stackSize + (c == 'D' || c == 'J' ? 1 : 0); 741 break; 742 default: 744 size = stackSize + (c == 'D' || c == 'J' ? -3 : -2); 745 break; 746 } 747 if (size > maxStackSize) { 749 maxStackSize = size; 750 } 751 stackSize = size; 752 } 753 code.put12(opcode, cw.newField(owner, name, desc)); 755 } 756 757 public void visitMethodInsn( 758 final int opcode, 759 final String owner, 760 final String name, 761 final String desc) 762 { 763 boolean itf = opcode == Opcodes.INVOKEINTERFACE; 764 Item i = cw.newMethodItem(owner, name, desc, itf); 765 int argSize = i.intVal; 766 if (computeMaxs) { 767 774 if (argSize == 0) { 775 argSize = getArgumentsAndReturnSizes(desc); 778 i.intVal = argSize; 781 } 782 int size; 783 if (opcode == Opcodes.INVOKESTATIC) { 784 size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1; 785 } else { 786 size = stackSize - (argSize >> 2) + (argSize & 0x03); 787 } 788 if (size > maxStackSize) { 790 maxStackSize = size; 791 } 792 stackSize = size; 793 } 794 if (itf) { 796 if (!computeMaxs) { 797 if (argSize == 0) { 798 argSize = getArgumentsAndReturnSizes(desc); 799 i.intVal = argSize; 800 } 801 } 802 code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0); 803 } else { 804 code.put12(opcode, i.index); 805 } 806 } 807 808 public void visitJumpInsn(final int opcode, final Label label) { 809 if (computeMaxs) { 810 if (opcode == Opcodes.GOTO) { 811 if (currentBlock != null) { 814 currentBlock.maxStackSize = maxStackSize; 815 addSuccessor(stackSize, label); 816 currentBlock = null; 817 } 818 } else if (opcode == Opcodes.JSR) { 819 if (currentBlock != null) { 820 addSuccessor(stackSize + 1, label); 821 } 822 } else { 823 stackSize += SIZE[opcode]; 826 if (currentBlock != null) { 827 addSuccessor(stackSize, label); 828 } 829 } 830 } 831 if (label.resolved && label.position - code.length < Short.MIN_VALUE) { 833 840 if (opcode == Opcodes.GOTO) { 841 code.putByte(200); } else if (opcode == Opcodes.JSR) { 843 code.putByte(201); } else { 845 code.putByte(opcode <= 166 846 ? ((opcode + 1) ^ 1) - 1 847 : opcode ^ 1); 848 code.putShort(8); code.putByte(200); } 851 label.put(this, code, code.length - 1, true); 852 } else { 853 859 code.putByte(opcode); 860 label.put(this, code, code.length - 1, false); 861 } 862 } 863 864 public void visitLabel(final Label label) { 865 if (computeMaxs) { 866 if (currentBlock != null) { 867 currentBlock.maxStackSize = maxStackSize; 869 addSuccessor(stackSize, label); 870 } 871 currentBlock = label; 874 stackSize = 0; 875 maxStackSize = 0; 876 } 877 resize |= label.resolve(this, code.length, code.data); 879 } 880 881 public void visitLdcInsn(final Object cst) { 882 Item i = cw.newConstItem(cst); 883 if (computeMaxs) { 884 int size; 885 if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) { 887 size = stackSize + 2; 888 } else { 889 size = stackSize + 1; 890 } 891 if (size > maxStackSize) { 893 maxStackSize = size; 894 } 895 stackSize = size; 896 } 897 int index = i.index; 899 if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) { 900 code.put12(20 , index); 901 } else if (index >= 256) { 902 code.put12(19 , index); 903 } else { 904 code.put11(Opcodes.LDC, index); 905 } 906 } 907 908 public void visitIincInsn(final int var, final int increment) { 909 if (computeMaxs) { 910 int n = var + 1; 912 if (n > maxLocals) { 913 maxLocals = n; 914 } 915 } 916 if ((var > 255) || (increment > 127) || (increment < -128)) { 918 code.putByte(196 ) 919 .put12(Opcodes.IINC, var) 920 .putShort(increment); 921 } else { 922 code.putByte(Opcodes.IINC).put11(var, increment); 923 } 924 } 925 926 public void visitTableSwitchInsn( 927 final int min, 928 final int max, 929 final Label dflt, 930 final Label labels[]) 931 { 932 if (computeMaxs) { 933 --stackSize; 935 if (currentBlock != null) { 937 currentBlock.maxStackSize = maxStackSize; 938 addSuccessor(stackSize, dflt); 939 for (int i = 0; i < labels.length; ++i) { 940 addSuccessor(stackSize, labels[i]); 941 } 942 currentBlock = null; 943 } 944 } 945 int source = code.length; 947 code.putByte(Opcodes.TABLESWITCH); 948 while (code.length % 4 != 0) { 949 code.putByte(0); 950 } 951 dflt.put(this, code, source, true); 952 code.putInt(min).putInt(max); 953 for (int i = 0; i < labels.length; ++i) { 954 labels[i].put(this, code, source, true); 955 } 956 } 957 958 public void visitLookupSwitchInsn( 959 final Label dflt, 960 final int keys[], 961 final Label labels[]) 962 { 963 if (computeMaxs) { 964 --stackSize; 966 if (currentBlock != null) { 968 currentBlock.maxStackSize = maxStackSize; 969 addSuccessor(stackSize, dflt); 970 for (int i = 0; i < labels.length; ++i) { 971 addSuccessor(stackSize, labels[i]); 972 } 973 currentBlock = null; 974 } 975 } 976 int source = code.length; 978 code.putByte(Opcodes.LOOKUPSWITCH); 979 while (code.length % 4 != 0) { 980 code.putByte(0); 981 } 982 dflt.put(this, code, source, true); 983 code.putInt(labels.length); 984 for (int i = 0; i < labels.length; ++i) { 985 code.putInt(keys[i]); 986 labels[i].put(this, code, source, true); 987 } 988 } 989 990 public void visitMultiANewArrayInsn(final String desc, final int dims) { 991 if (computeMaxs) { 992 stackSize += 1 - dims; 995 } 996 code.put12(Opcodes.MULTIANEWARRAY, cw.newClass(desc)).putByte(dims); 998 } 999 1000 public void visitTryCatchBlock( 1001 final Label start, 1002 final Label end, 1003 final Label handler, 1004 final String type) 1005 { 1006 if (computeMaxs) { 1007 if (!handler.pushed) { 1009 handler.beginStackSize = 1; 1010 handler.pushed = true; 1011 handler.next = blockStack; 1012 blockStack = handler; 1013 } 1014 } 1015 ++catchCount; 1016 Handler h = new Handler(); 1017 h.start = start; 1018 h.end = end; 1019 h.handler = handler; 1020 h.desc = type; 1021 h.type = type != null ? cw.newClass(type) : 0; 1022 if (lastHandler == null) { 1023 catchTable = h; 1024 } else { 1025 lastHandler.next = h; 1026 } 1027 lastHandler = h; 1028 } 1029 1030 public void visitLocalVariable( 1031 final String name, 1032 final String desc, 1033 final String signature, 1034 final Label start, 1035 final Label end, 1036 final int index) 1037 { 1038 if (signature != null) { 1039 if (localVarType == null) { 1040 localVarType = new ByteVector(); 1041 } 1042 ++localVarTypeCount; 1043 localVarType.putShort(start.position) 1044 .putShort(end.position - start.position) 1045 .putShort(cw.newUTF8(name)) 1046 .putShort(cw.newUTF8(signature)) 1047 .putShort(index); 1048 } 1049 if (localVar == null) { 1050 localVar = new ByteVector(); 1051 } 1052 ++localVarCount; 1053 localVar.putShort(start.position) 1054 .putShort(end.position - start.position) 1055 .putShort(cw.newUTF8(name)) 1056 .putShort(cw.newUTF8(desc)) 1057 .putShort(index); 1058 1059 if(computeMaxs) { 1060 char c = desc.charAt(0); 1062 int n = index + ( c=='J' || c=='D' ? 2 : 1); 1063 if (n > maxLocals) { 1064 maxLocals = n; 1065 } 1066 } 1067 } 1068 1069 public void visitLineNumber(final int line, final Label start) { 1070 if (lineNumber == null) { 1071 lineNumber = new ByteVector(); 1072 } 1073 ++lineNumberCount; 1074 lineNumber.putShort(start.position); 1075 lineNumber.putShort(line); 1076 } 1077 1078 public void visitMaxs(final int maxStack, final int maxLocals) { 1079 if (computeMaxs) { 1080 int max = 0; 1082 1092 Label stack = blockStack; 1093 while (stack != null) { 1094 Label l = stack; 1096 stack = stack.next; 1097 int start = l.beginStackSize; 1099 int blockMax = start + l.maxStackSize; 1100 if (blockMax > max) { 1102 max = blockMax; 1103 } 1104 Edge b = l.successors; 1106 while (b != null) { 1107 l = b.successor; 1108 if (!l.pushed) { 1111 l.beginStackSize = start + b.stackSize; 1114 l.pushed = true; 1116 l.next = stack; 1117 stack = l; 1118 } 1119 b = b.next; 1120 } 1121 } 1122 this.maxStack = max; 1123 } else { 1124 this.maxStack = maxStack; 1125 this.maxLocals = maxLocals; 1126 } 1127 } 1128 1129 public void visitEnd() { 1130 } 1131 1132 1136 1146 private static int getArgumentsAndReturnSizes(final String desc) { 1147 int n = 1; 1148 int c = 1; 1149 while (true) { 1150 char car = desc.charAt(c++); 1151 if (car == ')') { 1152 car = desc.charAt(c); 1153 return n << 2 1154 | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1)); 1155 } else if (car == 'L') { 1156 while (desc.charAt(c++) != ';') { 1157 } 1158 n += 1; 1159 } else if (car == '[') { 1160 while ((car = desc.charAt(c)) == '[') { 1161 ++c; 1162 } 1163 if (car == 'D' || car == 'J') { 1164 n -= 1; 1165 } 1166 } else if (car == 'D' || car == 'J') { 1167 n += 2; 1168 } else { 1169 n += 1; 1170 } 1171 } 1172 } 1173 1174 1180 private void addSuccessor(final int stackSize, final Label successor) { 1181 Edge b = new Edge(); 1182 b.stackSize = stackSize; 1184 b.successor = successor; 1185 b.next = currentBlock.successors; 1187 currentBlock.successors = b; 1188 } 1189 1190 1194 1199 final int getSize() { 1200 if (classReaderOffset != 0) { 1201 return 6 + classReaderLength; 1202 } 1203 if (resize) { 1204 resizeInstructions(new int[0], new int[0], 0); 1206 } 1207 int size = 8; 1208 if (code.length > 0) { 1209 cw.newUTF8("Code"); 1210 size += 18 + code.length + 8 * catchCount; 1211 if (localVar != null) { 1212 cw.newUTF8("LocalVariableTable"); 1213 size += 8 + localVar.length; 1214 } 1215 if (localVarType != null) { 1216 cw.newUTF8("LocalVariableTypeTable"); 1217 size += 8 + localVarType.length; 1218 } 1219 if (lineNumber != null) { 1220 cw.newUTF8("LineNumberTable"); 1221 size += 8 + lineNumber.length; 1222 } 1223 if (cattrs != null) { 1224 size += cattrs.getSize(cw, 1225 code.data, 1226 code.length, 1227 maxStack, 1228 maxLocals); 1229 } 1230 } 1231 if (exceptionCount > 0) { 1232 cw.newUTF8("Exceptions"); 1233 size += 8 + 2 * exceptionCount; 1234 } 1235 if ((access & Opcodes.ACC_SYNTHETIC) != 0 1236 && (cw.version & 0xffff) < Opcodes.V1_5) 1237 { 1238 cw.newUTF8("Synthetic"); 1239 size += 6; 1240 } 1241 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 1242 cw.newUTF8("Deprecated"); 1243 size += 6; 1244 } 1245 if (cw.version == Opcodes.V1_4) { 1246 if ((access & Opcodes.ACC_VARARGS) != 0) { 1247 cw.newUTF8("Varargs"); 1248 size += 6; 1249 } 1250 if ((access & Opcodes.ACC_BRIDGE) != 0) { 1251 cw.newUTF8("Bridge"); 1252 size += 6; 1253 } 1254 } 1255 if (signature != null) { 1256 cw.newUTF8("Signature"); 1257 cw.newUTF8(signature); 1258 size += 8; 1259 } 1260 if (annd != null) { 1261 cw.newUTF8("AnnotationDefault"); 1262 size += 6 + annd.length; 1263 } 1264 if (anns != null) { 1265 cw.newUTF8("RuntimeVisibleAnnotations"); 1266 size += 8 + anns.getSize(); 1267 } 1268 if (ianns != null) { 1269 cw.newUTF8("RuntimeInvisibleAnnotations"); 1270 size += 8 + ianns.getSize(); 1271 } 1272 if (panns != null) { 1273 cw.newUTF8("RuntimeVisibleParameterAnnotations"); 1274 size += 7 + 2 * panns.length; 1275 for (int i = panns.length - 1; i >= 0; --i) { 1276 size += panns[i] == null ? 0 : panns[i].getSize(); 1277 } 1278 } 1279 if (ipanns != null) { 1280 cw.newUTF8("RuntimeInvisibleParameterAnnotations"); 1281 size += 7 + 2 * ipanns.length; 1282 for (int i = ipanns.length - 1; i >= 0; --i) { 1283 size += ipanns[i] == null ? 0 : ipanns[i].getSize(); 1284 } 1285 } 1286 if (attrs != null) { 1287 size += attrs.getSize(cw, null, 0, -1, -1); 1288 } 1289 return size; 1290 } 1291 1292 1298 final void put(final ByteVector out) { 1299 out.putShort(access).putShort(name).putShort(desc); 1300 if (classReaderOffset != 0) { 1301 out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength); 1302 return; 1303 } 1304 int attributeCount = 0; 1305 if (code.length > 0) { 1306 ++attributeCount; 1307 } 1308 if (exceptionCount > 0) { 1309 ++attributeCount; 1310 } 1311 if ((access & Opcodes.ACC_SYNTHETIC) != 0 1312 && (cw.version & 0xffff) < Opcodes.V1_5) 1313 { 1314 ++attributeCount; 1315 } 1316 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 1317 ++attributeCount; 1318 } 1319 if (cw.version == Opcodes.V1_4) { 1320 if ((access & Opcodes.ACC_VARARGS) != 0) { 1321 ++attributeCount; 1322 } 1323 if ((access & Opcodes.ACC_BRIDGE) != 0) { 1324 ++attributeCount; 1325 } 1326 } 1327 if (signature != null) { 1328 ++attributeCount; 1329 } 1330 if (annd != null) { 1331 ++attributeCount; 1332 } 1333 if (anns != null) { 1334 ++attributeCount; 1335 } 1336 if (ianns != null) { 1337 ++attributeCount; 1338 } 1339 if (panns != null) { 1340 ++attributeCount; 1341 } 1342 if (ipanns != null) { 1343 ++attributeCount; 1344 } 1345 if (attrs != null) { 1346 attributeCount += attrs.getCount(); 1347 } 1348 out.putShort(attributeCount); 1349 if (code.length > 0) { 1350 int size = 12 + code.length + 8 * catchCount; 1351 if (localVar != null) { 1352 size += 8 + localVar.length; 1353 } 1354 if (localVarType != null) { 1355 size += 8 + localVarType.length; 1356 } 1357 if (lineNumber != null) { 1358 size += 8 + lineNumber.length; 1359 } 1360 if (cattrs != null) { 1361 size += cattrs.getSize(cw, 1362 code.data, 1363 code.length, 1364 maxStack, 1365 maxLocals); 1366 } 1367 out.putShort(cw.newUTF8("Code")).putInt(size); 1368 out.putShort(maxStack).putShort(maxLocals); 1369 out.putInt(code.length).putByteArray(code.data, 0, code.length); 1370 out.putShort(catchCount); 1371 if (catchCount > 0) { 1372 Handler h = catchTable; 1373 while (h != null) { 1374 out.putShort(h.start.position) 1375 .putShort(h.end.position) 1376 .putShort(h.handler.position) 1377 .putShort(h.type); 1378 h = h.next; 1379 } 1380 } 1381 attributeCount = 0; 1382 if (localVar != null) { 1383 ++attributeCount; 1384 } 1385 if (localVarType != null) { 1386 ++attributeCount; 1387 } 1388 if (lineNumber != null) { 1389 ++attributeCount; 1390 } 1391 if (cattrs != null) { 1392 attributeCount += cattrs.getCount(); 1393 } 1394 out.putShort(attributeCount); 1395 if (localVar != null) { 1396 out.putShort(cw.newUTF8("LocalVariableTable")); 1397 out.putInt(localVar.length + 2).putShort(localVarCount); 1398 out.putByteArray(localVar.data, 0, localVar.length); 1399 } 1400 if (localVarType != null) { 1401 out.putShort(cw.newUTF8("LocalVariableTypeTable")); 1402 out.putInt(localVarType.length + 2).putShort(localVarTypeCount); 1403 out.putByteArray(localVarType.data, 0, localVarType.length); 1404 } 1405 if (lineNumber != null) { 1406 out.putShort(cw.newUTF8("LineNumberTable")); 1407 out.putInt(lineNumber.length + 2).putShort(lineNumberCount); 1408 out.putByteArray(lineNumber.data, 0, lineNumber.length); 1409 } 1410 if (cattrs != null) { 1411 cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out); 1412 } 1413 } 1414 if (exceptionCount > 0) { 1415 out.putShort(cw.newUTF8("Exceptions")) 1416 .putInt(2 * exceptionCount + 2); 1417 out.putShort(exceptionCount); 1418 for (int i = 0; i < exceptionCount; ++i) { 1419 out.putShort(exceptions[i]); 1420 } 1421 } 1422 if ((access & Opcodes.ACC_SYNTHETIC) != 0 1423 && (cw.version & 0xffff) < Opcodes.V1_5) 1424 { 1425 out.putShort(cw.newUTF8("Synthetic")).putInt(0); 1426 } 1427 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 1428 out.putShort(cw.newUTF8("Deprecated")).putInt(0); 1429 } 1430 if (cw.version == Opcodes.V1_4) { 1431 if ((access & Opcodes.ACC_VARARGS) != 0) { 1432 out.putShort(cw.newUTF8("Varargs")).putInt(0); 1433 } 1434 if ((access & Opcodes.ACC_BRIDGE) != 0) { 1435 out.putShort(cw.newUTF8("Bridge")).putInt(0); 1436 } 1437 } 1438 if (signature != null) { 1439 out.putShort(cw.newUTF8("Signature")) 1440 .putInt(2) 1441 .putShort(cw.newUTF8(signature)); 1442 } 1443 if (annd != null) { 1444 out.putShort(cw.newUTF8("AnnotationDefault")); 1445 out.putInt(annd.length); 1446 out.putByteArray(annd.data, 0, annd.length); 1447 } 1448 if (anns != null) { 1449 out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); 1450 anns.put(out); 1451 } 1452 if (ianns != null) { 1453 out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); 1454 ianns.put(out); 1455 } 1456 if (panns != null) { 1457 out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations")); 1458 AnnotationWriter.put(panns, out); 1459 } 1460 if (ipanns != null) { 1461 out.putShort(cw.newUTF8("RuntimeInvisibleParameterAnnotations")); 1462 AnnotationWriter.put(ipanns, out); 1463 } 1464 if (attrs != null) { 1465 attrs.put(cw, null, 0, -1, -1, out); 1466 } 1467 } 1468 1469 1473 1505 private int[] resizeInstructions( 1506 final int[] indexes, 1507 final int[] sizes, 1508 final int len) 1509 { 1510 byte[] b = code.data; int u, v, label; int i, j; 1514 1539 int[] allIndexes = new int[len]; int[] allSizes = new int[len]; boolean[] resize; int newOffset; 1544 System.arraycopy(indexes, 0, allIndexes, 0, len); 1545 System.arraycopy(sizes, 0, allSizes, 0, len); 1546 resize = new boolean[code.length]; 1547 1548 int state = 3; 1550 do { 1551 if (state == 3) { 1552 state = 2; 1553 } 1554 u = 0; 1555 while (u < b.length) { 1556 int opcode = b[u] & 0xFF; int insert = 0; 1559 switch (ClassWriter.TYPE[opcode]) { 1560 case ClassWriter.NOARG_INSN: 1561 case ClassWriter.IMPLVAR_INSN: 1562 u += 1; 1563 break; 1564 case ClassWriter.LABEL_INSN: 1565 if (opcode > 201) { 1566 opcode = opcode < 218 ? opcode - 49 : opcode - 20; 1570 label = u + readUnsignedShort(b, u + 1); 1571 } else { 1572 label = u + readShort(b, u + 1); 1573 } 1574 newOffset = getNewOffset(allIndexes, allSizes, u, label); 1575 if (newOffset < Short.MIN_VALUE 1576 || newOffset > Short.MAX_VALUE) 1577 { 1578 if (!resize[u]) { 1579 if (opcode == Opcodes.GOTO 1580 || opcode == Opcodes.JSR) 1581 { 1582 insert = 2; 1586 } else { 1587 insert = 5; 1594 } 1595 resize[u] = true; 1596 } 1597 } 1598 u += 3; 1599 break; 1600 case ClassWriter.LABELW_INSN: 1601 u += 5; 1602 break; 1603 case ClassWriter.TABL_INSN: 1604 if (state == 1) { 1605 newOffset = getNewOffset(allIndexes, allSizes, 0, u); 1613 insert = -(newOffset & 3); 1614 } else if (!resize[u]) { 1615 insert = u & 3; 1619 resize[u] = true; 1620 } 1621 u = u + 4 - (u & 3); 1623 u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12; 1624 break; 1625 case ClassWriter.LOOK_INSN: 1626 if (state == 1) { 1627 newOffset = getNewOffset(allIndexes, allSizes, 0, u); 1629 insert = -(newOffset & 3); 1630 } else if (!resize[u]) { 1631 insert = u & 3; 1633 resize[u] = true; 1634 } 1635 u = u + 4 - (u & 3); 1637 u += 8 * readInt(b, u + 4) + 8; 1638 break; 1639 case ClassWriter.WIDE_INSN: 1640 opcode = b[u + 1] & 0xFF; 1641 if (opcode == Opcodes.IINC) { 1642 u += 6; 1643 } else { 1644 u += 4; 1645 } 1646 break; 1647 case ClassWriter.VAR_INSN: 1648 case ClassWriter.SBYTE_INSN: 1649 case ClassWriter.LDC_INSN: 1650 u += 2; 1651 break; 1652 case ClassWriter.SHORT_INSN: 1653 case ClassWriter.LDCW_INSN: 1654 case ClassWriter.FIELDORMETH_INSN: 1655 case ClassWriter.TYPE_INSN: 1656 case ClassWriter.IINC_INSN: 1657 u += 3; 1658 break; 1659 case ClassWriter.ITFMETH_INSN: 1660 u += 5; 1661 break; 1662 default: 1664 u += 4; 1665 break; 1666 } 1667 if (insert != 0) { 1668 int[] newIndexes = new int[allIndexes.length + 1]; 1671 int[] newSizes = new int[allSizes.length + 1]; 1672 System.arraycopy(allIndexes, 1673 0, 1674 newIndexes, 1675 0, 1676 allIndexes.length); 1677 System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length); 1678 newIndexes[allIndexes.length] = u; 1679 newSizes[allSizes.length] = insert; 1680 allIndexes = newIndexes; 1681 allSizes = newSizes; 1682 if (insert > 0) { 1683 state = 3; 1684 } 1685 } 1686 } 1687 if (state < 3) { 1688 --state; 1689 } 1690 } while (state != 0); 1691 1692 1696 ByteVector newCode = new ByteVector(code.length); 1697 1698 u = 0; 1699 while (u < code.length) { 1700 for (i = allIndexes.length - 1; i >= 0; --i) { 1701 if (allIndexes[i] == u) { 1702 if (i < len) { 1703 if (sizes[i] > 0) { 1704 newCode.putByteArray(null, 0, sizes[i]); 1705 } else { 1706 newCode.length += sizes[i]; 1707 } 1708 indexes[i] = newCode.length; 1709 } 1710 } 1711 } 1712 int opcode = b[u] & 0xFF; 1713 switch (ClassWriter.TYPE[opcode]) { 1714 case ClassWriter.NOARG_INSN: 1715 case ClassWriter.IMPLVAR_INSN: 1716 newCode.putByte(opcode); 1717 u += 1; 1718 break; 1719 case ClassWriter.LABEL_INSN: 1720 if (opcode > 201) { 1721 opcode = opcode < 218 ? opcode - 49 : opcode - 20; 1725 label = u + readUnsignedShort(b, u + 1); 1726 } else { 1727 label = u + readShort(b, u + 1); 1728 } 1729 newOffset = getNewOffset(allIndexes, allSizes, u, label); 1730 if (resize[u]) { 1731 if (opcode == Opcodes.GOTO) { 1737 newCode.putByte(200); } else if (opcode == Opcodes.JSR) { 1739 newCode.putByte(201); } else { 1741 newCode.putByte(opcode <= 166 1742 ? ((opcode + 1) ^ 1) - 1 1743 : opcode ^ 1); 1744 newCode.putShort(8); newCode.putByte(200); newOffset -= 3; 1748 } 1749 newCode.putInt(newOffset); 1750 } else { 1751 newCode.putByte(opcode); 1752 newCode.putShort(newOffset); 1753 } 1754 u += 3; 1755 break; 1756 case ClassWriter.LABELW_INSN: 1757 label = u + readInt(b, u + 1); 1758 newOffset = getNewOffset(allIndexes, allSizes, u, label); 1759 newCode.putByte(opcode); 1760 newCode.putInt(newOffset); 1761 u += 5; 1762 break; 1763 case ClassWriter.TABL_INSN: 1764 v = u; 1766 u = u + 4 - (v & 3); 1767 newCode.putByte(Opcodes.TABLESWITCH); 1769 while (newCode.length % 4 != 0) { 1770 newCode.putByte(0); 1771 } 1772 label = v + readInt(b, u); 1773 u += 4; 1774 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1775 newCode.putInt(newOffset); 1776 j = readInt(b, u); 1777 u += 4; 1778 newCode.putInt(j); 1779 j = readInt(b, u) - j + 1; 1780 u += 4; 1781 newCode.putInt(readInt(b, u - 4)); 1782 for (; j > 0; --j) { 1783 label = v + readInt(b, u); 1784 u += 4; 1785 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1786 newCode.putInt(newOffset); 1787 } 1788 break; 1789 case ClassWriter.LOOK_INSN: 1790 v = u; 1792 u = u + 4 - (v & 3); 1793 newCode.putByte(Opcodes.LOOKUPSWITCH); 1795 while (newCode.length % 4 != 0) { 1796 newCode.putByte(0); 1797 } 1798 label = v + readInt(b, u); 1799 u += 4; 1800 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1801 newCode.putInt(newOffset); 1802 j = readInt(b, u); 1803 u += 4; 1804 newCode.putInt(j); 1805 for (; j > 0; --j) { 1806 newCode.putInt(readInt(b, u)); 1807 u += 4; 1808 label = v + readInt(b, u); 1809 u += 4; 1810 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1811 newCode.putInt(newOffset); 1812 } 1813 break; 1814 case ClassWriter.WIDE_INSN: 1815 opcode = b[u + 1] & 0xFF; 1816 if (opcode == Opcodes.IINC) { 1817 newCode.putByteArray(b, u, 6); 1818 u += 6; 1819 } else { 1820 newCode.putByteArray(b, u, 4); 1821 u += 4; 1822 } 1823 break; 1824 case ClassWriter.VAR_INSN: 1825 case ClassWriter.SBYTE_INSN: 1826 case ClassWriter.LDC_INSN: 1827 newCode.putByteArray(b, u, 2); 1828 u += 2; 1829 break; 1830 case ClassWriter.SHORT_INSN: 1831 case ClassWriter.LDCW_INSN: 1832 case ClassWriter.FIELDORMETH_INSN: 1833 case ClassWriter.TYPE_INSN: 1834 case ClassWriter.IINC_INSN: 1835 newCode.putByteArray(b, u, 3); 1836 u += 3; 1837 break; 1838 case ClassWriter.ITFMETH_INSN: 1839 newCode.putByteArray(b, u, 5); 1840 u += 5; 1841 break; 1842 default: 1844 newCode.putByteArray(b, u, 4); 1845 u += 4; 1846 break; 1847 } 1848 } 1849 1850 Handler h = catchTable; 1852 while (h != null) { 1853 getNewOffset(allIndexes, allSizes, h.start); 1854 getNewOffset(allIndexes, allSizes, h.end); 1855 getNewOffset(allIndexes, allSizes, h.handler); 1856 h = h.next; 1857 } 1858 for (i = 0; i < 2; ++i) { 1859 ByteVector bv = i == 0 ? localVar : localVarType; 1860 if (bv != null) { 1861 b = bv.data; 1862 u = 0; 1863 while (u < bv.length) { 1864 label = readUnsignedShort(b, u); 1865 newOffset = getNewOffset(allIndexes, allSizes, 0, label); 1866 writeShort(b, u, newOffset); 1867 label += readUnsignedShort(b, u + 2); 1868 newOffset = getNewOffset(allIndexes, allSizes, 0, label) 1869 - newOffset; 1870 writeShort(b, u + 2, newOffset); 1871 u += 10; 1872 } 1873 } 1874 } 1875 if (lineNumber != null) { 1876 b = lineNumber.data; 1877 u = 0; 1878 while (u < lineNumber.length) { 1879 writeShort(b, u, getNewOffset(allIndexes, 1880 allSizes, 1881 0, 1882 readUnsignedShort(b, u))); 1883 u += 4; 1884 } 1885 } 1886 while (cattrs != null) { 1888 Label[] labels = cattrs.getLabels(); 1889 if (labels != null) { 1890 for (i = labels.length - 1; i >= 0; --i) { 1891 if (!labels[i].resized) { 1892 labels[i].position = getNewOffset(allIndexes, 1893 allSizes, 1894 0, 1895 labels[i].position); 1896 labels[i].resized = true; 1897 } 1898 } 1899 } 1900 } 1901 1902 code = newCode; 1904 1905 return indexes; 1907 } 1908 1909 1916 static int readUnsignedShort(final byte[] b, final int index) { 1917 return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); 1918 } 1919 1920 1927 static short readShort(final byte[] b, final int index) { 1928 return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); 1929 } 1930 1931 1938 static int readInt(final byte[] b, final int index) { 1939 return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) 1940 | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF); 1941 } 1942 1943 1950 static void writeShort(final byte[] b, final int index, final int s) { 1951 b[index] = (byte) (s >>> 8); 1952 b[index + 1] = (byte) s; 1953 } 1954 1955 1976 static int getNewOffset( 1977 final int[] indexes, 1978 final int[] sizes, 1979 final int begin, 1980 final int end) 1981 { 1982 int offset = end - begin; 1983 for (int i = 0; i < indexes.length; ++i) { 1984 if (begin < indexes[i] && indexes[i] <= end) { 1985 offset += sizes[i]; 1987 } else if (end < indexes[i] && indexes[i] <= begin) { 1988 offset -= sizes[i]; 1990 } 1991 } 1992 return offset; 1993 } 1994 1995 2011 static void getNewOffset( 2012 final int[] indexes, 2013 final int[] sizes, 2014 final Label label) 2015 { 2016 if (!label.resized) { 2017 label.position = getNewOffset(indexes, sizes, 0, label.position); 2018 label.resized = true; 2019 } 2020 } 2021} 2022 2023 | Popular Tags |