1674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/*** 2674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * ASM: a very small and fast Java bytecode manipulation framework 3674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Copyright (c) 2000-2007 INRIA, France Telecom 4674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * All rights reserved. 5674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 6674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Redistribution and use in source and binary forms, with or without 7674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * modification, are permitted provided that the following conditions 8674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * are met: 9674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 1. Redistributions of source code must retain the above copyright 10674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * notice, this list of conditions and the following disclaimer. 11674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 2. Redistributions in binary form must reproduce the above copyright 12674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * notice, this list of conditions and the following disclaimer in the 13674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * documentation and/or other materials provided with the distribution. 14674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 3. Neither the name of the copyright holders nor the names of its 15674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * contributors may be used to endorse or promote products derived from 16674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * this software without specific prior written permission. 17674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 18674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * THE POSSIBILITY OF SUCH DAMAGE. 29674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 30674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenpackage org.mockito.asm; 31674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 32674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/** 33674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * A label represents a position in the bytecode of a method. Labels are used 34674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * for jump, goto, and switch instructions, and for try catch blocks. 35674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 36674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @author Eric Bruneton 37674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 38674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenpublic class Label { 39674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 40674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 41674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Indicates if this label is only used for debug attributes. Such a label 42674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * is not the start of a basic block, the target of a jump instruction, or 43674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * an exception handler. It can be safely ignored in control flow graph 44674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * analysis algorithms (for optimization purposes). 45674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 46674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int DEBUG = 1; 47674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 48674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 49674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Indicates if the position of this label is known. 50674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 51674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int RESOLVED = 2; 52674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 53674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 54674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Indicates if this label has been updated, after instruction resizing. 55674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 56674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int RESIZED = 4; 57674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 58674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 59674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Indicates if this basic block has been pushed in the basic block stack. 60674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * See {@link MethodWriter#visitMaxs visitMaxs}. 61674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 62674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int PUSHED = 8; 63674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 64674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 65674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Indicates if this label is the target of a jump instruction, or the start 66674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * of an exception handler. 67674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 68674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int TARGET = 16; 69674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 70674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 71674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Indicates if a stack map frame must be stored for this label. 72674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 73674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int STORE = 32; 74674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 75674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 76674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Indicates if this label corresponds to a reachable basic block. 77674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 78674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int REACHABLE = 64; 79674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 80674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 81674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Indicates if this basic block ends with a JSR instruction. 82674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 83674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int JSR = 128; 84674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 85674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 86674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Indicates if this basic block ends with a RET instruction. 87674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 88674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int RET = 256; 89674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 90674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 91674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Indicates if this basic block is the start of a subroutine. 92674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 93674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int SUBROUTINE = 512; 94674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 95674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 96674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Indicates if this subroutine basic block has been visited. 97674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 98674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static final int VISITED = 1024; 99674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 100674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 101674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Field used to associate user information to a label. Warning: this field 102674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * is used by the ASM tree package. In order to use it with the ASM tree 103674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * package you must override the {@link 104674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * org.mockito.asm.tree.MethodNode#getLabelNode} method. 105674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 106674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Object info; 107674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 108674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 109674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Flags that indicate the status of this label. 110674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 111674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #DEBUG 112674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #RESOLVED 113674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #RESIZED 114674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #PUSHED 115674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #TARGET 116674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #STORE 117674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #REACHABLE 118674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #JSR 119674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see #RET 120674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 121674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int status; 122674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 123674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 124674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The line number corresponding to this label, if known. 125674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 126674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int line; 127674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 128674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 129674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The position of this label in the code, if known. 130674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 131674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int position; 132674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 133674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 134674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Number of forward references to this label, times two. 135674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 136674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int referenceCount; 137674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 138674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 139674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Informations about forward references. Each forward reference is 140674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * described by two consecutive integers in this array: the first one is the 141674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * position of the first byte of the bytecode instruction that contains the 142674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * forward reference, while the second is the position of the first byte of 143674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * the forward reference itself. In fact the sign of the first integer 144674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * indicates if this reference uses 2 or 4 bytes, and its absolute value 145674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * gives the position of the bytecode instruction. This array is also used 146674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * as a bitset to store the subroutines to which a basic block belongs. This 147674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * information is needed in {@linked MethodWriter#visitMaxs}, after all 148674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * forward references have been resolved. Hence the same array can be used 149674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * for both purposes without problems. 150674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 151674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private int[] srcAndRefPositions; 152674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 153674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 154674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 155674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /* 156674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Fields for the control flow and data flow graph analysis algorithms (used 157674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * to compute the maximum stack size or the stack map frames). A control 158674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * flow graph contains one node per "basic block", and one edge per "jump" 159674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * from one basic block to another. Each node (i.e., each basic block) is 160674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * represented by the Label object that corresponds to the first instruction 161674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * of this basic block. Each node also stores the list of its successors in 162674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * the graph, as a linked list of Edge objects. 163674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 164674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The control flow analysis algorithms used to compute the maximum stack 165674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * size or the stack map frames are similar and use two steps. The first 166674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * step, during the visit of each instruction, builds information about the 167674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * state of the local variables and the operand stack at the end of each 168674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * basic block, called the "output frame", <i>relatively</i> to the frame 169674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * state at the beginning of the basic block, which is called the "input 170674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * frame", and which is <i>unknown</i> during this step. The second step, 171674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * in {@link MethodWriter#visitMaxs}, is a fix point algorithm that 172674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * computes information about the input frame of each basic block, from the 173674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * input state of the first basic block (known from the method signature), 174674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * and by the using the previously computed relative output frames. 175674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 176674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The algorithm used to compute the maximum stack size only computes the 177674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * relative output and absolute input stack heights, while the algorithm 178674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * used to compute stack map frames computes relative output frames and 179674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * absolute input frames. 180674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 181674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 182674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 183674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Start of the output stack relatively to the input stack. The exact 184674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * semantics of this field depends on the algorithm that is used. 185674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 186674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * When only the maximum stack size is computed, this field is the number of 187674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * elements in the input stack. 188674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 189674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * When the stack map frames are completely computed, this field is the 190674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * offset of the first output stack element relatively to the top of the 191674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * input stack. This offset is always negative or null. A null offset means 192674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * that the output stack must be appended to the input stack. A -n offset 193674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * means that the first n output stack elements must replace the top n input 194674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * stack elements, and that the other elements must be appended to the input 195674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * stack. 196674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 197674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int inputStackTop; 198674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 199674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 200674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Maximum height reached by the output stack, relatively to the top of the 201674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * input stack. This maximum is always positive or null. 202674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 203674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int outputStackMax; 204674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 205674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 206674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Information about the input and output stack map frames of this basic 207674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * block. This field is only used when {@link ClassWriter#COMPUTE_FRAMES} 208674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * option is used. 209674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 210674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Frame frame; 211674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 212674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 213674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The successor of this label, in the order they are visited. This linked 214674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * list does not include labels used for debug info only. If 215674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it 216674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * does not contain successive labels that denote the same bytecode position 217674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * (in this case only the first label appears in this list). 218674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 219674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label successor; 220674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 221674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 222674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The successors of this node in the control flow graph. These successors 223674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * are stored in a linked list of {@link Edge Edge} objects, linked to each 224674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * other by their {@link Edge#next} field. 225674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 226674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Edge successors; 227674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 228674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 229674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * The next basic block in the basic block stack. This stack is used in the 230674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * main loop of the fix point algorithm used in the second step of the 231674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * control flow analysis algorithms. 232674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 233674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @see MethodWriter#visitMaxs 234674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 235674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label next; 236674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 237674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 238674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Constructor 239674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 240674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 241674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 242674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Constructs a new label. 243674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 244674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Label() { 245674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 246674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 247674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 248674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Methods to compute offsets and to manage forward references 249674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 250674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 251674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 252674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Returns the offset corresponding to this label. This offset is computed 253674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * from the start of the method's bytecode. <i>This method is intended for 254674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * {@link Attribute} sub classes, and is normally not needed by class 255674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * generators or adapters.</i> 256674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 257674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return the offset corresponding to this label. 258674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @throws IllegalStateException if this label is not resolved yet. 259674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 260674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public int getOffset() { 261674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((status & RESOLVED) == 0) { 262674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalStateException("Label offset position has not been resolved yet"); 263674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 264674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return position; 265674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 266674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 267674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 268674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Puts a reference to this label in the bytecode of a method. If the 269674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * position of the label is known, the offset is computed and written 270674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * directly. Otherwise, a null offset is written and a new forward reference 271674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * is declared for this label. 272674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 273674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param owner the code writer that calls this method. 274674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param out the bytecode of the method. 275674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param source the position of first byte of the bytecode instruction that 276674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * contains this label. 277674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param wideOffset <tt>true</tt> if the reference must be stored in 4 278674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * bytes, or <tt>false</tt> if it must be stored with 2 bytes. 279674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @throws IllegalArgumentException if this label has not been created by 280674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * the given code writer. 281674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 282674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen void put( 283674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final MethodWriter owner, 284674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final ByteVector out, 285674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int source, 286674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final boolean wideOffset) 287674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 288674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((status & RESOLVED) == 0) { 289674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (wideOffset) { 290674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen addReference(-1 - source, out.length); 291674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putInt(-1); 292674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 293674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen addReference(source, out.length); 294674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(-1); 295674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 296674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 297674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (wideOffset) { 298674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putInt(position - source); 299674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 300674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen out.putShort(position - source); 301674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 302674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 303674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 304674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 305674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 306674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Adds a forward reference to this label. This method must be called only 307674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * for a true forward reference, i.e. only if this label is not resolved 308674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * yet. For backward references, the offset of the reference can be, and 309674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * must be, computed and stored directly. 310674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 311674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param sourcePosition the position of the referencing instruction. This 312674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * position will be used to compute the offset of this forward 313674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * reference. 314674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param referencePosition the position where the offset for this forward 315674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * reference must be stored. 316674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 317674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private void addReference( 318674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int sourcePosition, 319674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int referencePosition) 320674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 321674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (srcAndRefPositions == null) { 322674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen srcAndRefPositions = new int[6]; 323674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 324674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (referenceCount >= srcAndRefPositions.length) { 325674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int[] a = new int[srcAndRefPositions.length + 6]; 326674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen System.arraycopy(srcAndRefPositions, 327674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 0, 328674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen a, 329674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 0, 330674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen srcAndRefPositions.length); 331674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen srcAndRefPositions = a; 332674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 333674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen srcAndRefPositions[referenceCount++] = sourcePosition; 334674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen srcAndRefPositions[referenceCount++] = referencePosition; 335674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 336674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 337674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 338674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Resolves all forward references to this label. This method must be called 339674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * when this label is added to the bytecode of the method, i.e. when its 340674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * position becomes known. This method fills in the blanks that where left 341674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * in the bytecode by each forward reference previously added to this label. 342674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 343674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param owner the code writer that calls this method. 344674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param position the position of this label in the bytecode. 345674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param data the bytecode of the method. 346674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return <tt>true</tt> if a blank that was left for this label was to 347674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * small to store the offset. In such a case the corresponding jump 348674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instruction is replaced with a pseudo instruction (using unused 349674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * opcodes) using an unsigned two bytes offset. These pseudo 350674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instructions will need to be replaced with true instructions with 351674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * wider offsets (4 bytes instead of 2). This is done in 352674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * {@link MethodWriter#resizeInstructions}. 353674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @throws IllegalArgumentException if this label has already been resolved, 354674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * or if it has not been created by the given code writer. 355674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 356674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen boolean resolve( 357674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final MethodWriter owner, 358674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int position, 359674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final byte[] data) 360674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 361674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen boolean needUpdate = false; 362674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.status |= RESOLVED; 363674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.position = position; 364674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int i = 0; 365674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (i < referenceCount) { 366674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int source = srcAndRefPositions[i++]; 367674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int reference = srcAndRefPositions[i++]; 368674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int offset; 369674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (source >= 0) { 370674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen offset = position - source; 371674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) { 372674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /* 373674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * changes the opcode of the jump instruction, in order to 374674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * be able to find it later (see resizeInstructions in 375674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * MethodWriter). These temporary opcodes are similar to 376674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * jump instruction opcodes, except that the 2 bytes offset 377674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * is unsigned (and can therefore represent values from 0 to 378674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 65535, which is sufficient since the size of a method is 379674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * limited to 65535 bytes). 380674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 381674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int opcode = data[reference - 1] & 0xFF; 382674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (opcode <= Opcodes.JSR) { 383674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // changes IFEQ ... JSR to opcodes 202 to 217 384674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen data[reference - 1] = (byte) (opcode + 49); 385674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 386674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // changes IFNULL and IFNONNULL to opcodes 218 and 219 387674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen data[reference - 1] = (byte) (opcode + 20); 388674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 389674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen needUpdate = true; 390674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 391674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen data[reference++] = (byte) (offset >>> 8); 392674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen data[reference] = (byte) offset; 393674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 394674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen offset = position + source + 1; 395674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen data[reference++] = (byte) (offset >>> 24); 396674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen data[reference++] = (byte) (offset >>> 16); 397674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen data[reference++] = (byte) (offset >>> 8); 398674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen data[reference] = (byte) offset; 399674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 400674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 401674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return needUpdate; 402674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 403674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 404674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 405674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Returns the first label of the series to which this label belongs. For an 406674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * isolated label or for the first label in a series of successive labels, 407674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * this method returns the label itself. For other labels it returns the 408674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * first label of the series. 409674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 410674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return the first label of the series to which this label belongs. 411674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 412674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label getFirst() { 413674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return !ClassReader.FRAMES || frame == null ? this : frame.owner; 414674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 415674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 416674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 417674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Methods related to subroutines 418674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 419674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 420674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 421674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Returns true is this basic block belongs to the given subroutine. 422674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 423674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param id a subroutine id. 424674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return true is this basic block belongs to the given subroutine. 425674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 426674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen boolean inSubroutine(final long id) { 427674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((status & Label.VISITED) != 0) { 428674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0; 429674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 430674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return false; 431674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 432674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 433674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 434674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Returns true if this basic block and the given one belong to a common 435674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * subroutine. 436674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 437674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param block another basic block. 438674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return true if this basic block and the given one belong to a common 439674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * subroutine. 440674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 441674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen boolean inSameSubroutine(final Label block) { 442674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < srcAndRefPositions.length; ++i) { 443674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((srcAndRefPositions[i] & block.srcAndRefPositions[i]) != 0) { 444674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return true; 445674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 446674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 447674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return false; 448674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 449674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 450674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 451674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Marks this basic block as belonging to the given subroutine. 452674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 453674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param id a subroutine id. 454674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param nbSubroutines the total number of subroutines in the method. 455674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 456674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen void addToSubroutine(final long id, final int nbSubroutines) { 457674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((status & VISITED) == 0) { 458674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen status |= VISITED; 459674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen srcAndRefPositions = new int[(nbSubroutines - 1) / 32 + 1]; 460674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 461674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen srcAndRefPositions[(int) (id >>> 32)] |= (int) id; 462674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 463674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 464674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 465674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Finds the basic blocks that belong to a given subroutine, and marks these 466674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * blocks as belonging to this subroutine. This recursive method follows the 467674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * control flow graph to find all the blocks that are reachable from the 468674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * current block WITHOUT following any JSR target. 469674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 470674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param JSR a JSR block that jumps to this subroutine. If this JSR is not 471674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * null it is added to the successor of the RET blocks found in the 472674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * subroutine. 473674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param id the id of this subroutine. 474674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param nbSubroutines the total number of subroutines in the method. 475674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 476674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) 477674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen { 478674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (JSR != null) { 479674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((status & VISITED) != 0) { 480674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return; 481674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 482674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen status |= VISITED; 483674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // adds JSR to the successors of this block, if it is a RET block 484674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((status & RET) != 0) { 485674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (!inSameSubroutine(JSR)) { 486674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Edge e = new Edge(); 487674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.info = inputStackTop; 488674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.successor = JSR.successors.successor; 489674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.next = successors; 490674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen successors = e; 491674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 492674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 493674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 494674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // if this block already belongs to subroutine 'id', returns 495674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (inSubroutine(id)) { 496674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return; 497674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 498674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // marks this block as belonging to subroutine 'id' 499674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen addToSubroutine(id, nbSubroutines); 500674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 501674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // calls this method recursively on each successor, except JSR targets 502674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Edge e = successors; 503674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen while (e != null) { 504674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // if this block is a JSR block, then 'successors.next' leads 505674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // to the JSR target (see {@link #visitJumpInsn}) and must therefore 506674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // not be followed 507674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if ((status & Label.JSR) == 0 || e != successors.next) { 508674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.successor.visitSubroutine(JSR, id, nbSubroutines); 509674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 510674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e = e.next; 511674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 512674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 513674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 514674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 515674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Overriden Object methods 516674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // ------------------------------------------------------------------------ 517674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 518674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 519674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Returns a string representation of this label. 520674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 521674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @return a string representation of this label. 522674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 523674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public String toString() { 524674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return "L" + System.identityHashCode(this); 525674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 526674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen} 527