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 bit mask to extract the 'handle' of a forward reference to this label. The extracted handle 121 * is the bytecode offset where the forward reference value is stored (using either 2 or 4 bytes, 122 * as indicated by the {@link #FORWARD_REFERENCE_TYPE_MASK}). 123 * 124 * @see #forwardReferences 125 */ 126 static final int FORWARD_REFERENCE_HANDLE_MASK = 0x0FFFFFFF; 127 128 /** 129 * A sentinel element used to indicate the end of a list of labels. 130 * 131 * @see #nextListElement 132 */ 133 static final Label EMPTY_LIST = new Label(); 134 135 /** 136 * A user managed state associated with this label. Warning: this field is used by the ASM tree 137 * package. In order to use it with the ASM tree package you must override the getLabelNode method 138 * in MethodNode. 139 */ 140 public Object info; 141 142 /** 143 * The type and status of this label or its corresponding basic block. Must be zero or more of 144 * {@link #FLAG_DEBUG_ONLY}, {@link #FLAG_JUMP_TARGET}, {@link #FLAG_RESOLVED}, {@link 145 * #FLAG_REACHABLE}, {@link #FLAG_SUBROUTINE_CALLER}, {@link #FLAG_SUBROUTINE_START}, {@link 146 * #FLAG_SUBROUTINE_END}. 147 */ 148 short flags; 149 150 /** 151 * The source line number corresponding to this label, if {@link #FLAG_LINE_NUMBER} is set. If 152 * there are several source line numbers corresponding to this label, the first one is stored in 153 * this field, and the remaining ones are stored in {@link #otherLineNumbers}. 154 */ 155 private short lineNumber; 156 157 /** 158 * The source line numbers corresponding to this label, in addition to {@link #lineNumber}, or 159 * null. The first element of this array is the number n of source line numbers it contains, which 160 * are stored between indices 1 and n (inclusive). 161 */ 162 private int[] otherLineNumbers; 163 164 /** 165 * The offset of this label in the bytecode of its method, in bytes. This value is set if and only 166 * if the {@link #FLAG_RESOLVED} flag is set. 167 */ 168 int bytecodeOffset; 169 170 /** 171 * The forward references to this label. The first element is the number of forward references, 172 * times 2 (this corresponds to the index of the last element actually used in this array). Then, 173 * each forward reference is described with two consecutive integers noted 174 * 'sourceInsnBytecodeOffset' and 'reference': 175 * 176 * <ul> 177 * <li>'sourceInsnBytecodeOffset' is the bytecode offset of the instruction that contains the 178 * forward reference, 179 * <li>'reference' contains the type and the offset in the bytecode where the forward reference 180 * value must be stored, which can be extracted with {@link #FORWARD_REFERENCE_TYPE_MASK} 181 * and {@link #FORWARD_REFERENCE_HANDLE_MASK}. 182 * </ul> 183 * 184 * <p>For instance, for an ifnull instruction at bytecode offset x, 'sourceInsnBytecodeOffset' is 185 * equal to x, and 'reference' is of type {@link #FORWARD_REFERENCE_TYPE_SHORT} with value x + 1 186 * (because the ifnull instruction uses a 2 bytes bytecode offset operand stored one byte after 187 * the start of the instruction itself). For the default case of a lookupswitch instruction at 188 * bytecode offset x, 'sourceInsnBytecodeOffset' is equal to x, and 'reference' is of type {@link 189 * #FORWARD_REFERENCE_TYPE_WIDE} with value between x + 1 and x + 4 (because the lookupswitch 190 * instruction uses a 4 bytes bytecode offset operand stored one to four bytes after the start of 191 * the instruction itself). 192 */ 193 private int[] forwardReferences; 194 195 // ----------------------------------------------------------------------------------------------- 196 197 // Fields for the control flow and data flow graph analysis algorithms (used to compute the 198 // maximum stack size or the stack map frames). A control flow graph contains one node per "basic 199 // block", and one edge per "jump" from one basic block to another. Each node (i.e., each basic 200 // block) is represented with the Label object that corresponds to the first instruction of this 201 // basic block. Each node also stores the list of its successors in the graph, as a linked list of 202 // Edge objects. 203 // 204 // The control flow analysis algorithms used to compute the maximum stack size or the stack map 205 // frames are similar and use two steps. The first step, during the visit of each instruction, 206 // builds information about the state of the local variables and the operand stack at the end of 207 // each basic block, called the "output frame", <i>relatively</i> to the frame state at the 208 // beginning of the basic block, which is called the "input frame", and which is <i>unknown</i> 209 // during this step. The second step, in {@link MethodWriter#computeAllFrames} and {@link 210 // MethodWriter#computeMaxStackAndLocal}, is a fix point algorithm 211 // that computes information about the input frame of each basic block, from the input state of 212 // the first basic block (known from the method signature), and by the using the previously 213 // computed relative output frames. 214 // 215 // The algorithm used to compute the maximum stack size only computes the relative output and 216 // absolute input stack heights, while the algorithm used to compute stack map frames computes 217 // relative output frames and absolute input frames. 218 219 /** 220 * The number of elements in the input stack of the basic block corresponding to this label. This 221 * field is computed in {@link MethodWriter#computeMaxStackAndLocal}. 222 */ 223 short inputStackSize; 224 225 /** 226 * The number of elements in the output stack, at the end of the basic block corresponding to this 227 * label. This field is only computed for basic blocks that end with a RET instruction. 228 */ 229 short outputStackSize; 230 231 /** 232 * The maximum height reached by the output stack, relatively to the top of the input stack, in 233 * the basic block corresponding to this label. This maximum is always positive or {@literal 234 * null}. 235 */ 236 short outputStackMax; 237 238 /** 239 * The id of the subroutine to which this basic block belongs, or 0. If the basic block belongs to 240 * several subroutines, this is the id of the "oldest" subroutine that contains it (with the 241 * convention that a subroutine calling another one is "older" than the callee). This field is 242 * computed in {@link MethodWriter#computeMaxStackAndLocal}, if the method contains JSR 243 * instructions. 244 */ 245 short subroutineId; 246 247 /** 248 * The input and output stack map frames of the basic block corresponding to this label. This 249 * field is only used when the {@link MethodWriter#COMPUTE_ALL_FRAMES} or {@link 250 * MethodWriter#COMPUTE_INSERTED_FRAMES} option is used. 251 */ 252 Frame frame; 253 254 /** 255 * The successor of this label, in the order they are visited in {@link MethodVisitor#visitLabel}. 256 * This linked list does not include labels used for debug info only. If the {@link 257 * MethodWriter#COMPUTE_ALL_FRAMES} or {@link MethodWriter#COMPUTE_INSERTED_FRAMES} option is used 258 * then it does not contain either successive labels that denote the same bytecode offset (in this 259 * case only the first label appears in this list). 260 */ 261 Label nextBasicBlock; 262 263 /** 264 * The outgoing edges of the basic block corresponding to this label, in the control flow graph of 265 * its method. These edges are stored in a linked list of {@link Edge} objects, linked to each 266 * other by their {@link Edge#nextEdge} field. 267 */ 268 Edge outgoingEdges; 269 270 /** 271 * The next element in the list of labels to which this label belongs, or {@literal null} if it 272 * does not belong to any list. All lists of labels must end with the {@link #EMPTY_LIST} 273 * sentinel, in order to ensure that this field is null if and only if this label does not belong 274 * to a list of labels. Note that there can be several lists of labels at the same time, but that 275 * a label can belong to at most one list at a time (unless some lists share a common tail, but 276 * this is not used in practice). 277 * 278 * <p>List of labels are used in {@link MethodWriter#computeAllFrames} and {@link 279 * MethodWriter#computeMaxStackAndLocal} to compute stack map frames and the maximum stack size, 280 * respectively, as well as in {@link #markSubroutine} and {@link #addSubroutineRetSuccessors} to 281 * compute the basic blocks belonging to subroutines and their outgoing edges. Outside of these 282 * methods, this field should be null (this property is a precondition and a postcondition of 283 * these methods). 284 */ 285 Label nextListElement; 286 287 // ----------------------------------------------------------------------------------------------- 288 // Constructor and accessors 289 // ----------------------------------------------------------------------------------------------- 290 291 /** Constructs a new label. */ Label()292 public Label() { 293 // Nothing to do. 294 } 295 296 /** 297 * Returns the bytecode offset corresponding to this label. This offset is computed from the start 298 * of the method's bytecode. <i>This method is intended for {@link Attribute} sub classes, and is 299 * normally not needed by class generators or adapters.</i> 300 * 301 * @return the bytecode offset corresponding to this label. 302 * @throws IllegalStateException if this label is not resolved yet. 303 */ getOffset()304 public int getOffset() { 305 if ((flags & FLAG_RESOLVED) == 0) { 306 throw new IllegalStateException("Label offset position has not been resolved yet"); 307 } 308 return bytecodeOffset; 309 } 310 311 /** 312 * Returns the "canonical" {@link Label} instance corresponding to this label's bytecode offset, 313 * if known, otherwise the label itself. The canonical instance is the first label (in the order 314 * of their visit by {@link MethodVisitor#visitLabel}) corresponding to this bytecode offset. It 315 * cannot be known for labels which have not been visited yet. 316 * 317 * <p><i>This method should only be used when the {@link MethodWriter#COMPUTE_ALL_FRAMES} option 318 * is used.</i> 319 * 320 * @return the label itself if {@link #frame} is null, otherwise the Label's frame owner. This 321 * corresponds to the "canonical" label instance described above thanks to the way the label 322 * frame is set in {@link MethodWriter#visitLabel}. 323 */ getCanonicalInstance()324 final Label getCanonicalInstance() { 325 return frame == null ? this : frame.owner; 326 } 327 328 // ----------------------------------------------------------------------------------------------- 329 // Methods to manage line numbers 330 // ----------------------------------------------------------------------------------------------- 331 332 /** 333 * Adds a source line number corresponding to this label. 334 * 335 * @param lineNumber a source line number (which should be strictly positive). 336 */ addLineNumber(final int lineNumber)337 final void addLineNumber(final int lineNumber) { 338 if ((flags & FLAG_LINE_NUMBER) == 0) { 339 flags |= FLAG_LINE_NUMBER; 340 this.lineNumber = (short) lineNumber; 341 } else { 342 if (otherLineNumbers == null) { 343 otherLineNumbers = new int[LINE_NUMBERS_CAPACITY_INCREMENT]; 344 } 345 int otherLineNumberIndex = ++otherLineNumbers[0]; 346 if (otherLineNumberIndex >= otherLineNumbers.length) { 347 int[] newLineNumbers = new int[otherLineNumbers.length + LINE_NUMBERS_CAPACITY_INCREMENT]; 348 System.arraycopy(otherLineNumbers, 0, newLineNumbers, 0, otherLineNumbers.length); 349 otherLineNumbers = newLineNumbers; 350 } 351 otherLineNumbers[otherLineNumberIndex] = lineNumber; 352 } 353 } 354 355 /** 356 * Makes the given visitor visit this label and its source line numbers, if applicable. 357 * 358 * @param methodVisitor a method visitor. 359 * @param visitLineNumbers whether to visit of the label's source line numbers, if any. 360 */ accept(final MethodVisitor methodVisitor, final boolean visitLineNumbers)361 final void accept(final MethodVisitor methodVisitor, final boolean visitLineNumbers) { 362 methodVisitor.visitLabel(this); 363 if (visitLineNumbers && (flags & FLAG_LINE_NUMBER) != 0) { 364 methodVisitor.visitLineNumber(lineNumber & 0xFFFF, this); 365 if (otherLineNumbers != null) { 366 for (int i = 1; i <= otherLineNumbers[0]; ++i) { 367 methodVisitor.visitLineNumber(otherLineNumbers[i], this); 368 } 369 } 370 } 371 } 372 373 // ----------------------------------------------------------------------------------------------- 374 // Methods to compute offsets and to manage forward references 375 // ----------------------------------------------------------------------------------------------- 376 377 /** 378 * Puts a reference to this label in the bytecode of a method. If the bytecode offset of the label 379 * is known, the relative bytecode offset between the label and the instruction referencing it is 380 * computed and written directly. Otherwise, a null relative offset is written and a new forward 381 * reference is declared for this label. 382 * 383 * @param code the bytecode of the method. This is where the reference is appended. 384 * @param sourceInsnBytecodeOffset the bytecode offset of the instruction that contains the 385 * reference to be appended. 386 * @param wideReference whether the reference must be stored in 4 bytes (instead of 2 bytes). 387 */ put( final ByteVector code, final int sourceInsnBytecodeOffset, final boolean wideReference)388 final void put( 389 final ByteVector code, final int sourceInsnBytecodeOffset, final boolean wideReference) { 390 if ((flags & FLAG_RESOLVED) == 0) { 391 if (wideReference) { 392 addForwardReference(sourceInsnBytecodeOffset, FORWARD_REFERENCE_TYPE_WIDE, code.length); 393 code.putInt(-1); 394 } else { 395 addForwardReference(sourceInsnBytecodeOffset, FORWARD_REFERENCE_TYPE_SHORT, code.length); 396 code.putShort(-1); 397 } 398 } else { 399 if (wideReference) { 400 code.putInt(bytecodeOffset - sourceInsnBytecodeOffset); 401 } else { 402 code.putShort(bytecodeOffset - sourceInsnBytecodeOffset); 403 } 404 } 405 } 406 407 /** 408 * Adds a forward reference to this label. This method must be called only for a true forward 409 * reference, i.e. only if this label is not resolved yet. For backward references, the relative 410 * bytecode offset of the reference can be, and must be, computed and stored directly. 411 * 412 * @param sourceInsnBytecodeOffset the bytecode offset of the instruction that contains the 413 * reference stored at referenceHandle. 414 * @param referenceType either {@link #FORWARD_REFERENCE_TYPE_SHORT} or {@link 415 * #FORWARD_REFERENCE_TYPE_WIDE}. 416 * @param referenceHandle the offset in the bytecode where the forward reference value must be 417 * stored. 418 */ addForwardReference( final int sourceInsnBytecodeOffset, final int referenceType, final int referenceHandle)419 private void addForwardReference( 420 final int sourceInsnBytecodeOffset, final int referenceType, final int referenceHandle) { 421 if (forwardReferences == null) { 422 forwardReferences = new int[FORWARD_REFERENCES_CAPACITY_INCREMENT]; 423 } 424 int lastElementIndex = forwardReferences[0]; 425 if (lastElementIndex + 2 >= forwardReferences.length) { 426 int[] newValues = new int[forwardReferences.length + FORWARD_REFERENCES_CAPACITY_INCREMENT]; 427 System.arraycopy(forwardReferences, 0, newValues, 0, forwardReferences.length); 428 forwardReferences = newValues; 429 } 430 forwardReferences[++lastElementIndex] = sourceInsnBytecodeOffset; 431 forwardReferences[++lastElementIndex] = referenceType | referenceHandle; 432 forwardReferences[0] = lastElementIndex; 433 } 434 435 /** 436 * Sets the bytecode offset of this label to the given value and resolves the forward references 437 * to this label, if any. This method must be called when this label is added to the bytecode of 438 * the method, i.e. when its bytecode offset becomes known. This method fills in the blanks that 439 * where left in the bytecode by each forward reference previously added to this label. 440 * 441 * @param code the bytecode of the method. 442 * @param bytecodeOffset the bytecode offset of this label. 443 * @return {@literal true} if a blank that was left for this label was too small to store the 444 * offset. In such a case the corresponding jump instruction is replaced with an equivalent 445 * ASM specific instruction using an unsigned two bytes offset. These ASM specific 446 * instructions are later replaced with standard bytecode instructions with wider offsets (4 447 * bytes instead of 2), in ClassReader. 448 */ resolve(final byte[] code, final int bytecodeOffset)449 final boolean resolve(final byte[] code, final int bytecodeOffset) { 450 this.flags |= FLAG_RESOLVED; 451 this.bytecodeOffset = bytecodeOffset; 452 if (forwardReferences == null) { 453 return false; 454 } 455 boolean hasAsmInstructions = false; 456 for (int i = forwardReferences[0]; i > 0; i -= 2) { 457 final int sourceInsnBytecodeOffset = forwardReferences[i - 1]; 458 final int reference = forwardReferences[i]; 459 final int relativeOffset = bytecodeOffset - sourceInsnBytecodeOffset; 460 int handle = reference & FORWARD_REFERENCE_HANDLE_MASK; 461 if ((reference & FORWARD_REFERENCE_TYPE_MASK) == FORWARD_REFERENCE_TYPE_SHORT) { 462 if (relativeOffset < Short.MIN_VALUE || relativeOffset > Short.MAX_VALUE) { 463 // Change the opcode of the jump instruction, in order to be able to find it later in 464 // ClassReader. These ASM specific opcodes are similar to jump instruction opcodes, except 465 // that the 2 bytes offset is unsigned (and can therefore represent values from 0 to 466 // 65535, which is sufficient since the size of a method is limited to 65535 bytes). 467 int opcode = code[sourceInsnBytecodeOffset] & 0xFF; 468 if (opcode < Opcodes.IFNULL) { 469 // Change IFEQ ... JSR to ASM_IFEQ ... ASM_JSR. 470 code[sourceInsnBytecodeOffset] = (byte) (opcode + Constants.ASM_OPCODE_DELTA); 471 } else { 472 // Change IFNULL and IFNONNULL to ASM_IFNULL and ASM_IFNONNULL. 473 code[sourceInsnBytecodeOffset] = (byte) (opcode + Constants.ASM_IFNULL_OPCODE_DELTA); 474 } 475 hasAsmInstructions = true; 476 } 477 code[handle++] = (byte) (relativeOffset >>> 8); 478 code[handle] = (byte) relativeOffset; 479 } else { 480 code[handle++] = (byte) (relativeOffset >>> 24); 481 code[handle++] = (byte) (relativeOffset >>> 16); 482 code[handle++] = (byte) (relativeOffset >>> 8); 483 code[handle] = (byte) relativeOffset; 484 } 485 } 486 return hasAsmInstructions; 487 } 488 489 // ----------------------------------------------------------------------------------------------- 490 // Methods related to subroutines 491 // ----------------------------------------------------------------------------------------------- 492 493 /** 494 * Finds the basic blocks that belong to the subroutine starting with the basic block 495 * corresponding to this label, and marks these blocks as belonging to this subroutine. This 496 * method follows the control flow graph to find all the blocks that are reachable from the 497 * current basic block WITHOUT following any jsr target. 498 * 499 * <p>Note: a precondition and postcondition of this method is that all labels must have a null 500 * {@link #nextListElement}. 501 * 502 * @param subroutineId the id of the subroutine starting with the basic block corresponding to 503 * this label. 504 */ markSubroutine(final short subroutineId)505 final void markSubroutine(final short subroutineId) { 506 // Data flow algorithm: put this basic block in a list of blocks to process (which are blocks 507 // belonging to subroutine subroutineId) and, while there are blocks to process, remove one from 508 // the list, mark it as belonging to the subroutine, and add its successor basic blocks in the 509 // control flow graph to the list of blocks to process (if not already done). 510 Label listOfBlocksToProcess = this; 511 listOfBlocksToProcess.nextListElement = EMPTY_LIST; 512 while (listOfBlocksToProcess != EMPTY_LIST) { 513 // Remove a basic block from the list of blocks to process. 514 Label basicBlock = listOfBlocksToProcess; 515 listOfBlocksToProcess = listOfBlocksToProcess.nextListElement; 516 basicBlock.nextListElement = null; 517 518 // If it is not already marked as belonging to a subroutine, mark it as belonging to 519 // subroutineId and add its successors to the list of blocks to process (unless already done). 520 if (basicBlock.subroutineId == 0) { 521 basicBlock.subroutineId = subroutineId; 522 listOfBlocksToProcess = basicBlock.pushSuccessors(listOfBlocksToProcess); 523 } 524 } 525 } 526 527 /** 528 * Finds the basic blocks that end a subroutine starting with the basic block corresponding to 529 * this label and, for each one of them, adds an outgoing edge to the basic block following the 530 * given subroutine call. In other words, completes the control flow graph by adding the edges 531 * corresponding to the return from this subroutine, when called from the given caller basic 532 * block. 533 * 534 * <p>Note: a precondition and postcondition of this method is that all labels must have a null 535 * {@link #nextListElement}. 536 * 537 * @param subroutineCaller a basic block that ends with a jsr to the basic block corresponding to 538 * this label. This label is supposed to correspond to the start of a subroutine. 539 */ addSubroutineRetSuccessors(final Label subroutineCaller)540 final void addSubroutineRetSuccessors(final Label subroutineCaller) { 541 // Data flow algorithm: put this basic block in a list blocks to process (which are blocks 542 // belonging to a subroutine starting with this label) and, while there are blocks to process, 543 // remove one from the list, put it in a list of blocks that have been processed, add a return 544 // edge to the successor of subroutineCaller if applicable, and add its successor basic blocks 545 // in the control flow graph to the list of blocks to process (if not already done). 546 Label listOfProcessedBlocks = EMPTY_LIST; 547 Label listOfBlocksToProcess = this; 548 listOfBlocksToProcess.nextListElement = EMPTY_LIST; 549 while (listOfBlocksToProcess != EMPTY_LIST) { 550 // Move a basic block from the list of blocks to process to the list of processed blocks. 551 Label basicBlock = listOfBlocksToProcess; 552 listOfBlocksToProcess = basicBlock.nextListElement; 553 basicBlock.nextListElement = listOfProcessedBlocks; 554 listOfProcessedBlocks = basicBlock; 555 556 // Add an edge from this block to the successor of the caller basic block, if this block is 557 // the end of a subroutine and if this block and subroutineCaller do not belong to the same 558 // subroutine. 559 if ((basicBlock.flags & FLAG_SUBROUTINE_END) != 0 560 && basicBlock.subroutineId != subroutineCaller.subroutineId) { 561 basicBlock.outgoingEdges = 562 new Edge( 563 basicBlock.outputStackSize, 564 // By construction, the first outgoing edge of a basic block that ends with a jsr 565 // instruction leads to the jsr continuation block, i.e. where execution continues 566 // when ret is called (see {@link #FLAG_SUBROUTINE_CALLER}). 567 subroutineCaller.outgoingEdges.successor, 568 basicBlock.outgoingEdges); 569 } 570 // Add its successors to the list of blocks to process. Note that {@link #pushSuccessors} does 571 // not push basic blocks which are already in a list. Here this means either in the list of 572 // blocks to process, or in the list of already processed blocks. This second list is 573 // important to make sure we don't reprocess an already processed block. 574 listOfBlocksToProcess = basicBlock.pushSuccessors(listOfBlocksToProcess); 575 } 576 // Reset the {@link #nextListElement} of all the basic blocks that have been processed to null, 577 // so that this method can be called again with a different subroutine or subroutine caller. 578 while (listOfProcessedBlocks != EMPTY_LIST) { 579 Label newListOfProcessedBlocks = listOfProcessedBlocks.nextListElement; 580 listOfProcessedBlocks.nextListElement = null; 581 listOfProcessedBlocks = newListOfProcessedBlocks; 582 } 583 } 584 585 /** 586 * Adds the successors of this label in the method's control flow graph (except those 587 * corresponding to a jsr target, and those already in a list of labels) to the given list of 588 * blocks to process, and returns the new list. 589 * 590 * @param listOfLabelsToProcess a list of basic blocks to process, linked together with their 591 * {@link #nextListElement} field. 592 * @return the new list of blocks to process. 593 */ pushSuccessors(final Label listOfLabelsToProcess)594 private Label pushSuccessors(final Label listOfLabelsToProcess) { 595 Label newListOfLabelsToProcess = listOfLabelsToProcess; 596 Edge outgoingEdge = outgoingEdges; 597 while (outgoingEdge != null) { 598 // By construction, the second outgoing edge of a basic block that ends with a jsr instruction 599 // leads to the jsr target (see {@link #FLAG_SUBROUTINE_CALLER}). 600 boolean isJsrTarget = 601 (flags & Label.FLAG_SUBROUTINE_CALLER) != 0 && outgoingEdge == outgoingEdges.nextEdge; 602 if (!isJsrTarget && outgoingEdge.successor.nextListElement == null) { 603 // Add this successor to the list of blocks to process, if it does not already belong to a 604 // list of labels. 605 outgoingEdge.successor.nextListElement = newListOfLabelsToProcess; 606 newListOfLabelsToProcess = outgoingEdge.successor; 607 } 608 outgoingEdge = outgoingEdge.nextEdge; 609 } 610 return newListOfLabelsToProcess; 611 } 612 613 // ----------------------------------------------------------------------------------------------- 614 // Overridden Object methods 615 // ----------------------------------------------------------------------------------------------- 616 617 /** 618 * Returns a string representation of this label. 619 * 620 * @return a string representation of this label. 621 */ 622 @Override toString()623 public String toString() { 624 return "L" + System.identityHashCode(this); 625 } 626 } 627