1 30 package com.sleepycat.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 1060 public void visitLineNumber(final int line, final Label start) { 1061 if (lineNumber == null) { 1062 lineNumber = new ByteVector(); 1063 } 1064 ++lineNumberCount; 1065 lineNumber.putShort(start.position); 1066 lineNumber.putShort(line); 1067 } 1068 1069 public void visitMaxs(final int maxStack, final int maxLocals) { 1070 if (computeMaxs) { 1071 int max = 0; 1073 1083 Label stack = blockStack; 1084 while (stack != null) { 1085 Label l = stack; 1087 stack = stack.next; 1088 int start = l.beginStackSize; 1090 int blockMax = start + l.maxStackSize; 1091 if (blockMax > max) { 1093 max = blockMax; 1094 } 1095 Edge b = l.successors; 1097 while (b != null) { 1098 l = b.successor; 1099 if (!l.pushed) { 1102 l.beginStackSize = start + b.stackSize; 1105 l.pushed = true; 1107 l.next = stack; 1108 stack = l; 1109 } 1110 b = b.next; 1111 } 1112 } 1113 this.maxStack = max; 1114 } else { 1115 this.maxStack = maxStack; 1116 this.maxLocals = maxLocals; 1117 } 1118 } 1119 1120 public void visitEnd() { 1121 } 1122 1123 1127 1137 private static int getArgumentsAndReturnSizes(final String desc) { 1138 int n = 1; 1139 int c = 1; 1140 while (true) { 1141 char car = desc.charAt(c++); 1142 if (car == ')') { 1143 car = desc.charAt(c); 1144 return n << 2 1145 | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1)); 1146 } else if (car == 'L') { 1147 while (desc.charAt(c++) != ';') { 1148 } 1149 n += 1; 1150 } else if (car == '[') { 1151 while ((car = desc.charAt(c)) == '[') { 1152 ++c; 1153 } 1154 if (car == 'D' || car == 'J') { 1155 n -= 1; 1156 } 1157 } else if (car == 'D' || car == 'J') { 1158 n += 2; 1159 } else { 1160 n += 1; 1161 } 1162 } 1163 } 1164 1165 1171 private void addSuccessor(final int stackSize, final Label successor) { 1172 Edge b = new Edge(); 1173 b.stackSize = stackSize; 1175 b.successor = successor; 1176 b.next = currentBlock.successors; 1178 currentBlock.successors = b; 1179 } 1180 1181 1185 1190 final int getSize() { 1191 if (classReaderOffset != 0) { 1192 return 6 + classReaderLength; 1193 } 1194 if (resize) { 1195 resizeInstructions(new int[0], new int[0], 0); 1197 } 1198 int size = 8; 1199 if (code.length > 0) { 1200 cw.newUTF8("Code"); 1201 size += 18 + code.length + 8 * catchCount; 1202 if (localVar != null) { 1203 cw.newUTF8("LocalVariableTable"); 1204 size += 8 + localVar.length; 1205 } 1206 if (localVarType != null) { 1207 cw.newUTF8("LocalVariableTypeTable"); 1208 size += 8 + localVarType.length; 1209 } 1210 if (lineNumber != null) { 1211 cw.newUTF8("LineNumberTable"); 1212 size += 8 + lineNumber.length; 1213 } 1214 if (cattrs != null) { 1215 size += cattrs.getSize(cw, 1216 code.data, 1217 code.length, 1218 maxStack, 1219 maxLocals); 1220 } 1221 } 1222 if (exceptionCount > 0) { 1223 cw.newUTF8("Exceptions"); 1224 size += 8 + 2 * exceptionCount; 1225 } 1226 if ((access & Opcodes.ACC_SYNTHETIC) != 0 1227 && (cw.version & 0xffff) < Opcodes.V1_5) 1228 { 1229 cw.newUTF8("Synthetic"); 1230 size += 6; 1231 } 1232 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 1233 cw.newUTF8("Deprecated"); 1234 size += 6; 1235 } 1236 if (cw.version == Opcodes.V1_4) { 1237 if ((access & Opcodes.ACC_VARARGS) != 0) { 1238 cw.newUTF8("Varargs"); 1239 size += 6; 1240 } 1241 if ((access & Opcodes.ACC_BRIDGE) != 0) { 1242 cw.newUTF8("Bridge"); 1243 size += 6; 1244 } 1245 } 1246 if (signature != null) { 1247 cw.newUTF8("Signature"); 1248 cw.newUTF8(signature); 1249 size += 8; 1250 } 1251 if (annd != null) { 1252 cw.newUTF8("AnnotationDefault"); 1253 size += 6 + annd.length; 1254 } 1255 if (anns != null) { 1256 cw.newUTF8("RuntimeVisibleAnnotations"); 1257 size += 8 + anns.getSize(); 1258 } 1259 if (ianns != null) { 1260 cw.newUTF8("RuntimeInvisibleAnnotations"); 1261 size += 8 + ianns.getSize(); 1262 } 1263 if (panns != null) { 1264 cw.newUTF8("RuntimeVisibleParameterAnnotations"); 1265 size += 7 + 2 * panns.length; 1266 for (int i = panns.length - 1; i >= 0; --i) { 1267 size += panns[i] == null ? 0 : panns[i].getSize(); 1268 } 1269 } 1270 if (ipanns != null) { 1271 cw.newUTF8("RuntimeInvisibleParameterAnnotations"); 1272 size += 7 + 2 * ipanns.length; 1273 for (int i = ipanns.length - 1; i >= 0; --i) { 1274 size += ipanns[i] == null ? 0 : ipanns[i].getSize(); 1275 } 1276 } 1277 if (attrs != null) { 1278 size += attrs.getSize(cw, null, 0, -1, -1); 1279 } 1280 return size; 1281 } 1282 1283 1289 final void put(final ByteVector out) { 1290 out.putShort(access).putShort(name).putShort(desc); 1291 if (classReaderOffset != 0) { 1292 out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength); 1293 return; 1294 } 1295 int attributeCount = 0; 1296 if (code.length > 0) { 1297 ++attributeCount; 1298 } 1299 if (exceptionCount > 0) { 1300 ++attributeCount; 1301 } 1302 if ((access & Opcodes.ACC_SYNTHETIC) != 0 1303 && (cw.version & 0xffff) < Opcodes.V1_5) 1304 { 1305 ++attributeCount; 1306 } 1307 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 1308 ++attributeCount; 1309 } 1310 if (cw.version == Opcodes.V1_4) { 1311 if ((access & Opcodes.ACC_VARARGS) != 0) { 1312 ++attributeCount; 1313 } 1314 if ((access & Opcodes.ACC_BRIDGE) != 0) { 1315 ++attributeCount; 1316 } 1317 } 1318 if (signature != null) { 1319 ++attributeCount; 1320 } 1321 if (annd != null) { 1322 ++attributeCount; 1323 } 1324 if (anns != null) { 1325 ++attributeCount; 1326 } 1327 if (ianns != null) { 1328 ++attributeCount; 1329 } 1330 if (panns != null) { 1331 ++attributeCount; 1332 } 1333 if (ipanns != null) { 1334 ++attributeCount; 1335 } 1336 if (attrs != null) { 1337 attributeCount += attrs.getCount(); 1338 } 1339 out.putShort(attributeCount); 1340 if (code.length > 0) { 1341 int size = 12 + code.length + 8 * catchCount; 1342 if (localVar != null) { 1343 size += 8 + localVar.length; 1344 } 1345 if (localVarType != null) { 1346 size += 8 + localVarType.length; 1347 } 1348 if (lineNumber != null) { 1349 size += 8 + lineNumber.length; 1350 } 1351 if (cattrs != null) { 1352 size += cattrs.getSize(cw, 1353 code.data, 1354 code.length, 1355 maxStack, 1356 maxLocals); 1357 } 1358 out.putShort(cw.newUTF8("Code")).putInt(size); 1359 out.putShort(maxStack).putShort(maxLocals); 1360 out.putInt(code.length).putByteArray(code.data, 0, code.length); 1361 out.putShort(catchCount); 1362 if (catchCount > 0) { 1363 Handler h = catchTable; 1364 while (h != null) { 1365 out.putShort(h.start.position) 1366 .putShort(h.end.position) 1367 .putShort(h.handler.position) 1368 .putShort(h.type); 1369 h = h.next; 1370 } 1371 } 1372 attributeCount = 0; 1373 if (localVar != null) { 1374 ++attributeCount; 1375 } 1376 if (localVarType != null) { 1377 ++attributeCount; 1378 } 1379 if (lineNumber != null) { 1380 ++attributeCount; 1381 } 1382 if (cattrs != null) { 1383 attributeCount += cattrs.getCount(); 1384 } 1385 out.putShort(attributeCount); 1386 if (localVar != null) { 1387 out.putShort(cw.newUTF8("LocalVariableTable")); 1388 out.putInt(localVar.length + 2).putShort(localVarCount); 1389 out.putByteArray(localVar.data, 0, localVar.length); 1390 } 1391 if (localVarType != null) { 1392 out.putShort(cw.newUTF8("LocalVariableTypeTable")); 1393 out.putInt(localVarType.length + 2).putShort(localVarTypeCount); 1394 out.putByteArray(localVarType.data, 0, localVarType.length); 1395 } 1396 if (lineNumber != null) { 1397 out.putShort(cw.newUTF8("LineNumberTable")); 1398 out.putInt(lineNumber.length + 2).putShort(lineNumberCount); 1399 out.putByteArray(lineNumber.data, 0, lineNumber.length); 1400 } 1401 if (cattrs != null) { 1402 cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out); 1403 } 1404 } 1405 if (exceptionCount > 0) { 1406 out.putShort(cw.newUTF8("Exceptions")) 1407 .putInt(2 * exceptionCount + 2); 1408 out.putShort(exceptionCount); 1409 for (int i = 0; i < exceptionCount; ++i) { 1410 out.putShort(exceptions[i]); 1411 } 1412 } 1413 if ((access & Opcodes.ACC_SYNTHETIC) != 0 1414 && (cw.version & 0xffff) < Opcodes.V1_5) 1415 { 1416 out.putShort(cw.newUTF8("Synthetic")).putInt(0); 1417 } 1418 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 1419 out.putShort(cw.newUTF8("Deprecated")).putInt(0); 1420 } 1421 if (cw.version == Opcodes.V1_4) { 1422 if ((access & Opcodes.ACC_VARARGS) != 0) { 1423 out.putShort(cw.newUTF8("Varargs")).putInt(0); 1424 } 1425 if ((access & Opcodes.ACC_BRIDGE) != 0) { 1426 out.putShort(cw.newUTF8("Bridge")).putInt(0); 1427 } 1428 } 1429 if (signature != null) { 1430 out.putShort(cw.newUTF8("Signature")) 1431 .putInt(2) 1432 .putShort(cw.newUTF8(signature)); 1433 } 1434 if (annd != null) { 1435 out.putShort(cw.newUTF8("AnnotationDefault")); 1436 out.putInt(annd.length); 1437 out.putByteArray(annd.data, 0, annd.length); 1438 } 1439 if (anns != null) { 1440 out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); 1441 anns.put(out); 1442 } 1443 if (ianns != null) { 1444 out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); 1445 ianns.put(out); 1446 } 1447 if (panns != null) { 1448 out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations")); 1449 AnnotationWriter.put(panns, out); 1450 } 1451 if (ipanns != null) { 1452 out.putShort(cw.newUTF8("RuntimeInvisibleParameterAnnotations")); 1453 AnnotationWriter.put(ipanns, out); 1454 } 1455 if (attrs != null) { 1456 attrs.put(cw, null, 0, -1, -1, out); 1457 } 1458 } 1459 1460 1464 1496 private int[] resizeInstructions( 1497 final int[] indexes, 1498 final int[] sizes, 1499 final int len) 1500 { 1501 byte[] b = code.data; int u, v, label; int i, j; 1505 1530 int[] allIndexes = new int[len]; int[] allSizes = new int[len]; boolean[] resize; int newOffset; 1535 System.arraycopy(indexes, 0, allIndexes, 0, len); 1536 System.arraycopy(sizes, 0, allSizes, 0, len); 1537 resize = new boolean[code.length]; 1538 1539 int state = 3; 1541 do { 1542 if (state == 3) { 1543 state = 2; 1544 } 1545 u = 0; 1546 while (u < b.length) { 1547 int opcode = b[u] & 0xFF; int insert = 0; 1550 switch (ClassWriter.TYPE[opcode]) { 1551 case ClassWriter.NOARG_INSN: 1552 case ClassWriter.IMPLVAR_INSN: 1553 u += 1; 1554 break; 1555 case ClassWriter.LABEL_INSN: 1556 if (opcode > 201) { 1557 opcode = opcode < 218 ? opcode - 49 : opcode - 20; 1561 label = u + readUnsignedShort(b, u + 1); 1562 } else { 1563 label = u + readShort(b, u + 1); 1564 } 1565 newOffset = getNewOffset(allIndexes, allSizes, u, label); 1566 if (newOffset < Short.MIN_VALUE 1567 || newOffset > Short.MAX_VALUE) 1568 { 1569 if (!resize[u]) { 1570 if (opcode == Opcodes.GOTO 1571 || opcode == Opcodes.JSR) 1572 { 1573 insert = 2; 1577 } else { 1578 insert = 5; 1585 } 1586 resize[u] = true; 1587 } 1588 } 1589 u += 3; 1590 break; 1591 case ClassWriter.LABELW_INSN: 1592 u += 5; 1593 break; 1594 case ClassWriter.TABL_INSN: 1595 if (state == 1) { 1596 newOffset = getNewOffset(allIndexes, allSizes, 0, u); 1604 insert = -(newOffset & 3); 1605 } else if (!resize[u]) { 1606 insert = u & 3; 1610 resize[u] = true; 1611 } 1612 u = u + 4 - (u & 3); 1614 u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12; 1615 break; 1616 case ClassWriter.LOOK_INSN: 1617 if (state == 1) { 1618 newOffset = getNewOffset(allIndexes, allSizes, 0, u); 1620 insert = -(newOffset & 3); 1621 } else if (!resize[u]) { 1622 insert = u & 3; 1624 resize[u] = true; 1625 } 1626 u = u + 4 - (u & 3); 1628 u += 8 * readInt(b, u + 4) + 8; 1629 break; 1630 case ClassWriter.WIDE_INSN: 1631 opcode = b[u + 1] & 0xFF; 1632 if (opcode == Opcodes.IINC) { 1633 u += 6; 1634 } else { 1635 u += 4; 1636 } 1637 break; 1638 case ClassWriter.VAR_INSN: 1639 case ClassWriter.SBYTE_INSN: 1640 case ClassWriter.LDC_INSN: 1641 u += 2; 1642 break; 1643 case ClassWriter.SHORT_INSN: 1644 case ClassWriter.LDCW_INSN: 1645 case ClassWriter.FIELDORMETH_INSN: 1646 case ClassWriter.TYPE_INSN: 1647 case ClassWriter.IINC_INSN: 1648 u += 3; 1649 break; 1650 case ClassWriter.ITFMETH_INSN: 1651 u += 5; 1652 break; 1653 default: 1655 u += 4; 1656 break; 1657 } 1658 if (insert != 0) { 1659 int[] newIndexes = new int[allIndexes.length + 1]; 1662 int[] newSizes = new int[allSizes.length + 1]; 1663 System.arraycopy(allIndexes, 1664 0, 1665 newIndexes, 1666 0, 1667 allIndexes.length); 1668 System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length); 1669 newIndexes[allIndexes.length] = u; 1670 newSizes[allSizes.length] = insert; 1671 allIndexes = newIndexes; 1672 allSizes = newSizes; 1673 if (insert > 0) { 1674 state = 3; 1675 } 1676 } 1677 } 1678 if (state < 3) { 1679 --state; 1680 } 1681 } while (state != 0); 1682 1683 1687 ByteVector newCode = new ByteVector(code.length); 1688 1689 u = 0; 1690 while (u < code.length) { 1691 for (i = allIndexes.length - 1; i >= 0; --i) { 1692 if (allIndexes[i] == u) { 1693 if (i < len) { 1694 if (sizes[i] > 0) { 1695 newCode.putByteArray(null, 0, sizes[i]); 1696 } else { 1697 newCode.length += sizes[i]; 1698 } 1699 indexes[i] = newCode.length; 1700 } 1701 } 1702 } 1703 int opcode = b[u] & 0xFF; 1704 switch (ClassWriter.TYPE[opcode]) { 1705 case ClassWriter.NOARG_INSN: 1706 case ClassWriter.IMPLVAR_INSN: 1707 newCode.putByte(opcode); 1708 u += 1; 1709 break; 1710 case ClassWriter.LABEL_INSN: 1711 if (opcode > 201) { 1712 opcode = opcode < 218 ? opcode - 49 : opcode - 20; 1716 label = u + readUnsignedShort(b, u + 1); 1717 } else { 1718 label = u + readShort(b, u + 1); 1719 } 1720 newOffset = getNewOffset(allIndexes, allSizes, u, label); 1721 if (resize[u]) { 1722 if (opcode == Opcodes.GOTO) { 1728 newCode.putByte(200); } else if (opcode == Opcodes.JSR) { 1730 newCode.putByte(201); } else { 1732 newCode.putByte(opcode <= 166 1733 ? ((opcode + 1) ^ 1) - 1 1734 : opcode ^ 1); 1735 newCode.putShort(8); newCode.putByte(200); newOffset -= 3; 1739 } 1740 newCode.putInt(newOffset); 1741 } else { 1742 newCode.putByte(opcode); 1743 newCode.putShort(newOffset); 1744 } 1745 u += 3; 1746 break; 1747 case ClassWriter.LABELW_INSN: 1748 label = u + readInt(b, u + 1); 1749 newOffset = getNewOffset(allIndexes, allSizes, u, label); 1750 newCode.putByte(opcode); 1751 newCode.putInt(newOffset); 1752 u += 5; 1753 break; 1754 case ClassWriter.TABL_INSN: 1755 v = u; 1757 u = u + 4 - (v & 3); 1758 newCode.putByte(Opcodes.TABLESWITCH); 1760 while (newCode.length % 4 != 0) { 1761 newCode.putByte(0); 1762 } 1763 label = v + readInt(b, u); 1764 u += 4; 1765 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1766 newCode.putInt(newOffset); 1767 j = readInt(b, u); 1768 u += 4; 1769 newCode.putInt(j); 1770 j = readInt(b, u) - j + 1; 1771 u += 4; 1772 newCode.putInt(readInt(b, u - 4)); 1773 for (; j > 0; --j) { 1774 label = v + readInt(b, u); 1775 u += 4; 1776 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1777 newCode.putInt(newOffset); 1778 } 1779 break; 1780 case ClassWriter.LOOK_INSN: 1781 v = u; 1783 u = u + 4 - (v & 3); 1784 newCode.putByte(Opcodes.LOOKUPSWITCH); 1786 while (newCode.length % 4 != 0) { 1787 newCode.putByte(0); 1788 } 1789 label = v + readInt(b, u); 1790 u += 4; 1791 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1792 newCode.putInt(newOffset); 1793 j = readInt(b, u); 1794 u += 4; 1795 newCode.putInt(j); 1796 for (; j > 0; --j) { 1797 newCode.putInt(readInt(b, u)); 1798 u += 4; 1799 label = v + readInt(b, u); 1800 u += 4; 1801 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1802 newCode.putInt(newOffset); 1803 } 1804 break; 1805 case ClassWriter.WIDE_INSN: 1806 opcode = b[u + 1] & 0xFF; 1807 if (opcode == Opcodes.IINC) { 1808 newCode.putByteArray(b, u, 6); 1809 u += 6; 1810 } else { 1811 newCode.putByteArray(b, u, 4); 1812 u += 4; 1813 } 1814 break; 1815 case ClassWriter.VAR_INSN: 1816 case ClassWriter.SBYTE_INSN: 1817 case ClassWriter.LDC_INSN: 1818 newCode.putByteArray(b, u, 2); 1819 u += 2; 1820 break; 1821 case ClassWriter.SHORT_INSN: 1822 case ClassWriter.LDCW_INSN: 1823 case ClassWriter.FIELDORMETH_INSN: 1824 case ClassWriter.TYPE_INSN: 1825 case ClassWriter.IINC_INSN: 1826 newCode.putByteArray(b, u, 3); 1827 u += 3; 1828 break; 1829 case ClassWriter.ITFMETH_INSN: 1830 newCode.putByteArray(b, u, 5); 1831 u += 5; 1832 break; 1833 default: 1835 newCode.putByteArray(b, u, 4); 1836 u += 4; 1837 break; 1838 } 1839 } 1840 1841 Handler h = catchTable; 1843 while (h != null) { 1844 getNewOffset(allIndexes, allSizes, h.start); 1845 getNewOffset(allIndexes, allSizes, h.end); 1846 getNewOffset(allIndexes, allSizes, h.handler); 1847 h = h.next; 1848 } 1849 for (i = 0; i < 2; ++i) { 1850 ByteVector bv = i == 0 ? localVar : localVarType; 1851 if (bv != null) { 1852 b = bv.data; 1853 u = 0; 1854 while (u < bv.length) { 1855 label = readUnsignedShort(b, u); 1856 newOffset = getNewOffset(allIndexes, allSizes, 0, label); 1857 writeShort(b, u, newOffset); 1858 label += readUnsignedShort(b, u + 2); 1859 newOffset = getNewOffset(allIndexes, allSizes, 0, label) 1860 - newOffset; 1861 writeShort(b, u + 2, newOffset); 1862 u += 10; 1863 } 1864 } 1865 } 1866 if (lineNumber != null) { 1867 b = lineNumber.data; 1868 u = 0; 1869 while (u < lineNumber.length) { 1870 writeShort(b, u, getNewOffset(allIndexes, 1871 allSizes, 1872 0, 1873 readUnsignedShort(b, u))); 1874 u += 4; 1875 } 1876 } 1877 while (cattrs != null) { 1879 Label[] labels = cattrs.getLabels(); 1880 if (labels != null) { 1881 for (i = labels.length - 1; i >= 0; --i) { 1882 if (!labels[i].resized) { 1883 labels[i].position = getNewOffset(allIndexes, 1884 allSizes, 1885 0, 1886 labels[i].position); 1887 labels[i].resized = true; 1888 } 1889 } 1890 } 1891 } 1892 1893 code = newCode; 1895 1896 return indexes; 1898 } 1899 1900 1907 static int readUnsignedShort(final byte[] b, final int index) { 1908 return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); 1909 } 1910 1911 1918 static short readShort(final byte[] b, final int index) { 1919 return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); 1920 } 1921 1922 1929 static int readInt(final byte[] b, final int index) { 1930 return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) 1931 | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF); 1932 } 1933 1934 1941 static void writeShort(final byte[] b, final int index, final int s) { 1942 b[index] = (byte) (s >>> 8); 1943 b[index + 1] = (byte) s; 1944 } 1945 1946 1967 static int getNewOffset( 1968 final int[] indexes, 1969 final int[] sizes, 1970 final int begin, 1971 final int end) 1972 { 1973 int offset = end - begin; 1974 for (int i = 0; i < indexes.length; ++i) { 1975 if (begin < indexes[i] && indexes[i] <= end) { 1976 offset += sizes[i]; 1978 } else if (end < indexes[i] && indexes[i] <= begin) { 1979 offset -= sizes[i]; 1981 } 1982 } 1983 return offset; 1984 } 1985 1986 2002 static void getNewOffset( 2003 final int[] indexes, 2004 final int[] sizes, 2005 final Label label) 2006 { 2007 if (!label.resized) { 2008 label.position = getNewOffset(indexes, sizes, 0, label.position); 2009 label.resized = true; 2010 } 2011 } 2012} 2013 | Popular Tags |