1 30 package org.objectweb.asm; 31 32 39 class MethodWriter implements MethodVisitor { 40 41 44 MethodWriter next; 45 46 49 private 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 77 private int signature; 78 79 82 private int exceptionCount; 83 84 89 private int[] exceptions; 90 91 94 private ByteVector annd; 95 96 99 private AnnotationWriter anns; 100 101 104 private AnnotationWriter ianns; 105 106 110 private AnnotationWriter[] panns; 111 112 116 private AnnotationWriter[] ipanns; 117 118 121 private Attribute attrs; 122 123 126 private ByteVector code = new ByteVector(); 127 128 131 private int maxStack; 132 133 136 private int maxLocals; 137 138 141 private int catchCount; 142 143 146 private ByteVector catchTable; 147 148 151 private int localVarCount; 152 153 156 private ByteVector localVar; 157 158 161 private int localVarTypeCount; 162 163 166 private ByteVector localVarType; 167 168 171 private int lineNumberCount; 172 173 176 private ByteVector lineNumber; 177 178 181 private Attribute cattrs; 182 183 186 private boolean resize; 187 188 197 198 202 private final boolean computeMaxs; 203 204 211 private int stackSize; 212 213 220 private int maxStackSize; 221 222 226 private Label currentBlock; 227 228 234 private Label blockStack; 235 236 241 private final static int[] SIZE; 242 243 247 250 static { 251 int i; 252 int[] b = new int[202]; 253 String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD" 254 + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD" 255 + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED" 256 + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE"; 257 for (i = 0; i < b.length; ++i) { 258 b[i] = s.charAt(i) - 'E'; 259 } 260 SIZE = b; 261 262 } 475 476 480 493 MethodWriter( 494 final ClassWriter cw, 495 final int access, 496 final String name, 497 final String desc, 498 final String signature, 499 final String [] exceptions, 500 final boolean computeMaxs) 501 { 502 if (cw.firstMethod == null) { 503 cw.firstMethod = this; 504 } else { 505 cw.lastMethod.next = this; 506 } 507 cw.lastMethod = this; 508 this.cw = cw; 509 this.access = access; 510 this.name = cw.newUTF8(name); 511 this.desc = cw.newUTF8(desc); 512 this.descriptor = desc; 513 if (signature != null) { 514 this.signature = cw.newUTF8(signature); 515 } 516 if (exceptions != null && exceptions.length > 0) { 517 exceptionCount = exceptions.length; 518 this.exceptions = new int[exceptionCount]; 519 for (int i = 0; i < exceptionCount; ++i) { 520 this.exceptions[i] = cw.newClass(exceptions[i]); 521 } 522 } 523 this.computeMaxs = computeMaxs; 524 if (computeMaxs) { 525 int size = getArgumentsAndReturnSizes(desc) >> 2; 527 if ((access & Opcodes.ACC_STATIC) != 0) { 528 --size; 529 } 530 maxLocals = size; 531 currentBlock = new Label(); 533 currentBlock.pushed = true; 534 blockStack = currentBlock; 535 } 536 } 537 538 542 public AnnotationVisitor visitAnnotationDefault() { 543 annd = new ByteVector(); 544 return new AnnotationWriter(cw, false, annd, null, 0); 545 } 546 547 public AnnotationVisitor visitAnnotation( 548 final String desc, 549 final boolean visible) 550 { 551 ByteVector bv = new ByteVector(); 552 bv.putShort(cw.newUTF8(desc)).putShort(0); 554 AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); 555 if (visible) { 556 aw.next = anns; 557 anns = aw; 558 } else { 559 aw.next = ianns; 560 ianns = aw; 561 } 562 return aw; 563 } 564 565 public AnnotationVisitor visitParameterAnnotation( 566 final int parameter, 567 final String desc, 568 final boolean visible) 569 { 570 ByteVector bv = new ByteVector(); 571 bv.putShort(cw.newUTF8(desc)).putShort(0); 573 AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); 574 if (visible) { 575 if (panns == null) { 576 panns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length]; 577 } 578 aw.next = panns[parameter]; 579 panns[parameter] = aw; 580 } else { 581 if (ipanns == null) { 582 ipanns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length]; 583 } 584 aw.next = ipanns[parameter]; 585 ipanns[parameter] = aw; 586 } 587 return aw; 588 } 589 590 public void visitAttribute(final Attribute attr) { 591 if (attr.isCodeAttribute()) { 592 attr.next = cattrs; 593 cattrs = attr; 594 } else { 595 attr.next = attrs; 596 attrs = attr; 597 } 598 } 599 600 public void visitCode() { 601 } 602 603 public void visitInsn(final int opcode) { 604 if (computeMaxs) { 605 int size = stackSize + SIZE[opcode]; 607 if (size > maxStackSize) { 608 maxStackSize = size; 609 } 610 stackSize = size; 611 if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) 613 || opcode == Opcodes.ATHROW) 614 { 615 if (currentBlock != null) { 616 currentBlock.maxStackSize = maxStackSize; 617 currentBlock = null; 618 } 619 } 620 } 621 code.putByte(opcode); 623 } 624 625 public void visitIntInsn(final int opcode, final int operand) { 626 if (computeMaxs && opcode != Opcodes.NEWARRAY) { 627 int size = stackSize + 1; 630 if (size > maxStackSize) { 631 maxStackSize = size; 632 } 633 stackSize = size; 634 } 635 if (opcode == Opcodes.SIPUSH) { 637 code.put12(opcode, operand); 638 } else { code.put11(opcode, operand); 640 } 641 } 642 643 public void visitVarInsn(final int opcode, final int var) { 644 if (computeMaxs) { 645 if (opcode == Opcodes.RET) { 647 if (currentBlock != null) { 649 currentBlock.maxStackSize = maxStackSize; 650 currentBlock = null; 651 } 652 } else { int size = stackSize + SIZE[opcode]; 654 if (size > maxStackSize) { 655 maxStackSize = size; 656 } 657 stackSize = size; 658 } 659 int n; 661 if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD 662 || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) 663 { 664 n = var + 2; 665 } else { 666 n = var + 1; 667 } 668 if (n > maxLocals) { 669 maxLocals = n; 670 } 671 } 672 if (var < 4 && opcode != Opcodes.RET) { 674 int opt; 675 if (opcode < Opcodes.ISTORE) { 676 677 opt = 26 + ((opcode - Opcodes.ILOAD) << 2) + var; 678 } else { 679 680 opt = 59 + ((opcode - Opcodes.ISTORE) << 2) + var; 681 } 682 code.putByte(opt); 683 } else if (var >= 256) { 684 code.putByte(196 ).put12(opcode, var); 685 } else { 686 code.put11(opcode, var); 687 } 688 } 689 690 public void visitTypeInsn(final int opcode, final String desc) { 691 if (computeMaxs && opcode == Opcodes.NEW) { 692 int size = stackSize + 1; 695 if (size > maxStackSize) { 696 maxStackSize = size; 697 } 698 stackSize = size; 699 } 700 code.put12(opcode, cw.newClass(desc)); 702 } 703 704 public void visitFieldInsn( 705 final int opcode, 706 final String owner, 707 final String name, 708 final String desc) 709 { 710 if (computeMaxs) { 711 int size; 712 char c = desc.charAt(0); 714 switch (opcode) { 715 case Opcodes.GETSTATIC: 716 size = stackSize + (c == 'D' || c == 'J' ? 2 : 1); 717 break; 718 case Opcodes.PUTSTATIC: 719 size = stackSize + (c == 'D' || c == 'J' ? -2 : -1); 720 break; 721 case Opcodes.GETFIELD: 722 size = stackSize + (c == 'D' || c == 'J' ? 1 : 0); 723 break; 724 default: 726 size = stackSize + (c == 'D' || c == 'J' ? -3 : -2); 727 break; 728 } 729 if (size > maxStackSize) { 731 maxStackSize = size; 732 } 733 stackSize = size; 734 } 735 code.put12(opcode, cw.newField(owner, name, desc)); 737 } 738 739 public void visitMethodInsn( 740 final int opcode, 741 final String owner, 742 final String name, 743 final String desc) 744 { 745 boolean itf = opcode == Opcodes.INVOKEINTERFACE; 746 Item i = cw.newMethodItem(owner, name, desc, itf); 747 int argSize = i.intVal; 748 if (computeMaxs) { 749 756 if (argSize == 0) { 757 argSize = getArgumentsAndReturnSizes(desc); 760 i.intVal = argSize; 763 } 764 int size; 765 if (opcode == Opcodes.INVOKESTATIC) { 766 size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1; 767 } else { 768 size = stackSize - (argSize >> 2) + (argSize & 0x03); 769 } 770 if (size > maxStackSize) { 772 maxStackSize = size; 773 } 774 stackSize = size; 775 } 776 if (itf) { 778 if (!computeMaxs) { 779 if (argSize == 0) { 780 argSize = getArgumentsAndReturnSizes(desc); 781 i.intVal = argSize; 782 } 783 } 784 code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0); 785 } else { 786 code.put12(opcode, i.index); 787 } 788 } 789 790 public void visitJumpInsn(final int opcode, final Label label) { 791 if (computeMaxs) { 792 if (opcode == Opcodes.GOTO) { 793 if (currentBlock != null) { 796 currentBlock.maxStackSize = maxStackSize; 797 addSuccessor(stackSize, label); 798 currentBlock = null; 799 } 800 } else if (opcode == Opcodes.JSR) { 801 if (currentBlock != null) { 802 addSuccessor(stackSize + 1, label); 803 } 804 } else { 805 stackSize += SIZE[opcode]; 808 if (currentBlock != null) { 809 addSuccessor(stackSize, label); 810 } 811 } 812 } 813 if (label.resolved && label.position - code.length < Short.MIN_VALUE) { 815 822 if (opcode == Opcodes.GOTO) { 823 code.putByte(200); } else if (opcode == Opcodes.JSR) { 825 code.putByte(201); } else { 827 code.putByte(opcode <= 166 828 ? ((opcode + 1) ^ 1) - 1 829 : opcode ^ 1); 830 code.putShort(8); code.putByte(200); } 833 label.put(this, code, code.length - 1, true); 834 } else { 835 841 code.putByte(opcode); 842 label.put(this, code, code.length - 1, false); 843 } 844 } 845 846 public void visitLabel(final Label label) { 847 if (computeMaxs) { 848 if (currentBlock != null) { 849 currentBlock.maxStackSize = maxStackSize; 851 addSuccessor(stackSize, label); 852 } 853 currentBlock = label; 856 stackSize = 0; 857 maxStackSize = 0; 858 } 859 resize |= label.resolve(this, code.length, code.data); 861 } 862 863 public void visitLdcInsn(final Object cst) { 864 Item i = cw.newConstItem(cst); 865 if (computeMaxs) { 866 int size; 867 if (i.type == 'J' || i.type == 'D') { 869 size = stackSize + 2; 870 } else { 871 size = stackSize + 1; 872 } 873 if (size > maxStackSize) { 875 maxStackSize = size; 876 } 877 stackSize = size; 878 } 879 int index = i.index; 881 if (i.type == 'J' || i.type == 'D') { 882 code.put12(20 , index); 883 } else if (index >= 256) { 884 code.put12(19 , index); 885 } else { 886 code.put11(Opcodes.LDC, index); 887 } 888 } 889 890 public void visitIincInsn(final int var, final int increment) { 891 if (computeMaxs) { 892 int n = var + 1; 894 if (n > maxLocals) { 895 maxLocals = n; 896 } 897 } 898 if ((var > 255) || (increment > 127) || (increment < -128)) { 900 code.putByte(196 ) 901 .put12(Opcodes.IINC, var) 902 .putShort(increment); 903 } else { 904 code.putByte(Opcodes.IINC).put11(var, increment); 905 } 906 } 907 908 public void visitTableSwitchInsn( 909 final int min, 910 final int max, 911 final Label dflt, 912 final Label labels[]) 913 { 914 if (computeMaxs) { 915 --stackSize; 917 if (currentBlock != null) { 919 currentBlock.maxStackSize = maxStackSize; 920 addSuccessor(stackSize, dflt); 921 for (int i = 0; i < labels.length; ++i) { 922 addSuccessor(stackSize, labels[i]); 923 } 924 currentBlock = null; 925 } 926 } 927 int source = code.length; 929 code.putByte(Opcodes.TABLESWITCH); 930 while (code.length % 4 != 0) { 931 code.putByte(0); 932 } 933 dflt.put(this, code, source, true); 934 code.putInt(min).putInt(max); 935 for (int i = 0; i < labels.length; ++i) { 936 labels[i].put(this, code, source, true); 937 } 938 } 939 940 public void visitLookupSwitchInsn( 941 final Label dflt, 942 final int keys[], 943 final Label labels[]) 944 { 945 if (computeMaxs) { 946 --stackSize; 948 if (currentBlock != null) { 950 currentBlock.maxStackSize = maxStackSize; 951 addSuccessor(stackSize, dflt); 952 for (int i = 0; i < labels.length; ++i) { 953 addSuccessor(stackSize, labels[i]); 954 } 955 currentBlock = null; 956 } 957 } 958 int source = code.length; 960 code.putByte(Opcodes.LOOKUPSWITCH); 961 while (code.length % 4 != 0) { 962 code.putByte(0); 963 } 964 dflt.put(this, code, source, true); 965 code.putInt(labels.length); 966 for (int i = 0; i < labels.length; ++i) { 967 code.putInt(keys[i]); 968 labels[i].put(this, code, source, true); 969 } 970 } 971 972 public void visitMultiANewArrayInsn(final String desc, final int dims) { 973 if (computeMaxs) { 974 stackSize += 1 - dims; 977 } 978 code.put12(Opcodes.MULTIANEWARRAY, cw.newClass(desc)).putByte(dims); 980 } 981 982 public void visitTryCatchBlock( 983 final Label start, 984 final Label end, 985 final Label handler, 986 final String type) 987 { 988 if (computeMaxs) { 989 if (!handler.pushed) { 991 handler.beginStackSize = 1; 992 handler.pushed = true; 993 handler.next = blockStack; 994 blockStack = handler; 995 } 996 } 997 ++catchCount; 998 if (catchTable == null) { 999 catchTable = new ByteVector(); 1000 } 1001 catchTable.putShort(start.position); 1002 catchTable.putShort(end.position); 1003 catchTable.putShort(handler.position); 1004 catchTable.putShort(type != null ? cw.newClass(type) : 0); 1005 } 1006 1007 public void visitLocalVariable( 1008 final String name, 1009 final String desc, 1010 final String signature, 1011 final Label start, 1012 final Label end, 1013 final int index) 1014 { 1015 if (signature != null) { 1016 if (localVarType == null) { 1017 localVarType = new ByteVector(); 1018 } 1019 ++localVarTypeCount; 1020 localVarType.putShort(start.position) 1021 .putShort(end.position - start.position) 1022 .putShort(cw.newUTF8(name)) 1023 .putShort(cw.newUTF8(signature)) 1024 .putShort(index); 1025 } 1026 if (localVar == null) { 1027 localVar = new ByteVector(); 1028 } 1029 ++localVarCount; 1030 localVar.putShort(start.position) 1031 .putShort(end.position - start.position) 1032 .putShort(cw.newUTF8(name)) 1033 .putShort(cw.newUTF8(desc)) 1034 .putShort(index); 1035 } 1036 1037 public void visitLineNumber(final int line, final Label start) { 1038 if (lineNumber == null) { 1039 lineNumber = new ByteVector(); 1040 } 1041 ++lineNumberCount; 1042 lineNumber.putShort(start.position); 1043 lineNumber.putShort(line); 1044 } 1045 1046 public void visitMaxs(final int maxStack, final int maxLocals) { 1047 if (computeMaxs) { 1048 int max = 0; 1050 1060 Label stack = blockStack; 1061 while (stack != null) { 1062 Label l = stack; 1064 stack = stack.next; 1065 int start = l.beginStackSize; 1067 int blockMax = start + l.maxStackSize; 1068 if (blockMax > max) { 1070 max = blockMax; 1071 } 1072 Edge b = l.successors; 1074 while (b != null) { 1075 l = b.successor; 1076 if (!l.pushed) { 1079 l.beginStackSize = start + b.stackSize; 1082 l.pushed = true; 1084 l.next = stack; 1085 stack = l; 1086 } 1087 b = b.next; 1088 } 1089 } 1090 this.maxStack = max; 1091 } else { 1092 this.maxStack = maxStack; 1093 this.maxLocals = maxLocals; 1094 } 1095 } 1096 1097 public void visitEnd() { 1098 } 1099 1100 1104 1114 private static int getArgumentsAndReturnSizes(final String desc) { 1115 int n = 1; 1116 int c = 1; 1117 while (true) { 1118 char car = desc.charAt(c++); 1119 if (car == ')') { 1120 car = desc.charAt(c); 1121 return n << 2 1122 | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1)); 1123 } else if (car == 'L') { 1124 while (desc.charAt(c++) != ';') { 1125 } 1126 n += 1; 1127 } else if (car == '[') { 1128 while ((car = desc.charAt(c)) == '[') { 1129 ++c; 1130 } 1131 if (car == 'D' || car == 'J') { 1132 n -= 1; 1133 } 1134 } else if (car == 'D' || car == 'J') { 1135 n += 2; 1136 } else { 1137 n += 1; 1138 } 1139 } 1140 } 1141 1142 1148 private void addSuccessor(final int stackSize, final Label successor) { 1149 Edge b = new Edge(); 1150 b.stackSize = stackSize; 1152 b.successor = successor; 1153 b.next = currentBlock.successors; 1155 currentBlock.successors = b; 1156 } 1157 1158 1162 1167 final int getSize() { 1168 if (resize) { 1169 resizeInstructions(new int[0], new int[0], 0); 1171 } 1172 int size = 8; 1173 if (code.length > 0) { 1174 cw.newUTF8("Code"); 1175 size += 18 + code.length + 8 * catchCount; 1176 if (localVar != null) { 1177 cw.newUTF8("LocalVariableTable"); 1178 size += 8 + localVar.length; 1179 } 1180 if (localVarType != null) { 1181 cw.newUTF8("LocalVariableTypeTable"); 1182 size += 8 + localVarType.length; 1183 } 1184 if (lineNumber != null) { 1185 cw.newUTF8("LineNumberTable"); 1186 size += 8 + lineNumber.length; 1187 } 1188 if (cattrs != null) { 1189 size += cattrs.getSize(cw, 1190 code.data, 1191 code.length, 1192 maxStack, 1193 maxLocals); 1194 } 1195 } 1196 if (exceptionCount > 0) { 1197 cw.newUTF8("Exceptions"); 1198 size += 8 + 2 * exceptionCount; 1199 } 1200 if ((access & Opcodes.ACC_SYNTHETIC) != 0 1201 && (cw.version & 0xffff) < Opcodes.V1_5) 1202 { 1203 cw.newUTF8("Synthetic"); 1204 size += 6; 1205 } 1206 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 1207 cw.newUTF8("Deprecated"); 1208 size += 6; 1209 } 1210 if (cw.version == Opcodes.V1_4) { 1211 if ((access & Opcodes.ACC_VARARGS) != 0) { 1212 cw.newUTF8("Varargs"); 1213 size += 6; 1214 } 1215 if ((access & Opcodes.ACC_BRIDGE) != 0) { 1216 cw.newUTF8("Bridge"); 1217 size += 6; 1218 } 1219 } 1220 if (signature != 0) { 1221 cw.newUTF8("Signature"); 1222 size += 8; 1223 } 1224 if (annd != null) { 1225 cw.newUTF8("AnnotationDefault"); 1226 size += 6 + annd.length; 1227 } 1228 if (anns != null) { 1229 cw.newUTF8("RuntimeVisibleAnnotations"); 1230 size += 8 + anns.getSize(); 1231 } 1232 if (ianns != null) { 1233 cw.newUTF8("RuntimeInvisibleAnnotations"); 1234 size += 8 + ianns.getSize(); 1235 } 1236 if (panns != null) { 1237 cw.newUTF8("RuntimeVisibleParameterAnnotations"); 1238 size += 7 + 2 * panns.length; 1239 for (int i = panns.length - 1; i >= 0; --i) { 1240 size += panns[i] == null ? 0 : panns[i].getSize(); 1241 } 1242 } 1243 if (ipanns != null) { 1244 cw.newUTF8("RuntimeInvisibleParameterAnnotations"); 1245 size += 7 + 2 * ipanns.length; 1246 for (int i = ipanns.length - 1; i >= 0; --i) { 1247 size += ipanns[i] == null ? 0 : ipanns[i].getSize(); 1248 } 1249 } 1250 if (attrs != null) { 1251 size += attrs.getSize(cw, null, 0, -1, -1); 1252 } 1253 return size; 1254 } 1255 1256 1262 final void put(final ByteVector out) { 1263 out.putShort(access).putShort(name).putShort(desc); 1264 int attributeCount = 0; 1265 if (code.length > 0) { 1266 ++attributeCount; 1267 } 1268 if (exceptionCount > 0) { 1269 ++attributeCount; 1270 } 1271 if ((access & Opcodes.ACC_SYNTHETIC) != 0 1272 && (cw.version & 0xffff) < Opcodes.V1_5) 1273 { 1274 ++attributeCount; 1275 } 1276 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 1277 ++attributeCount; 1278 } 1279 if (cw.version == Opcodes.V1_4) { 1280 if ((access & Opcodes.ACC_VARARGS) != 0) { 1281 ++attributeCount; 1282 } 1283 if ((access & Opcodes.ACC_BRIDGE) != 0) { 1284 ++attributeCount; 1285 } 1286 } 1287 if (signature != 0) { 1288 ++attributeCount; 1289 } 1290 if (annd != null) { 1291 ++attributeCount; 1292 } 1293 if (anns != null) { 1294 ++attributeCount; 1295 } 1296 if (ianns != null) { 1297 ++attributeCount; 1298 } 1299 if (panns != null) { 1300 ++attributeCount; 1301 } 1302 if (ipanns != null) { 1303 ++attributeCount; 1304 } 1305 if (attrs != null) { 1306 attributeCount += attrs.getCount(); 1307 } 1308 out.putShort(attributeCount); 1309 if (code.length > 0) { 1310 int size = 12 + code.length + 8 * catchCount; 1311 if (localVar != null) { 1312 size += 8 + localVar.length; 1313 } 1314 if (localVarType != null) { 1315 size += 8 + localVarType.length; 1316 } 1317 if (lineNumber != null) { 1318 size += 8 + lineNumber.length; 1319 } 1320 if (cattrs != null) { 1321 size += cattrs.getSize(cw, 1322 code.data, 1323 code.length, 1324 maxStack, 1325 maxLocals); 1326 } 1327 out.putShort(cw.newUTF8("Code")).putInt(size); 1328 out.putShort(maxStack).putShort(maxLocals); 1329 out.putInt(code.length).putByteArray(code.data, 0, code.length); 1330 out.putShort(catchCount); 1331 if (catchCount > 0) { 1332 out.putByteArray(catchTable.data, 0, catchTable.length); 1333 } 1334 attributeCount = 0; 1335 if (localVar != null) { 1336 ++attributeCount; 1337 } 1338 if (localVarType != null) { 1339 ++attributeCount; 1340 } 1341 if (lineNumber != null) { 1342 ++attributeCount; 1343 } 1344 if (cattrs != null) { 1345 attributeCount += cattrs.getCount(); 1346 } 1347 out.putShort(attributeCount); 1348 if (localVar != null) { 1349 out.putShort(cw.newUTF8("LocalVariableTable")); 1350 out.putInt(localVar.length + 2).putShort(localVarCount); 1351 out.putByteArray(localVar.data, 0, localVar.length); 1352 } 1353 if (localVarType != null) { 1354 out.putShort(cw.newUTF8("LocalVariableTypeTable")); 1355 out.putInt(localVarType.length + 2).putShort(localVarTypeCount); 1356 out.putByteArray(localVarType.data, 0, localVarType.length); 1357 } 1358 if (lineNumber != null) { 1359 out.putShort(cw.newUTF8("LineNumberTable")); 1360 out.putInt(lineNumber.length + 2).putShort(lineNumberCount); 1361 out.putByteArray(lineNumber.data, 0, lineNumber.length); 1362 } 1363 if (cattrs != null) { 1364 cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out); 1365 } 1366 } 1367 if (exceptionCount > 0) { 1368 out.putShort(cw.newUTF8("Exceptions")) 1369 .putInt(2 * exceptionCount + 2); 1370 out.putShort(exceptionCount); 1371 for (int i = 0; i < exceptionCount; ++i) { 1372 out.putShort(exceptions[i]); 1373 } 1374 } 1375 if ((access & Opcodes.ACC_SYNTHETIC) != 0 1376 && (cw.version & 0xffff) < Opcodes.V1_5) 1377 { 1378 out.putShort(cw.newUTF8("Synthetic")).putInt(0); 1379 } 1380 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 1381 out.putShort(cw.newUTF8("Deprecated")).putInt(0); 1382 } 1383 if (cw.version == Opcodes.V1_4) { 1384 if ((access & Opcodes.ACC_VARARGS) != 0) { 1385 out.putShort(cw.newUTF8("Varargs")).putInt(0); 1386 } 1387 if ((access & Opcodes.ACC_BRIDGE) != 0) { 1388 out.putShort(cw.newUTF8("Bridge")).putInt(0); 1389 } 1390 } 1391 if (signature != 0) { 1392 out.putShort(cw.newUTF8("Signature")).putInt(2).putShort(signature); 1393 } 1394 if (annd != null) { 1395 out.putShort(cw.newUTF8("AnnotationDefault")); 1396 out.putInt(annd.length); 1397 out.putByteArray(annd.data, 0, annd.length); 1398 } 1399 if (anns != null) { 1400 out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); 1401 anns.put(out); 1402 } 1403 if (ianns != null) { 1404 out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); 1405 ianns.put(out); 1406 } 1407 if (panns != null) { 1408 out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations")); 1409 AnnotationWriter.put(panns, out); 1410 } 1411 if (ipanns != null) { 1412 out.putShort(cw.newUTF8("RuntimeInvisibleParameterAnnotations")); 1413 AnnotationWriter.put(ipanns, out); 1414 } 1415 if (attrs != null) { 1416 attrs.put(cw, null, 0, -1, -1, out); 1417 } 1418 } 1419 1420 1424 1456 private int[] resizeInstructions( 1457 final int[] indexes, 1458 final int[] sizes, 1459 final int len) 1460 { 1461 byte[] b = code.data; int u, v, label; int i, j; 1465 int[] allIndexes = new int[len]; int[] allSizes = new int[len]; boolean[] resize; int newOffset; 1494 System.arraycopy(indexes, 0, allIndexes, 0, len); 1495 System.arraycopy(sizes, 0, allSizes, 0, len); 1496 resize = new boolean[code.length]; 1497 1498 int state = 3; do { 1501 if (state == 3) { 1502 state = 2; 1503 } 1504 u = 0; 1505 while (u < b.length) { 1506 int opcode = b[u] & 0xFF; int insert = 0; 1509 switch (ClassWriter.TYPE[opcode]) { 1510 case ClassWriter.NOARG_INSN: 1511 case ClassWriter.IMPLVAR_INSN: 1512 u += 1; 1513 break; 1514 case ClassWriter.LABEL_INSN: 1515 if (opcode > 201) { 1516 opcode = opcode < 218 ? opcode - 49 : opcode - 20; 1520 label = u + readUnsignedShort(b, u + 1); 1521 } else { 1522 label = u + readShort(b, u + 1); 1523 } 1524 newOffset = getNewOffset(allIndexes, allSizes, u, label); 1525 if (newOffset < Short.MIN_VALUE 1526 || newOffset > Short.MAX_VALUE) 1527 { 1528 if (!resize[u]) { 1529 if (opcode == Opcodes.GOTO 1530 || opcode == Opcodes.JSR) 1531 { 1532 insert = 2; 1536 } else { 1537 insert = 5; 1544 } 1545 resize[u] = true; 1546 } 1547 } 1548 u += 3; 1549 break; 1550 case ClassWriter.LABELW_INSN: 1551 u += 5; 1552 break; 1553 case ClassWriter.TABL_INSN: 1554 if (state == 1) { 1555 newOffset = getNewOffset(allIndexes, allSizes, 0, u); 1563 insert = -(newOffset & 3); 1564 } else if (!resize[u]) { 1565 insert = u & 3; 1569 resize[u] = true; 1570 } 1571 u = u + 4 - (u & 3); 1573 u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12; 1574 break; 1575 case ClassWriter.LOOK_INSN: 1576 if (state == 1) { 1577 newOffset = getNewOffset(allIndexes, allSizes, 0, u); 1579 insert = -(newOffset & 3); 1580 } else if (!resize[u]) { 1581 insert = u & 3; 1583 resize[u] = true; 1584 } 1585 u = u + 4 - (u & 3); 1587 u += 8 * readInt(b, u + 4) + 8; 1588 break; 1589 case ClassWriter.WIDE_INSN: 1590 opcode = b[u + 1] & 0xFF; 1591 if (opcode == Opcodes.IINC) { 1592 u += 6; 1593 } else { 1594 u += 4; 1595 } 1596 break; 1597 case ClassWriter.VAR_INSN: 1598 case ClassWriter.SBYTE_INSN: 1599 case ClassWriter.LDC_INSN: 1600 u += 2; 1601 break; 1602 case ClassWriter.SHORT_INSN: 1603 case ClassWriter.LDCW_INSN: 1604 case ClassWriter.FIELDORMETH_INSN: 1605 case ClassWriter.TYPE_INSN: 1606 case ClassWriter.IINC_INSN: 1607 u += 3; 1608 break; 1609 case ClassWriter.ITFMETH_INSN: 1610 u += 5; 1611 break; 1612 default: 1614 u += 4; 1615 break; 1616 } 1617 if (insert != 0) { 1618 int[] newIndexes = new int[allIndexes.length + 1]; 1621 int[] newSizes = new int[allSizes.length + 1]; 1622 System.arraycopy(allIndexes, 1623 0, 1624 newIndexes, 1625 0, 1626 allIndexes.length); 1627 System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length); 1628 newIndexes[allIndexes.length] = u; 1629 newSizes[allSizes.length] = insert; 1630 allIndexes = newIndexes; 1631 allSizes = newSizes; 1632 if (insert > 0) { 1633 state = 3; 1634 } 1635 } 1636 } 1637 if (state < 3) { 1638 --state; 1639 } 1640 } while (state != 0); 1641 1642 1646 ByteVector newCode = new ByteVector(code.length); 1647 1648 u = 0; 1649 while (u < code.length) { 1650 for (i = allIndexes.length - 1; i >= 0; --i) { 1651 if (allIndexes[i] == u) { 1652 if (i < len) { 1653 if (sizes[i] > 0) { 1654 newCode.putByteArray(null, 0, sizes[i]); 1655 } else { 1656 newCode.length += sizes[i]; 1657 } 1658 indexes[i] = newCode.length; 1659 } 1660 } 1661 } 1662 int opcode = b[u] & 0xFF; 1663 switch (ClassWriter.TYPE[opcode]) { 1664 case ClassWriter.NOARG_INSN: 1665 case ClassWriter.IMPLVAR_INSN: 1666 newCode.putByte(opcode); 1667 u += 1; 1668 break; 1669 case ClassWriter.LABEL_INSN: 1670 if (opcode > 201) { 1671 opcode = opcode < 218 ? opcode - 49 : opcode - 20; 1675 label = u + readUnsignedShort(b, u + 1); 1676 } else { 1677 label = u + readShort(b, u + 1); 1678 } 1679 newOffset = getNewOffset(allIndexes, allSizes, u, label); 1680 if (resize[u]) { 1681 if (opcode == Opcodes.GOTO) { 1687 newCode.putByte(200); } else if (opcode == Opcodes.JSR) { 1689 newCode.putByte(201); } else { 1691 newCode.putByte(opcode <= 166 1692 ? ((opcode + 1) ^ 1) - 1 1693 : opcode ^ 1); 1694 newCode.putShort(8); newCode.putByte(200); newOffset -= 3; 1698 } 1699 newCode.putInt(newOffset); 1700 } else { 1701 newCode.putByte(opcode); 1702 newCode.putShort(newOffset); 1703 } 1704 u += 3; 1705 break; 1706 case ClassWriter.LABELW_INSN: 1707 label = u + readInt(b, u + 1); 1708 newOffset = getNewOffset(allIndexes, allSizes, u, label); 1709 newCode.putByte(opcode); 1710 newCode.putInt(newOffset); 1711 u += 5; 1712 break; 1713 case ClassWriter.TABL_INSN: 1714 v = u; 1716 u = u + 4 - (v & 3); 1717 newCode.putByte(Opcodes.TABLESWITCH); 1719 while (newCode.length % 4 != 0) { 1720 newCode.putByte(0); 1721 } 1722 label = v + readInt(b, u); 1723 u += 4; 1724 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1725 newCode.putInt(newOffset); 1726 j = readInt(b, u); 1727 u += 4; 1728 newCode.putInt(j); 1729 j = readInt(b, u) - j + 1; 1730 u += 4; 1731 newCode.putInt(readInt(b, u - 4)); 1732 for (; j > 0; --j) { 1733 label = v + readInt(b, u); 1734 u += 4; 1735 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1736 newCode.putInt(newOffset); 1737 } 1738 break; 1739 case ClassWriter.LOOK_INSN: 1740 v = u; 1742 u = u + 4 - (v & 3); 1743 newCode.putByte(Opcodes.LOOKUPSWITCH); 1745 while (newCode.length % 4 != 0) { 1746 newCode.putByte(0); 1747 } 1748 label = v + readInt(b, u); 1749 u += 4; 1750 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1751 newCode.putInt(newOffset); 1752 j = readInt(b, u); 1753 u += 4; 1754 newCode.putInt(j); 1755 for (; j > 0; --j) { 1756 newCode.putInt(readInt(b, u)); 1757 u += 4; 1758 label = v + readInt(b, u); 1759 u += 4; 1760 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1761 newCode.putInt(newOffset); 1762 } 1763 break; 1764 case ClassWriter.WIDE_INSN: 1765 opcode = b[u + 1] & 0xFF; 1766 if (opcode == Opcodes.IINC) { 1767 newCode.putByteArray(b, u, 6); 1768 u += 6; 1769 } else { 1770 newCode.putByteArray(b, u, 4); 1771 u += 4; 1772 } 1773 break; 1774 case ClassWriter.VAR_INSN: 1775 case ClassWriter.SBYTE_INSN: 1776 case ClassWriter.LDC_INSN: 1777 newCode.putByteArray(b, u, 2); 1778 u += 2; 1779 break; 1780 case ClassWriter.SHORT_INSN: 1781 case ClassWriter.LDCW_INSN: 1782 case ClassWriter.FIELDORMETH_INSN: 1783 case ClassWriter.TYPE_INSN: 1784 case ClassWriter.IINC_INSN: 1785 newCode.putByteArray(b, u, 3); 1786 u += 3; 1787 break; 1788 case ClassWriter.ITFMETH_INSN: 1789 newCode.putByteArray(b, u, 5); 1790 u += 5; 1791 break; 1792 default: 1794 newCode.putByteArray(b, u, 4); 1795 u += 4; 1796 break; 1797 } 1798 } 1799 1800 if (catchTable != null) { 1803 b = catchTable.data; 1804 u = 0; 1805 while (u < catchTable.length) { 1806 writeShort(b, u, getNewOffset(allIndexes, 1807 allSizes, 1808 0, 1809 readUnsignedShort(b, u))); 1810 writeShort(b, u + 2, getNewOffset(allIndexes, 1811 allSizes, 1812 0, 1813 readUnsignedShort(b, u + 2))); 1814 writeShort(b, u + 4, getNewOffset(allIndexes, 1815 allSizes, 1816 0, 1817 readUnsignedShort(b, u + 4))); 1818 u += 8; 1819 } 1820 } 1821 for (i = 0; i < 2; ++i) { 1822 ByteVector bv = i == 0 ? localVar : localVarType; 1823 if (bv != null) { 1824 b = bv.data; 1825 u = 0; 1826 while (u < bv.length) { 1827 label = readUnsignedShort(b, u); 1828 newOffset = getNewOffset(allIndexes, allSizes, 0, label); 1829 writeShort(b, u, newOffset); 1830 label += readUnsignedShort(b, u + 2); 1831 newOffset = getNewOffset(allIndexes, allSizes, 0, label) 1832 - newOffset; 1833 writeShort(b, u + 2, newOffset); 1834 u += 10; 1835 } 1836 } 1837 } 1838 if (lineNumber != null) { 1839 b = lineNumber.data; 1840 u = 0; 1841 while (u < lineNumber.length) { 1842 writeShort(b, u, getNewOffset(allIndexes, 1843 allSizes, 1844 0, 1845 readUnsignedShort(b, u))); 1846 u += 4; 1847 } 1848 } 1849 while (cattrs != null) { 1851 Label[] labels = cattrs.getLabels(); 1852 if (labels != null) { 1853 for (i = labels.length - 1; i >= 0; --i) { 1854 if (!labels[i].resized) { 1855 labels[i].position = getNewOffset(allIndexes, 1856 allSizes, 1857 0, 1858 labels[i].position); 1859 labels[i].resized = true; 1860 } 1861 } 1862 } 1863 } 1864 1865 code = newCode; 1867 1868 return indexes; 1870 } 1871 1872 1879 static int readUnsignedShort(final byte[] b, final int index) { 1880 return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); 1881 } 1882 1883 1890 static short readShort(final byte[] b, final int index) { 1891 return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); 1892 } 1893 1894 1901 static int readInt(final byte[] b, final int index) { 1902 return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) 1903 | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF); 1904 } 1905 1906 1913 static void writeShort(final byte[] b, final int index, final int s) { 1914 b[index] = (byte) (s >>> 8); 1915 b[index + 1] = (byte) s; 1916 } 1917 1918 1939 static int getNewOffset( 1940 final int[] indexes, 1941 final int[] sizes, 1942 final int begin, 1943 final int end) 1944 { 1945 int offset = end - begin; 1946 for (int i = 0; i < indexes.length; ++i) { 1947 if (begin < indexes[i] && indexes[i] <= end) { offset += sizes[i]; 1949 } else if (end < indexes[i] && indexes[i] <= begin) { offset -= sizes[i]; 1952 } 1953 } 1954 return offset; 1955 } 1956} 1957 | Popular Tags |