1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.  Oracle designates this
   7  * particular file as subject to the "Classpath" exception as provided
   8  * by Oracle in the LICENSE file that accompanied this code.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 /*
  26  * This file is available under and governed by the GNU General Public
  27  * License version 2 only, as published by the Free Software Foundation.
  28  * However, the following notice accompanied the original version of this
  29  * file:
  30  *
  31  * ASM: a very small and fast Java bytecode manipulation framework
  32  * Copyright (c) 2000-2011 INRIA, France Telecom
  33  * All rights reserved.
  34  *
  35  * Redistribution and use in source and binary forms, with or without
  36  * modification, are permitted provided that the following conditions
  37  * are met:
  38  * 1. Redistributions of source code must retain the above copyright
  39  *    notice, this list of conditions and the following disclaimer.
  40  * 2. Redistributions in binary form must reproduce the above copyright
  41  *    notice, this list of conditions and the following disclaimer in the
  42  *    documentation and/or other materials provided with the distribution.
  43  * 3. Neither the name of the copyright holders nor the names of its
  44  *    contributors may be used to endorse or promote products derived from
  45  *    this software without specific prior written permission.
  46  *
  47  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  48  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  50  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  51  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  52  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  53  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  54  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  55  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  56  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  57  * THE POSSIBILITY OF SUCH DAMAGE.
  58  */
  59 package jdk.internal.org.objectweb.asm;
  60 
  61 /**
  62  * A {@link MethodVisitor} that generates a corresponding 'method_info' structure, as defined in the
  63  * Java Virtual Machine Specification (JVMS).
  64  *
  65  * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.6">JVMS
  66  *     4.6</a>
  67  * @author Eric Bruneton
  68  * @author Eugene Kuleshov
  69  */
  70 final class MethodWriter extends MethodVisitor {
  71 
  72     /** Indicates that nothing must be computed. */
  73     static final int COMPUTE_NOTHING = 0;
  74 
  75     /**
  76       * Indicates that the maximum stack size and the maximum number of local variables must be
  77       * computed, from scratch.
  78       */
  79     static final int COMPUTE_MAX_STACK_AND_LOCAL = 1;
  80 
  81     /**
  82       * Indicates that the maximum stack size and the maximum number of local variables must be
  83       * computed, from the existing stack map frames. This can be done more efficiently than with the
  84       * control flow graph algorithm used for {@link #COMPUTE_MAX_STACK_AND_LOCAL}, by using a linear
  85       * scan of the bytecode instructions.
  86       */
  87     static final int COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES = 2;
  88 
  89     /**
  90       * Indicates that the stack map frames of type F_INSERT must be computed. The other frames are not
  91       * computed. They should all be of type F_NEW and should be sufficient to compute the content of
  92       * the F_INSERT frames, together with the bytecode instructions between a F_NEW and a F_INSERT
  93       * frame - and without any knowledge of the type hierarchy (by definition of F_INSERT).
  94       */
  95     static final int COMPUTE_INSERTED_FRAMES = 3;
  96 
  97     /**
  98       * Indicates that all the stack map frames must be computed. In this case the maximum stack size
  99       * and the maximum number of local variables is also computed.
 100       */
 101     static final int COMPUTE_ALL_FRAMES = 4;
 102 
 103     /** Indicates that {@link #STACK_SIZE_DELTA} is not applicable (not constant or never used). */
 104     private static final int NA = 0;
 105 
 106     /**
 107       * The stack size variation corresponding to each JVM opcode. The stack size variation for opcode
 108       * 'o' is given by the array element at index 'o'.
 109       *
 110       * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html">JVMS 6</a>
 111       */
 112     private static final int[] STACK_SIZE_DELTA = {
 113         0, // nop = 0 (0x0)
 114         1, // aconst_null = 1 (0x1)
 115         1, // iconst_m1 = 2 (0x2)
 116         1, // iconst_0 = 3 (0x3)
 117         1, // iconst_1 = 4 (0x4)
 118         1, // iconst_2 = 5 (0x5)
 119         1, // iconst_3 = 6 (0x6)
 120         1, // iconst_4 = 7 (0x7)
 121         1, // iconst_5 = 8 (0x8)
 122         2, // lconst_0 = 9 (0x9)
 123         2, // lconst_1 = 10 (0xa)
 124         1, // fconst_0 = 11 (0xb)
 125         1, // fconst_1 = 12 (0xc)
 126         1, // fconst_2 = 13 (0xd)
 127         2, // dconst_0 = 14 (0xe)
 128         2, // dconst_1 = 15 (0xf)
 129         1, // bipush = 16 (0x10)
 130         1, // sipush = 17 (0x11)
 131         1, // ldc = 18 (0x12)
 132         NA, // ldc_w = 19 (0x13)
 133         NA, // ldc2_w = 20 (0x14)
 134         1, // iload = 21 (0x15)
 135         2, // lload = 22 (0x16)
 136         1, // fload = 23 (0x17)
 137         2, // dload = 24 (0x18)
 138         1, // aload = 25 (0x19)
 139         NA, // iload_0 = 26 (0x1a)
 140         NA, // iload_1 = 27 (0x1b)
 141         NA, // iload_2 = 28 (0x1c)
 142         NA, // iload_3 = 29 (0x1d)
 143         NA, // lload_0 = 30 (0x1e)
 144         NA, // lload_1 = 31 (0x1f)
 145         NA, // lload_2 = 32 (0x20)
 146         NA, // lload_3 = 33 (0x21)
 147         NA, // fload_0 = 34 (0x22)
 148         NA, // fload_1 = 35 (0x23)
 149         NA, // fload_2 = 36 (0x24)
 150         NA, // fload_3 = 37 (0x25)
 151         NA, // dload_0 = 38 (0x26)
 152         NA, // dload_1 = 39 (0x27)
 153         NA, // dload_2 = 40 (0x28)
 154         NA, // dload_3 = 41 (0x29)
 155         NA, // aload_0 = 42 (0x2a)
 156         NA, // aload_1 = 43 (0x2b)
 157         NA, // aload_2 = 44 (0x2c)
 158         NA, // aload_3 = 45 (0x2d)
 159         -1, // iaload = 46 (0x2e)
 160         0, // laload = 47 (0x2f)
 161         -1, // faload = 48 (0x30)
 162         0, // daload = 49 (0x31)
 163         -1, // aaload = 50 (0x32)
 164         -1, // baload = 51 (0x33)
 165         -1, // caload = 52 (0x34)
 166         -1, // saload = 53 (0x35)
 167         -1, // istore = 54 (0x36)
 168         -2, // lstore = 55 (0x37)
 169         -1, // fstore = 56 (0x38)
 170         -2, // dstore = 57 (0x39)
 171         -1, // astore = 58 (0x3a)
 172         NA, // istore_0 = 59 (0x3b)
 173         NA, // istore_1 = 60 (0x3c)
 174         NA, // istore_2 = 61 (0x3d)
 175         NA, // istore_3 = 62 (0x3e)
 176         NA, // lstore_0 = 63 (0x3f)
 177         NA, // lstore_1 = 64 (0x40)
 178         NA, // lstore_2 = 65 (0x41)
 179         NA, // lstore_3 = 66 (0x42)
 180         NA, // fstore_0 = 67 (0x43)
 181         NA, // fstore_1 = 68 (0x44)
 182         NA, // fstore_2 = 69 (0x45)
 183         NA, // fstore_3 = 70 (0x46)
 184         NA, // dstore_0 = 71 (0x47)
 185         NA, // dstore_1 = 72 (0x48)
 186         NA, // dstore_2 = 73 (0x49)
 187         NA, // dstore_3 = 74 (0x4a)
 188         NA, // astore_0 = 75 (0x4b)
 189         NA, // astore_1 = 76 (0x4c)
 190         NA, // astore_2 = 77 (0x4d)
 191         NA, // astore_3 = 78 (0x4e)
 192         -3, // iastore = 79 (0x4f)
 193         -4, // lastore = 80 (0x50)
 194         -3, // fastore = 81 (0x51)
 195         -4, // dastore = 82 (0x52)
 196         -3, // aastore = 83 (0x53)
 197         -3, // bastore = 84 (0x54)
 198         -3, // castore = 85 (0x55)
 199         -3, // sastore = 86 (0x56)
 200         -1, // pop = 87 (0x57)
 201         -2, // pop2 = 88 (0x58)
 202         1, // dup = 89 (0x59)
 203         1, // dup_x1 = 90 (0x5a)
 204         1, // dup_x2 = 91 (0x5b)
 205         2, // dup2 = 92 (0x5c)
 206         2, // dup2_x1 = 93 (0x5d)
 207         2, // dup2_x2 = 94 (0x5e)
 208         0, // swap = 95 (0x5f)
 209         -1, // iadd = 96 (0x60)
 210         -2, // ladd = 97 (0x61)
 211         -1, // fadd = 98 (0x62)
 212         -2, // dadd = 99 (0x63)
 213         -1, // isub = 100 (0x64)
 214         -2, // lsub = 101 (0x65)
 215         -1, // fsub = 102 (0x66)
 216         -2, // dsub = 103 (0x67)
 217         -1, // imul = 104 (0x68)
 218         -2, // lmul = 105 (0x69)
 219         -1, // fmul = 106 (0x6a)
 220         -2, // dmul = 107 (0x6b)
 221         -1, // idiv = 108 (0x6c)
 222         -2, // ldiv = 109 (0x6d)
 223         -1, // fdiv = 110 (0x6e)
 224         -2, // ddiv = 111 (0x6f)
 225         -1, // irem = 112 (0x70)
 226         -2, // lrem = 113 (0x71)
 227         -1, // frem = 114 (0x72)
 228         -2, // drem = 115 (0x73)
 229         0, // ineg = 116 (0x74)
 230         0, // lneg = 117 (0x75)
 231         0, // fneg = 118 (0x76)
 232         0, // dneg = 119 (0x77)
 233         -1, // ishl = 120 (0x78)
 234         -1, // lshl = 121 (0x79)
 235         -1, // ishr = 122 (0x7a)
 236         -1, // lshr = 123 (0x7b)
 237         -1, // iushr = 124 (0x7c)
 238         -1, // lushr = 125 (0x7d)
 239         -1, // iand = 126 (0x7e)
 240         -2, // land = 127 (0x7f)
 241         -1, // ior = 128 (0x80)
 242         -2, // lor = 129 (0x81)
 243         -1, // ixor = 130 (0x82)
 244         -2, // lxor = 131 (0x83)
 245         0, // iinc = 132 (0x84)
 246         1, // i2l = 133 (0x85)
 247         0, // i2f = 134 (0x86)
 248         1, // i2d = 135 (0x87)
 249         -1, // l2i = 136 (0x88)
 250         -1, // l2f = 137 (0x89)
 251         0, // l2d = 138 (0x8a)
 252         0, // f2i = 139 (0x8b)
 253         1, // f2l = 140 (0x8c)
 254         1, // f2d = 141 (0x8d)
 255         -1, // d2i = 142 (0x8e)
 256         0, // d2l = 143 (0x8f)
 257         -1, // d2f = 144 (0x90)
 258         0, // i2b = 145 (0x91)
 259         0, // i2c = 146 (0x92)
 260         0, // i2s = 147 (0x93)
 261         -3, // lcmp = 148 (0x94)
 262         -1, // fcmpl = 149 (0x95)
 263         -1, // fcmpg = 150 (0x96)
 264         -3, // dcmpl = 151 (0x97)
 265         -3, // dcmpg = 152 (0x98)
 266         -1, // ifeq = 153 (0x99)
 267         -1, // ifne = 154 (0x9a)
 268         -1, // iflt = 155 (0x9b)
 269         -1, // ifge = 156 (0x9c)
 270         -1, // ifgt = 157 (0x9d)
 271         -1, // ifle = 158 (0x9e)
 272         -2, // if_icmpeq = 159 (0x9f)
 273         -2, // if_icmpne = 160 (0xa0)
 274         -2, // if_icmplt = 161 (0xa1)
 275         -2, // if_icmpge = 162 (0xa2)
 276         -2, // if_icmpgt = 163 (0xa3)
 277         -2, // if_icmple = 164 (0xa4)
 278         -2, // if_acmpeq = 165 (0xa5)
 279         -2, // if_acmpne = 166 (0xa6)
 280         0, // goto = 167 (0xa7)
 281         1, // jsr = 168 (0xa8)
 282         0, // ret = 169 (0xa9)
 283         -1, // tableswitch = 170 (0xaa)
 284         -1, // lookupswitch = 171 (0xab)
 285         -1, // ireturn = 172 (0xac)
 286         -2, // lreturn = 173 (0xad)
 287         -1, // freturn = 174 (0xae)
 288         -2, // dreturn = 175 (0xaf)
 289         -1, // areturn = 176 (0xb0)
 290         0, // return = 177 (0xb1)
 291         NA, // getstatic = 178 (0xb2)
 292         NA, // putstatic = 179 (0xb3)
 293         NA, // getfield = 180 (0xb4)
 294         NA, // putfield = 181 (0xb5)
 295         NA, // invokevirtual = 182 (0xb6)
 296         NA, // invokespecial = 183 (0xb7)
 297         NA, // invokestatic = 184 (0xb8)
 298         NA, // invokeinterface = 185 (0xb9)
 299         NA, // invokedynamic = 186 (0xba)
 300         1, // new = 187 (0xbb)
 301         0, // newarray = 188 (0xbc)
 302         0, // anewarray = 189 (0xbd)
 303         0, // arraylength = 190 (0xbe)
 304         NA, // athrow = 191 (0xbf)
 305         0, // checkcast = 192 (0xc0)
 306         0, // instanceof = 193 (0xc1)
 307         -1, // monitorenter = 194 (0xc2)
 308         -1, // monitorexit = 195 (0xc3)
 309         NA, // wide = 196 (0xc4)
 310         NA, // multianewarray = 197 (0xc5)
 311         -1, // ifnull = 198 (0xc6)
 312         -1, // ifnonnull = 199 (0xc7)
 313         NA, // goto_w = 200 (0xc8)
 314         NA // jsr_w = 201 (0xc9)
 315     };
 316 
 317     /** Where the constants used in this MethodWriter must be stored. */
 318     private final SymbolTable symbolTable;
 319 
 320     // Note: fields are ordered as in the method_info structure, and those related to attributes are
 321     // ordered as in Section 4.7 of the JVMS.
 322 
 323     /**
 324       * The access_flags field of the method_info JVMS structure. This field can contain ASM specific
 325       * access flags, such as {@link Opcodes#ACC_DEPRECATED}, which are removed when generating the
 326       * ClassFile structure.
 327       */
 328     private final int accessFlags;
 329 
 330     /** The name_index field of the method_info JVMS structure. */
 331     private final int nameIndex;
 332 
 333     /** The name of this method. */
 334     private final String name;
 335 
 336     /** The descriptor_index field of the method_info JVMS structure. */
 337     private final int descriptorIndex;
 338 
 339     /** The descriptor of this method. */
 340     private final String descriptor;
 341 
 342     // Code attribute fields and sub attributes:
 343 
 344     /** The max_stack field of the Code attribute. */
 345     private int maxStack;
 346 
 347     /** The max_locals field of the Code attribute. */
 348     private int maxLocals;
 349 
 350     /** The 'code' field of the Code attribute. */
 351     private final ByteVector code = new ByteVector();
 352 
 353     /**
 354       * The first element in the exception handler list (used to generate the exception_table of the
 355       * Code attribute). The next ones can be accessed with the {@link Handler#nextHandler} field. May
 356       * be {@literal null}.
 357       */
 358     private Handler firstHandler;
 359 
 360     /**
 361       * The last element in the exception handler list (used to generate the exception_table of the
 362       * Code attribute). The next ones can be accessed with the {@link Handler#nextHandler} field. May
 363       * be {@literal null}.
 364       */
 365     private Handler lastHandler;
 366 
 367     /** The line_number_table_length field of the LineNumberTable code attribute. */
 368     private int lineNumberTableLength;
 369 
 370     /** The line_number_table array of the LineNumberTable code attribute, or {@literal null}. */
 371     private ByteVector lineNumberTable;
 372 
 373     /** The local_variable_table_length field of the LocalVariableTable code attribute. */
 374     private int localVariableTableLength;
 375 
 376     /**
 377       * The local_variable_table array of the LocalVariableTable code attribute, or {@literal null}.
 378       */
 379     private ByteVector localVariableTable;
 380 
 381     /** The local_variable_type_table_length field of the LocalVariableTypeTable code attribute. */
 382     private int localVariableTypeTableLength;
 383 
 384     /**
 385       * The local_variable_type_table array of the LocalVariableTypeTable code attribute, or {@literal
 386       * null}.
 387       */
 388     private ByteVector localVariableTypeTable;
 389 
 390     /** The number_of_entries field of the StackMapTable code attribute. */
 391     private int stackMapTableNumberOfEntries;
 392 
 393     /** The 'entries' array of the StackMapTable code attribute. */
 394     private ByteVector stackMapTableEntries;
 395 
 396     /**
 397       * The last runtime visible type annotation of the Code attribute. The previous ones can be
 398       * accessed with the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
 399       */
 400     private AnnotationWriter lastCodeRuntimeVisibleTypeAnnotation;
 401 
 402     /**
 403       * The last runtime invisible type annotation of the Code attribute. The previous ones can be
 404       * accessed with the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
 405       */
 406     private AnnotationWriter lastCodeRuntimeInvisibleTypeAnnotation;
 407 
 408     /**
 409       * The first non standard attribute of the Code attribute. The next ones can be accessed with the
 410       * {@link Attribute#nextAttribute} field. May be {@literal null}.
 411       *
 412       * <p><b>WARNING</b>: this list stores the attributes in the <i>reverse</i> order of their visit.
 413       * firstAttribute is actually the last attribute visited in {@link #visitAttribute}. The {@link
 414       * #putMethodInfo} method writes the attributes in the order defined by this list, i.e. in the
 415       * reverse order specified by the user.
 416       */
 417     private Attribute firstCodeAttribute;
 418 
 419     // Other method_info attributes:
 420 
 421     /** The number_of_exceptions field of the Exceptions attribute. */
 422     private final int numberOfExceptions;
 423 
 424     /** The exception_index_table array of the Exceptions attribute, or {@literal null}. */
 425     private final int[] exceptionIndexTable;
 426 
 427     /** The signature_index field of the Signature attribute. */
 428     private final int signatureIndex;
 429 
 430     /**
 431       * The last runtime visible annotation of this method. The previous ones can be accessed with the
 432       * {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
 433       */
 434     private AnnotationWriter lastRuntimeVisibleAnnotation;
 435 
 436     /**
 437       * The last runtime invisible annotation of this method. The previous ones can be accessed with
 438       * the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
 439       */
 440     private AnnotationWriter lastRuntimeInvisibleAnnotation;
 441 
 442     /** The number of method parameters that can have runtime visible annotations, or 0. */
 443     private int visibleAnnotableParameterCount;
 444 
 445     /**
 446       * The runtime visible parameter annotations of this method. Each array element contains the last
 447       * annotation of a parameter (which can be {@literal null} - the previous ones can be accessed
 448       * with the {@link AnnotationWriter#previousAnnotation} field). May be {@literal null}.
 449       */
 450     private AnnotationWriter[] lastRuntimeVisibleParameterAnnotations;
 451 
 452     /** The number of method parameters that can have runtime visible annotations, or 0. */
 453     private int invisibleAnnotableParameterCount;
 454 
 455     /**
 456       * The runtime invisible parameter annotations of this method. Each array element contains the
 457       * last annotation of a parameter (which can be {@literal null} - the previous ones can be
 458       * accessed with the {@link AnnotationWriter#previousAnnotation} field). May be {@literal null}.
 459       */
 460     private AnnotationWriter[] lastRuntimeInvisibleParameterAnnotations;
 461 
 462     /**
 463       * The last runtime visible type annotation of this method. The previous ones can be accessed with
 464       * the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
 465       */
 466     private AnnotationWriter lastRuntimeVisibleTypeAnnotation;
 467 
 468     /**
 469       * The last runtime invisible type annotation of this method. The previous ones can be accessed
 470       * with the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
 471       */
 472     private AnnotationWriter lastRuntimeInvisibleTypeAnnotation;
 473 
 474     /** The default_value field of the AnnotationDefault attribute, or {@literal null}. */
 475     private ByteVector defaultValue;
 476 
 477     /** The parameters_count field of the MethodParameters attribute. */
 478     private int parametersCount;
 479 
 480     /** The 'parameters' array of the MethodParameters attribute, or {@literal null}. */
 481     private ByteVector parameters;
 482 
 483     /**
 484       * The first non standard attribute of this method. The next ones can be accessed with the {@link
 485       * Attribute#nextAttribute} field. May be {@literal null}.
 486       *
 487       * <p><b>WARNING</b>: this list stores the attributes in the <i>reverse</i> order of their visit.
 488       * firstAttribute is actually the last attribute visited in {@link #visitAttribute}. The {@link
 489       * #putMethodInfo} method writes the attributes in the order defined by this list, i.e. in the
 490       * reverse order specified by the user.
 491       */
 492     private Attribute firstAttribute;
 493 
 494     // -----------------------------------------------------------------------------------------------
 495     // Fields used to compute the maximum stack size and number of locals, and the stack map frames
 496     // -----------------------------------------------------------------------------------------------
 497 
 498     /**
 499       * Indicates what must be computed. Must be one of {@link #COMPUTE_ALL_FRAMES}, {@link
 500       * #COMPUTE_INSERTED_FRAMES}, {@link #COMPUTE_MAX_STACK_AND_LOCAL} or {@link #COMPUTE_NOTHING}.
 501       */
 502     private final int compute;
 503 
 504     /**
 505       * The first basic block of the method. The next ones (in bytecode offset order) can be accessed
 506       * with the {@link Label#nextBasicBlock} field.
 507       */
 508     private Label firstBasicBlock;
 509 
 510     /**
 511       * The last basic block of the method (in bytecode offset order). This field is updated each time
 512       * a basic block is encountered, and is used to append it at the end of the basic block list.
 513       */
 514     private Label lastBasicBlock;
 515 
 516     /**
 517       * The current basic block, i.e. the basic block of the last visited instruction. When {@link
 518       * #compute} is equal to {@link #COMPUTE_MAX_STACK_AND_LOCAL} or {@link #COMPUTE_ALL_FRAMES}, this
 519       * field is {@literal null} for unreachable code. When {@link #compute} is equal to {@link
 520       * #COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES} or {@link #COMPUTE_INSERTED_FRAMES}, this field stays
 521       * unchanged throughout the whole method (i.e. the whole code is seen as a single basic block;
 522       * indeed, the existing frames are sufficient by hypothesis to compute any intermediate frame -
 523       * and the maximum stack size as well - without using any control flow graph).
 524       */
 525     private Label currentBasicBlock;
 526 
 527     /**
 528       * The relative stack size after the last visited instruction. This size is relative to the
 529       * beginning of {@link #currentBasicBlock}, i.e. the true stack size after the last visited
 530       * instruction is equal to the {@link Label#inputStackSize} of the current basic block plus {@link
 531       * #relativeStackSize}. When {@link #compute} is equal to {@link
 532       * #COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES}, {@link #currentBasicBlock} is always the start of
 533       * the method, so this relative size is also equal to the absolute stack size after the last
 534       * visited instruction.
 535       */
 536     private int relativeStackSize;
 537 
 538     /**
 539       * The maximum relative stack size after the last visited instruction. This size is relative to
 540       * the beginning of {@link #currentBasicBlock}, i.e. the true maximum stack size after the last
 541       * visited instruction is equal to the {@link Label#inputStackSize} of the current basic block
 542       * plus {@link #maxRelativeStackSize}.When {@link #compute} is equal to {@link
 543       * #COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES}, {@link #currentBasicBlock} is always the start of
 544       * the method, so this relative size is also equal to the absolute maximum stack size after the
 545       * last visited instruction.
 546       */
 547     private int maxRelativeStackSize;
 548 
 549     /** The number of local variables in the last visited stack map frame. */
 550     private int currentLocals;
 551 
 552     /** The bytecode offset of the last frame that was written in {@link #stackMapTableEntries}. */
 553     private int previousFrameOffset;
 554 
 555     /**
 556       * The last frame that was written in {@link #stackMapTableEntries}. This field has the same
 557       * format as {@link #currentFrame}.
 558       */
 559     private int[] previousFrame;
 560 
 561     /**
 562       * The current stack map frame. The first element contains the bytecode offset of the instruction
 563       * to which the frame corresponds, the second element is the number of locals and the third one is
 564       * the number of stack elements. The local variables start at index 3 and are followed by the
 565       * operand stack elements. In summary frame[0] = offset, frame[1] = numLocal, frame[2] = numStack.
 566       * Local variables and operand stack entries contain abstract types, as defined in {@link Frame},
 567       * but restricted to {@link Frame#CONSTANT_KIND}, {@link Frame#REFERENCE_KIND} or {@link
 568       * Frame#UNINITIALIZED_KIND} abstract types. Long and double types use only one array entry.
 569       */
 570     private int[] currentFrame;
 571 
 572     /** Whether this method contains subroutines. */
 573     private boolean hasSubroutines;
 574 
 575     // -----------------------------------------------------------------------------------------------
 576     // Other miscellaneous status fields
 577     // -----------------------------------------------------------------------------------------------
 578 
 579     /** Whether the bytecode of this method contains ASM specific instructions. */
 580     private boolean hasAsmInstructions;
 581 
 582     /**
 583       * The start offset of the last visited instruction. Used to set the offset field of type
 584       * annotations of type 'offset_target' (see <a
 585       * href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20.1">JVMS
 586       * 4.7.20.1</a>).
 587       */
 588     private int lastBytecodeOffset;
 589 
 590     /**
 591       * The offset in bytes in {@link SymbolTable#getSource} from which the method_info for this method
 592       * (excluding its first 6 bytes) must be copied, or 0.
 593       */
 594     private int sourceOffset;
 595 
 596     /**
 597       * The length in bytes in {@link SymbolTable#getSource} which must be copied to get the
 598       * method_info for this method (excluding its first 6 bytes for access_flags, name_index and
 599       * descriptor_index).
 600       */
 601     private int sourceLength;
 602 
 603     // -----------------------------------------------------------------------------------------------
 604     // Constructor and accessors
 605     // -----------------------------------------------------------------------------------------------
 606 
 607     /**
 608       * Constructs a new {@link MethodWriter}.
 609       *
 610       * @param symbolTable where the constants used in this AnnotationWriter must be stored.
 611       * @param access the method's access flags (see {@link Opcodes}).
 612       * @param name the method's name.
 613       * @param descriptor the method's descriptor (see {@link Type}).
 614       * @param signature the method's signature. May be {@literal null}.
 615       * @param exceptions the internal names of the method's exceptions. May be {@literal null}.
 616       * @param compute indicates what must be computed (see #compute).
 617       */
 618     MethodWriter(
 619             final SymbolTable symbolTable,
 620             final int access,
 621             final String name,
 622             final String descriptor,
 623             final String signature,
 624             final String[] exceptions,
 625             final int compute) {
 626         super(/* latest api = */ Opcodes.ASM8);
 627         this.symbolTable = symbolTable;
 628         this.accessFlags = "<init>".equals(name) ? access | Constants.ACC_CONSTRUCTOR : access;
 629         this.nameIndex = symbolTable.addConstantUtf8(name);
 630         this.name = name;
 631         this.descriptorIndex = symbolTable.addConstantUtf8(descriptor);
 632         this.descriptor = descriptor;
 633         this.signatureIndex = signature == null ? 0 : symbolTable.addConstantUtf8(signature);
 634         if (exceptions != null && exceptions.length > 0) {
 635             numberOfExceptions = exceptions.length;
 636             this.exceptionIndexTable = new int[numberOfExceptions];
 637             for (int i = 0; i < numberOfExceptions; ++i) {
 638                 this.exceptionIndexTable[i] = symbolTable.addConstantClass(exceptions[i]).index;
 639             }
 640         } else {
 641             numberOfExceptions = 0;
 642             this.exceptionIndexTable = null;
 643         }
 644         this.compute = compute;
 645         if (compute != COMPUTE_NOTHING) {
 646             // Update maxLocals and currentLocals.
 647             int argumentsSize = Type.getArgumentsAndReturnSizes(descriptor) >> 2;
 648             if ((access & Opcodes.ACC_STATIC) != 0) {
 649                 --argumentsSize;
 650             }
 651             maxLocals = argumentsSize;
 652             currentLocals = argumentsSize;
 653             // Create and visit the label for the first basic block.
 654             firstBasicBlock = new Label();
 655             visitLabel(firstBasicBlock);
 656         }
 657     }
 658 
 659     boolean hasFrames() {
 660         return stackMapTableNumberOfEntries > 0;
 661     }
 662 
 663     boolean hasAsmInstructions() {
 664         return hasAsmInstructions;
 665     }
 666 
 667     // -----------------------------------------------------------------------------------------------
 668     // Implementation of the MethodVisitor abstract class
 669     // -----------------------------------------------------------------------------------------------
 670 
 671     @Override
 672     public void visitParameter(final String name, final int access) {
 673         if (parameters == null) {
 674             parameters = new ByteVector();
 675         }
 676         ++parametersCount;
 677         parameters.putShort((name == null) ? 0 : symbolTable.addConstantUtf8(name)).putShort(access);
 678     }
 679 
 680     @Override
 681     public AnnotationVisitor visitAnnotationDefault() {
 682         defaultValue = new ByteVector();
 683         return new AnnotationWriter(symbolTable, /* useNamedValues = */ false, defaultValue, null);
 684     }
 685 
 686     @Override
 687     public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
 688         if (visible) {
 689             return lastRuntimeVisibleAnnotation =
 690                     AnnotationWriter.create(symbolTable, descriptor, lastRuntimeVisibleAnnotation);
 691         } else {
 692             return lastRuntimeInvisibleAnnotation =
 693                     AnnotationWriter.create(symbolTable, descriptor, lastRuntimeInvisibleAnnotation);
 694         }
 695     }
 696 
 697     @Override
 698     public AnnotationVisitor visitTypeAnnotation(
 699             final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
 700         if (visible) {
 701             return lastRuntimeVisibleTypeAnnotation =
 702                     AnnotationWriter.create(
 703                             symbolTable, typeRef, typePath, descriptor, lastRuntimeVisibleTypeAnnotation);
 704         } else {
 705             return lastRuntimeInvisibleTypeAnnotation =
 706                     AnnotationWriter.create(
 707                             symbolTable, typeRef, typePath, descriptor, lastRuntimeInvisibleTypeAnnotation);
 708         }
 709     }
 710 
 711     @Override
 712     public void visitAnnotableParameterCount(final int parameterCount, final boolean visible) {
 713         if (visible) {
 714             visibleAnnotableParameterCount = parameterCount;
 715         } else {
 716             invisibleAnnotableParameterCount = parameterCount;
 717         }
 718     }
 719 
 720     @Override
 721     public AnnotationVisitor visitParameterAnnotation(
 722             final int parameter, final String annotationDescriptor, final boolean visible) {
 723         if (visible) {
 724             if (lastRuntimeVisibleParameterAnnotations == null) {
 725                 lastRuntimeVisibleParameterAnnotations =
 726                         new AnnotationWriter[Type.getArgumentTypes(descriptor).length];
 727             }
 728             return lastRuntimeVisibleParameterAnnotations[parameter] =
 729                     AnnotationWriter.create(
 730                             symbolTable, annotationDescriptor, lastRuntimeVisibleParameterAnnotations[parameter]);
 731         } else {
 732             if (lastRuntimeInvisibleParameterAnnotations == null) {
 733                 lastRuntimeInvisibleParameterAnnotations =
 734                         new AnnotationWriter[Type.getArgumentTypes(descriptor).length];
 735             }
 736             return lastRuntimeInvisibleParameterAnnotations[parameter] =
 737                     AnnotationWriter.create(
 738                             symbolTable,
 739                             annotationDescriptor,
 740                             lastRuntimeInvisibleParameterAnnotations[parameter]);
 741         }
 742     }
 743 
 744     @Override
 745     public void visitAttribute(final Attribute attribute) {
 746         // Store the attributes in the <i>reverse</i> order of their visit by this method.
 747         if (attribute.isCodeAttribute()) {
 748             attribute.nextAttribute = firstCodeAttribute;
 749             firstCodeAttribute = attribute;
 750         } else {
 751             attribute.nextAttribute = firstAttribute;
 752             firstAttribute = attribute;
 753         }
 754     }
 755 
 756     @Override
 757     public void visitCode() {
 758         // Nothing to do.
 759     }
 760 
 761     @Override
 762     public void visitFrame(
 763             final int type,
 764             final int numLocal,
 765             final Object[] local,
 766             final int numStack,
 767             final Object[] stack) {
 768         if (compute == COMPUTE_ALL_FRAMES) {
 769             return;
 770         }
 771 
 772         if (compute == COMPUTE_INSERTED_FRAMES) {
 773             if (currentBasicBlock.frame == null) {
 774                 // This should happen only once, for the implicit first frame (which is explicitly visited
 775                 // in ClassReader if the EXPAND_ASM_INSNS option is used - and COMPUTE_INSERTED_FRAMES
 776                 // can't be set if EXPAND_ASM_INSNS is not used).
 777                 currentBasicBlock.frame = new CurrentFrame(currentBasicBlock);
 778                 currentBasicBlock.frame.setInputFrameFromDescriptor(
 779                         symbolTable, accessFlags, descriptor, numLocal);
 780                 currentBasicBlock.frame.accept(this);
 781             } else {
 782                 if (type == Opcodes.F_NEW) {
 783                     currentBasicBlock.frame.setInputFrameFromApiFormat(
 784                             symbolTable, numLocal, local, numStack, stack);
 785                 }
 786                 // If type is not F_NEW then it is F_INSERT by hypothesis, and currentBlock.frame contains
 787                 // the stack map frame at the current instruction, computed from the last F_NEW frame and
 788                 // the bytecode instructions in between (via calls to CurrentFrame#execute).
 789                 currentBasicBlock.frame.accept(this);
 790             }
 791         } else if (type == Opcodes.F_NEW) {
 792             if (previousFrame == null) {
 793                 int argumentsSize = Type.getArgumentsAndReturnSizes(descriptor) >> 2;
 794                 Frame implicitFirstFrame = new Frame(new Label());
 795                 implicitFirstFrame.setInputFrameFromDescriptor(
 796                         symbolTable, accessFlags, descriptor, argumentsSize);
 797                 implicitFirstFrame.accept(this);
 798             }
 799             currentLocals = numLocal;
 800             int frameIndex = visitFrameStart(code.length, numLocal, numStack);
 801             for (int i = 0; i < numLocal; ++i) {
 802                 currentFrame[frameIndex++] = Frame.getAbstractTypeFromApiFormat(symbolTable, local[i]);
 803             }
 804             for (int i = 0; i < numStack; ++i) {
 805                 currentFrame[frameIndex++] = Frame.getAbstractTypeFromApiFormat(symbolTable, stack[i]);
 806             }
 807             visitFrameEnd();
 808         } else {
 809             if (symbolTable.getMajorVersion() < Opcodes.V1_6) {
 810                 throw new IllegalArgumentException("Class versions V1_5 or less must use F_NEW frames.");
 811             }
 812             int offsetDelta;
 813             if (stackMapTableEntries == null) {
 814                 stackMapTableEntries = new ByteVector();
 815                 offsetDelta = code.length;
 816             } else {
 817                 offsetDelta = code.length - previousFrameOffset - 1;
 818                 if (offsetDelta < 0) {
 819                     if (type == Opcodes.F_SAME) {
 820                         return;
 821                     } else {
 822                         throw new IllegalStateException();
 823                     }
 824                 }
 825             }
 826 
 827             switch (type) {
 828                 case Opcodes.F_FULL:
 829                     currentLocals = numLocal;
 830                     stackMapTableEntries.putByte(Frame.FULL_FRAME).putShort(offsetDelta).putShort(numLocal);
 831                     for (int i = 0; i < numLocal; ++i) {
 832                         putFrameType(local[i]);
 833                     }
 834                     stackMapTableEntries.putShort(numStack);
 835                     for (int i = 0; i < numStack; ++i) {
 836                         putFrameType(stack[i]);
 837                     }
 838                     break;
 839                 case Opcodes.F_APPEND:
 840                     currentLocals += numLocal;
 841                     stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED + numLocal).putShort(offsetDelta);
 842                     for (int i = 0; i < numLocal; ++i) {
 843                         putFrameType(local[i]);
 844                     }
 845                     break;
 846                 case Opcodes.F_CHOP:
 847                     currentLocals -= numLocal;
 848                     stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED - numLocal).putShort(offsetDelta);
 849                     break;
 850                 case Opcodes.F_SAME:
 851                     if (offsetDelta < 64) {
 852                         stackMapTableEntries.putByte(offsetDelta);
 853                     } else {
 854                         stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED).putShort(offsetDelta);
 855                     }
 856                     break;
 857                 case Opcodes.F_SAME1:
 858                     if (offsetDelta < 64) {
 859                         stackMapTableEntries.putByte(Frame.SAME_LOCALS_1_STACK_ITEM_FRAME + offsetDelta);
 860                     } else {
 861                         stackMapTableEntries
 862                                 .putByte(Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
 863                                 .putShort(offsetDelta);
 864                     }
 865                     putFrameType(stack[0]);
 866                     break;
 867                 default:
 868                     throw new IllegalArgumentException();
 869             }
 870 
 871             previousFrameOffset = code.length;
 872             ++stackMapTableNumberOfEntries;
 873         }
 874 
 875         if (compute == COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES) {
 876             relativeStackSize = numStack;
 877             for (int i = 0; i < numStack; ++i) {
 878                 if (stack[i] == Opcodes.LONG || stack[i] == Opcodes.DOUBLE) {
 879                     relativeStackSize++;
 880                 }
 881             }
 882             if (relativeStackSize > maxRelativeStackSize) {
 883                 maxRelativeStackSize = relativeStackSize;
 884             }
 885         }
 886 
 887         maxStack = Math.max(maxStack, numStack);
 888         maxLocals = Math.max(maxLocals, currentLocals);
 889     }
 890 
 891     @Override
 892     public void visitInsn(final int opcode) {
 893         lastBytecodeOffset = code.length;
 894         // Add the instruction to the bytecode of the method.
 895         code.putByte(opcode);
 896         // If needed, update the maximum stack size and number of locals, and stack map frames.
 897         if (currentBasicBlock != null) {
 898             if (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES) {
 899                 currentBasicBlock.frame.execute(opcode, 0, null, null);
 900             } else {
 901                 int size = relativeStackSize + STACK_SIZE_DELTA[opcode];
 902                 if (size > maxRelativeStackSize) {
 903                     maxRelativeStackSize = size;
 904                 }
 905                 relativeStackSize = size;
 906             }
 907             if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) || opcode == Opcodes.ATHROW) {
 908                 endCurrentBasicBlockWithNoSuccessor();
 909             }
 910         }
 911     }
 912 
 913     @Override
 914     public void visitIntInsn(final int opcode, final int operand) {
 915         lastBytecodeOffset = code.length;
 916         // Add the instruction to the bytecode of the method.
 917         if (opcode == Opcodes.SIPUSH) {
 918             code.put12(opcode, operand);
 919         } else { // BIPUSH or NEWARRAY
 920             code.put11(opcode, operand);
 921         }
 922         // If needed, update the maximum stack size and number of locals, and stack map frames.
 923         if (currentBasicBlock != null) {
 924             if (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES) {
 925                 currentBasicBlock.frame.execute(opcode, operand, null, null);
 926             } else if (opcode != Opcodes.NEWARRAY) {
 927                 // The stack size delta is 1 for BIPUSH or SIPUSH, and 0 for NEWARRAY.
 928                 int size = relativeStackSize + 1;
 929                 if (size > maxRelativeStackSize) {
 930                     maxRelativeStackSize = size;
 931                 }
 932                 relativeStackSize = size;
 933             }
 934         }
 935     }
 936 
 937     @Override
 938     public void visitVarInsn(final int opcode, final int var) {
 939         lastBytecodeOffset = code.length;
 940         // Add the instruction to the bytecode of the method.
 941         if (var < 4 && opcode != Opcodes.RET) {
 942             int optimizedOpcode;
 943             if (opcode < Opcodes.ISTORE) {
 944                 optimizedOpcode = Constants.ILOAD_0 + ((opcode - Opcodes.ILOAD) << 2) + var;
 945             } else {
 946                 optimizedOpcode = Constants.ISTORE_0 + ((opcode - Opcodes.ISTORE) << 2) + var;
 947             }
 948             code.putByte(optimizedOpcode);
 949         } else if (var >= 256) {
 950             code.putByte(Constants.WIDE).put12(opcode, var);
 951         } else {
 952             code.put11(opcode, var);
 953         }
 954         // If needed, update the maximum stack size and number of locals, and stack map frames.
 955         if (currentBasicBlock != null) {
 956             if (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES) {
 957                 currentBasicBlock.frame.execute(opcode, var, null, null);
 958             } else {
 959                 if (opcode == Opcodes.RET) {
 960                     // No stack size delta.
 961                     currentBasicBlock.flags |= Label.FLAG_SUBROUTINE_END;
 962                     currentBasicBlock.outputStackSize = (short) relativeStackSize;
 963                     endCurrentBasicBlockWithNoSuccessor();
 964                 } else { // xLOAD or xSTORE
 965                     int size = relativeStackSize + STACK_SIZE_DELTA[opcode];
 966                     if (size > maxRelativeStackSize) {
 967                         maxRelativeStackSize = size;
 968                     }
 969                     relativeStackSize = size;
 970                 }
 971             }
 972         }
 973         if (compute != COMPUTE_NOTHING) {
 974             int currentMaxLocals;
 975             if (opcode == Opcodes.LLOAD
 976                     || opcode == Opcodes.DLOAD
 977                     || opcode == Opcodes.LSTORE
 978                     || opcode == Opcodes.DSTORE) {
 979                 currentMaxLocals = var + 2;
 980             } else {
 981                 currentMaxLocals = var + 1;
 982             }
 983             if (currentMaxLocals > maxLocals) {
 984                 maxLocals = currentMaxLocals;
 985             }
 986         }
 987         if (opcode >= Opcodes.ISTORE && compute == COMPUTE_ALL_FRAMES && firstHandler != null) {
 988             // If there are exception handler blocks, each instruction within a handler range is, in
 989             // theory, a basic block (since execution can jump from this instruction to the exception
 990             // handler). As a consequence, the local variable types at the beginning of the handler
 991             // block should be the merge of the local variable types at all the instructions within the
 992             // handler range. However, instead of creating a basic block for each instruction, we can
 993             // get the same result in a more efficient way. Namely, by starting a new basic block after
 994             // each xSTORE instruction, which is what we do here.
 995             visitLabel(new Label());
 996         }
 997     }
 998 
 999     @Override
1000     public void visitTypeInsn(final int opcode, final String type) {
1001         lastBytecodeOffset = code.length;
1002         // Add the instruction to the bytecode of the method.
1003         Symbol typeSymbol = symbolTable.addConstantClass(type);
1004         code.put12(opcode, typeSymbol.index);
1005         // If needed, update the maximum stack size and number of locals, and stack map frames.
1006         if (currentBasicBlock != null) {
1007             if (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES) {
1008                 currentBasicBlock.frame.execute(opcode, lastBytecodeOffset, typeSymbol, symbolTable);
1009             } else if (opcode == Opcodes.NEW) {
1010                 // The stack size delta is 1 for NEW, and 0 for ANEWARRAY, CHECKCAST, or INSTANCEOF.
1011                 int size = relativeStackSize + 1;
1012                 if (size > maxRelativeStackSize) {
1013                     maxRelativeStackSize = size;
1014                 }
1015                 relativeStackSize = size;
1016             }
1017         }
1018     }
1019 
1020     @Override
1021     public void visitFieldInsn(
1022             final int opcode, final String owner, final String name, final String descriptor) {
1023         lastBytecodeOffset = code.length;
1024         // Add the instruction to the bytecode of the method.
1025         Symbol fieldrefSymbol = symbolTable.addConstantFieldref(owner, name, descriptor);
1026         code.put12(opcode, fieldrefSymbol.index);
1027         // If needed, update the maximum stack size and number of locals, and stack map frames.
1028         if (currentBasicBlock != null) {
1029             if (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES) {
1030                 currentBasicBlock.frame.execute(opcode, 0, fieldrefSymbol, symbolTable);
1031             } else {
1032                 int size;
1033                 char firstDescChar = descriptor.charAt(0);
1034                 switch (opcode) {
1035                     case Opcodes.GETSTATIC:
1036                         size = relativeStackSize + (firstDescChar == 'D' || firstDescChar == 'J' ? 2 : 1);
1037                         break;
1038                     case Opcodes.PUTSTATIC:
1039                         size = relativeStackSize + (firstDescChar == 'D' || firstDescChar == 'J' ? -2 : -1);
1040                         break;
1041                     case Opcodes.GETFIELD:
1042                         size = relativeStackSize + (firstDescChar == 'D' || firstDescChar == 'J' ? 1 : 0);
1043                         break;
1044                     case Opcodes.PUTFIELD:
1045                     default:
1046                         size = relativeStackSize + (firstDescChar == 'D' || firstDescChar == 'J' ? -3 : -2);
1047                         break;
1048                 }
1049                 if (size > maxRelativeStackSize) {
1050                     maxRelativeStackSize = size;
1051                 }
1052                 relativeStackSize = size;
1053             }
1054         }
1055     }
1056 
1057     @Override
1058     public void visitMethodInsn(
1059             final int opcode,
1060             final String owner,
1061             final String name,
1062             final String descriptor,
1063             final boolean isInterface) {
1064         lastBytecodeOffset = code.length;
1065         // Add the instruction to the bytecode of the method.
1066         Symbol methodrefSymbol = symbolTable.addConstantMethodref(owner, name, descriptor, isInterface);
1067         if (opcode == Opcodes.INVOKEINTERFACE) {
1068             code.put12(Opcodes.INVOKEINTERFACE, methodrefSymbol.index)
1069                     .put11(methodrefSymbol.getArgumentsAndReturnSizes() >> 2, 0);
1070         } else {
1071             code.put12(opcode, methodrefSymbol.index);
1072         }
1073         // If needed, update the maximum stack size and number of locals, and stack map frames.
1074         if (currentBasicBlock != null) {
1075             if (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES) {
1076                 currentBasicBlock.frame.execute(opcode, 0, methodrefSymbol, symbolTable);
1077             } else {
1078                 int argumentsAndReturnSize = methodrefSymbol.getArgumentsAndReturnSizes();
1079                 int stackSizeDelta = (argumentsAndReturnSize & 3) - (argumentsAndReturnSize >> 2);
1080                 int size;
1081                 if (opcode == Opcodes.INVOKESTATIC) {
1082                     size = relativeStackSize + stackSizeDelta + 1;
1083                 } else {
1084                     size = relativeStackSize + stackSizeDelta;
1085                 }
1086                 if (size > maxRelativeStackSize) {
1087                     maxRelativeStackSize = size;
1088                 }
1089                 relativeStackSize = size;
1090             }
1091         }
1092     }
1093 
1094     @Override
1095     public void visitInvokeDynamicInsn(
1096             final String name,
1097             final String descriptor,
1098             final Handle bootstrapMethodHandle,
1099             final Object... bootstrapMethodArguments) {
1100         lastBytecodeOffset = code.length;
1101         // Add the instruction to the bytecode of the method.
1102         Symbol invokeDynamicSymbol =
1103                 symbolTable.addConstantInvokeDynamic(
1104                         name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
1105         code.put12(Opcodes.INVOKEDYNAMIC, invokeDynamicSymbol.index);
1106         code.putShort(0);
1107         // If needed, update the maximum stack size and number of locals, and stack map frames.
1108         if (currentBasicBlock != null) {
1109             if (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES) {
1110                 currentBasicBlock.frame.execute(Opcodes.INVOKEDYNAMIC, 0, invokeDynamicSymbol, symbolTable);
1111             } else {
1112                 int argumentsAndReturnSize = invokeDynamicSymbol.getArgumentsAndReturnSizes();
1113                 int stackSizeDelta = (argumentsAndReturnSize & 3) - (argumentsAndReturnSize >> 2) + 1;
1114                 int size = relativeStackSize + stackSizeDelta;
1115                 if (size > maxRelativeStackSize) {
1116                     maxRelativeStackSize = size;
1117                 }
1118                 relativeStackSize = size;
1119             }
1120         }
1121     }
1122 
1123     @Override
1124     public void visitJumpInsn(final int opcode, final Label label) {
1125         lastBytecodeOffset = code.length;
1126         // Add the instruction to the bytecode of the method.
1127         // Compute the 'base' opcode, i.e. GOTO or JSR if opcode is GOTO_W or JSR_W, otherwise opcode.
1128         int baseOpcode =
1129                 opcode >= Constants.GOTO_W ? opcode - Constants.WIDE_JUMP_OPCODE_DELTA : opcode;
1130         boolean nextInsnIsJumpTarget = false;
1131         if ((label.flags & Label.FLAG_RESOLVED) != 0
1132                 && label.bytecodeOffset - code.length < Short.MIN_VALUE) {
1133             // Case of a backward jump with an offset < -32768. In this case we automatically replace GOTO
1134             // with GOTO_W, JSR with JSR_W and IFxxx <l> with IFNOTxxx <L> GOTO_W <l> L:..., where
1135             // IFNOTxxx is the "opposite" opcode of IFxxx (e.g. IFNE for IFEQ) and where <L> designates
1136             // the instruction just after the GOTO_W.
1137             if (baseOpcode == Opcodes.GOTO) {
1138                 code.putByte(Constants.GOTO_W);
1139             } else if (baseOpcode == Opcodes.JSR) {
1140                 code.putByte(Constants.JSR_W);
1141             } else {
1142                 // Put the "opposite" opcode of baseOpcode. This can be done by flipping the least
1143                 // significant bit for IFNULL and IFNONNULL, and similarly for IFEQ ... IF_ACMPEQ (with a
1144                 // pre and post offset by 1). The jump offset is 8 bytes (3 for IFNOTxxx, 5 for GOTO_W).
1145                 code.putByte(baseOpcode >= Opcodes.IFNULL ? baseOpcode ^ 1 : ((baseOpcode + 1) ^ 1) - 1);
1146                 code.putShort(8);
1147                 // Here we could put a GOTO_W in theory, but if ASM specific instructions are used in this
1148                 // method or another one, and if the class has frames, we will need to insert a frame after
1149                 // this GOTO_W during the additional ClassReader -> ClassWriter round trip to remove the ASM
1150                 // specific instructions. To not miss this additional frame, we need to use an ASM_GOTO_W
1151                 // here, which has the unfortunate effect of forcing this additional round trip (which in
1152                 // some case would not have been really necessary, but we can't know this at this point).
1153                 code.putByte(Constants.ASM_GOTO_W);
1154                 hasAsmInstructions = true;
1155                 // The instruction after the GOTO_W becomes the target of the IFNOT instruction.
1156                 nextInsnIsJumpTarget = true;
1157             }
1158             label.put(code, code.length - 1, true);
1159         } else if (baseOpcode != opcode) {
1160             // Case of a GOTO_W or JSR_W specified by the user (normally ClassReader when used to remove
1161             // ASM specific instructions). In this case we keep the original instruction.
1162             code.putByte(opcode);
1163             label.put(code, code.length - 1, true);
1164         } else {
1165             // Case of a jump with an offset >= -32768, or of a jump with an unknown offset. In these
1166             // cases we store the offset in 2 bytes (which will be increased via a ClassReader ->
1167             // ClassWriter round trip if it turns out that 2 bytes are not sufficient).
1168             code.putByte(baseOpcode);
1169             label.put(code, code.length - 1, false);
1170         }
1171 
1172         // If needed, update the maximum stack size and number of locals, and stack map frames.
1173         if (currentBasicBlock != null) {
1174             Label nextBasicBlock = null;
1175             if (compute == COMPUTE_ALL_FRAMES) {
1176                 currentBasicBlock.frame.execute(baseOpcode, 0, null, null);
1177                 // Record the fact that 'label' is the target of a jump instruction.
1178                 label.getCanonicalInstance().flags |= Label.FLAG_JUMP_TARGET;
1179                 // Add 'label' as a successor of the current basic block.
1180                 addSuccessorToCurrentBasicBlock(Edge.JUMP, label);
1181                 if (baseOpcode != Opcodes.GOTO) {
1182                     // The next instruction starts a new basic block (except for GOTO: by default the code
1183                     // following a goto is unreachable - unless there is an explicit label for it - and we
1184                     // should not compute stack frame types for its instructions).
1185                     nextBasicBlock = new Label();
1186                 }
1187             } else if (compute == COMPUTE_INSERTED_FRAMES) {
1188                 currentBasicBlock.frame.execute(baseOpcode, 0, null, null);
1189             } else if (compute == COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES) {
1190                 // No need to update maxRelativeStackSize (the stack size delta is always negative).
1191                 relativeStackSize += STACK_SIZE_DELTA[baseOpcode];
1192             } else {
1193                 if (baseOpcode == Opcodes.JSR) {
1194                     // Record the fact that 'label' designates a subroutine, if not already done.
1195                     if ((label.flags & Label.FLAG_SUBROUTINE_START) == 0) {
1196                         label.flags |= Label.FLAG_SUBROUTINE_START;
1197                         hasSubroutines = true;
1198                     }
1199                     currentBasicBlock.flags |= Label.FLAG_SUBROUTINE_CALLER;
1200                     // Note that, by construction in this method, a block which calls a subroutine has at
1201                     // least two successors in the control flow graph: the first one (added below) leads to
1202                     // the instruction after the JSR, while the second one (added here) leads to the JSR
1203                     // target. Note that the first successor is virtual (it does not correspond to a possible
1204                     // execution path): it is only used to compute the successors of the basic blocks ending
1205                     // with a ret, in {@link Label#addSubroutineRetSuccessors}.
1206                     addSuccessorToCurrentBasicBlock(relativeStackSize + 1, label);
1207                     // The instruction after the JSR starts a new basic block.
1208                     nextBasicBlock = new Label();
1209                 } else {
1210                     // No need to update maxRelativeStackSize (the stack size delta is always negative).
1211                     relativeStackSize += STACK_SIZE_DELTA[baseOpcode];
1212                     addSuccessorToCurrentBasicBlock(relativeStackSize, label);
1213                 }
1214             }
1215             // If the next instruction starts a new basic block, call visitLabel to add the label of this
1216             // instruction as a successor of the current block, and to start a new basic block.
1217             if (nextBasicBlock != null) {
1218                 if (nextInsnIsJumpTarget) {
1219                     nextBasicBlock.flags |= Label.FLAG_JUMP_TARGET;
1220                 }
1221                 visitLabel(nextBasicBlock);
1222             }
1223             if (baseOpcode == Opcodes.GOTO) {
1224                 endCurrentBasicBlockWithNoSuccessor();
1225             }
1226         }
1227     }
1228 
1229     @Override
1230     public void visitLabel(final Label label) {
1231         // Resolve the forward references to this label, if any.
1232         hasAsmInstructions |= label.resolve(code.data, code.length);
1233         // visitLabel starts a new basic block (except for debug only labels), so we need to update the
1234         // previous and current block references and list of successors.
1235         if ((label.flags & Label.FLAG_DEBUG_ONLY) != 0) {
1236             return;
1237         }
1238         if (compute == COMPUTE_ALL_FRAMES) {
1239             if (currentBasicBlock != null) {
1240                 if (label.bytecodeOffset == currentBasicBlock.bytecodeOffset) {
1241                     // We use {@link Label#getCanonicalInstance} to store the state of a basic block in only
1242                     // one place, but this does not work for labels which have not been visited yet.
1243                     // Therefore, when we detect here two labels having the same bytecode offset, we need to
1244                     // - consolidate the state scattered in these two instances into the canonical instance:
1245                     currentBasicBlock.flags |= (label.flags & Label.FLAG_JUMP_TARGET);
1246                     // - make sure the two instances share the same Frame instance (the implementation of
1247                     // {@link Label#getCanonicalInstance} relies on this property; here label.frame should be
1248                     // null):
1249                     label.frame = currentBasicBlock.frame;
1250                     // - and make sure to NOT assign 'label' into 'currentBasicBlock' or 'lastBasicBlock', so
1251                     // that they still refer to the canonical instance for this bytecode offset.
1252                     return;
1253                 }
1254                 // End the current basic block (with one new successor).
1255                 addSuccessorToCurrentBasicBlock(Edge.JUMP, label);
1256             }
1257             // Append 'label' at the end of the basic block list.
1258             if (lastBasicBlock != null) {
1259                 if (label.bytecodeOffset == lastBasicBlock.bytecodeOffset) {
1260                     // Same comment as above.
1261                     lastBasicBlock.flags |= (label.flags & Label.FLAG_JUMP_TARGET);
1262                     // Here label.frame should be null.
1263                     label.frame = lastBasicBlock.frame;
1264                     currentBasicBlock = lastBasicBlock;
1265                     return;
1266                 }
1267                 lastBasicBlock.nextBasicBlock = label;
1268             }
1269             lastBasicBlock = label;
1270             // Make it the new current basic block.
1271             currentBasicBlock = label;
1272             // Here label.frame should be null.
1273             label.frame = new Frame(label);
1274         } else if (compute == COMPUTE_INSERTED_FRAMES) {
1275             if (currentBasicBlock == null) {
1276                 // This case should happen only once, for the visitLabel call in the constructor. Indeed, if
1277                 // compute is equal to COMPUTE_INSERTED_FRAMES, currentBasicBlock stays unchanged.
1278                 currentBasicBlock = label;
1279             } else {
1280                 // Update the frame owner so that a correct frame offset is computed in Frame.accept().
1281                 currentBasicBlock.frame.owner = label;
1282             }
1283         } else if (compute == COMPUTE_MAX_STACK_AND_LOCAL) {
1284             if (currentBasicBlock != null) {
1285                 // End the current basic block (with one new successor).
1286                 currentBasicBlock.outputStackMax = (short) maxRelativeStackSize;
1287                 addSuccessorToCurrentBasicBlock(relativeStackSize, label);
1288             }
1289             // Start a new current basic block, and reset the current and maximum relative stack sizes.
1290             currentBasicBlock = label;
1291             relativeStackSize = 0;
1292             maxRelativeStackSize = 0;
1293             // Append the new basic block at the end of the basic block list.
1294             if (lastBasicBlock != null) {
1295                 lastBasicBlock.nextBasicBlock = label;
1296             }
1297             lastBasicBlock = label;
1298         } else if (compute == COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES && currentBasicBlock == null) {
1299             // This case should happen only once, for the visitLabel call in the constructor. Indeed, if
1300             // compute is equal to COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES, currentBasicBlock stays
1301             // unchanged.
1302             currentBasicBlock = label;
1303         }
1304     }
1305 
1306     @Override
1307     public void visitLdcInsn(final Object value) {
1308         lastBytecodeOffset = code.length;
1309         // Add the instruction to the bytecode of the method.
1310         Symbol constantSymbol = symbolTable.addConstant(value);
1311         int constantIndex = constantSymbol.index;
1312         char firstDescriptorChar;
1313         boolean isLongOrDouble =
1314                 constantSymbol.tag == Symbol.CONSTANT_LONG_TAG
1315                         || constantSymbol.tag == Symbol.CONSTANT_DOUBLE_TAG
1316                         || (constantSymbol.tag == Symbol.CONSTANT_DYNAMIC_TAG
1317                                 && ((firstDescriptorChar = constantSymbol.value.charAt(0)) == 'J'
1318                                         || firstDescriptorChar == 'D'));
1319         if (isLongOrDouble) {
1320             code.put12(Constants.LDC2_W, constantIndex);
1321         } else if (constantIndex >= 256) {
1322             code.put12(Constants.LDC_W, constantIndex);
1323         } else {
1324             code.put11(Opcodes.LDC, constantIndex);
1325         }
1326         // If needed, update the maximum stack size and number of locals, and stack map frames.
1327         if (currentBasicBlock != null) {
1328             if (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES) {
1329                 currentBasicBlock.frame.execute(Opcodes.LDC, 0, constantSymbol, symbolTable);
1330             } else {
1331                 int size = relativeStackSize + (isLongOrDouble ? 2 : 1);
1332                 if (size > maxRelativeStackSize) {
1333                     maxRelativeStackSize = size;
1334                 }
1335                 relativeStackSize = size;
1336             }
1337         }
1338     }
1339 
1340     @Override
1341     public void visitIincInsn(final int var, final int increment) {
1342         lastBytecodeOffset = code.length;
1343         // Add the instruction to the bytecode of the method.
1344         if ((var > 255) || (increment > 127) || (increment < -128)) {
1345             code.putByte(Constants.WIDE).put12(Opcodes.IINC, var).putShort(increment);
1346         } else {
1347             code.putByte(Opcodes.IINC).put11(var, increment);
1348         }
1349         // If needed, update the maximum stack size and number of locals, and stack map frames.
1350         if (currentBasicBlock != null
1351                 && (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES)) {
1352             currentBasicBlock.frame.execute(Opcodes.IINC, var, null, null);
1353         }
1354         if (compute != COMPUTE_NOTHING) {
1355             int currentMaxLocals = var + 1;
1356             if (currentMaxLocals > maxLocals) {
1357                 maxLocals = currentMaxLocals;
1358             }
1359         }
1360     }
1361 
1362     @Override
1363     public void visitTableSwitchInsn(
1364             final int min, final int max, final Label dflt, final Label... labels) {
1365         lastBytecodeOffset = code.length;
1366         // Add the instruction to the bytecode of the method.
1367         code.putByte(Opcodes.TABLESWITCH).putByteArray(null, 0, (4 - code.length % 4) % 4);
1368         dflt.put(code, lastBytecodeOffset, true);
1369         code.putInt(min).putInt(max);
1370         for (Label label : labels) {
1371             label.put(code, lastBytecodeOffset, true);
1372         }
1373         // If needed, update the maximum stack size and number of locals, and stack map frames.
1374         visitSwitchInsn(dflt, labels);
1375     }
1376 
1377     @Override
1378     public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
1379         lastBytecodeOffset = code.length;
1380         // Add the instruction to the bytecode of the method.
1381         code.putByte(Opcodes.LOOKUPSWITCH).putByteArray(null, 0, (4 - code.length % 4) % 4);
1382         dflt.put(code, lastBytecodeOffset, true);
1383         code.putInt(labels.length);
1384         for (int i = 0; i < labels.length; ++i) {
1385             code.putInt(keys[i]);
1386             labels[i].put(code, lastBytecodeOffset, true);
1387         }
1388         // If needed, update the maximum stack size and number of locals, and stack map frames.
1389         visitSwitchInsn(dflt, labels);
1390     }
1391 
1392     private void visitSwitchInsn(final Label dflt, final Label[] labels) {
1393         if (currentBasicBlock != null) {
1394             if (compute == COMPUTE_ALL_FRAMES) {
1395                 currentBasicBlock.frame.execute(Opcodes.LOOKUPSWITCH, 0, null, null);
1396                 // Add all the labels as successors of the current basic block.
1397                 addSuccessorToCurrentBasicBlock(Edge.JUMP, dflt);
1398                 dflt.getCanonicalInstance().flags |= Label.FLAG_JUMP_TARGET;
1399                 for (Label label : labels) {
1400                     addSuccessorToCurrentBasicBlock(Edge.JUMP, label);
1401                     label.getCanonicalInstance().flags |= Label.FLAG_JUMP_TARGET;
1402                 }
1403             } else if (compute == COMPUTE_MAX_STACK_AND_LOCAL) {
1404                 // No need to update maxRelativeStackSize (the stack size delta is always negative).
1405                 --relativeStackSize;
1406                 // Add all the labels as successors of the current basic block.
1407                 addSuccessorToCurrentBasicBlock(relativeStackSize, dflt);
1408                 for (Label label : labels) {
1409                     addSuccessorToCurrentBasicBlock(relativeStackSize, label);
1410                 }
1411             }
1412             // End the current basic block.
1413             endCurrentBasicBlockWithNoSuccessor();
1414         }
1415     }
1416 
1417     @Override
1418     public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
1419         lastBytecodeOffset = code.length;
1420         // Add the instruction to the bytecode of the method.
1421         Symbol descSymbol = symbolTable.addConstantClass(descriptor);
1422         code.put12(Opcodes.MULTIANEWARRAY, descSymbol.index).putByte(numDimensions);
1423         // If needed, update the maximum stack size and number of locals, and stack map frames.
1424         if (currentBasicBlock != null) {
1425             if (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES) {
1426                 currentBasicBlock.frame.execute(
1427                         Opcodes.MULTIANEWARRAY, numDimensions, descSymbol, symbolTable);
1428             } else {
1429                 // No need to update maxRelativeStackSize (the stack size delta is always negative).
1430                 relativeStackSize += 1 - numDimensions;
1431             }
1432         }
1433     }
1434 
1435     @Override
1436     public AnnotationVisitor visitInsnAnnotation(
1437             final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
1438         if (visible) {
1439             return lastCodeRuntimeVisibleTypeAnnotation =
1440                     AnnotationWriter.create(
1441                             symbolTable,
1442                             (typeRef & 0xFF0000FF) | (lastBytecodeOffset << 8),
1443                             typePath,
1444                             descriptor,
1445                             lastCodeRuntimeVisibleTypeAnnotation);
1446         } else {
1447             return lastCodeRuntimeInvisibleTypeAnnotation =
1448                     AnnotationWriter.create(
1449                             symbolTable,
1450                             (typeRef & 0xFF0000FF) | (lastBytecodeOffset << 8),
1451                             typePath,
1452                             descriptor,
1453                             lastCodeRuntimeInvisibleTypeAnnotation);
1454         }
1455     }
1456 
1457     @Override
1458     public void visitTryCatchBlock(
1459             final Label start, final Label end, final Label handler, final String type) {
1460         Handler newHandler =
1461                 new Handler(
1462                         start, end, handler, type != null ? symbolTable.addConstantClass(type).index : 0, type);
1463         if (firstHandler == null) {
1464             firstHandler = newHandler;
1465         } else {
1466             lastHandler.nextHandler = newHandler;
1467         }
1468         lastHandler = newHandler;
1469     }
1470 
1471     @Override
1472     public AnnotationVisitor visitTryCatchAnnotation(
1473             final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
1474         if (visible) {
1475             return lastCodeRuntimeVisibleTypeAnnotation =
1476                     AnnotationWriter.create(
1477                             symbolTable, typeRef, typePath, descriptor, lastCodeRuntimeVisibleTypeAnnotation);
1478         } else {
1479             return lastCodeRuntimeInvisibleTypeAnnotation =
1480                     AnnotationWriter.create(
1481                             symbolTable, typeRef, typePath, descriptor, lastCodeRuntimeInvisibleTypeAnnotation);
1482         }
1483     }
1484 
1485     @Override
1486     public void visitLocalVariable(
1487             final String name,
1488             final String descriptor,
1489             final String signature,
1490             final Label start,
1491             final Label end,
1492             final int index) {
1493         if (signature != null) {
1494             if (localVariableTypeTable == null) {
1495                 localVariableTypeTable = new ByteVector();
1496             }
1497             ++localVariableTypeTableLength;
1498             localVariableTypeTable
1499                     .putShort(start.bytecodeOffset)
1500                     .putShort(end.bytecodeOffset - start.bytecodeOffset)
1501                     .putShort(symbolTable.addConstantUtf8(name))
1502                     .putShort(symbolTable.addConstantUtf8(signature))
1503                     .putShort(index);
1504         }
1505         if (localVariableTable == null) {
1506             localVariableTable = new ByteVector();
1507         }
1508         ++localVariableTableLength;
1509         localVariableTable
1510                 .putShort(start.bytecodeOffset)
1511                 .putShort(end.bytecodeOffset - start.bytecodeOffset)
1512                 .putShort(symbolTable.addConstantUtf8(name))
1513                 .putShort(symbolTable.addConstantUtf8(descriptor))
1514                 .putShort(index);
1515         if (compute != COMPUTE_NOTHING) {
1516             char firstDescChar = descriptor.charAt(0);
1517             int currentMaxLocals = index + (firstDescChar == 'J' || firstDescChar == 'D' ? 2 : 1);
1518             if (currentMaxLocals > maxLocals) {
1519                 maxLocals = currentMaxLocals;
1520             }
1521         }
1522     }
1523 
1524     @Override
1525     public AnnotationVisitor visitLocalVariableAnnotation(
1526             final int typeRef,
1527             final TypePath typePath,
1528             final Label[] start,
1529             final Label[] end,
1530             final int[] index,
1531             final String descriptor,
1532             final boolean visible) {
1533         // Create a ByteVector to hold a 'type_annotation' JVMS structure.
1534         // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20.
1535         ByteVector typeAnnotation = new ByteVector();
1536         // Write target_type, target_info, and target_path.
1537         typeAnnotation.putByte(typeRef >>> 24).putShort(start.length);
1538         for (int i = 0; i < start.length; ++i) {
1539             typeAnnotation
1540                     .putShort(start[i].bytecodeOffset)
1541                     .putShort(end[i].bytecodeOffset - start[i].bytecodeOffset)
1542                     .putShort(index[i]);
1543         }
1544         TypePath.put(typePath, typeAnnotation);
1545         // Write type_index and reserve space for num_element_value_pairs.
1546         typeAnnotation.putShort(symbolTable.addConstantUtf8(descriptor)).putShort(0);
1547         if (visible) {
1548             return lastCodeRuntimeVisibleTypeAnnotation =
1549                     new AnnotationWriter(
1550                             symbolTable,
1551                             /* useNamedValues = */ true,
1552                             typeAnnotation,
1553                             lastCodeRuntimeVisibleTypeAnnotation);
1554         } else {
1555             return lastCodeRuntimeInvisibleTypeAnnotation =
1556                     new AnnotationWriter(
1557                             symbolTable,
1558                             /* useNamedValues = */ true,
1559                             typeAnnotation,
1560                             lastCodeRuntimeInvisibleTypeAnnotation);
1561         }
1562     }
1563 
1564     @Override
1565     public void visitLineNumber(final int line, final Label start) {
1566         if (lineNumberTable == null) {
1567             lineNumberTable = new ByteVector();
1568         }
1569         ++lineNumberTableLength;
1570         lineNumberTable.putShort(start.bytecodeOffset);
1571         lineNumberTable.putShort(line);
1572     }
1573 
1574     @Override
1575     public void visitMaxs(final int maxStack, final int maxLocals) {
1576         if (compute == COMPUTE_ALL_FRAMES) {
1577             computeAllFrames();
1578         } else if (compute == COMPUTE_MAX_STACK_AND_LOCAL) {
1579             computeMaxStackAndLocal();
1580         } else if (compute == COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES) {
1581             this.maxStack = maxRelativeStackSize;
1582         } else {
1583             this.maxStack = maxStack;
1584             this.maxLocals = maxLocals;
1585         }
1586     }
1587 
1588     /** Computes all the stack map frames of the method, from scratch. */
1589     private void computeAllFrames() {
1590         // Complete the control flow graph with exception handler blocks.
1591         Handler handler = firstHandler;
1592         while (handler != null) {
1593             String catchTypeDescriptor =
1594                     handler.catchTypeDescriptor == null ? "java/lang/Throwable" : handler.catchTypeDescriptor;
1595             int catchType = Frame.getAbstractTypeFromInternalName(symbolTable, catchTypeDescriptor);
1596             // Mark handlerBlock as an exception handler.
1597             Label handlerBlock = handler.handlerPc.getCanonicalInstance();
1598             handlerBlock.flags |= Label.FLAG_JUMP_TARGET;
1599             // Add handlerBlock as a successor of all the basic blocks in the exception handler range.
1600             Label handlerRangeBlock = handler.startPc.getCanonicalInstance();
1601             Label handlerRangeEnd = handler.endPc.getCanonicalInstance();
1602             while (handlerRangeBlock != handlerRangeEnd) {
1603                 handlerRangeBlock.outgoingEdges =
1604                         new Edge(catchType, handlerBlock, handlerRangeBlock.outgoingEdges);
1605                 handlerRangeBlock = handlerRangeBlock.nextBasicBlock;
1606             }
1607             handler = handler.nextHandler;
1608         }
1609 
1610         // Create and visit the first (implicit) frame.
1611         Frame firstFrame = firstBasicBlock.frame;
1612         firstFrame.setInputFrameFromDescriptor(symbolTable, accessFlags, descriptor, this.maxLocals);
1613         firstFrame.accept(this);
1614 
1615         // Fix point algorithm: add the first basic block to a list of blocks to process (i.e. blocks
1616         // whose stack map frame has changed) and, while there are blocks to process, remove one from
1617         // the list and update the stack map frames of its successor blocks in the control flow graph
1618         // (which might change them, in which case these blocks must be processed too, and are thus
1619         // added to the list of blocks to process). Also compute the maximum stack size of the method,
1620         // as a by-product.
1621         Label listOfBlocksToProcess = firstBasicBlock;
1622         listOfBlocksToProcess.nextListElement = Label.EMPTY_LIST;
1623         int maxStackSize = 0;
1624         while (listOfBlocksToProcess != Label.EMPTY_LIST) {
1625             // Remove a basic block from the list of blocks to process.
1626             Label basicBlock = listOfBlocksToProcess;
1627             listOfBlocksToProcess = listOfBlocksToProcess.nextListElement;
1628             basicBlock.nextListElement = null;
1629             // By definition, basicBlock is reachable.
1630             basicBlock.flags |= Label.FLAG_REACHABLE;
1631             // Update the (absolute) maximum stack size.
1632             int maxBlockStackSize = basicBlock.frame.getInputStackSize() + basicBlock.outputStackMax;
1633             if (maxBlockStackSize > maxStackSize) {
1634                 maxStackSize = maxBlockStackSize;
1635             }
1636             // Update the successor blocks of basicBlock in the control flow graph.
1637             Edge outgoingEdge = basicBlock.outgoingEdges;
1638             while (outgoingEdge != null) {
1639                 Label successorBlock = outgoingEdge.successor.getCanonicalInstance();
1640                 boolean successorBlockChanged =
1641                         basicBlock.frame.merge(symbolTable, successorBlock.frame, outgoingEdge.info);
1642                 if (successorBlockChanged && successorBlock.nextListElement == null) {
1643                     // If successorBlock has changed it must be processed. Thus, if it is not already in the
1644                     // list of blocks to process, add it to this list.
1645                     successorBlock.nextListElement = listOfBlocksToProcess;
1646                     listOfBlocksToProcess = successorBlock;
1647                 }
1648                 outgoingEdge = outgoingEdge.nextEdge;
1649             }
1650         }
1651 
1652         // Loop over all the basic blocks and visit the stack map frames that must be stored in the
1653         // StackMapTable attribute. Also replace unreachable code with NOP* ATHROW, and remove it from
1654         // exception handler ranges.
1655         Label basicBlock = firstBasicBlock;
1656         while (basicBlock != null) {
1657             if ((basicBlock.flags & (Label.FLAG_JUMP_TARGET | Label.FLAG_REACHABLE))
1658                     == (Label.FLAG_JUMP_TARGET | Label.FLAG_REACHABLE)) {
1659                 basicBlock.frame.accept(this);
1660             }
1661             if ((basicBlock.flags & Label.FLAG_REACHABLE) == 0) {
1662                 // Find the start and end bytecode offsets of this unreachable block.
1663                 Label nextBasicBlock = basicBlock.nextBasicBlock;
1664                 int startOffset = basicBlock.bytecodeOffset;
1665                 int endOffset = (nextBasicBlock == null ? code.length : nextBasicBlock.bytecodeOffset) - 1;
1666                 if (endOffset >= startOffset) {
1667                     // Replace its instructions with NOP ... NOP ATHROW.
1668                     for (int i = startOffset; i < endOffset; ++i) {
1669                         code.data[i] = Opcodes.NOP;
1670                     }
1671                     code.data[endOffset] = (byte) Opcodes.ATHROW;
1672                     // Emit a frame for this unreachable block, with no local and a Throwable on the stack
1673                     // (so that the ATHROW could consume this Throwable if it were reachable).
1674                     int frameIndex = visitFrameStart(startOffset, /* numLocal = */ 0, /* numStack = */ 1);
1675                     currentFrame[frameIndex] =
1676                             Frame.getAbstractTypeFromInternalName(symbolTable, "java/lang/Throwable");
1677                     visitFrameEnd();
1678                     // Remove this unreachable basic block from the exception handler ranges.
1679                     firstHandler = Handler.removeRange(firstHandler, basicBlock, nextBasicBlock);
1680                     // The maximum stack size is now at least one, because of the Throwable declared above.
1681                     maxStackSize = Math.max(maxStackSize, 1);
1682                 }
1683             }
1684             basicBlock = basicBlock.nextBasicBlock;
1685         }
1686 
1687         this.maxStack = maxStackSize;
1688     }
1689 
1690     /** Computes the maximum stack size of the method. */
1691     private void computeMaxStackAndLocal() {
1692         // Complete the control flow graph with exception handler blocks.
1693         Handler handler = firstHandler;
1694         while (handler != null) {
1695             Label handlerBlock = handler.handlerPc;
1696             Label handlerRangeBlock = handler.startPc;
1697             Label handlerRangeEnd = handler.endPc;
1698             // Add handlerBlock as a successor of all the basic blocks in the exception handler range.
1699             while (handlerRangeBlock != handlerRangeEnd) {
1700                 if ((handlerRangeBlock.flags & Label.FLAG_SUBROUTINE_CALLER) == 0) {
1701                     handlerRangeBlock.outgoingEdges =
1702                             new Edge(Edge.EXCEPTION, handlerBlock, handlerRangeBlock.outgoingEdges);
1703                 } else {
1704                     // If handlerRangeBlock is a JSR block, add handlerBlock after the first two outgoing
1705                     // edges to preserve the hypothesis about JSR block successors order (see
1706                     // {@link #visitJumpInsn}).
1707                     handlerRangeBlock.outgoingEdges.nextEdge.nextEdge =
1708                             new Edge(
1709                                     Edge.EXCEPTION, handlerBlock, handlerRangeBlock.outgoingEdges.nextEdge.nextEdge);
1710                 }
1711                 handlerRangeBlock = handlerRangeBlock.nextBasicBlock;
1712             }
1713             handler = handler.nextHandler;
1714         }
1715 
1716         // Complete the control flow graph with the successor blocks of subroutines, if needed.
1717         if (hasSubroutines) {
1718             // First step: find the subroutines. This step determines, for each basic block, to which
1719             // subroutine(s) it belongs. Start with the main "subroutine":
1720             short numSubroutines = 1;
1721             firstBasicBlock.markSubroutine(numSubroutines);
1722             // Then, mark the subroutines called by the main subroutine, then the subroutines called by
1723             // those called by the main subroutine, etc.
1724             for (short currentSubroutine = 1; currentSubroutine <= numSubroutines; ++currentSubroutine) {
1725                 Label basicBlock = firstBasicBlock;
1726                 while (basicBlock != null) {
1727                     if ((basicBlock.flags & Label.FLAG_SUBROUTINE_CALLER) != 0
1728                             && basicBlock.subroutineId == currentSubroutine) {
1729                         Label jsrTarget = basicBlock.outgoingEdges.nextEdge.successor;
1730                         if (jsrTarget.subroutineId == 0) {
1731                             // If this subroutine has not been marked yet, find its basic blocks.
1732                             jsrTarget.markSubroutine(++numSubroutines);
1733                         }
1734                     }
1735                     basicBlock = basicBlock.nextBasicBlock;
1736                 }
1737             }
1738             // Second step: find the successors in the control flow graph of each subroutine basic block
1739             // 'r' ending with a RET instruction. These successors are the virtual successors of the basic
1740             // blocks ending with JSR instructions (see {@link #visitJumpInsn)} that can reach 'r'.
1741             Label basicBlock = firstBasicBlock;
1742             while (basicBlock != null) {
1743                 if ((basicBlock.flags & Label.FLAG_SUBROUTINE_CALLER) != 0) {
1744                     // By construction, jsr targets are stored in the second outgoing edge of basic blocks
1745                     // that ends with a jsr instruction (see {@link #FLAG_SUBROUTINE_CALLER}).
1746                     Label subroutine = basicBlock.outgoingEdges.nextEdge.successor;
1747                     subroutine.addSubroutineRetSuccessors(basicBlock);
1748                 }
1749                 basicBlock = basicBlock.nextBasicBlock;
1750             }
1751         }
1752 
1753         // Data flow algorithm: put the first basic block in a list of blocks to process (i.e. blocks
1754         // whose input stack size has changed) and, while there are blocks to process, remove one
1755         // from the list, update the input stack size of its successor blocks in the control flow
1756         // graph, and add these blocks to the list of blocks to process (if not already done).
1757         Label listOfBlocksToProcess = firstBasicBlock;
1758         listOfBlocksToProcess.nextListElement = Label.EMPTY_LIST;
1759         int maxStackSize = maxStack;
1760         while (listOfBlocksToProcess != Label.EMPTY_LIST) {
1761             // Remove a basic block from the list of blocks to process. Note that we don't reset
1762             // basicBlock.nextListElement to null on purpose, to make sure we don't reprocess already
1763             // processed basic blocks.
1764             Label basicBlock = listOfBlocksToProcess;
1765             listOfBlocksToProcess = listOfBlocksToProcess.nextListElement;
1766             // Compute the (absolute) input stack size and maximum stack size of this block.
1767             int inputStackTop = basicBlock.inputStackSize;
1768             int maxBlockStackSize = inputStackTop + basicBlock.outputStackMax;
1769             // Update the absolute maximum stack size of the method.
1770             if (maxBlockStackSize > maxStackSize) {
1771                 maxStackSize = maxBlockStackSize;
1772             }
1773             // Update the input stack size of the successor blocks of basicBlock in the control flow
1774             // graph, and add these blocks to the list of blocks to process, if not already done.
1775             Edge outgoingEdge = basicBlock.outgoingEdges;
1776             if ((basicBlock.flags & Label.FLAG_SUBROUTINE_CALLER) != 0) {
1777                 // Ignore the first outgoing edge of the basic blocks ending with a jsr: these are virtual
1778                 // edges which lead to the instruction just after the jsr, and do not correspond to a
1779                 // possible execution path (see {@link #visitJumpInsn} and
1780                 // {@link Label#FLAG_SUBROUTINE_CALLER}).
1781                 outgoingEdge = outgoingEdge.nextEdge;
1782             }
1783             while (outgoingEdge != null) {
1784                 Label successorBlock = outgoingEdge.successor;
1785                 if (successorBlock.nextListElement == null) {
1786                     successorBlock.inputStackSize =
1787                             (short) (outgoingEdge.info == Edge.EXCEPTION ? 1 : inputStackTop + outgoingEdge.info);
1788                     successorBlock.nextListElement = listOfBlocksToProcess;
1789                     listOfBlocksToProcess = successorBlock;
1790                 }
1791                 outgoingEdge = outgoingEdge.nextEdge;
1792             }
1793         }
1794         this.maxStack = maxStackSize;
1795     }
1796 
1797     @Override
1798     public void visitEnd() {
1799         // Nothing to do.
1800     }
1801 
1802     // -----------------------------------------------------------------------------------------------
1803     // Utility methods: control flow analysis algorithm
1804     // -----------------------------------------------------------------------------------------------
1805 
1806     /**
1807       * Adds a successor to {@link #currentBasicBlock} in the control flow graph.
1808       *
1809       * @param info information about the control flow edge to be added.
1810       * @param successor the successor block to be added to the current basic block.
1811       */
1812     private void addSuccessorToCurrentBasicBlock(final int info, final Label successor) {
1813         currentBasicBlock.outgoingEdges = new Edge(info, successor, currentBasicBlock.outgoingEdges);
1814     }
1815 
1816     /**
1817       * Ends the current basic block. This method must be used in the case where the current basic
1818       * block does not have any successor.
1819       *
1820       * <p>WARNING: this method must be called after the currently visited instruction has been put in
1821       * {@link #code} (if frames are computed, this method inserts a new Label to start a new basic
1822       * block after the current instruction).
1823       */
1824     private void endCurrentBasicBlockWithNoSuccessor() {
1825         if (compute == COMPUTE_ALL_FRAMES) {
1826             Label nextBasicBlock = new Label();
1827             nextBasicBlock.frame = new Frame(nextBasicBlock);
1828             nextBasicBlock.resolve(code.data, code.length);
1829             lastBasicBlock.nextBasicBlock = nextBasicBlock;
1830             lastBasicBlock = nextBasicBlock;
1831             currentBasicBlock = null;
1832         } else if (compute == COMPUTE_MAX_STACK_AND_LOCAL) {
1833             currentBasicBlock.outputStackMax = (short) maxRelativeStackSize;
1834             currentBasicBlock = null;
1835         }
1836     }
1837 
1838     // -----------------------------------------------------------------------------------------------
1839     // Utility methods: stack map frames
1840     // -----------------------------------------------------------------------------------------------
1841 
1842     /**
1843       * Starts the visit of a new stack map frame, stored in {@link #currentFrame}.
1844       *
1845       * @param offset the bytecode offset of the instruction to which the frame corresponds.
1846       * @param numLocal the number of local variables in the frame.
1847       * @param numStack the number of stack elements in the frame.
1848       * @return the index of the next element to be written in this frame.
1849       */
1850     int visitFrameStart(final int offset, final int numLocal, final int numStack) {
1851         int frameLength = 3 + numLocal + numStack;
1852         if (currentFrame == null || currentFrame.length < frameLength) {
1853             currentFrame = new int[frameLength];
1854         }
1855         currentFrame[0] = offset;
1856         currentFrame[1] = numLocal;
1857         currentFrame[2] = numStack;
1858         return 3;
1859     }
1860 
1861     /**
1862       * Sets an abstract type in {@link #currentFrame}.
1863       *
1864       * @param frameIndex the index of the element to be set in {@link #currentFrame}.
1865       * @param abstractType an abstract type.
1866       */
1867     void visitAbstractType(final int frameIndex, final int abstractType) {
1868         currentFrame[frameIndex] = abstractType;
1869     }
1870 
1871     /**
1872       * Ends the visit of {@link #currentFrame} by writing it in the StackMapTable entries and by
1873       * updating the StackMapTable number_of_entries (except if the current frame is the first one,
1874       * which is implicit in StackMapTable). Then resets {@link #currentFrame} to {@literal null}.
1875       */
1876     void visitFrameEnd() {
1877         if (previousFrame != null) {
1878             if (stackMapTableEntries == null) {
1879                 stackMapTableEntries = new ByteVector();
1880             }
1881             putFrame();
1882             ++stackMapTableNumberOfEntries;
1883         }
1884         previousFrame = currentFrame;
1885         currentFrame = null;
1886     }
1887 
1888     /** Compresses and writes {@link #currentFrame} in a new StackMapTable entry. */
1889     private void putFrame() {
1890         final int numLocal = currentFrame[1];
1891         final int numStack = currentFrame[2];
1892         if (symbolTable.getMajorVersion() < Opcodes.V1_6) {
1893             // Generate a StackMap attribute entry, which are always uncompressed.
1894             stackMapTableEntries.putShort(currentFrame[0]).putShort(numLocal);
1895             putAbstractTypes(3, 3 + numLocal);
1896             stackMapTableEntries.putShort(numStack);
1897             putAbstractTypes(3 + numLocal, 3 + numLocal + numStack);
1898             return;
1899         }
1900         final int offsetDelta =
1901                 stackMapTableNumberOfEntries == 0
1902                         ? currentFrame[0]
1903                         : currentFrame[0] - previousFrame[0] - 1;
1904         final int previousNumlocal = previousFrame[1];
1905         final int numLocalDelta = numLocal - previousNumlocal;
1906         int type = Frame.FULL_FRAME;
1907         if (numStack == 0) {
1908             switch (numLocalDelta) {
1909                 case -3:
1910                 case -2:
1911                 case -1:
1912                     type = Frame.CHOP_FRAME;
1913                     break;
1914                 case 0:
1915                     type = offsetDelta < 64 ? Frame.SAME_FRAME : Frame.SAME_FRAME_EXTENDED;
1916                     break;
1917                 case 1:
1918                 case 2:
1919                 case 3:
1920                     type = Frame.APPEND_FRAME;
1921                     break;
1922                 default:
1923                     // Keep the FULL_FRAME type.
1924                     break;
1925             }
1926         } else if (numLocalDelta == 0 && numStack == 1) {
1927             type =
1928                     offsetDelta < 63
1929                             ? Frame.SAME_LOCALS_1_STACK_ITEM_FRAME
1930                             : Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;
1931         }
1932         if (type != Frame.FULL_FRAME) {
1933             // Verify if locals are the same as in the previous frame.
1934             int frameIndex = 3;
1935             for (int i = 0; i < previousNumlocal && i < numLocal; i++) {
1936                 if (currentFrame[frameIndex] != previousFrame[frameIndex]) {
1937                     type = Frame.FULL_FRAME;
1938                     break;
1939                 }
1940                 frameIndex++;
1941             }
1942         }
1943         switch (type) {
1944             case Frame.SAME_FRAME:
1945                 stackMapTableEntries.putByte(offsetDelta);
1946                 break;
1947             case Frame.SAME_LOCALS_1_STACK_ITEM_FRAME:
1948                 stackMapTableEntries.putByte(Frame.SAME_LOCALS_1_STACK_ITEM_FRAME + offsetDelta);
1949                 putAbstractTypes(3 + numLocal, 4 + numLocal);
1950                 break;
1951             case Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:
1952                 stackMapTableEntries
1953                         .putByte(Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
1954                         .putShort(offsetDelta);
1955                 putAbstractTypes(3 + numLocal, 4 + numLocal);
1956                 break;
1957             case Frame.SAME_FRAME_EXTENDED:
1958                 stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED).putShort(offsetDelta);
1959                 break;
1960             case Frame.CHOP_FRAME:
1961                 stackMapTableEntries
1962                         .putByte(Frame.SAME_FRAME_EXTENDED + numLocalDelta)
1963                         .putShort(offsetDelta);
1964                 break;
1965             case Frame.APPEND_FRAME:
1966                 stackMapTableEntries
1967                         .putByte(Frame.SAME_FRAME_EXTENDED + numLocalDelta)
1968                         .putShort(offsetDelta);
1969                 putAbstractTypes(3 + previousNumlocal, 3 + numLocal);
1970                 break;
1971             case Frame.FULL_FRAME:
1972             default:
1973                 stackMapTableEntries.putByte(Frame.FULL_FRAME).putShort(offsetDelta).putShort(numLocal);
1974                 putAbstractTypes(3, 3 + numLocal);
1975                 stackMapTableEntries.putShort(numStack);
1976                 putAbstractTypes(3 + numLocal, 3 + numLocal + numStack);
1977                 break;
1978         }
1979     }
1980 
1981     /**
1982       * Puts some abstract types of {@link #currentFrame} in {@link #stackMapTableEntries} , using the
1983       * JVMS verification_type_info format used in StackMapTable attributes.
1984       *
1985       * @param start index of the first type in {@link #currentFrame} to write.
1986       * @param end index of last type in {@link #currentFrame} to write (exclusive).
1987       */
1988     private void putAbstractTypes(final int start, final int end) {
1989         for (int i = start; i < end; ++i) {
1990             Frame.putAbstractType(symbolTable, currentFrame[i], stackMapTableEntries);
1991         }
1992     }
1993 
1994     /**
1995       * Puts the given public API frame element type in {@link #stackMapTableEntries} , using the JVMS
1996       * verification_type_info format used in StackMapTable attributes.
1997       *
1998       * @param type a frame element type described using the same format as in {@link
1999       *     MethodVisitor#visitFrame}, i.e. either {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, {@link
2000       *     Opcodes#FLOAT}, {@link Opcodes#LONG}, {@link Opcodes#DOUBLE}, {@link Opcodes#NULL}, or
2001       *     {@link Opcodes#UNINITIALIZED_THIS}, or the internal name of a class, or a Label designating
2002       *     a NEW instruction (for uninitialized types).
2003       */
2004     private void putFrameType(final Object type) {
2005         if (type instanceof Integer) {
2006             stackMapTableEntries.putByte(((Integer) type).intValue());
2007         } else if (type instanceof String) {
2008             stackMapTableEntries
2009                     .putByte(Frame.ITEM_OBJECT)
2010                     .putShort(symbolTable.addConstantClass((String) type).index);
2011         } else {
2012             stackMapTableEntries
2013                     .putByte(Frame.ITEM_UNINITIALIZED)
2014                     .putShort(((Label) type).bytecodeOffset);
2015         }
2016     }
2017 
2018     // -----------------------------------------------------------------------------------------------
2019     // Utility methods
2020     // -----------------------------------------------------------------------------------------------
2021 
2022     /**
2023       * Returns whether the attributes of this method can be copied from the attributes of the given
2024       * method (assuming there is no method visitor between the given ClassReader and this
2025       * MethodWriter). This method should only be called just after this MethodWriter has been created,
2026       * and before any content is visited. It returns true if the attributes corresponding to the
2027       * constructor arguments (at most a Signature, an Exception, a Deprecated and a Synthetic
2028       * attribute) are the same as the corresponding attributes in the given method.
2029       *
2030       * @param source the source ClassReader from which the attributes of this method might be copied.
2031       * @param hasSyntheticAttribute whether the method_info JVMS structure from which the attributes
2032       *     of this method might be copied contains a Synthetic attribute.
2033       * @param hasDeprecatedAttribute whether the method_info JVMS structure from which the attributes
2034       *     of this method might be copied contains a Deprecated attribute.
2035       * @param descriptorIndex the descriptor_index field of the method_info JVMS structure from which
2036       *     the attributes of this method might be copied.
2037       * @param signatureIndex the constant pool index contained in the Signature attribute of the
2038       *     method_info JVMS structure from which the attributes of this method might be copied, or 0.
2039       * @param exceptionsOffset the offset in 'source.b' of the Exceptions attribute of the method_info
2040       *     JVMS structure from which the attributes of this method might be copied, or 0.
2041       * @return whether the attributes of this method can be copied from the attributes of the
2042       *     method_info JVMS structure in 'source.b', between 'methodInfoOffset' and 'methodInfoOffset'
2043       *     + 'methodInfoLength'.
2044       */
2045     boolean canCopyMethodAttributes(
2046             final ClassReader source,
2047             final boolean hasSyntheticAttribute,
2048             final boolean hasDeprecatedAttribute,
2049             final int descriptorIndex,
2050             final int signatureIndex,
2051             final int exceptionsOffset) {
2052         // If the method descriptor has changed, with more locals than the max_locals field of the
2053         // original Code attribute, if any, then the original method attributes can't be copied. A
2054         // conservative check on the descriptor changes alone ensures this (being more precise is not
2055         // worth the additional complexity, because these cases should be rare -- if a transform changes
2056         // a method descriptor, most of the time it needs to change the method's code too).
2057         if (source != symbolTable.getSource()
2058                 || descriptorIndex != this.descriptorIndex
2059                 || signatureIndex != this.signatureIndex
2060                 || hasDeprecatedAttribute != ((accessFlags & Opcodes.ACC_DEPRECATED) != 0)) {
2061             return false;
2062         }
2063         boolean needSyntheticAttribute =
2064                 symbolTable.getMajorVersion() < Opcodes.V1_5 && (accessFlags & Opcodes.ACC_SYNTHETIC) != 0;
2065         if (hasSyntheticAttribute != needSyntheticAttribute) {
2066             return false;
2067         }
2068         if (exceptionsOffset == 0) {
2069             if (numberOfExceptions != 0) {
2070                 return false;
2071             }
2072         } else if (source.readUnsignedShort(exceptionsOffset) == numberOfExceptions) {
2073             int currentExceptionOffset = exceptionsOffset + 2;
2074             for (int i = 0; i < numberOfExceptions; ++i) {
2075                 if (source.readUnsignedShort(currentExceptionOffset) != exceptionIndexTable[i]) {
2076                     return false;
2077                 }
2078                 currentExceptionOffset += 2;
2079             }
2080         }
2081         return true;
2082     }
2083 
2084     /**
2085       * Sets the source from which the attributes of this method will be copied.
2086       *
2087       * @param methodInfoOffset the offset in 'symbolTable.getSource()' of the method_info JVMS
2088       *     structure from which the attributes of this method will be copied.
2089       * @param methodInfoLength the length in 'symbolTable.getSource()' of the method_info JVMS
2090       *     structure from which the attributes of this method will be copied.
2091       */
2092     void setMethodAttributesSource(final int methodInfoOffset, final int methodInfoLength) {
2093         // Don't copy the attributes yet, instead store their location in the source class reader so
2094         // they can be copied later, in {@link #putMethodInfo}. Note that we skip the 6 header bytes
2095         // of the method_info JVMS structure.
2096         this.sourceOffset = methodInfoOffset + 6;
2097         this.sourceLength = methodInfoLength - 6;
2098     }
2099 
2100     /**
2101       * Returns the size of the method_info JVMS structure generated by this MethodWriter. Also add the
2102       * names of the attributes of this method in the constant pool.
2103       *
2104       * @return the size in bytes of the method_info JVMS structure.
2105       */
2106     int computeMethodInfoSize() {
2107         // If this method_info must be copied from an existing one, the size computation is trivial.
2108         if (sourceOffset != 0) {
2109             // sourceLength excludes the first 6 bytes for access_flags, name_index and descriptor_index.
2110             return 6 + sourceLength;
2111         }
2112         // 2 bytes each for access_flags, name_index, descriptor_index and attributes_count.
2113         int size = 8;
2114         // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
2115         if (code.length > 0) {
2116             if (code.length > 65535) {
2117                 throw new MethodTooLargeException(
2118                         symbolTable.getClassName(), name, descriptor, code.length);
2119             }
2120             symbolTable.addConstantUtf8(Constants.CODE);
2121             // The Code attribute has 6 header bytes, plus 2, 2, 4 and 2 bytes respectively for max_stack,
2122             // max_locals, code_length and attributes_count, plus the bytecode and the exception table.
2123             size += 16 + code.length + Handler.getExceptionTableSize(firstHandler);
2124             if (stackMapTableEntries != null) {
2125                 boolean useStackMapTable = symbolTable.getMajorVersion() >= Opcodes.V1_6;
2126                 symbolTable.addConstantUtf8(useStackMapTable ? Constants.STACK_MAP_TABLE : "StackMap");
2127                 // 6 header bytes and 2 bytes for number_of_entries.
2128                 size += 8 + stackMapTableEntries.length;
2129             }
2130             if (lineNumberTable != null) {
2131                 symbolTable.addConstantUtf8(Constants.LINE_NUMBER_TABLE);
2132                 // 6 header bytes and 2 bytes for line_number_table_length.
2133                 size += 8 + lineNumberTable.length;
2134             }
2135             if (localVariableTable != null) {
2136                 symbolTable.addConstantUtf8(Constants.LOCAL_VARIABLE_TABLE);
2137                 // 6 header bytes and 2 bytes for local_variable_table_length.
2138                 size += 8 + localVariableTable.length;
2139             }
2140             if (localVariableTypeTable != null) {
2141                 symbolTable.addConstantUtf8(Constants.LOCAL_VARIABLE_TYPE_TABLE);
2142                 // 6 header bytes and 2 bytes for local_variable_type_table_length.
2143                 size += 8 + localVariableTypeTable.length;
2144             }
2145             if (lastCodeRuntimeVisibleTypeAnnotation != null) {
2146                 size +=
2147                         lastCodeRuntimeVisibleTypeAnnotation.computeAnnotationsSize(
2148                                 Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
2149             }
2150             if (lastCodeRuntimeInvisibleTypeAnnotation != null) {
2151                 size +=
2152                         lastCodeRuntimeInvisibleTypeAnnotation.computeAnnotationsSize(
2153                                 Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS);
2154             }
2155             if (firstCodeAttribute != null) {
2156                 size +=
2157                         firstCodeAttribute.computeAttributesSize(
2158                                 symbolTable, code.data, code.length, maxStack, maxLocals);
2159             }
2160         }
2161         if (numberOfExceptions > 0) {
2162             symbolTable.addConstantUtf8(Constants.EXCEPTIONS);
2163             size += 8 + 2 * numberOfExceptions;
2164         }
2165         size += Attribute.computeAttributesSize(symbolTable, accessFlags, signatureIndex);
2166         size +=
2167                 AnnotationWriter.computeAnnotationsSize(
2168                         lastRuntimeVisibleAnnotation,
2169                         lastRuntimeInvisibleAnnotation,
2170                         lastRuntimeVisibleTypeAnnotation,
2171                         lastRuntimeInvisibleTypeAnnotation);
2172         if (lastRuntimeVisibleParameterAnnotations != null) {
2173             size +=
2174                     AnnotationWriter.computeParameterAnnotationsSize(
2175                             Constants.RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS,
2176                             lastRuntimeVisibleParameterAnnotations,
2177                             visibleAnnotableParameterCount == 0
2178                                     ? lastRuntimeVisibleParameterAnnotations.length
2179                                     : visibleAnnotableParameterCount);
2180         }
2181         if (lastRuntimeInvisibleParameterAnnotations != null) {
2182             size +=
2183                     AnnotationWriter.computeParameterAnnotationsSize(
2184                             Constants.RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS,
2185                             lastRuntimeInvisibleParameterAnnotations,
2186                             invisibleAnnotableParameterCount == 0
2187                                     ? lastRuntimeInvisibleParameterAnnotations.length
2188                                     : invisibleAnnotableParameterCount);
2189         }
2190         if (defaultValue != null) {
2191             symbolTable.addConstantUtf8(Constants.ANNOTATION_DEFAULT);
2192             size += 6 + defaultValue.length;
2193         }
2194         if (parameters != null) {
2195             symbolTable.addConstantUtf8(Constants.METHOD_PARAMETERS);
2196             // 6 header bytes and 1 byte for parameters_count.
2197             size += 7 + parameters.length;
2198         }
2199         if (firstAttribute != null) {
2200             size += firstAttribute.computeAttributesSize(symbolTable);
2201         }
2202         return size;
2203     }
2204 
2205     /**
2206       * Puts the content of the method_info JVMS structure generated by this MethodWriter into the
2207       * given ByteVector.
2208       *
2209       * @param output where the method_info structure must be put.
2210       */
2211     void putMethodInfo(final ByteVector output) {
2212         boolean useSyntheticAttribute = symbolTable.getMajorVersion() < Opcodes.V1_5;
2213         int mask = useSyntheticAttribute ? Opcodes.ACC_SYNTHETIC : 0;
2214         output.putShort(accessFlags & ~mask).putShort(nameIndex).putShort(descriptorIndex);
2215         // If this method_info must be copied from an existing one, copy it now and return early.
2216         if (sourceOffset != 0) {
2217             output.putByteArray(symbolTable.getSource().classFileBuffer, sourceOffset, sourceLength);
2218             return;
2219         }
2220         // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
2221         int attributeCount = 0;
2222         if (code.length > 0) {
2223             ++attributeCount;
2224         }
2225         if (numberOfExceptions > 0) {
2226             ++attributeCount;
2227         }
2228         if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && useSyntheticAttribute) {
2229             ++attributeCount;
2230         }
2231         if (signatureIndex != 0) {
2232             ++attributeCount;
2233         }
2234         if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) {
2235             ++attributeCount;
2236         }
2237         if (lastRuntimeVisibleAnnotation != null) {
2238             ++attributeCount;
2239         }
2240         if (lastRuntimeInvisibleAnnotation != null) {
2241             ++attributeCount;
2242         }
2243         if (lastRuntimeVisibleParameterAnnotations != null) {
2244             ++attributeCount;
2245         }
2246         if (lastRuntimeInvisibleParameterAnnotations != null) {
2247             ++attributeCount;
2248         }
2249         if (lastRuntimeVisibleTypeAnnotation != null) {
2250             ++attributeCount;
2251         }
2252         if (lastRuntimeInvisibleTypeAnnotation != null) {
2253             ++attributeCount;
2254         }
2255         if (defaultValue != null) {
2256             ++attributeCount;
2257         }
2258         if (parameters != null) {
2259             ++attributeCount;
2260         }
2261         if (firstAttribute != null) {
2262             attributeCount += firstAttribute.getAttributeCount();
2263         }
2264         // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
2265         output.putShort(attributeCount);
2266         if (code.length > 0) {
2267             // 2, 2, 4 and 2 bytes respectively for max_stack, max_locals, code_length and
2268             // attributes_count, plus the bytecode and the exception table.
2269             int size = 10 + code.length + Handler.getExceptionTableSize(firstHandler);
2270             int codeAttributeCount = 0;
2271             if (stackMapTableEntries != null) {
2272                 // 6 header bytes and 2 bytes for number_of_entries.
2273                 size += 8 + stackMapTableEntries.length;
2274                 ++codeAttributeCount;
2275             }
2276             if (lineNumberTable != null) {
2277                 // 6 header bytes and 2 bytes for line_number_table_length.
2278                 size += 8 + lineNumberTable.length;
2279                 ++codeAttributeCount;
2280             }
2281             if (localVariableTable != null) {
2282                 // 6 header bytes and 2 bytes for local_variable_table_length.
2283                 size += 8 + localVariableTable.length;
2284                 ++codeAttributeCount;
2285             }
2286             if (localVariableTypeTable != null) {
2287                 // 6 header bytes and 2 bytes for local_variable_type_table_length.
2288                 size += 8 + localVariableTypeTable.length;
2289                 ++codeAttributeCount;
2290             }
2291             if (lastCodeRuntimeVisibleTypeAnnotation != null) {
2292                 size +=
2293                         lastCodeRuntimeVisibleTypeAnnotation.computeAnnotationsSize(
2294                                 Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
2295                 ++codeAttributeCount;
2296             }
2297             if (lastCodeRuntimeInvisibleTypeAnnotation != null) {
2298                 size +=
2299                         lastCodeRuntimeInvisibleTypeAnnotation.computeAnnotationsSize(
2300                                 Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS);
2301                 ++codeAttributeCount;
2302             }
2303             if (firstCodeAttribute != null) {
2304                 size +=
2305                         firstCodeAttribute.computeAttributesSize(
2306                                 symbolTable, code.data, code.length, maxStack, maxLocals);
2307                 codeAttributeCount += firstCodeAttribute.getAttributeCount();
2308             }
2309             output
2310                     .putShort(symbolTable.addConstantUtf8(Constants.CODE))
2311                     .putInt(size)
2312                     .putShort(maxStack)
2313                     .putShort(maxLocals)
2314                     .putInt(code.length)
2315                     .putByteArray(code.data, 0, code.length);
2316             Handler.putExceptionTable(firstHandler, output);
2317             output.putShort(codeAttributeCount);
2318             if (stackMapTableEntries != null) {
2319                 boolean useStackMapTable = symbolTable.getMajorVersion() >= Opcodes.V1_6;
2320                 output
2321                         .putShort(
2322                                 symbolTable.addConstantUtf8(
2323                                         useStackMapTable ? Constants.STACK_MAP_TABLE : "StackMap"))
2324                         .putInt(2 + stackMapTableEntries.length)
2325                         .putShort(stackMapTableNumberOfEntries)
2326                         .putByteArray(stackMapTableEntries.data, 0, stackMapTableEntries.length);
2327             }
2328             if (lineNumberTable != null) {
2329                 output
2330                         .putShort(symbolTable.addConstantUtf8(Constants.LINE_NUMBER_TABLE))
2331                         .putInt(2 + lineNumberTable.length)
2332                         .putShort(lineNumberTableLength)
2333                         .putByteArray(lineNumberTable.data, 0, lineNumberTable.length);
2334             }
2335             if (localVariableTable != null) {
2336                 output
2337                         .putShort(symbolTable.addConstantUtf8(Constants.LOCAL_VARIABLE_TABLE))
2338                         .putInt(2 + localVariableTable.length)
2339                         .putShort(localVariableTableLength)
2340                         .putByteArray(localVariableTable.data, 0, localVariableTable.length);
2341             }
2342             if (localVariableTypeTable != null) {
2343                 output
2344                         .putShort(symbolTable.addConstantUtf8(Constants.LOCAL_VARIABLE_TYPE_TABLE))
2345                         .putInt(2 + localVariableTypeTable.length)
2346                         .putShort(localVariableTypeTableLength)
2347                         .putByteArray(localVariableTypeTable.data, 0, localVariableTypeTable.length);
2348             }
2349             if (lastCodeRuntimeVisibleTypeAnnotation != null) {
2350                 lastCodeRuntimeVisibleTypeAnnotation.putAnnotations(
2351                         symbolTable.addConstantUtf8(Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS), output);
2352             }
2353             if (lastCodeRuntimeInvisibleTypeAnnotation != null) {
2354                 lastCodeRuntimeInvisibleTypeAnnotation.putAnnotations(
2355                         symbolTable.addConstantUtf8(Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS), output);
2356             }
2357             if (firstCodeAttribute != null) {
2358                 firstCodeAttribute.putAttributes(
2359                         symbolTable, code.data, code.length, maxStack, maxLocals, output);
2360             }
2361         }
2362         if (numberOfExceptions > 0) {
2363             output
2364                     .putShort(symbolTable.addConstantUtf8(Constants.EXCEPTIONS))
2365                     .putInt(2 + 2 * numberOfExceptions)
2366                     .putShort(numberOfExceptions);
2367             for (int exceptionIndex : exceptionIndexTable) {
2368                 output.putShort(exceptionIndex);
2369             }
2370         }
2371         Attribute.putAttributes(symbolTable, accessFlags, signatureIndex, output);
2372         AnnotationWriter.putAnnotations(
2373                 symbolTable,
2374                 lastRuntimeVisibleAnnotation,
2375                 lastRuntimeInvisibleAnnotation,
2376                 lastRuntimeVisibleTypeAnnotation,
2377                 lastRuntimeInvisibleTypeAnnotation,
2378                 output);
2379         if (lastRuntimeVisibleParameterAnnotations != null) {
2380             AnnotationWriter.putParameterAnnotations(
2381                     symbolTable.addConstantUtf8(Constants.RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS),
2382                     lastRuntimeVisibleParameterAnnotations,
2383                     visibleAnnotableParameterCount == 0
2384                             ? lastRuntimeVisibleParameterAnnotations.length
2385                             : visibleAnnotableParameterCount,
2386                     output);
2387         }
2388         if (lastRuntimeInvisibleParameterAnnotations != null) {
2389             AnnotationWriter.putParameterAnnotations(
2390                     symbolTable.addConstantUtf8(Constants.RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS),
2391                     lastRuntimeInvisibleParameterAnnotations,
2392                     invisibleAnnotableParameterCount == 0
2393                             ? lastRuntimeInvisibleParameterAnnotations.length
2394                             : invisibleAnnotableParameterCount,
2395                     output);
2396         }
2397         if (defaultValue != null) {
2398             output
2399                     .putShort(symbolTable.addConstantUtf8(Constants.ANNOTATION_DEFAULT))
2400                     .putInt(defaultValue.length)
2401                     .putByteArray(defaultValue.data, 0, defaultValue.length);
2402         }
2403         if (parameters != null) {
2404             output
2405                     .putShort(symbolTable.addConstantUtf8(Constants.METHOD_PARAMETERS))
2406                     .putInt(1 + parameters.length)
2407                     .putByte(parametersCount)
2408                     .putByteArray(parameters.data, 0, parameters.length);
2409         }
2410         if (firstAttribute != null) {
2411             firstAttribute.putAttributes(symbolTable, output);
2412         }
2413     }
2414 
2415     /**
2416       * Collects the attributes of this method into the given set of attribute prototypes.
2417       *
2418       * @param attributePrototypes a set of attribute prototypes.
2419       */
2420     final void collectAttributePrototypes(final Attribute.Set attributePrototypes) {
2421         attributePrototypes.addAttributes(firstAttribute);
2422         attributePrototypes.addAttributes(firstCodeAttribute);
2423     }
2424 }