1 // ASM: a very small and fast Java bytecode manipulation framework 2 // Copyright (c) 2000-2011 INRIA, France Telecom 3 // All rights reserved. 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions 7 // are met: 8 // 1. Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // 2. Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // 3. Neither the name of the copyright holders nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 // THE POSSIBILITY OF SUCH DAMAGE. 28 package org.objectweb.asm; 29 30 /** 31 * A position in the bytecode of a method. Labels are used for jump, goto, and switch instructions, 32 * and for try catch blocks. A label designates the <i>instruction</i> that is just after. Note 33 * however that there can be other elements between a label and the instruction it designates (such 34 * as other labels, stack map frames, line numbers, etc.). 35 * 36 * @author Eric Bruneton 37 */ 38 public class Label { 39 40 /** 41 * A flag indicating that a label is only used for debug attributes. Such a label is not the start 42 * of a basic block, the target of a jump instruction, or an exception handler. It can be safely 43 * ignored in control flow graph analysis algorithms (for optimization purposes). 44 */ 45 static final int FLAG_DEBUG_ONLY = 1; 46 47 /** 48 * A flag indicating that a label is the target of a jump instruction, or the start of an 49 * exception handler. 50 */ 51 static final int FLAG_JUMP_TARGET = 2; 52 53 /** A flag indicating that the bytecode offset of a label is known. */ 54 static final int FLAG_RESOLVED = 4; 55 56 /** A flag indicating that a label corresponds to a reachable basic block. */ 57 static final int FLAG_REACHABLE = 8; 58 59 /** 60 * A flag indicating that the basic block corresponding to a label ends with a subroutine call. By 61 * construction in {@link MethodWriter#visitJumpInsn}, labels with this flag set have at least two 62 * outgoing edges: 63 * 64 * <ul> 65 * <li>the first one corresponds to the instruction that follows the jsr instruction in the 66 * bytecode, i.e. where execution continues when it returns from the jsr call. This is a 67 * virtual control flow edge, since execution never goes directly from the jsr to the next 68 * instruction. Instead, it goes to the subroutine and eventually returns to the instruction 69 * following the jsr. This virtual edge is used to compute the real outgoing edges of the 70 * basic blocks ending with a ret instruction, in {@link #addSubroutineRetSuccessors}. 71 * <li>the second one corresponds to the target of the jsr instruction, 72 * </ul> 73 */ 74 static final int FLAG_SUBROUTINE_CALLER = 16; 75 76 /** 77 * A flag indicating that the basic block corresponding to a label is the start of a subroutine. 78 */ 79 static final int FLAG_SUBROUTINE_START = 32; 80 81 /** A flag indicating that the basic block corresponding to a label is the end of a subroutine. */ 82 static final int FLAG_SUBROUTINE_END = 64; 83 84 /** A flag indicating that this label has at least one associated line number. */ 85 static final int FLAG_LINE_NUMBER = 128; 86 87 /** 88 * The number of elements to add to the {@link #otherLineNumbers} array when it needs to be 89 * resized to store a new source line number. 90 */ 91 static final int LINE_NUMBERS_CAPACITY_INCREMENT = 4; 92 93 /** 94 * The number of elements to add to the {@link #forwardReferences} array when it needs to be 95 * resized to store a new forward reference. 96 */ 97 static final int FORWARD_REFERENCES_CAPACITY_INCREMENT = 6; 98 99 /** 100 * The bit mask to extract the type of a forward reference to this label. The extracted type is 101 * either {@link #FORWARD_REFERENCE_TYPE_SHORT} or {@link #FORWARD_REFERENCE_TYPE_WIDE}. 102 * 103 * @see #forwardReferences 104 */ 105 static final int FORWARD_REFERENCE_TYPE_MASK = 0xF0000000; 106 107 /** 108 * The type of forward references stored with two bytes in the bytecode. This is the case, for 109 * instance, of a forward reference from an ifnull instruction. 110 */ 111 static final int FORWARD_REFERENCE_TYPE_SHORT = 0x10000000; 112 113 /** 114 * The type of forward references stored in four bytes in the bytecode. This is the case, for 115 * instance, of a forward reference from a lookupswitch instruction. 116 */ 117 static final int FORWARD_REFERENCE_TYPE_WIDE = 0x20000000; 118 119 /** 120 * The type of forward references stored in two bytes in the <i>stack map table</i>. This is the 121 * case of the labels of {@link Frame#ITEM_UNINITIALIZED} stack map frame elements, when the NEW 122 * instruction is after the <init> constructor call (in bytecode offset order). 123 */ 124 static final int FORWARD_REFERENCE_TYPE_STACK_MAP = 0x30000000; 125 126 /** 127 * The bit mask to extract the 'handle' of a forward reference to this label. The extracted handle 128 * is the bytecode offset where the forward reference value is stored (using either 2 or 4 bytes, 129 * as indicated by the {@link #FORWARD_REFERENCE_TYPE_MASK}). 130 * 131 * @see #forwardReferences 132 */ 133 static final int FORWARD_REFERENCE_HANDLE_MASK = 0x0FFFFFFF; 134 135 /** 136 * A sentinel element used to indicate the end of a list of labels. 137 * 138 * @see #nextListElement 139 */ 140 static final Label EMPTY_LIST = new Label(); 141 142 /** 143 * A user managed state associated with this label. Warning: this field is used by the ASM tree 144 * package. In order to use it with the ASM tree package you must override the getLabelNode method 145 * in MethodNode. 146 */ 147 public Object info; 148 149 /** 150 * The type and status of this label or its corresponding basic block. Must be zero or more of 151 * {@link #FLAG_DEBUG_ONLY}, {@link #FLAG_JUMP_TARGET}, {@link #FLAG_RESOLVED}, {@link 152 * #FLAG_REACHABLE}, {@link #FLAG_SUBROUTINE_CALLER}, {@link #FLAG_SUBROUTINE_START}, {@link 153 * #FLAG_SUBROUTINE_END}. 154 */ 155 short flags; 156 157 /** 158 * The source line number corresponding to this label, if {@link #FLAG_LINE_NUMBER} is set. If 159 * there are several source line numbers corresponding to this label, the first one is stored in 160 * this field, and the remaining ones are stored in {@link #otherLineNumbers}. 161 */ 162 private short lineNumber; 163 164 /** 165 * The source line numbers corresponding to this label, in addition to {@link #lineNumber}, or 166 * null. The first element of this array is the number n of source line numbers it contains, which 167 * are stored between indices 1 and n (inclusive). 168 */ 169 private int[] otherLineNumbers; 170 171 /** 172 * The offset of this label in the bytecode of its method, in bytes. This value is set if and only 173 * if the {@link #FLAG_RESOLVED} flag is set. 174 */ 175 int bytecodeOffset; 176 177 /** 178 * The forward references to this label. The first element is the number of forward references, 179 * times 2 (this corresponds to the index of the last element actually used in this array). Then, 180 * each forward reference is described with two consecutive integers noted 181 * 'sourceInsnBytecodeOffset' and 'reference': 182 * 183 * <ul> 184 * <li>'sourceInsnBytecodeOffset' is the bytecode offset of the instruction that contains the 185 * forward reference, 186 * <li>'reference' contains the type and the offset in the bytecode where the forward reference 187 * value must be stored, which can be extracted with {@link #FORWARD_REFERENCE_TYPE_MASK} 188 * and {@link #FORWARD_REFERENCE_HANDLE_MASK}. 189 * </ul> 190 * 191 * <p>For instance, for an ifnull instruction at bytecode offset x, 'sourceInsnBytecodeOffset' is 192 * equal to x, and 'reference' is of type {@link #FORWARD_REFERENCE_TYPE_SHORT} with value x + 1 193 * (because the ifnull instruction uses a 2 bytes bytecode offset operand stored one byte after 194 * the start of the instruction itself). For the default case of a lookupswitch instruction at 195 * bytecode offset x, 'sourceInsnBytecodeOffset' is equal to x, and 'reference' is of type {@link 196 * #FORWARD_REFERENCE_TYPE_WIDE} with value between x + 1 and x + 4 (because the lookupswitch 197 * instruction uses a 4 bytes bytecode offset operand stored one to four bytes after the start of 198 * the instruction itself). 199 */ 200 private int[] forwardReferences; 201 202 // ----------------------------------------------------------------------------------------------- 203 204 // Fields for the control flow and data flow graph analysis algorithms (used to compute the 205 // maximum stack size or the stack map frames). A control flow graph contains one node per "basic 206 // block", and one edge per "jump" from one basic block to another. Each node (i.e., each basic 207 // block) is represented with the Label object that corresponds to the first instruction of this 208 // basic block. Each node also stores the list of its successors in the graph, as a linked list of 209 // Edge objects. 210 // 211 // The control flow analysis algorithms used to compute the maximum stack size or the stack map 212 // frames are similar and use two steps. The first step, during the visit of each instruction, 213 // builds information about the state of the local variables and the operand stack at the end of 214 // each basic block, called the "output frame", <i>relatively</i> to the frame state at the 215 // beginning of the basic block, which is called the "input frame", and which is <i>unknown</i> 216 // during this step. The second step, in {@link MethodWriter#computeAllFrames} and {@link 217 // MethodWriter#computeMaxStackAndLocal}, is a fix point algorithm 218 // that computes information about the input frame of each basic block, from the input state of 219 // the first basic block (known from the method signature), and by the using the previously 220 // computed relative output frames. 221 // 222 // The algorithm used to compute the maximum stack size only computes the relative output and 223 // absolute input stack heights, while the algorithm used to compute stack map frames computes 224 // relative output frames and absolute input frames. 225 226 /** 227 * The number of elements in the input stack of the basic block corresponding to this label. This 228 * field is computed in {@link MethodWriter#computeMaxStackAndLocal}. 229 */ 230 short inputStackSize; 231 232 /** 233 * The number of elements in the output stack, at the end of the basic block corresponding to this 234 * label. This field is only computed for basic blocks that end with a RET instruction. 235 */ 236 short outputStackSize; 237 238 /** 239 * The maximum height reached by the output stack, relatively to the top of the input stack, in 240 * the basic block corresponding to this label. This maximum is always positive or {@literal 241 * null}. 242 */ 243 short outputStackMax; 244 245 /** 246 * The id of the subroutine to which this basic block belongs, or 0. If the basic block belongs to 247 * several subroutines, this is the id of the "oldest" subroutine that contains it (with the 248 * convention that a subroutine calling another one is "older" than the callee). This field is 249 * computed in {@link MethodWriter#computeMaxStackAndLocal}, if the method contains JSR 250 * instructions. 251 */ 252 short subroutineId; 253 254 /** 255 * The input and output stack map frames of the basic block corresponding to this label. This 256 * field is only used when the {@link MethodWriter#COMPUTE_ALL_FRAMES} or {@link 257 * MethodWriter#COMPUTE_INSERTED_FRAMES} option is used. 258 */ 259 Frame frame; 260 261 /** 262 * The successor of this label, in the order they are visited in {@link MethodVisitor#visitLabel}. 263 * This linked list does not include labels used for debug info only. If the {@link 264 * MethodWriter#COMPUTE_ALL_FRAMES} or {@link MethodWriter#COMPUTE_INSERTED_FRAMES} option is used 265 * then it does not contain either successive labels that denote the same bytecode offset (in this 266 * case only the first label appears in this list). 267 */ 268 Label nextBasicBlock; 269 270 /** 271 * The outgoing edges of the basic block corresponding to this label, in the control flow graph of 272 * its method. These edges are stored in a linked list of {@link Edge} objects, linked to each 273 * other by their {@link Edge#nextEdge} field. 274 */ 275 Edge outgoingEdges; 276 277 /** 278 * The next element in the list of labels to which this label belongs, or {@literal null} if it 279 * does not belong to any list. All lists of labels must end with the {@link #EMPTY_LIST} 280 * sentinel, in order to ensure that this field is null if and only if this label does not belong 281 * to a list of labels. Note that there can be several lists of labels at the same time, but that 282 * a label can belong to at most one list at a time (unless some lists share a common tail, but 283 * this is not used in practice). 284 * 285 * <p>List of labels are used in {@link MethodWriter#computeAllFrames} and {@link 286 * MethodWriter#computeMaxStackAndLocal} to compute stack map frames and the maximum stack size, 287 * respectively, as well as in {@link #markSubroutine} and {@link #addSubroutineRetSuccessors} to 288 * compute the basic blocks belonging to subroutines and their outgoing edges. Outside of these 289 * methods, this field should be null (this property is a precondition and a postcondition of 290 * these methods). 291 */ 292 Label nextListElement; 293 294 // ----------------------------------------------------------------------------------------------- 295 // Constructor and accessors 296 // ----------------------------------------------------------------------------------------------- 297 298 /** Constructs a new label. */ Label()299 public Label() { 300 // Nothing to do. 301 } 302 303 /** 304 * Returns the bytecode offset corresponding to this label. This offset is computed from the start 305 * of the method's bytecode. <i>This method is intended for {@link Attribute} sub classes, and is 306 * normally not needed by class generators or adapters.</i> 307 * 308 * @return the bytecode offset corresponding to this label. 309 * @throws IllegalStateException if this label is not resolved yet. 310 */ getOffset()311 public int getOffset() { 312 if ((flags & FLAG_RESOLVED) == 0) { 313 throw new IllegalStateException("Label offset position has not been resolved yet"); 314 } 315 return bytecodeOffset; 316 } 317 318 /** 319 * Returns the "canonical" {@link Label} instance corresponding to this label's bytecode offset, 320 * if known, otherwise the label itself. The canonical instance is the first label (in the order 321 * of their visit by {@link MethodVisitor#visitLabel}) corresponding to this bytecode offset. It 322 * cannot be known for labels which have not been visited yet. 323 * 324 * <p><i>This method should only be used when the {@link MethodWriter#COMPUTE_ALL_FRAMES} option 325 * is used.</i> 326 * 327 * @return the label itself if {@link #frame} is null, otherwise the Label's frame owner. This 328 * corresponds to the "canonical" label instance described above thanks to the way the label 329 * frame is set in {@link MethodWriter#visitLabel}. 330 */ getCanonicalInstance()331 final Label getCanonicalInstance() { 332 return frame == null ? this : frame.owner; 333 } 334 335 // ----------------------------------------------------------------------------------------------- 336 // Methods to manage line numbers 337 // ----------------------------------------------------------------------------------------------- 338 339 /** 340 * Adds a source line number corresponding to this label. 341 * 342 * @param lineNumber a source line number (which should be strictly positive). 343 */ addLineNumber(final int lineNumber)344 final void addLineNumber(final int lineNumber) { 345 if ((flags & FLAG_LINE_NUMBER) == 0) { 346 flags |= FLAG_LINE_NUMBER; 347 this.lineNumber = (short) lineNumber; 348 } else { 349 if (otherLineNumbers == null) { 350 otherLineNumbers = new int[LINE_NUMBERS_CAPACITY_INCREMENT]; 351 } 352 int otherLineNumberIndex = ++otherLineNumbers[0]; 353 if (otherLineNumberIndex >= otherLineNumbers.length) { 354 int[] newLineNumbers = new int[otherLineNumbers.length + LINE_NUMBERS_CAPACITY_INCREMENT]; 355 System.arraycopy(otherLineNumbers, 0, newLineNumbers, 0, otherLineNumbers.length); 356 otherLineNumbers = newLineNumbers; 357 } 358 otherLineNumbers[otherLineNumberIndex] = lineNumber; 359 } 360 } 361 362 /** 363 * Makes the given visitor visit this label and its source line numbers, if applicable. 364 * 365 * @param methodVisitor a method visitor. 366 * @param visitLineNumbers whether to visit of the label's source line numbers, if any. 367 */ accept(final MethodVisitor methodVisitor, final boolean visitLineNumbers)368 final void accept(final MethodVisitor methodVisitor, final boolean visitLineNumbers) { 369 methodVisitor.visitLabel(this); 370 if (visitLineNumbers && (flags & FLAG_LINE_NUMBER) != 0) { 371 methodVisitor.visitLineNumber(lineNumber & 0xFFFF, this); 372 if (otherLineNumbers != null) { 373 for (int i = 1; i <= otherLineNumbers[0]; ++i) { 374 methodVisitor.visitLineNumber(otherLineNumbers[i], this); 375 } 376 } 377 } 378 } 379 380 // ----------------------------------------------------------------------------------------------- 381 // Methods to compute offsets and to manage forward references 382 // ----------------------------------------------------------------------------------------------- 383 384 /** 385 * Puts a reference to this label in the bytecode of a method. If the bytecode offset of the label 386 * is known, the relative bytecode offset between the label and the instruction referencing it is 387 * computed and written directly. Otherwise, a null relative offset is written and a new forward 388 * reference is declared for this label. 389 * 390 * @param code the bytecode of the method. This is where the reference is appended. 391 * @param sourceInsnBytecodeOffset the bytecode offset of the instruction that contains the 392 * reference to be appended. 393 * @param wideReference whether the reference must be stored in 4 bytes (instead of 2 bytes). 394 */ put( final ByteVector code, final int sourceInsnBytecodeOffset, final boolean wideReference)395 final void put( 396 final ByteVector code, final int sourceInsnBytecodeOffset, final boolean wideReference) { 397 if ((flags & FLAG_RESOLVED) == 0) { 398 if (wideReference) { 399 addForwardReference(sourceInsnBytecodeOffset, FORWARD_REFERENCE_TYPE_WIDE, code.length); 400 code.putInt(-1); 401 } else { 402 addForwardReference(sourceInsnBytecodeOffset, FORWARD_REFERENCE_TYPE_SHORT, code.length); 403 code.putShort(-1); 404 } 405 } else { 406 if (wideReference) { 407 code.putInt(bytecodeOffset - sourceInsnBytecodeOffset); 408 } else { 409 code.putShort(bytecodeOffset - sourceInsnBytecodeOffset); 410 } 411 } 412 } 413 414 /** 415 * Puts a reference to this label in the <i>stack map table</i> of a method. If the bytecode 416 * offset of the label is known, it is written directly. Otherwise, a null relative offset is 417 * written and a new forward reference is declared for this label. 418 * 419 * @param stackMapTableEntries the stack map table where the label offset must be added. 420 */ put(final ByteVector stackMapTableEntries)421 final void put(final ByteVector stackMapTableEntries) { 422 if ((flags & FLAG_RESOLVED) == 0) { 423 addForwardReference(0, FORWARD_REFERENCE_TYPE_STACK_MAP, stackMapTableEntries.length); 424 } 425 stackMapTableEntries.putShort(bytecodeOffset); 426 } 427 428 /** 429 * Adds a forward reference to this label. This method must be called only for a true forward 430 * reference, i.e. only if this label is not resolved yet. For backward references, the relative 431 * bytecode offset of the reference can be, and must be, computed and stored directly. 432 * 433 * @param sourceInsnBytecodeOffset the bytecode offset of the instruction that contains the 434 * reference stored at referenceHandle. 435 * @param referenceType either {@link #FORWARD_REFERENCE_TYPE_SHORT} or {@link 436 * #FORWARD_REFERENCE_TYPE_WIDE}. 437 * @param referenceHandle the offset in the bytecode where the forward reference value must be 438 * stored. 439 */ addForwardReference( final int sourceInsnBytecodeOffset, final int referenceType, final int referenceHandle)440 private void addForwardReference( 441 final int sourceInsnBytecodeOffset, final int referenceType, final int referenceHandle) { 442 if (forwardReferences == null) { 443 forwardReferences = new int[FORWARD_REFERENCES_CAPACITY_INCREMENT]; 444 } 445 int lastElementIndex = forwardReferences[0]; 446 if (lastElementIndex + 2 >= forwardReferences.length) { 447 int[] newValues = new int[forwardReferences.length + FORWARD_REFERENCES_CAPACITY_INCREMENT]; 448 System.arraycopy(forwardReferences, 0, newValues, 0, forwardReferences.length); 449 forwardReferences = newValues; 450 } 451 forwardReferences[++lastElementIndex] = sourceInsnBytecodeOffset; 452 forwardReferences[++lastElementIndex] = referenceType | referenceHandle; 453 forwardReferences[0] = lastElementIndex; 454 } 455 456 /** 457 * Sets the bytecode offset of this label to the given value and resolves the forward references 458 * to this label, if any. This method must be called when this label is added to the bytecode of 459 * the method, i.e. when its bytecode offset becomes known. This method fills in the blanks that 460 * where left in the bytecode (and optionally in the stack map table) by each forward reference 461 * previously added to this label. 462 * 463 * @param code the bytecode of the method. 464 * @param stackMapTableEntries the 'entries' array of the StackMapTable code attribute of the 465 * method. Maybe {@literal null}. 466 * @param bytecodeOffset the bytecode offset of this label. 467 * @return {@literal true} if a blank that was left for this label was too small to store the 468 * offset. In such a case the corresponding jump instruction is replaced with an equivalent 469 * ASM specific instruction using an unsigned two bytes offset. These ASM specific 470 * instructions are later replaced with standard bytecode instructions with wider offsets (4 471 * bytes instead of 2), in ClassReader. 472 */ resolve( final byte[] code, final ByteVector stackMapTableEntries, final int bytecodeOffset)473 final boolean resolve( 474 final byte[] code, final ByteVector stackMapTableEntries, final int bytecodeOffset) { 475 this.flags |= FLAG_RESOLVED; 476 this.bytecodeOffset = bytecodeOffset; 477 if (forwardReferences == null) { 478 return false; 479 } 480 boolean hasAsmInstructions = false; 481 for (int i = forwardReferences[0]; i > 0; i -= 2) { 482 final int sourceInsnBytecodeOffset = forwardReferences[i - 1]; 483 final int reference = forwardReferences[i]; 484 final int relativeOffset = bytecodeOffset - sourceInsnBytecodeOffset; 485 int handle = reference & FORWARD_REFERENCE_HANDLE_MASK; 486 if ((reference & FORWARD_REFERENCE_TYPE_MASK) == FORWARD_REFERENCE_TYPE_SHORT) { 487 if (relativeOffset < Short.MIN_VALUE || relativeOffset > Short.MAX_VALUE) { 488 // Change the opcode of the jump instruction, in order to be able to find it later in 489 // ClassReader. These ASM specific opcodes are similar to jump instruction opcodes, except 490 // that the 2 bytes offset is unsigned (and can therefore represent values from 0 to 491 // 65535, which is sufficient since the size of a method is limited to 65535 bytes). 492 int opcode = code[sourceInsnBytecodeOffset] & 0xFF; 493 if (opcode < Opcodes.IFNULL) { 494 // Change IFEQ ... JSR to ASM_IFEQ ... ASM_JSR. 495 code[sourceInsnBytecodeOffset] = (byte) (opcode + Constants.ASM_OPCODE_DELTA); 496 } else { 497 // Change IFNULL and IFNONNULL to ASM_IFNULL and ASM_IFNONNULL. 498 code[sourceInsnBytecodeOffset] = (byte) (opcode + Constants.ASM_IFNULL_OPCODE_DELTA); 499 } 500 hasAsmInstructions = true; 501 } 502 code[handle++] = (byte) (relativeOffset >>> 8); 503 code[handle] = (byte) relativeOffset; 504 } else if ((reference & FORWARD_REFERENCE_TYPE_MASK) == FORWARD_REFERENCE_TYPE_WIDE) { 505 code[handle++] = (byte) (relativeOffset >>> 24); 506 code[handle++] = (byte) (relativeOffset >>> 16); 507 code[handle++] = (byte) (relativeOffset >>> 8); 508 code[handle] = (byte) relativeOffset; 509 } else { 510 stackMapTableEntries.data[handle++] = (byte) (bytecodeOffset >>> 8); 511 stackMapTableEntries.data[handle] = (byte) bytecodeOffset; 512 } 513 } 514 return hasAsmInstructions; 515 } 516 517 // ----------------------------------------------------------------------------------------------- 518 // Methods related to subroutines 519 // ----------------------------------------------------------------------------------------------- 520 521 /** 522 * Finds the basic blocks that belong to the subroutine starting with the basic block 523 * corresponding to this label, and marks these blocks as belonging to this subroutine. This 524 * method follows the control flow graph to find all the blocks that are reachable from the 525 * current basic block WITHOUT following any jsr target. 526 * 527 * <p>Note: a precondition and postcondition of this method is that all labels must have a null 528 * {@link #nextListElement}. 529 * 530 * @param subroutineId the id of the subroutine starting with the basic block corresponding to 531 * this label. 532 */ markSubroutine(final short subroutineId)533 final void markSubroutine(final short subroutineId) { 534 // Data flow algorithm: put this basic block in a list of blocks to process (which are blocks 535 // belonging to subroutine subroutineId) and, while there are blocks to process, remove one from 536 // the list, mark it as belonging to the subroutine, and add its successor basic blocks in the 537 // control flow graph to the list of blocks to process (if not already done). 538 Label listOfBlocksToProcess = this; 539 listOfBlocksToProcess.nextListElement = EMPTY_LIST; 540 while (listOfBlocksToProcess != EMPTY_LIST) { 541 // Remove a basic block from the list of blocks to process. 542 Label basicBlock = listOfBlocksToProcess; 543 listOfBlocksToProcess = listOfBlocksToProcess.nextListElement; 544 basicBlock.nextListElement = null; 545 546 // If it is not already marked as belonging to a subroutine, mark it as belonging to 547 // subroutineId and add its successors to the list of blocks to process (unless already done). 548 if (basicBlock.subroutineId == 0) { 549 basicBlock.subroutineId = subroutineId; 550 listOfBlocksToProcess = basicBlock.pushSuccessors(listOfBlocksToProcess); 551 } 552 } 553 } 554 555 /** 556 * Finds the basic blocks that end a subroutine starting with the basic block corresponding to 557 * this label and, for each one of them, adds an outgoing edge to the basic block following the 558 * given subroutine call. In other words, completes the control flow graph by adding the edges 559 * corresponding to the return from this subroutine, when called from the given caller basic 560 * block. 561 * 562 * <p>Note: a precondition and postcondition of this method is that all labels must have a null 563 * {@link #nextListElement}. 564 * 565 * @param subroutineCaller a basic block that ends with a jsr to the basic block corresponding to 566 * this label. This label is supposed to correspond to the start of a subroutine. 567 */ addSubroutineRetSuccessors(final Label subroutineCaller)568 final void addSubroutineRetSuccessors(final Label subroutineCaller) { 569 // Data flow algorithm: put this basic block in a list blocks to process (which are blocks 570 // belonging to a subroutine starting with this label) and, while there are blocks to process, 571 // remove one from the list, put it in a list of blocks that have been processed, add a return 572 // edge to the successor of subroutineCaller if applicable, and add its successor basic blocks 573 // in the control flow graph to the list of blocks to process (if not already done). 574 Label listOfProcessedBlocks = EMPTY_LIST; 575 Label listOfBlocksToProcess = this; 576 listOfBlocksToProcess.nextListElement = EMPTY_LIST; 577 while (listOfBlocksToProcess != EMPTY_LIST) { 578 // Move a basic block from the list of blocks to process to the list of processed blocks. 579 Label basicBlock = listOfBlocksToProcess; 580 listOfBlocksToProcess = basicBlock.nextListElement; 581 basicBlock.nextListElement = listOfProcessedBlocks; 582 listOfProcessedBlocks = basicBlock; 583 584 // Add an edge from this block to the successor of the caller basic block, if this block is 585 // the end of a subroutine and if this block and subroutineCaller do not belong to the same 586 // subroutine. 587 if ((basicBlock.flags & FLAG_SUBROUTINE_END) != 0 588 && basicBlock.subroutineId != subroutineCaller.subroutineId) { 589 basicBlock.outgoingEdges = 590 new Edge( 591 basicBlock.outputStackSize, 592 // By construction, the first outgoing edge of a basic block that ends with a jsr 593 // instruction leads to the jsr continuation block, i.e. where execution continues 594 // when ret is called (see {@link #FLAG_SUBROUTINE_CALLER}). 595 subroutineCaller.outgoingEdges.successor, 596 basicBlock.outgoingEdges); 597 } 598 // Add its successors to the list of blocks to process. Note that {@link #pushSuccessors} does 599 // not push basic blocks which are already in a list. Here this means either in the list of 600 // blocks to process, or in the list of already processed blocks. This second list is 601 // important to make sure we don't reprocess an already processed block. 602 listOfBlocksToProcess = basicBlock.pushSuccessors(listOfBlocksToProcess); 603 } 604 // Reset the {@link #nextListElement} of all the basic blocks that have been processed to null, 605 // so that this method can be called again with a different subroutine or subroutine caller. 606 while (listOfProcessedBlocks != EMPTY_LIST) { 607 Label newListOfProcessedBlocks = listOfProcessedBlocks.nextListElement; 608 listOfProcessedBlocks.nextListElement = null; 609 listOfProcessedBlocks = newListOfProcessedBlocks; 610 } 611 } 612 613 /** 614 * Adds the successors of this label in the method's control flow graph (except those 615 * corresponding to a jsr target, and those already in a list of labels) to the given list of 616 * blocks to process, and returns the new list. 617 * 618 * @param listOfLabelsToProcess a list of basic blocks to process, linked together with their 619 * {@link #nextListElement} field. 620 * @return the new list of blocks to process. 621 */ pushSuccessors(final Label listOfLabelsToProcess)622 private Label pushSuccessors(final Label listOfLabelsToProcess) { 623 Label newListOfLabelsToProcess = listOfLabelsToProcess; 624 Edge outgoingEdge = outgoingEdges; 625 while (outgoingEdge != null) { 626 // By construction, the second outgoing edge of a basic block that ends with a jsr instruction 627 // leads to the jsr target (see {@link #FLAG_SUBROUTINE_CALLER}). 628 boolean isJsrTarget = 629 (flags & Label.FLAG_SUBROUTINE_CALLER) != 0 && outgoingEdge == outgoingEdges.nextEdge; 630 if (!isJsrTarget && outgoingEdge.successor.nextListElement == null) { 631 // Add this successor to the list of blocks to process, if it does not already belong to a 632 // list of labels. 633 outgoingEdge.successor.nextListElement = newListOfLabelsToProcess; 634 newListOfLabelsToProcess = outgoingEdge.successor; 635 } 636 outgoingEdge = outgoingEdge.nextEdge; 637 } 638 return newListOfLabelsToProcess; 639 } 640 641 // ----------------------------------------------------------------------------------------------- 642 // Overridden Object methods 643 // ----------------------------------------------------------------------------------------------- 644 645 /** 646 * Returns a string representation of this label. 647 * 648 * @return a string representation of this label. 649 */ 650 @Override toString()651 public String toString() { 652 return "L" + System.identityHashCode(this); 653 } 654 } 655