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