1 34 35 package org.logicalcobwebs.asm; 36 37 42 43 public class CodeWriter implements CodeVisitor { 44 45 48 49 final static boolean CHECK = false; 50 51 54 55 CodeWriter next; 56 57 60 61 private ClassWriter cw; 62 63 66 67 private int name; 68 69 73 74 private int desc; 75 76 79 80 private int access; 81 82 85 86 private int maxStack; 87 88 91 92 private int maxLocals; 93 94 97 98 private ByteVector code = new ByteVector(); 99 100 103 104 private int catchCount; 105 106 109 110 private ByteVector catchTable; 111 112 115 116 private int exceptionCount; 117 118 123 124 private int[] exceptions; 125 126 129 130 private Attribute attrs; 131 132 135 136 private int localVarCount; 137 138 141 142 private ByteVector localVar; 143 144 147 148 private int lineNumberCount; 149 150 153 154 private ByteVector lineNumber; 155 156 159 160 private Attribute cattrs; 161 162 165 166 private boolean resize; 167 168 178 182 183 private final boolean computeMaxs; 184 185 192 193 private int stackSize; 194 195 202 203 private int maxStackSize; 204 205 209 210 private Label currentBlock; 211 212 218 219 private Label blockStack; 220 221 226 227 private final static int[] SIZE; 228 229 241 247 248 private Edge head; 249 250 256 257 private Edge tail; 258 259 263 264 private static Edge pool; 265 266 270 273 274 static { 275 int i; 276 int[] b = new int[202]; 277 String s = 278 "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDDCDCDEEEEEEEEE" + 279 "EEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCDCDCEEEEDDDDDDDCDCDCEFEF" + 280 "DDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFEDDDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE"; 281 for (i = 0; i < b.length; ++i) { 282 b[i] = s.charAt(i) - 'E'; 283 } 284 SIZE = b; 285 286 499 } 500 501 505 512 513 protected CodeWriter (final ClassWriter cw, final boolean computeMaxs) { 514 if (cw.firstMethod == null) { 515 cw.firstMethod = this; 516 cw.lastMethod = this; 517 } else { 518 cw.lastMethod.next = this; 519 cw.lastMethod = this; 520 } 521 this.cw = cw; 522 this.computeMaxs = computeMaxs; 523 if (computeMaxs) { 524 currentBlock = new Label(); 526 currentBlock.pushed = true; 527 blockStack = currentBlock; 528 } 529 } 530 531 541 542 protected void init ( 543 final int access, 544 final String name, 545 final String desc, 546 final String [] exceptions, 547 final Attribute attrs) 548 { 549 this.access = access; 550 this.name = cw.newUTF8(name); 551 this.desc = cw.newUTF8(desc); 552 if (exceptions != null && exceptions.length > 0) { 553 exceptionCount = exceptions.length; 554 this.exceptions = new int[exceptionCount]; 555 for (int i = 0; i < exceptionCount; ++i) { 556 this.exceptions[i] = cw.newClass(exceptions[i]); 557 } 558 } 559 this.attrs = attrs; 560 if (computeMaxs) { 561 int size = getArgumentsAndReturnSizes(desc) >> 2; 563 if ((access & Constants.ACC_STATIC) != 0) { 564 --size; 565 } 566 if (size > maxLocals) { 567 maxLocals = size; 568 } 569 } 570 } 571 572 576 public void visitInsn (final int opcode) { 577 if (computeMaxs) { 578 int size = stackSize + SIZE[opcode]; 580 if (size > maxStackSize) { 581 maxStackSize = size; 582 } 583 stackSize = size; 584 if ((opcode >= Constants.IRETURN && opcode <= Constants.RETURN) || 586 opcode == Constants.ATHROW) 587 { 588 if (currentBlock != null) { 589 currentBlock.maxStackSize = maxStackSize; 590 currentBlock = null; 591 } 592 } 593 } 594 code.put1(opcode); 596 } 597 598 public void visitIntInsn (final int opcode, final int operand) { 599 if (computeMaxs && opcode != Constants.NEWARRAY) { 600 int size = stackSize + 1; 603 if (size > maxStackSize) { 604 maxStackSize = size; 605 } 606 stackSize = size; 607 } 608 if (opcode == Constants.SIPUSH) { 610 code.put12(opcode, operand); 611 } else { code.put11(opcode, operand); 613 } 614 } 615 616 public void visitVarInsn (final int opcode, final int var) { 617 if (computeMaxs) { 618 if (opcode == Constants.RET) { 620 if (currentBlock != null) { 622 currentBlock.maxStackSize = maxStackSize; 623 currentBlock = null; 624 } 625 } else { int size = stackSize + SIZE[opcode]; 627 if (size > maxStackSize) { 628 maxStackSize = size; 629 } 630 stackSize = size; 631 } 632 int n; 634 if (opcode == Constants.LLOAD || opcode == Constants.DLOAD || 635 opcode == Constants.LSTORE || opcode == Constants.DSTORE) 636 { 637 n = var + 2; 638 } else { 639 n = var + 1; 640 } 641 if (n > maxLocals) { 642 maxLocals = n; 643 } 644 } 645 if (var < 4 && opcode != Constants.RET) { 647 int opt; 648 if (opcode < Constants.ISTORE) { 649 opt = 26 + ((opcode - Constants.ILOAD) << 2) + var; 650 } else { 651 opt = 59 + ((opcode - Constants.ISTORE) << 2) + var; 652 } 653 code.put1(opt); 654 } else if (var >= 256) { 655 code.put1(196 ).put12(opcode, var); 656 } else { 657 code.put11(opcode, var); 658 } 659 } 660 661 public void visitTypeInsn (final int opcode, final String desc) { 662 if (computeMaxs && opcode == Constants.NEW) { 663 int size = stackSize + 1; 666 if (size > maxStackSize) { 667 maxStackSize = size; 668 } 669 stackSize = size; 670 } 671 code.put12(opcode, cw.newClass(desc)); 673 } 674 675 public void visitFieldInsn ( 676 final int opcode, 677 final String owner, 678 final String name, 679 final String desc) 680 { 681 if (computeMaxs) { 682 int size; 683 char c = desc.charAt(0); 685 switch (opcode) { 686 case Constants.GETSTATIC: 687 size = stackSize + (c == 'D' || c == 'J' ? 2 : 1); 688 break; 689 case Constants.PUTSTATIC: 690 size = stackSize + (c == 'D' || c == 'J' ? -2 : -1); 691 break; 692 case Constants.GETFIELD: 693 size = stackSize + (c == 'D' || c == 'J' ? 1 : 0); 694 break; 695 default: 697 size = stackSize + (c == 'D' || c == 'J' ? -3 : -2); 698 break; 699 } 700 if (size > maxStackSize) { 702 maxStackSize = size; 703 } 704 stackSize = size; 705 } 706 code.put12(opcode, cw.newField(owner, name, desc)); 708 } 709 710 public void visitMethodInsn ( 711 final int opcode, 712 final String owner, 713 final String name, 714 final String desc) 715 { 716 boolean itf = opcode == Constants.INVOKEINTERFACE; 717 Item i = cw.newMethodItem(owner, name, desc, itf); 718 int argSize = i.intVal; 719 if (computeMaxs) { 720 if (argSize == 0) { 726 argSize = getArgumentsAndReturnSizes(desc); 728 i.intVal = argSize; 730 } 731 int size; 732 if (opcode == Constants.INVOKESTATIC) { 733 size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1; 734 } else { 735 size = stackSize - (argSize >> 2) + (argSize & 0x03); 736 } 737 if (size > maxStackSize) { 739 maxStackSize = size; 740 } 741 stackSize = size; 742 } 743 if (itf) { 745 if (!computeMaxs) { 746 if (argSize == 0) { 747 argSize = getArgumentsAndReturnSizes(desc); 748 i.intVal = argSize; 749 } 750 } 751 code.put12(Constants.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0); 752 } else { 753 code.put12(opcode, i.index); 754 } 755 } 756 757 public void visitJumpInsn (final int opcode, final Label label) { 758 if (CHECK) { 759 if (label.owner == null) { 760 label.owner = this; 761 } else if (label.owner != this) { 762 throw new IllegalArgumentException (); 763 } 764 } 765 if (computeMaxs) { 766 if (opcode == Constants.GOTO) { 767 if (currentBlock != null) { 769 currentBlock.maxStackSize = maxStackSize; 770 addSuccessor(stackSize, label); 771 currentBlock = null; 772 } 773 } else if (opcode == Constants.JSR) { 774 if (currentBlock != null) { 775 addSuccessor(stackSize + 1, label); 776 } 777 } else { 778 stackSize += SIZE[opcode]; 781 if (currentBlock != null) { 782 addSuccessor(stackSize, label); 783 } 784 } 785 } 786 if (label.resolved && label.position - code.length < Short.MIN_VALUE) { 788 if (opcode == Constants.GOTO) { 794 code.put1(200); } else if (opcode == Constants.JSR) { 796 code.put1(201); } else { 798 code.put1(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1); 799 code.put2(8); code.put1(200); } 802 label.put(this, code, code.length - 1, true); 803 } else { 804 code.put1(opcode); 808 label.put(this, code, code.length - 1, false); 809 } 810 } 811 812 public void visitLabel (final Label label) { 813 if (CHECK) { 814 if (label.owner == null) { 815 label.owner = this; 816 } else if (label.owner != this) { 817 throw new IllegalArgumentException (); 818 } 819 } 820 if (computeMaxs) { 821 if (currentBlock != null) { 822 currentBlock.maxStackSize = maxStackSize; 824 addSuccessor(stackSize, label); 825 } 826 currentBlock = label; 829 stackSize = 0; 830 maxStackSize = 0; 831 } 832 resize |= label.resolve(this, code.length, code.data); 834 } 835 836 public void visitLdcInsn (final Object cst) { 837 Item i = cw.newConst(cst); 838 if (computeMaxs) { 839 int size; 840 if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) { 842 size = stackSize + 2; 843 } else { 844 size = stackSize + 1; 845 } 846 if (size > maxStackSize) { 848 maxStackSize = size; 849 } 850 stackSize = size; 851 } 852 int index = i.index; 854 if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) { 855 code.put12(20 , index); 856 } else if (index >= 256) { 857 code.put12(19 , index); 858 } else { 859 code.put11(Constants.LDC, index); 860 } 861 } 862 863 public void visitIincInsn (final int var, final int increment) { 864 if (computeMaxs) { 865 int n = var + 1; 867 if (n > maxLocals) { 868 maxLocals = n; 869 } 870 } 871 if ((var > 255) || (increment > 127) || (increment < -128)) { 873 code.put1(196 ).put12(Constants.IINC, var).put2(increment); 874 } else { 875 code.put1(Constants.IINC).put11(var, increment); 876 } 877 } 878 879 public void visitTableSwitchInsn ( 880 final int min, 881 final int max, 882 final Label dflt, 883 final Label labels[]) 884 { 885 if (computeMaxs) { 886 --stackSize; 888 if (currentBlock != null) { 890 currentBlock.maxStackSize = maxStackSize; 891 addSuccessor(stackSize, dflt); 892 for (int i = 0; i < labels.length; ++i) { 893 addSuccessor(stackSize, labels[i]); 894 } 895 currentBlock = null; 896 } 897 } 898 int source = code.length; 900 code.put1(Constants.TABLESWITCH); 901 while (code.length % 4 != 0) { 902 code.put1(0); 903 } 904 dflt.put(this, code, source, true); 905 code.put4(min).put4(max); 906 for (int i = 0; i < labels.length; ++i) { 907 labels[i].put(this, code, source, true); 908 } 909 } 910 911 public void visitLookupSwitchInsn ( 912 final Label dflt, 913 final int keys[], 914 final Label labels[]) 915 { 916 if (computeMaxs) { 917 --stackSize; 919 if (currentBlock != null) { 921 currentBlock.maxStackSize = maxStackSize; 922 addSuccessor(stackSize, dflt); 923 for (int i = 0; i < labels.length; ++i) { 924 addSuccessor(stackSize, labels[i]); 925 } 926 currentBlock = null; 927 } 928 } 929 int source = code.length; 931 code.put1(Constants.LOOKUPSWITCH); 932 while (code.length % 4 != 0) { 933 code.put1(0); 934 } 935 dflt.put(this, code, source, true); 936 code.put4(labels.length); 937 for (int i = 0; i < labels.length; ++i) { 938 code.put4(keys[i]); 939 labels[i].put(this, code, source, true); 940 } 941 } 942 943 public void visitMultiANewArrayInsn (final String desc, final int dims) { 944 if (computeMaxs) { 945 stackSize += 1 - dims; 948 } 949 code.put12(Constants.MULTIANEWARRAY, cw.newClass(desc)).put1(dims); 951 } 952 953 public void visitTryCatchBlock ( 954 final Label start, 955 final Label end, 956 final Label handler, 957 final String type) 958 { 959 if (CHECK) { 960 if (start.owner != this || end.owner != this || handler.owner != this) { 961 throw new IllegalArgumentException (); 962 } 963 if (!start.resolved || !end.resolved || !handler.resolved) { 964 throw new IllegalArgumentException (); 965 } 966 } 967 if (computeMaxs) { 968 if (!handler.pushed) { 970 handler.beginStackSize = 1; 971 handler.pushed = true; 972 handler.next = blockStack; 973 blockStack = handler; 974 } 975 } 976 ++catchCount; 977 if (catchTable == null) { 978 catchTable = new ByteVector(); 979 } 980 catchTable.put2(start.position); 981 catchTable.put2(end.position); 982 catchTable.put2(handler.position); 983 catchTable.put2(type != null ? cw.newClass(type) : 0); 984 } 985 986 public void visitMaxs (final int maxStack, final int maxLocals) { 987 if (computeMaxs) { 988 int max = 0; 990 Label stack = blockStack; 998 while (stack != null) { 999 Label l = stack; 1001 stack = stack.next; 1002 int start = l.beginStackSize; 1004 int blockMax = start + l.maxStackSize; 1005 if (blockMax > max) { 1007 max = blockMax; 1008 } 1009 Edge b = l.successors; 1011 while (b != null) { 1012 l = b.successor; 1013 if (!l.pushed) { 1015 l.beginStackSize = start + b.stackSize; 1017 l.pushed = true; 1019 l.next = stack; 1020 stack = l; 1021 } 1022 b = b.next; 1023 } 1024 } 1025 this.maxStack = max; 1026 synchronized (SIZE) { 1028 if (tail != null) { 1030 tail.poolNext = pool; 1031 pool = head; 1032 } 1033 } 1034 } else { 1035 this.maxStack = maxStack; 1036 this.maxLocals = maxLocals; 1037 } 1038 } 1039 1040 public void visitLocalVariable ( 1041 final String name, 1042 final String desc, 1043 final Label start, 1044 final Label end, 1045 final int index) 1046 { 1047 if (CHECK) { 1048 if (start.owner != this || !start.resolved) { 1049 throw new IllegalArgumentException (); 1050 } 1051 if (end.owner != this || !end.resolved) { 1052 throw new IllegalArgumentException (); 1053 } 1054 } 1055 if (localVar == null) { 1056 cw.newUTF8("LocalVariableTable"); 1057 localVar = new ByteVector(); 1058 } 1059 ++localVarCount; 1060 localVar.put2(start.position); 1061 localVar.put2(end.position - start.position); 1062 localVar.put2(cw.newUTF8(name)); 1063 localVar.put2(cw.newUTF8(desc)); 1064 localVar.put2(index); 1065 } 1066 1067 public void visitLineNumber (final int line, final Label start) { 1068 if (CHECK) { 1069 if (start.owner != this || !start.resolved) { 1070 throw new IllegalArgumentException (); 1071 } 1072 } 1073 if (lineNumber == null) { 1074 cw.newUTF8("LineNumberTable"); 1075 lineNumber = new ByteVector(); 1076 } 1077 ++lineNumberCount; 1078 lineNumber.put2(start.position); 1079 lineNumber.put2(line); 1080 } 1081 1082 public void visitAttribute (final Attribute attr) { 1083 attr.next = cattrs; 1084 cattrs = attr; 1085 } 1086 1087 1091 1101 1102 private static int getArgumentsAndReturnSizes (final String desc) { 1103 int n = 1; 1104 int c = 1; 1105 while (true) { 1106 char car = desc.charAt(c++); 1107 if (car == ')') { 1108 car = desc.charAt(c); 1109 return n << 2 | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1)); 1110 } else if (car == 'L') { 1111 while (desc.charAt(c++) != ';') { 1112 } 1113 n += 1; 1114 } else if (car == '[') { 1115 while ((car = desc.charAt(c)) == '[') { 1116 ++c; 1117 } 1118 if (car == 'D' || car == 'J') { 1119 n -= 1; 1120 } 1121 } else if (car == 'D' || car == 'J') { 1122 n += 2; 1123 } else { 1124 n += 1; 1125 } 1126 } 1127 } 1128 1129 1135 1136 private void addSuccessor (final int stackSize, final Label successor) { 1137 Edge b; 1138 synchronized (SIZE) { 1140 if (pool == null) { 1141 b = new Edge(); 1142 } else { 1143 b = pool; 1144 pool = pool.poolNext; 1146 } 1147 } 1148 if (tail == null) { 1150 tail = b; 1151 } 1152 b.poolNext = head; 1153 head = b; 1154 b.stackSize = stackSize; 1156 b.successor = successor; 1157 b.next = currentBlock.successors; 1159 currentBlock.successors = b; 1160 } 1161 1162 1166 1171 1172 final int getSize () { 1173 if (resize) { 1174 resizeInstructions(new int[0], new int[0], 0); 1176 } 1177 int size = 8; 1178 if (code.length > 0) { 1179 cw.newUTF8("Code"); 1180 size += 18 + code.length + 8 * catchCount; 1181 if (localVar != null) { 1182 size += 8 + localVar.length; 1183 } 1184 if (lineNumber != null) { 1185 size += 8 + lineNumber.length; 1186 } 1187 if (cattrs != null) { 1188 size += cattrs.getSize(cw); 1189 } 1190 } 1191 if (exceptionCount > 0) { 1192 cw.newUTF8("Exceptions"); 1193 size += 8 + 2 * exceptionCount; 1194 } 1195 if ((access & Constants.ACC_SYNTHETIC) != 0) { 1196 cw.newUTF8("Synthetic"); 1197 size += 6; 1198 } 1199 if ((access & Constants.ACC_DEPRECATED) != 0) { 1200 cw.newUTF8("Deprecated"); 1201 size += 6; 1202 } 1203 if (attrs != null) { 1204 size += attrs.getSize(cw); 1205 } 1206 return size; 1207 } 1208 1209 1215 1216 final void put (final ByteVector out) { 1217 out.put2(access).put2(name).put2(desc); 1218 int attributeCount = 0; 1219 if (code.length > 0) { 1220 ++attributeCount; 1221 } 1222 if (exceptionCount > 0) { 1223 ++attributeCount; 1224 } 1225 if ((access & Constants.ACC_SYNTHETIC) != 0) { 1226 ++attributeCount; 1227 } 1228 if ((access & Constants.ACC_DEPRECATED) != 0) { 1229 ++attributeCount; 1230 } 1231 if (attrs != null) { 1232 attributeCount += attrs.getCount(); 1233 } 1234 out.put2(attributeCount); 1235 if (code.length > 0) { 1236 int size = 12 + code.length + 8 * catchCount; 1237 if (localVar != null) { 1238 size += 8 + localVar.length; 1239 } 1240 if (lineNumber != null) { 1241 size += 8 + lineNumber.length; 1242 } 1243 if (cattrs != null) { 1244 size += cattrs.getSize(cw); 1245 } 1246 out.put2(cw.newUTF8("Code")).put4(size); 1247 out.put2(maxStack).put2(maxLocals); 1248 out.put4(code.length).putByteArray(code.data, 0, code.length); 1249 out.put2(catchCount); 1250 if (catchCount > 0) { 1251 out.putByteArray(catchTable.data, 0, catchTable.length); 1252 } 1253 attributeCount = 0; 1254 if (localVar != null) { 1255 ++attributeCount; 1256 } 1257 if (lineNumber != null) { 1258 ++attributeCount; 1259 } 1260 if (cattrs != null) { 1261 attributeCount += cattrs.getCount(); 1262 } 1263 out.put2(attributeCount); 1264 if (localVar != null) { 1265 out.put2(cw.newUTF8("LocalVariableTable")); 1266 out.put4(localVar.length + 2).put2(localVarCount); 1267 out.putByteArray(localVar.data, 0, localVar.length); 1268 } 1269 if (lineNumber != null) { 1270 out.put2(cw.newUTF8("LineNumberTable")); 1271 out.put4(lineNumber.length + 2).put2(lineNumberCount); 1272 out.putByteArray(lineNumber.data, 0, lineNumber.length); 1273 } 1274 if (cattrs != null) { 1275 cattrs.put(cw, out); 1276 } 1277 } 1278 if (exceptionCount > 0) { 1279 out.put2(cw.newUTF8("Exceptions")).put4(2 * exceptionCount + 2); 1280 out.put2(exceptionCount); 1281 for (int i = 0; i < exceptionCount; ++i) { 1282 out.put2(exceptions[i]); 1283 } 1284 } 1285 if ((access & Constants.ACC_SYNTHETIC) != 0) { 1286 out.put2(cw.newUTF8("Synthetic")).put4(0); 1287 } 1288 if ((access & Constants.ACC_DEPRECATED) != 0) { 1289 out.put2(cw.newUTF8("Deprecated")).put4(0); 1290 } 1291 if (attrs != null) { 1292 attrs.put(cw, out); 1293 } 1294 } 1295 1296 1300 1332 1333 protected int[] resizeInstructions ( 1334 final int[] indexes, 1335 final int[] sizes, 1336 final int len) 1337 { 1338 byte[] b = code.data; int u, v, label; int i, j; 1342 1364 int[] allIndexes = new int[len]; int[] allSizes = new int[len]; boolean[] resize; int newOffset; 1369 System.arraycopy(indexes, 0, allIndexes, 0, len); 1370 System.arraycopy(sizes, 0, allSizes, 0, len); 1371 resize = new boolean[code.length]; 1372 1373 int state = 3; do { 1375 if (state == 3) { 1376 state = 2; 1377 } 1378 u = 0; 1379 while (u < b.length) { 1380 int opcode = b[u] & 0xFF; int insert = 0; 1383 switch (ClassWriter.TYPE[opcode]) { 1384 case ClassWriter.NOARG_INSN: 1385 case ClassWriter.IMPLVAR_INSN: 1386 u += 1; 1387 break; 1388 case ClassWriter.LABEL_INSN: 1389 if (opcode > 201) { 1390 opcode = opcode < 218 ? opcode - 49 : opcode - 20; 1393 label = u + readUnsignedShort(b, u + 1); 1394 } else { 1395 label = u + readShort(b, u + 1); 1396 } 1397 newOffset = getNewOffset(allIndexes, allSizes, u, label); 1398 if (newOffset < Short.MIN_VALUE || newOffset > Short.MAX_VALUE) { 1399 if (!resize[u]) { 1400 if (opcode == Constants.GOTO || opcode == Constants.JSR) { 1401 insert = 2; 1404 } else { 1405 insert = 5; 1411 } 1412 resize[u] = true; 1413 } 1414 } 1415 u += 3; 1416 break; 1417 case ClassWriter.LABELW_INSN: 1418 u += 5; 1419 break; 1420 case ClassWriter.TABL_INSN: 1421 if (state == 1) { 1422 newOffset = getNewOffset(allIndexes, allSizes, 0, u); 1429 insert = -(newOffset & 3); 1430 } else if (!resize[u]) { 1431 insert = u & 3; 1435 resize[u] = true; 1436 } 1437 u = u + 4 - (u & 3); 1439 u += 4*(readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12; 1440 break; 1441 case ClassWriter.LOOK_INSN: 1442 if (state == 1) { 1443 newOffset = getNewOffset(allIndexes, allSizes, 0, u); 1445 insert = -(newOffset & 3); 1446 } else if (!resize[u]) { 1447 insert = u & 3; 1449 resize[u] = true; 1450 } 1451 u = u + 4 - (u & 3); 1453 u += 8*readInt(b, u + 4) + 8; 1454 break; 1455 case ClassWriter.WIDE_INSN: 1456 opcode = b[u + 1] & 0xFF; 1457 if (opcode == Constants.IINC) { 1458 u += 6; 1459 } else { 1460 u += 4; 1461 } 1462 break; 1463 case ClassWriter.VAR_INSN: 1464 case ClassWriter.SBYTE_INSN: 1465 case ClassWriter.LDC_INSN: 1466 u += 2; 1467 break; 1468 case ClassWriter.SHORT_INSN: 1469 case ClassWriter.LDCW_INSN: 1470 case ClassWriter.FIELDORMETH_INSN: 1471 case ClassWriter.TYPE_INSN: 1472 case ClassWriter.IINC_INSN: 1473 u += 3; 1474 break; 1475 case ClassWriter.ITFMETH_INSN: 1476 u += 5; 1477 break; 1478 default: 1480 u += 4; 1481 break; 1482 } 1483 if (insert != 0) { 1484 int[] newIndexes = new int[allIndexes.length + 1]; 1486 int[] newSizes = new int[allSizes.length + 1]; 1487 System.arraycopy(allIndexes, 0, newIndexes, 0, allIndexes.length); 1488 System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length); 1489 newIndexes[allIndexes.length] = u; 1490 newSizes[allSizes.length] = insert; 1491 allIndexes = newIndexes; 1492 allSizes = newSizes; 1493 if (insert > 0) { 1494 state = 3; 1495 } 1496 } 1497 } 1498 if (state < 3) { 1499 --state; 1500 } 1501 } while (state != 0); 1502 1503 1507 ByteVector newCode = new ByteVector(code.length); 1508 1509 u = 0; 1510 while (u < code.length) { 1511 for (i = allIndexes.length - 1; i >= 0; --i) { 1512 if (allIndexes[i] == u) { 1513 if (i < len) { 1514 if (sizes[i] > 0) { 1515 newCode.putByteArray(null, 0, sizes[i]); 1516 } else { 1517 newCode.length += sizes[i]; 1518 } 1519 indexes[i] = newCode.length; 1520 } 1521 } 1522 } 1523 int opcode = b[u] & 0xFF; 1524 switch (ClassWriter.TYPE[opcode]) { 1525 case ClassWriter.NOARG_INSN: 1526 case ClassWriter.IMPLVAR_INSN: 1527 newCode.put1(opcode); 1528 u += 1; 1529 break; 1530 case ClassWriter.LABEL_INSN: 1531 if (opcode > 201) { 1532 opcode = opcode < 218 ? opcode - 49 : opcode - 20; 1535 label = u + readUnsignedShort(b, u + 1); 1536 } else { 1537 label = u + readShort(b, u + 1); 1538 } 1539 newOffset = getNewOffset(allIndexes, allSizes, u, label); 1540 if (newOffset < Short.MIN_VALUE || newOffset > Short.MAX_VALUE) { 1541 if (opcode == Constants.GOTO) { 1546 newCode.put1(200); } else if (opcode == Constants.JSR) { 1548 newCode.put1(201); } else { 1550 newCode.put1(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1); 1551 newCode.put2(8); newCode.put1(200); newOffset -= 3; } 1555 newCode.put4(newOffset); 1556 } else { 1557 newCode.put1(opcode); 1558 newCode.put2(newOffset); 1559 } 1560 u += 3; 1561 break; 1562 case ClassWriter.LABELW_INSN: 1563 label = u + readInt(b, u + 1); 1564 newOffset = getNewOffset(allIndexes, allSizes, u, label); 1565 newCode.put1(opcode); 1566 newCode.put4(newOffset); 1567 u += 5; 1568 break; 1569 case ClassWriter.TABL_INSN: 1570 v = u; 1572 u = u + 4 - (v & 3); 1573 int source = newCode.length; 1575 newCode.put1(Constants.TABLESWITCH); 1576 while (newCode.length % 4 != 0) { 1577 newCode.put1(0); 1578 } 1579 label = v + readInt(b, u); u += 4; 1580 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1581 newCode.put4(newOffset); 1582 j = readInt(b, u); u += 4; 1583 newCode.put4(j); 1584 j = readInt(b, u) - j + 1; u += 4; 1585 newCode.put4(readInt(b, u - 4)); 1586 for ( ; j > 0; --j) { 1587 label = v + readInt(b, u); u += 4; 1588 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1589 newCode.put4(newOffset); 1590 } 1591 break; 1592 case ClassWriter.LOOK_INSN: 1593 v = u; 1595 u = u + 4 - (v & 3); 1596 source = newCode.length; 1598 newCode.put1(Constants.LOOKUPSWITCH); 1599 while (newCode.length % 4 != 0) { 1600 newCode.put1(0); 1601 } 1602 label = v + readInt(b, u); u += 4; 1603 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1604 newCode.put4(newOffset); 1605 j = readInt(b, u); u += 4; 1606 newCode.put4(j); 1607 for ( ; j > 0; --j) { 1608 newCode.put4(readInt(b, u)); u += 4; 1609 label = v + readInt(b, u); u += 4; 1610 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1611 newCode.put4(newOffset); 1612 } 1613 break; 1614 case ClassWriter.WIDE_INSN: 1615 opcode = b[u + 1] & 0xFF; 1616 if (opcode == Constants.IINC) { 1617 newCode.putByteArray(b, u, 6); 1618 u += 6; 1619 } else { 1620 newCode.putByteArray(b, u, 4); 1621 u += 4; 1622 } 1623 break; 1624 case ClassWriter.VAR_INSN: 1625 case ClassWriter.SBYTE_INSN: 1626 case ClassWriter.LDC_INSN: 1627 newCode.putByteArray(b, u, 2); 1628 u += 2; 1629 break; 1630 case ClassWriter.SHORT_INSN: 1631 case ClassWriter.LDCW_INSN: 1632 case ClassWriter.FIELDORMETH_INSN: 1633 case ClassWriter.TYPE_INSN: 1634 case ClassWriter.IINC_INSN: 1635 newCode.putByteArray(b, u, 3); 1636 u += 3; 1637 break; 1638 case ClassWriter.ITFMETH_INSN: 1639 newCode.putByteArray(b, u, 5); 1640 u += 5; 1641 break; 1642 default: 1644 newCode.putByteArray(b, u, 4); 1645 u += 4; 1646 break; 1647 } 1648 } 1649 1650 if (catchTable != null) { 1653 b = catchTable.data; 1654 u = 0; 1655 while (u < catchTable.length) { 1656 writeShort(b, u, getNewOffset( 1657 allIndexes, allSizes, 0, readUnsignedShort(b, u))); 1658 writeShort(b, u + 2, getNewOffset( 1659 allIndexes, allSizes, 0, readUnsignedShort(b, u + 2))); 1660 writeShort(b, u + 4, getNewOffset( 1661 allIndexes, allSizes, 0, readUnsignedShort(b, u + 4))); 1662 u += 8; 1663 } 1664 } 1665 if (localVar != null) { 1666 b = localVar.data; 1667 u = 0; 1668 while (u < localVar.length) { 1669 label = readUnsignedShort(b, u); 1670 newOffset = getNewOffset(allIndexes, allSizes, 0, label); 1671 writeShort(b, u, newOffset); 1672 label += readUnsignedShort(b, u + 2); 1673 newOffset = getNewOffset(allIndexes, allSizes, 0, label) - newOffset; 1674 writeShort(b, u, newOffset); 1675 u += 10; 1676 } 1677 } 1678 if (lineNumber != null) { 1679 b = lineNumber.data; 1680 u = 0; 1681 while (u < lineNumber.length) { 1682 writeShort(b, u, getNewOffset( 1683 allIndexes, allSizes, 0, readUnsignedShort(b, u))); 1684 u += 4; 1685 } 1686 } 1687 1688 code = newCode; 1690 1691 return indexes; 1693 } 1694 1695 1702 1703 static int readUnsignedShort (final byte[] b, final int index) { 1704 return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); 1705 } 1706 1707 1714 1715 static short readShort (final byte[] b, final int index) { 1716 return (short)(((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); 1717 } 1718 1719 1726 1727 static int readInt (final byte[] b, final int index) { 1728 return ((b[index] & 0xFF) << 24) | 1729 ((b[index + 1] & 0xFF) << 16) | 1730 ((b[index + 2] & 0xFF) << 8) | 1731 (b[index + 3] & 0xFF); 1732 } 1733 1734 1741 1742 static void writeShort (final byte[] b, final int index, final int s) { 1743 b[index] = (byte)(s >>> 8); 1744 b[index + 1] = (byte)s; 1745 } 1746 1747 1769 1770 static int getNewOffset ( 1771 final int[] indexes, 1772 final int[] sizes, 1773 final int begin, 1774 final int end) 1775 { 1776 int offset = end - begin; 1777 for (int i = 0; i < indexes.length; ++i) { 1778 if (begin < indexes[i] && indexes[i] <= end) { offset += sizes[i]; 1780 } else if (end < indexes[i] && indexes[i] <= begin) { offset -= sizes[i]; 1782 } 1783 } 1784 return offset; 1785 } 1786 1787 1795 1796 protected int getCodeSize () { 1797 return code.length; 1798 } 1799 1800 1809 1810 protected byte[] getCode () { 1811 return code.data; 1812 } 1813} 1814 | Popular Tags |