< prev index next >

src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java

Print this page
rev 47452 : imported patch jdk-new-asmv6.patch


  56  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  57  * THE POSSIBILITY OF SUCH DAMAGE.
  58  */
  59 package jdk.internal.org.objectweb.asm;
  60 
  61 import java.io.IOException;
  62 import java.io.InputStream;
  63 
  64 /**
  65  * A Java class parser to make a {@link ClassVisitor} visit an existing class.
  66  * This class parses a byte array conforming to the Java class file format and
  67  * calls the appropriate visit methods of a given class visitor for each field,
  68  * method and bytecode instruction encountered.
  69  *
  70  * @author Eric Bruneton
  71  * @author Eugene Kuleshov
  72  */
  73 public class ClassReader {
  74 
  75     /**
  76      * True to enable signatures support.
  77      */
  78     static final boolean SIGNATURES = true;
  79 
  80     /**
  81      * True to enable annotations support.
  82      */
  83     static final boolean ANNOTATIONS = true;
  84 
  85     /**
  86      * True to enable stack map frames support.
  87      */
  88     static final boolean FRAMES = true;
  89 
  90     /**
  91      * True to enable bytecode writing support.
  92      */
  93     static final boolean WRITER = true;
  94 
  95     /**
  96      * True to enable JSR_W and GOTO_W support.
  97      */
  98     static final boolean RESIZE = true;
  99 
 100     /**
 101      * Flag to skip method code. If this class is set <code>CODE</code>
 102      * attribute won't be visited. This can be used, for example, to retrieve
 103      * annotations for methods and method parameters.
 104      */
 105     public static final int SKIP_CODE = 1;
 106 
 107     /**
 108      * Flag to skip the debug information in the class. If this flag is set the
 109      * debug information of the class is not visited, i.e. the
 110      * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
 111      * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be
 112      * called.
 113      */
 114     public static final int SKIP_DEBUG = 2;
 115 
 116     /**
 117      * Flag to skip the stack map frames in the class. If this flag is set the
 118      * stack map frames of the class is not visited, i.e. the
 119      * {@link MethodVisitor#visitFrame visitFrame} method will not be called.
 120      * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is
 121      * used: it avoids visiting frames that will be ignored and recomputed from
 122      * scratch in the class writer.
 123      */
 124     public static final int SKIP_FRAMES = 4;
 125 
 126     /**
 127      * Flag to expand the stack map frames. By default stack map frames are
 128      * visited in their original format (i.e. "expanded" for classes whose
 129      * version is less than V1_6, and "compressed" for the other classes). If
 130      * this flag is set, stack map frames are always visited in expanded format
 131      * (this option adds a decompression/recompression step in ClassReader and
 132      * ClassWriter which degrades performances quite a lot).
 133      */
 134     public static final int EXPAND_FRAMES = 8;
 135 
 136     /**















 137      * The class to be parsed. <i>The content of this array must not be
 138      * modified. This field is intended for {@link Attribute} sub classes, and
 139      * is normally not needed by class generators or adapters.</i>
 140      */
 141     public final byte[] b;
 142 
 143     /**
 144      * The start index of each constant pool item in {@link #b b}, plus one. The
 145      * one byte offset skips the constant pool item tag that indicates its type.
 146      */
 147     private final int[] items;
 148 
 149     /**
 150      * The String objects corresponding to the CONSTANT_Utf8 items. This cache
 151      * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
 152      * which GREATLY improves performances (by a factor 2 to 3). This caching
 153      * strategy could be extended to all constant pool items, but its benefit
 154      * would not be so great for these items (because they are much less
 155      * expensive to parse than CONSTANT_Utf8 items).
 156      */


 178      * @param b
 179      *            the bytecode of the class to be read.
 180      */
 181     public ClassReader(final byte[] b) {
 182         this(b, 0, b.length);
 183     }
 184 
 185     /**
 186      * Constructs a new {@link ClassReader} object.
 187      *
 188      * @param b
 189      *            the bytecode of the class to be read.
 190      * @param off
 191      *            the start offset of the class data.
 192      * @param len
 193      *            the length of the class data.
 194      */
 195     public ClassReader(final byte[] b, final int off, final int len) {
 196         this.b = b;
 197         // checks the class version
 198         if (readShort(off + 6) > Opcodes.V1_9) {
 199             throw new IllegalArgumentException();
 200         }
 201         // parses the constant pool
 202         items = new int[readUnsignedShort(off + 8)];
 203         int n = items.length;
 204         strings = new String[n];
 205         int max = 0;
 206         int index = off + 10;
 207         for (int i = 1; i < n; ++i) {
 208             items[i] = index + 1;
 209             int size;
 210             switch (b[index]) {
 211             case ClassWriter.FIELD:
 212             case ClassWriter.METH:
 213             case ClassWriter.IMETH:
 214             case ClassWriter.INT:
 215             case ClassWriter.FLOAT:
 216             case ClassWriter.NAME_TYPE:
 217             case ClassWriter.INDY:
 218                 size = 5;
 219                 break;
 220             case ClassWriter.LONG:
 221             case ClassWriter.DOUBLE:
 222                 size = 9;
 223                 ++i;
 224                 break;
 225             case ClassWriter.UTF8:
 226                 size = 3 + readUnsignedShort(index + 1);
 227                 if (size > max) {
 228                     max = size;
 229                 }
 230                 break;
 231             case ClassWriter.HANDLE:
 232                 size = 4;
 233                 break;
 234             // case ClassWriter.CLASS:
 235             // case ClassWriter.STR:
 236             // case ClassWriter.MTYPE


 237             default:
 238                 size = 3;
 239                 break;
 240             }
 241             index += size;
 242         }
 243         maxStringLength = max;
 244         // the class header information starts just after the constant pool
 245         header = index;
 246     }
 247 
 248     /**
 249      * Returns the class's access flags (see {@link Opcodes}). This value may
 250      * not reflect Deprecated and Synthetic flags when bytecode is before 1.5
 251      * and those flags are represented by attributes.
 252      *
 253      * @return the class access flags
 254      *
 255      * @see ClassVisitor#visit(int, int, String, String, String, String[])
 256      */


 360                 break;
 361             }
 362             case ClassWriter.HANDLE: {
 363                 int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
 364                 nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
 365                 item.set(ClassWriter.HANDLE_BASE + readByte(index),
 366                         readClass(fieldOrMethodRef, buf),
 367                         readUTF8(nameType, buf), readUTF8(nameType + 2, buf));
 368                 break;
 369             }
 370             case ClassWriter.INDY:
 371                 if (classWriter.bootstrapMethods == null) {
 372                     copyBootstrapMethods(classWriter, items2, buf);
 373                 }
 374                 nameType = items[readUnsignedShort(index + 2)];
 375                 item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf),
 376                         readUnsignedShort(index));
 377                 break;
 378             // case ClassWriter.STR:
 379             // case ClassWriter.CLASS:
 380             // case ClassWriter.MTYPE


 381             default:
 382                 item.set(tag, readUTF8(index, buf), null, null);
 383                 break;
 384             }
 385 
 386             int index2 = item.hashCode % items2.length;
 387             item.next = items2[index2];
 388             items2[index2] = item;
 389         }
 390 
 391         int off = items[1] - 1;
 392         classWriter.pool.putByteArray(b, off, header - off);
 393         classWriter.items = items2;
 394         classWriter.threshold = (int) (0.75d * ll);
 395         classWriter.index = ll;
 396     }
 397 
 398     /**
 399      * Copies the bootstrap method data into the given {@link ClassWriter}.
 400      * Should be called before the {@link #accept(ClassVisitor,int)} method.


 567         context.buffer = c;
 568 
 569         // reads the class declaration
 570         int access = readUnsignedShort(u);
 571         String name = readClass(u + 2, c);
 572         String superClass = readClass(u + 4, c);
 573         String[] interfaces = new String[readUnsignedShort(u + 6)];
 574         u += 8;
 575         for (int i = 0; i < interfaces.length; ++i) {
 576             interfaces[i] = readClass(u, c);
 577             u += 2;
 578         }
 579 
 580         // reads the class attributes
 581         String signature = null;
 582         String sourceFile = null;
 583         String sourceDebug = null;
 584         String enclosingOwner = null;
 585         String enclosingName = null;
 586         String enclosingDesc = null;

 587         int anns = 0;
 588         int ianns = 0;
 589         int tanns = 0;
 590         int itanns = 0;
 591         int innerClasses = 0;


 592         Attribute attributes = null;
 593 
 594         u = getAttributes();
 595         for (int i = readUnsignedShort(u); i > 0; --i) {
 596             String attrName = readUTF8(u + 2, c);
 597             // tests are sorted in decreasing frequency order
 598             // (based on frequencies observed on typical classes)
 599             if ("SourceFile".equals(attrName)) {
 600                 sourceFile = readUTF8(u + 8, c);
 601             } else if ("InnerClasses".equals(attrName)) {
 602                 innerClasses = u + 8;
 603             } else if ("EnclosingMethod".equals(attrName)) {
 604                 enclosingOwner = readClass(u + 8, c);
 605                 int item = readUnsignedShort(u + 10);
 606                 if (item != 0) {
 607                     enclosingName = readUTF8(items[item], c);
 608                     enclosingDesc = readUTF8(items[item] + 2, c);
 609                 }
 610             } else if (SIGNATURES && "Signature".equals(attrName)) {
 611                 signature = readUTF8(u + 8, c);
 612             } else if (ANNOTATIONS
 613                     && "RuntimeVisibleAnnotations".equals(attrName)) {
 614                 anns = u + 8;
 615             } else if (ANNOTATIONS
 616                     && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
 617                 tanns = u + 8;
 618             } else if ("Deprecated".equals(attrName)) {
 619                 access |= Opcodes.ACC_DEPRECATED;
 620             } else if ("Synthetic".equals(attrName)) {
 621                 access |= Opcodes.ACC_SYNTHETIC
 622                         | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
 623             } else if ("SourceDebugExtension".equals(attrName)) {
 624                 int len = readInt(u + 4);
 625                 sourceDebug = readUTF(u + 8, len, new char[len]);
 626             } else if (ANNOTATIONS
 627                     && "RuntimeInvisibleAnnotations".equals(attrName)) {
 628                 ianns = u + 8;
 629             } else if (ANNOTATIONS
 630                     && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
 631                 itanns = u + 8;






 632             } else if ("BootstrapMethods".equals(attrName)) {
 633                 int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
 634                 for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
 635                     bootstrapMethods[j] = v;
 636                     v += 2 + readUnsignedShort(v + 2) << 1;
 637                 }
 638                 context.bootstrapMethods = bootstrapMethods;
 639             } else {
 640                 Attribute attr = readAttribute(attrs, attrName, u + 8,
 641                         readInt(u + 4), c, -1, null);
 642                 if (attr != null) {
 643                     attr.next = attributes;
 644                     attributes = attr;
 645                 }
 646             }
 647             u += 6 + readInt(u + 4);
 648         }
 649 
 650         // visits the class declaration
 651         classVisitor.visit(readInt(items[1] - 7), access, name, signature,
 652                 superClass, interfaces);
 653 
 654         // visits the source and debug info
 655         if ((flags & SKIP_DEBUG) == 0
 656                 && (sourceFile != null || sourceDebug != null)) {
 657             classVisitor.visitSource(sourceFile, sourceDebug);
 658         }
 659 






 660         // visits the outer class
 661         if (enclosingOwner != null) {
 662             classVisitor.visitOuterClass(enclosingOwner, enclosingName,
 663                     enclosingDesc);
 664         }
 665 
 666         // visits the class annotations and type annotations
 667         if (ANNOTATIONS && anns != 0) {
 668             for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
 669                 v = readAnnotationValues(v + 2, c, true,
 670                         classVisitor.visitAnnotation(readUTF8(v, c), true));
 671             }
 672         }
 673         if (ANNOTATIONS && ianns != 0) {
 674             for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
 675                 v = readAnnotationValues(v + 2, c, true,
 676                         classVisitor.visitAnnotation(readUTF8(v, c), false));
 677             }
 678         }
 679         if (ANNOTATIONS && tanns != 0) {
 680             for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
 681                 v = readAnnotationTarget(context, v);
 682                 v = readAnnotationValues(v + 2, c, true,
 683                         classVisitor.visitTypeAnnotation(context.typeRef,
 684                                 context.typePath, readUTF8(v, c), true));
 685             }
 686         }
 687         if (ANNOTATIONS && itanns != 0) {
 688             for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
 689                 v = readAnnotationTarget(context, v);
 690                 v = readAnnotationValues(v + 2, c, true,
 691                         classVisitor.visitTypeAnnotation(context.typeRef,
 692                                 context.typePath, readUTF8(v, c), false));
 693             }
 694         }
 695 
 696         // visits the attributes
 697         while (attributes != null) {
 698             Attribute attr = attributes.next;
 699             attributes.next = null;
 700             classVisitor.visitAttribute(attributes);
 701             attributes = attr;
 702         }
 703 
 704         // visits the inner classes
 705         if (innerClasses != 0) {
 706             int v = innerClasses + 2;
 707             for (int i = readUnsignedShort(innerClasses); i > 0; --i) {


 710                         readUnsignedShort(v + 6));
 711                 v += 8;
 712             }
 713         }
 714 
 715         // visits the fields and methods
 716         u = header + 10 + 2 * interfaces.length;
 717         for (int i = readUnsignedShort(u - 2); i > 0; --i) {
 718             u = readField(classVisitor, context, u);
 719         }
 720         u += 2;
 721         for (int i = readUnsignedShort(u - 2); i > 0; --i) {
 722             u = readMethod(classVisitor, context, u);
 723         }
 724 
 725         // visits the end of the class
 726         classVisitor.visitEnd();
 727     }
 728 
 729     /**


















































































































 730      * Reads a field and makes the given visitor visit it.
 731      *
 732      * @param classVisitor
 733      *            the visitor that must visit the field.
 734      * @param context
 735      *            information about the class being parsed.
 736      * @param u
 737      *            the start offset of the field in the class file.
 738      * @return the offset of the first byte following the field in the class.
 739      */
 740     private int readField(final ClassVisitor classVisitor,
 741             final Context context, int u) {
 742         // reads the field declaration
 743         char[] c = context.buffer;
 744         int access = readUnsignedShort(u);
 745         String name = readUTF8(u + 2, c);
 746         String desc = readUTF8(u + 4, c);
 747         u += 6;
 748 
 749         // reads the field attributes
 750         String signature = null;
 751         int anns = 0;
 752         int ianns = 0;
 753         int tanns = 0;
 754         int itanns = 0;
 755         Object value = null;
 756         Attribute attributes = null;
 757 
 758         for (int i = readUnsignedShort(u); i > 0; --i) {
 759             String attrName = readUTF8(u + 2, c);
 760             // tests are sorted in decreasing frequency order
 761             // (based on frequencies observed on typical classes)
 762             if ("ConstantValue".equals(attrName)) {
 763                 int item = readUnsignedShort(u + 8);
 764                 value = item == 0 ? null : readConst(item, c);
 765             } else if (SIGNATURES && "Signature".equals(attrName)) {
 766                 signature = readUTF8(u + 8, c);
 767             } else if ("Deprecated".equals(attrName)) {
 768                 access |= Opcodes.ACC_DEPRECATED;
 769             } else if ("Synthetic".equals(attrName)) {
 770                 access |= Opcodes.ACC_SYNTHETIC
 771                         | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
 772             } else if (ANNOTATIONS
 773                     && "RuntimeVisibleAnnotations".equals(attrName)) {
 774                 anns = u + 8;
 775             } else if (ANNOTATIONS
 776                     && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
 777                 tanns = u + 8;
 778             } else if (ANNOTATIONS
 779                     && "RuntimeInvisibleAnnotations".equals(attrName)) {
 780                 ianns = u + 8;
 781             } else if (ANNOTATIONS
 782                     && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
 783                 itanns = u + 8;
 784             } else {
 785                 Attribute attr = readAttribute(context.attrs, attrName, u + 8,
 786                         readInt(u + 4), c, -1, null);
 787                 if (attr != null) {
 788                     attr.next = attributes;
 789                     attributes = attr;
 790                 }
 791             }
 792             u += 6 + readInt(u + 4);
 793         }
 794         u += 2;
 795 
 796         // visits the field declaration
 797         FieldVisitor fv = classVisitor.visitField(access, name, desc,
 798                 signature, value);
 799         if (fv == null) {
 800             return u;
 801         }
 802 
 803         // visits the field annotations and type annotations
 804         if (ANNOTATIONS && anns != 0) {
 805             for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
 806                 v = readAnnotationValues(v + 2, c, true,
 807                         fv.visitAnnotation(readUTF8(v, c), true));
 808             }
 809         }
 810         if (ANNOTATIONS && ianns != 0) {
 811             for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
 812                 v = readAnnotationValues(v + 2, c, true,
 813                         fv.visitAnnotation(readUTF8(v, c), false));
 814             }
 815         }
 816         if (ANNOTATIONS && tanns != 0) {
 817             for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
 818                 v = readAnnotationTarget(context, v);
 819                 v = readAnnotationValues(v + 2, c, true,
 820                         fv.visitTypeAnnotation(context.typeRef,
 821                                 context.typePath, readUTF8(v, c), true));
 822             }
 823         }
 824         if (ANNOTATIONS && itanns != 0) {
 825             for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
 826                 v = readAnnotationTarget(context, v);
 827                 v = readAnnotationValues(v + 2, c, true,
 828                         fv.visitTypeAnnotation(context.typeRef,
 829                                 context.typePath, readUTF8(v, c), false));
 830             }
 831         }
 832 
 833         // visits the field attributes
 834         while (attributes != null) {
 835             Attribute attr = attributes.next;
 836             attributes.next = null;
 837             fv.visitAttribute(attributes);
 838             attributes = attr;
 839         }
 840 
 841         // visits the end of the field
 842         fv.visitEnd();
 843 
 844         return u;


 878         int mpanns = 0;
 879         int impanns = 0;
 880         int firstAttribute = u;
 881         Attribute attributes = null;
 882 
 883         for (int i = readUnsignedShort(u); i > 0; --i) {
 884             String attrName = readUTF8(u + 2, c);
 885             // tests are sorted in decreasing frequency order
 886             // (based on frequencies observed on typical classes)
 887             if ("Code".equals(attrName)) {
 888                 if ((context.flags & SKIP_CODE) == 0) {
 889                     code = u + 8;
 890                 }
 891             } else if ("Exceptions".equals(attrName)) {
 892                 exceptions = new String[readUnsignedShort(u + 8)];
 893                 exception = u + 10;
 894                 for (int j = 0; j < exceptions.length; ++j) {
 895                     exceptions[j] = readClass(exception, c);
 896                     exception += 2;
 897                 }
 898             } else if (SIGNATURES && "Signature".equals(attrName)) {
 899                 signature = readUTF8(u + 8, c);
 900             } else if ("Deprecated".equals(attrName)) {
 901                 context.access |= Opcodes.ACC_DEPRECATED;
 902             } else if (ANNOTATIONS
 903                     && "RuntimeVisibleAnnotations".equals(attrName)) {
 904                 anns = u + 8;
 905             } else if (ANNOTATIONS
 906                     && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
 907                 tanns = u + 8;
 908             } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
 909                 dann = u + 8;
 910             } else if ("Synthetic".equals(attrName)) {
 911                 context.access |= Opcodes.ACC_SYNTHETIC
 912                         | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
 913             } else if (ANNOTATIONS
 914                     && "RuntimeInvisibleAnnotations".equals(attrName)) {
 915                 ianns = u + 8;
 916             } else if (ANNOTATIONS
 917                     && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
 918                 itanns = u + 8;
 919             } else if (ANNOTATIONS
 920                     && "RuntimeVisibleParameterAnnotations".equals(attrName)) {
 921                 mpanns = u + 8;
 922             } else if (ANNOTATIONS
 923                     && "RuntimeInvisibleParameterAnnotations".equals(attrName)) {
 924                 impanns = u + 8;
 925             } else if ("MethodParameters".equals(attrName)) {
 926                 methodParameters = u + 8;
 927             } else {
 928                 Attribute attr = readAttribute(context.attrs, attrName, u + 8,
 929                         readInt(u + 4), c, -1, null);
 930                 if (attr != null) {
 931                     attr.next = attributes;
 932                     attributes = attr;
 933                 }
 934             }
 935             u += 6 + readInt(u + 4);
 936         }
 937         u += 2;
 938 
 939         // visits the method declaration
 940         MethodVisitor mv = classVisitor.visitMethod(context.access,
 941                 context.name, context.desc, signature, exceptions);
 942         if (mv == null) {
 943             return u;
 944         }
 945 
 946         /*
 947          * if the returned MethodVisitor is in fact a MethodWriter, it means
 948          * there is no method adapter between the reader and the writer. If, in
 949          * addition, the writer's constant pool was copied from this reader
 950          * (mw.cw.cr == this), and the signature and exceptions of the method
 951          * have not been changed, then it is possible to skip all visit events
 952          * and just copy the original code of the method to the writer (the
 953          * access, name and descriptor can have been changed, this is not
 954          * important since they are not copied as is from the reader).
 955          */
 956         if (WRITER && mv instanceof MethodWriter) {
 957             MethodWriter mw = (MethodWriter) mv;
 958             if (mw.cw.cr == this && signature == mw.signature) {
 959                 boolean sameExceptions = false;
 960                 if (exceptions == null) {
 961                     sameExceptions = mw.exceptionCount == 0;
 962                 } else if (exceptions.length == mw.exceptionCount) {
 963                     sameExceptions = true;
 964                     for (int j = exceptions.length - 1; j >= 0; --j) {
 965                         exception -= 2;
 966                         if (mw.exceptions[j] != readUnsignedShort(exception)) {
 967                             sameExceptions = false;
 968                             break;
 969                         }
 970                     }
 971                 }
 972                 if (sameExceptions) {
 973                     /*
 974                      * we do not copy directly the code into MethodWriter to
 975                      * save a byte array copy operation. The real copy will be
 976                      * done in ClassWriter.toByteArray().
 977                      */
 978                     mw.classReaderOffset = firstAttribute;
 979                     mw.classReaderLength = u - firstAttribute;
 980                     return u;
 981                 }
 982             }
 983         }
 984 
 985         // visit the method parameters
 986         if (methodParameters != 0) {
 987             for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) {
 988                 mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2));
 989             }
 990         }
 991 
 992         // visits the method annotations
 993         if (ANNOTATIONS && dann != 0) {
 994             AnnotationVisitor dv = mv.visitAnnotationDefault();
 995             readAnnotationValue(dann, c, null, dv);
 996             if (dv != null) {
 997                 dv.visitEnd();
 998             }
 999         }
1000         if (ANNOTATIONS && anns != 0) {
1001             for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
1002                 v = readAnnotationValues(v + 2, c, true,
1003                         mv.visitAnnotation(readUTF8(v, c), true));
1004             }
1005         }
1006         if (ANNOTATIONS && ianns != 0) {
1007             for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
1008                 v = readAnnotationValues(v + 2, c, true,
1009                         mv.visitAnnotation(readUTF8(v, c), false));
1010             }
1011         }
1012         if (ANNOTATIONS && tanns != 0) {
1013             for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
1014                 v = readAnnotationTarget(context, v);
1015                 v = readAnnotationValues(v + 2, c, true,
1016                         mv.visitTypeAnnotation(context.typeRef,
1017                                 context.typePath, readUTF8(v, c), true));
1018             }
1019         }
1020         if (ANNOTATIONS && itanns != 0) {
1021             for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
1022                 v = readAnnotationTarget(context, v);
1023                 v = readAnnotationValues(v + 2, c, true,
1024                         mv.visitTypeAnnotation(context.typeRef,
1025                                 context.typePath, readUTF8(v, c), false));
1026             }
1027         }
1028         if (ANNOTATIONS && mpanns != 0) {
1029             readParameterAnnotations(mv, context, mpanns, true);
1030         }
1031         if (ANNOTATIONS && impanns != 0) {
1032             readParameterAnnotations(mv, context, impanns, false);
1033         }
1034 
1035         // visits the method attributes
1036         while (attributes != null) {
1037             Attribute attr = attributes.next;
1038             attributes.next = null;
1039             mv.visitAttribute(attributes);
1040             attributes = attr;
1041         }
1042 
1043         // visits the method code
1044         if (code != 0) {
1045             mv.visitCode();
1046             readCode(mv, context, code);
1047         }
1048 
1049         // visits the end of the method
1050         mv.visitEnd();
1051 


1058      * @param mv
1059      *            the visitor that must visit the method's code.
1060      * @param context
1061      *            information about the class being parsed.
1062      * @param u
1063      *            the start offset of the code attribute in the class file.
1064      */
1065     private void readCode(final MethodVisitor mv, final Context context, int u) {
1066         // reads the header
1067         byte[] b = this.b;
1068         char[] c = context.buffer;
1069         int maxStack = readUnsignedShort(u);
1070         int maxLocals = readUnsignedShort(u + 2);
1071         int codeLength = readInt(u + 4);
1072         u += 8;
1073 
1074         // reads the bytecode to find the labels
1075         int codeStart = u;
1076         int codeEnd = u + codeLength;
1077         Label[] labels = context.labels = new Label[codeLength + 2];
1078         readLabel(codeLength + 1, labels);
1079         while (u < codeEnd) {
1080             int offset = u - codeStart;
1081             int opcode = b[u] & 0xFF;
1082             switch (ClassWriter.TYPE[opcode]) {
1083             case ClassWriter.NOARG_INSN:
1084             case ClassWriter.IMPLVAR_INSN:
1085                 u += 1;
1086                 break;
1087             case ClassWriter.LABEL_INSN:
1088                 readLabel(offset + readShort(u + 1), labels);
1089                 u += 3;
1090                 break;




1091             case ClassWriter.LABELW_INSN:
1092                 readLabel(offset + readInt(u + 1), labels);

1093                 u += 5;
1094                 break;
1095             case ClassWriter.WIDE_INSN:
1096                 opcode = b[u + 1] & 0xFF;
1097                 if (opcode == Opcodes.IINC) {
1098                     u += 6;
1099                 } else {
1100                     u += 4;
1101                 }
1102                 break;
1103             case ClassWriter.TABL_INSN:
1104                 // skips 0 to 3 padding bytes
1105                 u = u + 4 - (offset & 3);
1106                 // reads instruction
1107                 readLabel(offset + readInt(u), labels);
1108                 for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) {
1109                     readLabel(offset + readInt(u + 12), labels);
1110                     u += 4;
1111                 }
1112                 u += 12;
1113                 break;
1114             case ClassWriter.LOOK_INSN:
1115                 // skips 0 to 3 padding bytes
1116                 u = u + 4 - (offset & 3);
1117                 // reads instruction
1118                 readLabel(offset + readInt(u), labels);
1119                 for (int i = readInt(u + 4); i > 0; --i) {
1120                     readLabel(offset + readInt(u + 12), labels);
1121                     u += 8;
1122                 }
1123                 u += 8;
1124                 break;
1125             case ClassWriter.VAR_INSN:
1126             case ClassWriter.SBYTE_INSN:
1127             case ClassWriter.LDC_INSN:
1128                 u += 2;
1129                 break;
1130             case ClassWriter.SHORT_INSN:
1131             case ClassWriter.LDCW_INSN:
1132             case ClassWriter.FIELDORMETH_INSN:
1133             case ClassWriter.TYPE_INSN:
1134             case ClassWriter.IINC_INSN:
1135                 u += 3;
1136                 break;
1137             case ClassWriter.ITFMETH_INSN:
1138             case ClassWriter.INDYMETH_INSN:
1139                 u += 5;
1140                 break;
1141             // case MANA_INSN:
1142             default:
1143                 u += 4;
1144                 break;
1145             }
1146         }
1147 
1148         // reads the try catch entries to find the labels, and also visits them
1149         for (int i = readUnsignedShort(u); i > 0; --i) {
1150             Label start = readLabel(readUnsignedShort(u + 2), labels);
1151             Label end = readLabel(readUnsignedShort(u + 4), labels);
1152             Label handler = readLabel(readUnsignedShort(u + 6), labels);
1153             String type = readUTF8(items[readUnsignedShort(u + 8)], c);
1154             mv.visitTryCatchBlock(start, end, handler, type);
1155             u += 8;
1156         }
1157         u += 2;
1158 
1159         // reads the code attributes
1160         int[] tanns = null; // start index of each visible type annotation
1161         int[] itanns = null; // start index of each invisible type annotation
1162         int tann = 0; // current index in tanns array
1163         int itann = 0; // current index in itanns array
1164         int ntoff = -1; // next visible type annotation code offset
1165         int nitoff = -1; // next invisible type annotation code offset
1166         int varTable = 0;
1167         int varTypeTable = 0;
1168         boolean zip = true;
1169         boolean unzip = (context.flags & EXPAND_FRAMES) != 0;
1170         int stackMap = 0;
1171         int stackMapSize = 0;
1172         int frameCount = 0;
1173         Context frame = null;
1174         Attribute attributes = null;
1175 
1176         for (int i = readUnsignedShort(u); i > 0; --i) {
1177             String attrName = readUTF8(u + 2, c);
1178             if ("LocalVariableTable".equals(attrName)) {
1179                 if ((context.flags & SKIP_DEBUG) == 0) {
1180                     varTable = u + 8;
1181                     for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
1182                         int label = readUnsignedShort(v + 10);
1183                         if (labels[label] == null) {
1184                             readLabel(label, labels).status |= Label.DEBUG;
1185                         }
1186                         label += readUnsignedShort(v + 12);
1187                         if (labels[label] == null) {
1188                             readLabel(label, labels).status |= Label.DEBUG;
1189                         }
1190                         v += 10;
1191                     }
1192                 }
1193             } else if ("LocalVariableTypeTable".equals(attrName)) {
1194                 varTypeTable = u + 8;
1195             } else if ("LineNumberTable".equals(attrName)) {
1196                 if ((context.flags & SKIP_DEBUG) == 0) {
1197                     for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
1198                         int label = readUnsignedShort(v + 10);
1199                         if (labels[label] == null) {
1200                             readLabel(label, labels).status |= Label.DEBUG;
1201                         }
1202                         Label l = labels[label];
1203                         while (l.line > 0) {
1204                             if (l.next == null) {
1205                                 l.next = new Label();
1206                             }
1207                             l = l.next;
1208                         }
1209                         l.line = readUnsignedShort(v + 12);
1210                         v += 4;
1211                     }
1212                 }
1213             } else if (ANNOTATIONS
1214                     && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
1215                 tanns = readTypeAnnotations(mv, context, u + 8, true);
1216                 ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1
1217                         : readUnsignedShort(tanns[0] + 1);
1218             } else if (ANNOTATIONS
1219                     && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
1220                 itanns = readTypeAnnotations(mv, context, u + 8, false);
1221                 nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1
1222                         : readUnsignedShort(itanns[0] + 1);
1223             } else if (FRAMES && "StackMapTable".equals(attrName)) {
1224                 if ((context.flags & SKIP_FRAMES) == 0) {
1225                     stackMap = u + 10;
1226                     stackMapSize = readInt(u + 4);
1227                     frameCount = readUnsignedShort(u + 8);
1228                 }
1229                 /*
1230                  * here we do not extract the labels corresponding to the
1231                  * attribute content. This would require a full parsing of the
1232                  * attribute, which would need to be repeated in the second
1233                  * phase (see below). Instead the content of the attribute is
1234                  * read one frame at a time (i.e. after a frame has been
1235                  * visited, the next frame is read), and the labels it contains
1236                  * are also extracted one frame at a time. Thanks to the
1237                  * ordering of frames, having only a "one frame lookahead" is
1238                  * not a problem, i.e. it is not possible to see an offset
1239                  * smaller than the offset of the current insn and for which no
1240                  * Label exist.
1241                  */
1242                 /*
1243                  * This is not true for UNINITIALIZED type offsets. We solve
1244                  * this by parsing the stack map table without a full decoding
1245                  * (see below).
1246                  */
1247             } else if (FRAMES && "StackMap".equals(attrName)) {
1248                 if ((context.flags & SKIP_FRAMES) == 0) {
1249                     zip = false;
1250                     stackMap = u + 10;
1251                     stackMapSize = readInt(u + 4);
1252                     frameCount = readUnsignedShort(u + 8);
1253                 }
1254                 /*
1255                  * IMPORTANT! here we assume that the frames are ordered, as in
1256                  * the StackMapTable attribute, although this is not guaranteed
1257                  * by the attribute format.
1258                  */
1259             } else {
1260                 for (int j = 0; j < context.attrs.length; ++j) {
1261                     if (context.attrs[j].type.equals(attrName)) {
1262                         Attribute attr = context.attrs[j].read(this, u + 8,
1263                                 readInt(u + 4), c, codeStart - 8, labels);
1264                         if (attr != null) {
1265                             attr.next = attributes;
1266                             attributes = attr;
1267                         }
1268                     }
1269                 }
1270             }
1271             u += 6 + readInt(u + 4);
1272         }
1273         u += 2;
1274 
1275         // generates the first (implicit) stack map frame
1276         if (FRAMES && stackMap != 0) {
1277             /*
1278              * for the first explicit frame the offset is not offset_delta + 1
1279              * but only offset_delta; setting the implicit frame offset to -1
1280              * allow the use of the "offset_delta + 1" rule in all cases
1281              */
1282             frame = context;
1283             frame.offset = -1;
1284             frame.mode = 0;
1285             frame.localCount = 0;
1286             frame.localDiff = 0;
1287             frame.stackCount = 0;
1288             frame.local = new Object[maxLocals];
1289             frame.stack = new Object[maxStack];
1290             if (unzip) {
1291                 getImplicitFrame(context);
1292             }
1293             /*
1294              * Finds labels for UNINITIALIZED frame types. Instead of decoding
1295              * each element of the stack map table, we look for 3 consecutive
1296              * bytes that "look like" an UNINITIALIZED type (tag 8, offset
1297              * within code bounds, NEW instruction at this offset). We may find
1298              * false positives (i.e. not real UNINITIALIZED types), but this
1299              * should be rare, and the only consequence will be the creation of
1300              * an unneeded label. This is better than creating a label for each
1301              * NEW instruction, and faster than fully decoding the whole stack
1302              * map table.
1303              */
1304             for (int i = stackMap; i < stackMap + stackMapSize - 2; ++i) {
1305                 if (b[i] == 8) { // UNINITIALIZED FRAME TYPE
1306                     int v = readUnsignedShort(i + 1);
1307                     if (v >= 0 && v < codeLength) {
1308                         if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) {
1309                             readLabel(v, labels);
1310                         }
1311                     }
1312                 }
1313             }
1314         }















1315 
1316         // visits the instructions


1317         u = codeStart;
1318         while (u < codeEnd) {
1319             int offset = u - codeStart;
1320 
1321             // visits the label and line number for this offset, if any
1322             Label l = labels[offset];
1323             if (l != null) {
1324                 Label next = l.next;
1325                 l.next = null;
1326                 mv.visitLabel(l);
1327                 if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) {
1328                     mv.visitLineNumber(l.line, l);
1329                     while (next != null) {
1330                         mv.visitLineNumber(next.line, l);
1331                         next = next.next;
1332                     }
1333                 }
1334             }
1335 
1336             // visits the frame for this offset, if any
1337             while (FRAMES && frame != null
1338                     && (frame.offset == offset || frame.offset == -1)) {
1339                 // if there is a frame for this offset, makes the visitor visit
1340                 // it, and reads the next frame if there is one.
1341                 if (frame.offset != -1) {
1342                     if (!zip || unzip) {
1343                         mv.visitFrame(Opcodes.F_NEW, frame.localCount,
1344                                 frame.local, frame.stackCount, frame.stack);
1345                     } else {
1346                         mv.visitFrame(frame.mode, frame.localDiff, frame.local,
1347                                 frame.stackCount, frame.stack);
1348                     }



1349                 }
1350                 if (frameCount > 0) {
1351                     stackMap = readFrame(stackMap, zip, unzip, frame);
1352                     --frameCount;
1353                 } else {
1354                     frame = null;
1355                 }
1356             }







1357 
1358             // visits the instruction at this offset
1359             int opcode = b[u] & 0xFF;
1360             switch (ClassWriter.TYPE[opcode]) {
1361             case ClassWriter.NOARG_INSN:
1362                 mv.visitInsn(opcode);
1363                 u += 1;
1364                 break;
1365             case ClassWriter.IMPLVAR_INSN:
1366                 if (opcode > Opcodes.ISTORE) {
1367                     opcode -= 59; // ISTORE_0
1368                     mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),
1369                             opcode & 0x3);
1370                 } else {
1371                     opcode -= 26; // ILOAD_0
1372                     mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), opcode & 0x3);
1373                 }
1374                 u += 1;
1375                 break;
1376             case ClassWriter.LABEL_INSN:
1377                 mv.visitJumpInsn(opcode, labels[offset + readShort(u + 1)]);
1378                 u += 3;
1379                 break;
1380             case ClassWriter.LABELW_INSN:
1381                 mv.visitJumpInsn(opcode - 33, labels[offset + readInt(u + 1)]);

1382                 u += 5;
1383                 break;





































1384             case ClassWriter.WIDE_INSN:
1385                 opcode = b[u + 1] & 0xFF;
1386                 if (opcode == Opcodes.IINC) {
1387                     mv.visitIincInsn(readUnsignedShort(u + 2), readShort(u + 4));
1388                     u += 6;
1389                 } else {
1390                     mv.visitVarInsn(opcode, readUnsignedShort(u + 2));
1391                     u += 4;
1392                 }
1393                 break;
1394             case ClassWriter.TABL_INSN: {
1395                 // skips 0 to 3 padding bytes
1396                 u = u + 4 - (offset & 3);
1397                 // reads instruction
1398                 int label = offset + readInt(u);
1399                 int min = readInt(u + 4);
1400                 int max = readInt(u + 8);
1401                 Label[] table = new Label[max - min + 1];
1402                 u += 12;
1403                 for (int i = 0; i < table.length; ++i) {


1619         u += 2;
1620         for (int i = 0; i < offsets.length; ++i) {
1621             offsets[i] = u;
1622             int target = readInt(u);
1623             switch (target >>> 24) {
1624             case 0x00: // CLASS_TYPE_PARAMETER
1625             case 0x01: // METHOD_TYPE_PARAMETER
1626             case 0x16: // METHOD_FORMAL_PARAMETER
1627                 u += 2;
1628                 break;
1629             case 0x13: // FIELD
1630             case 0x14: // METHOD_RETURN
1631             case 0x15: // METHOD_RECEIVER
1632                 u += 1;
1633                 break;
1634             case 0x40: // LOCAL_VARIABLE
1635             case 0x41: // RESOURCE_VARIABLE
1636                 for (int j = readUnsignedShort(u + 1); j > 0; --j) {
1637                     int start = readUnsignedShort(u + 3);
1638                     int length = readUnsignedShort(u + 5);
1639                     readLabel(start, context.labels);
1640                     readLabel(start + length, context.labels);
1641                     u += 6;
1642                 }
1643                 u += 3;
1644                 break;
1645             case 0x47: // CAST
1646             case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
1647             case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
1648             case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
1649             case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
1650                 u += 4;
1651                 break;
1652             // case 0x10: // CLASS_EXTENDS
1653             // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
1654             // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
1655             // case 0x17: // THROWS
1656             // case 0x42: // EXCEPTION_PARAMETER
1657             // case 0x43: // INSTANCEOF
1658             // case 0x44: // NEW
1659             // case 0x45: // CONSTRUCTOR_REFERENCE
1660             // case 0x46: // METHOD_REFERENCE


1699             target &= 0xFFFF0000;
1700             u += 2;
1701             break;
1702         case 0x13: // FIELD
1703         case 0x14: // METHOD_RETURN
1704         case 0x15: // METHOD_RECEIVER
1705             target &= 0xFF000000;
1706             u += 1;
1707             break;
1708         case 0x40: // LOCAL_VARIABLE
1709         case 0x41: { // RESOURCE_VARIABLE
1710             target &= 0xFF000000;
1711             int n = readUnsignedShort(u + 1);
1712             context.start = new Label[n];
1713             context.end = new Label[n];
1714             context.index = new int[n];
1715             u += 3;
1716             for (int i = 0; i < n; ++i) {
1717                 int start = readUnsignedShort(u);
1718                 int length = readUnsignedShort(u + 2);
1719                 context.start[i] = readLabel(start, context.labels);
1720                 context.end[i] = readLabel(start + length, context.labels);
1721                 context.index[i] = readUnsignedShort(u + 4);
1722                 u += 6;
1723             }
1724             break;
1725         }
1726         case 0x47: // CAST
1727         case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
1728         case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
1729         case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
1730         case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
1731             target &= 0xFF0000FF;
1732             u += 4;
1733             break;
1734         // case 0x10: // CLASS_EXTENDS
1735         // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
1736         // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
1737         // case 0x17: // THROWS
1738         // case 0x42: // EXCEPTION_PARAMETER
1739         // case 0x43: // INSTANCEOF
1740         // case 0x44: // NEW


2120             } else { // if (tag == FULL_FRAME) {
2121                 frame.mode = Opcodes.F_FULL;
2122                 int n = readUnsignedShort(stackMap);
2123                 stackMap += 2;
2124                 frame.localDiff = n;
2125                 frame.localCount = n;
2126                 for (int local = 0; n > 0; n--) {
2127                     stackMap = readFrameType(frame.local, local++, stackMap, c,
2128                             labels);
2129                 }
2130                 n = readUnsignedShort(stackMap);
2131                 stackMap += 2;
2132                 frame.stackCount = n;
2133                 for (int stack = 0; n > 0; n--) {
2134                     stackMap = readFrameType(frame.stack, stack++, stackMap, c,
2135                             labels);
2136                 }
2137             }
2138         }
2139         frame.offset += delta + 1;
2140         readLabel(frame.offset, labels);
2141         return stackMap;
2142     }
2143 
2144     /**
2145      * Reads a stack map frame type and stores it at the given index in the
2146      * given array.
2147      *
2148      * @param frame
2149      *            the array where the parsed type must be stored.
2150      * @param index
2151      *            the index in 'frame' where the parsed type must be stored.
2152      * @param v
2153      *            the start offset of the stack map frame type to read.
2154      * @param buf
2155      *            a buffer to read strings.
2156      * @param labels
2157      *            the labels of the method currently being parsed, indexed by
2158      *            their offset. If the parsed type is an Uninitialized type, a
2159      *            new label for the corresponding NEW instruction is stored in
2160      *            this array if it does not already exist.


2173         case 2:
2174             frame[index] = Opcodes.FLOAT;
2175             break;
2176         case 3:
2177             frame[index] = Opcodes.DOUBLE;
2178             break;
2179         case 4:
2180             frame[index] = Opcodes.LONG;
2181             break;
2182         case 5:
2183             frame[index] = Opcodes.NULL;
2184             break;
2185         case 6:
2186             frame[index] = Opcodes.UNINITIALIZED_THIS;
2187             break;
2188         case 7: // Object
2189             frame[index] = readClass(v, buf);
2190             v += 2;
2191             break;
2192         default: // Uninitialized
2193             frame[index] = readLabel(readUnsignedShort(v), labels);
2194             v += 2;
2195         }
2196         return v;
2197     }
2198 
2199     /**
2200      * Returns the label corresponding to the given offset. The default
2201      * implementation of this method creates a label for the given offset if it
2202      * has not been already created.
2203      *
2204      * @param offset
2205      *            a bytecode offset in a method.
2206      * @param labels
2207      *            the already created labels, indexed by their offset. If a
2208      *            label already exists for offset this method must not create a
2209      *            new one. Otherwise it must store the new label in this array.
2210      * @return a non null Label, which must be equal to labels[offset].
2211      */
2212     protected Label readLabel(int offset, Label[] labels) {
2213         if (labels[offset] == null) {
2214             labels[offset] = new Label();
2215         }
2216         return labels[offset];
2217     }
2218 
2219     /**

































2220      * Returns the start index of the attribute_info structure of this class.
2221      *
2222      * @return the start index of the attribute_info structure of this class.
2223      */
2224     private int getAttributes() {
2225         // skips the header
2226         int u = header + 8 + readUnsignedShort(header + 6) * 2;
2227         // skips fields and methods
2228         for (int i = readUnsignedShort(u); i > 0; --i) {
2229             for (int j = readUnsignedShort(u + 8); j > 0; --j) {
2230                 u += 6 + readInt(u + 12);
2231             }
2232             u += 8;
2233         }
2234         u += 2;
2235         for (int i = readUnsignedShort(u); i > 0; --i) {
2236             for (int j = readUnsignedShort(u + 8); j > 0; --j) {
2237                 u += 6 + readInt(u + 12);
2238             }
2239             u += 8;


2454                     cc = (char) (c & 0x0F);
2455                     st = 2;
2456                 }
2457                 break;
2458 
2459             case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char
2460                 buf[strLen++] = (char) ((cc << 6) | (c & 0x3F));
2461                 st = 0;
2462                 break;
2463 
2464             case 2: // byte 2 of 3-byte char
2465                 cc = (char) ((cc << 6) | (c & 0x3F));
2466                 st = 1;
2467                 break;
2468             }
2469         }
2470         return new String(buf, 0, strLen);
2471     }
2472 
2473     /**














2474      * Reads a class constant pool item in {@link #b b}. <i>This method is
2475      * intended for {@link Attribute} sub classes, and is normally not needed by
2476      * class generators or adapters.</i>
2477      *
2478      * @param index
2479      *            the start index of an unsigned short value in {@link #b b},
2480      *            whose value is the index of a class constant pool item.
2481      * @param buf
2482      *            buffer to be used to read the item. This buffer must be
2483      *            sufficiently large. It is not automatically resized.
2484      * @return the String corresponding to the specified class item.
2485      */
2486     public String readClass(final int index, final char[] buf) {
2487         // computes the start index of the CONSTANT_Class item in b
2488         // and reads the CONSTANT_Utf8 item designated by
2489         // the first two bytes of this CONSTANT_Class item
2490         return readUTF8(items[readUnsignedShort(index)], buf);
2491     }
2492 
2493     /**
2494      * Reads a CONSTANT_Module_info item in {@code b}. This method is intended
2495      * for {@link Attribute} sub classes, and is normally not needed by class
2496      * generators or adapters.</i>
2497      *
2498      * @param  index
2499      *         the start index of an unsigned short value in {@link #b b},
2500      *         whose value is the index of a module constant pool item.
2501      * @param  buf
2502      *         buffer to be used to read the item. This buffer must be
2503      *         sufficiently large. It is not automatically resized.
2504      * @return the String corresponding to the specified module item.
2505      */
2506     public String readModule(int index, char[] buf) {
2507         return readUTF8(items[readUnsignedShort(index)], buf);
2508     }
2509 
2510     /**
2511      * Reads a CONSTANT_Package_info item in {@code b}.  This method is
2512      * intended for {@link Attribute} sub slasses, and is normally not needed
2513      * by class generators or adapters.</i>
2514      *
2515      * @param  index
2516      *         the start index of an unsigned short value in {@link #b b},
2517      *         whose value is the index of a package constant pool item.
2518      * @param  buf
2519      *         buffer to be used to read the item. This buffer must be
2520      *         sufficiently large. It is not automatically resized.
2521      * @return the String corresponding to the specified package item.
2522      */
2523     public String readPackage(int index, char[] buf) {
2524         return readUTF8(items[readUnsignedShort(index)], buf);
2525     }
2526 
2527     /**
2528      * Reads a numeric or string constant pool item in {@link #b b}. <i>This
2529      * method is intended for {@link Attribute} sub classes, and is normally not
2530      * needed by class generators or adapters.</i>
2531      *
2532      * @param item
2533      *            the index of a constant pool item.
2534      * @param buf
2535      *            buffer to be used to read the item. This buffer must be
2536      *            sufficiently large. It is not automatically resized.
2537      * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double},
2538      *         {@link String}, {@link Type} or {@link Handle} corresponding to
2539      *         the given constant pool item.
2540      */
2541     public Object readConst(final int item, final char[] buf) {
2542         int index = items[item];
2543         switch (b[index - 1]) {
2544         case ClassWriter.INT:
2545             return readInt(index);
2546         case ClassWriter.FLOAT:
2547             return Float.intBitsToFloat(readInt(index));
2548         case ClassWriter.LONG:
2549             return readLong(index);
2550         case ClassWriter.DOUBLE:
2551             return Double.longBitsToDouble(readLong(index));
2552         case ClassWriter.CLASS:
2553         case ClassWriter.MODULE:
2554         case ClassWriter.PACKAGE:
2555             return Type.getObjectType(readUTF8(index, buf));
2556         case ClassWriter.STR:
2557             return readUTF8(index, buf);
2558         case ClassWriter.MTYPE:
2559             return Type.getMethodType(readUTF8(index, buf));
2560         default: // case ClassWriter.HANDLE_BASE + [1..9]:
2561             int tag = readByte(index);
2562             int[] items = this.items;
2563             int cpIndex = items[readUnsignedShort(index + 1)];
2564             boolean itf = b[cpIndex - 1] == ClassWriter.IMETH;
2565             String owner = readClass(cpIndex, buf);
2566             cpIndex = items[readUnsignedShort(cpIndex + 2)];
2567             String name = readUTF8(cpIndex, buf);
2568             String desc = readUTF8(cpIndex + 2, buf);
2569             return new Handle(tag, owner, name, desc, itf);
2570         }
2571     }
2572 }


  56  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  57  * THE POSSIBILITY OF SUCH DAMAGE.
  58  */
  59 package jdk.internal.org.objectweb.asm;
  60 
  61 import java.io.IOException;
  62 import java.io.InputStream;
  63 
  64 /**
  65  * A Java class parser to make a {@link ClassVisitor} visit an existing class.
  66  * This class parses a byte array conforming to the Java class file format and
  67  * calls the appropriate visit methods of a given class visitor for each field,
  68  * method and bytecode instruction encountered.
  69  *
  70  * @author Eric Bruneton
  71  * @author Eugene Kuleshov
  72  */
  73 public class ClassReader {
  74 
  75     /**

























  76      * Flag to skip method code. If this class is set <code>CODE</code>
  77      * attribute won't be visited. This can be used, for example, to retrieve
  78      * annotations for methods and method parameters.
  79      */
  80     public static final int SKIP_CODE = 1;
  81 
  82     /**
  83      * Flag to skip the debug information in the class. If this flag is set the
  84      * debug information of the class is not visited, i.e. the
  85      * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
  86      * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be
  87      * called.
  88      */
  89     public static final int SKIP_DEBUG = 2;
  90 
  91     /**
  92      * Flag to skip the stack map frames in the class. If this flag is set the
  93      * stack map frames of the class is not visited, i.e. the
  94      * {@link MethodVisitor#visitFrame visitFrame} method will not be called.
  95      * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is
  96      * used: it avoids visiting frames that will be ignored and recomputed from
  97      * scratch in the class writer.
  98      */
  99     public static final int SKIP_FRAMES = 4;
 100 
 101     /**
 102      * Flag to expand the stack map frames. By default stack map frames are
 103      * visited in their original format (i.e. "expanded" for classes whose
 104      * version is less than V1_6, and "compressed" for the other classes). If
 105      * this flag is set, stack map frames are always visited in expanded format
 106      * (this option adds a decompression/recompression step in ClassReader and
 107      * ClassWriter which degrades performances quite a lot).
 108      */
 109     public static final int EXPAND_FRAMES = 8;
 110 
 111     /**
 112      * Flag to expand the ASM pseudo instructions into an equivalent sequence of
 113      * standard bytecode instructions. When resolving a forward jump it may
 114      * happen that the signed 2 bytes offset reserved for it is not sufficient
 115      * to store the bytecode offset. In this case the jump instruction is
 116      * replaced with a temporary ASM pseudo instruction using an unsigned 2
 117      * bytes offset (see Label#resolve). This internal flag is used to re-read
 118      * classes containing such instructions, in order to replace them with
 119      * standard instructions. In addition, when this flag is used, GOTO_W and
 120      * JSR_W are <i>not</i> converted into GOTO and JSR, to make sure that
 121      * infinite loops where a GOTO_W is replaced with a GOTO in ClassReader and
 122      * converted back to a GOTO_W in ClassWriter cannot occur.
 123      */
 124     static final int EXPAND_ASM_INSNS = 256;
 125 
 126     /**
 127      * The class to be parsed. <i>The content of this array must not be
 128      * modified. This field is intended for {@link Attribute} sub classes, and
 129      * is normally not needed by class generators or adapters.</i>
 130      */
 131     public final byte[] b;
 132 
 133     /**
 134      * The start index of each constant pool item in {@link #b b}, plus one. The
 135      * one byte offset skips the constant pool item tag that indicates its type.
 136      */
 137     private final int[] items;
 138 
 139     /**
 140      * The String objects corresponding to the CONSTANT_Utf8 items. This cache
 141      * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
 142      * which GREATLY improves performances (by a factor 2 to 3). This caching
 143      * strategy could be extended to all constant pool items, but its benefit
 144      * would not be so great for these items (because they are much less
 145      * expensive to parse than CONSTANT_Utf8 items).
 146      */


 168      * @param b
 169      *            the bytecode of the class to be read.
 170      */
 171     public ClassReader(final byte[] b) {
 172         this(b, 0, b.length);
 173     }
 174 
 175     /**
 176      * Constructs a new {@link ClassReader} object.
 177      *
 178      * @param b
 179      *            the bytecode of the class to be read.
 180      * @param off
 181      *            the start offset of the class data.
 182      * @param len
 183      *            the length of the class data.
 184      */
 185     public ClassReader(final byte[] b, final int off, final int len) {
 186         this.b = b;
 187         // checks the class version
 188         if (readShort(off + 6) > Opcodes.V9) {
 189             throw new IllegalArgumentException();
 190         }
 191         // parses the constant pool
 192         items = new int[readUnsignedShort(off + 8)];
 193         int n = items.length;
 194         strings = new String[n];
 195         int max = 0;
 196         int index = off + 10;
 197         for (int i = 1; i < n; ++i) {
 198             items[i] = index + 1;
 199             int size;
 200             switch (b[index]) {
 201             case ClassWriter.FIELD:
 202             case ClassWriter.METH:
 203             case ClassWriter.IMETH:
 204             case ClassWriter.INT:
 205             case ClassWriter.FLOAT:
 206             case ClassWriter.NAME_TYPE:
 207             case ClassWriter.INDY:
 208                 size = 5;
 209                 break;
 210             case ClassWriter.LONG:
 211             case ClassWriter.DOUBLE:
 212                 size = 9;
 213                 ++i;
 214                 break;
 215             case ClassWriter.UTF8:
 216                 size = 3 + readUnsignedShort(index + 1);
 217                 if (size > max) {
 218                     max = size;
 219                 }
 220                 break;
 221             case ClassWriter.HANDLE:
 222                 size = 4;
 223                 break;
 224             // case ClassWriter.CLASS:
 225             // case ClassWriter.STR:
 226             // case ClassWriter.MTYPE
 227             // case ClassWriter.PACKAGE:
 228             // case ClassWriter.MODULE:
 229             default:
 230                 size = 3;
 231                 break;
 232             }
 233             index += size;
 234         }
 235         maxStringLength = max;
 236         // the class header information starts just after the constant pool
 237         header = index;
 238     }
 239 
 240     /**
 241      * Returns the class's access flags (see {@link Opcodes}). This value may
 242      * not reflect Deprecated and Synthetic flags when bytecode is before 1.5
 243      * and those flags are represented by attributes.
 244      *
 245      * @return the class access flags
 246      *
 247      * @see ClassVisitor#visit(int, int, String, String, String, String[])
 248      */


 352                 break;
 353             }
 354             case ClassWriter.HANDLE: {
 355                 int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
 356                 nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
 357                 item.set(ClassWriter.HANDLE_BASE + readByte(index),
 358                         readClass(fieldOrMethodRef, buf),
 359                         readUTF8(nameType, buf), readUTF8(nameType + 2, buf));
 360                 break;
 361             }
 362             case ClassWriter.INDY:
 363                 if (classWriter.bootstrapMethods == null) {
 364                     copyBootstrapMethods(classWriter, items2, buf);
 365                 }
 366                 nameType = items[readUnsignedShort(index + 2)];
 367                 item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf),
 368                         readUnsignedShort(index));
 369                 break;
 370             // case ClassWriter.STR:
 371             // case ClassWriter.CLASS:
 372             // case ClassWriter.MTYPE:
 373             // case ClassWriter.MODULE:
 374             // case ClassWriter.PACKAGE:
 375             default:
 376                 item.set(tag, readUTF8(index, buf), null, null);
 377                 break;
 378             }
 379 
 380             int index2 = item.hashCode % items2.length;
 381             item.next = items2[index2];
 382             items2[index2] = item;
 383         }
 384 
 385         int off = items[1] - 1;
 386         classWriter.pool.putByteArray(b, off, header - off);
 387         classWriter.items = items2;
 388         classWriter.threshold = (int) (0.75d * ll);
 389         classWriter.index = ll;
 390     }
 391 
 392     /**
 393      * Copies the bootstrap method data into the given {@link ClassWriter}.
 394      * Should be called before the {@link #accept(ClassVisitor,int)} method.


 561         context.buffer = c;
 562 
 563         // reads the class declaration
 564         int access = readUnsignedShort(u);
 565         String name = readClass(u + 2, c);
 566         String superClass = readClass(u + 4, c);
 567         String[] interfaces = new String[readUnsignedShort(u + 6)];
 568         u += 8;
 569         for (int i = 0; i < interfaces.length; ++i) {
 570             interfaces[i] = readClass(u, c);
 571             u += 2;
 572         }
 573 
 574         // reads the class attributes
 575         String signature = null;
 576         String sourceFile = null;
 577         String sourceDebug = null;
 578         String enclosingOwner = null;
 579         String enclosingName = null;
 580         String enclosingDesc = null;
 581         String moduleMainClass = null;
 582         int anns = 0;
 583         int ianns = 0;
 584         int tanns = 0;
 585         int itanns = 0;
 586         int innerClasses = 0;
 587         int module = 0;
 588         int packages = 0;
 589         Attribute attributes = null;
 590 
 591         u = getAttributes();
 592         for (int i = readUnsignedShort(u); i > 0; --i) {
 593             String attrName = readUTF8(u + 2, c);
 594             // tests are sorted in decreasing frequency order
 595             // (based on frequencies observed on typical classes)
 596             if ("SourceFile".equals(attrName)) {
 597                 sourceFile = readUTF8(u + 8, c);
 598             } else if ("InnerClasses".equals(attrName)) {
 599                 innerClasses = u + 8;
 600             } else if ("EnclosingMethod".equals(attrName)) {
 601                 enclosingOwner = readClass(u + 8, c);
 602                 int item = readUnsignedShort(u + 10);
 603                 if (item != 0) {
 604                     enclosingName = readUTF8(items[item], c);
 605                     enclosingDesc = readUTF8(items[item] + 2, c);
 606                 }
 607             } else if ("Signature".equals(attrName)) {
 608                 signature = readUTF8(u + 8, c);
 609             } else if ("RuntimeVisibleAnnotations".equals(attrName)) {

 610                 anns = u + 8;
 611             } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {

 612                 tanns = u + 8;
 613             } else if ("Deprecated".equals(attrName)) {
 614                 access |= Opcodes.ACC_DEPRECATED;
 615             } else if ("Synthetic".equals(attrName)) {
 616                 access |= Opcodes.ACC_SYNTHETIC
 617                         | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
 618             } else if ("SourceDebugExtension".equals(attrName)) {
 619                 int len = readInt(u + 4);
 620                 sourceDebug = readUTF(u + 8, len, new char[len]);
 621             } else if ("RuntimeInvisibleAnnotations".equals(attrName)) {

 622                 ianns = u + 8;
 623             } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {

 624                 itanns = u + 8;
 625             } else if ("Module".equals(attrName)) {
 626                 module = u + 8;
 627             } else if ("ModuleMainClass".equals(attrName)) {
 628                 moduleMainClass = readClass(u + 8, c);
 629             } else if ("ModulePackages".equals(attrName)) {
 630                 packages = u + 10;
 631             } else if ("BootstrapMethods".equals(attrName)) {
 632                 int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
 633                 for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
 634                     bootstrapMethods[j] = v;
 635                     v += 2 + readUnsignedShort(v + 2) << 1;
 636                 }
 637                 context.bootstrapMethods = bootstrapMethods;
 638             } else {
 639                 Attribute attr = readAttribute(attrs, attrName, u + 8,
 640                         readInt(u + 4), c, -1, null);
 641                 if (attr != null) {
 642                     attr.next = attributes;
 643                     attributes = attr;
 644                 }
 645             }
 646             u += 6 + readInt(u + 4);
 647         }
 648 
 649         // visits the class declaration
 650         classVisitor.visit(readInt(items[1] - 7), access, name, signature,
 651                 superClass, interfaces);
 652 
 653         // visits the source and debug info
 654         if ((flags & SKIP_DEBUG) == 0
 655                 && (sourceFile != null || sourceDebug != null)) {
 656             classVisitor.visitSource(sourceFile, sourceDebug);
 657         }
 658 
 659         // visits the module info and associated attributes
 660         if (module != 0) {
 661             readModule(classVisitor, context, module,
 662                     moduleMainClass, packages);
 663         }
 664 
 665         // visits the outer class
 666         if (enclosingOwner != null) {
 667             classVisitor.visitOuterClass(enclosingOwner, enclosingName,
 668                     enclosingDesc);
 669         }
 670 
 671         // visits the class annotations and type annotations
 672         if (anns != 0) {
 673             for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
 674                 v = readAnnotationValues(v + 2, c, true,
 675                         classVisitor.visitAnnotation(readUTF8(v, c), true));
 676             }
 677         }
 678         if (ianns != 0) {
 679             for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
 680                 v = readAnnotationValues(v + 2, c, true,
 681                         classVisitor.visitAnnotation(readUTF8(v, c), false));
 682             }
 683         }
 684         if (tanns != 0) {
 685             for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
 686                 v = readAnnotationTarget(context, v);
 687                 v = readAnnotationValues(v + 2, c, true,
 688                         classVisitor.visitTypeAnnotation(context.typeRef,
 689                                 context.typePath, readUTF8(v, c), true));
 690             }
 691         }
 692         if (itanns != 0) {
 693             for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
 694                 v = readAnnotationTarget(context, v);
 695                 v = readAnnotationValues(v + 2, c, true,
 696                         classVisitor.visitTypeAnnotation(context.typeRef,
 697                                 context.typePath, readUTF8(v, c), false));
 698             }
 699         }
 700 
 701         // visits the attributes
 702         while (attributes != null) {
 703             Attribute attr = attributes.next;
 704             attributes.next = null;
 705             classVisitor.visitAttribute(attributes);
 706             attributes = attr;
 707         }
 708 
 709         // visits the inner classes
 710         if (innerClasses != 0) {
 711             int v = innerClasses + 2;
 712             for (int i = readUnsignedShort(innerClasses); i > 0; --i) {


 715                         readUnsignedShort(v + 6));
 716                 v += 8;
 717             }
 718         }
 719 
 720         // visits the fields and methods
 721         u = header + 10 + 2 * interfaces.length;
 722         for (int i = readUnsignedShort(u - 2); i > 0; --i) {
 723             u = readField(classVisitor, context, u);
 724         }
 725         u += 2;
 726         for (int i = readUnsignedShort(u - 2); i > 0; --i) {
 727             u = readMethod(classVisitor, context, u);
 728         }
 729 
 730         // visits the end of the class
 731         classVisitor.visitEnd();
 732     }
 733 
 734     /**
 735      * Reads the module attribute and visit it.
 736      *
 737      * @param classVisitor
 738      *           the current class visitor
 739      * @param context
 740      *           information about the class being parsed.
 741      * @param u
 742      *           start offset of the module attribute in the class file.
 743      * @param mainClass
 744      *           name of the main class of a module or null.
 745      * @param packages
 746      *           start offset of the concealed package attribute.
 747      */
 748     private void readModule(final ClassVisitor classVisitor,
 749             final Context context, int u,
 750             final String mainClass, int packages) {
 751 
 752         char[] buffer = context.buffer;
 753 
 754         // reads module name, flags and version
 755         String name = readModule(u, buffer);
 756         int flags = readUnsignedShort(u + 2);
 757         String version = readUTF8(u + 4, buffer);
 758         u += 6;
 759 
 760         ModuleVisitor mv = classVisitor.visitModule(name, flags, version);
 761         if (mv == null) {
 762             return;
 763         }
 764 
 765         // module attributes (main class, packages)
 766         if (mainClass != null) {
 767             mv.visitMainClass(mainClass);
 768         }
 769 
 770         if (packages != 0) {
 771             for (int i = readUnsignedShort(packages - 2); i > 0; --i) {
 772                 String packaze = readPackage(packages, buffer);
 773                 mv.visitPackage(packaze);
 774                 packages += 2;
 775             }
 776         }
 777 
 778         // reads requires
 779         u += 2;
 780         for (int i = readUnsignedShort(u - 2); i > 0; --i) {
 781             String module = readModule(u, buffer);
 782             int access = readUnsignedShort(u + 2);
 783             String requireVersion = readUTF8(u + 4, buffer);
 784             mv.visitRequire(module, access, requireVersion);
 785             u += 6;
 786         }
 787 
 788         // reads exports
 789         u += 2;
 790         for (int i = readUnsignedShort(u - 2); i > 0; --i) {
 791             String export = readPackage(u, buffer);
 792             int access = readUnsignedShort(u + 2);
 793             int exportToCount = readUnsignedShort(u + 4);
 794             u += 6;
 795             String[] tos = null;
 796             if (exportToCount != 0) {
 797                 tos = new String[exportToCount];
 798                 for (int j = 0; j < tos.length; ++j) {
 799                     tos[j] = readModule(u, buffer);
 800                     u += 2;
 801                 }
 802             }
 803             mv.visitExport(export, access, tos);
 804         }
 805 
 806         // reads opens
 807         u += 2;
 808         for (int i = readUnsignedShort(u - 2); i > 0; --i) {
 809             String open = readPackage(u, buffer);
 810             int access = readUnsignedShort(u + 2);
 811             int openToCount = readUnsignedShort(u + 4);
 812             u += 6;
 813             String[] tos = null;
 814             if (openToCount != 0) {
 815                 tos = new String[openToCount];
 816                 for (int j = 0; j < tos.length; ++j) {
 817                     tos[j] = readModule(u, buffer);
 818                     u += 2;
 819                 }
 820             }
 821             mv.visitOpen(open, access, tos);
 822         }
 823 
 824         // read uses
 825         u += 2;
 826         for (int i = readUnsignedShort(u - 2); i > 0; --i) {
 827             mv.visitUse(readClass(u, buffer));
 828             u += 2;
 829         }
 830 
 831         // read provides
 832         u += 2;
 833         for (int i = readUnsignedShort(u - 2); i > 0; --i) {
 834             String service = readClass(u, buffer);
 835             int provideWithCount = readUnsignedShort(u + 2);
 836             u += 4;
 837             String[] withs = new String[provideWithCount];
 838             for (int j = 0; j < withs.length; ++j) {
 839                 withs[j] = readClass(u, buffer);
 840                 u += 2;
 841             }
 842             mv.visitProvide(service, withs);
 843         }
 844 
 845         mv.visitEnd();
 846     }
 847 
 848     /**
 849      * Reads a field and makes the given visitor visit it.
 850      *
 851      * @param classVisitor
 852      *            the visitor that must visit the field.
 853      * @param context
 854      *            information about the class being parsed.
 855      * @param u
 856      *            the start offset of the field in the class file.
 857      * @return the offset of the first byte following the field in the class.
 858      */
 859     private int readField(final ClassVisitor classVisitor,
 860             final Context context, int u) {
 861         // reads the field declaration
 862         char[] c = context.buffer;
 863         int access = readUnsignedShort(u);
 864         String name = readUTF8(u + 2, c);
 865         String desc = readUTF8(u + 4, c);
 866         u += 6;
 867 
 868         // reads the field attributes
 869         String signature = null;
 870         int anns = 0;
 871         int ianns = 0;
 872         int tanns = 0;
 873         int itanns = 0;
 874         Object value = null;
 875         Attribute attributes = null;
 876 
 877         for (int i = readUnsignedShort(u); i > 0; --i) {
 878             String attrName = readUTF8(u + 2, c);
 879             // tests are sorted in decreasing frequency order
 880             // (based on frequencies observed on typical classes)
 881             if ("ConstantValue".equals(attrName)) {
 882                 int item = readUnsignedShort(u + 8);
 883                 value = item == 0 ? null : readConst(item, c);
 884             } else if ("Signature".equals(attrName)) {
 885                 signature = readUTF8(u + 8, c);
 886             } else if ("Deprecated".equals(attrName)) {
 887                 access |= Opcodes.ACC_DEPRECATED;
 888             } else if ("Synthetic".equals(attrName)) {
 889                 access |= Opcodes.ACC_SYNTHETIC
 890                         | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
 891             } else if ("RuntimeVisibleAnnotations".equals(attrName)) {

 892                 anns = u + 8;
 893             } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {

 894                 tanns = u + 8;
 895             } else if ("RuntimeInvisibleAnnotations".equals(attrName)) {

 896                 ianns = u + 8;
 897             } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {

 898                 itanns = u + 8;
 899             } else {
 900                 Attribute attr = readAttribute(context.attrs, attrName, u + 8,
 901                         readInt(u + 4), c, -1, null);
 902                 if (attr != null) {
 903                     attr.next = attributes;
 904                     attributes = attr;
 905                 }
 906             }
 907             u += 6 + readInt(u + 4);
 908         }
 909         u += 2;
 910 
 911         // visits the field declaration
 912         FieldVisitor fv = classVisitor.visitField(access, name, desc,
 913                 signature, value);
 914         if (fv == null) {
 915             return u;
 916         }
 917 
 918         // visits the field annotations and type annotations
 919         if (anns != 0) {
 920             for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
 921                 v = readAnnotationValues(v + 2, c, true,
 922                         fv.visitAnnotation(readUTF8(v, c), true));
 923             }
 924         }
 925         if (ianns != 0) {
 926             for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
 927                 v = readAnnotationValues(v + 2, c, true,
 928                         fv.visitAnnotation(readUTF8(v, c), false));
 929             }
 930         }
 931         if (tanns != 0) {
 932             for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
 933                 v = readAnnotationTarget(context, v);
 934                 v = readAnnotationValues(v + 2, c, true,
 935                         fv.visitTypeAnnotation(context.typeRef,
 936                                 context.typePath, readUTF8(v, c), true));
 937             }
 938         }
 939         if (itanns != 0) {
 940             for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
 941                 v = readAnnotationTarget(context, v);
 942                 v = readAnnotationValues(v + 2, c, true,
 943                         fv.visitTypeAnnotation(context.typeRef,
 944                                 context.typePath, readUTF8(v, c), false));
 945             }
 946         }
 947 
 948         // visits the field attributes
 949         while (attributes != null) {
 950             Attribute attr = attributes.next;
 951             attributes.next = null;
 952             fv.visitAttribute(attributes);
 953             attributes = attr;
 954         }
 955 
 956         // visits the end of the field
 957         fv.visitEnd();
 958 
 959         return u;


 993         int mpanns = 0;
 994         int impanns = 0;
 995         int firstAttribute = u;
 996         Attribute attributes = null;
 997 
 998         for (int i = readUnsignedShort(u); i > 0; --i) {
 999             String attrName = readUTF8(u + 2, c);
1000             // tests are sorted in decreasing frequency order
1001             // (based on frequencies observed on typical classes)
1002             if ("Code".equals(attrName)) {
1003                 if ((context.flags & SKIP_CODE) == 0) {
1004                     code = u + 8;
1005                 }
1006             } else if ("Exceptions".equals(attrName)) {
1007                 exceptions = new String[readUnsignedShort(u + 8)];
1008                 exception = u + 10;
1009                 for (int j = 0; j < exceptions.length; ++j) {
1010                     exceptions[j] = readClass(exception, c);
1011                     exception += 2;
1012                 }
1013             } else if ("Signature".equals(attrName)) {
1014                 signature = readUTF8(u + 8, c);
1015             } else if ("Deprecated".equals(attrName)) {
1016                 context.access |= Opcodes.ACC_DEPRECATED;
1017             } else if ("RuntimeVisibleAnnotations".equals(attrName)) {

1018                 anns = u + 8;
1019             } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {

1020                 tanns = u + 8;
1021             } else if ("AnnotationDefault".equals(attrName)) {
1022                 dann = u + 8;
1023             } else if ("Synthetic".equals(attrName)) {
1024                 context.access |= Opcodes.ACC_SYNTHETIC
1025                         | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
1026             } else if ("RuntimeInvisibleAnnotations".equals(attrName)) {

1027                 ianns = u + 8;
1028             } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {

1029                 itanns = u + 8;
1030             } else if ("RuntimeVisibleParameterAnnotations".equals(attrName)) {

1031                 mpanns = u + 8;
1032             } else if ("RuntimeInvisibleParameterAnnotations".equals(attrName)) {

1033                 impanns = u + 8;
1034             } else if ("MethodParameters".equals(attrName)) {
1035                 methodParameters = u + 8;
1036             } else {
1037                 Attribute attr = readAttribute(context.attrs, attrName, u + 8,
1038                         readInt(u + 4), c, -1, null);
1039                 if (attr != null) {
1040                     attr.next = attributes;
1041                     attributes = attr;
1042                 }
1043             }
1044             u += 6 + readInt(u + 4);
1045         }
1046         u += 2;
1047 
1048         // visits the method declaration
1049         MethodVisitor mv = classVisitor.visitMethod(context.access,
1050                 context.name, context.desc, signature, exceptions);
1051         if (mv == null) {
1052             return u;
1053         }
1054 
1055         /*
1056          * if the returned MethodVisitor is in fact a MethodWriter, it means
1057          * there is no method adapter between the reader and the writer. If, in
1058          * addition, the writer's constant pool was copied from this reader
1059          * (mw.cw.cr == this), and the signature and exceptions of the method
1060          * have not been changed, then it is possible to skip all visit events
1061          * and just copy the original code of the method to the writer (the
1062          * access, name and descriptor can have been changed, this is not
1063          * important since they are not copied as is from the reader).
1064          */
1065         if (mv instanceof MethodWriter) {
1066             MethodWriter mw = (MethodWriter) mv;
1067             if (mw.cw.cr == this && signature == mw.signature) {
1068                 boolean sameExceptions = false;
1069                 if (exceptions == null) {
1070                     sameExceptions = mw.exceptionCount == 0;
1071                 } else if (exceptions.length == mw.exceptionCount) {
1072                     sameExceptions = true;
1073                     for (int j = exceptions.length - 1; j >= 0; --j) {
1074                         exception -= 2;
1075                         if (mw.exceptions[j] != readUnsignedShort(exception)) {
1076                             sameExceptions = false;
1077                             break;
1078                         }
1079                     }
1080                 }
1081                 if (sameExceptions) {
1082                     /*
1083                      * we do not copy directly the code into MethodWriter to
1084                      * save a byte array copy operation. The real copy will be
1085                      * done in ClassWriter.toByteArray().
1086                      */
1087                     mw.classReaderOffset = firstAttribute;
1088                     mw.classReaderLength = u - firstAttribute;
1089                     return u;
1090                 }
1091             }
1092         }
1093 
1094         // visit the method parameters
1095         if (methodParameters != 0) {
1096             for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) {
1097                 mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2));
1098             }
1099         }
1100 
1101         // visits the method annotations
1102         if (dann != 0) {
1103             AnnotationVisitor dv = mv.visitAnnotationDefault();
1104             readAnnotationValue(dann, c, null, dv);
1105             if (dv != null) {
1106                 dv.visitEnd();
1107             }
1108         }
1109         if (anns != 0) {
1110             for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
1111                 v = readAnnotationValues(v + 2, c, true,
1112                         mv.visitAnnotation(readUTF8(v, c), true));
1113             }
1114         }
1115         if (ianns != 0) {
1116             for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
1117                 v = readAnnotationValues(v + 2, c, true,
1118                         mv.visitAnnotation(readUTF8(v, c), false));
1119             }
1120         }
1121         if (tanns != 0) {
1122             for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
1123                 v = readAnnotationTarget(context, v);
1124                 v = readAnnotationValues(v + 2, c, true,
1125                         mv.visitTypeAnnotation(context.typeRef,
1126                                 context.typePath, readUTF8(v, c), true));
1127             }
1128         }
1129         if (itanns != 0) {
1130             for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
1131                 v = readAnnotationTarget(context, v);
1132                 v = readAnnotationValues(v + 2, c, true,
1133                         mv.visitTypeAnnotation(context.typeRef,
1134                                 context.typePath, readUTF8(v, c), false));
1135             }
1136         }
1137         if (mpanns != 0) {
1138             readParameterAnnotations(mv, context, mpanns, true);
1139         }
1140         if (impanns != 0) {
1141             readParameterAnnotations(mv, context, impanns, false);
1142         }
1143 
1144         // visits the method attributes
1145         while (attributes != null) {
1146             Attribute attr = attributes.next;
1147             attributes.next = null;
1148             mv.visitAttribute(attributes);
1149             attributes = attr;
1150         }
1151 
1152         // visits the method code
1153         if (code != 0) {
1154             mv.visitCode();
1155             readCode(mv, context, code);
1156         }
1157 
1158         // visits the end of the method
1159         mv.visitEnd();
1160 


1167      * @param mv
1168      *            the visitor that must visit the method's code.
1169      * @param context
1170      *            information about the class being parsed.
1171      * @param u
1172      *            the start offset of the code attribute in the class file.
1173      */
1174     private void readCode(final MethodVisitor mv, final Context context, int u) {
1175         // reads the header
1176         byte[] b = this.b;
1177         char[] c = context.buffer;
1178         int maxStack = readUnsignedShort(u);
1179         int maxLocals = readUnsignedShort(u + 2);
1180         int codeLength = readInt(u + 4);
1181         u += 8;
1182 
1183         // reads the bytecode to find the labels
1184         int codeStart = u;
1185         int codeEnd = u + codeLength;
1186         Label[] labels = context.labels = new Label[codeLength + 2];
1187         createLabel(codeLength + 1, labels);
1188         while (u < codeEnd) {
1189             int offset = u - codeStart;
1190             int opcode = b[u] & 0xFF;
1191             switch (ClassWriter.TYPE[opcode]) {
1192             case ClassWriter.NOARG_INSN:
1193             case ClassWriter.IMPLVAR_INSN:
1194                 u += 1;
1195                 break;
1196             case ClassWriter.LABEL_INSN:
1197                 createLabel(offset + readShort(u + 1), labels);
1198                 u += 3;
1199                 break;
1200             case ClassWriter.ASM_LABEL_INSN:
1201                 createLabel(offset + readUnsignedShort(u + 1), labels);
1202                 u += 3;
1203                 break;
1204             case ClassWriter.LABELW_INSN:
1205             case ClassWriter.ASM_LABELW_INSN:
1206                 createLabel(offset + readInt(u + 1), labels);
1207                 u += 5;
1208                 break;
1209             case ClassWriter.WIDE_INSN:
1210                 opcode = b[u + 1] & 0xFF;
1211                 if (opcode == Opcodes.IINC) {
1212                     u += 6;
1213                 } else {
1214                     u += 4;
1215                 }
1216                 break;
1217             case ClassWriter.TABL_INSN:
1218                 // skips 0 to 3 padding bytes
1219                 u = u + 4 - (offset & 3);
1220                 // reads instruction
1221                 createLabel(offset + readInt(u), labels);
1222                 for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) {
1223                     createLabel(offset + readInt(u + 12), labels);
1224                     u += 4;
1225                 }
1226                 u += 12;
1227                 break;
1228             case ClassWriter.LOOK_INSN:
1229                 // skips 0 to 3 padding bytes
1230                 u = u + 4 - (offset & 3);
1231                 // reads instruction
1232                 createLabel(offset + readInt(u), labels);
1233                 for (int i = readInt(u + 4); i > 0; --i) {
1234                     createLabel(offset + readInt(u + 12), labels);
1235                     u += 8;
1236                 }
1237                 u += 8;
1238                 break;
1239             case ClassWriter.VAR_INSN:
1240             case ClassWriter.SBYTE_INSN:
1241             case ClassWriter.LDC_INSN:
1242                 u += 2;
1243                 break;
1244             case ClassWriter.SHORT_INSN:
1245             case ClassWriter.LDCW_INSN:
1246             case ClassWriter.FIELDORMETH_INSN:
1247             case ClassWriter.TYPE_INSN:
1248             case ClassWriter.IINC_INSN:
1249                 u += 3;
1250                 break;
1251             case ClassWriter.ITFMETH_INSN:
1252             case ClassWriter.INDYMETH_INSN:
1253                 u += 5;
1254                 break;
1255             // case MANA_INSN:
1256             default:
1257                 u += 4;
1258                 break;
1259             }
1260         }
1261 
1262         // reads the try catch entries to find the labels, and also visits them
1263         for (int i = readUnsignedShort(u); i > 0; --i) {
1264             Label start = createLabel(readUnsignedShort(u + 2), labels);
1265             Label end = createLabel(readUnsignedShort(u + 4), labels);
1266             Label handler = createLabel(readUnsignedShort(u + 6), labels);
1267             String type = readUTF8(items[readUnsignedShort(u + 8)], c);
1268             mv.visitTryCatchBlock(start, end, handler, type);
1269             u += 8;
1270         }
1271         u += 2;
1272 
1273         // reads the code attributes
1274         int[] tanns = null; // start index of each visible type annotation
1275         int[] itanns = null; // start index of each invisible type annotation
1276         int tann = 0; // current index in tanns array
1277         int itann = 0; // current index in itanns array
1278         int ntoff = -1; // next visible type annotation code offset
1279         int nitoff = -1; // next invisible type annotation code offset
1280         int varTable = 0;
1281         int varTypeTable = 0;
1282         boolean zip = true;
1283         boolean unzip = (context.flags & EXPAND_FRAMES) != 0;
1284         int stackMap = 0;
1285         int stackMapSize = 0;
1286         int frameCount = 0;
1287         Context frame = null;
1288         Attribute attributes = null;
1289 
1290         for (int i = readUnsignedShort(u); i > 0; --i) {
1291             String attrName = readUTF8(u + 2, c);
1292             if ("LocalVariableTable".equals(attrName)) {
1293                 if ((context.flags & SKIP_DEBUG) == 0) {
1294                     varTable = u + 8;
1295                     for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
1296                         int label = readUnsignedShort(v + 10);
1297                         createDebugLabel(label, labels);


1298                         label += readUnsignedShort(v + 12);
1299                         createDebugLabel(label, labels);


1300                         v += 10;
1301                     }
1302                 }
1303             } else if ("LocalVariableTypeTable".equals(attrName)) {
1304                 varTypeTable = u + 8;
1305             } else if ("LineNumberTable".equals(attrName)) {
1306                 if ((context.flags & SKIP_DEBUG) == 0) {
1307                     for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
1308                         int label = readUnsignedShort(v + 10);
1309                         createDebugLabel(label, labels);


1310                         Label l = labels[label];
1311                         while (l.line > 0) {
1312                             if (l.next == null) {
1313                                 l.next = new Label();
1314                             }
1315                             l = l.next;
1316                         }
1317                         l.line = readUnsignedShort(v + 12);
1318                         v += 4;
1319                     }
1320                 }
1321             } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {

1322                 tanns = readTypeAnnotations(mv, context, u + 8, true);
1323                 ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1
1324                         : readUnsignedShort(tanns[0] + 1);
1325             } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {

1326                 itanns = readTypeAnnotations(mv, context, u + 8, false);
1327                 nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1
1328                         : readUnsignedShort(itanns[0] + 1);
1329             } else if ("StackMapTable".equals(attrName)) {
1330                 if ((context.flags & SKIP_FRAMES) == 0) {
1331                     stackMap = u + 10;
1332                     stackMapSize = readInt(u + 4);
1333                     frameCount = readUnsignedShort(u + 8);
1334                 }
1335                 /*
1336                  * here we do not extract the labels corresponding to the
1337                  * attribute content. This would require a full parsing of the
1338                  * attribute, which would need to be repeated in the second
1339                  * phase (see below). Instead the content of the attribute is
1340                  * read one frame at a time (i.e. after a frame has been
1341                  * visited, the next frame is read), and the labels it contains
1342                  * are also extracted one frame at a time. Thanks to the
1343                  * ordering of frames, having only a "one frame lookahead" is
1344                  * not a problem, i.e. it is not possible to see an offset
1345                  * smaller than the offset of the current insn and for which no
1346                  * Label exist.
1347                  */
1348                 /*
1349                  * This is not true for UNINITIALIZED type offsets. We solve
1350                  * this by parsing the stack map table without a full decoding
1351                  * (see below).
1352                  */
1353             } else if ("StackMap".equals(attrName)) {
1354                 if ((context.flags & SKIP_FRAMES) == 0) {
1355                     zip = false;
1356                     stackMap = u + 10;
1357                     stackMapSize = readInt(u + 4);
1358                     frameCount = readUnsignedShort(u + 8);
1359                 }
1360                 /*
1361                  * IMPORTANT! here we assume that the frames are ordered, as in
1362                  * the StackMapTable attribute, although this is not guaranteed
1363                  * by the attribute format.
1364                  */
1365             } else {
1366                 for (int j = 0; j < context.attrs.length; ++j) {
1367                     if (context.attrs[j].type.equals(attrName)) {
1368                         Attribute attr = context.attrs[j].read(this, u + 8,
1369                                 readInt(u + 4), c, codeStart - 8, labels);
1370                         if (attr != null) {
1371                             attr.next = attributes;
1372                             attributes = attr;
1373                         }
1374                     }
1375                 }
1376             }
1377             u += 6 + readInt(u + 4);
1378         }
1379         u += 2;
1380 
1381         // generates the first (implicit) stack map frame
1382         if (stackMap != 0) {
1383             /*
1384              * for the first explicit frame the offset is not offset_delta + 1
1385              * but only offset_delta; setting the implicit frame offset to -1
1386              * allow the use of the "offset_delta + 1" rule in all cases
1387              */
1388             frame = context;
1389             frame.offset = -1;
1390             frame.mode = 0;
1391             frame.localCount = 0;
1392             frame.localDiff = 0;
1393             frame.stackCount = 0;
1394             frame.local = new Object[maxLocals];
1395             frame.stack = new Object[maxStack];
1396             if (unzip) {
1397                 getImplicitFrame(context);
1398             }
1399             /*
1400              * Finds labels for UNINITIALIZED frame types. Instead of decoding
1401              * each element of the stack map table, we look for 3 consecutive
1402              * bytes that "look like" an UNINITIALIZED type (tag 8, offset
1403              * within code bounds, NEW instruction at this offset). We may find
1404              * false positives (i.e. not real UNINITIALIZED types), but this
1405              * should be rare, and the only consequence will be the creation of
1406              * an unneeded label. This is better than creating a label for each
1407              * NEW instruction, and faster than fully decoding the whole stack
1408              * map table.
1409              */
1410             for (int i = stackMap; i < stackMap + stackMapSize - 2; ++i) {
1411                 if (b[i] == 8) { // UNINITIALIZED FRAME TYPE
1412                     int v = readUnsignedShort(i + 1);
1413                     if (v >= 0 && v < codeLength) {
1414                         if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) {
1415                             createLabel(v, labels);
1416                         }
1417                     }
1418                 }
1419             }
1420         }
1421         if ((context.flags & EXPAND_ASM_INSNS) != 0
1422             && (context.flags & EXPAND_FRAMES) != 0) {
1423             // Expanding the ASM pseudo instructions can introduce F_INSERT
1424             // frames, even if the method does not currently have any frame.
1425             // Also these inserted frames must be computed by simulating the
1426             // effect of the bytecode instructions one by one, starting from the
1427             // first one and the last existing frame (or the implicit first
1428             // one). Finally, due to the way MethodWriter computes this (with
1429             // the compute = INSERTED_FRAMES option), MethodWriter needs to know
1430             // maxLocals before the first instruction is visited. For all these
1431             // reasons we always visit the implicit first frame in this case
1432             // (passing only maxLocals - the rest can be and is computed in
1433             // MethodWriter).
1434             mv.visitFrame(Opcodes.F_NEW, maxLocals, null, 0, null);
1435         }
1436 
1437         // visits the instructions
1438         int opcodeDelta = (context.flags & EXPAND_ASM_INSNS) == 0 ? -33 : 0;
1439         boolean insertFrame = false;
1440         u = codeStart;
1441         while (u < codeEnd) {
1442             int offset = u - codeStart;
1443 
1444             // visits the label and line number for this offset, if any
1445             Label l = labels[offset];
1446             if (l != null) {
1447                 Label next = l.next;
1448                 l.next = null;
1449                 mv.visitLabel(l);
1450                 if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) {
1451                     mv.visitLineNumber(l.line, l);
1452                     while (next != null) {
1453                         mv.visitLineNumber(next.line, l);
1454                         next = next.next;
1455                     }
1456                 }
1457             }
1458 
1459             // visits the frame for this offset, if any
1460             while (frame != null
1461                     && (frame.offset == offset || frame.offset == -1)) {
1462                 // if there is a frame for this offset, makes the visitor visit
1463                 // it, and reads the next frame if there is one.
1464                 if (frame.offset != -1) {
1465                     if (!zip || unzip) {
1466                         mv.visitFrame(Opcodes.F_NEW, frame.localCount,
1467                                 frame.local, frame.stackCount, frame.stack);
1468                     } else {
1469                         mv.visitFrame(frame.mode, frame.localDiff, frame.local,
1470                                 frame.stackCount, frame.stack);
1471                     }
1472                     // if there is already a frame for this offset, there is no
1473                     // need to insert a new one.
1474                     insertFrame = false;
1475                 }
1476                 if (frameCount > 0) {
1477                     stackMap = readFrame(stackMap, zip, unzip, frame);
1478                     --frameCount;
1479                 } else {
1480                     frame = null;
1481                 }
1482             }
1483             // inserts a frame for this offset, if requested by setting
1484             // insertFrame to true during the previous iteration. The actual
1485             // frame content will be computed in MethodWriter.
1486             if (insertFrame) {
1487                 mv.visitFrame(ClassWriter.F_INSERT, 0, null, 0, null);
1488                 insertFrame = false;
1489             }
1490 
1491             // visits the instruction at this offset
1492             int opcode = b[u] & 0xFF;
1493             switch (ClassWriter.TYPE[opcode]) {
1494             case ClassWriter.NOARG_INSN:
1495                 mv.visitInsn(opcode);
1496                 u += 1;
1497                 break;
1498             case ClassWriter.IMPLVAR_INSN:
1499                 if (opcode > Opcodes.ISTORE) {
1500                     opcode -= 59; // ISTORE_0
1501                     mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),
1502                             opcode & 0x3);
1503                 } else {
1504                     opcode -= 26; // ILOAD_0
1505                     mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), opcode & 0x3);
1506                 }
1507                 u += 1;
1508                 break;
1509             case ClassWriter.LABEL_INSN:
1510                 mv.visitJumpInsn(opcode, labels[offset + readShort(u + 1)]);
1511                 u += 3;
1512                 break;
1513             case ClassWriter.LABELW_INSN:
1514                 mv.visitJumpInsn(opcode + opcodeDelta, labels[offset
1515                         + readInt(u + 1)]);
1516                 u += 5;
1517                 break;
1518             case ClassWriter.ASM_LABEL_INSN: {
1519                 // changes temporary opcodes 202 to 217 (inclusive), 218
1520                 // and 219 to IFEQ ... JSR (inclusive), IFNULL and
1521                 // IFNONNULL
1522                 opcode = opcode < 218 ? opcode - 49 : opcode - 20;
1523                 Label target = labels[offset + readUnsignedShort(u + 1)];
1524                 // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
1525                 // <l> with IFNOTxxx <L> GOTO_W <l> L:..., where IFNOTxxx is
1526                 // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
1527                 // and where <L> designates the instruction just after
1528                 // the GOTO_W.
1529                 if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
1530                     mv.visitJumpInsn(opcode + 33, target);
1531                 } else {
1532                     opcode = opcode <= 166 ? ((opcode + 1) ^ 1) - 1
1533                             : opcode ^ 1;
1534                     Label endif = createLabel(offset + 3, labels);
1535                     mv.visitJumpInsn(opcode, endif);
1536                     mv.visitJumpInsn(200, target); // GOTO_W
1537                     // endif designates the instruction just after GOTO_W,
1538                     // and is visited as part of the next instruction. Since
1539                     // it is a jump target, we need to insert a frame here.
1540                     insertFrame = true;
1541                 }
1542                 u += 3;
1543                 break;
1544             }
1545             case ClassWriter.ASM_LABELW_INSN: {
1546                 // replaces the pseudo GOTO_W instruction with a real one.
1547                 mv.visitJumpInsn(200, labels[offset + readInt(u + 1)]);
1548                 // The instruction just after is a jump target (because pseudo
1549                 // GOTO_W are used in patterns IFNOTxxx <L> GOTO_W <l> L:...,
1550                 // see MethodWriter), so we need to insert a frame here.
1551                 insertFrame = true;
1552                 u += 5;
1553                 break;
1554             }
1555             case ClassWriter.WIDE_INSN:
1556                 opcode = b[u + 1] & 0xFF;
1557                 if (opcode == Opcodes.IINC) {
1558                     mv.visitIincInsn(readUnsignedShort(u + 2), readShort(u + 4));
1559                     u += 6;
1560                 } else {
1561                     mv.visitVarInsn(opcode, readUnsignedShort(u + 2));
1562                     u += 4;
1563                 }
1564                 break;
1565             case ClassWriter.TABL_INSN: {
1566                 // skips 0 to 3 padding bytes
1567                 u = u + 4 - (offset & 3);
1568                 // reads instruction
1569                 int label = offset + readInt(u);
1570                 int min = readInt(u + 4);
1571                 int max = readInt(u + 8);
1572                 Label[] table = new Label[max - min + 1];
1573                 u += 12;
1574                 for (int i = 0; i < table.length; ++i) {


1790         u += 2;
1791         for (int i = 0; i < offsets.length; ++i) {
1792             offsets[i] = u;
1793             int target = readInt(u);
1794             switch (target >>> 24) {
1795             case 0x00: // CLASS_TYPE_PARAMETER
1796             case 0x01: // METHOD_TYPE_PARAMETER
1797             case 0x16: // METHOD_FORMAL_PARAMETER
1798                 u += 2;
1799                 break;
1800             case 0x13: // FIELD
1801             case 0x14: // METHOD_RETURN
1802             case 0x15: // METHOD_RECEIVER
1803                 u += 1;
1804                 break;
1805             case 0x40: // LOCAL_VARIABLE
1806             case 0x41: // RESOURCE_VARIABLE
1807                 for (int j = readUnsignedShort(u + 1); j > 0; --j) {
1808                     int start = readUnsignedShort(u + 3);
1809                     int length = readUnsignedShort(u + 5);
1810                     createLabel(start, context.labels);
1811                     createLabel(start + length, context.labels);
1812                     u += 6;
1813                 }
1814                 u += 3;
1815                 break;
1816             case 0x47: // CAST
1817             case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
1818             case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
1819             case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
1820             case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
1821                 u += 4;
1822                 break;
1823             // case 0x10: // CLASS_EXTENDS
1824             // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
1825             // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
1826             // case 0x17: // THROWS
1827             // case 0x42: // EXCEPTION_PARAMETER
1828             // case 0x43: // INSTANCEOF
1829             // case 0x44: // NEW
1830             // case 0x45: // CONSTRUCTOR_REFERENCE
1831             // case 0x46: // METHOD_REFERENCE


1870             target &= 0xFFFF0000;
1871             u += 2;
1872             break;
1873         case 0x13: // FIELD
1874         case 0x14: // METHOD_RETURN
1875         case 0x15: // METHOD_RECEIVER
1876             target &= 0xFF000000;
1877             u += 1;
1878             break;
1879         case 0x40: // LOCAL_VARIABLE
1880         case 0x41: { // RESOURCE_VARIABLE
1881             target &= 0xFF000000;
1882             int n = readUnsignedShort(u + 1);
1883             context.start = new Label[n];
1884             context.end = new Label[n];
1885             context.index = new int[n];
1886             u += 3;
1887             for (int i = 0; i < n; ++i) {
1888                 int start = readUnsignedShort(u);
1889                 int length = readUnsignedShort(u + 2);
1890                 context.start[i] = createLabel(start, context.labels);
1891                 context.end[i] = createLabel(start + length, context.labels);
1892                 context.index[i] = readUnsignedShort(u + 4);
1893                 u += 6;
1894             }
1895             break;
1896         }
1897         case 0x47: // CAST
1898         case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
1899         case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
1900         case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
1901         case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
1902             target &= 0xFF0000FF;
1903             u += 4;
1904             break;
1905         // case 0x10: // CLASS_EXTENDS
1906         // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
1907         // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
1908         // case 0x17: // THROWS
1909         // case 0x42: // EXCEPTION_PARAMETER
1910         // case 0x43: // INSTANCEOF
1911         // case 0x44: // NEW


2291             } else { // if (tag == FULL_FRAME) {
2292                 frame.mode = Opcodes.F_FULL;
2293                 int n = readUnsignedShort(stackMap);
2294                 stackMap += 2;
2295                 frame.localDiff = n;
2296                 frame.localCount = n;
2297                 for (int local = 0; n > 0; n--) {
2298                     stackMap = readFrameType(frame.local, local++, stackMap, c,
2299                             labels);
2300                 }
2301                 n = readUnsignedShort(stackMap);
2302                 stackMap += 2;
2303                 frame.stackCount = n;
2304                 for (int stack = 0; n > 0; n--) {
2305                     stackMap = readFrameType(frame.stack, stack++, stackMap, c,
2306                             labels);
2307                 }
2308             }
2309         }
2310         frame.offset += delta + 1;
2311         createLabel(frame.offset, labels);
2312         return stackMap;
2313     }
2314 
2315     /**
2316      * Reads a stack map frame type and stores it at the given index in the
2317      * given array.
2318      *
2319      * @param frame
2320      *            the array where the parsed type must be stored.
2321      * @param index
2322      *            the index in 'frame' where the parsed type must be stored.
2323      * @param v
2324      *            the start offset of the stack map frame type to read.
2325      * @param buf
2326      *            a buffer to read strings.
2327      * @param labels
2328      *            the labels of the method currently being parsed, indexed by
2329      *            their offset. If the parsed type is an Uninitialized type, a
2330      *            new label for the corresponding NEW instruction is stored in
2331      *            this array if it does not already exist.


2344         case 2:
2345             frame[index] = Opcodes.FLOAT;
2346             break;
2347         case 3:
2348             frame[index] = Opcodes.DOUBLE;
2349             break;
2350         case 4:
2351             frame[index] = Opcodes.LONG;
2352             break;
2353         case 5:
2354             frame[index] = Opcodes.NULL;
2355             break;
2356         case 6:
2357             frame[index] = Opcodes.UNINITIALIZED_THIS;
2358             break;
2359         case 7: // Object
2360             frame[index] = readClass(v, buf);
2361             v += 2;
2362             break;
2363         default: // Uninitialized
2364             frame[index] = createLabel(readUnsignedShort(v), labels);
2365             v += 2;
2366         }
2367         return v;
2368     }
2369 
2370     /**
2371      * Returns the label corresponding to the given offset. The default
2372      * implementation of this method creates a label for the given offset if it
2373      * has not been already created.
2374      *
2375      * @param offset
2376      *            a bytecode offset in a method.
2377      * @param labels
2378      *            the already created labels, indexed by their offset. If a
2379      *            label already exists for offset this method must not create a
2380      *            new one. Otherwise it must store the new label in this array.
2381      * @return a non null Label, which must be equal to labels[offset].
2382      */
2383     protected Label readLabel(int offset, Label[] labels) {
2384         if (labels[offset] == null) {
2385             labels[offset] = new Label();
2386         }
2387         return labels[offset];
2388     }
2389 
2390     /**
2391      * Creates a label without the Label.DEBUG flag set, for the given offset.
2392      * The label is created with a call to {@link #readLabel} and its
2393      * Label.DEBUG flag is cleared.
2394      *
2395      * @param offset
2396      *            a bytecode offset in a method.
2397      * @param labels
2398      *            the already created labels, indexed by their offset.
2399      * @return a Label without the Label.DEBUG flag set.
2400      */
2401     private Label createLabel(int offset, Label[] labels) {
2402       Label label = readLabel(offset, labels);
2403       label.status &= ~Label.DEBUG;
2404       return label;
2405     }
2406 
2407     /**
2408      * Creates a label with the Label.DEBUG flag set, if there is no already
2409      * existing label for the given offset (otherwise does nothing). The label
2410      * is created with a call to {@link #readLabel}.
2411      *
2412      * @param offset
2413      *            a bytecode offset in a method.
2414      * @param labels
2415      *            the already created labels, indexed by their offset.
2416      */
2417     private void createDebugLabel(int offset, Label[] labels) {
2418         if (labels[offset] == null) {
2419             readLabel(offset, labels).status |= Label.DEBUG;
2420         }
2421     }
2422 
2423     /**
2424      * Returns the start index of the attribute_info structure of this class.
2425      *
2426      * @return the start index of the attribute_info structure of this class.
2427      */
2428     private int getAttributes() {
2429         // skips the header
2430         int u = header + 8 + readUnsignedShort(header + 6) * 2;
2431         // skips fields and methods
2432         for (int i = readUnsignedShort(u); i > 0; --i) {
2433             for (int j = readUnsignedShort(u + 8); j > 0; --j) {
2434                 u += 6 + readInt(u + 12);
2435             }
2436             u += 8;
2437         }
2438         u += 2;
2439         for (int i = readUnsignedShort(u); i > 0; --i) {
2440             for (int j = readUnsignedShort(u + 8); j > 0; --j) {
2441                 u += 6 + readInt(u + 12);
2442             }
2443             u += 8;


2658                     cc = (char) (c & 0x0F);
2659                     st = 2;
2660                 }
2661                 break;
2662 
2663             case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char
2664                 buf[strLen++] = (char) ((cc << 6) | (c & 0x3F));
2665                 st = 0;
2666                 break;
2667 
2668             case 2: // byte 2 of 3-byte char
2669                 cc = (char) ((cc << 6) | (c & 0x3F));
2670                 st = 1;
2671                 break;
2672             }
2673         }
2674         return new String(buf, 0, strLen);
2675     }
2676 
2677     /**
2678      * Read a stringish constant item (CONSTANT_Class, CONSTANT_String,
2679      * CONSTANT_MethodType, CONSTANT_Module or CONSTANT_Package
2680      * @param index
2681      * @param buf
2682      * @return
2683      */
2684     private String readStringish(final int index, final char[] buf) {
2685         // computes the start index of the item in b
2686         // and reads the CONSTANT_Utf8 item designated by
2687         // the first two bytes of this item
2688         return readUTF8(items[readUnsignedShort(index)], buf);
2689     }
2690 
2691     /**
2692      * Reads a class constant pool item in {@link #b b}. <i>This method is
2693      * intended for {@link Attribute} sub classes, and is normally not needed by
2694      * class generators or adapters.</i>
2695      *
2696      * @param index
2697      *            the start index of an unsigned short value in {@link #b b},
2698      *            whose value is the index of a class constant pool item.
2699      * @param buf
2700      *            buffer to be used to read the item. This buffer must be
2701      *            sufficiently large. It is not automatically resized.
2702      * @return the String corresponding to the specified class item.
2703      */
2704     public String readClass(final int index, final char[] buf) {
2705         return readStringish(index, buf);



2706     }
2707 
2708     /**
2709      * Reads a module constant pool item in {@link #b b}. <i>This method is
2710      * intended for {@link Attribute} sub classes, and is normally not needed by
2711      * class generators or adapters.</i>
2712      *
2713      * @param index
2714      *            the start index of an unsigned short value in {@link #b b},
2715      *            whose value is the index of a module constant pool item.
2716      * @param buf
2717      *            buffer to be used to read the item. This buffer must be
2718      *            sufficiently large. It is not automatically resized.
2719      * @return the String corresponding to the specified module item.
2720      */
2721     public String readModule(final int index, final char[] buf) {
2722         return readStringish(index, buf);
2723     }
2724 
2725     /**
2726      * Reads a module constant pool item in {@link #b b}. <i>This method is
2727      * intended for {@link Attribute} sub classes, and is normally not needed by
2728      * class generators or adapters.</i>
2729      *
2730      * @param index
2731      *            the start index of an unsigned short value in {@link #b b},
2732      *            whose value is the index of a module constant pool item.
2733      * @param buf
2734      *            buffer to be used to read the item. This buffer must be
2735      *            sufficiently large. It is not automatically resized.
2736      * @return the String corresponding to the specified module item.
2737      */
2738     public String readPackage(final int index, final char[] buf) {
2739         return readStringish(index, buf);
2740     }
2741 
2742     /**
2743      * Reads a numeric or string constant pool item in {@link #b b}. <i>This
2744      * method is intended for {@link Attribute} sub classes, and is normally not
2745      * needed by class generators or adapters.</i>
2746      *
2747      * @param item
2748      *            the index of a constant pool item.
2749      * @param buf
2750      *            buffer to be used to read the item. This buffer must be
2751      *            sufficiently large. It is not automatically resized.
2752      * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double},
2753      *         {@link String}, {@link Type} or {@link Handle} corresponding to
2754      *         the given constant pool item.
2755      */
2756     public Object readConst(final int item, final char[] buf) {
2757         int index = items[item];
2758         switch (b[index - 1]) {
2759         case ClassWriter.INT:
2760             return readInt(index);
2761         case ClassWriter.FLOAT:
2762             return Float.intBitsToFloat(readInt(index));
2763         case ClassWriter.LONG:
2764             return readLong(index);
2765         case ClassWriter.DOUBLE:
2766             return Double.longBitsToDouble(readLong(index));
2767         case ClassWriter.CLASS:


2768             return Type.getObjectType(readUTF8(index, buf));
2769         case ClassWriter.STR:
2770             return readUTF8(index, buf);
2771         case ClassWriter.MTYPE:
2772             return Type.getMethodType(readUTF8(index, buf));
2773         default: // case ClassWriter.HANDLE_BASE + [1..9]:
2774             int tag = readByte(index);
2775             int[] items = this.items;
2776             int cpIndex = items[readUnsignedShort(index + 1)];
2777             boolean itf = b[cpIndex - 1] == ClassWriter.IMETH;
2778             String owner = readClass(cpIndex, buf);
2779             cpIndex = items[readUnsignedShort(cpIndex + 2)];
2780             String name = readUTF8(cpIndex, buf);
2781             String desc = readUTF8(cpIndex + 2, buf);
2782             return new Handle(tag, owner, name, desc, itf);
2783         }
2784     }
2785 }
< prev index next >