1 24 25 package bsh.org.objectweb.asm; 26 27 32 33 public class CodeWriter implements CodeVisitor { 34 35 38 39 final static boolean CHECK = false; 40 41 44 45 CodeWriter next; 46 47 50 51 private ClassWriter cw; 52 53 56 57 private Item name; 58 59 62 63 private Item desc; 64 65 68 69 private int access; 70 71 74 75 private int maxStack; 76 77 80 81 private int maxLocals; 82 83 86 87 private ByteVector code = new ByteVector(); 88 89 92 93 private int catchCount; 94 95 98 99 private ByteVector catchTable; 100 101 104 105 private int exceptionCount; 106 107 112 113 private int[] exceptions; 114 115 118 119 private int localVarCount; 120 121 124 125 private ByteVector localVar; 126 127 130 131 private int lineNumberCount; 132 133 136 137 private ByteVector lineNumber; 138 139 142 143 private boolean resize; 144 145 155 159 160 private final boolean computeMaxs; 161 162 169 170 private int stackSize; 171 172 179 180 private int maxStackSize; 181 182 186 187 private Label currentBlock; 188 189 195 196 private Label blockStack; 197 198 203 204 private final static int[] SIZE; 205 206 218 224 225 private Edge head; 226 227 233 234 private Edge tail; 235 236 240 241 private static Edge pool; 242 243 247 250 251 static { 252 int i; 253 int[] b = new int[202]; 254 String s = 255 "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDDCDCDEEEEEEEEE" + 256 "EEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCDCDCEEEEDDDDDDDCDCDCEFEF" + 257 "DDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFEDDDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE"; 258 for (i = 0; i < b.length; ++i) { 259 b[i] = s.charAt(i) - 'E'; 260 } 261 SIZE = b; 262 263 476 } 477 478 482 489 490 protected CodeWriter (final ClassWriter cw, final boolean computeMaxs) { 491 if (cw.firstMethod == null) { 492 cw.firstMethod = this; 493 cw.lastMethod = this; 494 } else { 495 cw.lastMethod.next = this; 496 cw.lastMethod = this; 497 } 498 this.cw = cw; 499 this.computeMaxs = computeMaxs; 500 if (computeMaxs) { 501 currentBlock = new Label(); 503 currentBlock.pushed = true; 504 blockStack = currentBlock; 505 } 506 } 507 508 517 518 protected void init ( 519 final int access, 520 final String name, 521 final String desc, 522 final String [] exceptions) 523 { 524 this.access = access; 525 this.name = cw.newUTF8(name); 526 this.desc = cw.newUTF8(desc); 527 if (exceptions != null && exceptions.length > 0) { 528 exceptionCount = exceptions.length; 529 this.exceptions = new int[exceptionCount]; 530 for (int i = 0; i < exceptionCount; ++i) { 531 this.exceptions[i] = cw.newClass(exceptions[i]).index; 532 } 533 } 534 if (computeMaxs) { 535 int size = getArgumentsAndReturnSizes(desc) >> 2; 537 if ((access & Constants.ACC_STATIC) != 0) { 538 --size; 539 } 540 if (size > maxLocals) { 541 maxLocals = size; 542 } 543 } 544 } 545 546 550 public void visitInsn (final int opcode) { 551 if (computeMaxs) { 552 int size = stackSize + SIZE[opcode]; 554 if (size > maxStackSize) { 555 maxStackSize = size; 556 } 557 stackSize = size; 558 if ((opcode >= Constants.IRETURN && opcode <= Constants.RETURN) || 560 opcode == Constants.ATHROW) 561 { 562 if (currentBlock != null) { 563 currentBlock.maxStackSize = maxStackSize; 564 currentBlock = null; 565 } 566 } 567 } 568 code.put1(opcode); 570 } 571 572 public void visitIntInsn (final int opcode, final int operand) { 573 if (computeMaxs && opcode != Constants.NEWARRAY) { 574 int size = stackSize + 1; 577 if (size > maxStackSize) { 578 maxStackSize = size; 579 } 580 stackSize = size; 581 } 582 if (opcode == Constants.SIPUSH) { 584 code.put12(opcode, operand); 585 } else { code.put11(opcode, operand); 587 } 588 } 589 590 public void visitVarInsn (final int opcode, final int var) { 591 if (computeMaxs) { 592 if (opcode == Constants.RET) { 594 if (currentBlock != null) { 596 currentBlock.maxStackSize = maxStackSize; 597 currentBlock = null; 598 } 599 } else { int size = stackSize + SIZE[opcode]; 601 if (size > maxStackSize) { 602 maxStackSize = size; 603 } 604 stackSize = size; 605 } 606 int n; 608 if (opcode == Constants.LLOAD || opcode == Constants.DLOAD || 609 opcode == Constants.LSTORE || opcode == Constants.DSTORE) 610 { 611 n = var + 2; 612 } else { 613 n = var + 1; 614 } 615 if (n > maxLocals) { 616 maxLocals = n; 617 } 618 } 619 if (var < 4 && opcode != Constants.RET) { 621 int opt; 622 if (opcode < Constants.ISTORE) { 623 opt = 26 + ((opcode - Constants.ILOAD) << 2) + var; 624 } else { 625 opt = 59 + ((opcode - Constants.ISTORE) << 2) + var; 626 } 627 code.put1(opt); 628 } else if (var >= 256) { 629 code.put1(196 ).put12(opcode, var); 630 } else { 631 code.put11(opcode, var); 632 } 633 } 634 635 public void visitTypeInsn (final int opcode, final String desc) { 636 if (computeMaxs && opcode == Constants.NEW) { 637 int size = stackSize + 1; 640 if (size > maxStackSize) { 641 maxStackSize = size; 642 } 643 stackSize = size; 644 } 645 code.put12(opcode, cw.newClass(desc).index); 647 } 648 649 public void visitFieldInsn ( 650 final int opcode, 651 final String owner, 652 final String name, 653 final String desc) 654 { 655 if (computeMaxs) { 656 int size; 657 char c = desc.charAt(0); 659 switch (opcode) { 660 case Constants.GETSTATIC: 661 size = stackSize + (c == 'D' || c == 'J' ? 2 : 1); 662 break; 663 case Constants.PUTSTATIC: 664 size = stackSize + (c == 'D' || c == 'J' ? -2 : -1); 665 break; 666 case Constants.GETFIELD: 667 size = stackSize + (c == 'D' || c == 'J' ? 1 : 0); 668 break; 669 default: 671 size = stackSize + (c == 'D' || c == 'J' ? -3 : -2); 672 break; 673 } 674 if (size > maxStackSize) { 676 maxStackSize = size; 677 } 678 stackSize = size; 679 } 680 code.put12(opcode, cw.newField(owner, name, desc).index); 682 } 683 684 public void visitMethodInsn ( 685 final int opcode, 686 final String owner, 687 final String name, 688 final String desc) 689 { 690 Item i; 691 if (opcode == Constants.INVOKEINTERFACE) { 692 i = cw.newItfMethod(owner, name, desc); 693 } else { 694 i = cw.newMethod(owner, name, desc); 695 } 696 int argSize = i.intVal; 697 if (computeMaxs) { 698 if (argSize == 0) { 704 argSize = getArgumentsAndReturnSizes(desc); 706 i.intVal = argSize; 708 } 709 int size; 710 if (opcode == Constants.INVOKESTATIC) { 711 size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1; 712 } else { 713 size = stackSize - (argSize >> 2) + (argSize & 0x03); 714 } 715 if (size > maxStackSize) { 717 maxStackSize = size; 718 } 719 stackSize = size; 720 } 721 if (opcode == Constants.INVOKEINTERFACE) { 723 if (!computeMaxs) { 724 if (argSize == 0) { 725 argSize = getArgumentsAndReturnSizes(desc); 726 i.intVal = argSize; 727 } 728 } 729 code.put12(Constants.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0); 730 } else { 731 code.put12(opcode, i.index); 732 } 733 } 734 735 public void visitJumpInsn (final int opcode, final Label label) { 736 if (CHECK) { 737 if (label.owner == null) { 738 label.owner = this; 739 } else if (label.owner != this) { 740 throw new IllegalArgumentException (); 741 } 742 } 743 if (computeMaxs) { 744 if (opcode == Constants.GOTO) { 745 if (currentBlock != null) { 747 currentBlock.maxStackSize = maxStackSize; 748 addSuccessor(stackSize, label); 749 currentBlock = null; 750 } 751 } else if (opcode == Constants.JSR) { 752 if (currentBlock != null) { 753 addSuccessor(stackSize + 1, label); 754 } 755 } else { 756 stackSize += SIZE[opcode]; 759 if (currentBlock != null) { 760 addSuccessor(stackSize, label); 761 } 762 } 763 } 764 if (label.resolved && label.position - code.length < Short.MIN_VALUE) { 766 if (opcode == Constants.GOTO) { 772 code.put1(200); } else if (opcode == Constants.JSR) { 774 code.put1(201); } else { 776 code.put1(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1); 777 code.put2(8); code.put1(200); } 780 label.put(this, code, code.length - 1, true); 781 } else { 782 code.put1(opcode); 786 label.put(this, code, code.length - 1, false); 787 } 788 } 789 790 public void visitLabel (final Label label) { 791 if (CHECK) { 792 if (label.owner == null) { 793 label.owner = this; 794 } else if (label.owner != this) { 795 throw new IllegalArgumentException (); 796 } 797 } 798 if (computeMaxs) { 799 if (currentBlock != null) { 800 currentBlock.maxStackSize = maxStackSize; 802 addSuccessor(stackSize, label); 803 } 804 currentBlock = label; 807 stackSize = 0; 808 maxStackSize = 0; 809 } 810 resize |= label.resolve(this, code.length, code.data); 812 } 813 814 public void visitLdcInsn (final Object cst) { 815 Item i = cw.newCst(cst); 816 if (computeMaxs) { 817 int size; 818 if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) { 820 size = stackSize + 2; 821 } else { 822 size = stackSize + 1; 823 } 824 if (size > maxStackSize) { 826 maxStackSize = size; 827 } 828 stackSize = size; 829 } 830 int index = i.index; 832 if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) { 833 code.put12(20 , index); 834 } else if (index >= 256) { 835 code.put12(19 , index); 836 } else { 837 code.put11(Constants.LDC, index); 838 } 839 } 840 841 public void visitIincInsn (final int var, final int increment) { 842 if (computeMaxs) { 843 int n = var + 1; 845 if (n > maxLocals) { 846 maxLocals = n; 847 } 848 } 849 if ((var > 255) || (increment > 127) || (increment < -128)) { 851 code.put1(196 ).put12(Constants.IINC, var).put2(increment); 852 } else { 853 code.put1(Constants.IINC).put11(var, increment); 854 } 855 } 856 857 public void visitTableSwitchInsn ( 858 final int min, 859 final int max, 860 final Label dflt, 861 final Label labels[]) 862 { 863 if (computeMaxs) { 864 --stackSize; 866 if (currentBlock != null) { 868 currentBlock.maxStackSize = maxStackSize; 869 addSuccessor(stackSize, dflt); 870 for (int i = 0; i < labels.length; ++i) { 871 addSuccessor(stackSize, labels[i]); 872 } 873 currentBlock = null; 874 } 875 } 876 int source = code.length; 878 code.put1(Constants.TABLESWITCH); 879 while (code.length % 4 != 0) { 880 code.put1(0); 881 } 882 dflt.put(this, code, source, true); 883 code.put4(min).put4(max); 884 for (int i = 0; i < labels.length; ++i) { 885 labels[i].put(this, code, source, true); 886 } 887 } 888 889 public void visitLookupSwitchInsn ( 890 final Label dflt, 891 final int keys[], 892 final Label labels[]) 893 { 894 if (computeMaxs) { 895 --stackSize; 897 if (currentBlock != null) { 899 currentBlock.maxStackSize = maxStackSize; 900 addSuccessor(stackSize, dflt); 901 for (int i = 0; i < labels.length; ++i) { 902 addSuccessor(stackSize, labels[i]); 903 } 904 currentBlock = null; 905 } 906 } 907 int source = code.length; 909 code.put1(Constants.LOOKUPSWITCH); 910 while (code.length % 4 != 0) { 911 code.put1(0); 912 } 913 dflt.put(this, code, source, true); 914 code.put4(labels.length); 915 for (int i = 0; i < labels.length; ++i) { 916 code.put4(keys[i]); 917 labels[i].put(this, code, source, true); 918 } 919 } 920 921 public void visitMultiANewArrayInsn (final String desc, final int dims) { 922 if (computeMaxs) { 923 stackSize += 1 - dims; 926 } 927 Item classItem = cw.newClass(desc); 929 code.put12(Constants.MULTIANEWARRAY, classItem.index).put1(dims); 930 } 931 932 public void visitTryCatchBlock ( 933 final Label start, 934 final Label end, 935 final Label handler, 936 final String type) 937 { 938 if (CHECK) { 939 if (start.owner != this || end.owner != this || handler.owner != this) { 940 throw new IllegalArgumentException (); 941 } 942 if (!start.resolved || !end.resolved || !handler.resolved) { 943 throw new IllegalArgumentException (); 944 } 945 } 946 if (computeMaxs) { 947 if (!handler.pushed) { 949 handler.beginStackSize = 1; 950 handler.pushed = true; 951 handler.next = blockStack; 952 blockStack = handler; 953 } 954 } 955 ++catchCount; 956 if (catchTable == null) { 957 catchTable = new ByteVector(); 958 } 959 catchTable.put2(start.position); 960 catchTable.put2(end.position); 961 catchTable.put2(handler.position); 962 catchTable.put2(type != null ? cw.newClass(type).index : 0); 963 } 964 965 public void visitMaxs (final int maxStack, final int maxLocals) { 966 if (computeMaxs) { 967 int max = 0; 969 Label stack = blockStack; 977 while (stack != null) { 978 Label l = stack; 980 stack = stack.next; 981 int start = l.beginStackSize; 983 int blockMax = start + l.maxStackSize; 984 if (blockMax > max) { 986 max = blockMax; 987 } 988 Edge b = l.successors; 990 while (b != null) { 991 l = b.successor; 992 if (!l.pushed) { 994 l.beginStackSize = start + b.stackSize; 996 l.pushed = true; 998 l.next = stack; 999 stack = l; 1000 } 1001 b = b.next; 1002 } 1003 } 1004 this.maxStack = max; 1005 synchronized (SIZE) { 1007 if (tail != null) { 1009 tail.poolNext = pool; 1010 pool = head; 1011 } 1012 } 1013 } else { 1014 this.maxStack = maxStack; 1015 this.maxLocals = maxLocals; 1016 } 1017 } 1018 1019 public void visitLocalVariable ( 1020 final String name, 1021 final String desc, 1022 final Label start, 1023 final Label end, 1024 final int index) 1025 { 1026 if (CHECK) { 1027 if (start.owner != this || !start.resolved) { 1028 throw new IllegalArgumentException (); 1029 } 1030 if (end.owner != this || !end.resolved) { 1031 throw new IllegalArgumentException (); 1032 } 1033 } 1034 if (localVar == null) { 1035 cw.newUTF8("LocalVariableTable"); 1036 localVar = new ByteVector(); 1037 } 1038 ++localVarCount; 1039 localVar.put2(start.position); 1040 localVar.put2(end.position - start.position); 1041 localVar.put2(cw.newUTF8(name).index); 1042 localVar.put2(cw.newUTF8(desc).index); 1043 localVar.put2(index); 1044 } 1045 1046 public void visitLineNumber (final int line, final Label start) { 1047 if (CHECK) { 1048 if (start.owner != this || !start.resolved) { 1049 throw new IllegalArgumentException (); 1050 } 1051 } 1052 if (lineNumber == null) { 1053 cw.newUTF8("LineNumberTable"); 1054 lineNumber = new ByteVector(); 1055 } 1056 ++lineNumberCount; 1057 lineNumber.put2(start.position); 1058 lineNumber.put2(line); 1059 } 1060 1061 1065 1075 1076 private static int getArgumentsAndReturnSizes (final String desc) { 1077 int n = 1; 1078 int c = 1; 1079 while (true) { 1080 char car = desc.charAt(c++); 1081 if (car == ')') { 1082 car = desc.charAt(c); 1083 return n << 2 | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1)); 1084 } else if (car == 'L') { 1085 while (desc.charAt(c++) != ';') { 1086 } 1087 n += 1; 1088 } else if (car == '[') { 1089 while ((car = desc.charAt(c)) == '[') { 1090 ++c; 1091 } 1092 if (car == 'D' || car == 'J') { 1093 n -= 1; 1094 } 1095 } else if (car == 'D' || car == 'J') { 1096 n += 2; 1097 } else { 1098 n += 1; 1099 } 1100 } 1101 } 1102 1103 1109 1110 private void addSuccessor (final int stackSize, final Label successor) { 1111 Edge b; 1112 synchronized (SIZE) { 1114 if (pool == null) { 1115 b = new Edge(); 1116 } else { 1117 b = pool; 1118 pool = pool.poolNext; 1120 } 1121 } 1122 if (tail == null) { 1124 tail = b; 1125 } 1126 b.poolNext = head; 1127 head = b; 1128 b.stackSize = stackSize; 1130 b.successor = successor; 1131 b.next = currentBlock.successors; 1133 currentBlock.successors = b; 1134 } 1135 1136 1140 1145 1146 final int getSize () { 1147 if (resize) { 1148 resizeInstructions(new int[0], new int[0], 0); 1150 } 1151 int size = 8; 1152 if (code.length > 0) { 1153 cw.newUTF8("Code"); 1154 size += 18 + code.length + 8 * catchCount; 1155 if (localVar != null) { 1156 size += 8 + localVar.length; 1157 } 1158 if (lineNumber != null) { 1159 size += 8 + lineNumber.length; 1160 } 1161 } 1162 if (exceptionCount > 0) { 1163 cw.newUTF8("Exceptions"); 1164 size += 8 + 2 * exceptionCount; 1165 } 1166 if ((access & Constants.ACC_SYNTHETIC) != 0) { 1167 cw.newUTF8("Synthetic"); 1168 size += 6; 1169 } 1170 if ((access & Constants.ACC_DEPRECATED) != 0) { 1171 cw.newUTF8("Deprecated"); 1172 size += 6; 1173 } 1174 return size; 1175 } 1176 1177 1183 1184 final void put (final ByteVector out) { 1185 out.put2(access).put2(name.index).put2(desc.index); 1186 int attributeCount = 0; 1187 if (code.length > 0) { 1188 ++attributeCount; 1189 } 1190 if (exceptionCount > 0) { 1191 ++attributeCount; 1192 } 1193 if ((access & Constants.ACC_SYNTHETIC) != 0) { 1194 ++attributeCount; 1195 } 1196 if ((access & Constants.ACC_DEPRECATED) != 0) { 1197 ++attributeCount; 1198 } 1199 out.put2(attributeCount); 1200 if (code.length > 0) { 1201 int size = 12 + code.length + 8 * catchCount; 1202 if (localVar != null) { 1203 size += 8 + localVar.length; 1204 } 1205 if (lineNumber != null) { 1206 size += 8 + lineNumber.length; 1207 } 1208 out.put2(cw.newUTF8("Code").index).put4(size); 1209 out.put2(maxStack).put2(maxLocals); 1210 out.put4(code.length).putByteArray(code.data, 0, code.length); 1211 out.put2(catchCount); 1212 if (catchCount > 0) { 1213 out.putByteArray(catchTable.data, 0, catchTable.length); 1214 } 1215 attributeCount = 0; 1216 if (localVar != null) { 1217 ++attributeCount; 1218 } 1219 if (lineNumber != null) { 1220 ++attributeCount; 1221 } 1222 out.put2(attributeCount); 1223 if (localVar != null) { 1224 out.put2(cw.newUTF8("LocalVariableTable").index); 1225 out.put4(localVar.length + 2).put2(localVarCount); 1226 out.putByteArray(localVar.data, 0, localVar.length); 1227 } 1228 if (lineNumber != null) { 1229 out.put2(cw.newUTF8("LineNumberTable").index); 1230 out.put4(lineNumber.length + 2).put2(lineNumberCount); 1231 out.putByteArray(lineNumber.data, 0, lineNumber.length); 1232 } 1233 } 1234 if (exceptionCount > 0) { 1235 out.put2(cw.newUTF8("Exceptions").index).put4(2 * exceptionCount + 2); 1236 out.put2(exceptionCount); 1237 for (int i = 0; i < exceptionCount; ++i) { 1238 out.put2(exceptions[i]); 1239 } 1240 } 1241 if ((access & Constants.ACC_SYNTHETIC) != 0) { 1242 out.put2(cw.newUTF8("Synthetic").index).put4(0); 1243 } 1244 if ((access & Constants.ACC_DEPRECATED) != 0) { 1245 out.put2(cw.newUTF8("Deprecated").index).put4(0); 1246 } 1247 } 1248 1249 1253 1285 1286 protected int[] resizeInstructions ( 1287 final int[] indexes, 1288 final int[] sizes, 1289 final int len) 1290 { 1291 byte[] b = code.data; int u, v, label; int i, j; 1295 1317 int[] allIndexes = new int[len]; int[] allSizes = new int[len]; boolean[] resize; int newOffset; 1322 System.arraycopy(indexes, 0, allIndexes, 0, len); 1323 System.arraycopy(sizes, 0, allSizes, 0, len); 1324 resize = new boolean[code.length]; 1325 1326 int state = 3; do { 1328 if (state == 3) { 1329 state = 2; 1330 } 1331 u = 0; 1332 while (u < b.length) { 1333 int opcode = b[u] & 0xFF; int insert = 0; 1336 switch (ClassWriter.TYPE[opcode]) { 1337 case ClassWriter.NOARG_INSN: 1338 case ClassWriter.IMPLVAR_INSN: 1339 u += 1; 1340 break; 1341 case ClassWriter.LABEL_INSN: 1342 if (opcode > 201) { 1343 opcode = opcode < 218 ? opcode - 49 : opcode - 20; 1346 label = u + readUnsignedShort(b, u + 1); 1347 } else { 1348 label = u + readShort(b, u + 1); 1349 } 1350 newOffset = getNewOffset(allIndexes, allSizes, u, label); 1351 if (newOffset < Short.MIN_VALUE || newOffset > Short.MAX_VALUE) { 1352 if (!resize[u]) { 1353 if (opcode == Constants.GOTO || opcode == Constants.JSR) { 1354 insert = 2; 1357 } else { 1358 insert = 5; 1364 } 1365 resize[u] = true; 1366 } 1367 } 1368 u += 3; 1369 break; 1370 case ClassWriter.LABELW_INSN: 1371 u += 5; 1372 break; 1373 case ClassWriter.TABL_INSN: 1374 if (state == 1) { 1375 newOffset = getNewOffset(allIndexes, allSizes, 0, u); 1382 insert = -(newOffset & 3); 1383 } else if (!resize[u]) { 1384 insert = u & 3; 1388 resize[u] = true; 1389 } 1390 u = u + 4 - (u & 3); 1392 u += 4*(readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12; 1393 break; 1394 case ClassWriter.LOOK_INSN: 1395 if (state == 1) { 1396 newOffset = getNewOffset(allIndexes, allSizes, 0, u); 1398 insert = -(newOffset & 3); 1399 } else if (!resize[u]) { 1400 insert = u & 3; 1402 resize[u] = true; 1403 } 1404 u = u + 4 - (u & 3); 1406 u += 8*readInt(b, u + 4) + 8; 1407 break; 1408 case ClassWriter.WIDE_INSN: 1409 opcode = b[u + 1] & 0xFF; 1410 if (opcode == Constants.IINC) { 1411 u += 6; 1412 } else { 1413 u += 4; 1414 } 1415 break; 1416 case ClassWriter.VAR_INSN: 1417 case ClassWriter.SBYTE_INSN: 1418 case ClassWriter.LDC_INSN: 1419 u += 2; 1420 break; 1421 case ClassWriter.SHORT_INSN: 1422 case ClassWriter.LDCW_INSN: 1423 case ClassWriter.FIELDORMETH_INSN: 1424 case ClassWriter.TYPE_INSN: 1425 case ClassWriter.IINC_INSN: 1426 u += 3; 1427 break; 1428 case ClassWriter.ITFMETH_INSN: 1429 u += 5; 1430 break; 1431 default: 1433 u += 4; 1434 break; 1435 } 1436 if (insert != 0) { 1437 int[] newIndexes = new int[allIndexes.length + 1]; 1439 int[] newSizes = new int[allSizes.length + 1]; 1440 System.arraycopy(allIndexes, 0, newIndexes, 0, allIndexes.length); 1441 System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length); 1442 newIndexes[allIndexes.length] = u; 1443 newSizes[allSizes.length] = insert; 1444 allIndexes = newIndexes; 1445 allSizes = newSizes; 1446 if (insert > 0) { 1447 state = 3; 1448 } 1449 } 1450 } 1451 if (state < 3) { 1452 --state; 1453 } 1454 } while (state != 0); 1455 1456 1460 ByteVector newCode = new ByteVector(code.length); 1461 1462 u = 0; 1463 while (u < code.length) { 1464 for (i = allIndexes.length - 1; i >= 0; --i) { 1465 if (allIndexes[i] == u) { 1466 if (i < len) { 1467 if (sizes[i] > 0) { 1468 newCode.putByteArray(null, 0, sizes[i]); 1469 } else { 1470 newCode.length += sizes[i]; 1471 } 1472 indexes[i] = newCode.length; 1473 } 1474 } 1475 } 1476 int opcode = b[u] & 0xFF; 1477 switch (ClassWriter.TYPE[opcode]) { 1478 case ClassWriter.NOARG_INSN: 1479 case ClassWriter.IMPLVAR_INSN: 1480 newCode.put1(opcode); 1481 u += 1; 1482 break; 1483 case ClassWriter.LABEL_INSN: 1484 if (opcode > 201) { 1485 opcode = opcode < 218 ? opcode - 49 : opcode - 20; 1488 label = u + readUnsignedShort(b, u + 1); 1489 } else { 1490 label = u + readShort(b, u + 1); 1491 } 1492 newOffset = getNewOffset(allIndexes, allSizes, u, label); 1493 if (newOffset < Short.MIN_VALUE || newOffset > Short.MAX_VALUE) { 1494 if (opcode == Constants.GOTO) { 1499 newCode.put1(200); } else if (opcode == Constants.JSR) { 1501 newCode.put1(201); } else { 1503 newCode.put1(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1); 1504 newCode.put2(8); newCode.put1(200); newOffset -= 3; } 1508 newCode.put4(newOffset); 1509 } else { 1510 newCode.put1(opcode); 1511 newCode.put2(newOffset); 1512 } 1513 u += 3; 1514 break; 1515 case ClassWriter.LABELW_INSN: 1516 label = u + readInt(b, u + 1); 1517 newOffset = getNewOffset(allIndexes, allSizes, u, label); 1518 newCode.put1(opcode); 1519 newCode.put4(newOffset); 1520 u += 5; 1521 break; 1522 case ClassWriter.TABL_INSN: 1523 v = u; 1525 u = u + 4 - (v & 3); 1526 int source = newCode.length; 1528 newCode.put1(Constants.TABLESWITCH); 1529 while (newCode.length % 4 != 0) { 1530 newCode.put1(0); 1531 } 1532 label = v + readInt(b, u); u += 4; 1533 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1534 newCode.put4(newOffset); 1535 j = readInt(b, u); u += 4; 1536 newCode.put4(j); 1537 j = readInt(b, u) - j + 1; u += 4; 1538 newCode.put4(readInt(b, u - 4)); 1539 for ( ; j > 0; --j) { 1540 label = v + readInt(b, u); u += 4; 1541 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1542 newCode.put4(newOffset); 1543 } 1544 break; 1545 case ClassWriter.LOOK_INSN: 1546 v = u; 1548 u = u + 4 - (v & 3); 1549 source = newCode.length; 1551 newCode.put1(Constants.LOOKUPSWITCH); 1552 while (newCode.length % 4 != 0) { 1553 newCode.put1(0); 1554 } 1555 label = v + readInt(b, u); u += 4; 1556 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1557 newCode.put4(newOffset); 1558 j = readInt(b, u); u += 4; 1559 newCode.put4(j); 1560 for ( ; j > 0; --j) { 1561 newCode.put4(readInt(b, u)); u += 4; 1562 label = v + readInt(b, u); u += 4; 1563 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1564 newCode.put4(newOffset); 1565 } 1566 break; 1567 case ClassWriter.WIDE_INSN: 1568 opcode = b[u + 1] & 0xFF; 1569 if (opcode == Constants.IINC) { 1570 newCode.putByteArray(b, u, 6); 1571 u += 6; 1572 } else { 1573 newCode.putByteArray(b, u, 4); 1574 u += 4; 1575 } 1576 break; 1577 case ClassWriter.VAR_INSN: 1578 case ClassWriter.SBYTE_INSN: 1579 case ClassWriter.LDC_INSN: 1580 newCode.putByteArray(b, u, 2); 1581 u += 2; 1582 break; 1583 case ClassWriter.SHORT_INSN: 1584 case ClassWriter.LDCW_INSN: 1585 case ClassWriter.FIELDORMETH_INSN: 1586 case ClassWriter.TYPE_INSN: 1587 case ClassWriter.IINC_INSN: 1588 newCode.putByteArray(b, u, 3); 1589 u += 3; 1590 break; 1591 case ClassWriter.ITFMETH_INSN: 1592 newCode.putByteArray(b, u, 5); 1593 u += 5; 1594 break; 1595 default: 1597 newCode.putByteArray(b, u, 4); 1598 u += 4; 1599 break; 1600 } 1601 } 1602 1603 if (catchTable != null) { 1606 b = catchTable.data; 1607 u = 0; 1608 while (u < catchTable.length) { 1609 writeShort(b, u, getNewOffset( 1610 allIndexes, allSizes, 0, readUnsignedShort(b, u))); 1611 writeShort(b, u + 2, getNewOffset( 1612 allIndexes, allSizes, 0, readUnsignedShort(b, u + 2))); 1613 writeShort(b, u + 4, getNewOffset( 1614 allIndexes, allSizes, 0, readUnsignedShort(b, u + 4))); 1615 u += 8; 1616 } 1617 } 1618 if (localVar != null) { 1619 b = localVar.data; 1620 u = 0; 1621 while (u < localVar.length) { 1622 label = readUnsignedShort(b, u); 1623 newOffset = getNewOffset(allIndexes, allSizes, 0, label); 1624 writeShort(b, u, newOffset); 1625 label += readUnsignedShort(b, u + 2); 1626 newOffset = getNewOffset(allIndexes, allSizes, 0, label) - newOffset; 1627 writeShort(b, u, newOffset); 1628 u += 10; 1629 } 1630 } 1631 if (lineNumber != null) { 1632 b = lineNumber.data; 1633 u = 0; 1634 while (u < lineNumber.length) { 1635 writeShort(b, u, getNewOffset( 1636 allIndexes, allSizes, 0, readUnsignedShort(b, u))); 1637 u += 4; 1638 } 1639 } 1640 1641 code = newCode; 1643 1644 return indexes; 1646 } 1647 1648 1655 1656 static int readUnsignedShort (final byte[] b, final int index) { 1657 return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); 1658 } 1659 1660 1667 1668 static short readShort (final byte[] b, final int index) { 1669 return (short)(((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); 1670 } 1671 1672 1679 1680 static int readInt (final byte[] b, final int index) { 1681 return ((b[index] & 0xFF) << 24) | 1682 ((b[index + 1] & 0xFF) << 16) | 1683 ((b[index + 2] & 0xFF) << 8) | 1684 (b[index + 3] & 0xFF); 1685 } 1686 1687 1694 1695 static void writeShort (final byte[] b, final int index, final int s) { 1696 b[index] = (byte)(s >>> 8); 1697 b[index + 1] = (byte)s; 1698 } 1699 1700 1722 1723 static int getNewOffset ( 1724 final int[] indexes, 1725 final int[] sizes, 1726 final int begin, 1727 final int end) 1728 { 1729 int offset = end - begin; 1730 for (int i = 0; i < indexes.length; ++i) { 1731 if (begin < indexes[i] && indexes[i] <= end) { offset += sizes[i]; 1733 } else if (end < indexes[i] && indexes[i] <= begin) { offset -= sizes[i]; 1735 } 1736 } 1737 return offset; 1738 } 1739 1740 1748 1749 protected int getCodeSize () { 1750 return code.length; 1751 } 1752 1753 1762 1763 protected byte[] getCode () { 1764 return code.data; 1765 } 1766} 1767 | Popular Tags |