1 30 31 package oracle.toplink.libraries.asm; 32 33 40 41 public class CodeWriter implements CodeVisitor { 42 43 46 47 final static boolean CHECK = false; 48 49 52 53 CodeWriter next; 54 55 58 59 private ClassWriter cw; 60 61 64 65 private int name; 66 67 71 72 private int desc; 73 74 77 78 private int access; 79 80 83 84 private int maxStack; 85 86 89 90 private int maxLocals; 91 92 95 96 private ByteVector code = new ByteVector(); 97 98 101 102 private int catchCount; 103 104 107 108 private ByteVector catchTable; 109 110 113 114 private int exceptionCount; 115 116 121 122 private int[] exceptions; 123 124 127 128 private Attribute attrs; 129 130 133 134 private int localVarCount; 135 136 139 140 private ByteVector localVar; 141 142 145 146 private int lineNumberCount; 147 148 151 152 private ByteVector lineNumber; 153 154 157 158 private Attribute cattrs; 159 160 163 164 private boolean resize; 165 166 176 180 181 private final boolean computeMaxs; 182 183 190 191 private int stackSize; 192 193 200 201 private int maxStackSize; 202 203 207 208 private Label currentBlock; 209 210 216 217 private Label blockStack; 218 219 224 225 private final static int[] SIZE; 226 227 239 245 246 private Edge head; 247 248 254 255 private Edge tail; 256 257 261 262 private static Edge pool; 263 264 268 271 272 static { 273 int i; 274 int[] b = new int[202]; 275 String s = 276 "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDDCDCDEEEEEEEEE" + 277 "EEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCDCDCEEEEDDDDDDDCDCDCEFEF" + 278 "DDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFEDDDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE"; 279 for (i = 0; i < b.length; ++i) { 280 b[i] = s.charAt(i) - 'E'; 281 } 282 SIZE = b; 283 284 497 } 498 499 503 510 511 protected CodeWriter (final ClassWriter cw, final boolean computeMaxs) { 512 if (cw.firstMethod == null) { 513 cw.firstMethod = this; 514 } else { 515 cw.lastMethod.next = this; 516 } 517 cw.lastMethod = this; 518 this.cw = cw; 519 this.computeMaxs = computeMaxs; 520 if (computeMaxs) { 521 currentBlock = new Label(); 523 currentBlock.pushed = true; 524 blockStack = currentBlock; 525 } 526 } 527 528 538 539 protected void init ( 540 final int access, 541 final String name, 542 final String desc, 543 final String [] exceptions, 544 final Attribute attrs) 545 { 546 this.access = access; 547 this.name = cw.newUTF8(name); 548 this.desc = cw.newUTF8(desc); 549 if (exceptions != null && exceptions.length > 0) { 550 exceptionCount = exceptions.length; 551 this.exceptions = new int[exceptionCount]; 552 for (int i = 0; i < exceptionCount; ++i) { 553 this.exceptions[i] = cw.newClass(exceptions[i]); 554 } 555 } 556 this.attrs = attrs; 557 if (computeMaxs) { 558 int size = getArgumentsAndReturnSizes(desc) >> 2; 560 if ((access & Constants.ACC_STATIC) != 0) { 561 --size; 562 } 563 if (size > maxLocals) { 564 maxLocals = size; 565 } 566 } 567 } 568 569 573 public void visitInsn (final int opcode) { 574 if (computeMaxs) { 575 int size = stackSize + SIZE[opcode]; 577 if (size > maxStackSize) { 578 maxStackSize = size; 579 } 580 stackSize = size; 581 if ((opcode >= Constants.IRETURN && opcode <= Constants.RETURN) || 583 opcode == Constants.ATHROW) 584 { 585 if (currentBlock != null) { 586 currentBlock.maxStackSize = maxStackSize; 587 currentBlock = null; 588 } 589 } 590 } 591 code.putByte(opcode); 593 } 594 595 public void visitIntInsn (final int opcode, final int operand) { 596 if (computeMaxs && opcode != Constants.NEWARRAY) { 597 int size = stackSize + 1; 600 if (size > maxStackSize) { 601 maxStackSize = size; 602 } 603 stackSize = size; 604 } 605 if (opcode == Constants.SIPUSH) { 607 code.put12(opcode, operand); 608 } else { code.put11(opcode, operand); 610 } 611 } 612 613 public void visitVarInsn (final int opcode, final int var) { 614 if (computeMaxs) { 615 if (opcode == Constants.RET) { 617 if (currentBlock != null) { 619 currentBlock.maxStackSize = maxStackSize; 620 currentBlock = null; 621 } 622 } else { int size = stackSize + SIZE[opcode]; 624 if (size > maxStackSize) { 625 maxStackSize = size; 626 } 627 stackSize = size; 628 } 629 int n; 631 if (opcode == Constants.LLOAD || opcode == Constants.DLOAD || 632 opcode == Constants.LSTORE || opcode == Constants.DSTORE) 633 { 634 n = var + 2; 635 } else { 636 n = var + 1; 637 } 638 if (n > maxLocals) { 639 maxLocals = n; 640 } 641 } 642 if (var < 4 && opcode != Constants.RET) { 644 int opt; 645 if (opcode < Constants.ISTORE) { 646 opt = 26 + ((opcode - Constants.ILOAD) << 2) + var; 647 } else { 648 opt = 59 + ((opcode - Constants.ISTORE) << 2) + var; 649 } 650 code.putByte(opt); 651 } else if (var >= 256) { 652 code.putByte(196 ).put12(opcode, var); 653 } else { 654 code.put11(opcode, var); 655 } 656 } 657 658 public void visitTypeInsn (final int opcode, final String desc) { 659 if (computeMaxs && opcode == Constants.NEW) { 660 int size = stackSize + 1; 663 if (size > maxStackSize) { 664 maxStackSize = size; 665 } 666 stackSize = size; 667 } 668 code.put12(opcode, cw.newClass(desc)); 670 } 671 672 public void visitFieldInsn ( 673 final int opcode, 674 final String owner, 675 final String name, 676 final String desc) 677 { 678 if (computeMaxs) { 679 int size; 680 char c = desc.charAt(0); 682 switch (opcode) { 683 case Constants.GETSTATIC: 684 size = stackSize + (c == 'D' || c == 'J' ? 2 : 1); 685 break; 686 case Constants.PUTSTATIC: 687 size = stackSize + (c == 'D' || c == 'J' ? -2 : -1); 688 break; 689 case Constants.GETFIELD: 690 size = stackSize + (c == 'D' || c == 'J' ? 1 : 0); 691 break; 692 default: 694 size = stackSize + (c == 'D' || c == 'J' ? -3 : -2); 695 break; 696 } 697 if (size > maxStackSize) { 699 maxStackSize = size; 700 } 701 stackSize = size; 702 } 703 code.put12(opcode, cw.newField(owner, name, desc)); 705 } 706 707 public void visitMethodInsn ( 708 final int opcode, 709 final String owner, 710 final String name, 711 final String desc) 712 { 713 boolean itf = opcode == Constants.INVOKEINTERFACE; 714 Item i = cw.newMethodItem(owner, name, desc, itf); 715 int argSize = i.intVal; 716 if (computeMaxs) { 717 if (argSize == 0) { 723 argSize = getArgumentsAndReturnSizes(desc); 725 i.intVal = argSize; 727 } 728 int size; 729 if (opcode == Constants.INVOKESTATIC) { 730 size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1; 731 } else { 732 size = stackSize - (argSize >> 2) + (argSize & 0x03); 733 } 734 if (size > maxStackSize) { 736 maxStackSize = size; 737 } 738 stackSize = size; 739 } 740 if (itf) { 742 if (!computeMaxs) { 743 if (argSize == 0) { 744 argSize = getArgumentsAndReturnSizes(desc); 745 i.intVal = argSize; 746 } 747 } 748 code.put12(Constants.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0); 749 } else { 750 code.put12(opcode, i.index); 751 } 752 } 753 754 public void visitJumpInsn (final int opcode, final Label label) { 755 if (CHECK) { 756 if (label.owner == null) { 757 label.owner = this; 758 } else if (label.owner != this) { 759 throw new IllegalArgumentException (); 760 } 761 } 762 if (computeMaxs) { 763 if (opcode == Constants.GOTO) { 764 if (currentBlock != null) { 766 currentBlock.maxStackSize = maxStackSize; 767 addSuccessor(stackSize, label); 768 currentBlock = null; 769 } 770 } else if (opcode == Constants.JSR) { 771 if (currentBlock != null) { 772 addSuccessor(stackSize + 1, label); 773 } 774 } else { 775 stackSize += SIZE[opcode]; 778 if (currentBlock != null) { 779 addSuccessor(stackSize, label); 780 } 781 } 782 } 783 if (label.resolved && label.position - code.length < Short.MIN_VALUE) { 785 if (opcode == Constants.GOTO) { 791 code.putByte(200); } else if (opcode == Constants.JSR) { 793 code.putByte(201); } else { 795 code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1); 796 code.putShort(8); code.putByte(200); } 799 label.put(this, code, code.length - 1, true); 800 } else { 801 code.putByte(opcode); 805 label.put(this, code, code.length - 1, false); 806 } 807 } 808 809 public void visitLabel (final Label label) { 810 if (CHECK) { 811 if (label.owner == null) { 812 label.owner = this; 813 } else if (label.owner != this) { 814 throw new IllegalArgumentException (); 815 } 816 } 817 if (computeMaxs) { 818 if (currentBlock != null) { 819 currentBlock.maxStackSize = maxStackSize; 821 addSuccessor(stackSize, label); 822 } 823 currentBlock = label; 826 stackSize = 0; 827 maxStackSize = 0; 828 } 829 resize |= label.resolve(this, code.length, code.data); 831 } 832 833 public void visitLdcInsn (final Object cst) { 834 Item i = cw.newConstItem(cst); 835 if (computeMaxs) { 836 int size; 837 if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) { 839 size = stackSize + 2; 840 } else { 841 size = stackSize + 1; 842 } 843 if (size > maxStackSize) { 845 maxStackSize = size; 846 } 847 stackSize = size; 848 } 849 int index = i.index; 851 if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) { 852 code.put12(20 , index); 853 } else if (index >= 256) { 854 code.put12(19 , index); 855 } else { 856 code.put11(Constants.LDC, index); 857 } 858 } 859 860 public void visitIincInsn (final int var, final int increment) { 861 if (computeMaxs) { 862 int n = var + 1; 864 if (n > maxLocals) { 865 maxLocals = n; 866 } 867 } 868 if ((var > 255) || (increment > 127) || (increment < -128)) { 870 code.putByte(196 ).put12(Constants.IINC, var).putShort(increment); 871 } else { 872 code.putByte(Constants.IINC).put11(var, increment); 873 } 874 } 875 876 public void visitTableSwitchInsn ( 877 final int min, 878 final int max, 879 final Label dflt, 880 final Label labels[]) 881 { 882 if (computeMaxs) { 883 --stackSize; 885 if (currentBlock != null) { 887 currentBlock.maxStackSize = maxStackSize; 888 addSuccessor(stackSize, dflt); 889 for (int i = 0; i < labels.length; ++i) { 890 addSuccessor(stackSize, labels[i]); 891 } 892 currentBlock = null; 893 } 894 } 895 int source = code.length; 897 code.putByte(Constants.TABLESWITCH); 898 while (code.length % 4 != 0) { 899 code.putByte(0); 900 } 901 dflt.put(this, code, source, true); 902 code.putInt(min).putInt(max); 903 for (int i = 0; i < labels.length; ++i) { 904 labels[i].put(this, code, source, true); 905 } 906 } 907 908 public void visitLookupSwitchInsn ( 909 final Label dflt, 910 final int keys[], 911 final Label labels[]) 912 { 913 if (computeMaxs) { 914 --stackSize; 916 if (currentBlock != null) { 918 currentBlock.maxStackSize = maxStackSize; 919 addSuccessor(stackSize, dflt); 920 for (int i = 0; i < labels.length; ++i) { 921 addSuccessor(stackSize, labels[i]); 922 } 923 currentBlock = null; 924 } 925 } 926 int source = code.length; 928 code.putByte(Constants.LOOKUPSWITCH); 929 while (code.length % 4 != 0) { 930 code.putByte(0); 931 } 932 dflt.put(this, code, source, true); 933 code.putInt(labels.length); 934 for (int i = 0; i < labels.length; ++i) { 935 code.putInt(keys[i]); 936 labels[i].put(this, code, source, true); 937 } 938 } 939 940 public void visitMultiANewArrayInsn (final String desc, final int dims) { 941 if (computeMaxs) { 942 stackSize += 1 - dims; 945 } 946 code.put12(Constants.MULTIANEWARRAY, cw.newClass(desc)).putByte(dims); 948 } 949 950 public void visitTryCatchBlock ( 951 final Label start, 952 final Label end, 953 final Label handler, 954 final String type) 955 { 956 if (CHECK) { 957 if (start.owner != this || end.owner != this || handler.owner != this) { 958 throw new IllegalArgumentException (); 959 } 960 if (!start.resolved || !end.resolved || !handler.resolved) { 961 throw new IllegalArgumentException (); 962 } 963 } 964 if (computeMaxs) { 965 if (!handler.pushed) { 967 handler.beginStackSize = 1; 968 handler.pushed = true; 969 handler.next = blockStack; 970 blockStack = handler; 971 } 972 } 973 ++catchCount; 974 if (catchTable == null) { 975 catchTable = new ByteVector(); 976 } 977 catchTable.putShort(start.position); 978 catchTable.putShort(end.position); 979 catchTable.putShort(handler.position); 980 catchTable.putShort(type != null ? cw.newClass(type) : 0); 981 } 982 983 public void visitMaxs (final int maxStack, final int maxLocals) { 984 if (computeMaxs) { 985 int max = 0; 987 Label stack = blockStack; 995 while (stack != null) { 996 Label l = stack; 998 stack = stack.next; 999 int start = l.beginStackSize; 1001 int blockMax = start + l.maxStackSize; 1002 if (blockMax > max) { 1004 max = blockMax; 1005 } 1006 Edge b = l.successors; 1008 while (b != null) { 1009 l = b.successor; 1010 if (!l.pushed) { 1012 l.beginStackSize = start + b.stackSize; 1014 l.pushed = true; 1016 l.next = stack; 1017 stack = l; 1018 } 1019 b = b.next; 1020 } 1021 } 1022 this.maxStack = max; 1023 synchronized (SIZE) { 1025 if (tail != null) { 1027 tail.poolNext = pool; 1028 pool = head; 1029 } 1030 } 1031 } else { 1032 this.maxStack = maxStack; 1033 this.maxLocals = maxLocals; 1034 } 1035 } 1036 1037 public void visitLocalVariable ( 1038 final String name, 1039 final String desc, 1040 final Label start, 1041 final Label end, 1042 final int index) 1043 { 1044 if (CHECK) { 1045 if (start.owner != this || !start.resolved) { 1046 throw new IllegalArgumentException (); 1047 } 1048 if (end.owner != this || !end.resolved) { 1049 throw new IllegalArgumentException (); 1050 } 1051 } 1052 if (localVar == null) { 1053 cw.newUTF8("LocalVariableTable"); 1054 localVar = new ByteVector(); 1055 } 1056 ++localVarCount; 1057 localVar.putShort(start.position); 1058 localVar.putShort(end.position - start.position); 1059 localVar.putShort(cw.newUTF8(name)); 1060 localVar.putShort(cw.newUTF8(desc)); 1061 localVar.putShort(index); 1062 } 1063 1064 public void visitLineNumber (final int line, final Label start) { 1065 if (CHECK) { 1066 if (start.owner != this || !start.resolved) { 1067 throw new IllegalArgumentException (); 1068 } 1069 } 1070 if (lineNumber == null) { 1071 cw.newUTF8("LineNumberTable"); 1072 lineNumber = new ByteVector(); 1073 } 1074 ++lineNumberCount; 1075 lineNumber.putShort(start.position); 1076 lineNumber.putShort(line); 1077 } 1078 1079 public void visitAttribute (final Attribute attr) { 1080 attr.next = cattrs; 1081 cattrs = attr; 1082 } 1083 1084 1088 1098 1099 private static int getArgumentsAndReturnSizes (final String desc) { 1100 int n = 1; 1101 int c = 1; 1102 while (true) { 1103 char car = desc.charAt(c++); 1104 if (car == ')') { 1105 car = desc.charAt(c); 1106 return n << 2 | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1)); 1107 } else if (car == 'L') { 1108 while (desc.charAt(c++) != ';') { 1109 } 1110 n += 1; 1111 } else if (car == '[') { 1112 while ((car = desc.charAt(c)) == '[') { 1113 ++c; 1114 } 1115 if (car == 'D' || car == 'J') { 1116 n -= 1; 1117 } 1118 } else if (car == 'D' || car == 'J') { 1119 n += 2; 1120 } else { 1121 n += 1; 1122 } 1123 } 1124 } 1125 1126 1132 1133 private void addSuccessor (final int stackSize, final Label successor) { 1134 Edge b; 1135 synchronized (SIZE) { 1137 if (pool == null) { 1138 b = new Edge(); 1139 } else { 1140 b = pool; 1141 pool = pool.poolNext; 1143 } 1144 } 1145 if (tail == null) { 1147 tail = b; 1148 } 1149 b.poolNext = head; 1150 head = b; 1151 b.stackSize = stackSize; 1153 b.successor = successor; 1154 b.next = currentBlock.successors; 1156 currentBlock.successors = b; 1157 } 1158 1159 1163 1168 1169 final int getSize () { 1170 if (resize) { 1171 resizeInstructions(new int[0], new int[0], 0); 1173 } 1174 int size = 8; 1175 if (code.length > 0) { 1176 cw.newUTF8("Code"); 1177 size += 18 + code.length + 8 * catchCount; 1178 if (localVar != null) { 1179 size += 8 + localVar.length; 1180 } 1181 if (lineNumber != null) { 1182 size += 8 + lineNumber.length; 1183 } 1184 if (cattrs != null) { 1185 size += cattrs.getSize(cw, code.data, code.length, maxStack, maxLocals); 1186 } 1187 } 1188 if (exceptionCount > 0) { 1189 cw.newUTF8("Exceptions"); 1190 size += 8 + 2 * exceptionCount; 1191 } 1192 if ((access & Constants.ACC_SYNTHETIC) != 0) { 1193 cw.newUTF8("Synthetic"); 1194 size += 6; 1195 } 1196 if ((access & Constants.ACC_DEPRECATED) != 0) { 1197 cw.newUTF8("Deprecated"); 1198 size += 6; 1199 } 1200 if (attrs != null) { 1201 size += attrs.getSize(cw, null, 0, -1, -1); 1202 } 1203 return size; 1204 } 1205 1206 1212 1213 final void put (final ByteVector out) { 1214 out.putShort(access).putShort(name).putShort(desc); 1215 int attributeCount = 0; 1216 if (code.length > 0) { 1217 ++attributeCount; 1218 } 1219 if (exceptionCount > 0) { 1220 ++attributeCount; 1221 } 1222 if ((access & Constants.ACC_SYNTHETIC) != 0) { 1223 ++attributeCount; 1224 } 1225 if ((access & Constants.ACC_DEPRECATED) != 0) { 1226 ++attributeCount; 1227 } 1228 if (attrs != null) { 1229 attributeCount += attrs.getCount(); 1230 } 1231 out.putShort(attributeCount); 1232 if (code.length > 0) { 1233 int size = 12 + code.length + 8 * catchCount; 1234 if (localVar != null) { 1235 size += 8 + localVar.length; 1236 } 1237 if (lineNumber != null) { 1238 size += 8 + lineNumber.length; 1239 } 1240 if (cattrs != null) { 1241 size += cattrs.getSize(cw, code.data, code.length, maxStack, maxLocals); 1242 } 1243 out.putShort(cw.newUTF8("Code")).putInt(size); 1244 out.putShort(maxStack).putShort(maxLocals); 1245 out.putInt(code.length).putByteArray(code.data, 0, code.length); 1246 out.putShort(catchCount); 1247 if (catchCount > 0) { 1248 out.putByteArray(catchTable.data, 0, catchTable.length); 1249 } 1250 attributeCount = 0; 1251 if (localVar != null) { 1252 ++attributeCount; 1253 } 1254 if (lineNumber != null) { 1255 ++attributeCount; 1256 } 1257 if (cattrs != null) { 1258 attributeCount += cattrs.getCount(); 1259 } 1260 out.putShort(attributeCount); 1261 if (localVar != null) { 1262 out.putShort(cw.newUTF8("LocalVariableTable")); 1263 out.putInt(localVar.length + 2).putShort(localVarCount); 1264 out.putByteArray(localVar.data, 0, localVar.length); 1265 } 1266 if (lineNumber != null) { 1267 out.putShort(cw.newUTF8("LineNumberTable")); 1268 out.putInt(lineNumber.length + 2).putShort(lineNumberCount); 1269 out.putByteArray(lineNumber.data, 0, lineNumber.length); 1270 } 1271 if (cattrs != null) { 1272 cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out); 1273 } 1274 } 1275 if (exceptionCount > 0) { 1276 out.putShort(cw.newUTF8("Exceptions")).putInt(2 * exceptionCount + 2); 1277 out.putShort(exceptionCount); 1278 for (int i = 0; i < exceptionCount; ++i) { 1279 out.putShort(exceptions[i]); 1280 } 1281 } 1282 if ((access & Constants.ACC_SYNTHETIC) != 0) { 1283 out.putShort(cw.newUTF8("Synthetic")).putInt(0); 1284 } 1285 if ((access & Constants.ACC_DEPRECATED) != 0) { 1286 out.putShort(cw.newUTF8("Deprecated")).putInt(0); 1287 } 1288 if (attrs != null) { 1289 attrs.put(cw, null, 0, -1, -1, out); 1290 } 1291 } 1292 1293 1297 1329 1330 protected int[] resizeInstructions ( 1331 final int[] indexes, 1332 final int[] sizes, 1333 final int len) 1334 { 1335 byte[] b = code.data; int u, v, label; int i, j; 1339 1361 int[] allIndexes = new int[len]; int[] allSizes = new int[len]; boolean[] resize; int newOffset; 1366 System.arraycopy(indexes, 0, allIndexes, 0, len); 1367 System.arraycopy(sizes, 0, allSizes, 0, len); 1368 resize = new boolean[code.length]; 1369 1370 int state = 3; do { 1372 if (state == 3) { 1373 state = 2; 1374 } 1375 u = 0; 1376 while (u < b.length) { 1377 int opcode = b[u] & 0xFF; int insert = 0; 1380 switch (ClassWriter.TYPE[opcode]) { 1381 case ClassWriter.NOARG_INSN: 1382 case ClassWriter.IMPLVAR_INSN: 1383 u += 1; 1384 break; 1385 case ClassWriter.LABEL_INSN: 1386 if (opcode > 201) { 1387 opcode = opcode < 218 ? opcode - 49 : opcode - 20; 1390 label = u + readUnsignedShort(b, u + 1); 1391 } else { 1392 label = u + readShort(b, u + 1); 1393 } 1394 newOffset = getNewOffset(allIndexes, allSizes, u, label); 1395 if (newOffset < Short.MIN_VALUE || newOffset > Short.MAX_VALUE) { 1396 if (!resize[u]) { 1397 if (opcode == Constants.GOTO || opcode == Constants.JSR) { 1398 insert = 2; 1401 } else { 1402 insert = 5; 1408 } 1409 resize[u] = true; 1410 } 1411 } 1412 u += 3; 1413 break; 1414 case ClassWriter.LABELW_INSN: 1415 u += 5; 1416 break; 1417 case ClassWriter.TABL_INSN: 1418 if (state == 1) { 1419 newOffset = getNewOffset(allIndexes, allSizes, 0, u); 1426 insert = -(newOffset & 3); 1427 } else if (!resize[u]) { 1428 insert = u & 3; 1432 resize[u] = true; 1433 } 1434 u = u + 4 - (u & 3); 1436 u += 4*(readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12; 1437 break; 1438 case ClassWriter.LOOK_INSN: 1439 if (state == 1) { 1440 newOffset = getNewOffset(allIndexes, allSizes, 0, u); 1442 insert = -(newOffset & 3); 1443 } else if (!resize[u]) { 1444 insert = u & 3; 1446 resize[u] = true; 1447 } 1448 u = u + 4 - (u & 3); 1450 u += 8*readInt(b, u + 4) + 8; 1451 break; 1452 case ClassWriter.WIDE_INSN: 1453 opcode = b[u + 1] & 0xFF; 1454 if (opcode == Constants.IINC) { 1455 u += 6; 1456 } else { 1457 u += 4; 1458 } 1459 break; 1460 case ClassWriter.VAR_INSN: 1461 case ClassWriter.SBYTE_INSN: 1462 case ClassWriter.LDC_INSN: 1463 u += 2; 1464 break; 1465 case ClassWriter.SHORT_INSN: 1466 case ClassWriter.LDCW_INSN: 1467 case ClassWriter.FIELDORMETH_INSN: 1468 case ClassWriter.TYPE_INSN: 1469 case ClassWriter.IINC_INSN: 1470 u += 3; 1471 break; 1472 case ClassWriter.ITFMETH_INSN: 1473 u += 5; 1474 break; 1475 default: 1477 u += 4; 1478 break; 1479 } 1480 if (insert != 0) { 1481 int[] newIndexes = new int[allIndexes.length + 1]; 1483 int[] newSizes = new int[allSizes.length + 1]; 1484 System.arraycopy(allIndexes, 0, newIndexes, 0, allIndexes.length); 1485 System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length); 1486 newIndexes[allIndexes.length] = u; 1487 newSizes[allSizes.length] = insert; 1488 allIndexes = newIndexes; 1489 allSizes = newSizes; 1490 if (insert > 0) { 1491 state = 3; 1492 } 1493 } 1494 } 1495 if (state < 3) { 1496 --state; 1497 } 1498 } while (state != 0); 1499 1500 1504 ByteVector newCode = new ByteVector(code.length); 1505 1506 u = 0; 1507 while (u < code.length) { 1508 for (i = allIndexes.length - 1; i >= 0; --i) { 1509 if (allIndexes[i] == u) { 1510 if (i < len) { 1511 if (sizes[i] > 0) { 1512 newCode.putByteArray(null, 0, sizes[i]); 1513 } else { 1514 newCode.length += sizes[i]; 1515 } 1516 indexes[i] = newCode.length; 1517 } 1518 } 1519 } 1520 int opcode = b[u] & 0xFF; 1521 switch (ClassWriter.TYPE[opcode]) { 1522 case ClassWriter.NOARG_INSN: 1523 case ClassWriter.IMPLVAR_INSN: 1524 newCode.putByte(opcode); 1525 u += 1; 1526 break; 1527 case ClassWriter.LABEL_INSN: 1528 if (opcode > 201) { 1529 opcode = opcode < 218 ? opcode - 49 : opcode - 20; 1532 label = u + readUnsignedShort(b, u + 1); 1533 } else { 1534 label = u + readShort(b, u + 1); 1535 } 1536 newOffset = getNewOffset(allIndexes, allSizes, u, label); 1537 if (resize[u]) { 1538 if (opcode == Constants.GOTO) { 1543 newCode.putByte(200); } else if (opcode == Constants.JSR) { 1545 newCode.putByte(201); } else { 1547 newCode.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1); 1548 newCode.putShort(8); newCode.putByte(200); newOffset -= 3; } 1552 newCode.putInt(newOffset); 1553 } else { 1554 newCode.putByte(opcode); 1555 newCode.putShort(newOffset); 1556 } 1557 u += 3; 1558 break; 1559 case ClassWriter.LABELW_INSN: 1560 label = u + readInt(b, u + 1); 1561 newOffset = getNewOffset(allIndexes, allSizes, u, label); 1562 newCode.putByte(opcode); 1563 newCode.putInt(newOffset); 1564 u += 5; 1565 break; 1566 case ClassWriter.TABL_INSN: 1567 v = u; 1569 u = u + 4 - (v & 3); 1570 newCode.putByte(Constants.TABLESWITCH); 1572 while (newCode.length % 4 != 0) { 1573 newCode.putByte(0); 1574 } 1575 label = v + readInt(b, u); u += 4; 1576 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1577 newCode.putInt(newOffset); 1578 j = readInt(b, u); u += 4; 1579 newCode.putInt(j); 1580 j = readInt(b, u) - j + 1; u += 4; 1581 newCode.putInt(readInt(b, u - 4)); 1582 for ( ; j > 0; --j) { 1583 label = v + readInt(b, u); u += 4; 1584 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1585 newCode.putInt(newOffset); 1586 } 1587 break; 1588 case ClassWriter.LOOK_INSN: 1589 v = u; 1591 u = u + 4 - (v & 3); 1592 newCode.putByte(Constants.LOOKUPSWITCH); 1594 while (newCode.length % 4 != 0) { 1595 newCode.putByte(0); 1596 } 1597 label = v + readInt(b, u); u += 4; 1598 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1599 newCode.putInt(newOffset); 1600 j = readInt(b, u); u += 4; 1601 newCode.putInt(j); 1602 for ( ; j > 0; --j) { 1603 newCode.putInt(readInt(b, u)); u += 4; 1604 label = v + readInt(b, u); u += 4; 1605 newOffset = getNewOffset(allIndexes, allSizes, v, label); 1606 newCode.putInt(newOffset); 1607 } 1608 break; 1609 case ClassWriter.WIDE_INSN: 1610 opcode = b[u + 1] & 0xFF; 1611 if (opcode == Constants.IINC) { 1612 newCode.putByteArray(b, u, 6); 1613 u += 6; 1614 } else { 1615 newCode.putByteArray(b, u, 4); 1616 u += 4; 1617 } 1618 break; 1619 case ClassWriter.VAR_INSN: 1620 case ClassWriter.SBYTE_INSN: 1621 case ClassWriter.LDC_INSN: 1622 newCode.putByteArray(b, u, 2); 1623 u += 2; 1624 break; 1625 case ClassWriter.SHORT_INSN: 1626 case ClassWriter.LDCW_INSN: 1627 case ClassWriter.FIELDORMETH_INSN: 1628 case ClassWriter.TYPE_INSN: 1629 case ClassWriter.IINC_INSN: 1630 newCode.putByteArray(b, u, 3); 1631 u += 3; 1632 break; 1633 case ClassWriter.ITFMETH_INSN: 1634 newCode.putByteArray(b, u, 5); 1635 u += 5; 1636 break; 1637 default: 1639 newCode.putByteArray(b, u, 4); 1640 u += 4; 1641 break; 1642 } 1643 } 1644 1645 if (catchTable != null) { 1648 b = catchTable.data; 1649 u = 0; 1650 while (u < catchTable.length) { 1651 writeShort(b, u, getNewOffset( 1652 allIndexes, allSizes, 0, readUnsignedShort(b, u))); 1653 writeShort(b, u + 2, getNewOffset( 1654 allIndexes, allSizes, 0, readUnsignedShort(b, u + 2))); 1655 writeShort(b, u + 4, getNewOffset( 1656 allIndexes, allSizes, 0, readUnsignedShort(b, u + 4))); 1657 u += 8; 1658 } 1659 } 1660 if (localVar != null) { 1661 b = localVar.data; 1662 u = 0; 1663 while (u < localVar.length) { 1664 label = readUnsignedShort(b, u); 1665 newOffset = getNewOffset(allIndexes, allSizes, 0, label); 1666 writeShort(b, u, newOffset); 1667 label += readUnsignedShort(b, u + 2); 1668 newOffset = getNewOffset(allIndexes, allSizes, 0, label) - newOffset; 1669 writeShort(b, u + 2, newOffset); 1670 u += 10; 1671 } 1672 } 1673 if (lineNumber != null) { 1674 b = lineNumber.data; 1675 u = 0; 1676 while (u < lineNumber.length) { 1677 writeShort(b, u, getNewOffset( 1678 allIndexes, allSizes, 0, readUnsignedShort(b, u))); 1679 u += 4; 1680 } 1681 } 1682 while (cattrs != null) { 1684 Label[] labels = cattrs.getLabels(); 1685 if (labels != null) { 1686 for (i = labels.length - 1; i >= 0; --i) { 1687 if (!labels[i].resized) { 1688 labels[i].position = 1689 getNewOffset(allIndexes, allSizes, 0, labels[i].position); 1690 labels[i].resized = true; 1691 } 1692 } 1693 } 1694 } 1695 1696 code = newCode; 1698 1699 return indexes; 1701 } 1702 1703 1710 1711 static int readUnsignedShort (final byte[] b, final int index) { 1712 return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); 1713 } 1714 1715 1722 1723 static short readShort (final byte[] b, final int index) { 1724 return (short)(((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); 1725 } 1726 1727 1734 1735 static int readInt (final byte[] b, final int index) { 1736 return ((b[index] & 0xFF) << 24) | 1737 ((b[index + 1] & 0xFF) << 16) | 1738 ((b[index + 2] & 0xFF) << 8) | 1739 (b[index + 3] & 0xFF); 1740 } 1741 1742 1749 1750 static void writeShort (final byte[] b, final int index, final int s) { 1751 b[index] = (byte)(s >>> 8); 1752 b[index + 1] = (byte)s; 1753 } 1754 1755 1777 1778 static int getNewOffset ( 1779 final int[] indexes, 1780 final int[] sizes, 1781 final int begin, 1782 final int end) 1783 { 1784 int offset = end - begin; 1785 for (int i = 0; i < indexes.length; ++i) { 1786 if (begin < indexes[i] && indexes[i] <= end) { offset += sizes[i]; 1788 } else if (end < indexes[i] && indexes[i] <= begin) { offset -= sizes[i]; 1790 } 1791 } 1792 return offset; 1793 } 1794 1795 1803 1804 public int getCodeSize () { 1805 return code.length; 1806 } 1807 1808 1817 1818 public byte[] getCode () { 1819 return code.data; 1820 } 1821} 1822 | Popular Tags |