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