001// ASM: a very small and fast Java bytecode manipulation framework
002// Copyright (c) 2000-2011 INRIA, France Telecom
003// All rights reserved.
004//
005// Redistribution and use in source and binary forms, with or without
006// modification, are permitted provided that the following conditions
007// are met:
008// 1. Redistributions of source code must retain the above copyright
009//    notice, this list of conditions and the following disclaimer.
010// 2. Redistributions in binary form must reproduce the above copyright
011//    notice, this list of conditions and the following disclaimer in the
012//    documentation and/or other materials provided with the distribution.
013// 3. Neither the name of the copyright holders nor the names of its
014//    contributors may be used to endorse or promote products derived from
015//    this software without specific prior written permission.
016//
017// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
018// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
019// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
020// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
021// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
022// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
023// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
024// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
025// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
026// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
027// THE POSSIBILITY OF SUCH DAMAGE.
028package io.ebean.enhance.asm;
029
030import java.io.ByteArrayOutputStream;
031import java.io.IOException;
032import java.io.InputStream;
033
034/**
035 * A parser to make a {@link ClassVisitor} visit a ClassFile structure, as defined in the Java
036 * Virtual Machine Specification (JVMS). This class parses the ClassFile content and calls the
037 * appropriate visit methods of a given {@link ClassVisitor} for each field, method and bytecode
038 * instruction encountered.
039 *
040 * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html">JVMS 4</a>
041 * @author Eric Bruneton
042 * @author Eugene Kuleshov
043 */
044public class ClassReader {
045
046  /**
047   * A flag to skip the Code attributes. If this flag is set the Code attributes are neither parsed
048   * nor visited.
049   */
050  public static final int SKIP_CODE = 1;
051
052  /**
053   * A flag to skip the SourceFile, SourceDebugExtension, LocalVariableTable,
054   * LocalVariableTypeTable, LineNumberTable and MethodParameters attributes. If this flag is set
055   * these attributes are neither parsed nor visited (i.e. {@link ClassVisitor#visitSource}, {@link
056   * MethodVisitor#visitLocalVariable}, {@link MethodVisitor#visitLineNumber} and {@link
057   * MethodVisitor#visitParameter} are not called).
058   */
059  public static final int SKIP_DEBUG = 2;
060
061  /**
062   * A flag to skip the StackMap and StackMapTable attributes. If this flag is set these attributes
063   * are neither parsed nor visited (i.e. {@link MethodVisitor#visitFrame} is not called). This flag
064   * is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is used: it avoids visiting frames
065   * that will be ignored and recomputed from scratch.
066   */
067  public static final int SKIP_FRAMES = 4;
068
069  /**
070   * A flag to expand the stack map frames. By default stack map frames are visited in their
071   * original format (i.e. "expanded" for classes whose version is less than V1_6, and "compressed"
072   * for the other classes). If this flag is set, stack map frames are always visited in expanded
073   * format (this option adds a decompression/compression step in ClassReader and ClassWriter which
074   * degrades performance quite a lot).
075   */
076  public static final int EXPAND_FRAMES = 8;
077
078  /**
079   * A flag to expand the ASM specific instructions into an equivalent sequence of standard bytecode
080   * instructions. When resolving a forward jump it may happen that the signed 2 bytes offset
081   * reserved for it is not sufficient to store the bytecode offset. In this case the jump
082   * instruction is replaced with a temporary ASM specific instruction using an unsigned 2 bytes
083   * offset (see {@link Label#resolve}). This internal flag is used to re-read classes containing
084   * such instructions, in order to replace them with standard instructions. In addition, when this
085   * flag is used, goto_w and jsr_w are <i>not</i> converted into goto and jsr, to make sure that
086   * infinite loops where a goto_w is replaced with a goto in ClassReader and converted back to a
087   * goto_w in ClassWriter cannot occur.
088   */
089  static final int EXPAND_ASM_INSNS = 256;
090
091  /** The maximum size of array to allocate. */
092  private static final int MAX_BUFFER_SIZE = 1024 * 1024;
093
094  /** The size of the temporary byte array used to read class input streams chunk by chunk. */
095  private static final int INPUT_STREAM_DATA_CHUNK_SIZE = 4096;
096
097  /**
098   * A byte array containing the JVMS ClassFile structure to be parsed.
099   *
100   * @deprecated Use {@link #readByte(int)} and the other read methods instead. This field will
101   *     eventually be deleted.
102   */
103  @Deprecated
104  // DontCheck(MemberName): can't be renamed (for backward binary compatibility).
105  public final byte[] b;
106
107  /** The offset in bytes of the ClassFile's access_flags field. */
108  public final int header;
109
110  /**
111   * A byte array containing the JVMS ClassFile structure to be parsed. <i>The content of this array
112   * must not be modified. This field is intended for {@link Attribute} sub classes, and is normally
113   * not needed by class visitors.</i>
114   *
115   * <p>NOTE: the ClassFile structure can start at any offset within this array, i.e. it does not
116   * necessarily start at offset 0. Use {@link #getItem} and {@link #header} to get correct
117   * ClassFile element offsets within this byte array.
118   */
119  final byte[] classFileBuffer;
120
121  /**
122   * The offset in bytes, in {@link #classFileBuffer}, of each cp_info entry of the ClassFile's
123   * constant_pool array, <i>plus one</i>. In other words, the offset of constant pool entry i is
124   * given by cpInfoOffsets[i] - 1, i.e. its cp_info's tag field is given by b[cpInfoOffsets[i] -
125   * 1].
126   */
127  private final int[] cpInfoOffsets;
128
129  /**
130   * The String objects corresponding to the CONSTANT_Utf8 constant pool items. This cache avoids
131   * multiple parsing of a given CONSTANT_Utf8 constant pool item.
132   */
133  private final String[] constantUtf8Values;
134
135  /**
136   * The ConstantDynamic objects corresponding to the CONSTANT_Dynamic constant pool items. This
137   * cache avoids multiple parsing of a given CONSTANT_Dynamic constant pool item.
138   */
139  private final ConstantDynamic[] constantDynamicValues;
140
141  /**
142   * The start offsets in {@link #classFileBuffer} of each element of the bootstrap_methods array
143   * (in the BootstrapMethods attribute).
144   *
145   * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.23">JVMS
146   *     4.7.23</a>
147   */
148  private final int[] bootstrapMethodOffsets;
149
150  /**
151   * A conservative estimate of the maximum length of the strings contained in the constant pool of
152   * the class.
153   */
154  private final int maxStringLength;
155
156  // -----------------------------------------------------------------------------------------------
157  // Constructors
158  // -----------------------------------------------------------------------------------------------
159
160  /**
161   * Constructs a new {@link ClassReader} object.
162   *
163   * @param classFile the JVMS ClassFile structure to be read.
164   */
165  public ClassReader(final byte[] classFile) {
166    this(classFile, 0, classFile.length);
167  }
168
169  /**
170   * Constructs a new {@link ClassReader} object.
171   *
172   * @param classFileBuffer a byte array containing the JVMS ClassFile structure to be read.
173   * @param classFileOffset the offset in byteBuffer of the first byte of the ClassFile to be read.
174   * @param classFileLength the length in bytes of the ClassFile to be read.
175   */
176  public ClassReader(
177      final byte[] classFileBuffer,
178      final int classFileOffset,
179      final int classFileLength) { // NOPMD(UnusedFormalParameter) used for backward compatibility.
180    this(classFileBuffer, classFileOffset, /* checkClassVersion = */ true);
181  }
182
183  /**
184   * Constructs a new {@link ClassReader} object. <i>This internal constructor must not be exposed
185   * as a public API</i>.
186   *
187   * @param classFileBuffer a byte array containing the JVMS ClassFile structure to be read.
188   * @param classFileOffset the offset in byteBuffer of the first byte of the ClassFile to be read.
189   * @param checkClassVersion whether to check the class version or not.
190   */
191  ClassReader(
192      final byte[] classFileBuffer, final int classFileOffset, final boolean checkClassVersion) {
193    this.classFileBuffer = classFileBuffer;
194    this.b = classFileBuffer;
195    // Check the class' major_version. This field is after the magic and minor_version fields, which
196    // use 4 and 2 bytes respectively.
197    if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V21) {
198      throw new IllegalArgumentException(
199          "Unsupported class file major version " + readShort(classFileOffset + 6));
200    }
201    // Create the constant pool arrays. The constant_pool_count field is after the magic,
202    // minor_version and major_version fields, which use 4, 2 and 2 bytes respectively.
203    int constantPoolCount = readUnsignedShort(classFileOffset + 8);
204    cpInfoOffsets = new int[constantPoolCount];
205    constantUtf8Values = new String[constantPoolCount];
206    // Compute the offset of each constant pool entry, as well as a conservative estimate of the
207    // maximum length of the constant pool strings. The first constant pool entry is after the
208    // magic, minor_version, major_version and constant_pool_count fields, which use 4, 2, 2 and 2
209    // bytes respectively.
210    int currentCpInfoIndex = 1;
211    int currentCpInfoOffset = classFileOffset + 10;
212    int currentMaxStringLength = 0;
213    boolean hasBootstrapMethods = false;
214    boolean hasConstantDynamic = false;
215    // The offset of the other entries depend on the total size of all the previous entries.
216    while (currentCpInfoIndex < constantPoolCount) {
217      cpInfoOffsets[currentCpInfoIndex++] = currentCpInfoOffset + 1;
218      int cpInfoSize;
219      switch (classFileBuffer[currentCpInfoOffset]) {
220        case Symbol.CONSTANT_FIELDREF_TAG:
221        case Symbol.CONSTANT_METHODREF_TAG:
222        case Symbol.CONSTANT_INTERFACE_METHODREF_TAG:
223        case Symbol.CONSTANT_INTEGER_TAG:
224        case Symbol.CONSTANT_FLOAT_TAG:
225        case Symbol.CONSTANT_NAME_AND_TYPE_TAG:
226          cpInfoSize = 5;
227          break;
228        case Symbol.CONSTANT_DYNAMIC_TAG:
229          cpInfoSize = 5;
230          hasBootstrapMethods = true;
231          hasConstantDynamic = true;
232          break;
233        case Symbol.CONSTANT_INVOKE_DYNAMIC_TAG:
234          cpInfoSize = 5;
235          hasBootstrapMethods = true;
236          break;
237        case Symbol.CONSTANT_LONG_TAG:
238        case Symbol.CONSTANT_DOUBLE_TAG:
239          cpInfoSize = 9;
240          currentCpInfoIndex++;
241          break;
242        case Symbol.CONSTANT_UTF8_TAG:
243          cpInfoSize = 3 + readUnsignedShort(currentCpInfoOffset + 1);
244          if (cpInfoSize > currentMaxStringLength) {
245            // The size in bytes of this CONSTANT_Utf8 structure provides a conservative estimate
246            // of the length in characters of the corresponding string, and is much cheaper to
247            // compute than this exact length.
248            currentMaxStringLength = cpInfoSize;
249          }
250          break;
251        case Symbol.CONSTANT_METHOD_HANDLE_TAG:
252          cpInfoSize = 4;
253          break;
254        case Symbol.CONSTANT_CLASS_TAG:
255        case Symbol.CONSTANT_STRING_TAG:
256        case Symbol.CONSTANT_METHOD_TYPE_TAG:
257        case Symbol.CONSTANT_PACKAGE_TAG:
258        case Symbol.CONSTANT_MODULE_TAG:
259          cpInfoSize = 3;
260          break;
261        default:
262          throw new IllegalArgumentException();
263      }
264      currentCpInfoOffset += cpInfoSize;
265    }
266    maxStringLength = currentMaxStringLength;
267    // The Classfile's access_flags field is just after the last constant pool entry.
268    header = currentCpInfoOffset;
269
270    // Allocate the cache of ConstantDynamic values, if there is at least one.
271    constantDynamicValues = hasConstantDynamic ? new ConstantDynamic[constantPoolCount] : null;
272
273    // Read the BootstrapMethods attribute, if any (only get the offset of each method).
274    bootstrapMethodOffsets =
275        hasBootstrapMethods ? readBootstrapMethodsAttribute(currentMaxStringLength) : null;
276  }
277
278  /**
279   * Constructs a new {@link ClassReader} object.
280   *
281   * @param inputStream an input stream of the JVMS ClassFile structure to be read. This input
282   *     stream must contain nothing more than the ClassFile structure itself. It is read from its
283   *     current position to its end.
284   * @throws IOException if a problem occurs during reading.
285   */
286  public ClassReader(final InputStream inputStream) throws IOException {
287    this(readStream(inputStream, false));
288  }
289
290  /**
291   * Constructs a new {@link ClassReader} object.
292   *
293   * @param className the fully qualified name of the class to be read. The ClassFile structure is
294   *     retrieved with the current class loader's {@link ClassLoader#getSystemResourceAsStream}.
295   * @throws IOException if an exception occurs during reading.
296   */
297  public ClassReader(final String className) throws IOException {
298    this(
299        readStream(
300            ClassLoader.getSystemResourceAsStream(className.replace('.', '/') + ".class"), true));
301  }
302
303  /**
304   * Reads the given input stream and returns its content as a byte array.
305   *
306   * @param inputStream an input stream.
307   * @param close true to close the input stream after reading.
308   * @return the content of the given input stream.
309   * @throws IOException if a problem occurs during reading.
310   */
311  @SuppressWarnings("PMD.UseTryWithResources")
312  private static byte[] readStream(final InputStream inputStream, final boolean close)
313      throws IOException {
314    if (inputStream == null) {
315      throw new IOException("Class not found");
316    }
317    int bufferSize = computeBufferSize(inputStream);
318    try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
319      byte[] data = new byte[bufferSize];
320      int bytesRead;
321      int readCount = 0;
322      while ((bytesRead = inputStream.read(data, 0, bufferSize)) != -1) {
323        outputStream.write(data, 0, bytesRead);
324        readCount++;
325      }
326      outputStream.flush();
327      if (readCount == 1) {
328        return data;
329      }
330      return outputStream.toByteArray();
331    } finally {
332      if (close) {
333        inputStream.close();
334      }
335    }
336  }
337
338  private static int computeBufferSize(final InputStream inputStream) throws IOException {
339    int expectedLength = inputStream.available();
340    /*
341     * Some implementations can return 0 while holding available data (e.g. new
342     * FileInputStream("/proc/a_file")). Also in some pathological cases a very small number might
343     * be returned, and in this case we use a default size.
344     */
345    if (expectedLength < 256) {
346      return INPUT_STREAM_DATA_CHUNK_SIZE;
347    }
348    return Math.min(expectedLength, MAX_BUFFER_SIZE);
349  }
350
351  // -----------------------------------------------------------------------------------------------
352  // Accessors
353  // -----------------------------------------------------------------------------------------------
354
355  /**
356   * Returns the class's access flags (see {@link Opcodes}). This value may not reflect Deprecated
357   * and Synthetic flags when bytecode is before 1.5 and those flags are represented by attributes.
358   *
359   * @return the class access flags.
360   * @see ClassVisitor#visit(int, int, String, String, String, String[])
361   */
362  public int getAccess() {
363    return readUnsignedShort(header);
364  }
365
366  /**
367   * Returns the internal name of the class (see {@link Type#getInternalName()}).
368   *
369   * @return the internal class name.
370   * @see ClassVisitor#visit(int, int, String, String, String, String[])
371   */
372  public String getClassName() {
373    // this_class is just after the access_flags field (using 2 bytes).
374    return readClass(header + 2, new char[maxStringLength]);
375  }
376
377  /**
378   * Returns the internal name of the super class (see {@link Type#getInternalName()}). For
379   * interfaces, the super class is {@link Object}.
380   *
381   * @return the internal name of the super class, or {@literal null} for {@link Object} class.
382   * @see ClassVisitor#visit(int, int, String, String, String, String[])
383   */
384  public String getSuperName() {
385    // super_class is after the access_flags and this_class fields (2 bytes each).
386    return readClass(header + 4, new char[maxStringLength]);
387  }
388
389  /**
390   * Returns the internal names of the implemented interfaces (see {@link Type#getInternalName()}).
391   *
392   * @return the internal names of the directly implemented interfaces. Inherited implemented
393   *     interfaces are not returned.
394   * @see ClassVisitor#visit(int, int, String, String, String, String[])
395   */
396  public String[] getInterfaces() {
397    // interfaces_count is after the access_flags, this_class and super_class fields (2 bytes each).
398    int currentOffset = header + 6;
399    int interfacesCount = readUnsignedShort(currentOffset);
400    String[] interfaces = new String[interfacesCount];
401    if (interfacesCount > 0) {
402      char[] charBuffer = new char[maxStringLength];
403      for (int i = 0; i < interfacesCount; ++i) {
404        currentOffset += 2;
405        interfaces[i] = readClass(currentOffset, charBuffer);
406      }
407    }
408    return interfaces;
409  }
410
411  // -----------------------------------------------------------------------------------------------
412  // Public methods
413  // -----------------------------------------------------------------------------------------------
414
415  /**
416   * Makes the given visitor visit the JVMS ClassFile structure passed to the constructor of this
417   * {@link ClassReader}.
418   *
419   * @param classVisitor the visitor that must visit this class.
420   * @param parsingOptions the options to use to parse this class. One or more of {@link
421   *     #SKIP_CODE}, {@link #SKIP_DEBUG}, {@link #SKIP_FRAMES} or {@link #EXPAND_FRAMES}.
422   */
423  public void accept(final ClassVisitor classVisitor, final int parsingOptions) {
424    accept(classVisitor, new Attribute[0], parsingOptions);
425  }
426
427  /**
428   * Makes the given visitor visit the JVMS ClassFile structure passed to the constructor of this
429   * {@link ClassReader}.
430   *
431   * @param classVisitor the visitor that must visit this class.
432   * @param attributePrototypes prototypes of the attributes that must be parsed during the visit of
433   *     the class. Any attribute whose type is not equal to the type of one the prototypes will not
434   *     be parsed: its byte array value will be passed unchanged to the ClassWriter. <i>This may
435   *     corrupt it if this value contains references to the constant pool, or has syntactic or
436   *     semantic links with a class element that has been transformed by a class adapter between
437   *     the reader and the writer</i>.
438   * @param parsingOptions the options to use to parse this class. One or more of {@link
439   *     #SKIP_CODE}, {@link #SKIP_DEBUG}, {@link #SKIP_FRAMES} or {@link #EXPAND_FRAMES}.
440   */
441  public void accept(
442      final ClassVisitor classVisitor,
443      final Attribute[] attributePrototypes,
444      final int parsingOptions) {
445    Context context = new Context();
446    context.attributePrototypes = attributePrototypes;
447    context.parsingOptions = parsingOptions;
448    context.charBuffer = new char[maxStringLength];
449
450    // Read the access_flags, this_class, super_class, interface_count and interfaces fields.
451    char[] charBuffer = context.charBuffer;
452    int currentOffset = header;
453    int accessFlags = readUnsignedShort(currentOffset);
454    String thisClass = readClass(currentOffset + 2, charBuffer);
455    String superClass = readClass(currentOffset + 4, charBuffer);
456    String[] interfaces = new String[readUnsignedShort(currentOffset + 6)];
457    currentOffset += 8;
458    for (int i = 0; i < interfaces.length; ++i) {
459      interfaces[i] = readClass(currentOffset, charBuffer);
460      currentOffset += 2;
461    }
462
463    // Read the class attributes (the variables are ordered as in Section 4.7 of the JVMS).
464    // Attribute offsets exclude the attribute_name_index and attribute_length fields.
465    // - The offset of the InnerClasses attribute, or 0.
466    int innerClassesOffset = 0;
467    // - The offset of the EnclosingMethod attribute, or 0.
468    int enclosingMethodOffset = 0;
469    // - The string corresponding to the Signature attribute, or null.
470    String signature = null;
471    // - The string corresponding to the SourceFile attribute, or null.
472    String sourceFile = null;
473    // - The string corresponding to the SourceDebugExtension attribute, or null.
474    String sourceDebugExtension = null;
475    // - The offset of the RuntimeVisibleAnnotations attribute, or 0.
476    int runtimeVisibleAnnotationsOffset = 0;
477    // - The offset of the RuntimeInvisibleAnnotations attribute, or 0.
478    int runtimeInvisibleAnnotationsOffset = 0;
479    // - The offset of the RuntimeVisibleTypeAnnotations attribute, or 0.
480    int runtimeVisibleTypeAnnotationsOffset = 0;
481    // - The offset of the RuntimeInvisibleTypeAnnotations attribute, or 0.
482    int runtimeInvisibleTypeAnnotationsOffset = 0;
483    // - The offset of the Module attribute, or 0.
484    int moduleOffset = 0;
485    // - The offset of the ModulePackages attribute, or 0.
486    int modulePackagesOffset = 0;
487    // - The string corresponding to the ModuleMainClass attribute, or null.
488    String moduleMainClass = null;
489    // - The string corresponding to the NestHost attribute, or null.
490    String nestHostClass = null;
491    // - The offset of the NestMembers attribute, or 0.
492    int nestMembersOffset = 0;
493    // - The offset of the PermittedSubclasses attribute, or 0
494    int permittedSubclassesOffset = 0;
495    // - The offset of the Record attribute, or 0.
496    int recordOffset = 0;
497    // - The non standard attributes (linked with their {@link Attribute#nextAttribute} field).
498    //   This list in the <i>reverse order</i> or their order in the ClassFile structure.
499    Attribute attributes = null;
500
501    int currentAttributeOffset = getFirstAttributeOffset();
502    for (int i = readUnsignedShort(currentAttributeOffset - 2); i > 0; --i) {
503      // Read the attribute_info's attribute_name and attribute_length fields.
504      String attributeName = readUTF8(currentAttributeOffset, charBuffer);
505      int attributeLength = readInt(currentAttributeOffset + 2);
506      currentAttributeOffset += 6;
507      // The tests are sorted in decreasing frequency order (based on frequencies observed on
508      // typical classes).
509      if (Constants.SOURCE_FILE.equals(attributeName)) {
510        sourceFile = readUTF8(currentAttributeOffset, charBuffer);
511      } else if (Constants.INNER_CLASSES.equals(attributeName)) {
512        innerClassesOffset = currentAttributeOffset;
513      } else if (Constants.ENCLOSING_METHOD.equals(attributeName)) {
514        enclosingMethodOffset = currentAttributeOffset;
515      } else if (Constants.NEST_HOST.equals(attributeName)) {
516        nestHostClass = readClass(currentAttributeOffset, charBuffer);
517      } else if (Constants.NEST_MEMBERS.equals(attributeName)) {
518        nestMembersOffset = currentAttributeOffset;
519      } else if (Constants.PERMITTED_SUBCLASSES.equals(attributeName)) {
520        permittedSubclassesOffset = currentAttributeOffset;
521      } else if (Constants.SIGNATURE.equals(attributeName)) {
522        signature = readUTF8(currentAttributeOffset, charBuffer);
523      } else if (Constants.RUNTIME_VISIBLE_ANNOTATIONS.equals(attributeName)) {
524        runtimeVisibleAnnotationsOffset = currentAttributeOffset;
525      } else if (Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
526        runtimeVisibleTypeAnnotationsOffset = currentAttributeOffset;
527      } else if (Constants.DEPRECATED.equals(attributeName)) {
528        accessFlags |= Opcodes.ACC_DEPRECATED;
529      } else if (Constants.SYNTHETIC.equals(attributeName)) {
530        accessFlags |= Opcodes.ACC_SYNTHETIC;
531      } else if (Constants.SOURCE_DEBUG_EXTENSION.equals(attributeName)) {
532        if (attributeLength > classFileBuffer.length - currentAttributeOffset) {
533          throw new IllegalArgumentException();
534        }
535        sourceDebugExtension =
536            readUtf(currentAttributeOffset, attributeLength, new char[attributeLength]);
537      } else if (Constants.RUNTIME_INVISIBLE_ANNOTATIONS.equals(attributeName)) {
538        runtimeInvisibleAnnotationsOffset = currentAttributeOffset;
539      } else if (Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
540        runtimeInvisibleTypeAnnotationsOffset = currentAttributeOffset;
541      } else if (Constants.RECORD.equals(attributeName)) {
542        recordOffset = currentAttributeOffset;
543        accessFlags |= Opcodes.ACC_RECORD;
544      } else if (Constants.MODULE.equals(attributeName)) {
545        moduleOffset = currentAttributeOffset;
546      } else if (Constants.MODULE_MAIN_CLASS.equals(attributeName)) {
547        moduleMainClass = readClass(currentAttributeOffset, charBuffer);
548      } else if (Constants.MODULE_PACKAGES.equals(attributeName)) {
549        modulePackagesOffset = currentAttributeOffset;
550      } else if (!Constants.BOOTSTRAP_METHODS.equals(attributeName)) {
551        // The BootstrapMethods attribute is read in the constructor.
552        Attribute attribute =
553            readAttribute(
554                attributePrototypes,
555                attributeName,
556                currentAttributeOffset,
557                attributeLength,
558                charBuffer,
559                -1,
560                null);
561        attribute.nextAttribute = attributes;
562        attributes = attribute;
563      }
564      currentAttributeOffset += attributeLength;
565    }
566
567    // Visit the class declaration. The minor_version and major_version fields start 6 bytes before
568    // the first constant pool entry, which itself starts at cpInfoOffsets[1] - 1 (by definition).
569    classVisitor.visit(
570        readInt(cpInfoOffsets[1] - 7), accessFlags, thisClass, signature, superClass, interfaces);
571
572    // Visit the SourceFile and SourceDebugExtenstion attributes.
573    if ((parsingOptions & SKIP_DEBUG) == 0
574        && (sourceFile != null || sourceDebugExtension != null)) {
575      classVisitor.visitSource(sourceFile, sourceDebugExtension);
576    }
577
578    // Visit the Module, ModulePackages and ModuleMainClass attributes.
579    if (moduleOffset != 0) {
580      readModuleAttributes(
581          classVisitor, context, moduleOffset, modulePackagesOffset, moduleMainClass);
582    }
583
584    // Visit the NestHost attribute.
585    if (nestHostClass != null) {
586      classVisitor.visitNestHost(nestHostClass);
587    }
588
589    // Visit the EnclosingMethod attribute.
590    if (enclosingMethodOffset != 0) {
591      String className = readClass(enclosingMethodOffset, charBuffer);
592      int methodIndex = readUnsignedShort(enclosingMethodOffset + 2);
593      String name = methodIndex == 0 ? null : readUTF8(cpInfoOffsets[methodIndex], charBuffer);
594      String type = methodIndex == 0 ? null : readUTF8(cpInfoOffsets[methodIndex] + 2, charBuffer);
595      classVisitor.visitOuterClass(className, name, type);
596    }
597
598    // Visit the RuntimeVisibleAnnotations attribute.
599    if (runtimeVisibleAnnotationsOffset != 0) {
600      int numAnnotations = readUnsignedShort(runtimeVisibleAnnotationsOffset);
601      int currentAnnotationOffset = runtimeVisibleAnnotationsOffset + 2;
602      while (numAnnotations-- > 0) {
603        // Parse the type_index field.
604        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
605        currentAnnotationOffset += 2;
606        // Parse num_element_value_pairs and element_value_pairs and visit these values.
607        currentAnnotationOffset =
608            readElementValues(
609                classVisitor.visitAnnotation(annotationDescriptor, /* visible = */ true),
610                currentAnnotationOffset,
611                /* named = */ true,
612                charBuffer);
613      }
614    }
615
616    // Visit the RuntimeInvisibleAnnotations attribute.
617    if (runtimeInvisibleAnnotationsOffset != 0) {
618      int numAnnotations = readUnsignedShort(runtimeInvisibleAnnotationsOffset);
619      int currentAnnotationOffset = runtimeInvisibleAnnotationsOffset + 2;
620      while (numAnnotations-- > 0) {
621        // Parse the type_index field.
622        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
623        currentAnnotationOffset += 2;
624        // Parse num_element_value_pairs and element_value_pairs and visit these values.
625        currentAnnotationOffset =
626            readElementValues(
627                classVisitor.visitAnnotation(annotationDescriptor, /* visible = */ false),
628                currentAnnotationOffset,
629                /* named = */ true,
630                charBuffer);
631      }
632    }
633
634    // Visit the RuntimeVisibleTypeAnnotations attribute.
635    if (runtimeVisibleTypeAnnotationsOffset != 0) {
636      int numAnnotations = readUnsignedShort(runtimeVisibleTypeAnnotationsOffset);
637      int currentAnnotationOffset = runtimeVisibleTypeAnnotationsOffset + 2;
638      while (numAnnotations-- > 0) {
639        // Parse the target_type, target_info and target_path fields.
640        currentAnnotationOffset = readTypeAnnotationTarget(context, currentAnnotationOffset);
641        // Parse the type_index field.
642        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
643        currentAnnotationOffset += 2;
644        // Parse num_element_value_pairs and element_value_pairs and visit these values.
645        currentAnnotationOffset =
646            readElementValues(
647                classVisitor.visitTypeAnnotation(
648                    context.currentTypeAnnotationTarget,
649                    context.currentTypeAnnotationTargetPath,
650                    annotationDescriptor,
651                    /* visible = */ true),
652                currentAnnotationOffset,
653                /* named = */ true,
654                charBuffer);
655      }
656    }
657
658    // Visit the RuntimeInvisibleTypeAnnotations attribute.
659    if (runtimeInvisibleTypeAnnotationsOffset != 0) {
660      int numAnnotations = readUnsignedShort(runtimeInvisibleTypeAnnotationsOffset);
661      int currentAnnotationOffset = runtimeInvisibleTypeAnnotationsOffset + 2;
662      while (numAnnotations-- > 0) {
663        // Parse the target_type, target_info and target_path fields.
664        currentAnnotationOffset = readTypeAnnotationTarget(context, currentAnnotationOffset);
665        // Parse the type_index field.
666        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
667        currentAnnotationOffset += 2;
668        // Parse num_element_value_pairs and element_value_pairs and visit these values.
669        currentAnnotationOffset =
670            readElementValues(
671                classVisitor.visitTypeAnnotation(
672                    context.currentTypeAnnotationTarget,
673                    context.currentTypeAnnotationTargetPath,
674                    annotationDescriptor,
675                    /* visible = */ false),
676                currentAnnotationOffset,
677                /* named = */ true,
678                charBuffer);
679      }
680    }
681
682    // Visit the non standard attributes.
683    while (attributes != null) {
684      // Copy and reset the nextAttribute field so that it can also be used in ClassWriter.
685      Attribute nextAttribute = attributes.nextAttribute;
686      attributes.nextAttribute = null;
687      classVisitor.visitAttribute(attributes);
688      attributes = nextAttribute;
689    }
690
691    // Visit the NestedMembers attribute.
692    if (nestMembersOffset != 0) {
693      int numberOfNestMembers = readUnsignedShort(nestMembersOffset);
694      int currentNestMemberOffset = nestMembersOffset + 2;
695      while (numberOfNestMembers-- > 0) {
696        classVisitor.visitNestMember(readClass(currentNestMemberOffset, charBuffer));
697        currentNestMemberOffset += 2;
698      }
699    }
700
701    // Visit the PermittedSubclasses attribute.
702    if (permittedSubclassesOffset != 0) {
703      int numberOfPermittedSubclasses = readUnsignedShort(permittedSubclassesOffset);
704      int currentPermittedSubclassesOffset = permittedSubclassesOffset + 2;
705      while (numberOfPermittedSubclasses-- > 0) {
706        classVisitor.visitPermittedSubclass(
707            readClass(currentPermittedSubclassesOffset, charBuffer));
708        currentPermittedSubclassesOffset += 2;
709      }
710    }
711
712    // Visit the InnerClasses attribute.
713    if (innerClassesOffset != 0) {
714      int numberOfClasses = readUnsignedShort(innerClassesOffset);
715      int currentClassesOffset = innerClassesOffset + 2;
716      while (numberOfClasses-- > 0) {
717        classVisitor.visitInnerClass(
718            readClass(currentClassesOffset, charBuffer),
719            readClass(currentClassesOffset + 2, charBuffer),
720            readUTF8(currentClassesOffset + 4, charBuffer),
721            readUnsignedShort(currentClassesOffset + 6));
722        currentClassesOffset += 8;
723      }
724    }
725
726    // Visit Record components.
727    if (recordOffset != 0) {
728      int recordComponentsCount = readUnsignedShort(recordOffset);
729      recordOffset += 2;
730      while (recordComponentsCount-- > 0) {
731        recordOffset = readRecordComponent(classVisitor, context, recordOffset);
732      }
733    }
734
735    // Visit the fields and methods.
736    int fieldsCount = readUnsignedShort(currentOffset);
737    currentOffset += 2;
738    while (fieldsCount-- > 0) {
739      currentOffset = readField(classVisitor, context, currentOffset);
740    }
741    int methodsCount = readUnsignedShort(currentOffset);
742    currentOffset += 2;
743    while (methodsCount-- > 0) {
744      currentOffset = readMethod(classVisitor, context, currentOffset);
745    }
746
747    // Visit the end of the class.
748    classVisitor.visitEnd();
749  }
750
751  // ----------------------------------------------------------------------------------------------
752  // Methods to parse modules, fields and methods
753  // ----------------------------------------------------------------------------------------------
754
755  /**
756   * Reads the Module, ModulePackages and ModuleMainClass attributes and visit them.
757   *
758   * @param classVisitor the current class visitor
759   * @param context information about the class being parsed.
760   * @param moduleOffset the offset of the Module attribute (excluding the attribute_info's
761   *     attribute_name_index and attribute_length fields).
762   * @param modulePackagesOffset the offset of the ModulePackages attribute (excluding the
763   *     attribute_info's attribute_name_index and attribute_length fields), or 0.
764   * @param moduleMainClass the string corresponding to the ModuleMainClass attribute, or {@literal
765   *     null}.
766   */
767  private void readModuleAttributes(
768      final ClassVisitor classVisitor,
769      final Context context,
770      final int moduleOffset,
771      final int modulePackagesOffset,
772      final String moduleMainClass) {
773    char[] buffer = context.charBuffer;
774
775    // Read the module_name_index, module_flags and module_version_index fields and visit them.
776    int currentOffset = moduleOffset;
777    String moduleName = readModule(currentOffset, buffer);
778    int moduleFlags = readUnsignedShort(currentOffset + 2);
779    String moduleVersion = readUTF8(currentOffset + 4, buffer);
780    currentOffset += 6;
781    ModuleVisitor moduleVisitor = classVisitor.visitModule(moduleName, moduleFlags, moduleVersion);
782    if (moduleVisitor == null) {
783      return;
784    }
785
786    // Visit the ModuleMainClass attribute.
787    if (moduleMainClass != null) {
788      moduleVisitor.visitMainClass(moduleMainClass);
789    }
790
791    // Visit the ModulePackages attribute.
792    if (modulePackagesOffset != 0) {
793      int packageCount = readUnsignedShort(modulePackagesOffset);
794      int currentPackageOffset = modulePackagesOffset + 2;
795      while (packageCount-- > 0) {
796        moduleVisitor.visitPackage(readPackage(currentPackageOffset, buffer));
797        currentPackageOffset += 2;
798      }
799    }
800
801    // Read the 'requires_count' and 'requires' fields.
802    int requiresCount = readUnsignedShort(currentOffset);
803    currentOffset += 2;
804    while (requiresCount-- > 0) {
805      // Read the requires_index, requires_flags and requires_version fields and visit them.
806      String requires = readModule(currentOffset, buffer);
807      int requiresFlags = readUnsignedShort(currentOffset + 2);
808      String requiresVersion = readUTF8(currentOffset + 4, buffer);
809      currentOffset += 6;
810      moduleVisitor.visitRequire(requires, requiresFlags, requiresVersion);
811    }
812
813    // Read the 'exports_count' and 'exports' fields.
814    int exportsCount = readUnsignedShort(currentOffset);
815    currentOffset += 2;
816    while (exportsCount-- > 0) {
817      // Read the exports_index, exports_flags, exports_to_count and exports_to_index fields
818      // and visit them.
819      String exports = readPackage(currentOffset, buffer);
820      int exportsFlags = readUnsignedShort(currentOffset + 2);
821      int exportsToCount = readUnsignedShort(currentOffset + 4);
822      currentOffset += 6;
823      String[] exportsTo = null;
824      if (exportsToCount != 0) {
825        exportsTo = new String[exportsToCount];
826        for (int i = 0; i < exportsToCount; ++i) {
827          exportsTo[i] = readModule(currentOffset, buffer);
828          currentOffset += 2;
829        }
830      }
831      moduleVisitor.visitExport(exports, exportsFlags, exportsTo);
832    }
833
834    // Reads the 'opens_count' and 'opens' fields.
835    int opensCount = readUnsignedShort(currentOffset);
836    currentOffset += 2;
837    while (opensCount-- > 0) {
838      // Read the opens_index, opens_flags, opens_to_count and opens_to_index fields and visit them.
839      String opens = readPackage(currentOffset, buffer);
840      int opensFlags = readUnsignedShort(currentOffset + 2);
841      int opensToCount = readUnsignedShort(currentOffset + 4);
842      currentOffset += 6;
843      String[] opensTo = null;
844      if (opensToCount != 0) {
845        opensTo = new String[opensToCount];
846        for (int i = 0; i < opensToCount; ++i) {
847          opensTo[i] = readModule(currentOffset, buffer);
848          currentOffset += 2;
849        }
850      }
851      moduleVisitor.visitOpen(opens, opensFlags, opensTo);
852    }
853
854    // Read the 'uses_count' and 'uses' fields.
855    int usesCount = readUnsignedShort(currentOffset);
856    currentOffset += 2;
857    while (usesCount-- > 0) {
858      moduleVisitor.visitUse(readClass(currentOffset, buffer));
859      currentOffset += 2;
860    }
861
862    // Read the 'provides_count' and 'provides' fields.
863    int providesCount = readUnsignedShort(currentOffset);
864    currentOffset += 2;
865    while (providesCount-- > 0) {
866      // Read the provides_index, provides_with_count and provides_with_index fields and visit them.
867      String provides = readClass(currentOffset, buffer);
868      int providesWithCount = readUnsignedShort(currentOffset + 2);
869      currentOffset += 4;
870      String[] providesWith = new String[providesWithCount];
871      for (int i = 0; i < providesWithCount; ++i) {
872        providesWith[i] = readClass(currentOffset, buffer);
873        currentOffset += 2;
874      }
875      moduleVisitor.visitProvide(provides, providesWith);
876    }
877
878    // Visit the end of the module attributes.
879    moduleVisitor.visitEnd();
880  }
881
882  /**
883   * Reads a record component and visit it.
884   *
885   * @param classVisitor the current class visitor
886   * @param context information about the class being parsed.
887   * @param recordComponentOffset the offset of the current record component.
888   * @return the offset of the first byte following the record component.
889   */
890  private int readRecordComponent(
891      final ClassVisitor classVisitor, final Context context, final int recordComponentOffset) {
892    char[] charBuffer = context.charBuffer;
893
894    int currentOffset = recordComponentOffset;
895    String name = readUTF8(currentOffset, charBuffer);
896    String descriptor = readUTF8(currentOffset + 2, charBuffer);
897    currentOffset += 4;
898
899    // Read the record component attributes (the variables are ordered as in Section 4.7 of the
900    // JVMS).
901
902    // Attribute offsets exclude the attribute_name_index and attribute_length fields.
903    // - The string corresponding to the Signature attribute, or null.
904    String signature = null;
905    // - The offset of the RuntimeVisibleAnnotations attribute, or 0.
906    int runtimeVisibleAnnotationsOffset = 0;
907    // - The offset of the RuntimeInvisibleAnnotations attribute, or 0.
908    int runtimeInvisibleAnnotationsOffset = 0;
909    // - The offset of the RuntimeVisibleTypeAnnotations attribute, or 0.
910    int runtimeVisibleTypeAnnotationsOffset = 0;
911    // - The offset of the RuntimeInvisibleTypeAnnotations attribute, or 0.
912    int runtimeInvisibleTypeAnnotationsOffset = 0;
913    // - The non standard attributes (linked with their {@link Attribute#nextAttribute} field).
914    //   This list in the <i>reverse order</i> or their order in the ClassFile structure.
915    Attribute attributes = null;
916
917    int attributesCount = readUnsignedShort(currentOffset);
918    currentOffset += 2;
919    while (attributesCount-- > 0) {
920      // Read the attribute_info's attribute_name and attribute_length fields.
921      String attributeName = readUTF8(currentOffset, charBuffer);
922      int attributeLength = readInt(currentOffset + 2);
923      currentOffset += 6;
924      // The tests are sorted in decreasing frequency order (based on frequencies observed on
925      // typical classes).
926      if (Constants.SIGNATURE.equals(attributeName)) {
927        signature = readUTF8(currentOffset, charBuffer);
928      } else if (Constants.RUNTIME_VISIBLE_ANNOTATIONS.equals(attributeName)) {
929        runtimeVisibleAnnotationsOffset = currentOffset;
930      } else if (Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
931        runtimeVisibleTypeAnnotationsOffset = currentOffset;
932      } else if (Constants.RUNTIME_INVISIBLE_ANNOTATIONS.equals(attributeName)) {
933        runtimeInvisibleAnnotationsOffset = currentOffset;
934      } else if (Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
935        runtimeInvisibleTypeAnnotationsOffset = currentOffset;
936      } else {
937        Attribute attribute =
938            readAttribute(
939                context.attributePrototypes,
940                attributeName,
941                currentOffset,
942                attributeLength,
943                charBuffer,
944                -1,
945                null);
946        attribute.nextAttribute = attributes;
947        attributes = attribute;
948      }
949      currentOffset += attributeLength;
950    }
951
952    RecordComponentVisitor recordComponentVisitor =
953        classVisitor.visitRecordComponent(name, descriptor, signature);
954    if (recordComponentVisitor == null) {
955      return currentOffset;
956    }
957
958    // Visit the RuntimeVisibleAnnotations attribute.
959    if (runtimeVisibleAnnotationsOffset != 0) {
960      int numAnnotations = readUnsignedShort(runtimeVisibleAnnotationsOffset);
961      int currentAnnotationOffset = runtimeVisibleAnnotationsOffset + 2;
962      while (numAnnotations-- > 0) {
963        // Parse the type_index field.
964        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
965        currentAnnotationOffset += 2;
966        // Parse num_element_value_pairs and element_value_pairs and visit these values.
967        currentAnnotationOffset =
968            readElementValues(
969                recordComponentVisitor.visitAnnotation(annotationDescriptor, /* visible = */ true),
970                currentAnnotationOffset,
971                /* named = */ true,
972                charBuffer);
973      }
974    }
975
976    // Visit the RuntimeInvisibleAnnotations attribute.
977    if (runtimeInvisibleAnnotationsOffset != 0) {
978      int numAnnotations = readUnsignedShort(runtimeInvisibleAnnotationsOffset);
979      int currentAnnotationOffset = runtimeInvisibleAnnotationsOffset + 2;
980      while (numAnnotations-- > 0) {
981        // Parse the type_index field.
982        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
983        currentAnnotationOffset += 2;
984        // Parse num_element_value_pairs and element_value_pairs and visit these values.
985        currentAnnotationOffset =
986            readElementValues(
987                recordComponentVisitor.visitAnnotation(annotationDescriptor, /* visible = */ false),
988                currentAnnotationOffset,
989                /* named = */ true,
990                charBuffer);
991      }
992    }
993
994    // Visit the RuntimeVisibleTypeAnnotations attribute.
995    if (runtimeVisibleTypeAnnotationsOffset != 0) {
996      int numAnnotations = readUnsignedShort(runtimeVisibleTypeAnnotationsOffset);
997      int currentAnnotationOffset = runtimeVisibleTypeAnnotationsOffset + 2;
998      while (numAnnotations-- > 0) {
999        // Parse the target_type, target_info and target_path fields.
1000        currentAnnotationOffset = readTypeAnnotationTarget(context, currentAnnotationOffset);
1001        // Parse the type_index field.
1002        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
1003        currentAnnotationOffset += 2;
1004        // Parse num_element_value_pairs and element_value_pairs and visit these values.
1005        currentAnnotationOffset =
1006            readElementValues(
1007                recordComponentVisitor.visitTypeAnnotation(
1008                    context.currentTypeAnnotationTarget,
1009                    context.currentTypeAnnotationTargetPath,
1010                    annotationDescriptor,
1011                    /* visible = */ true),
1012                currentAnnotationOffset,
1013                /* named = */ true,
1014                charBuffer);
1015      }
1016    }
1017
1018    // Visit the RuntimeInvisibleTypeAnnotations attribute.
1019    if (runtimeInvisibleTypeAnnotationsOffset != 0) {
1020      int numAnnotations = readUnsignedShort(runtimeInvisibleTypeAnnotationsOffset);
1021      int currentAnnotationOffset = runtimeInvisibleTypeAnnotationsOffset + 2;
1022      while (numAnnotations-- > 0) {
1023        // Parse the target_type, target_info and target_path fields.
1024        currentAnnotationOffset = readTypeAnnotationTarget(context, currentAnnotationOffset);
1025        // Parse the type_index field.
1026        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
1027        currentAnnotationOffset += 2;
1028        // Parse num_element_value_pairs and element_value_pairs and visit these values.
1029        currentAnnotationOffset =
1030            readElementValues(
1031                recordComponentVisitor.visitTypeAnnotation(
1032                    context.currentTypeAnnotationTarget,
1033                    context.currentTypeAnnotationTargetPath,
1034                    annotationDescriptor,
1035                    /* visible = */ false),
1036                currentAnnotationOffset,
1037                /* named = */ true,
1038                charBuffer);
1039      }
1040    }
1041
1042    // Visit the non standard attributes.
1043    while (attributes != null) {
1044      // Copy and reset the nextAttribute field so that it can also be used in FieldWriter.
1045      Attribute nextAttribute = attributes.nextAttribute;
1046      attributes.nextAttribute = null;
1047      recordComponentVisitor.visitAttribute(attributes);
1048      attributes = nextAttribute;
1049    }
1050
1051    // Visit the end of the field.
1052    recordComponentVisitor.visitEnd();
1053    return currentOffset;
1054  }
1055
1056  /**
1057   * Reads a JVMS field_info structure and makes the given visitor visit it.
1058   *
1059   * @param classVisitor the visitor that must visit the field.
1060   * @param context information about the class being parsed.
1061   * @param fieldInfoOffset the start offset of the field_info structure.
1062   * @return the offset of the first byte following the field_info structure.
1063   */
1064  private int readField(
1065      final ClassVisitor classVisitor, final Context context, final int fieldInfoOffset) {
1066    char[] charBuffer = context.charBuffer;
1067
1068    // Read the access_flags, name_index and descriptor_index fields.
1069    int currentOffset = fieldInfoOffset;
1070    int accessFlags = readUnsignedShort(currentOffset);
1071    String name = readUTF8(currentOffset + 2, charBuffer);
1072    String descriptor = readUTF8(currentOffset + 4, charBuffer);
1073    currentOffset += 6;
1074
1075    // Read the field attributes (the variables are ordered as in Section 4.7 of the JVMS).
1076    // Attribute offsets exclude the attribute_name_index and attribute_length fields.
1077    // - The value corresponding to the ConstantValue attribute, or null.
1078    Object constantValue = null;
1079    // - The string corresponding to the Signature attribute, or null.
1080    String signature = null;
1081    // - The offset of the RuntimeVisibleAnnotations attribute, or 0.
1082    int runtimeVisibleAnnotationsOffset = 0;
1083    // - The offset of the RuntimeInvisibleAnnotations attribute, or 0.
1084    int runtimeInvisibleAnnotationsOffset = 0;
1085    // - The offset of the RuntimeVisibleTypeAnnotations attribute, or 0.
1086    int runtimeVisibleTypeAnnotationsOffset = 0;
1087    // - The offset of the RuntimeInvisibleTypeAnnotations attribute, or 0.
1088    int runtimeInvisibleTypeAnnotationsOffset = 0;
1089    // - The non standard attributes (linked with their {@link Attribute#nextAttribute} field).
1090    //   This list in the <i>reverse order</i> or their order in the ClassFile structure.
1091    Attribute attributes = null;
1092
1093    int attributesCount = readUnsignedShort(currentOffset);
1094    currentOffset += 2;
1095    while (attributesCount-- > 0) {
1096      // Read the attribute_info's attribute_name and attribute_length fields.
1097      String attributeName = readUTF8(currentOffset, charBuffer);
1098      int attributeLength = readInt(currentOffset + 2);
1099      currentOffset += 6;
1100      // The tests are sorted in decreasing frequency order (based on frequencies observed on
1101      // typical classes).
1102      if (Constants.CONSTANT_VALUE.equals(attributeName)) {
1103        int constantvalueIndex = readUnsignedShort(currentOffset);
1104        constantValue = constantvalueIndex == 0 ? null : readConst(constantvalueIndex, charBuffer);
1105      } else if (Constants.SIGNATURE.equals(attributeName)) {
1106        signature = readUTF8(currentOffset, charBuffer);
1107      } else if (Constants.DEPRECATED.equals(attributeName)) {
1108        accessFlags |= Opcodes.ACC_DEPRECATED;
1109      } else if (Constants.SYNTHETIC.equals(attributeName)) {
1110        accessFlags |= Opcodes.ACC_SYNTHETIC;
1111      } else if (Constants.RUNTIME_VISIBLE_ANNOTATIONS.equals(attributeName)) {
1112        runtimeVisibleAnnotationsOffset = currentOffset;
1113      } else if (Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
1114        runtimeVisibleTypeAnnotationsOffset = currentOffset;
1115      } else if (Constants.RUNTIME_INVISIBLE_ANNOTATIONS.equals(attributeName)) {
1116        runtimeInvisibleAnnotationsOffset = currentOffset;
1117      } else if (Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
1118        runtimeInvisibleTypeAnnotationsOffset = currentOffset;
1119      } else {
1120        Attribute attribute =
1121            readAttribute(
1122                context.attributePrototypes,
1123                attributeName,
1124                currentOffset,
1125                attributeLength,
1126                charBuffer,
1127                -1,
1128                null);
1129        attribute.nextAttribute = attributes;
1130        attributes = attribute;
1131      }
1132      currentOffset += attributeLength;
1133    }
1134
1135    // Visit the field declaration.
1136    FieldVisitor fieldVisitor =
1137        classVisitor.visitField(accessFlags, name, descriptor, signature, constantValue);
1138    if (fieldVisitor == null) {
1139      return currentOffset;
1140    }
1141
1142    // Visit the RuntimeVisibleAnnotations attribute.
1143    if (runtimeVisibleAnnotationsOffset != 0) {
1144      int numAnnotations = readUnsignedShort(runtimeVisibleAnnotationsOffset);
1145      int currentAnnotationOffset = runtimeVisibleAnnotationsOffset + 2;
1146      while (numAnnotations-- > 0) {
1147        // Parse the type_index field.
1148        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
1149        currentAnnotationOffset += 2;
1150        // Parse num_element_value_pairs and element_value_pairs and visit these values.
1151        currentAnnotationOffset =
1152            readElementValues(
1153                fieldVisitor.visitAnnotation(annotationDescriptor, /* visible = */ true),
1154                currentAnnotationOffset,
1155                /* named = */ true,
1156                charBuffer);
1157      }
1158    }
1159
1160    // Visit the RuntimeInvisibleAnnotations attribute.
1161    if (runtimeInvisibleAnnotationsOffset != 0) {
1162      int numAnnotations = readUnsignedShort(runtimeInvisibleAnnotationsOffset);
1163      int currentAnnotationOffset = runtimeInvisibleAnnotationsOffset + 2;
1164      while (numAnnotations-- > 0) {
1165        // Parse the type_index field.
1166        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
1167        currentAnnotationOffset += 2;
1168        // Parse num_element_value_pairs and element_value_pairs and visit these values.
1169        currentAnnotationOffset =
1170            readElementValues(
1171                fieldVisitor.visitAnnotation(annotationDescriptor, /* visible = */ false),
1172                currentAnnotationOffset,
1173                /* named = */ true,
1174                charBuffer);
1175      }
1176    }
1177
1178    // Visit the RuntimeVisibleTypeAnnotations attribute.
1179    if (runtimeVisibleTypeAnnotationsOffset != 0) {
1180      int numAnnotations = readUnsignedShort(runtimeVisibleTypeAnnotationsOffset);
1181      int currentAnnotationOffset = runtimeVisibleTypeAnnotationsOffset + 2;
1182      while (numAnnotations-- > 0) {
1183        // Parse the target_type, target_info and target_path fields.
1184        currentAnnotationOffset = readTypeAnnotationTarget(context, currentAnnotationOffset);
1185        // Parse the type_index field.
1186        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
1187        currentAnnotationOffset += 2;
1188        // Parse num_element_value_pairs and element_value_pairs and visit these values.
1189        currentAnnotationOffset =
1190            readElementValues(
1191                fieldVisitor.visitTypeAnnotation(
1192                    context.currentTypeAnnotationTarget,
1193                    context.currentTypeAnnotationTargetPath,
1194                    annotationDescriptor,
1195                    /* visible = */ true),
1196                currentAnnotationOffset,
1197                /* named = */ true,
1198                charBuffer);
1199      }
1200    }
1201
1202    // Visit the RuntimeInvisibleTypeAnnotations attribute.
1203    if (runtimeInvisibleTypeAnnotationsOffset != 0) {
1204      int numAnnotations = readUnsignedShort(runtimeInvisibleTypeAnnotationsOffset);
1205      int currentAnnotationOffset = runtimeInvisibleTypeAnnotationsOffset + 2;
1206      while (numAnnotations-- > 0) {
1207        // Parse the target_type, target_info and target_path fields.
1208        currentAnnotationOffset = readTypeAnnotationTarget(context, currentAnnotationOffset);
1209        // Parse the type_index field.
1210        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
1211        currentAnnotationOffset += 2;
1212        // Parse num_element_value_pairs and element_value_pairs and visit these values.
1213        currentAnnotationOffset =
1214            readElementValues(
1215                fieldVisitor.visitTypeAnnotation(
1216                    context.currentTypeAnnotationTarget,
1217                    context.currentTypeAnnotationTargetPath,
1218                    annotationDescriptor,
1219                    /* visible = */ false),
1220                currentAnnotationOffset,
1221                /* named = */ true,
1222                charBuffer);
1223      }
1224    }
1225
1226    // Visit the non standard attributes.
1227    while (attributes != null) {
1228      // Copy and reset the nextAttribute field so that it can also be used in FieldWriter.
1229      Attribute nextAttribute = attributes.nextAttribute;
1230      attributes.nextAttribute = null;
1231      fieldVisitor.visitAttribute(attributes);
1232      attributes = nextAttribute;
1233    }
1234
1235    // Visit the end of the field.
1236    fieldVisitor.visitEnd();
1237    return currentOffset;
1238  }
1239
1240  /**
1241   * Reads a JVMS method_info structure and makes the given visitor visit it.
1242   *
1243   * @param classVisitor the visitor that must visit the method.
1244   * @param context information about the class being parsed.
1245   * @param methodInfoOffset the start offset of the method_info structure.
1246   * @return the offset of the first byte following the method_info structure.
1247   */
1248  private int readMethod(
1249      final ClassVisitor classVisitor, final Context context, final int methodInfoOffset) {
1250    char[] charBuffer = context.charBuffer;
1251
1252    // Read the access_flags, name_index and descriptor_index fields.
1253    int currentOffset = methodInfoOffset;
1254    context.currentMethodAccessFlags = readUnsignedShort(currentOffset);
1255    context.currentMethodName = readUTF8(currentOffset + 2, charBuffer);
1256    context.currentMethodDescriptor = readUTF8(currentOffset + 4, charBuffer);
1257    currentOffset += 6;
1258
1259    // Read the method attributes (the variables are ordered as in Section 4.7 of the JVMS).
1260    // Attribute offsets exclude the attribute_name_index and attribute_length fields.
1261    // - The offset of the Code attribute, or 0.
1262    int codeOffset = 0;
1263    // - The offset of the Exceptions attribute, or 0.
1264    int exceptionsOffset = 0;
1265    // - The strings corresponding to the Exceptions attribute, or null.
1266    String[] exceptions = null;
1267    // - Whether the method has a Synthetic attribute.
1268    boolean synthetic = false;
1269    // - The constant pool index contained in the Signature attribute, or 0.
1270    int signatureIndex = 0;
1271    // - The offset of the RuntimeVisibleAnnotations attribute, or 0.
1272    int runtimeVisibleAnnotationsOffset = 0;
1273    // - The offset of the RuntimeInvisibleAnnotations attribute, or 0.
1274    int runtimeInvisibleAnnotationsOffset = 0;
1275    // - The offset of the RuntimeVisibleParameterAnnotations attribute, or 0.
1276    int runtimeVisibleParameterAnnotationsOffset = 0;
1277    // - The offset of the RuntimeInvisibleParameterAnnotations attribute, or 0.
1278    int runtimeInvisibleParameterAnnotationsOffset = 0;
1279    // - The offset of the RuntimeVisibleTypeAnnotations attribute, or 0.
1280    int runtimeVisibleTypeAnnotationsOffset = 0;
1281    // - The offset of the RuntimeInvisibleTypeAnnotations attribute, or 0.
1282    int runtimeInvisibleTypeAnnotationsOffset = 0;
1283    // - The offset of the AnnotationDefault attribute, or 0.
1284    int annotationDefaultOffset = 0;
1285    // - The offset of the MethodParameters attribute, or 0.
1286    int methodParametersOffset = 0;
1287    // - The non standard attributes (linked with their {@link Attribute#nextAttribute} field).
1288    //   This list in the <i>reverse order</i> or their order in the ClassFile structure.
1289    Attribute attributes = null;
1290
1291    int attributesCount = readUnsignedShort(currentOffset);
1292    currentOffset += 2;
1293    while (attributesCount-- > 0) {
1294      // Read the attribute_info's attribute_name and attribute_length fields.
1295      String attributeName = readUTF8(currentOffset, charBuffer);
1296      int attributeLength = readInt(currentOffset + 2);
1297      currentOffset += 6;
1298      // The tests are sorted in decreasing frequency order (based on frequencies observed on
1299      // typical classes).
1300      if (Constants.CODE.equals(attributeName)) {
1301        if ((context.parsingOptions & SKIP_CODE) == 0) {
1302          codeOffset = currentOffset;
1303        }
1304      } else if (Constants.EXCEPTIONS.equals(attributeName)) {
1305        exceptionsOffset = currentOffset;
1306        exceptions = new String[readUnsignedShort(exceptionsOffset)];
1307        int currentExceptionOffset = exceptionsOffset + 2;
1308        for (int i = 0; i < exceptions.length; ++i) {
1309          exceptions[i] = readClass(currentExceptionOffset, charBuffer);
1310          currentExceptionOffset += 2;
1311        }
1312      } else if (Constants.SIGNATURE.equals(attributeName)) {
1313        signatureIndex = readUnsignedShort(currentOffset);
1314      } else if (Constants.DEPRECATED.equals(attributeName)) {
1315        context.currentMethodAccessFlags |= Opcodes.ACC_DEPRECATED;
1316      } else if (Constants.RUNTIME_VISIBLE_ANNOTATIONS.equals(attributeName)) {
1317        runtimeVisibleAnnotationsOffset = currentOffset;
1318      } else if (Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
1319        runtimeVisibleTypeAnnotationsOffset = currentOffset;
1320      } else if (Constants.ANNOTATION_DEFAULT.equals(attributeName)) {
1321        annotationDefaultOffset = currentOffset;
1322      } else if (Constants.SYNTHETIC.equals(attributeName)) {
1323        synthetic = true;
1324        context.currentMethodAccessFlags |= Opcodes.ACC_SYNTHETIC;
1325      } else if (Constants.RUNTIME_INVISIBLE_ANNOTATIONS.equals(attributeName)) {
1326        runtimeInvisibleAnnotationsOffset = currentOffset;
1327      } else if (Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
1328        runtimeInvisibleTypeAnnotationsOffset = currentOffset;
1329      } else if (Constants.RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS.equals(attributeName)) {
1330        runtimeVisibleParameterAnnotationsOffset = currentOffset;
1331      } else if (Constants.RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS.equals(attributeName)) {
1332        runtimeInvisibleParameterAnnotationsOffset = currentOffset;
1333      } else if (Constants.METHOD_PARAMETERS.equals(attributeName)) {
1334        methodParametersOffset = currentOffset;
1335      } else {
1336        Attribute attribute =
1337            readAttribute(
1338                context.attributePrototypes,
1339                attributeName,
1340                currentOffset,
1341                attributeLength,
1342                charBuffer,
1343                -1,
1344                null);
1345        attribute.nextAttribute = attributes;
1346        attributes = attribute;
1347      }
1348      currentOffset += attributeLength;
1349    }
1350
1351    // Visit the method declaration.
1352    MethodVisitor methodVisitor =
1353        classVisitor.visitMethod(
1354            context.currentMethodAccessFlags,
1355            context.currentMethodName,
1356            context.currentMethodDescriptor,
1357            signatureIndex == 0 ? null : readUtf(signatureIndex, charBuffer),
1358            exceptions);
1359    if (methodVisitor == null) {
1360      return currentOffset;
1361    }
1362
1363    // If the returned MethodVisitor is in fact a MethodWriter, it means there is no method
1364    // adapter between the reader and the writer. In this case, it might be possible to copy
1365    // the method attributes directly into the writer. If so, return early without visiting
1366    // the content of these attributes.
1367    if (methodVisitor instanceof MethodWriter) {
1368      MethodWriter methodWriter = (MethodWriter) methodVisitor;
1369      if (methodWriter.canCopyMethodAttributes(
1370          this,
1371          synthetic,
1372          (context.currentMethodAccessFlags & Opcodes.ACC_DEPRECATED) != 0,
1373          readUnsignedShort(methodInfoOffset + 4),
1374          signatureIndex,
1375          exceptionsOffset)) {
1376        methodWriter.setMethodAttributesSource(methodInfoOffset, currentOffset - methodInfoOffset);
1377        return currentOffset;
1378      }
1379    }
1380
1381    // Visit the MethodParameters attribute.
1382    if (methodParametersOffset != 0 && (context.parsingOptions & SKIP_DEBUG) == 0) {
1383      int parametersCount = readByte(methodParametersOffset);
1384      int currentParameterOffset = methodParametersOffset + 1;
1385      while (parametersCount-- > 0) {
1386        // Read the name_index and access_flags fields and visit them.
1387        methodVisitor.visitParameter(
1388            readUTF8(currentParameterOffset, charBuffer),
1389            readUnsignedShort(currentParameterOffset + 2));
1390        currentParameterOffset += 4;
1391      }
1392    }
1393
1394    // Visit the AnnotationDefault attribute.
1395    if (annotationDefaultOffset != 0) {
1396      AnnotationVisitor annotationVisitor = methodVisitor.visitAnnotationDefault();
1397      readElementValue(annotationVisitor, annotationDefaultOffset, null, charBuffer);
1398      if (annotationVisitor != null) {
1399        annotationVisitor.visitEnd();
1400      }
1401    }
1402
1403    // Visit the RuntimeVisibleAnnotations attribute.
1404    if (runtimeVisibleAnnotationsOffset != 0) {
1405      int numAnnotations = readUnsignedShort(runtimeVisibleAnnotationsOffset);
1406      int currentAnnotationOffset = runtimeVisibleAnnotationsOffset + 2;
1407      while (numAnnotations-- > 0) {
1408        // Parse the type_index field.
1409        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
1410        currentAnnotationOffset += 2;
1411        // Parse num_element_value_pairs and element_value_pairs and visit these values.
1412        currentAnnotationOffset =
1413            readElementValues(
1414                methodVisitor.visitAnnotation(annotationDescriptor, /* visible = */ true),
1415                currentAnnotationOffset,
1416                /* named = */ true,
1417                charBuffer);
1418      }
1419    }
1420
1421    // Visit the RuntimeInvisibleAnnotations attribute.
1422    if (runtimeInvisibleAnnotationsOffset != 0) {
1423      int numAnnotations = readUnsignedShort(runtimeInvisibleAnnotationsOffset);
1424      int currentAnnotationOffset = runtimeInvisibleAnnotationsOffset + 2;
1425      while (numAnnotations-- > 0) {
1426        // Parse the type_index field.
1427        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
1428        currentAnnotationOffset += 2;
1429        // Parse num_element_value_pairs and element_value_pairs and visit these values.
1430        currentAnnotationOffset =
1431            readElementValues(
1432                methodVisitor.visitAnnotation(annotationDescriptor, /* visible = */ false),
1433                currentAnnotationOffset,
1434                /* named = */ true,
1435                charBuffer);
1436      }
1437    }
1438
1439    // Visit the RuntimeVisibleTypeAnnotations attribute.
1440    if (runtimeVisibleTypeAnnotationsOffset != 0) {
1441      int numAnnotations = readUnsignedShort(runtimeVisibleTypeAnnotationsOffset);
1442      int currentAnnotationOffset = runtimeVisibleTypeAnnotationsOffset + 2;
1443      while (numAnnotations-- > 0) {
1444        // Parse the target_type, target_info and target_path fields.
1445        currentAnnotationOffset = readTypeAnnotationTarget(context, currentAnnotationOffset);
1446        // Parse the type_index field.
1447        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
1448        currentAnnotationOffset += 2;
1449        // Parse num_element_value_pairs and element_value_pairs and visit these values.
1450        currentAnnotationOffset =
1451            readElementValues(
1452                methodVisitor.visitTypeAnnotation(
1453                    context.currentTypeAnnotationTarget,
1454                    context.currentTypeAnnotationTargetPath,
1455                    annotationDescriptor,
1456                    /* visible = */ true),
1457                currentAnnotationOffset,
1458                /* named = */ true,
1459                charBuffer);
1460      }
1461    }
1462
1463    // Visit the RuntimeInvisibleTypeAnnotations attribute.
1464    if (runtimeInvisibleTypeAnnotationsOffset != 0) {
1465      int numAnnotations = readUnsignedShort(runtimeInvisibleTypeAnnotationsOffset);
1466      int currentAnnotationOffset = runtimeInvisibleTypeAnnotationsOffset + 2;
1467      while (numAnnotations-- > 0) {
1468        // Parse the target_type, target_info and target_path fields.
1469        currentAnnotationOffset = readTypeAnnotationTarget(context, currentAnnotationOffset);
1470        // Parse the type_index field.
1471        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
1472        currentAnnotationOffset += 2;
1473        // Parse num_element_value_pairs and element_value_pairs and visit these values.
1474        currentAnnotationOffset =
1475            readElementValues(
1476                methodVisitor.visitTypeAnnotation(
1477                    context.currentTypeAnnotationTarget,
1478                    context.currentTypeAnnotationTargetPath,
1479                    annotationDescriptor,
1480                    /* visible = */ false),
1481                currentAnnotationOffset,
1482                /* named = */ true,
1483                charBuffer);
1484      }
1485    }
1486
1487    // Visit the RuntimeVisibleParameterAnnotations attribute.
1488    if (runtimeVisibleParameterAnnotationsOffset != 0) {
1489      readParameterAnnotations(
1490          methodVisitor, context, runtimeVisibleParameterAnnotationsOffset, /* visible = */ true);
1491    }
1492
1493    // Visit the RuntimeInvisibleParameterAnnotations attribute.
1494    if (runtimeInvisibleParameterAnnotationsOffset != 0) {
1495      readParameterAnnotations(
1496          methodVisitor,
1497          context,
1498          runtimeInvisibleParameterAnnotationsOffset,
1499          /* visible = */ false);
1500    }
1501
1502    // Visit the non standard attributes.
1503    while (attributes != null) {
1504      // Copy and reset the nextAttribute field so that it can also be used in MethodWriter.
1505      Attribute nextAttribute = attributes.nextAttribute;
1506      attributes.nextAttribute = null;
1507      methodVisitor.visitAttribute(attributes);
1508      attributes = nextAttribute;
1509    }
1510
1511    // Visit the Code attribute.
1512    if (codeOffset != 0) {
1513      methodVisitor.visitCode();
1514      readCode(methodVisitor, context, codeOffset);
1515    }
1516
1517    // Visit the end of the method.
1518    methodVisitor.visitEnd();
1519    return currentOffset;
1520  }
1521
1522  // ----------------------------------------------------------------------------------------------
1523  // Methods to parse a Code attribute
1524  // ----------------------------------------------------------------------------------------------
1525
1526  /**
1527   * Reads a JVMS 'Code' attribute and makes the given visitor visit it.
1528   *
1529   * @param methodVisitor the visitor that must visit the Code attribute.
1530   * @param context information about the class being parsed.
1531   * @param codeOffset the start offset in {@link #classFileBuffer} of the Code attribute, excluding
1532   *     its attribute_name_index and attribute_length fields.
1533   */
1534  private void readCode(
1535      final MethodVisitor methodVisitor, final Context context, final int codeOffset) {
1536    int currentOffset = codeOffset;
1537
1538    // Read the max_stack, max_locals and code_length fields.
1539    final byte[] classBuffer = classFileBuffer;
1540    final char[] charBuffer = context.charBuffer;
1541    final int maxStack = readUnsignedShort(currentOffset);
1542    final int maxLocals = readUnsignedShort(currentOffset + 2);
1543    final int codeLength = readInt(currentOffset + 4);
1544    currentOffset += 8;
1545    if (codeLength > classFileBuffer.length - currentOffset) {
1546      throw new IllegalArgumentException();
1547    }
1548
1549    // Read the bytecode 'code' array to create a label for each referenced instruction.
1550    final int bytecodeStartOffset = currentOffset;
1551    final int bytecodeEndOffset = currentOffset + codeLength;
1552    final Label[] labels = context.currentMethodLabels = new Label[codeLength + 1];
1553    while (currentOffset < bytecodeEndOffset) {
1554      final int bytecodeOffset = currentOffset - bytecodeStartOffset;
1555      final int opcode = classBuffer[currentOffset] & 0xFF;
1556      switch (opcode) {
1557        case Opcodes.NOP:
1558        case Opcodes.ACONST_NULL:
1559        case Opcodes.ICONST_M1:
1560        case Opcodes.ICONST_0:
1561        case Opcodes.ICONST_1:
1562        case Opcodes.ICONST_2:
1563        case Opcodes.ICONST_3:
1564        case Opcodes.ICONST_4:
1565        case Opcodes.ICONST_5:
1566        case Opcodes.LCONST_0:
1567        case Opcodes.LCONST_1:
1568        case Opcodes.FCONST_0:
1569        case Opcodes.FCONST_1:
1570        case Opcodes.FCONST_2:
1571        case Opcodes.DCONST_0:
1572        case Opcodes.DCONST_1:
1573        case Opcodes.IALOAD:
1574        case Opcodes.LALOAD:
1575        case Opcodes.FALOAD:
1576        case Opcodes.DALOAD:
1577        case Opcodes.AALOAD:
1578        case Opcodes.BALOAD:
1579        case Opcodes.CALOAD:
1580        case Opcodes.SALOAD:
1581        case Opcodes.IASTORE:
1582        case Opcodes.LASTORE:
1583        case Opcodes.FASTORE:
1584        case Opcodes.DASTORE:
1585        case Opcodes.AASTORE:
1586        case Opcodes.BASTORE:
1587        case Opcodes.CASTORE:
1588        case Opcodes.SASTORE:
1589        case Opcodes.POP:
1590        case Opcodes.POP2:
1591        case Opcodes.DUP:
1592        case Opcodes.DUP_X1:
1593        case Opcodes.DUP_X2:
1594        case Opcodes.DUP2:
1595        case Opcodes.DUP2_X1:
1596        case Opcodes.DUP2_X2:
1597        case Opcodes.SWAP:
1598        case Opcodes.IADD:
1599        case Opcodes.LADD:
1600        case Opcodes.FADD:
1601        case Opcodes.DADD:
1602        case Opcodes.ISUB:
1603        case Opcodes.LSUB:
1604        case Opcodes.FSUB:
1605        case Opcodes.DSUB:
1606        case Opcodes.IMUL:
1607        case Opcodes.LMUL:
1608        case Opcodes.FMUL:
1609        case Opcodes.DMUL:
1610        case Opcodes.IDIV:
1611        case Opcodes.LDIV:
1612        case Opcodes.FDIV:
1613        case Opcodes.DDIV:
1614        case Opcodes.IREM:
1615        case Opcodes.LREM:
1616        case Opcodes.FREM:
1617        case Opcodes.DREM:
1618        case Opcodes.INEG:
1619        case Opcodes.LNEG:
1620        case Opcodes.FNEG:
1621        case Opcodes.DNEG:
1622        case Opcodes.ISHL:
1623        case Opcodes.LSHL:
1624        case Opcodes.ISHR:
1625        case Opcodes.LSHR:
1626        case Opcodes.IUSHR:
1627        case Opcodes.LUSHR:
1628        case Opcodes.IAND:
1629        case Opcodes.LAND:
1630        case Opcodes.IOR:
1631        case Opcodes.LOR:
1632        case Opcodes.IXOR:
1633        case Opcodes.LXOR:
1634        case Opcodes.I2L:
1635        case Opcodes.I2F:
1636        case Opcodes.I2D:
1637        case Opcodes.L2I:
1638        case Opcodes.L2F:
1639        case Opcodes.L2D:
1640        case Opcodes.F2I:
1641        case Opcodes.F2L:
1642        case Opcodes.F2D:
1643        case Opcodes.D2I:
1644        case Opcodes.D2L:
1645        case Opcodes.D2F:
1646        case Opcodes.I2B:
1647        case Opcodes.I2C:
1648        case Opcodes.I2S:
1649        case Opcodes.LCMP:
1650        case Opcodes.FCMPL:
1651        case Opcodes.FCMPG:
1652        case Opcodes.DCMPL:
1653        case Opcodes.DCMPG:
1654        case Opcodes.IRETURN:
1655        case Opcodes.LRETURN:
1656        case Opcodes.FRETURN:
1657        case Opcodes.DRETURN:
1658        case Opcodes.ARETURN:
1659        case Opcodes.RETURN:
1660        case Opcodes.ARRAYLENGTH:
1661        case Opcodes.ATHROW:
1662        case Opcodes.MONITORENTER:
1663        case Opcodes.MONITOREXIT:
1664        case Constants.ILOAD_0:
1665        case Constants.ILOAD_1:
1666        case Constants.ILOAD_2:
1667        case Constants.ILOAD_3:
1668        case Constants.LLOAD_0:
1669        case Constants.LLOAD_1:
1670        case Constants.LLOAD_2:
1671        case Constants.LLOAD_3:
1672        case Constants.FLOAD_0:
1673        case Constants.FLOAD_1:
1674        case Constants.FLOAD_2:
1675        case Constants.FLOAD_3:
1676        case Constants.DLOAD_0:
1677        case Constants.DLOAD_1:
1678        case Constants.DLOAD_2:
1679        case Constants.DLOAD_3:
1680        case Constants.ALOAD_0:
1681        case Constants.ALOAD_1:
1682        case Constants.ALOAD_2:
1683        case Constants.ALOAD_3:
1684        case Constants.ISTORE_0:
1685        case Constants.ISTORE_1:
1686        case Constants.ISTORE_2:
1687        case Constants.ISTORE_3:
1688        case Constants.LSTORE_0:
1689        case Constants.LSTORE_1:
1690        case Constants.LSTORE_2:
1691        case Constants.LSTORE_3:
1692        case Constants.FSTORE_0:
1693        case Constants.FSTORE_1:
1694        case Constants.FSTORE_2:
1695        case Constants.FSTORE_3:
1696        case Constants.DSTORE_0:
1697        case Constants.DSTORE_1:
1698        case Constants.DSTORE_2:
1699        case Constants.DSTORE_3:
1700        case Constants.ASTORE_0:
1701        case Constants.ASTORE_1:
1702        case Constants.ASTORE_2:
1703        case Constants.ASTORE_3:
1704          currentOffset += 1;
1705          break;
1706        case Opcodes.IFEQ:
1707        case Opcodes.IFNE:
1708        case Opcodes.IFLT:
1709        case Opcodes.IFGE:
1710        case Opcodes.IFGT:
1711        case Opcodes.IFLE:
1712        case Opcodes.IF_ICMPEQ:
1713        case Opcodes.IF_ICMPNE:
1714        case Opcodes.IF_ICMPLT:
1715        case Opcodes.IF_ICMPGE:
1716        case Opcodes.IF_ICMPGT:
1717        case Opcodes.IF_ICMPLE:
1718        case Opcodes.IF_ACMPEQ:
1719        case Opcodes.IF_ACMPNE:
1720        case Opcodes.GOTO:
1721        case Opcodes.JSR:
1722        case Opcodes.IFNULL:
1723        case Opcodes.IFNONNULL:
1724          createLabel(bytecodeOffset + readShort(currentOffset + 1), labels);
1725          currentOffset += 3;
1726          break;
1727        case Constants.ASM_IFEQ:
1728        case Constants.ASM_IFNE:
1729        case Constants.ASM_IFLT:
1730        case Constants.ASM_IFGE:
1731        case Constants.ASM_IFGT:
1732        case Constants.ASM_IFLE:
1733        case Constants.ASM_IF_ICMPEQ:
1734        case Constants.ASM_IF_ICMPNE:
1735        case Constants.ASM_IF_ICMPLT:
1736        case Constants.ASM_IF_ICMPGE:
1737        case Constants.ASM_IF_ICMPGT:
1738        case Constants.ASM_IF_ICMPLE:
1739        case Constants.ASM_IF_ACMPEQ:
1740        case Constants.ASM_IF_ACMPNE:
1741        case Constants.ASM_GOTO:
1742        case Constants.ASM_JSR:
1743        case Constants.ASM_IFNULL:
1744        case Constants.ASM_IFNONNULL:
1745          createLabel(bytecodeOffset + readUnsignedShort(currentOffset + 1), labels);
1746          currentOffset += 3;
1747          break;
1748        case Constants.GOTO_W:
1749        case Constants.JSR_W:
1750        case Constants.ASM_GOTO_W:
1751          createLabel(bytecodeOffset + readInt(currentOffset + 1), labels);
1752          currentOffset += 5;
1753          break;
1754        case Constants.WIDE:
1755          switch (classBuffer[currentOffset + 1] & 0xFF) {
1756            case Opcodes.ILOAD:
1757            case Opcodes.FLOAD:
1758            case Opcodes.ALOAD:
1759            case Opcodes.LLOAD:
1760            case Opcodes.DLOAD:
1761            case Opcodes.ISTORE:
1762            case Opcodes.FSTORE:
1763            case Opcodes.ASTORE:
1764            case Opcodes.LSTORE:
1765            case Opcodes.DSTORE:
1766            case Opcodes.RET:
1767              currentOffset += 4;
1768              break;
1769            case Opcodes.IINC:
1770              currentOffset += 6;
1771              break;
1772            default:
1773              throw new IllegalArgumentException();
1774          }
1775          break;
1776        case Opcodes.TABLESWITCH:
1777          // Skip 0 to 3 padding bytes.
1778          currentOffset += 4 - (bytecodeOffset & 3);
1779          // Read the default label and the number of table entries.
1780          createLabel(bytecodeOffset + readInt(currentOffset), labels);
1781          int numTableEntries = readInt(currentOffset + 8) - readInt(currentOffset + 4) + 1;
1782          currentOffset += 12;
1783          // Read the table labels.
1784          while (numTableEntries-- > 0) {
1785            createLabel(bytecodeOffset + readInt(currentOffset), labels);
1786            currentOffset += 4;
1787          }
1788          break;
1789        case Opcodes.LOOKUPSWITCH:
1790          // Skip 0 to 3 padding bytes.
1791          currentOffset += 4 - (bytecodeOffset & 3);
1792          // Read the default label and the number of switch cases.
1793          createLabel(bytecodeOffset + readInt(currentOffset), labels);
1794          int numSwitchCases = readInt(currentOffset + 4);
1795          currentOffset += 8;
1796          // Read the switch labels.
1797          while (numSwitchCases-- > 0) {
1798            createLabel(bytecodeOffset + readInt(currentOffset + 4), labels);
1799            currentOffset += 8;
1800          }
1801          break;
1802        case Opcodes.ILOAD:
1803        case Opcodes.LLOAD:
1804        case Opcodes.FLOAD:
1805        case Opcodes.DLOAD:
1806        case Opcodes.ALOAD:
1807        case Opcodes.ISTORE:
1808        case Opcodes.LSTORE:
1809        case Opcodes.FSTORE:
1810        case Opcodes.DSTORE:
1811        case Opcodes.ASTORE:
1812        case Opcodes.RET:
1813        case Opcodes.BIPUSH:
1814        case Opcodes.NEWARRAY:
1815        case Opcodes.LDC:
1816          currentOffset += 2;
1817          break;
1818        case Opcodes.SIPUSH:
1819        case Constants.LDC_W:
1820        case Constants.LDC2_W:
1821        case Opcodes.GETSTATIC:
1822        case Opcodes.PUTSTATIC:
1823        case Opcodes.GETFIELD:
1824        case Opcodes.PUTFIELD:
1825        case Opcodes.INVOKEVIRTUAL:
1826        case Opcodes.INVOKESPECIAL:
1827        case Opcodes.INVOKESTATIC:
1828        case Opcodes.NEW:
1829        case Opcodes.ANEWARRAY:
1830        case Opcodes.CHECKCAST:
1831        case Opcodes.INSTANCEOF:
1832        case Opcodes.IINC:
1833          currentOffset += 3;
1834          break;
1835        case Opcodes.INVOKEINTERFACE:
1836        case Opcodes.INVOKEDYNAMIC:
1837          currentOffset += 5;
1838          break;
1839        case Opcodes.MULTIANEWARRAY:
1840          currentOffset += 4;
1841          break;
1842        default:
1843          throw new IllegalArgumentException();
1844      }
1845    }
1846
1847    // Read the 'exception_table_length' and 'exception_table' field to create a label for each
1848    // referenced instruction, and to make methodVisitor visit the corresponding try catch blocks.
1849    int exceptionTableLength = readUnsignedShort(currentOffset);
1850    currentOffset += 2;
1851    while (exceptionTableLength-- > 0) {
1852      Label start = createLabel(readUnsignedShort(currentOffset), labels);
1853      Label end = createLabel(readUnsignedShort(currentOffset + 2), labels);
1854      Label handler = createLabel(readUnsignedShort(currentOffset + 4), labels);
1855      String catchType = readUTF8(cpInfoOffsets[readUnsignedShort(currentOffset + 6)], charBuffer);
1856      currentOffset += 8;
1857      methodVisitor.visitTryCatchBlock(start, end, handler, catchType);
1858    }
1859
1860    // Read the Code attributes to create a label for each referenced instruction (the variables
1861    // are ordered as in Section 4.7 of the JVMS). Attribute offsets exclude the
1862    // attribute_name_index and attribute_length fields.
1863    // - The offset of the current 'stack_map_frame' in the StackMap[Table] attribute, or 0.
1864    // Initially, this is the offset of the first 'stack_map_frame' entry. Then this offset is
1865    // updated after each stack_map_frame is read.
1866    int stackMapFrameOffset = 0;
1867    // - The end offset of the StackMap[Table] attribute, or 0.
1868    int stackMapTableEndOffset = 0;
1869    // - Whether the stack map frames are compressed (i.e. in a StackMapTable) or not.
1870    boolean compressedFrames = true;
1871    // - The offset of the LocalVariableTable attribute, or 0.
1872    int localVariableTableOffset = 0;
1873    // - The offset of the LocalVariableTypeTable attribute, or 0.
1874    int localVariableTypeTableOffset = 0;
1875    // - The offset of each 'type_annotation' entry in the RuntimeVisibleTypeAnnotations
1876    // attribute, or null.
1877    int[] visibleTypeAnnotationOffsets = null;
1878    // - The offset of each 'type_annotation' entry in the RuntimeInvisibleTypeAnnotations
1879    // attribute, or null.
1880    int[] invisibleTypeAnnotationOffsets = null;
1881    // - The non standard attributes (linked with their {@link Attribute#nextAttribute} field).
1882    //   This list in the <i>reverse order</i> or their order in the ClassFile structure.
1883    Attribute attributes = null;
1884
1885    int attributesCount = readUnsignedShort(currentOffset);
1886    currentOffset += 2;
1887    while (attributesCount-- > 0) {
1888      // Read the attribute_info's attribute_name and attribute_length fields.
1889      String attributeName = readUTF8(currentOffset, charBuffer);
1890      int attributeLength = readInt(currentOffset + 2);
1891      currentOffset += 6;
1892      if (Constants.LOCAL_VARIABLE_TABLE.equals(attributeName)) {
1893        if ((context.parsingOptions & SKIP_DEBUG) == 0) {
1894          localVariableTableOffset = currentOffset;
1895          // Parse the attribute to find the corresponding (debug only) labels.
1896          int currentLocalVariableTableOffset = currentOffset;
1897          int localVariableTableLength = readUnsignedShort(currentLocalVariableTableOffset);
1898          currentLocalVariableTableOffset += 2;
1899          while (localVariableTableLength-- > 0) {
1900            int startPc = readUnsignedShort(currentLocalVariableTableOffset);
1901            createDebugLabel(startPc, labels);
1902            int length = readUnsignedShort(currentLocalVariableTableOffset + 2);
1903            createDebugLabel(startPc + length, labels);
1904            // Skip the name_index, descriptor_index and index fields (2 bytes each).
1905            currentLocalVariableTableOffset += 10;
1906          }
1907        }
1908      } else if (Constants.LOCAL_VARIABLE_TYPE_TABLE.equals(attributeName)) {
1909        localVariableTypeTableOffset = currentOffset;
1910        // Here we do not extract the labels corresponding to the attribute content. We assume they
1911        // are the same or a subset of those of the LocalVariableTable attribute.
1912      } else if (Constants.LINE_NUMBER_TABLE.equals(attributeName)) {
1913        if ((context.parsingOptions & SKIP_DEBUG) == 0) {
1914          // Parse the attribute to find the corresponding (debug only) labels.
1915          int currentLineNumberTableOffset = currentOffset;
1916          int lineNumberTableLength = readUnsignedShort(currentLineNumberTableOffset);
1917          currentLineNumberTableOffset += 2;
1918          while (lineNumberTableLength-- > 0) {
1919            int startPc = readUnsignedShort(currentLineNumberTableOffset);
1920            int lineNumber = readUnsignedShort(currentLineNumberTableOffset + 2);
1921            currentLineNumberTableOffset += 4;
1922            createDebugLabel(startPc, labels);
1923            labels[startPc].addLineNumber(lineNumber);
1924          }
1925        }
1926      } else if (Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
1927        visibleTypeAnnotationOffsets =
1928            readTypeAnnotations(methodVisitor, context, currentOffset, /* visible = */ true);
1929        // Here we do not extract the labels corresponding to the attribute content. This would
1930        // require a full parsing of the attribute, which would need to be repeated when parsing
1931        // the bytecode instructions (see below). Instead, the content of the attribute is read one
1932        // type annotation at a time (i.e. after a type annotation has been visited, the next type
1933        // annotation is read), and the labels it contains are also extracted one annotation at a
1934        // time. This assumes that type annotations are ordered by increasing bytecode offset.
1935      } else if (Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
1936        invisibleTypeAnnotationOffsets =
1937            readTypeAnnotations(methodVisitor, context, currentOffset, /* visible = */ false);
1938        // Same comment as above for the RuntimeVisibleTypeAnnotations attribute.
1939      } else if (Constants.STACK_MAP_TABLE.equals(attributeName)) {
1940        if ((context.parsingOptions & SKIP_FRAMES) == 0) {
1941          stackMapFrameOffset = currentOffset + 2;
1942          stackMapTableEndOffset = currentOffset + attributeLength;
1943        }
1944        // Here we do not extract the labels corresponding to the attribute content. This would
1945        // require a full parsing of the attribute, which would need to be repeated when parsing
1946        // the bytecode instructions (see below). Instead, the content of the attribute is read one
1947        // frame at a time (i.e. after a frame has been visited, the next frame is read), and the
1948        // labels it contains are also extracted one frame at a time. Thanks to the ordering of
1949        // frames, having only a "one frame lookahead" is not a problem, i.e. it is not possible to
1950        // see an offset smaller than the offset of the current instruction and for which no Label
1951        // exist. Except for UNINITIALIZED type offsets. We solve this by parsing the stack map
1952        // table without a full decoding (see below).
1953      } else if ("StackMap".equals(attributeName)) {
1954        if ((context.parsingOptions & SKIP_FRAMES) == 0) {
1955          stackMapFrameOffset = currentOffset + 2;
1956          stackMapTableEndOffset = currentOffset + attributeLength;
1957          compressedFrames = false;
1958        }
1959        // IMPORTANT! Here we assume that the frames are ordered, as in the StackMapTable attribute,
1960        // although this is not guaranteed by the attribute format. This allows an incremental
1961        // extraction of the labels corresponding to this attribute (see the comment above for the
1962        // StackMapTable attribute).
1963      } else {
1964        Attribute attribute =
1965            readAttribute(
1966                context.attributePrototypes,
1967                attributeName,
1968                currentOffset,
1969                attributeLength,
1970                charBuffer,
1971                codeOffset,
1972                labels);
1973        attribute.nextAttribute = attributes;
1974        attributes = attribute;
1975      }
1976      currentOffset += attributeLength;
1977    }
1978
1979    // Initialize the context fields related to stack map frames, and generate the first
1980    // (implicit) stack map frame, if needed.
1981    final boolean expandFrames = (context.parsingOptions & EXPAND_FRAMES) != 0;
1982    if (stackMapFrameOffset != 0) {
1983      // The bytecode offset of the first explicit frame is not offset_delta + 1 but only
1984      // offset_delta. Setting the implicit frame offset to -1 allows us to use of the
1985      // "offset_delta + 1" rule in all cases.
1986      context.currentFrameOffset = -1;
1987      context.currentFrameType = 0;
1988      context.currentFrameLocalCount = 0;
1989      context.currentFrameLocalCountDelta = 0;
1990      context.currentFrameLocalTypes = new Object[maxLocals];
1991      context.currentFrameStackCount = 0;
1992      context.currentFrameStackTypes = new Object[maxStack];
1993      if (expandFrames) {
1994        computeImplicitFrame(context);
1995      }
1996      // Find the labels for UNINITIALIZED frame types. Instead of decoding each element of the
1997      // stack map table, we look for 3 consecutive bytes that "look like" an UNINITIALIZED type
1998      // (tag ITEM_Uninitialized, offset within bytecode bounds, NEW instruction at this offset).
1999      // We may find false positives (i.e. not real UNINITIALIZED types), but this should be rare,
2000      // and the only consequence will be the creation of an unneeded label. This is better than
2001      // creating a label for each NEW instruction, and faster than fully decoding the whole stack
2002      // map table.
2003      for (int offset = stackMapFrameOffset; offset < stackMapTableEndOffset - 2; ++offset) {
2004        if (classBuffer[offset] == Frame.ITEM_UNINITIALIZED) {
2005          int potentialBytecodeOffset = readUnsignedShort(offset + 1);
2006          if (potentialBytecodeOffset >= 0
2007              && potentialBytecodeOffset < codeLength
2008              && (classBuffer[bytecodeStartOffset + potentialBytecodeOffset] & 0xFF)
2009                  == Opcodes.NEW) {
2010            createLabel(potentialBytecodeOffset, labels);
2011          }
2012        }
2013      }
2014    }
2015    if (expandFrames && (context.parsingOptions & EXPAND_ASM_INSNS) != 0) {
2016      // Expanding the ASM specific instructions can introduce F_INSERT frames, even if the method
2017      // does not currently have any frame. These inserted frames must be computed by simulating the
2018      // effect of the bytecode instructions, one by one, starting from the implicit first frame.
2019      // For this, MethodWriter needs to know maxLocals before the first instruction is visited. To
2020      // ensure this, we visit the implicit first frame here (passing only maxLocals - the rest is
2021      // computed in MethodWriter).
2022      methodVisitor.visitFrame(Opcodes.F_NEW, maxLocals, null, 0, null);
2023    }
2024
2025    // Visit the bytecode instructions. First, introduce state variables for the incremental parsing
2026    // of the type annotations.
2027
2028    // Index of the next runtime visible type annotation to read (in the
2029    // visibleTypeAnnotationOffsets array).
2030    int currentVisibleTypeAnnotationIndex = 0;
2031    // The bytecode offset of the next runtime visible type annotation to read, or -1.
2032    int currentVisibleTypeAnnotationBytecodeOffset =
2033        getTypeAnnotationBytecodeOffset(visibleTypeAnnotationOffsets, 0);
2034    // Index of the next runtime invisible type annotation to read (in the
2035    // invisibleTypeAnnotationOffsets array).
2036    int currentInvisibleTypeAnnotationIndex = 0;
2037    // The bytecode offset of the next runtime invisible type annotation to read, or -1.
2038    int currentInvisibleTypeAnnotationBytecodeOffset =
2039        getTypeAnnotationBytecodeOffset(invisibleTypeAnnotationOffsets, 0);
2040
2041    // Whether a F_INSERT stack map frame must be inserted before the current instruction.
2042    boolean insertFrame = false;
2043
2044    // The delta to subtract from a goto_w or jsr_w opcode to get the corresponding goto or jsr
2045    // opcode, or 0 if goto_w and jsr_w must be left unchanged (i.e. when expanding ASM specific
2046    // instructions).
2047    final int wideJumpOpcodeDelta =
2048        (context.parsingOptions & EXPAND_ASM_INSNS) == 0 ? Constants.WIDE_JUMP_OPCODE_DELTA : 0;
2049
2050    currentOffset = bytecodeStartOffset;
2051    while (currentOffset < bytecodeEndOffset) {
2052      final int currentBytecodeOffset = currentOffset - bytecodeStartOffset;
2053      readBytecodeInstructionOffset(currentBytecodeOffset);
2054
2055      // Visit the label and the line number(s) for this bytecode offset, if any.
2056      Label currentLabel = labels[currentBytecodeOffset];
2057      if (currentLabel != null) {
2058        currentLabel.accept(methodVisitor, (context.parsingOptions & SKIP_DEBUG) == 0);
2059      }
2060
2061      // Visit the stack map frame for this bytecode offset, if any.
2062      while (stackMapFrameOffset != 0
2063          && (context.currentFrameOffset == currentBytecodeOffset
2064              || context.currentFrameOffset == -1)) {
2065        // If there is a stack map frame for this offset, make methodVisitor visit it, and read the
2066        // next stack map frame if there is one.
2067        if (context.currentFrameOffset != -1) {
2068          if (!compressedFrames || expandFrames) {
2069            methodVisitor.visitFrame(
2070                Opcodes.F_NEW,
2071                context.currentFrameLocalCount,
2072                context.currentFrameLocalTypes,
2073                context.currentFrameStackCount,
2074                context.currentFrameStackTypes);
2075          } else {
2076            methodVisitor.visitFrame(
2077                context.currentFrameType,
2078                context.currentFrameLocalCountDelta,
2079                context.currentFrameLocalTypes,
2080                context.currentFrameStackCount,
2081                context.currentFrameStackTypes);
2082          }
2083          // Since there is already a stack map frame for this bytecode offset, there is no need to
2084          // insert a new one.
2085          insertFrame = false;
2086        }
2087        if (stackMapFrameOffset < stackMapTableEndOffset) {
2088          stackMapFrameOffset =
2089              readStackMapFrame(stackMapFrameOffset, compressedFrames, expandFrames, context);
2090        } else {
2091          stackMapFrameOffset = 0;
2092        }
2093      }
2094
2095      // Insert a stack map frame for this bytecode offset, if requested by setting insertFrame to
2096      // true during the previous iteration. The actual frame content is computed in MethodWriter.
2097      if (insertFrame) {
2098        if ((context.parsingOptions & EXPAND_FRAMES) != 0) {
2099          methodVisitor.visitFrame(Constants.F_INSERT, 0, null, 0, null);
2100        }
2101        insertFrame = false;
2102      }
2103
2104      // Visit the instruction at this bytecode offset.
2105      int opcode = classBuffer[currentOffset] & 0xFF;
2106      switch (opcode) {
2107        case Opcodes.NOP:
2108        case Opcodes.ACONST_NULL:
2109        case Opcodes.ICONST_M1:
2110        case Opcodes.ICONST_0:
2111        case Opcodes.ICONST_1:
2112        case Opcodes.ICONST_2:
2113        case Opcodes.ICONST_3:
2114        case Opcodes.ICONST_4:
2115        case Opcodes.ICONST_5:
2116        case Opcodes.LCONST_0:
2117        case Opcodes.LCONST_1:
2118        case Opcodes.FCONST_0:
2119        case Opcodes.FCONST_1:
2120        case Opcodes.FCONST_2:
2121        case Opcodes.DCONST_0:
2122        case Opcodes.DCONST_1:
2123        case Opcodes.IALOAD:
2124        case Opcodes.LALOAD:
2125        case Opcodes.FALOAD:
2126        case Opcodes.DALOAD:
2127        case Opcodes.AALOAD:
2128        case Opcodes.BALOAD:
2129        case Opcodes.CALOAD:
2130        case Opcodes.SALOAD:
2131        case Opcodes.IASTORE:
2132        case Opcodes.LASTORE:
2133        case Opcodes.FASTORE:
2134        case Opcodes.DASTORE:
2135        case Opcodes.AASTORE:
2136        case Opcodes.BASTORE:
2137        case Opcodes.CASTORE:
2138        case Opcodes.SASTORE:
2139        case Opcodes.POP:
2140        case Opcodes.POP2:
2141        case Opcodes.DUP:
2142        case Opcodes.DUP_X1:
2143        case Opcodes.DUP_X2:
2144        case Opcodes.DUP2:
2145        case Opcodes.DUP2_X1:
2146        case Opcodes.DUP2_X2:
2147        case Opcodes.SWAP:
2148        case Opcodes.IADD:
2149        case Opcodes.LADD:
2150        case Opcodes.FADD:
2151        case Opcodes.DADD:
2152        case Opcodes.ISUB:
2153        case Opcodes.LSUB:
2154        case Opcodes.FSUB:
2155        case Opcodes.DSUB:
2156        case Opcodes.IMUL:
2157        case Opcodes.LMUL:
2158        case Opcodes.FMUL:
2159        case Opcodes.DMUL:
2160        case Opcodes.IDIV:
2161        case Opcodes.LDIV:
2162        case Opcodes.FDIV:
2163        case Opcodes.DDIV:
2164        case Opcodes.IREM:
2165        case Opcodes.LREM:
2166        case Opcodes.FREM:
2167        case Opcodes.DREM:
2168        case Opcodes.INEG:
2169        case Opcodes.LNEG:
2170        case Opcodes.FNEG:
2171        case Opcodes.DNEG:
2172        case Opcodes.ISHL:
2173        case Opcodes.LSHL:
2174        case Opcodes.ISHR:
2175        case Opcodes.LSHR:
2176        case Opcodes.IUSHR:
2177        case Opcodes.LUSHR:
2178        case Opcodes.IAND:
2179        case Opcodes.LAND:
2180        case Opcodes.IOR:
2181        case Opcodes.LOR:
2182        case Opcodes.IXOR:
2183        case Opcodes.LXOR:
2184        case Opcodes.I2L:
2185        case Opcodes.I2F:
2186        case Opcodes.I2D:
2187        case Opcodes.L2I:
2188        case Opcodes.L2F:
2189        case Opcodes.L2D:
2190        case Opcodes.F2I:
2191        case Opcodes.F2L:
2192        case Opcodes.F2D:
2193        case Opcodes.D2I:
2194        case Opcodes.D2L:
2195        case Opcodes.D2F:
2196        case Opcodes.I2B:
2197        case Opcodes.I2C:
2198        case Opcodes.I2S:
2199        case Opcodes.LCMP:
2200        case Opcodes.FCMPL:
2201        case Opcodes.FCMPG:
2202        case Opcodes.DCMPL:
2203        case Opcodes.DCMPG:
2204        case Opcodes.IRETURN:
2205        case Opcodes.LRETURN:
2206        case Opcodes.FRETURN:
2207        case Opcodes.DRETURN:
2208        case Opcodes.ARETURN:
2209        case Opcodes.RETURN:
2210        case Opcodes.ARRAYLENGTH:
2211        case Opcodes.ATHROW:
2212        case Opcodes.MONITORENTER:
2213        case Opcodes.MONITOREXIT:
2214          methodVisitor.visitInsn(opcode);
2215          currentOffset += 1;
2216          break;
2217        case Constants.ILOAD_0:
2218        case Constants.ILOAD_1:
2219        case Constants.ILOAD_2:
2220        case Constants.ILOAD_3:
2221        case Constants.LLOAD_0:
2222        case Constants.LLOAD_1:
2223        case Constants.LLOAD_2:
2224        case Constants.LLOAD_3:
2225        case Constants.FLOAD_0:
2226        case Constants.FLOAD_1:
2227        case Constants.FLOAD_2:
2228        case Constants.FLOAD_3:
2229        case Constants.DLOAD_0:
2230        case Constants.DLOAD_1:
2231        case Constants.DLOAD_2:
2232        case Constants.DLOAD_3:
2233        case Constants.ALOAD_0:
2234        case Constants.ALOAD_1:
2235        case Constants.ALOAD_2:
2236        case Constants.ALOAD_3:
2237          opcode -= Constants.ILOAD_0;
2238          methodVisitor.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), opcode & 0x3);
2239          currentOffset += 1;
2240          break;
2241        case Constants.ISTORE_0:
2242        case Constants.ISTORE_1:
2243        case Constants.ISTORE_2:
2244        case Constants.ISTORE_3:
2245        case Constants.LSTORE_0:
2246        case Constants.LSTORE_1:
2247        case Constants.LSTORE_2:
2248        case Constants.LSTORE_3:
2249        case Constants.FSTORE_0:
2250        case Constants.FSTORE_1:
2251        case Constants.FSTORE_2:
2252        case Constants.FSTORE_3:
2253        case Constants.DSTORE_0:
2254        case Constants.DSTORE_1:
2255        case Constants.DSTORE_2:
2256        case Constants.DSTORE_3:
2257        case Constants.ASTORE_0:
2258        case Constants.ASTORE_1:
2259        case Constants.ASTORE_2:
2260        case Constants.ASTORE_3:
2261          opcode -= Constants.ISTORE_0;
2262          methodVisitor.visitVarInsn(Opcodes.ISTORE + (opcode >> 2), opcode & 0x3);
2263          currentOffset += 1;
2264          break;
2265        case Opcodes.IFEQ:
2266        case Opcodes.IFNE:
2267        case Opcodes.IFLT:
2268        case Opcodes.IFGE:
2269        case Opcodes.IFGT:
2270        case Opcodes.IFLE:
2271        case Opcodes.IF_ICMPEQ:
2272        case Opcodes.IF_ICMPNE:
2273        case Opcodes.IF_ICMPLT:
2274        case Opcodes.IF_ICMPGE:
2275        case Opcodes.IF_ICMPGT:
2276        case Opcodes.IF_ICMPLE:
2277        case Opcodes.IF_ACMPEQ:
2278        case Opcodes.IF_ACMPNE:
2279        case Opcodes.GOTO:
2280        case Opcodes.JSR:
2281        case Opcodes.IFNULL:
2282        case Opcodes.IFNONNULL:
2283          methodVisitor.visitJumpInsn(
2284              opcode, labels[currentBytecodeOffset + readShort(currentOffset + 1)]);
2285          currentOffset += 3;
2286          break;
2287        case Constants.GOTO_W:
2288        case Constants.JSR_W:
2289          methodVisitor.visitJumpInsn(
2290              opcode - wideJumpOpcodeDelta,
2291              labels[currentBytecodeOffset + readInt(currentOffset + 1)]);
2292          currentOffset += 5;
2293          break;
2294        case Constants.ASM_IFEQ:
2295        case Constants.ASM_IFNE:
2296        case Constants.ASM_IFLT:
2297        case Constants.ASM_IFGE:
2298        case Constants.ASM_IFGT:
2299        case Constants.ASM_IFLE:
2300        case Constants.ASM_IF_ICMPEQ:
2301        case Constants.ASM_IF_ICMPNE:
2302        case Constants.ASM_IF_ICMPLT:
2303        case Constants.ASM_IF_ICMPGE:
2304        case Constants.ASM_IF_ICMPGT:
2305        case Constants.ASM_IF_ICMPLE:
2306        case Constants.ASM_IF_ACMPEQ:
2307        case Constants.ASM_IF_ACMPNE:
2308        case Constants.ASM_GOTO:
2309        case Constants.ASM_JSR:
2310        case Constants.ASM_IFNULL:
2311        case Constants.ASM_IFNONNULL:
2312          {
2313            // A forward jump with an offset > 32767. In this case we automatically replace ASM_GOTO
2314            // with GOTO_W, ASM_JSR with JSR_W and ASM_IFxxx <l> with IFNOTxxx <L> GOTO_W <l> L:...,
2315            // where IFNOTxxx is the "opposite" opcode of ASMS_IFxxx (e.g. IFNE for ASM_IFEQ) and
2316            // where <L> designates the instruction just after the GOTO_W.
2317            // First, change the ASM specific opcodes ASM_IFEQ ... ASM_JSR, ASM_IFNULL and
2318            // ASM_IFNONNULL to IFEQ ... JSR, IFNULL and IFNONNULL.
2319            opcode =
2320                opcode < Constants.ASM_IFNULL
2321                    ? opcode - Constants.ASM_OPCODE_DELTA
2322                    : opcode - Constants.ASM_IFNULL_OPCODE_DELTA;
2323            Label target = labels[currentBytecodeOffset + readUnsignedShort(currentOffset + 1)];
2324            if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
2325              // Replace GOTO with GOTO_W and JSR with JSR_W.
2326              methodVisitor.visitJumpInsn(opcode + Constants.WIDE_JUMP_OPCODE_DELTA, target);
2327            } else {
2328              // Compute the "opposite" of opcode. This can be done by flipping the least
2329              // significant bit for IFNULL and IFNONNULL, and similarly for IFEQ ... IF_ACMPEQ
2330              // (with a pre and post offset by 1).
2331              opcode = opcode < Opcodes.GOTO ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1;
2332              Label endif = createLabel(currentBytecodeOffset + 3, labels);
2333              methodVisitor.visitJumpInsn(opcode, endif);
2334              methodVisitor.visitJumpInsn(Constants.GOTO_W, target);
2335              // endif designates the instruction just after GOTO_W, and is visited as part of the
2336              // next instruction. Since it is a jump target, we need to insert a frame here.
2337              insertFrame = true;
2338            }
2339            currentOffset += 3;
2340            break;
2341          }
2342        case Constants.ASM_GOTO_W:
2343          // Replace ASM_GOTO_W with GOTO_W.
2344          methodVisitor.visitJumpInsn(
2345              Constants.GOTO_W, labels[currentBytecodeOffset + readInt(currentOffset + 1)]);
2346          // The instruction just after is a jump target (because ASM_GOTO_W is used in patterns
2347          // IFNOTxxx <L> ASM_GOTO_W <l> L:..., see MethodWriter), so we need to insert a frame
2348          // here.
2349          insertFrame = true;
2350          currentOffset += 5;
2351          break;
2352        case Constants.WIDE:
2353          opcode = classBuffer[currentOffset + 1] & 0xFF;
2354          if (opcode == Opcodes.IINC) {
2355            methodVisitor.visitIincInsn(
2356                readUnsignedShort(currentOffset + 2), readShort(currentOffset + 4));
2357            currentOffset += 6;
2358          } else {
2359            methodVisitor.visitVarInsn(opcode, readUnsignedShort(currentOffset + 2));
2360            currentOffset += 4;
2361          }
2362          break;
2363        case Opcodes.TABLESWITCH:
2364          {
2365            // Skip 0 to 3 padding bytes.
2366            currentOffset += 4 - (currentBytecodeOffset & 3);
2367            // Read the instruction.
2368            Label defaultLabel = labels[currentBytecodeOffset + readInt(currentOffset)];
2369            int low = readInt(currentOffset + 4);
2370            int high = readInt(currentOffset + 8);
2371            currentOffset += 12;
2372            Label[] table = new Label[high - low + 1];
2373            for (int i = 0; i < table.length; ++i) {
2374              table[i] = labels[currentBytecodeOffset + readInt(currentOffset)];
2375              currentOffset += 4;
2376            }
2377            methodVisitor.visitTableSwitchInsn(low, high, defaultLabel, table);
2378            break;
2379          }
2380        case Opcodes.LOOKUPSWITCH:
2381          {
2382            // Skip 0 to 3 padding bytes.
2383            currentOffset += 4 - (currentBytecodeOffset & 3);
2384            // Read the instruction.
2385            Label defaultLabel = labels[currentBytecodeOffset + readInt(currentOffset)];
2386            int numPairs = readInt(currentOffset + 4);
2387            currentOffset += 8;
2388            int[] keys = new int[numPairs];
2389            Label[] values = new Label[numPairs];
2390            for (int i = 0; i < numPairs; ++i) {
2391              keys[i] = readInt(currentOffset);
2392              values[i] = labels[currentBytecodeOffset + readInt(currentOffset + 4)];
2393              currentOffset += 8;
2394            }
2395            methodVisitor.visitLookupSwitchInsn(defaultLabel, keys, values);
2396            break;
2397          }
2398        case Opcodes.ILOAD:
2399        case Opcodes.LLOAD:
2400        case Opcodes.FLOAD:
2401        case Opcodes.DLOAD:
2402        case Opcodes.ALOAD:
2403        case Opcodes.ISTORE:
2404        case Opcodes.LSTORE:
2405        case Opcodes.FSTORE:
2406        case Opcodes.DSTORE:
2407        case Opcodes.ASTORE:
2408        case Opcodes.RET:
2409          methodVisitor.visitVarInsn(opcode, classBuffer[currentOffset + 1] & 0xFF);
2410          currentOffset += 2;
2411          break;
2412        case Opcodes.BIPUSH:
2413        case Opcodes.NEWARRAY:
2414          methodVisitor.visitIntInsn(opcode, classBuffer[currentOffset + 1]);
2415          currentOffset += 2;
2416          break;
2417        case Opcodes.SIPUSH:
2418          methodVisitor.visitIntInsn(opcode, readShort(currentOffset + 1));
2419          currentOffset += 3;
2420          break;
2421        case Opcodes.LDC:
2422          methodVisitor.visitLdcInsn(readConst(classBuffer[currentOffset + 1] & 0xFF, charBuffer));
2423          currentOffset += 2;
2424          break;
2425        case Constants.LDC_W:
2426        case Constants.LDC2_W:
2427          methodVisitor.visitLdcInsn(readConst(readUnsignedShort(currentOffset + 1), charBuffer));
2428          currentOffset += 3;
2429          break;
2430        case Opcodes.GETSTATIC:
2431        case Opcodes.PUTSTATIC:
2432        case Opcodes.GETFIELD:
2433        case Opcodes.PUTFIELD:
2434        case Opcodes.INVOKEVIRTUAL:
2435        case Opcodes.INVOKESPECIAL:
2436        case Opcodes.INVOKESTATIC:
2437        case Opcodes.INVOKEINTERFACE:
2438          {
2439            int cpInfoOffset = cpInfoOffsets[readUnsignedShort(currentOffset + 1)];
2440            int nameAndTypeCpInfoOffset = cpInfoOffsets[readUnsignedShort(cpInfoOffset + 2)];
2441            String owner = readClass(cpInfoOffset, charBuffer);
2442            String name = readUTF8(nameAndTypeCpInfoOffset, charBuffer);
2443            String descriptor = readUTF8(nameAndTypeCpInfoOffset + 2, charBuffer);
2444            if (opcode < Opcodes.INVOKEVIRTUAL) {
2445              methodVisitor.visitFieldInsn(opcode, owner, name, descriptor);
2446            } else {
2447              boolean isInterface =
2448                  classBuffer[cpInfoOffset - 1] == Symbol.CONSTANT_INTERFACE_METHODREF_TAG;
2449              methodVisitor.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
2450            }
2451            if (opcode == Opcodes.INVOKEINTERFACE) {
2452              currentOffset += 5;
2453            } else {
2454              currentOffset += 3;
2455            }
2456            break;
2457          }
2458        case Opcodes.INVOKEDYNAMIC:
2459          {
2460            int cpInfoOffset = cpInfoOffsets[readUnsignedShort(currentOffset + 1)];
2461            int nameAndTypeCpInfoOffset = cpInfoOffsets[readUnsignedShort(cpInfoOffset + 2)];
2462            String name = readUTF8(nameAndTypeCpInfoOffset, charBuffer);
2463            String descriptor = readUTF8(nameAndTypeCpInfoOffset + 2, charBuffer);
2464            int bootstrapMethodOffset = bootstrapMethodOffsets[readUnsignedShort(cpInfoOffset)];
2465            Handle handle =
2466                (Handle) readConst(readUnsignedShort(bootstrapMethodOffset), charBuffer);
2467            Object[] bootstrapMethodArguments =
2468                new Object[readUnsignedShort(bootstrapMethodOffset + 2)];
2469            bootstrapMethodOffset += 4;
2470            for (int i = 0; i < bootstrapMethodArguments.length; i++) {
2471              bootstrapMethodArguments[i] =
2472                  readConst(readUnsignedShort(bootstrapMethodOffset), charBuffer);
2473              bootstrapMethodOffset += 2;
2474            }
2475            methodVisitor.visitInvokeDynamicInsn(
2476                name, descriptor, handle, bootstrapMethodArguments);
2477            currentOffset += 5;
2478            break;
2479          }
2480        case Opcodes.NEW:
2481        case Opcodes.ANEWARRAY:
2482        case Opcodes.CHECKCAST:
2483        case Opcodes.INSTANCEOF:
2484          methodVisitor.visitTypeInsn(opcode, readClass(currentOffset + 1, charBuffer));
2485          currentOffset += 3;
2486          break;
2487        case Opcodes.IINC:
2488          methodVisitor.visitIincInsn(
2489              classBuffer[currentOffset + 1] & 0xFF, classBuffer[currentOffset + 2]);
2490          currentOffset += 3;
2491          break;
2492        case Opcodes.MULTIANEWARRAY:
2493          methodVisitor.visitMultiANewArrayInsn(
2494              readClass(currentOffset + 1, charBuffer), classBuffer[currentOffset + 3] & 0xFF);
2495          currentOffset += 4;
2496          break;
2497        default:
2498          throw new AssertionError();
2499      }
2500
2501      // Visit the runtime visible instruction annotations, if any.
2502      while (visibleTypeAnnotationOffsets != null
2503          && currentVisibleTypeAnnotationIndex < visibleTypeAnnotationOffsets.length
2504          && currentVisibleTypeAnnotationBytecodeOffset <= currentBytecodeOffset) {
2505        if (currentVisibleTypeAnnotationBytecodeOffset == currentBytecodeOffset) {
2506          // Parse the target_type, target_info and target_path fields.
2507          int currentAnnotationOffset =
2508              readTypeAnnotationTarget(
2509                  context, visibleTypeAnnotationOffsets[currentVisibleTypeAnnotationIndex]);
2510          // Parse the type_index field.
2511          String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
2512          currentAnnotationOffset += 2;
2513          // Parse num_element_value_pairs and element_value_pairs and visit these values.
2514          readElementValues(
2515              methodVisitor.visitInsnAnnotation(
2516                  context.currentTypeAnnotationTarget,
2517                  context.currentTypeAnnotationTargetPath,
2518                  annotationDescriptor,
2519                  /* visible = */ true),
2520              currentAnnotationOffset,
2521              /* named = */ true,
2522              charBuffer);
2523        }
2524        currentVisibleTypeAnnotationBytecodeOffset =
2525            getTypeAnnotationBytecodeOffset(
2526                visibleTypeAnnotationOffsets, ++currentVisibleTypeAnnotationIndex);
2527      }
2528
2529      // Visit the runtime invisible instruction annotations, if any.
2530      while (invisibleTypeAnnotationOffsets != null
2531          && currentInvisibleTypeAnnotationIndex < invisibleTypeAnnotationOffsets.length
2532          && currentInvisibleTypeAnnotationBytecodeOffset <= currentBytecodeOffset) {
2533        if (currentInvisibleTypeAnnotationBytecodeOffset == currentBytecodeOffset) {
2534          // Parse the target_type, target_info and target_path fields.
2535          int currentAnnotationOffset =
2536              readTypeAnnotationTarget(
2537                  context, invisibleTypeAnnotationOffsets[currentInvisibleTypeAnnotationIndex]);
2538          // Parse the type_index field.
2539          String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
2540          currentAnnotationOffset += 2;
2541          // Parse num_element_value_pairs and element_value_pairs and visit these values.
2542          readElementValues(
2543              methodVisitor.visitInsnAnnotation(
2544                  context.currentTypeAnnotationTarget,
2545                  context.currentTypeAnnotationTargetPath,
2546                  annotationDescriptor,
2547                  /* visible = */ false),
2548              currentAnnotationOffset,
2549              /* named = */ true,
2550              charBuffer);
2551        }
2552        currentInvisibleTypeAnnotationBytecodeOffset =
2553            getTypeAnnotationBytecodeOffset(
2554                invisibleTypeAnnotationOffsets, ++currentInvisibleTypeAnnotationIndex);
2555      }
2556    }
2557    if (labels[codeLength] != null) {
2558      methodVisitor.visitLabel(labels[codeLength]);
2559    }
2560
2561    // Visit LocalVariableTable and LocalVariableTypeTable attributes.
2562    if (localVariableTableOffset != 0 && (context.parsingOptions & SKIP_DEBUG) == 0) {
2563      // The (start_pc, index, signature_index) fields of each entry of the LocalVariableTypeTable.
2564      int[] typeTable = null;
2565      if (localVariableTypeTableOffset != 0) {
2566        typeTable = new int[readUnsignedShort(localVariableTypeTableOffset) * 3];
2567        currentOffset = localVariableTypeTableOffset + 2;
2568        int typeTableIndex = typeTable.length;
2569        while (typeTableIndex > 0) {
2570          // Store the offset of 'signature_index', and the value of 'index' and 'start_pc'.
2571          typeTable[--typeTableIndex] = currentOffset + 6;
2572          typeTable[--typeTableIndex] = readUnsignedShort(currentOffset + 8);
2573          typeTable[--typeTableIndex] = readUnsignedShort(currentOffset);
2574          currentOffset += 10;
2575        }
2576      }
2577      int localVariableTableLength = readUnsignedShort(localVariableTableOffset);
2578      currentOffset = localVariableTableOffset + 2;
2579      while (localVariableTableLength-- > 0) {
2580        int startPc = readUnsignedShort(currentOffset);
2581        int length = readUnsignedShort(currentOffset + 2);
2582        String name = readUTF8(currentOffset + 4, charBuffer);
2583        String descriptor = readUTF8(currentOffset + 6, charBuffer);
2584        int index = readUnsignedShort(currentOffset + 8);
2585        currentOffset += 10;
2586        String signature = null;
2587        if (typeTable != null) {
2588          for (int i = 0; i < typeTable.length; i += 3) {
2589            if (typeTable[i] == startPc && typeTable[i + 1] == index) {
2590              signature = readUTF8(typeTable[i + 2], charBuffer);
2591              break;
2592            }
2593          }
2594        }
2595        methodVisitor.visitLocalVariable(
2596            name, descriptor, signature, labels[startPc], labels[startPc + length], index);
2597      }
2598    }
2599
2600    // Visit the local variable type annotations of the RuntimeVisibleTypeAnnotations attribute.
2601    if (visibleTypeAnnotationOffsets != null) {
2602      for (int typeAnnotationOffset : visibleTypeAnnotationOffsets) {
2603        int targetType = readByte(typeAnnotationOffset);
2604        if (targetType == TypeReference.LOCAL_VARIABLE
2605            || targetType == TypeReference.RESOURCE_VARIABLE) {
2606          // Parse the target_type, target_info and target_path fields.
2607          currentOffset = readTypeAnnotationTarget(context, typeAnnotationOffset);
2608          // Parse the type_index field.
2609          String annotationDescriptor = readUTF8(currentOffset, charBuffer);
2610          currentOffset += 2;
2611          // Parse num_element_value_pairs and element_value_pairs and visit these values.
2612          readElementValues(
2613              methodVisitor.visitLocalVariableAnnotation(
2614                  context.currentTypeAnnotationTarget,
2615                  context.currentTypeAnnotationTargetPath,
2616                  context.currentLocalVariableAnnotationRangeStarts,
2617                  context.currentLocalVariableAnnotationRangeEnds,
2618                  context.currentLocalVariableAnnotationRangeIndices,
2619                  annotationDescriptor,
2620                  /* visible = */ true),
2621              currentOffset,
2622              /* named = */ true,
2623              charBuffer);
2624        }
2625      }
2626    }
2627
2628    // Visit the local variable type annotations of the RuntimeInvisibleTypeAnnotations attribute.
2629    if (invisibleTypeAnnotationOffsets != null) {
2630      for (int typeAnnotationOffset : invisibleTypeAnnotationOffsets) {
2631        int targetType = readByte(typeAnnotationOffset);
2632        if (targetType == TypeReference.LOCAL_VARIABLE
2633            || targetType == TypeReference.RESOURCE_VARIABLE) {
2634          // Parse the target_type, target_info and target_path fields.
2635          currentOffset = readTypeAnnotationTarget(context, typeAnnotationOffset);
2636          // Parse the type_index field.
2637          String annotationDescriptor = readUTF8(currentOffset, charBuffer);
2638          currentOffset += 2;
2639          // Parse num_element_value_pairs and element_value_pairs and visit these values.
2640          readElementValues(
2641              methodVisitor.visitLocalVariableAnnotation(
2642                  context.currentTypeAnnotationTarget,
2643                  context.currentTypeAnnotationTargetPath,
2644                  context.currentLocalVariableAnnotationRangeStarts,
2645                  context.currentLocalVariableAnnotationRangeEnds,
2646                  context.currentLocalVariableAnnotationRangeIndices,
2647                  annotationDescriptor,
2648                  /* visible = */ false),
2649              currentOffset,
2650              /* named = */ true,
2651              charBuffer);
2652        }
2653      }
2654    }
2655
2656    // Visit the non standard attributes.
2657    while (attributes != null) {
2658      // Copy and reset the nextAttribute field so that it can also be used in MethodWriter.
2659      Attribute nextAttribute = attributes.nextAttribute;
2660      attributes.nextAttribute = null;
2661      methodVisitor.visitAttribute(attributes);
2662      attributes = nextAttribute;
2663    }
2664
2665    // Visit the max stack and max locals values.
2666    methodVisitor.visitMaxs(maxStack, maxLocals);
2667  }
2668
2669  /**
2670   * Handles the bytecode offset of the next instruction to be visited in {@link
2671   * #accept(ClassVisitor,int)}. This method is called just before the instruction and before its
2672   * associated label and stack map frame, if any. The default implementation of this method does
2673   * nothing. Subclasses can override this method to store the argument in a mutable field, for
2674   * instance, so that {@link MethodVisitor} instances can get the bytecode offset of each visited
2675   * instruction (if so, the usual concurrency issues related to mutable data should be addressed).
2676   *
2677   * @param bytecodeOffset the bytecode offset of the next instruction to be visited.
2678   */
2679  protected void readBytecodeInstructionOffset(final int bytecodeOffset) {
2680    // Do nothing by default.
2681  }
2682
2683  /**
2684   * Returns the label corresponding to the given bytecode offset. The default implementation of
2685   * this method creates a label for the given offset if it has not been already created.
2686   *
2687   * @param bytecodeOffset a bytecode offset in a method.
2688   * @param labels the already created labels, indexed by their offset. If a label already exists
2689   *     for bytecodeOffset this method must not create a new one. Otherwise it must store the new
2690   *     label in this array.
2691   * @return a non null Label, which must be equal to labels[bytecodeOffset].
2692   */
2693  protected Label readLabel(final int bytecodeOffset, final Label[] labels) {
2694    if (labels[bytecodeOffset] == null) {
2695      labels[bytecodeOffset] = new Label();
2696    }
2697    return labels[bytecodeOffset];
2698  }
2699
2700  /**
2701   * Creates a label without the {@link Label#FLAG_DEBUG_ONLY} flag set, for the given bytecode
2702   * offset. The label is created with a call to {@link #readLabel} and its {@link
2703   * Label#FLAG_DEBUG_ONLY} flag is cleared.
2704   *
2705   * @param bytecodeOffset a bytecode offset in a method.
2706   * @param labels the already created labels, indexed by their offset.
2707   * @return a Label without the {@link Label#FLAG_DEBUG_ONLY} flag set.
2708   */
2709  private Label createLabel(final int bytecodeOffset, final Label[] labels) {
2710    Label label = readLabel(bytecodeOffset, labels);
2711    label.flags &= ~Label.FLAG_DEBUG_ONLY;
2712    return label;
2713  }
2714
2715  /**
2716   * Creates a label with the {@link Label#FLAG_DEBUG_ONLY} flag set, if there is no already
2717   * existing label for the given bytecode offset (otherwise does nothing). The label is created
2718   * with a call to {@link #readLabel}.
2719   *
2720   * @param bytecodeOffset a bytecode offset in a method.
2721   * @param labels the already created labels, indexed by their offset.
2722   */
2723  private void createDebugLabel(final int bytecodeOffset, final Label[] labels) {
2724    if (labels[bytecodeOffset] == null) {
2725      readLabel(bytecodeOffset, labels).flags |= Label.FLAG_DEBUG_ONLY;
2726    }
2727  }
2728
2729  // ----------------------------------------------------------------------------------------------
2730  // Methods to parse annotations, type annotations and parameter annotations
2731  // ----------------------------------------------------------------------------------------------
2732
2733  /**
2734   * Parses a Runtime[In]VisibleTypeAnnotations attribute to find the offset of each type_annotation
2735   * entry it contains, to find the corresponding labels, and to visit the try catch block
2736   * annotations.
2737   *
2738   * @param methodVisitor the method visitor to be used to visit the try catch block annotations.
2739   * @param context information about the class being parsed.
2740   * @param runtimeTypeAnnotationsOffset the start offset of a Runtime[In]VisibleTypeAnnotations
2741   *     attribute, excluding the attribute_info's attribute_name_index and attribute_length fields.
2742   * @param visible true if the attribute to parse is a RuntimeVisibleTypeAnnotations attribute,
2743   *     false it is a RuntimeInvisibleTypeAnnotations attribute.
2744   * @return the start offset of each entry of the Runtime[In]VisibleTypeAnnotations_attribute's
2745   *     'annotations' array field.
2746   */
2747  private int[] readTypeAnnotations(
2748      final MethodVisitor methodVisitor,
2749      final Context context,
2750      final int runtimeTypeAnnotationsOffset,
2751      final boolean visible) {
2752    char[] charBuffer = context.charBuffer;
2753    int currentOffset = runtimeTypeAnnotationsOffset;
2754    // Read the num_annotations field and create an array to store the type_annotation offsets.
2755    int[] typeAnnotationsOffsets = new int[readUnsignedShort(currentOffset)];
2756    currentOffset += 2;
2757    // Parse the 'annotations' array field.
2758    for (int i = 0; i < typeAnnotationsOffsets.length; ++i) {
2759      typeAnnotationsOffsets[i] = currentOffset;
2760      // Parse the type_annotation's target_type and the target_info fields. The size of the
2761      // target_info field depends on the value of target_type.
2762      int targetType = readInt(currentOffset);
2763      switch (targetType >>> 24) {
2764        case TypeReference.LOCAL_VARIABLE:
2765        case TypeReference.RESOURCE_VARIABLE:
2766          // A localvar_target has a variable size, which depends on the value of their table_length
2767          // field. It also references bytecode offsets, for which we need labels.
2768          int tableLength = readUnsignedShort(currentOffset + 1);
2769          currentOffset += 3;
2770          while (tableLength-- > 0) {
2771            int startPc = readUnsignedShort(currentOffset);
2772            int length = readUnsignedShort(currentOffset + 2);
2773            // Skip the index field (2 bytes).
2774            currentOffset += 6;
2775            createLabel(startPc, context.currentMethodLabels);
2776            createLabel(startPc + length, context.currentMethodLabels);
2777          }
2778          break;
2779        case TypeReference.CAST:
2780        case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
2781        case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT:
2782        case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
2783        case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT:
2784          currentOffset += 4;
2785          break;
2786        case TypeReference.CLASS_EXTENDS:
2787        case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
2788        case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
2789        case TypeReference.THROWS:
2790        case TypeReference.EXCEPTION_PARAMETER:
2791        case TypeReference.INSTANCEOF:
2792        case TypeReference.NEW:
2793        case TypeReference.CONSTRUCTOR_REFERENCE:
2794        case TypeReference.METHOD_REFERENCE:
2795          currentOffset += 3;
2796          break;
2797        case TypeReference.CLASS_TYPE_PARAMETER:
2798        case TypeReference.METHOD_TYPE_PARAMETER:
2799        case TypeReference.METHOD_FORMAL_PARAMETER:
2800        case TypeReference.FIELD:
2801        case TypeReference.METHOD_RETURN:
2802        case TypeReference.METHOD_RECEIVER:
2803        default:
2804          // TypeReference type which can't be used in Code attribute, or which is unknown.
2805          throw new IllegalArgumentException();
2806      }
2807      // Parse the rest of the type_annotation structure, starting with the target_path structure
2808      // (whose size depends on its path_length field).
2809      int pathLength = readByte(currentOffset);
2810      if ((targetType >>> 24) == TypeReference.EXCEPTION_PARAMETER) {
2811        // Parse the target_path structure and create a corresponding TypePath.
2812        TypePath path = pathLength == 0 ? null : new TypePath(classFileBuffer, currentOffset);
2813        currentOffset += 1 + 2 * pathLength;
2814        // Parse the type_index field.
2815        String annotationDescriptor = readUTF8(currentOffset, charBuffer);
2816        currentOffset += 2;
2817        // Parse num_element_value_pairs and element_value_pairs and visit these values.
2818        currentOffset =
2819            readElementValues(
2820                methodVisitor.visitTryCatchAnnotation(
2821                    targetType & 0xFFFFFF00, path, annotationDescriptor, visible),
2822                currentOffset,
2823                /* named = */ true,
2824                charBuffer);
2825      } else {
2826        // We don't want to visit the other target_type annotations, so we just skip them (which
2827        // requires some parsing because the element_value_pairs array has a variable size). First,
2828        // skip the target_path structure:
2829        currentOffset += 3 + 2 * pathLength;
2830        // Then skip the num_element_value_pairs and element_value_pairs fields (by reading them
2831        // with a null AnnotationVisitor).
2832        currentOffset =
2833            readElementValues(
2834                /* annotationVisitor = */ null, currentOffset, /* named = */ true, charBuffer);
2835      }
2836    }
2837    return typeAnnotationsOffsets;
2838  }
2839
2840  /**
2841   * Returns the bytecode offset corresponding to the specified JVMS 'type_annotation' structure, or
2842   * -1 if there is no such type_annotation of if it does not have a bytecode offset.
2843   *
2844   * @param typeAnnotationOffsets the offset of each 'type_annotation' entry in a
2845   *     Runtime[In]VisibleTypeAnnotations attribute, or {@literal null}.
2846   * @param typeAnnotationIndex the index a 'type_annotation' entry in typeAnnotationOffsets.
2847   * @return bytecode offset corresponding to the specified JVMS 'type_annotation' structure, or -1
2848   *     if there is no such type_annotation of if it does not have a bytecode offset.
2849   */
2850  private int getTypeAnnotationBytecodeOffset(
2851      final int[] typeAnnotationOffsets, final int typeAnnotationIndex) {
2852    if (typeAnnotationOffsets == null
2853        || typeAnnotationIndex >= typeAnnotationOffsets.length
2854        || readByte(typeAnnotationOffsets[typeAnnotationIndex]) < TypeReference.INSTANCEOF) {
2855      return -1;
2856    }
2857    return readUnsignedShort(typeAnnotationOffsets[typeAnnotationIndex] + 1);
2858  }
2859
2860  /**
2861   * Parses the header of a JVMS type_annotation structure to extract its target_type, target_info
2862   * and target_path (the result is stored in the given context), and returns the start offset of
2863   * the rest of the type_annotation structure.
2864   *
2865   * @param context information about the class being parsed. This is where the extracted
2866   *     target_type and target_path must be stored.
2867   * @param typeAnnotationOffset the start offset of a type_annotation structure.
2868   * @return the start offset of the rest of the type_annotation structure.
2869   */
2870  private int readTypeAnnotationTarget(final Context context, final int typeAnnotationOffset) {
2871    int currentOffset = typeAnnotationOffset;
2872    // Parse and store the target_type structure.
2873    int targetType = readInt(typeAnnotationOffset);
2874    switch (targetType >>> 24) {
2875      case TypeReference.CLASS_TYPE_PARAMETER:
2876      case TypeReference.METHOD_TYPE_PARAMETER:
2877      case TypeReference.METHOD_FORMAL_PARAMETER:
2878        targetType &= 0xFFFF0000;
2879        currentOffset += 2;
2880        break;
2881      case TypeReference.FIELD:
2882      case TypeReference.METHOD_RETURN:
2883      case TypeReference.METHOD_RECEIVER:
2884        targetType &= 0xFF000000;
2885        currentOffset += 1;
2886        break;
2887      case TypeReference.LOCAL_VARIABLE:
2888      case TypeReference.RESOURCE_VARIABLE:
2889        targetType &= 0xFF000000;
2890        int tableLength = readUnsignedShort(currentOffset + 1);
2891        currentOffset += 3;
2892        context.currentLocalVariableAnnotationRangeStarts = new Label[tableLength];
2893        context.currentLocalVariableAnnotationRangeEnds = new Label[tableLength];
2894        context.currentLocalVariableAnnotationRangeIndices = new int[tableLength];
2895        for (int i = 0; i < tableLength; ++i) {
2896          int startPc = readUnsignedShort(currentOffset);
2897          int length = readUnsignedShort(currentOffset + 2);
2898          int index = readUnsignedShort(currentOffset + 4);
2899          currentOffset += 6;
2900          context.currentLocalVariableAnnotationRangeStarts[i] =
2901              createLabel(startPc, context.currentMethodLabels);
2902          context.currentLocalVariableAnnotationRangeEnds[i] =
2903              createLabel(startPc + length, context.currentMethodLabels);
2904          context.currentLocalVariableAnnotationRangeIndices[i] = index;
2905        }
2906        break;
2907      case TypeReference.CAST:
2908      case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
2909      case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT:
2910      case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
2911      case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT:
2912        targetType &= 0xFF0000FF;
2913        currentOffset += 4;
2914        break;
2915      case TypeReference.CLASS_EXTENDS:
2916      case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
2917      case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
2918      case TypeReference.THROWS:
2919      case TypeReference.EXCEPTION_PARAMETER:
2920        targetType &= 0xFFFFFF00;
2921        currentOffset += 3;
2922        break;
2923      case TypeReference.INSTANCEOF:
2924      case TypeReference.NEW:
2925      case TypeReference.CONSTRUCTOR_REFERENCE:
2926      case TypeReference.METHOD_REFERENCE:
2927        targetType &= 0xFF000000;
2928        currentOffset += 3;
2929        break;
2930      default:
2931        throw new IllegalArgumentException();
2932    }
2933    context.currentTypeAnnotationTarget = targetType;
2934    // Parse and store the target_path structure.
2935    int pathLength = readByte(currentOffset);
2936    context.currentTypeAnnotationTargetPath =
2937        pathLength == 0 ? null : new TypePath(classFileBuffer, currentOffset);
2938    // Return the start offset of the rest of the type_annotation structure.
2939    return currentOffset + 1 + 2 * pathLength;
2940  }
2941
2942  /**
2943   * Reads a Runtime[In]VisibleParameterAnnotations attribute and makes the given visitor visit it.
2944   *
2945   * @param methodVisitor the visitor that must visit the parameter annotations.
2946   * @param context information about the class being parsed.
2947   * @param runtimeParameterAnnotationsOffset the start offset of a
2948   *     Runtime[In]VisibleParameterAnnotations attribute, excluding the attribute_info's
2949   *     attribute_name_index and attribute_length fields.
2950   * @param visible true if the attribute to parse is a RuntimeVisibleParameterAnnotations
2951   *     attribute, false it is a RuntimeInvisibleParameterAnnotations attribute.
2952   */
2953  private void readParameterAnnotations(
2954      final MethodVisitor methodVisitor,
2955      final Context context,
2956      final int runtimeParameterAnnotationsOffset,
2957      final boolean visible) {
2958    int currentOffset = runtimeParameterAnnotationsOffset;
2959    int numParameters = classFileBuffer[currentOffset++] & 0xFF;
2960    methodVisitor.visitAnnotableParameterCount(numParameters, visible);
2961    char[] charBuffer = context.charBuffer;
2962    for (int i = 0; i < numParameters; ++i) {
2963      int numAnnotations = readUnsignedShort(currentOffset);
2964      currentOffset += 2;
2965      while (numAnnotations-- > 0) {
2966        // Parse the type_index field.
2967        String annotationDescriptor = readUTF8(currentOffset, charBuffer);
2968        currentOffset += 2;
2969        // Parse num_element_value_pairs and element_value_pairs and visit these values.
2970        currentOffset =
2971            readElementValues(
2972                methodVisitor.visitParameterAnnotation(i, annotationDescriptor, visible),
2973                currentOffset,
2974                /* named = */ true,
2975                charBuffer);
2976      }
2977    }
2978  }
2979
2980  /**
2981   * Reads the element values of a JVMS 'annotation' structure and makes the given visitor visit
2982   * them. This method can also be used to read the values of the JVMS 'array_value' field of an
2983   * annotation's 'element_value'.
2984   *
2985   * @param annotationVisitor the visitor that must visit the values.
2986   * @param annotationOffset the start offset of an 'annotation' structure (excluding its type_index
2987   *     field) or of an 'array_value' structure.
2988   * @param named if the annotation values are named or not. This should be true to parse the values
2989   *     of a JVMS 'annotation' structure, and false to parse the JVMS 'array_value' of an
2990   *     annotation's element_value.
2991   * @param charBuffer the buffer used to read strings in the constant pool.
2992   * @return the end offset of the JVMS 'annotation' or 'array_value' structure.
2993   */
2994  private int readElementValues(
2995      final AnnotationVisitor annotationVisitor,
2996      final int annotationOffset,
2997      final boolean named,
2998      final char[] charBuffer) {
2999    int currentOffset = annotationOffset;
3000    // Read the num_element_value_pairs field (or num_values field for an array_value).
3001    int numElementValuePairs = readUnsignedShort(currentOffset);
3002    currentOffset += 2;
3003    if (named) {
3004      // Parse the element_value_pairs array.
3005      while (numElementValuePairs-- > 0) {
3006        String elementName = readUTF8(currentOffset, charBuffer);
3007        currentOffset =
3008            readElementValue(annotationVisitor, currentOffset + 2, elementName, charBuffer);
3009      }
3010    } else {
3011      // Parse the array_value array.
3012      while (numElementValuePairs-- > 0) {
3013        currentOffset =
3014            readElementValue(annotationVisitor, currentOffset, /* elementName= */ null, charBuffer);
3015      }
3016    }
3017    if (annotationVisitor != null) {
3018      annotationVisitor.visitEnd();
3019    }
3020    return currentOffset;
3021  }
3022
3023  /**
3024   * Reads a JVMS 'element_value' structure and makes the given visitor visit it.
3025   *
3026   * @param annotationVisitor the visitor that must visit the element_value structure.
3027   * @param elementValueOffset the start offset in {@link #classFileBuffer} of the element_value
3028   *     structure to be read.
3029   * @param elementName the name of the element_value structure to be read, or {@literal null}.
3030   * @param charBuffer the buffer used to read strings in the constant pool.
3031   * @return the end offset of the JVMS 'element_value' structure.
3032   */
3033  private int readElementValue(
3034      final AnnotationVisitor annotationVisitor,
3035      final int elementValueOffset,
3036      final String elementName,
3037      final char[] charBuffer) {
3038    int currentOffset = elementValueOffset;
3039    if (annotationVisitor == null) {
3040      switch (classFileBuffer[currentOffset] & 0xFF) {
3041        case 'e': // enum_const_value
3042          return currentOffset + 5;
3043        case '@': // annotation_value
3044          return readElementValues(null, currentOffset + 3, /* named = */ true, charBuffer);
3045        case '[': // array_value
3046          return readElementValues(null, currentOffset + 1, /* named = */ false, charBuffer);
3047        default:
3048          return currentOffset + 3;
3049      }
3050    }
3051    switch (classFileBuffer[currentOffset++] & 0xFF) {
3052      case 'B': // const_value_index, CONSTANT_Integer
3053        annotationVisitor.visit(
3054            elementName, (byte) readInt(cpInfoOffsets[readUnsignedShort(currentOffset)]));
3055        currentOffset += 2;
3056        break;
3057      case 'C': // const_value_index, CONSTANT_Integer
3058        annotationVisitor.visit(
3059            elementName, (char) readInt(cpInfoOffsets[readUnsignedShort(currentOffset)]));
3060        currentOffset += 2;
3061        break;
3062      case 'D': // const_value_index, CONSTANT_Double
3063      case 'F': // const_value_index, CONSTANT_Float
3064      case 'I': // const_value_index, CONSTANT_Integer
3065      case 'J': // const_value_index, CONSTANT_Long
3066        annotationVisitor.visit(
3067            elementName, readConst(readUnsignedShort(currentOffset), charBuffer));
3068        currentOffset += 2;
3069        break;
3070      case 'S': // const_value_index, CONSTANT_Integer
3071        annotationVisitor.visit(
3072            elementName, (short) readInt(cpInfoOffsets[readUnsignedShort(currentOffset)]));
3073        currentOffset += 2;
3074        break;
3075
3076      case 'Z': // const_value_index, CONSTANT_Integer
3077        annotationVisitor.visit(
3078            elementName,
3079            readInt(cpInfoOffsets[readUnsignedShort(currentOffset)]) == 0
3080                ? Boolean.FALSE
3081                : Boolean.TRUE);
3082        currentOffset += 2;
3083        break;
3084      case 's': // const_value_index, CONSTANT_Utf8
3085        annotationVisitor.visit(elementName, readUTF8(currentOffset, charBuffer));
3086        currentOffset += 2;
3087        break;
3088      case 'e': // enum_const_value
3089        annotationVisitor.visitEnum(
3090            elementName,
3091            readUTF8(currentOffset, charBuffer),
3092            readUTF8(currentOffset + 2, charBuffer));
3093        currentOffset += 4;
3094        break;
3095      case 'c': // class_info
3096        annotationVisitor.visit(elementName, Type.getType(readUTF8(currentOffset, charBuffer)));
3097        currentOffset += 2;
3098        break;
3099      case '@': // annotation_value
3100        currentOffset =
3101            readElementValues(
3102                annotationVisitor.visitAnnotation(elementName, readUTF8(currentOffset, charBuffer)),
3103                currentOffset + 2,
3104                true,
3105                charBuffer);
3106        break;
3107      case '[': // array_value
3108        int numValues = readUnsignedShort(currentOffset);
3109        currentOffset += 2;
3110        if (numValues == 0) {
3111          return readElementValues(
3112              annotationVisitor.visitArray(elementName),
3113              currentOffset - 2,
3114              /* named = */ false,
3115              charBuffer);
3116        }
3117        switch (classFileBuffer[currentOffset] & 0xFF) {
3118          case 'B':
3119            byte[] byteValues = new byte[numValues];
3120            for (int i = 0; i < numValues; i++) {
3121              byteValues[i] = (byte) readInt(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]);
3122              currentOffset += 3;
3123            }
3124            annotationVisitor.visit(elementName, byteValues);
3125            break;
3126          case 'Z':
3127            boolean[] booleanValues = new boolean[numValues];
3128            for (int i = 0; i < numValues; i++) {
3129              booleanValues[i] = readInt(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]) != 0;
3130              currentOffset += 3;
3131            }
3132            annotationVisitor.visit(elementName, booleanValues);
3133            break;
3134          case 'S':
3135            short[] shortValues = new short[numValues];
3136            for (int i = 0; i < numValues; i++) {
3137              shortValues[i] = (short) readInt(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]);
3138              currentOffset += 3;
3139            }
3140            annotationVisitor.visit(elementName, shortValues);
3141            break;
3142          case 'C':
3143            char[] charValues = new char[numValues];
3144            for (int i = 0; i < numValues; i++) {
3145              charValues[i] = (char) readInt(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]);
3146              currentOffset += 3;
3147            }
3148            annotationVisitor.visit(elementName, charValues);
3149            break;
3150          case 'I':
3151            int[] intValues = new int[numValues];
3152            for (int i = 0; i < numValues; i++) {
3153              intValues[i] = readInt(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]);
3154              currentOffset += 3;
3155            }
3156            annotationVisitor.visit(elementName, intValues);
3157            break;
3158          case 'J':
3159            long[] longValues = new long[numValues];
3160            for (int i = 0; i < numValues; i++) {
3161              longValues[i] = readLong(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]);
3162              currentOffset += 3;
3163            }
3164            annotationVisitor.visit(elementName, longValues);
3165            break;
3166          case 'F':
3167            float[] floatValues = new float[numValues];
3168            for (int i = 0; i < numValues; i++) {
3169              floatValues[i] =
3170                  Float.intBitsToFloat(
3171                      readInt(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]));
3172              currentOffset += 3;
3173            }
3174            annotationVisitor.visit(elementName, floatValues);
3175            break;
3176          case 'D':
3177            double[] doubleValues = new double[numValues];
3178            for (int i = 0; i < numValues; i++) {
3179              doubleValues[i] =
3180                  Double.longBitsToDouble(
3181                      readLong(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]));
3182              currentOffset += 3;
3183            }
3184            annotationVisitor.visit(elementName, doubleValues);
3185            break;
3186          default:
3187            currentOffset =
3188                readElementValues(
3189                    annotationVisitor.visitArray(elementName),
3190                    currentOffset - 2,
3191                    /* named = */ false,
3192                    charBuffer);
3193            break;
3194        }
3195        break;
3196      default:
3197        throw new IllegalArgumentException();
3198    }
3199    return currentOffset;
3200  }
3201
3202  // ----------------------------------------------------------------------------------------------
3203  // Methods to parse stack map frames
3204  // ----------------------------------------------------------------------------------------------
3205
3206  /**
3207   * Computes the implicit frame of the method currently being parsed (as defined in the given
3208   * {@link Context}) and stores it in the given context.
3209   *
3210   * @param context information about the class being parsed.
3211   */
3212  private void computeImplicitFrame(final Context context) {
3213    String methodDescriptor = context.currentMethodDescriptor;
3214    Object[] locals = context.currentFrameLocalTypes;
3215    int numLocal = 0;
3216    if ((context.currentMethodAccessFlags & Opcodes.ACC_STATIC) == 0) {
3217      if ("<init>".equals(context.currentMethodName)) {
3218        locals[numLocal++] = Opcodes.UNINITIALIZED_THIS;
3219      } else {
3220        locals[numLocal++] = readClass(header + 2, context.charBuffer);
3221      }
3222    }
3223    // Parse the method descriptor, one argument type descriptor at each iteration. Start by
3224    // skipping the first method descriptor character, which is always '('.
3225    int currentMethodDescritorOffset = 1;
3226    while (true) {
3227      int currentArgumentDescriptorStartOffset = currentMethodDescritorOffset;
3228      switch (methodDescriptor.charAt(currentMethodDescritorOffset++)) {
3229        case 'Z':
3230        case 'C':
3231        case 'B':
3232        case 'S':
3233        case 'I':
3234          locals[numLocal++] = Opcodes.INTEGER;
3235          break;
3236        case 'F':
3237          locals[numLocal++] = Opcodes.FLOAT;
3238          break;
3239        case 'J':
3240          locals[numLocal++] = Opcodes.LONG;
3241          break;
3242        case 'D':
3243          locals[numLocal++] = Opcodes.DOUBLE;
3244          break;
3245        case '[':
3246          while (methodDescriptor.charAt(currentMethodDescritorOffset) == '[') {
3247            ++currentMethodDescritorOffset;
3248          }
3249          if (methodDescriptor.charAt(currentMethodDescritorOffset) == 'L') {
3250            ++currentMethodDescritorOffset;
3251            while (methodDescriptor.charAt(currentMethodDescritorOffset) != ';') {
3252              ++currentMethodDescritorOffset;
3253            }
3254          }
3255          locals[numLocal++] =
3256              methodDescriptor.substring(
3257                  currentArgumentDescriptorStartOffset, ++currentMethodDescritorOffset);
3258          break;
3259        case 'L':
3260          while (methodDescriptor.charAt(currentMethodDescritorOffset) != ';') {
3261            ++currentMethodDescritorOffset;
3262          }
3263          locals[numLocal++] =
3264              methodDescriptor.substring(
3265                  currentArgumentDescriptorStartOffset + 1, currentMethodDescritorOffset++);
3266          break;
3267        default:
3268          context.currentFrameLocalCount = numLocal;
3269          return;
3270      }
3271    }
3272  }
3273
3274  /**
3275   * Reads a JVMS 'stack_map_frame' structure and stores the result in the given {@link Context}
3276   * object. This method can also be used to read a full_frame structure, excluding its frame_type
3277   * field (this is used to parse the legacy StackMap attributes).
3278   *
3279   * @param stackMapFrameOffset the start offset in {@link #classFileBuffer} of the
3280   *     stack_map_frame_value structure to be read, or the start offset of a full_frame structure
3281   *     (excluding its frame_type field).
3282   * @param compressed true to read a 'stack_map_frame' structure, false to read a 'full_frame'
3283   *     structure without its frame_type field.
3284   * @param expand if the stack map frame must be expanded. See {@link #EXPAND_FRAMES}.
3285   * @param context where the parsed stack map frame must be stored.
3286   * @return the end offset of the JVMS 'stack_map_frame' or 'full_frame' structure.
3287   */
3288  private int readStackMapFrame(
3289      final int stackMapFrameOffset,
3290      final boolean compressed,
3291      final boolean expand,
3292      final Context context) {
3293    int currentOffset = stackMapFrameOffset;
3294    final char[] charBuffer = context.charBuffer;
3295    final Label[] labels = context.currentMethodLabels;
3296    int frameType;
3297    if (compressed) {
3298      // Read the frame_type field.
3299      frameType = classFileBuffer[currentOffset++] & 0xFF;
3300    } else {
3301      frameType = Frame.FULL_FRAME;
3302      context.currentFrameOffset = -1;
3303    }
3304    int offsetDelta;
3305    context.currentFrameLocalCountDelta = 0;
3306    if (frameType < Frame.SAME_LOCALS_1_STACK_ITEM_FRAME) {
3307      offsetDelta = frameType;
3308      context.currentFrameType = Opcodes.F_SAME;
3309      context.currentFrameStackCount = 0;
3310    } else if (frameType < Frame.RESERVED) {
3311      offsetDelta = frameType - Frame.SAME_LOCALS_1_STACK_ITEM_FRAME;
3312      currentOffset =
3313          readVerificationTypeInfo(
3314              currentOffset, context.currentFrameStackTypes, 0, charBuffer, labels);
3315      context.currentFrameType = Opcodes.F_SAME1;
3316      context.currentFrameStackCount = 1;
3317    } else if (frameType >= Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
3318      offsetDelta = readUnsignedShort(currentOffset);
3319      currentOffset += 2;
3320      if (frameType == Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
3321        currentOffset =
3322            readVerificationTypeInfo(
3323                currentOffset, context.currentFrameStackTypes, 0, charBuffer, labels);
3324        context.currentFrameType = Opcodes.F_SAME1;
3325        context.currentFrameStackCount = 1;
3326      } else if (frameType >= Frame.CHOP_FRAME && frameType < Frame.SAME_FRAME_EXTENDED) {
3327        context.currentFrameType = Opcodes.F_CHOP;
3328        context.currentFrameLocalCountDelta = Frame.SAME_FRAME_EXTENDED - frameType;
3329        context.currentFrameLocalCount -= context.currentFrameLocalCountDelta;
3330        context.currentFrameStackCount = 0;
3331      } else if (frameType == Frame.SAME_FRAME_EXTENDED) {
3332        context.currentFrameType = Opcodes.F_SAME;
3333        context.currentFrameStackCount = 0;
3334      } else if (frameType < Frame.FULL_FRAME) {
3335        int local = expand ? context.currentFrameLocalCount : 0;
3336        for (int k = frameType - Frame.SAME_FRAME_EXTENDED; k > 0; k--) {
3337          currentOffset =
3338              readVerificationTypeInfo(
3339                  currentOffset, context.currentFrameLocalTypes, local++, charBuffer, labels);
3340        }
3341        context.currentFrameType = Opcodes.F_APPEND;
3342        context.currentFrameLocalCountDelta = frameType - Frame.SAME_FRAME_EXTENDED;
3343        context.currentFrameLocalCount += context.currentFrameLocalCountDelta;
3344        context.currentFrameStackCount = 0;
3345      } else {
3346        final int numberOfLocals = readUnsignedShort(currentOffset);
3347        currentOffset += 2;
3348        context.currentFrameType = Opcodes.F_FULL;
3349        context.currentFrameLocalCountDelta = numberOfLocals;
3350        context.currentFrameLocalCount = numberOfLocals;
3351        for (int local = 0; local < numberOfLocals; ++local) {
3352          currentOffset =
3353              readVerificationTypeInfo(
3354                  currentOffset, context.currentFrameLocalTypes, local, charBuffer, labels);
3355        }
3356        final int numberOfStackItems = readUnsignedShort(currentOffset);
3357        currentOffset += 2;
3358        context.currentFrameStackCount = numberOfStackItems;
3359        for (int stack = 0; stack < numberOfStackItems; ++stack) {
3360          currentOffset =
3361              readVerificationTypeInfo(
3362                  currentOffset, context.currentFrameStackTypes, stack, charBuffer, labels);
3363        }
3364      }
3365    } else {
3366      throw new IllegalArgumentException();
3367    }
3368    context.currentFrameOffset += offsetDelta + 1;
3369    createLabel(context.currentFrameOffset, labels);
3370    return currentOffset;
3371  }
3372
3373  /**
3374   * Reads a JVMS 'verification_type_info' structure and stores it at the given index in the given
3375   * array.
3376   *
3377   * @param verificationTypeInfoOffset the start offset of the 'verification_type_info' structure to
3378   *     read.
3379   * @param frame the array where the parsed type must be stored.
3380   * @param index the index in 'frame' where the parsed type must be stored.
3381   * @param charBuffer the buffer used to read strings in the constant pool.
3382   * @param labels the labels of the method currently being parsed, indexed by their offset. If the
3383   *     parsed type is an ITEM_Uninitialized, a new label for the corresponding NEW instruction is
3384   *     stored in this array if it does not already exist.
3385   * @return the end offset of the JVMS 'verification_type_info' structure.
3386   */
3387  private int readVerificationTypeInfo(
3388      final int verificationTypeInfoOffset,
3389      final Object[] frame,
3390      final int index,
3391      final char[] charBuffer,
3392      final Label[] labels) {
3393    int currentOffset = verificationTypeInfoOffset;
3394    int tag = classFileBuffer[currentOffset++] & 0xFF;
3395    switch (tag) {
3396      case Frame.ITEM_TOP:
3397        frame[index] = Opcodes.TOP;
3398        break;
3399      case Frame.ITEM_INTEGER:
3400        frame[index] = Opcodes.INTEGER;
3401        break;
3402      case Frame.ITEM_FLOAT:
3403        frame[index] = Opcodes.FLOAT;
3404        break;
3405      case Frame.ITEM_DOUBLE:
3406        frame[index] = Opcodes.DOUBLE;
3407        break;
3408      case Frame.ITEM_LONG:
3409        frame[index] = Opcodes.LONG;
3410        break;
3411      case Frame.ITEM_NULL:
3412        frame[index] = Opcodes.NULL;
3413        break;
3414      case Frame.ITEM_UNINITIALIZED_THIS:
3415        frame[index] = Opcodes.UNINITIALIZED_THIS;
3416        break;
3417      case Frame.ITEM_OBJECT:
3418        frame[index] = readClass(currentOffset, charBuffer);
3419        currentOffset += 2;
3420        break;
3421      case Frame.ITEM_UNINITIALIZED:
3422        frame[index] = createLabel(readUnsignedShort(currentOffset), labels);
3423        currentOffset += 2;
3424        break;
3425      default:
3426        throw new IllegalArgumentException();
3427    }
3428    return currentOffset;
3429  }
3430
3431  // ----------------------------------------------------------------------------------------------
3432  // Methods to parse attributes
3433  // ----------------------------------------------------------------------------------------------
3434
3435  /**
3436   * Returns the offset in {@link #classFileBuffer} of the first ClassFile's 'attributes' array
3437   * field entry.
3438   *
3439   * @return the offset in {@link #classFileBuffer} of the first ClassFile's 'attributes' array
3440   *     field entry.
3441   */
3442  final int getFirstAttributeOffset() {
3443    // Skip the access_flags, this_class, super_class, and interfaces_count fields (using 2 bytes
3444    // each), as well as the interfaces array field (2 bytes per interface).
3445    int currentOffset = header + 8 + readUnsignedShort(header + 6) * 2;
3446
3447    // Read the fields_count field.
3448    int fieldsCount = readUnsignedShort(currentOffset);
3449    currentOffset += 2;
3450    // Skip the 'fields' array field.
3451    while (fieldsCount-- > 0) {
3452      // Invariant: currentOffset is the offset of a field_info structure.
3453      // Skip the access_flags, name_index and descriptor_index fields (2 bytes each), and read the
3454      // attributes_count field.
3455      int attributesCount = readUnsignedShort(currentOffset + 6);
3456      currentOffset += 8;
3457      // Skip the 'attributes' array field.
3458      while (attributesCount-- > 0) {
3459        // Invariant: currentOffset is the offset of an attribute_info structure.
3460        // Read the attribute_length field (2 bytes after the start of the attribute_info) and skip
3461        // this many bytes, plus 6 for the attribute_name_index and attribute_length fields
3462        // (yielding the total size of the attribute_info structure).
3463        currentOffset += 6 + readInt(currentOffset + 2);
3464      }
3465    }
3466
3467    // Skip the methods_count and 'methods' fields, using the same method as above.
3468    int methodsCount = readUnsignedShort(currentOffset);
3469    currentOffset += 2;
3470    while (methodsCount-- > 0) {
3471      int attributesCount = readUnsignedShort(currentOffset + 6);
3472      currentOffset += 8;
3473      while (attributesCount-- > 0) {
3474        currentOffset += 6 + readInt(currentOffset + 2);
3475      }
3476    }
3477
3478    // Skip the ClassFile's attributes_count field.
3479    return currentOffset + 2;
3480  }
3481
3482  /**
3483   * Reads the BootstrapMethods attribute to compute the offset of each bootstrap method.
3484   *
3485   * @param maxStringLength a conservative estimate of the maximum length of the strings contained
3486   *     in the constant pool of the class.
3487   * @return the offsets of the bootstrap methods.
3488   */
3489  private int[] readBootstrapMethodsAttribute(final int maxStringLength) {
3490    char[] charBuffer = new char[maxStringLength];
3491    int currentAttributeOffset = getFirstAttributeOffset();
3492    for (int i = readUnsignedShort(currentAttributeOffset - 2); i > 0; --i) {
3493      // Read the attribute_info's attribute_name and attribute_length fields.
3494      String attributeName = readUTF8(currentAttributeOffset, charBuffer);
3495      int attributeLength = readInt(currentAttributeOffset + 2);
3496      currentAttributeOffset += 6;
3497      if (Constants.BOOTSTRAP_METHODS.equals(attributeName)) {
3498        // Read the num_bootstrap_methods field and create an array of this size.
3499        int[] result = new int[readUnsignedShort(currentAttributeOffset)];
3500        // Compute and store the offset of each 'bootstrap_methods' array field entry.
3501        int currentBootstrapMethodOffset = currentAttributeOffset + 2;
3502        for (int j = 0; j < result.length; ++j) {
3503          result[j] = currentBootstrapMethodOffset;
3504          // Skip the bootstrap_method_ref and num_bootstrap_arguments fields (2 bytes each),
3505          // as well as the bootstrap_arguments array field (of size num_bootstrap_arguments * 2).
3506          currentBootstrapMethodOffset +=
3507              4 + readUnsignedShort(currentBootstrapMethodOffset + 2) * 2;
3508        }
3509        return result;
3510      }
3511      currentAttributeOffset += attributeLength;
3512    }
3513    throw new IllegalArgumentException();
3514  }
3515
3516  /**
3517   * Reads a non standard JVMS 'attribute' structure in {@link #classFileBuffer}.
3518   *
3519   * @param attributePrototypes prototypes of the attributes that must be parsed during the visit of
3520   *     the class. Any attribute whose type is not equal to the type of one the prototypes will not
3521   *     be parsed: its byte array value will be passed unchanged to the ClassWriter.
3522   * @param type the type of the attribute.
3523   * @param offset the start offset of the JVMS 'attribute' structure in {@link #classFileBuffer}.
3524   *     The 6 attribute header bytes (attribute_name_index and attribute_length) are not taken into
3525   *     account here.
3526   * @param length the length of the attribute's content (excluding the 6 attribute header bytes).
3527   * @param charBuffer the buffer to be used to read strings in the constant pool.
3528   * @param codeAttributeOffset the start offset of the enclosing Code attribute in {@link
3529   *     #classFileBuffer}, or -1 if the attribute to be read is not a code attribute. The 6
3530   *     attribute header bytes (attribute_name_index and attribute_length) are not taken into
3531   *     account here.
3532   * @param labels the labels of the method's code, or {@literal null} if the attribute to be read
3533   *     is not a code attribute.
3534   * @return the attribute that has been read.
3535   */
3536  private Attribute readAttribute(
3537      final Attribute[] attributePrototypes,
3538      final String type,
3539      final int offset,
3540      final int length,
3541      final char[] charBuffer,
3542      final int codeAttributeOffset,
3543      final Label[] labels) {
3544    for (Attribute attributePrototype : attributePrototypes) {
3545      if (attributePrototype.type.equals(type)) {
3546        return attributePrototype.read(
3547            this, offset, length, charBuffer, codeAttributeOffset, labels);
3548      }
3549    }
3550    return new Attribute(type).read(this, offset, length, null, -1, null);
3551  }
3552
3553  // -----------------------------------------------------------------------------------------------
3554  // Utility methods: low level parsing
3555  // -----------------------------------------------------------------------------------------------
3556
3557  /**
3558   * Returns the number of entries in the class's constant pool table.
3559   *
3560   * @return the number of entries in the class's constant pool table.
3561   */
3562  public int getItemCount() {
3563    return cpInfoOffsets.length;
3564  }
3565
3566  /**
3567   * Returns the start offset in this {@link ClassReader} of a JVMS 'cp_info' structure (i.e. a
3568   * constant pool entry), plus one. <i>This method is intended for {@link Attribute} sub classes,
3569   * and is normally not needed by class generators or adapters.</i>
3570   *
3571   * @param constantPoolEntryIndex the index a constant pool entry in the class's constant pool
3572   *     table.
3573   * @return the start offset in this {@link ClassReader} of the corresponding JVMS 'cp_info'
3574   *     structure, plus one.
3575   */
3576  public int getItem(final int constantPoolEntryIndex) {
3577    return cpInfoOffsets[constantPoolEntryIndex];
3578  }
3579
3580  /**
3581   * Returns a conservative estimate of the maximum length of the strings contained in the class's
3582   * constant pool table.
3583   *
3584   * @return a conservative estimate of the maximum length of the strings contained in the class's
3585   *     constant pool table.
3586   */
3587  public int getMaxStringLength() {
3588    return maxStringLength;
3589  }
3590
3591  /**
3592   * Reads a byte value in this {@link ClassReader}. <i>This method is intended for {@link
3593   * Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
3594   *
3595   * @param offset the start offset of the value to be read in this {@link ClassReader}.
3596   * @return the read value.
3597   */
3598  public int readByte(final int offset) {
3599    return classFileBuffer[offset] & 0xFF;
3600  }
3601
3602  /**
3603   * Reads an unsigned short value in this {@link ClassReader}. <i>This method is intended for
3604   * {@link Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
3605   *
3606   * @param offset the start index of the value to be read in this {@link ClassReader}.
3607   * @return the read value.
3608   */
3609  public int readUnsignedShort(final int offset) {
3610    byte[] classBuffer = classFileBuffer;
3611    return ((classBuffer[offset] & 0xFF) << 8) | (classBuffer[offset + 1] & 0xFF);
3612  }
3613
3614  /**
3615   * Reads a signed short value in this {@link ClassReader}. <i>This method is intended for {@link
3616   * Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
3617   *
3618   * @param offset the start offset of the value to be read in this {@link ClassReader}.
3619   * @return the read value.
3620   */
3621  public short readShort(final int offset) {
3622    byte[] classBuffer = classFileBuffer;
3623    return (short) (((classBuffer[offset] & 0xFF) << 8) | (classBuffer[offset + 1] & 0xFF));
3624  }
3625
3626  /**
3627   * Reads a signed int value in this {@link ClassReader}. <i>This method is intended for {@link
3628   * Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
3629   *
3630   * @param offset the start offset of the value to be read in this {@link ClassReader}.
3631   * @return the read value.
3632   */
3633  public int readInt(final int offset) {
3634    byte[] classBuffer = classFileBuffer;
3635    return ((classBuffer[offset] & 0xFF) << 24)
3636        | ((classBuffer[offset + 1] & 0xFF) << 16)
3637        | ((classBuffer[offset + 2] & 0xFF) << 8)
3638        | (classBuffer[offset + 3] & 0xFF);
3639  }
3640
3641  /**
3642   * Reads a signed long value in this {@link ClassReader}. <i>This method is intended for {@link
3643   * Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
3644   *
3645   * @param offset the start offset of the value to be read in this {@link ClassReader}.
3646   * @return the read value.
3647   */
3648  public long readLong(final int offset) {
3649    long l1 = readInt(offset);
3650    long l0 = readInt(offset + 4) & 0xFFFFFFFFL;
3651    return (l1 << 32) | l0;
3652  }
3653
3654  /**
3655   * Reads a CONSTANT_Utf8 constant pool entry in this {@link ClassReader}. <i>This method is
3656   * intended for {@link Attribute} sub classes, and is normally not needed by class generators or
3657   * adapters.</i>
3658   *
3659   * @param offset the start offset of an unsigned short value in this {@link ClassReader}, whose
3660   *     value is the index of a CONSTANT_Utf8 entry in the class's constant pool table.
3661   * @param charBuffer the buffer to be used to read the string. This buffer must be sufficiently
3662   *     large. It is not automatically resized.
3663   * @return the String corresponding to the specified CONSTANT_Utf8 entry.
3664   */
3665  // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
3666  public String readUTF8(final int offset, final char[] charBuffer) {
3667    int constantPoolEntryIndex = readUnsignedShort(offset);
3668    if (offset == 0 || constantPoolEntryIndex == 0) {
3669      return null;
3670    }
3671    return readUtf(constantPoolEntryIndex, charBuffer);
3672  }
3673
3674  /**
3675   * Reads a CONSTANT_Utf8 constant pool entry in {@link #classFileBuffer}.
3676   *
3677   * @param constantPoolEntryIndex the index of a CONSTANT_Utf8 entry in the class's constant pool
3678   *     table.
3679   * @param charBuffer the buffer to be used to read the string. This buffer must be sufficiently
3680   *     large. It is not automatically resized.
3681   * @return the String corresponding to the specified CONSTANT_Utf8 entry.
3682   */
3683  final String readUtf(final int constantPoolEntryIndex, final char[] charBuffer) {
3684    String value = constantUtf8Values[constantPoolEntryIndex];
3685    if (value != null) {
3686      return value;
3687    }
3688    int cpInfoOffset = cpInfoOffsets[constantPoolEntryIndex];
3689    return constantUtf8Values[constantPoolEntryIndex] =
3690        readUtf(cpInfoOffset + 2, readUnsignedShort(cpInfoOffset), charBuffer);
3691  }
3692
3693  /**
3694   * Reads an UTF8 string in {@link #classFileBuffer}.
3695   *
3696   * @param utfOffset the start offset of the UTF8 string to be read.
3697   * @param utfLength the length of the UTF8 string to be read.
3698   * @param charBuffer the buffer to be used to read the string. This buffer must be sufficiently
3699   *     large. It is not automatically resized.
3700   * @return the String corresponding to the specified UTF8 string.
3701   */
3702  private String readUtf(final int utfOffset, final int utfLength, final char[] charBuffer) {
3703    int currentOffset = utfOffset;
3704    int endOffset = currentOffset + utfLength;
3705    int strLength = 0;
3706    byte[] classBuffer = classFileBuffer;
3707    while (currentOffset < endOffset) {
3708      int currentByte = classBuffer[currentOffset++];
3709      if ((currentByte & 0x80) == 0) {
3710        charBuffer[strLength++] = (char) (currentByte & 0x7F);
3711      } else if ((currentByte & 0xE0) == 0xC0) {
3712        charBuffer[strLength++] =
3713            (char) (((currentByte & 0x1F) << 6) + (classBuffer[currentOffset++] & 0x3F));
3714      } else {
3715        charBuffer[strLength++] =
3716            (char)
3717                (((currentByte & 0xF) << 12)
3718                    + ((classBuffer[currentOffset++] & 0x3F) << 6)
3719                    + (classBuffer[currentOffset++] & 0x3F));
3720      }
3721    }
3722    return new String(charBuffer, 0, strLength);
3723  }
3724
3725  /**
3726   * Reads a CONSTANT_Class, CONSTANT_String, CONSTANT_MethodType, CONSTANT_Module or
3727   * CONSTANT_Package constant pool entry in {@link #classFileBuffer}. <i>This method is intended
3728   * for {@link Attribute} sub classes, and is normally not needed by class generators or
3729   * adapters.</i>
3730   *
3731   * @param offset the start offset of an unsigned short value in {@link #classFileBuffer}, whose
3732   *     value is the index of a CONSTANT_Class, CONSTANT_String, CONSTANT_MethodType,
3733   *     CONSTANT_Module or CONSTANT_Package entry in class's constant pool table.
3734   * @param charBuffer the buffer to be used to read the item. This buffer must be sufficiently
3735   *     large. It is not automatically resized.
3736   * @return the String corresponding to the specified constant pool entry.
3737   */
3738  private String readStringish(final int offset, final char[] charBuffer) {
3739    // Get the start offset of the cp_info structure (plus one), and read the CONSTANT_Utf8 entry
3740    // designated by the first two bytes of this cp_info.
3741    return readUTF8(cpInfoOffsets[readUnsignedShort(offset)], charBuffer);
3742  }
3743
3744  /**
3745   * Reads a CONSTANT_Class constant pool entry in this {@link ClassReader}. <i>This method is
3746   * intended for {@link Attribute} sub classes, and is normally not needed by class generators or
3747   * adapters.</i>
3748   *
3749   * @param offset the start offset of an unsigned short value in this {@link ClassReader}, whose
3750   *     value is the index of a CONSTANT_Class entry in class's constant pool table.
3751   * @param charBuffer the buffer to be used to read the item. This buffer must be sufficiently
3752   *     large. It is not automatically resized.
3753   * @return the String corresponding to the specified CONSTANT_Class entry.
3754   */
3755  public String readClass(final int offset, final char[] charBuffer) {
3756    return readStringish(offset, charBuffer);
3757  }
3758
3759  /**
3760   * Reads a CONSTANT_Module constant pool entry in this {@link ClassReader}. <i>This method is
3761   * intended for {@link Attribute} sub classes, and is normally not needed by class generators or
3762   * adapters.</i>
3763   *
3764   * @param offset the start offset of an unsigned short value in this {@link ClassReader}, whose
3765   *     value is the index of a CONSTANT_Module entry in class's constant pool table.
3766   * @param charBuffer the buffer to be used to read the item. This buffer must be sufficiently
3767   *     large. It is not automatically resized.
3768   * @return the String corresponding to the specified CONSTANT_Module entry.
3769   */
3770  public String readModule(final int offset, final char[] charBuffer) {
3771    return readStringish(offset, charBuffer);
3772  }
3773
3774  /**
3775   * Reads a CONSTANT_Package constant pool entry in this {@link ClassReader}. <i>This method is
3776   * intended for {@link Attribute} sub classes, and is normally not needed by class generators or
3777   * adapters.</i>
3778   *
3779   * @param offset the start offset of an unsigned short value in this {@link ClassReader}, whose
3780   *     value is the index of a CONSTANT_Package entry in class's constant pool table.
3781   * @param charBuffer the buffer to be used to read the item. This buffer must be sufficiently
3782   *     large. It is not automatically resized.
3783   * @return the String corresponding to the specified CONSTANT_Package entry.
3784   */
3785  public String readPackage(final int offset, final char[] charBuffer) {
3786    return readStringish(offset, charBuffer);
3787  }
3788
3789  /**
3790   * Reads a CONSTANT_Dynamic constant pool entry in {@link #classFileBuffer}.
3791   *
3792   * @param constantPoolEntryIndex the index of a CONSTANT_Dynamic entry in the class's constant
3793   *     pool table.
3794   * @param charBuffer the buffer to be used to read the string. This buffer must be sufficiently
3795   *     large. It is not automatically resized.
3796   * @return the ConstantDynamic corresponding to the specified CONSTANT_Dynamic entry.
3797   */
3798  private ConstantDynamic readConstantDynamic(
3799      final int constantPoolEntryIndex, final char[] charBuffer) {
3800    ConstantDynamic constantDynamic = constantDynamicValues[constantPoolEntryIndex];
3801    if (constantDynamic != null) {
3802      return constantDynamic;
3803    }
3804    int cpInfoOffset = cpInfoOffsets[constantPoolEntryIndex];
3805    int nameAndTypeCpInfoOffset = cpInfoOffsets[readUnsignedShort(cpInfoOffset + 2)];
3806    String name = readUTF8(nameAndTypeCpInfoOffset, charBuffer);
3807    String descriptor = readUTF8(nameAndTypeCpInfoOffset + 2, charBuffer);
3808    int bootstrapMethodOffset = bootstrapMethodOffsets[readUnsignedShort(cpInfoOffset)];
3809    Handle handle = (Handle) readConst(readUnsignedShort(bootstrapMethodOffset), charBuffer);
3810    Object[] bootstrapMethodArguments = new Object[readUnsignedShort(bootstrapMethodOffset + 2)];
3811    bootstrapMethodOffset += 4;
3812    for (int i = 0; i < bootstrapMethodArguments.length; i++) {
3813      bootstrapMethodArguments[i] = readConst(readUnsignedShort(bootstrapMethodOffset), charBuffer);
3814      bootstrapMethodOffset += 2;
3815    }
3816    return constantDynamicValues[constantPoolEntryIndex] =
3817        new ConstantDynamic(name, descriptor, handle, bootstrapMethodArguments);
3818  }
3819
3820  /**
3821   * Reads a numeric or string constant pool entry in this {@link ClassReader}. <i>This method is
3822   * intended for {@link Attribute} sub classes, and is normally not needed by class generators or
3823   * adapters.</i>
3824   *
3825   * @param constantPoolEntryIndex the index of a CONSTANT_Integer, CONSTANT_Float, CONSTANT_Long,
3826   *     CONSTANT_Double, CONSTANT_Class, CONSTANT_String, CONSTANT_MethodType,
3827   *     CONSTANT_MethodHandle or CONSTANT_Dynamic entry in the class's constant pool.
3828   * @param charBuffer the buffer to be used to read strings. This buffer must be sufficiently
3829   *     large. It is not automatically resized.
3830   * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double}, {@link String},
3831   *     {@link Type}, {@link Handle} or {@link ConstantDynamic} corresponding to the specified
3832   *     constant pool entry.
3833   */
3834  public Object readConst(final int constantPoolEntryIndex, final char[] charBuffer) {
3835    int cpInfoOffset = cpInfoOffsets[constantPoolEntryIndex];
3836    switch (classFileBuffer[cpInfoOffset - 1]) {
3837      case Symbol.CONSTANT_INTEGER_TAG:
3838        return readInt(cpInfoOffset);
3839      case Symbol.CONSTANT_FLOAT_TAG:
3840        return Float.intBitsToFloat(readInt(cpInfoOffset));
3841      case Symbol.CONSTANT_LONG_TAG:
3842        return readLong(cpInfoOffset);
3843      case Symbol.CONSTANT_DOUBLE_TAG:
3844        return Double.longBitsToDouble(readLong(cpInfoOffset));
3845      case Symbol.CONSTANT_CLASS_TAG:
3846        return Type.getObjectType(readUTF8(cpInfoOffset, charBuffer));
3847      case Symbol.CONSTANT_STRING_TAG:
3848        return readUTF8(cpInfoOffset, charBuffer);
3849      case Symbol.CONSTANT_METHOD_TYPE_TAG:
3850        return Type.getMethodType(readUTF8(cpInfoOffset, charBuffer));
3851      case Symbol.CONSTANT_METHOD_HANDLE_TAG:
3852        int referenceKind = readByte(cpInfoOffset);
3853        int referenceCpInfoOffset = cpInfoOffsets[readUnsignedShort(cpInfoOffset + 1)];
3854        int nameAndTypeCpInfoOffset = cpInfoOffsets[readUnsignedShort(referenceCpInfoOffset + 2)];
3855        String owner = readClass(referenceCpInfoOffset, charBuffer);
3856        String name = readUTF8(nameAndTypeCpInfoOffset, charBuffer);
3857        String descriptor = readUTF8(nameAndTypeCpInfoOffset + 2, charBuffer);
3858        boolean isInterface =
3859            classFileBuffer[referenceCpInfoOffset - 1] == Symbol.CONSTANT_INTERFACE_METHODREF_TAG;
3860        return new Handle(referenceKind, owner, name, descriptor, isInterface);
3861      case Symbol.CONSTANT_DYNAMIC_TAG:
3862        return readConstantDynamic(constantPoolEntryIndex, charBuffer);
3863      default:
3864        throw new IllegalArgumentException();
3865    }
3866  }
3867}