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