1 30 package net.sf.retrotranslator.runtime.asm; 31 32 41 public class ClassWriter implements ClassVisitor { 42 43 46 final static int NOARG_INSN = 0; 47 48 51 final static int SBYTE_INSN = 1; 52 53 56 final static int SHORT_INSN = 2; 57 58 61 final static int VAR_INSN = 3; 62 63 66 final static int IMPLVAR_INSN = 4; 67 68 71 final static int TYPE_INSN = 5; 72 73 76 final static int FIELDORMETH_INSN = 6; 77 78 81 final static int ITFMETH_INSN = 7; 82 83 86 final static int LABEL_INSN = 8; 87 88 91 final static int LABELW_INSN = 9; 92 93 96 final static int LDC_INSN = 10; 97 98 101 final static int LDCW_INSN = 11; 102 103 106 final static int IINC_INSN = 12; 107 108 111 final static int TABL_INSN = 13; 112 113 116 final static int LOOK_INSN = 14; 117 118 121 final static int MANA_INSN = 15; 122 123 126 final static int WIDE_INSN = 16; 127 128 131 static byte[] TYPE; 132 133 136 final static int CLASS = 7; 137 138 141 final static int FIELD = 9; 142 143 146 final static int METH = 10; 147 148 151 final static int IMETH = 11; 152 153 156 final static int STR = 8; 157 158 161 final static int INT = 3; 162 163 166 final static int FLOAT = 4; 167 168 171 final static int LONG = 5; 172 173 176 final static int DOUBLE = 6; 177 178 181 final static int NAME_TYPE = 12; 182 183 186 final static int UTF8 = 1; 187 188 191 ClassReader cr; 192 193 196 int version; 197 198 201 int index; 202 203 206 ByteVector pool; 207 208 211 Item[] items; 212 213 216 int threshold; 217 218 221 Item key; 222 223 226 Item key2; 227 228 231 Item key3; 232 233 236 private int access; 237 238 241 private int name; 242 243 246 private int signature; 247 248 252 private int superName; 253 254 257 private int interfaceCount; 258 259 264 private int[] interfaces; 265 266 270 private int sourceFile; 271 272 275 private ByteVector sourceDebug; 276 277 281 private int enclosingMethodOwner; 282 283 287 private int enclosingMethod; 288 289 292 private AnnotationWriter anns; 293 294 297 private AnnotationWriter ianns; 298 299 302 private Attribute attrs; 303 304 307 private int innerClassesCount; 308 309 312 private ByteVector innerClasses; 313 314 320 FieldWriter firstField; 321 322 328 FieldWriter lastField; 329 330 336 MethodWriter firstMethod; 337 338 344 MethodWriter lastMethod; 345 346 350 private boolean computeMaxs; 351 352 356 359 static { 360 int i; 361 byte[] b = new byte[220]; 362 String s = "AAAAAAAAAAAAAAAABCKLLDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD" 363 + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 364 + "AAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIDNOAA" 365 + "AAAAGGGGGGGHAFBFAAFFAAQPIIJJIIIIIIIIIIIIIIIIII"; 366 for (i = 0; i < b.length; ++i) { 367 b[i] = (byte) (s.charAt(i) - 'A'); 368 } 369 TYPE = b; 370 371 } 438 439 443 455 public ClassWriter(final boolean computeMaxs) { 456 this(computeMaxs, false); 457 } 458 459 473 public ClassWriter( 474 final boolean computeMaxs, 475 final boolean skipUnknownAttributes) 476 { 477 index = 1; 478 pool = new ByteVector(); 479 items = new Item[256]; 480 threshold = (int) (0.75d * items.length); 481 key = new Item(); 482 key2 = new Item(); 483 key3 = new Item(); 484 this.computeMaxs = computeMaxs; 485 } 486 487 517 public ClassWriter( 518 final ClassReader classReader, 519 final boolean computeMaxs) 520 { 521 this(computeMaxs, false); 522 classReader.copyPool(this); 523 this.cr = classReader; 524 } 525 526 530 public void visit( 531 final int version, 532 final int access, 533 final String name, 534 final String signature, 535 final String superName, 536 final String [] interfaces) 537 { 538 this.version = version; 539 this.access = access; 540 this.name = newClass(name); 541 if (signature != null) { 542 this.signature = newUTF8(signature); 543 } 544 this.superName = superName == null ? 0 : newClass(superName); 545 if (interfaces != null && interfaces.length > 0) { 546 interfaceCount = interfaces.length; 547 this.interfaces = new int[interfaceCount]; 548 for (int i = 0; i < interfaceCount; ++i) { 549 this.interfaces[i] = newClass(interfaces[i]); 550 } 551 } 552 } 553 554 public void visitSource(final String file, final String debug) { 555 if (file != null) { 556 sourceFile = newUTF8(file); 557 } 558 if (debug != null) { 559 sourceDebug = new ByteVector().putUTF8(debug); 560 } 561 } 562 563 public void visitOuterClass( 564 final String owner, 565 final String name, 566 final String desc) 567 { 568 enclosingMethodOwner = newClass(owner); 569 if (name != null && desc != null) { 570 enclosingMethod = newNameType(name, desc); 571 } 572 } 573 574 public AnnotationVisitor visitAnnotation(String desc, boolean visible) { 575 ByteVector bv = new ByteVector(); 576 bv.putShort(newUTF8(desc)).putShort(0); 578 AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2); 579 if (visible) { 580 aw.next = anns; 581 anns = aw; 582 } else { 583 aw.next = ianns; 584 ianns = aw; 585 } 586 return aw; 587 } 588 589 public void visitAttribute(final Attribute attr) { 590 attr.next = attrs; 591 attrs = attr; 592 } 593 594 public void visitInnerClass( 595 final String name, 596 final String outerName, 597 final String innerName, 598 final int access) 599 { 600 if (innerClasses == null) { 601 innerClasses = new ByteVector(); 602 } 603 ++innerClassesCount; 604 innerClasses.putShort(name == null ? 0 : newClass(name)); 605 innerClasses.putShort(outerName == null ? 0 : newClass(outerName)); 606 innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName)); 607 innerClasses.putShort(access); 608 } 609 610 public FieldVisitor visitField( 611 final int access, 612 final String name, 613 final String desc, 614 final String signature, 615 final Object value) 616 { 617 return new FieldWriter(this, access, name, desc, signature, value); 618 } 619 620 public MethodVisitor visitMethod( 621 final int access, 622 final String name, 623 final String desc, 624 final String signature, 625 final String [] exceptions) 626 { 627 return new MethodWriter(this, 628 access, 629 name, 630 desc, 631 signature, 632 exceptions, 633 computeMaxs); 634 } 635 636 public void visitEnd() { 637 } 638 639 643 648 public byte[] toByteArray() { 649 return toByteArray(false); 650 } 651 652 public byte[] toByteArray(boolean dropTigerFlags) { 653 int size = 24 + 2 * interfaceCount; 655 int nbFields = 0; 656 FieldWriter fb = firstField; 657 while (fb != null) { 658 ++nbFields; 659 size += fb.getSize(); 660 fb = fb.next; 661 } 662 int nbMethods = 0; 663 MethodWriter mb = firstMethod; 664 while (mb != null) { 665 ++nbMethods; 666 size += mb.getSize(); 667 mb = mb.next; 668 } 669 int attributeCount = 0; 670 if (signature != 0) { 671 ++attributeCount; 672 size += 8; 673 newUTF8("Signature"); 674 } 675 if (sourceFile != 0) { 676 ++attributeCount; 677 size += 8; 678 newUTF8("SourceFile"); 679 } 680 if (sourceDebug != null) { 681 ++attributeCount; 682 size += sourceDebug.length + 4; 683 newUTF8("SourceDebugExtension"); 684 } 685 if (enclosingMethodOwner != 0) { 686 ++attributeCount; 687 size += 10; 688 newUTF8("EnclosingMethod"); 689 } 690 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 691 ++attributeCount; 692 size += 6; 693 newUTF8("Deprecated"); 694 } 695 if ((access & Opcodes.ACC_SYNTHETIC) != 0 696 && (version & 0xffff) < Opcodes.V1_5) 697 { 698 ++attributeCount; 699 size += 6; 700 newUTF8("Synthetic"); 701 } 702 if (version == Opcodes.V1_4) { 703 if ((access & Opcodes.ACC_ANNOTATION) != 0) { 704 ++attributeCount; 705 size += 6; 706 newUTF8("Annotation"); 707 } 708 if ((access & Opcodes.ACC_ENUM) != 0) { 709 ++attributeCount; 710 size += 6; 711 newUTF8("Enum"); 712 } 713 } 714 if (innerClasses != null) { 715 ++attributeCount; 716 size += 8 + innerClasses.length; 717 newUTF8("InnerClasses"); 718 } 719 if (anns != null) { 720 ++attributeCount; 721 size += 8 + anns.getSize(); 722 newUTF8("RuntimeVisibleAnnotations"); 723 } 724 if (ianns != null) { 725 ++attributeCount; 726 size += 8 + ianns.getSize(); 727 newUTF8("RuntimeInvisibleAnnotations"); 728 } 729 if (attrs != null) { 730 attributeCount += attrs.getCount(); 731 size += attrs.getSize(this, null, 0, -1, -1); 732 } 733 size += pool.length; 734 ByteVector out = new ByteVector(size); 737 out.putInt(0xCAFEBABE).putInt(version); 738 out.putShort(index).putByteArray(pool.data, 0, pool.length); 739 int modifiers = access; 740 if (dropTigerFlags) { 741 modifiers &= ~(Opcodes.ACC_SYNTHETIC | Opcodes.ACC_ANNOTATION | Opcodes.ACC_ENUM); 742 } 743 out.putShort(modifiers).putShort(name).putShort(superName); 744 out.putShort(interfaceCount); 745 for (int i = 0; i < interfaceCount; ++i) { 746 out.putShort(interfaces[i]); 747 } 748 out.putShort(nbFields); 749 fb = firstField; 750 while (fb != null) { 751 fb.put(out, dropTigerFlags); 752 fb = fb.next; 753 } 754 out.putShort(nbMethods); 755 mb = firstMethod; 756 while (mb != null) { 757 mb.put(out, dropTigerFlags); 758 mb = mb.next; 759 } 760 out.putShort(attributeCount); 761 if (signature != 0) { 762 out.putShort(newUTF8("Signature")).putInt(2).putShort(signature); 763 } 764 if (sourceFile != 0) { 765 out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile); 766 } 767 if (sourceDebug != null) { 768 int len = sourceDebug.length - 2; 769 out.putShort(newUTF8("SourceDebugExtension")).putInt(len); 770 out.putByteArray(sourceDebug.data, 2, len); 771 } 772 if (enclosingMethodOwner != 0) { 773 out.putShort(newUTF8("EnclosingMethod")).putInt(4); 774 out.putShort(enclosingMethodOwner).putShort(enclosingMethod); 775 } 776 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 777 out.putShort(newUTF8("Deprecated")).putInt(0); 778 } 779 if ((access & Opcodes.ACC_SYNTHETIC) != 0 780 && (version & 0xffff) < Opcodes.V1_5) 781 { 782 out.putShort(newUTF8("Synthetic")).putInt(0); 783 } 784 if (version == Opcodes.V1_4) { 785 if ((access & Opcodes.ACC_ANNOTATION) != 0) { 786 out.putShort(newUTF8("Annotation")).putInt(0); 787 } 788 if ((access & Opcodes.ACC_ENUM) != 0) { 789 out.putShort(newUTF8("Enum")).putInt(0); 790 } 791 } 792 if (innerClasses != null) { 793 out.putShort(newUTF8("InnerClasses")); 794 out.putInt(innerClasses.length + 2).putShort(innerClassesCount); 795 out.putByteArray(innerClasses.data, 0, innerClasses.length); 796 } 797 if (anns != null) { 798 out.putShort(newUTF8("RuntimeVisibleAnnotations")); 799 anns.put(out); 800 } 801 if (ianns != null) { 802 out.putShort(newUTF8("RuntimeInvisibleAnnotations")); 803 ianns.put(out); 804 } 805 if (attrs != null) { 806 attrs.put(this, null, 0, -1, -1, out); 807 } 808 return out.data; 809 } 810 811 815 825 Item newConstItem(final Object cst) { 826 if (cst instanceof Integer ) { 827 int val = ((Integer ) cst).intValue(); 828 return newInteger(val); 829 } else if (cst instanceof Byte ) { 830 int val = ((Byte ) cst).intValue(); 831 return newInteger(val); 832 } else if (cst instanceof Character ) { 833 int val = ((Character ) cst).charValue(); 834 return newInteger(val); 835 } else if (cst instanceof Short ) { 836 int val = ((Short ) cst).intValue(); 837 return newInteger(val); 838 } else if (cst instanceof Boolean ) { 839 int val = ((Boolean ) cst).booleanValue() ? 1 : 0; 840 return newInteger(val); 841 } else if (cst instanceof Float ) { 842 float val = ((Float ) cst).floatValue(); 843 return newFloat(val); 844 } else if (cst instanceof Long ) { 845 long val = ((Long ) cst).longValue(); 846 return newLong(val); 847 } else if (cst instanceof Double ) { 848 double val = ((Double ) cst).doubleValue(); 849 return newDouble(val); 850 } else if (cst instanceof String ) { 851 return newString((String ) cst); 852 } else if (cst instanceof Type) { 853 Type t = (Type) cst; 854 return newClassItem(t.getSort() == Type.OBJECT 855 ? t.getInternalName() 856 : t.getDescriptor()); 857 } else { 858 throw new IllegalArgumentException ("value " + cst); 859 } 860 } 861 862 874 public int newConst(final Object cst) { 875 return newConstItem(cst).index; 876 } 877 878 887 public int newUTF8(final String value) { 888 key.set(UTF8, value, null, null); 889 Item result = get(key); 890 if (result == null) { 891 pool.putByte(UTF8).putUTF8(value); 892 result = new Item(index++, key); 893 put(result); 894 } 895 return result.index; 896 } 897 898 907 public int newClass(final String value) { 908 return newClassItem(value).index; 909 } 910 911 920 private Item newClassItem(final String value) { 921 key2.set(CLASS, value, null, null); 922 Item result = get(key2); 923 if (result == null) { 924 pool.put12(CLASS, newUTF8(value)); 925 result = new Item(index++, key2); 926 put(result); 927 } 928 return result; 929 } 930 931 942 public int newField(final String owner, final String name, final String desc) 943 { 944 key3.set(FIELD, owner, name, desc); 945 Item result = get(key3); 946 if (result == null) { 947 put122(FIELD, newClass(owner), newNameType(name, desc)); 948 result = new Item(index++, key3); 949 put(result); 950 } 951 return result.index; 952 } 953 954 964 Item newMethodItem( 965 final String owner, 966 final String name, 967 final String desc, 968 final boolean itf) 969 { 970 int type = itf ? IMETH : METH; 971 key3.set(type, owner, name, desc); 972 Item result = get(key3); 973 if (result == null) { 974 put122(type, newClass(owner), newNameType(name, desc)); 975 result = new Item(index++, key3); 976 put(result); 977 } 978 return result; 979 } 980 981 993 public int newMethod( 994 final String owner, 995 final String name, 996 final String desc, 997 final boolean itf) 998 { 999 return newMethodItem(owner, name, desc, itf).index; 1000 } 1001 1002 1009 Item newInteger(final int value) { 1010 key.set(value); 1011 Item result = get(key); 1012 if (result == null) { 1013 pool.putByte(INT).putInt(value); 1014 result = new Item(index++, key); 1015 put(result); 1016 } 1017 return result; 1018 } 1019 1020 1027 Item newFloat(final float value) { 1028 key.set(value); 1029 Item result = get(key); 1030 if (result == null) { 1031 pool.putByte(FLOAT).putInt(Float.floatToIntBits(value)); 1032 result = new Item(index++, key); 1033 put(result); 1034 } 1035 return result; 1036 } 1037 1038 1045 Item newLong(final long value) { 1046 key.set(value); 1047 Item result = get(key); 1048 if (result == null) { 1049 pool.putByte(LONG).putLong(value); 1050 result = new Item(index, key); 1051 put(result); 1052 index += 2; 1053 } 1054 return result; 1055 } 1056 1057 1064 Item newDouble(final double value) { 1065 key.set(value); 1066 Item result = get(key); 1067 if (result == null) { 1068 pool.putByte(DOUBLE).putLong(Double.doubleToLongBits(value)); 1069 result = new Item(index, key); 1070 put(result); 1071 index += 2; 1072 } 1073 return result; 1074 } 1075 1076 1083 private Item newString(final String value) { 1084 key2.set(STR, value, null, null); 1085 Item result = get(key2); 1086 if (result == null) { 1087 pool.put12(STR, newUTF8(value)); 1088 result = new Item(index++, key2); 1089 put(result); 1090 } 1091 return result; 1092 } 1093 1094 1104 public int newNameType(final String name, final String desc) { 1105 key2.set(NAME_TYPE, name, desc, null); 1106 Item result = get(key2); 1107 if (result == null) { 1108 put122(NAME_TYPE, newUTF8(name), newUTF8(desc)); 1109 result = new Item(index++, key2); 1110 put(result); 1111 } 1112 return result.index; 1113 } 1114 1115 1123 private Item get(final Item key) { 1124 Item i = items[key.hashCode % items.length]; 1125 while (i != null && !key.isEqualTo(i)) { 1126 i = i.next; 1127 } 1128 return i; 1129 } 1130 1131 1137 private void put(final Item i) { 1138 if (index > threshold) { 1139 int ll = items.length; 1140 int nl = ll * 2 + 1; 1141 Item[] newItems = new Item[nl]; 1142 for (int l = ll - 1; l >= 0; --l) { 1143 Item j = items[l]; 1144 while (j != null) { 1145 int index = j.hashCode % newItems.length; 1146 Item k = j.next; 1147 j.next = newItems[index]; 1148 newItems[index] = j; 1149 j = k; 1150 } 1151 } 1152 items = newItems; 1153 threshold = (int) (nl * 0.75); 1154 } 1155 int index = i.hashCode % items.length; 1156 i.next = items[index]; 1157 items[index] = i; 1158 } 1159 1160 1167 private void put122(final int b, final int s1, final int s2) { 1168 pool.put12(b, s1).putShort(s2); 1169 } 1170} 1171 | Popular Tags |