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 {@link MethodVisitor} that generates methods in bytecode form. Each visit
34674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * method of this class appends the bytecode corresponding to the visited
35674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * instruction to a byte vector, in the order these methods are called.
36674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *
37674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @author Eric Bruneton
38674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @author Eugene Kuleshov
39674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */
40674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenclass MethodWriter implements MethodVisitor {
41674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
42674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
43674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Pseudo access flag used to denote constructors.
44674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
45674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static final int ACC_CONSTRUCTOR = 262144;
46674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
47674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
48674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Frame has exactly the same locals as the previous stack map frame and
49674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * number of stack items is zero.
50674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
51674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static final int SAME_FRAME = 0; // to 63 (0-3f)
52674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
53674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
54674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Frame has exactly the same locals as the previous stack map frame and
55674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * number of stack items is 1
56674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
57674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; // to 127 (40-7f)
58674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
59674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
60674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Reserved for future use
61674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
62674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static final int RESERVED = 128;
63674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
64674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
65674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Frame has exactly the same locals as the previous stack map frame and
66674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * number of stack items is 1. Offset is bigger then 63;
67674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
68674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247; // f7
69674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
70674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
71674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Frame where current locals are the same as the locals in the previous
72674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * frame, except that the k last locals are absent. The value of k is given
73674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * by the formula 251-frame_type.
74674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
75674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static final int CHOP_FRAME = 248; // to 250 (f8-fA)
76674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
77674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
78674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Frame has exactly the same locals as the previous stack map frame and
79674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * number of stack items is zero. Offset is bigger then 63;
80674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
81674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static final int SAME_FRAME_EXTENDED = 251; // fb
82674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
83674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
84674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Frame where current locals are the same as the locals in the previous
85674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * frame, except that k additional locals are defined. The value of k is
86674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * given by the formula frame_type-251.
87674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
88674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static final int APPEND_FRAME = 252; // to 254 // fc-fe
89674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
90674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
91674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Full frame
92674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
93674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static final int FULL_FRAME = 255; // ff
94674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
95674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
96674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Indicates that the stack map frames must be recomputed from scratch. In
97674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * this case the maximum stack size and number of local variables is also
98674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * recomputed from scratch.
99674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
100674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @see #compute
101674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
102674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static final int FRAMES = 0;
103674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
104674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
105674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Indicates that the maximum stack size and number of local variables must
106674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * be automatically computed.
107674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
108674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @see #compute
109674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
110674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static final int MAXS = 1;
111674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
112674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
113674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Indicates that nothing must be automatically computed.
114674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
115674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @see #compute
116674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
117674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static final int NOTHING = 2;
118674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
119674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
120674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Next method writer (see {@link ClassWriter#firstMethod firstMethod}).
121674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
122674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    MethodWriter next;
123674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
124674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
125674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The class writer to which this method must be added.
126674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
127674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    final ClassWriter cw;
128674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
129674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
130674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Access flags of this method.
131674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
132674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private int access;
133674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
134674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
135674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The index of the constant pool item that contains the name of this
136674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * method.
137674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
138674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private final int name;
139674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
140674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
141674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The index of the constant pool item that contains the descriptor of this
142674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * method.
143674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
144674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private final int desc;
145674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
146674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
147674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The descriptor of this method.
148674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
149674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private final String descriptor;
150674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
151674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
152674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The signature of this method.
153674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
154674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    String signature;
155674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
156674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
157674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * If not zero, indicates that the code of this method must be copied from
158674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * the ClassReader associated to this writer in <code>cw.cr</code>. More
159674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * precisely, this field gives the index of the first byte to copied from
160674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * <code>cw.cr.b</code>.
161674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
162674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    int classReaderOffset;
163674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
164674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
165674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * If not zero, indicates that the code of this method must be copied from
166674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * the ClassReader associated to this writer in <code>cw.cr</code>. More
167674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * precisely, this field gives the number of bytes to copied from
168674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * <code>cw.cr.b</code>.
169674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
170674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    int classReaderLength;
171674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
172674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
173674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Number of exceptions that can be thrown by this method.
174674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
175674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    int exceptionCount;
176674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
177674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
178674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The exceptions that can be thrown by this method. More precisely, this
179674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * array contains the indexes of the constant pool items that contain the
180674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * internal names of these exception classes.
181674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
182674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    int[] exceptions;
183674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
184674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
185674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The annotation default attribute of this method. May be <tt>null</tt>.
186674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
187674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private ByteVector annd;
188674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
189674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
190674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The runtime visible annotations of this method. May be <tt>null</tt>.
191674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
192674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private AnnotationWriter anns;
193674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
194674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
195674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The runtime invisible annotations of this method. May be <tt>null</tt>.
196674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
197674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private AnnotationWriter ianns;
198674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
199674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
200674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The runtime visible parameter annotations of this method. May be
201674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * <tt>null</tt>.
202674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
203674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private AnnotationWriter[] panns;
204674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
205674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
206674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The runtime invisible parameter annotations of this method. May be
207674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * <tt>null</tt>.
208674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
209674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private AnnotationWriter[] ipanns;
210674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
211674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
212674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The number of synthetic parameters of this method.
213674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
214674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private int synthetics;
215674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
216674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
217674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The non standard attributes of the method.
218674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
219674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private Attribute attrs;
220674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
221674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
222674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The bytecode of this method.
223674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
224674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private ByteVector code = new ByteVector();
225674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
226674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
227674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Maximum stack size of this method.
228674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
229674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private int maxStack;
230674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
231674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
232674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Maximum number of local variables for this method.
233674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
234674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private int maxLocals;
235674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
236674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
237674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Number of stack map frames in the StackMapTable attribute.
238674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
239674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private int frameCount;
240674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
241674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
242674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The StackMapTable attribute.
243674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
244674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private ByteVector stackMap;
245674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
246674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
247674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The offset of the last frame that was written in the StackMapTable
248674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * attribute.
249674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
250674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private int previousFrameOffset;
251674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
252674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
253674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The last frame that was written in the StackMapTable attribute.
254674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
255674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @see #frame
256674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
257674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private int[] previousFrame;
258674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
259674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
260674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Index of the next element to be added in {@link #frame}.
261674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
262674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private int frameIndex;
263674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
264674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
265674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The current stack map frame. The first element contains the offset of the
266674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * instruction to which the frame corresponds, the second element is the
267674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * number of locals and the third one is the number of stack elements. The
268674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * local variables start at index 3 and are followed by the operand stack
269674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * values. In summary frame[0] = offset, frame[1] = nLocal, frame[2] =
270674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * nStack, frame[3] = nLocal. All types are encoded as integers, with the
271674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * same format as the one used in {@link Label}, but limited to BASE types.
272674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
273674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private int[] frame;
274674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
275674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
276674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Number of elements in the exception handler list.
277674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
278674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private int handlerCount;
279674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
280674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
281674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The first element in the exception handler list.
282674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
283674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private Handler firstHandler;
284674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
285674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
286674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The last element in the exception handler list.
287674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
288674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private Handler lastHandler;
289674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
290674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
291674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Number of entries in the LocalVariableTable attribute.
292674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
293674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private int localVarCount;
294674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
295674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
296674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The LocalVariableTable attribute.
297674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
298674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private ByteVector localVar;
299674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
300674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
301674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Number of entries in the LocalVariableTypeTable attribute.
302674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
303674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private int localVarTypeCount;
304674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
305674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
306674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The LocalVariableTypeTable attribute.
307674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
308674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private ByteVector localVarType;
309674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
310674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
311674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Number of entries in the LineNumberTable attribute.
312674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
313674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private int lineNumberCount;
314674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
315674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
316674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The LineNumberTable attribute.
317674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
318674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private ByteVector lineNumber;
319674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
320674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
321674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The non standard attributes of the method's code.
322674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
323674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private Attribute cattrs;
324674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
325674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
326674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Indicates if some jump instructions are too small and need to be resized.
327674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
328674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private boolean resize;
329674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
330674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
331674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The number of subroutines in this method.
332674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
333674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private int subroutines;
334674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
335674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // ------------------------------------------------------------------------
336674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
337674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /*
338674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Fields for the control flow graph analysis algorithm (used to compute the
339674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * maximum stack size). A control flow graph contains one node per "basic
340674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * block", and one edge per "jump" from one basic block to another. Each
341674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * node (i.e., each basic block) is represented by the Label object that
342674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * corresponds to the first instruction of this basic block. Each node also
343674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * stores the list of its successors in the graph, as a linked list of Edge
344674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * objects.
345674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
346674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
347674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
348674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Indicates what must be automatically computed.
349674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
350674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @see #FRAMES
351674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @see #MAXS
352674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @see #NOTHING
353674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
354674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private final int compute;
355674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
356674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
357674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * A list of labels. This list is the list of basic blocks in the method,
358674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * i.e. a list of Label objects linked to each other by their
359674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * {@link Label#successor} field, in the order they are visited by
360674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * {@link MethodVisitor#visitLabel}, and starting with the first basic block.
361674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
362674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private Label labels;
363674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
364674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
365674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The previous basic block.
366674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
367674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private Label previousBlock;
368674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
369674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
370674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The current basic block.
371674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
372674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private Label currentBlock;
373674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
374674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
375674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The (relative) stack size after the last visited instruction. This size
376674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * is relative to the beginning of the current basic block, i.e., the true
377674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * stack size after the last visited instruction is equal to the
378674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * {@link Label#inputStackTop beginStackSize} of the current basic block
379674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * plus <tt>stackSize</tt>.
380674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
381674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private int stackSize;
382674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
383674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
384674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * The (relative) maximum stack size after the last visited instruction.
385674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * This size is relative to the beginning of the current basic block, i.e.,
386674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * the true maximum stack size after the last visited instruction is equal
387674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * to the {@link Label#inputStackTop beginStackSize} of the current basic
388674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * block plus <tt>stackSize</tt>.
389674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
390674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private int maxStackSize;
391674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
392674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // ------------------------------------------------------------------------
393674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // Constructor
394674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // ------------------------------------------------------------------------
395674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
396674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
397674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Constructs a new {@link MethodWriter}.
398674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
399674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param cw the class writer in which the method must be added.
400674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param access the method's access flags (see {@link Opcodes}).
401674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param name the method's name.
402674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param desc the method's descriptor (see {@link Type}).
403674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param signature the method's signature. May be <tt>null</tt>.
404674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param exceptions the internal names of the method's exceptions. May be
405674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        <tt>null</tt>.
406674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param computeMaxs <tt>true</tt> if the maximum stack size and number
407674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        of local variables must be automatically computed.
408674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param computeFrames <tt>true</tt> if the stack map tables must be
409674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        recomputed from scratch.
410674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
411674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    MethodWriter(
412674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final ClassWriter cw,
413674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int access,
414674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String name,
415674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String desc,
416674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String signature,
417674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String[] exceptions,
418674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final boolean computeMaxs,
419674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final boolean computeFrames)
420674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
421674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (cw.firstMethod == null) {
422674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            cw.firstMethod = this;
423674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else {
424674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            cw.lastMethod.next = this;
425674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
426674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        cw.lastMethod = this;
427674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        this.cw = cw;
428674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        this.access = access;
429674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        this.name = cw.newUTF8(name);
430674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        this.desc = cw.newUTF8(desc);
431674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        this.descriptor = desc;
432674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.SIGNATURES) {
433674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            this.signature = signature;
434674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
435674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (exceptions != null && exceptions.length > 0) {
436674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            exceptionCount = exceptions.length;
437674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            this.exceptions = new int[exceptionCount];
438674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            for (int i = 0; i < exceptionCount; ++i) {
439674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                this.exceptions[i] = cw.newClass(exceptions[i]);
440674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
441674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
442674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING);
443674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (computeMaxs || computeFrames) {
444674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (computeFrames && "<init>".equals(name)) {
445674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                this.access |= ACC_CONSTRUCTOR;
446674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
447674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // updates maxLocals
448674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            int size = getArgumentsAndReturnSizes(descriptor) >> 2;
449674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if ((access & Opcodes.ACC_STATIC) != 0) {
450674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                --size;
451674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
452674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            maxLocals = size;
453674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // creates and visits the label for the first basic block
454674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            labels = new Label();
455674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            labels.status |= Label.PUSHED;
456674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            visitLabel(labels);
457674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
458674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
459674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
460674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // ------------------------------------------------------------------------
461674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // Implementation of the MethodVisitor interface
462674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // ------------------------------------------------------------------------
463674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
464674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public AnnotationVisitor visitAnnotationDefault() {
465674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (!ClassReader.ANNOTATIONS) {
466674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return null;
467674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
468674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        annd = new ByteVector();
469674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return new AnnotationWriter(cw, false, annd, null, 0);
470674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
471674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
472674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public AnnotationVisitor visitAnnotation(
473674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String desc,
474674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final boolean visible)
475674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
476674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (!ClassReader.ANNOTATIONS) {
477674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return null;
478674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
479674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        ByteVector bv = new ByteVector();
480674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // write type, and reserve space for values count
481674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        bv.putShort(cw.newUTF8(desc)).putShort(0);
482674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
483674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (visible) {
484674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            aw.next = anns;
485674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            anns = aw;
486674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else {
487674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            aw.next = ianns;
488674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ianns = aw;
489674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
490674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return aw;
491674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
492674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
493674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public AnnotationVisitor visitParameterAnnotation(
494674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int parameter,
495674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String desc,
496674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final boolean visible)
497674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
498674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (!ClassReader.ANNOTATIONS) {
499674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return null;
500674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
501674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        ByteVector bv = new ByteVector();
502674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if ("Ljava/lang/Synthetic;".equals(desc)) {
503674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // workaround for a bug in javac with synthetic parameters
504674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // see ClassReader.readParameterAnnotations
505674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            synthetics = Math.max(synthetics, parameter + 1);
506674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return new AnnotationWriter(cw, false, bv, null, 0);
507674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
508674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // write type, and reserve space for values count
509674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        bv.putShort(cw.newUTF8(desc)).putShort(0);
510674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
511674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (visible) {
512674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (panns == null) {
513674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                panns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length];
514674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
515674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            aw.next = panns[parameter];
516674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            panns[parameter] = aw;
517674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else {
518674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (ipanns == null) {
519674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                ipanns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length];
520674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
521674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            aw.next = ipanns[parameter];
522674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ipanns[parameter] = aw;
523674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
524674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return aw;
525674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
526674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
527674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitAttribute(final Attribute attr) {
528674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (attr.isCodeAttribute()) {
529674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            attr.next = cattrs;
530674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            cattrs = attr;
531674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else {
532674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            attr.next = attrs;
533674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            attrs = attr;
534674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
535674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
536674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
537674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitCode() {
538674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
539674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
540674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitFrame(
541674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int type,
542674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int nLocal,
543674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Object[] local,
544674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int nStack,
545674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Object[] stack)
546674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
547674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (!ClassReader.FRAMES || compute == FRAMES) {
548674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return;
549674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
550674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
551674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (type == Opcodes.F_NEW) {
552674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            startFrame(code.length, nLocal, nStack);
553674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            for (int i = 0; i < nLocal; ++i) {
554674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (local[i] instanceof String) {
555674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    frame[frameIndex++] = Frame.OBJECT
556674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            | cw.addType((String) local[i]);
557674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                } else if (local[i] instanceof Integer) {
558674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    frame[frameIndex++] = ((Integer) local[i]).intValue();
559674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                } else {
560674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    frame[frameIndex++] = Frame.UNINITIALIZED
561674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            | cw.addUninitializedType("",
562674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                    ((Label) local[i]).position);
563674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
564674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
565674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            for (int i = 0; i < nStack; ++i) {
566674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (stack[i] instanceof String) {
567674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    frame[frameIndex++] = Frame.OBJECT
568674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            | cw.addType((String) stack[i]);
569674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                } else if (stack[i] instanceof Integer) {
570674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    frame[frameIndex++] = ((Integer) stack[i]).intValue();
571674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                } else {
572674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    frame[frameIndex++] = Frame.UNINITIALIZED
573674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            | cw.addUninitializedType("",
574674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                    ((Label) stack[i]).position);
575674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
576674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
577674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            endFrame();
578674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else {
579674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            int delta;
580674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (stackMap == null) {
581674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stackMap = new ByteVector();
582674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                delta = code.length;
583674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
584674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                delta = code.length - previousFrameOffset - 1;
585674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
586674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
587674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            switch (type) {
588674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case Opcodes.F_FULL:
589674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    stackMap.putByte(FULL_FRAME)
590674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            .putShort(delta)
591674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            .putShort(nLocal);
592674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    for (int i = 0; i < nLocal; ++i) {
593674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        writeFrameType(local[i]);
594674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
595674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    stackMap.putShort(nStack);
596674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    for (int i = 0; i < nStack; ++i) {
597674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        writeFrameType(stack[i]);
598674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
599674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    break;
600674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case Opcodes.F_APPEND:
601674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    stackMap.putByte(SAME_FRAME_EXTENDED + nLocal)
602674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            .putShort(delta);
603674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    for (int i = 0; i < nLocal; ++i) {
604674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        writeFrameType(local[i]);
605674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
606674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    break;
607674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case Opcodes.F_CHOP:
608674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    stackMap.putByte(SAME_FRAME_EXTENDED - nLocal)
609674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            .putShort(delta);
610674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    break;
611674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case Opcodes.F_SAME:
612674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    if (delta < 64) {
613674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        stackMap.putByte(delta);
614674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    } else {
615674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
616674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
617674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    break;
618674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case Opcodes.F_SAME1:
619674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    if (delta < 64) {
620674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
621674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    } else {
622674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
623674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                .putShort(delta);
624674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
625674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    writeFrameType(stack[0]);
626674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    break;
627674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
628674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
629674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            previousFrameOffset = code.length;
630674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ++frameCount;
631674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
632674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
633674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
634674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitInsn(final int opcode) {
635674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // adds the instruction to the bytecode of the method
636674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        code.putByte(opcode);
637674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // update currentBlock
638674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // Label currentBlock = this.currentBlock;
639674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (currentBlock != null) {
640674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (compute == FRAMES) {
641674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                currentBlock.frame.execute(opcode, 0, null, null);
642674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
643674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // updates current and max stack sizes
644674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                int size = stackSize + Frame.SIZE[opcode];
645674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (size > maxStackSize) {
646674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    maxStackSize = size;
647674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
648674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stackSize = size;
649674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
650674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // if opcode == ATHROW or xRETURN, ends current block (no successor)
651674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
652674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    || opcode == Opcodes.ATHROW)
653674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            {
654674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                noSuccessor();
655674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
656674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
657674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
658674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
659674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitIntInsn(final int opcode, final int operand) {
660674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // Label currentBlock = this.currentBlock;
661674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (currentBlock != null) {
662674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (compute == FRAMES) {
663674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                currentBlock.frame.execute(opcode, operand, null, null);
664674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else if (opcode != Opcodes.NEWARRAY) {
665674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // updates current and max stack sizes only for NEWARRAY
666674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // (stack size variation = 0 for BIPUSH or SIPUSH)
667674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                int size = stackSize + 1;
668674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (size > maxStackSize) {
669674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    maxStackSize = size;
670674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
671674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stackSize = size;
672674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
673674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
674674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // adds the instruction to the bytecode of the method
675674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (opcode == Opcodes.SIPUSH) {
676674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            code.put12(opcode, operand);
677674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else { // BIPUSH or NEWARRAY
678674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            code.put11(opcode, operand);
679674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
680674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
681674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
682674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitVarInsn(final int opcode, final int var) {
683674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // Label currentBlock = this.currentBlock;
684674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (currentBlock != null) {
685674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (compute == FRAMES) {
686674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                currentBlock.frame.execute(opcode, var, null, null);
687674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
688674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // updates current and max stack sizes
689674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (opcode == Opcodes.RET) {
690674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // no stack change, but end of current block (no successor)
691674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    currentBlock.status |= Label.RET;
692674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // save 'stackSize' here for future use
693674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // (see {@link #findSubroutineSuccessors})
694674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    currentBlock.inputStackTop = stackSize;
695674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    noSuccessor();
696674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                } else { // xLOAD or xSTORE
697674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    int size = stackSize + Frame.SIZE[opcode];
698674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    if (size > maxStackSize) {
699674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        maxStackSize = size;
700674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
701674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    stackSize = size;
702674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
703674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
704674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
705674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (compute != NOTHING) {
706674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // updates max locals
707674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            int n;
708674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD
709674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE)
710674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            {
711674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                n = var + 2;
712674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
713674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                n = var + 1;
714674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
715674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (n > maxLocals) {
716674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                maxLocals = n;
717674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
718674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
719674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // adds the instruction to the bytecode of the method
720674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (var < 4 && opcode != Opcodes.RET) {
721674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            int opt;
722674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (opcode < Opcodes.ISTORE) {
723674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                /* ILOAD_0 */
724674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                opt = 26 + ((opcode - Opcodes.ILOAD) << 2) + var;
725674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
726674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                /* ISTORE_0 */
727674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                opt = 59 + ((opcode - Opcodes.ISTORE) << 2) + var;
728674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
729674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            code.putByte(opt);
730674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else if (var >= 256) {
731674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            code.putByte(196 /* WIDE */).put12(opcode, var);
732674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else {
733674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            code.put11(opcode, var);
734674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
735674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (opcode >= Opcodes.ISTORE && compute == FRAMES && handlerCount > 0) {
736674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            visitLabel(new Label());
737674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
738674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
739674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
740674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitTypeInsn(final int opcode, final String type) {
741674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        Item i = cw.newClassItem(type);
742674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // Label currentBlock = this.currentBlock;
743674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (currentBlock != null) {
744674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (compute == FRAMES) {
745674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                currentBlock.frame.execute(opcode, code.length, cw, i);
746674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else if (opcode == Opcodes.NEW) {
747674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // updates current and max stack sizes only if opcode == NEW
748674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // (no stack change for ANEWARRAY, CHECKCAST, INSTANCEOF)
749674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                int size = stackSize + 1;
750674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (size > maxStackSize) {
751674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    maxStackSize = size;
752674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
753674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stackSize = size;
754674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
755674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
756674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // adds the instruction to the bytecode of the method
757674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        code.put12(opcode, i.index);
758674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
759674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
760674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitFieldInsn(
761674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int opcode,
762674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String owner,
763674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String name,
764674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String desc)
765674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
766674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        Item i = cw.newFieldItem(owner, name, desc);
767674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // Label currentBlock = this.currentBlock;
768674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (currentBlock != null) {
769674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (compute == FRAMES) {
770674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                currentBlock.frame.execute(opcode, 0, cw, i);
771674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
772674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                int size;
773674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // computes the stack size variation
774674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                char c = desc.charAt(0);
775674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                switch (opcode) {
776674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case Opcodes.GETSTATIC:
777674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        size = stackSize + (c == 'D' || c == 'J' ? 2 : 1);
778674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        break;
779674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case Opcodes.PUTSTATIC:
780674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        size = stackSize + (c == 'D' || c == 'J' ? -2 : -1);
781674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        break;
782674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case Opcodes.GETFIELD:
783674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        size = stackSize + (c == 'D' || c == 'J' ? 1 : 0);
784674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        break;
785674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // case Constants.PUTFIELD:
786674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    default:
787674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        size = stackSize + (c == 'D' || c == 'J' ? -3 : -2);
788674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        break;
789674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
790674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // updates current and max stack sizes
791674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (size > maxStackSize) {
792674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    maxStackSize = size;
793674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
794674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stackSize = size;
795674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
796674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
797674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // adds the instruction to the bytecode of the method
798674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        code.put12(opcode, i.index);
799674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
800674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
801674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitMethodInsn(
802674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int opcode,
803674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String owner,
804674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String name,
805674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String desc)
806674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
807674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        boolean itf = opcode == Opcodes.INVOKEINTERFACE;
808674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        Item i = cw.newMethodItem(owner, name, desc, itf);
809674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int argSize = i.intVal;
810674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // Label currentBlock = this.currentBlock;
811674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (currentBlock != null) {
812674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (compute == FRAMES) {
813674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                currentBlock.frame.execute(opcode, 0, cw, i);
814674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
815674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                /*
816674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * computes the stack size variation. In order not to recompute
817674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * several times this variation for the same Item, we use the
818674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * intVal field of this item to store this variation, once it
819674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * has been computed. More precisely this intVal field stores
820674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * the sizes of the arguments and of the return value
821674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * corresponding to desc.
822674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 */
823674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (argSize == 0) {
824674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // the above sizes have not been computed yet,
825674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // so we compute them...
826674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    argSize = getArgumentsAndReturnSizes(desc);
827674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // ... and we save them in order
828674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // not to recompute them in the future
829674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    i.intVal = argSize;
830674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
831674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                int size;
832674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (opcode == Opcodes.INVOKESTATIC) {
833674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1;
834674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                } else {
835674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    size = stackSize - (argSize >> 2) + (argSize & 0x03);
836674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
837674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // updates current and max stack sizes
838674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (size > maxStackSize) {
839674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    maxStackSize = size;
840674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
841674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stackSize = size;
842674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
843674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
844674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // adds the instruction to the bytecode of the method
845674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (itf) {
846674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (argSize == 0) {
847674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                argSize = getArgumentsAndReturnSizes(desc);
848674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                i.intVal = argSize;
849674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
850674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0);
851674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else {
852674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            code.put12(opcode, i.index);
853674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
854674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
855674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
856674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitJumpInsn(final int opcode, final Label label) {
857674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        Label nextInsn = null;
858674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // Label currentBlock = this.currentBlock;
859674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (currentBlock != null) {
860674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (compute == FRAMES) {
861674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                currentBlock.frame.execute(opcode, 0, null, null);
862674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // 'label' is the target of a jump instruction
863674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                label.getFirst().status |= Label.TARGET;
864674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // adds 'label' as a successor of this basic block
865674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                addSuccessor(Edge.NORMAL, label);
866674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (opcode != Opcodes.GOTO) {
867674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // creates a Label for the next basic block
868674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    nextInsn = new Label();
869674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
870674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
871674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (opcode == Opcodes.JSR) {
872674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    if ((label.status & Label.SUBROUTINE) == 0) {
873674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        label.status |= Label.SUBROUTINE;
874674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        ++subroutines;
875674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
876674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    currentBlock.status |= Label.JSR;
877674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    addSuccessor(stackSize + 1, label);
878674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // creates a Label for the next basic block
879674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    nextInsn = new Label();
880674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    /*
881674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                     * note that, by construction in this method, a JSR block
882674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                     * has at least two successors in the control flow graph:
883674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                     * the first one leads the next instruction after the JSR,
884674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                     * while the second one leads to the JSR target.
885674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                     */
886674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                } else {
887674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // updates current stack size (max stack size unchanged
888674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // because stack size variation always negative in this
889674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // case)
890674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    stackSize += Frame.SIZE[opcode];
891674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    addSuccessor(stackSize, label);
892674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
893674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
894674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
895674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // adds the instruction to the bytecode of the method
896674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if ((label.status & Label.RESOLVED) != 0
897674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                && label.position - code.length < Short.MIN_VALUE)
898674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        {
899674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            /*
900674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * case of a backward jump with an offset < -32768. In this case we
901674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx
902674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the
903674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <l'>
904674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * designates the instruction just after the GOTO_W.
905674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             */
906674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (opcode == Opcodes.GOTO) {
907674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                code.putByte(200); // GOTO_W
908674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else if (opcode == Opcodes.JSR) {
909674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                code.putByte(201); // JSR_W
910674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
911674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // if the IF instruction is transformed into IFNOT GOTO_W the
912674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // next instruction becomes the target of the IFNOT instruction
913674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (nextInsn != null) {
914674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    nextInsn.status |= Label.TARGET;
915674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
916674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                code.putByte(opcode <= 166
917674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        ? ((opcode + 1) ^ 1) - 1
918674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        : opcode ^ 1);
919674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                code.putShort(8); // jump offset
920674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                code.putByte(200); // GOTO_W
921674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
922674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            label.put(this, code, code.length - 1, true);
923674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else {
924674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            /*
925674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * case of a backward jump with an offset >= -32768, or of a forward
926674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * jump with, of course, an unknown offset. In these cases we store
927674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * the offset in 2 bytes (which will be increased in
928674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * resizeInstructions, if needed).
929674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             */
930674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            code.putByte(opcode);
931674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            label.put(this, code, code.length - 1, false);
932674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
933674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (currentBlock != null) {
934674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (nextInsn != null) {
935674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // if the jump instruction is not a GOTO, the next instruction
936674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // is also a successor of this instruction. Calling visitLabel
937674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // adds the label of this next instruction as a successor of the
938674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // current block, and starts a new basic block
939674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                visitLabel(nextInsn);
940674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
941674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (opcode == Opcodes.GOTO) {
942674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                noSuccessor();
943674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
944674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
945674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
946674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
947674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitLabel(final Label label) {
948674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // resolves previous forward references to label, if any
949674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        resize |= label.resolve(this, code.length, code.data);
950674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // updates currentBlock
951674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if ((label.status & Label.DEBUG) != 0) {
952674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return;
953674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
954674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (compute == FRAMES) {
955674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (currentBlock != null) {
956674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (label.position == currentBlock.position) {
957674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // successive labels, do not start a new basic block
958674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    currentBlock.status |= (label.status & Label.TARGET);
959674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    label.frame = currentBlock.frame;
960674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    return;
961674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
962674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // ends current block (with one new successor)
963674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                addSuccessor(Edge.NORMAL, label);
964674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
965674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // begins a new current block
966674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            currentBlock = label;
967674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (label.frame == null) {
968674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                label.frame = new Frame();
969674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                label.frame.owner = label;
970674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
971674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // updates the basic block list
972674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (previousBlock != null) {
973674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (label.position == previousBlock.position) {
974674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    previousBlock.status |= (label.status & Label.TARGET);
975674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    label.frame = previousBlock.frame;
976674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    currentBlock = previousBlock;
977674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    return;
978674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
979674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                previousBlock.successor = label;
980674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
981674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            previousBlock = label;
982674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else if (compute == MAXS) {
983674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (currentBlock != null) {
984674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // ends current block (with one new successor)
985674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                currentBlock.outputStackMax = maxStackSize;
986674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                addSuccessor(stackSize, label);
987674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
988674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // begins a new current block
989674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            currentBlock = label;
990674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // resets the relative current and max stack sizes
991674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            stackSize = 0;
992674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            maxStackSize = 0;
993674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // updates the basic block list
994674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (previousBlock != null) {
995674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                previousBlock.successor = label;
996674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
997674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            previousBlock = label;
998674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
999674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1000674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1001674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitLdcInsn(final Object cst) {
1002674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        Item i = cw.newConstItem(cst);
1003674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // Label currentBlock = this.currentBlock;
1004674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (currentBlock != null) {
1005674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (compute == FRAMES) {
1006674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                currentBlock.frame.execute(Opcodes.LDC, 0, cw, i);
1007674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
1008674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                int size;
1009674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // computes the stack size variation
1010674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE)
1011674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                {
1012674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    size = stackSize + 2;
1013674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                } else {
1014674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    size = stackSize + 1;
1015674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1016674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // updates current and max stack sizes
1017674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (size > maxStackSize) {
1018674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    maxStackSize = size;
1019674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1020674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stackSize = size;
1021674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1022674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1023674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // adds the instruction to the bytecode of the method
1024674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int index = i.index;
1025674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {
1026674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            code.put12(20 /* LDC2_W */, index);
1027674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else if (index >= 256) {
1028674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            code.put12(19 /* LDC_W */, index);
1029674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else {
1030674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            code.put11(Opcodes.LDC, index);
1031674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1032674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1033674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1034674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitIincInsn(final int var, final int increment) {
1035674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (currentBlock != null) {
1036674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (compute == FRAMES) {
1037674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                currentBlock.frame.execute(Opcodes.IINC, var, null, null);
1038674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1039674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1040674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (compute != NOTHING) {
1041674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // updates max locals
1042674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            int n = var + 1;
1043674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (n > maxLocals) {
1044674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                maxLocals = n;
1045674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1046674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1047674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // adds the instruction to the bytecode of the method
1048674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if ((var > 255) || (increment > 127) || (increment < -128)) {
1049674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            code.putByte(196 /* WIDE */)
1050674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    .put12(Opcodes.IINC, var)
1051674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    .putShort(increment);
1052674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else {
1053674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            code.putByte(Opcodes.IINC).put11(var, increment);
1054674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1055674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1056674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1057674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitTableSwitchInsn(
1058674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int min,
1059674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int max,
1060674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label dflt,
1061674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label[] labels)
1062674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
1063674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // adds the instruction to the bytecode of the method
1064674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int source = code.length;
1065674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        code.putByte(Opcodes.TABLESWITCH);
1066674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        code.length += (4 - code.length % 4) % 4;
1067674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        dflt.put(this, code, source, true);
1068674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        code.putInt(min).putInt(max);
1069674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        for (int i = 0; i < labels.length; ++i) {
1070674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            labels[i].put(this, code, source, true);
1071674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1072674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // updates currentBlock
1073674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        visitSwitchInsn(dflt, labels);
1074674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1075674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1076674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitLookupSwitchInsn(
1077674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label dflt,
1078674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int[] keys,
1079674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label[] labels)
1080674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
1081674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // adds the instruction to the bytecode of the method
1082674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int source = code.length;
1083674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        code.putByte(Opcodes.LOOKUPSWITCH);
1084674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        code.length += (4 - code.length % 4) % 4;
1085674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        dflt.put(this, code, source, true);
1086674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        code.putInt(labels.length);
1087674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        for (int i = 0; i < labels.length; ++i) {
1088674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            code.putInt(keys[i]);
1089674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            labels[i].put(this, code, source, true);
1090674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1091674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // updates currentBlock
1092674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        visitSwitchInsn(dflt, labels);
1093674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1094674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1095674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private void visitSwitchInsn(final Label dflt, final Label[] labels) {
1096674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // Label currentBlock = this.currentBlock;
1097674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (currentBlock != null) {
1098674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (compute == FRAMES) {
1099674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                currentBlock.frame.execute(Opcodes.LOOKUPSWITCH, 0, null, null);
1100674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // adds current block successors
1101674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                addSuccessor(Edge.NORMAL, dflt);
1102674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                dflt.getFirst().status |= Label.TARGET;
1103674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                for (int i = 0; i < labels.length; ++i) {
1104674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    addSuccessor(Edge.NORMAL, labels[i]);
1105674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    labels[i].getFirst().status |= Label.TARGET;
1106674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1107674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
1108674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // updates current stack size (max stack size unchanged)
1109674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                --stackSize;
1110674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // adds current block successors
1111674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                addSuccessor(stackSize, dflt);
1112674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                for (int i = 0; i < labels.length; ++i) {
1113674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    addSuccessor(stackSize, labels[i]);
1114674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1115674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1116674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // ends current block
1117674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            noSuccessor();
1118674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1119674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1120674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1121674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitMultiANewArrayInsn(final String desc, final int dims) {
1122674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        Item i = cw.newClassItem(desc);
1123674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // Label currentBlock = this.currentBlock;
1124674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (currentBlock != null) {
1125674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (compute == FRAMES) {
1126674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                currentBlock.frame.execute(Opcodes.MULTIANEWARRAY, dims, cw, i);
1127674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
1128674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // updates current stack size (max stack size unchanged because
1129674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // stack size variation always negative or null)
1130674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stackSize += 1 - dims;
1131674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1132674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1133674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // adds the instruction to the bytecode of the method
1134674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        code.put12(Opcodes.MULTIANEWARRAY, i.index).putByte(dims);
1135674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1136674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1137674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitTryCatchBlock(
1138674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label start,
1139674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label end,
1140674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label handler,
1141674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String type)
1142674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
1143674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        ++handlerCount;
1144674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        Handler h = new Handler();
1145674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        h.start = start;
1146674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        h.end = end;
1147674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        h.handler = handler;
1148674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        h.desc = type;
1149674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        h.type = type != null ? cw.newClass(type) : 0;
1150674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (lastHandler == null) {
1151674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            firstHandler = h;
1152674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else {
1153674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            lastHandler.next = h;
1154674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1155674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        lastHandler = h;
1156674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1157674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1158674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitLocalVariable(
1159674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String name,
1160674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String desc,
1161674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final String signature,
1162674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label start,
1163674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label end,
1164674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int index)
1165674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
1166674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (signature != null) {
1167674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (localVarType == null) {
1168674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                localVarType = new ByteVector();
1169674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1170674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ++localVarTypeCount;
1171674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            localVarType.putShort(start.position)
1172674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    .putShort(end.position - start.position)
1173674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    .putShort(cw.newUTF8(name))
1174674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    .putShort(cw.newUTF8(signature))
1175674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    .putShort(index);
1176674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1177674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (localVar == null) {
1178674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            localVar = new ByteVector();
1179674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1180674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        ++localVarCount;
1181674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        localVar.putShort(start.position)
1182674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                .putShort(end.position - start.position)
1183674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                .putShort(cw.newUTF8(name))
1184674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                .putShort(cw.newUTF8(desc))
1185674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                .putShort(index);
1186674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (compute != NOTHING) {
1187674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // updates max locals
1188674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            char c = desc.charAt(0);
1189674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            int n = index + (c == 'J' || c == 'D' ? 2 : 1);
1190674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (n > maxLocals) {
1191674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                maxLocals = n;
1192674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1193674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1194674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1195674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1196674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitLineNumber(final int line, final Label start) {
1197674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (lineNumber == null) {
1198674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            lineNumber = new ByteVector();
1199674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1200674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        ++lineNumberCount;
1201674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        lineNumber.putShort(start.position);
1202674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        lineNumber.putShort(line);
1203674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1204674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1205674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitMaxs(final int maxStack, final int maxLocals) {
1206674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.FRAMES && compute == FRAMES) {
1207674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // completes the control flow graph with exception handler blocks
1208674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            Handler handler = firstHandler;
1209674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            while (handler != null) {
1210674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                Label l = handler.start.getFirst();
1211674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                Label h = handler.handler.getFirst();
1212674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                Label e = handler.end.getFirst();
1213674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // computes the kind of the edges to 'h'
1214674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                String t = handler.desc == null
1215674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        ? "java/lang/Throwable"
1216674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        : handler.desc;
1217674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                int kind = Frame.OBJECT | cw.addType(t);
1218674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // h is an exception handler
1219674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                h.status |= Label.TARGET;
1220674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // adds 'h' as a successor of labels between 'start' and 'end'
1221674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                while (l != e) {
1222674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // creates an edge to 'h'
1223674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    Edge b = new Edge();
1224674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    b.info = kind;
1225674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    b.successor = h;
1226674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // adds it to the successors of 'l'
1227674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    b.next = l.successors;
1228674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    l.successors = b;
1229674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // goes to the next label
1230674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    l = l.successor;
1231674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1232674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                handler = handler.next;
1233674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1234674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1235674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // creates and visits the first (implicit) frame
1236674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            Frame f = labels.frame;
1237674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            Type[] args = Type.getArgumentTypes(descriptor);
1238674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            f.initInputFrame(cw, access, args, this.maxLocals);
1239674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            visitFrame(f);
1240674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1241674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            /*
1242674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * fix point algorithm: mark the first basic block as 'changed'
1243674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * (i.e. put it in the 'changed' list) and, while there are changed
1244674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * basic blocks, choose one, mark it as unchanged, and update its
1245674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * successors (which can be changed in the process).
1246674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             */
1247674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            int max = 0;
1248674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            Label changed = labels;
1249674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            while (changed != null) {
1250674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // removes a basic block from the list of changed basic blocks
1251674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                Label l = changed;
1252674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                changed = changed.next;
1253674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                l.next = null;
1254674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                f = l.frame;
1255674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // a reacheable jump target must be stored in the stack map
1256674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if ((l.status & Label.TARGET) != 0) {
1257674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    l.status |= Label.STORE;
1258674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1259674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // all visited labels are reacheable, by definition
1260674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                l.status |= Label.REACHABLE;
1261674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // updates the (absolute) maximum stack size
1262674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                int blockMax = f.inputStack.length + l.outputStackMax;
1263674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (blockMax > max) {
1264674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    max = blockMax;
1265674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1266674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // updates the successors of the current basic block
1267674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                Edge e = l.successors;
1268674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                while (e != null) {
1269674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    Label n = e.successor.getFirst();
1270674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    boolean change = f.merge(cw, n.frame, e.info);
1271674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    if (change && n.next == null) {
1272674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // if n has changed and is not already in the 'changed'
1273674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // list, adds it to this list
1274674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        n.next = changed;
1275674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        changed = n;
1276674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
1277674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    e = e.next;
1278674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1279674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1280674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            this.maxStack = max;
1281674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1282674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // visits all the frames that must be stored in the stack map
1283674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            Label l = labels;
1284674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            while (l != null) {
1285674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                f = l.frame;
1286674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if ((l.status & Label.STORE) != 0) {
1287674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    visitFrame(f);
1288674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1289674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if ((l.status & Label.REACHABLE) == 0) {
1290674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // finds start and end of dead basic block
1291674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    Label k = l.successor;
1292674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    int start = l.position;
1293674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    int end = (k == null ? code.length : k.position) - 1;
1294674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // if non empty basic block
1295674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    if (end >= start) {
1296674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // replaces instructions with NOP ... NOP ATHROW
1297674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        for (int i = start; i < end; ++i) {
1298674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            code.data[i] = Opcodes.NOP;
1299674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        }
1300674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        code.data[end] = (byte) Opcodes.ATHROW;
1301674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // emits a frame for this unreachable block
1302674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        startFrame(start, 0, 1);
1303674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        frame[frameIndex++] = Frame.OBJECT
1304674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                | cw.addType("java/lang/Throwable");
1305674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        endFrame();
1306674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
1307674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1308674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                l = l.successor;
1309674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1310674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else if (compute == MAXS) {
1311674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // completes the control flow graph with exception handler blocks
1312674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            Handler handler = firstHandler;
1313674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            while (handler != null) {
1314674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                Label l = handler.start;
1315674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                Label h = handler.handler;
1316674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                Label e = handler.end;
1317674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // adds 'h' as a successor of labels between 'start' and 'end'
1318674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                while (l != e) {
1319674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // creates an edge to 'h'
1320674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    Edge b = new Edge();
1321674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    b.info = Edge.EXCEPTION;
1322674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    b.successor = h;
1323674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // adds it to the successors of 'l'
1324674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    if ((l.status & Label.JSR) == 0) {
1325674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        b.next = l.successors;
1326674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        l.successors = b;
1327674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    } else {
1328674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // if l is a JSR block, adds b after the first two edges
1329674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // to preserve the hypothesis about JSR block successors
1330674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // order (see {@link #visitJumpInsn})
1331674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        b.next = l.successors.next.next;
1332674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        l.successors.next.next = b;
1333674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
1334674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // goes to the next label
1335674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    l = l.successor;
1336674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1337674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                handler = handler.next;
1338674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1339674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1340674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (subroutines > 0) {
1341674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // completes the control flow graph with the RET successors
1342674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                /*
1343674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * first step: finds the subroutines. This step determines, for
1344674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * each basic block, to which subroutine(s) it belongs.
1345674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 */
1346674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // finds the basic blocks that belong to the "main" subroutine
1347674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                int id = 0;
1348674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                labels.visitSubroutine(null, 1, subroutines);
1349674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // finds the basic blocks that belong to the real subroutines
1350674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                Label l = labels;
1351674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                while (l != null) {
1352674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    if ((l.status & Label.JSR) != 0) {
1353674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // the subroutine is defined by l's TARGET, not by l
1354674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        Label subroutine = l.successors.next.successor;
1355674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // if this subroutine has not been visited yet...
1356674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        if ((subroutine.status & Label.VISITED) == 0) {
1357674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            // ...assigns it a new id and finds its basic blocks
1358674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            id += 1;
1359674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            subroutine.visitSubroutine(null, (id / 32L) << 32
1360674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                    | (1L << (id % 32)), subroutines);
1361674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        }
1362674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
1363674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    l = l.successor;
1364674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1365674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // second step: finds the successors of RET blocks
1366674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                l = labels;
1367674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                while (l != null) {
1368674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    if ((l.status & Label.JSR) != 0) {
1369674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        Label L = labels;
1370674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        while (L != null) {
1371674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            L.status &= ~Label.VISITED;
1372674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            L = L.successor;
1373674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        }
1374674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // the subroutine is defined by l's TARGET, not by l
1375674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        Label subroutine = l.successors.next.successor;
1376674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        subroutine.visitSubroutine(l, 0, subroutines);
1377674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
1378674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    l = l.successor;
1379674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1380674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1381674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1382674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            /*
1383674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * control flow analysis algorithm: while the block stack is not
1384674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * empty, pop a block from this stack, update the max stack size,
1385674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * compute the true (non relative) begin stack size of the
1386674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * successors of this block, and push these successors onto the
1387674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * stack (unless they have already been pushed onto the stack).
1388674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * Note: by hypothesis, the {@link Label#inputStackTop} of the
1389674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * blocks in the block stack are the true (non relative) beginning
1390674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             * stack sizes of these blocks.
1391674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             */
1392674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            int max = 0;
1393674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            Label stack = labels;
1394674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            while (stack != null) {
1395674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // pops a block from the stack
1396674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                Label l = stack;
1397674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stack = stack.next;
1398674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // computes the true (non relative) max stack size of this block
1399674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                int start = l.inputStackTop;
1400674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                int blockMax = start + l.outputStackMax;
1401674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // updates the global max stack size
1402674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (blockMax > max) {
1403674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    max = blockMax;
1404674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1405674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // analyzes the successors of the block
1406674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                Edge b = l.successors;
1407674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if ((l.status & Label.JSR) != 0) {
1408674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // ignores the first edge of JSR blocks (virtual successor)
1409674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    b = b.next;
1410674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1411674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                while (b != null) {
1412674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    l = b.successor;
1413674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // if this successor has not already been pushed...
1414674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    if ((l.status & Label.PUSHED) == 0) {
1415674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // computes its true beginning stack size...
1416674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        l.inputStackTop = b.info == Edge.EXCEPTION ? 1 : start
1417674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                + b.info;
1418674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // ...and pushes it onto the stack
1419674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        l.status |= Label.PUSHED;
1420674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        l.next = stack;
1421674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        stack = l;
1422674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
1423674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    b = b.next;
1424674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1425674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1426674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            this.maxStack = max;
1427674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else {
1428674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            this.maxStack = maxStack;
1429674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            this.maxLocals = maxLocals;
1430674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1431674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1432674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1433674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitEnd() {
1434674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1435674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1436674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // ------------------------------------------------------------------------
1437674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // Utility methods: control flow analysis algorithm
1438674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // ------------------------------------------------------------------------
1439674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1440674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1441674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Computes the size of the arguments and of the return value of a method.
1442674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1443674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param desc the descriptor of a method.
1444674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @return the size of the arguments of the method (plus one for the
1445674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *         implicit this argument), argSize, and the size of its return
1446674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *         value, retSize, packed into a single int i =
1447674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *         <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal
1448674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *         to <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>).
1449674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1450674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static int getArgumentsAndReturnSizes(final String desc) {
1451674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int n = 1;
1452674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int c = 1;
1453674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        while (true) {
1454674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            char car = desc.charAt(c++);
1455674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (car == ')') {
1456674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                car = desc.charAt(c);
1457674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                return n << 2
1458674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1));
1459674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else if (car == 'L') {
1460674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                while (desc.charAt(c++) != ';') {
1461674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1462674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                n += 1;
1463674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else if (car == '[') {
1464674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                while ((car = desc.charAt(c)) == '[') {
1465674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    ++c;
1466674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1467674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (car == 'D' || car == 'J') {
1468674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    n -= 1;
1469674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1470674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else if (car == 'D' || car == 'J') {
1471674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                n += 2;
1472674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
1473674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                n += 1;
1474674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1475674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1476674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1477674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1478674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1479674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Adds a successor to the {@link #currentBlock currentBlock} block.
1480674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1481674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param info information about the control flow edge to be added.
1482674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param successor the successor block to be added to the current block.
1483674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1484674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private void addSuccessor(final int info, final Label successor) {
1485674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // creates and initializes an Edge object...
1486674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        Edge b = new Edge();
1487674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        b.info = info;
1488674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        b.successor = successor;
1489674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // ...and adds it to the successor list of the currentBlock block
1490674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        b.next = currentBlock.successors;
1491674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        currentBlock.successors = b;
1492674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1493674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1494674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1495674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Ends the current basic block. This method must be used in the case where
1496674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * the current basic block does not have any successor.
1497674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1498674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private void noSuccessor() {
1499674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (compute == FRAMES) {
1500674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            Label l = new Label();
1501674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            l.frame = new Frame();
1502674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            l.frame.owner = l;
1503674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            l.resolve(this, code.length, code.data);
1504674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            previousBlock.successor = l;
1505674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            previousBlock = l;
1506674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else {
1507674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            currentBlock.outputStackMax = maxStackSize;
1508674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1509674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        currentBlock = null;
1510674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1511674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1512674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // ------------------------------------------------------------------------
1513674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // Utility methods: stack map frames
1514674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // ------------------------------------------------------------------------
1515674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1516674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1517674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Visits a frame that has been computed from scratch.
1518674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1519674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param f the frame that must be visited.
1520674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1521674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private void visitFrame(final Frame f) {
1522674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int i, t;
1523674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int nTop = 0;
1524674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int nLocal = 0;
1525674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int nStack = 0;
1526674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int[] locals = f.inputLocals;
1527674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int[] stacks = f.inputStack;
1528674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // computes the number of locals (ignores TOP types that are just after
1529674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // a LONG or a DOUBLE, and all trailing TOP types)
1530674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        for (i = 0; i < locals.length; ++i) {
1531674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            t = locals[i];
1532674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (t == Frame.TOP) {
1533674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                ++nTop;
1534674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
1535674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                nLocal += nTop + 1;
1536674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                nTop = 0;
1537674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1538674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (t == Frame.LONG || t == Frame.DOUBLE) {
1539674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                ++i;
1540674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1541674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1542674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // computes the stack size (ignores TOP types that are just after
1543674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // a LONG or a DOUBLE)
1544674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        for (i = 0; i < stacks.length; ++i) {
1545674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            t = stacks[i];
1546674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ++nStack;
1547674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (t == Frame.LONG || t == Frame.DOUBLE) {
1548674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                ++i;
1549674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1550674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1551674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // visits the frame and its content
1552674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        startFrame(f.owner.position, nLocal, nStack);
1553674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        for (i = 0; nLocal > 0; ++i, --nLocal) {
1554674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            t = locals[i];
1555674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            frame[frameIndex++] = t;
1556674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (t == Frame.LONG || t == Frame.DOUBLE) {
1557674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                ++i;
1558674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1559674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1560674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        for (i = 0; i < stacks.length; ++i) {
1561674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            t = stacks[i];
1562674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            frame[frameIndex++] = t;
1563674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (t == Frame.LONG || t == Frame.DOUBLE) {
1564674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                ++i;
1565674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1566674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1567674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        endFrame();
1568674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1569674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1570674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1571674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Starts the visit of a stack map frame.
1572674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1573674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param offset the offset of the instruction to which the frame
1574674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        corresponds.
1575674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param nLocal the number of local variables in the frame.
1576674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param nStack the number of stack elements in the frame.
1577674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1578674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private void startFrame(final int offset, final int nLocal, final int nStack)
1579674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
1580674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int n = 3 + nLocal + nStack;
1581674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (frame == null || frame.length < n) {
1582674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            frame = new int[n];
1583674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1584674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        frame[0] = offset;
1585674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        frame[1] = nLocal;
1586674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        frame[2] = nStack;
1587674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        frameIndex = 3;
1588674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1589674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1590674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1591674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Checks if the visit of the current frame {@link #frame} is finished, and
1592674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * if yes, write it in the StackMapTable attribute.
1593674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1594674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private void endFrame() {
1595674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (previousFrame != null) { // do not write the first frame
1596674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (stackMap == null) {
1597674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stackMap = new ByteVector();
1598674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1599674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            writeFrame();
1600674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ++frameCount;
1601674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1602674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        previousFrame = frame;
1603674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        frame = null;
1604674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1605674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1606674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1607674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Compress and writes the current frame {@link #frame} in the StackMapTable
1608674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * attribute.
1609674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1610674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private void writeFrame() {
1611674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int clocalsSize = frame[1];
1612674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int cstackSize = frame[2];
1613674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if ((cw.version & 0xFFFF) < Opcodes.V1_6) {
1614674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            stackMap.putShort(frame[0]).putShort(clocalsSize);
1615674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            writeFrameTypes(3, 3 + clocalsSize);
1616674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            stackMap.putShort(cstackSize);
1617674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);
1618674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return;
1619674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1620674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int localsSize = previousFrame[1];
1621674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int type = FULL_FRAME;
1622674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int k = 0;
1623674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int delta;
1624674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (frameCount == 0) {
1625674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            delta = frame[0];
1626674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else {
1627674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            delta = frame[0] - previousFrame[0] - 1;
1628674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1629674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (cstackSize == 0) {
1630674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            k = clocalsSize - localsSize;
1631674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            switch (k) {
1632674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case -3:
1633674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case -2:
1634674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case -1:
1635674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    type = CHOP_FRAME;
1636674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    localsSize = clocalsSize;
1637674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    break;
1638674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case 0:
1639674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED;
1640674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    break;
1641674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case 1:
1642674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case 2:
1643674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case 3:
1644674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    type = APPEND_FRAME;
1645674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    break;
1646674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1647674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else if (clocalsSize == localsSize && cstackSize == 1) {
1648674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            type = delta < 63
1649674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    ? SAME_LOCALS_1_STACK_ITEM_FRAME
1650674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    : SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;
1651674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1652674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (type != FULL_FRAME) {
1653674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // verify if locals are the same
1654674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            int l = 3;
1655674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            for (int j = 0; j < localsSize; j++) {
1656674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (frame[l] != previousFrame[l]) {
1657674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    type = FULL_FRAME;
1658674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    break;
1659674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1660674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                l++;
1661674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1662674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1663674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        switch (type) {
1664674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case SAME_FRAME:
1665674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stackMap.putByte(delta);
1666674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                break;
1667674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case SAME_LOCALS_1_STACK_ITEM_FRAME:
1668674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
1669674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
1670674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                break;
1671674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:
1672674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
1673674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        .putShort(delta);
1674674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
1675674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                break;
1676674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case SAME_FRAME_EXTENDED:
1677674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
1678674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                break;
1679674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case CHOP_FRAME:
1680674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
1681674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                break;
1682674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            case APPEND_FRAME:
1683674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
1684674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                writeFrameTypes(3 + localsSize, 3 + clocalsSize);
1685674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                break;
1686674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // case FULL_FRAME:
1687674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            default:
1688674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stackMap.putByte(FULL_FRAME)
1689674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        .putShort(delta)
1690674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        .putShort(clocalsSize);
1691674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                writeFrameTypes(3, 3 + clocalsSize);
1692674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stackMap.putShort(cstackSize);
1693674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);
1694674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1695674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1696674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1697674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1698674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Writes some types of the current frame {@link #frame} into the
1699674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * StackMapTableAttribute. This method converts types from the format used
1700674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * in {@link Label} to the format used in StackMapTable attributes. In
1701674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * particular, it converts type table indexes to constant pool indexes.
1702674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1703674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param start index of the first type in {@link #frame} to write.
1704674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param end index of last type in {@link #frame} to write (exclusive).
1705674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1706674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private void writeFrameTypes(final int start, final int end) {
1707674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        for (int i = start; i < end; ++i) {
1708674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            int t = frame[i];
1709674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            int d = t & Frame.DIM;
1710674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (d == 0) {
1711674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                int v = t & Frame.BASE_VALUE;
1712674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                switch (t & Frame.BASE_KIND) {
1713674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case Frame.OBJECT:
1714674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        stackMap.putByte(7)
1715674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                .putShort(cw.newClass(cw.typeTable[v].strVal1));
1716674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        break;
1717674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case Frame.UNINITIALIZED:
1718674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        stackMap.putByte(8).putShort(cw.typeTable[v].intVal);
1719674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        break;
1720674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    default:
1721674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        stackMap.putByte(v);
1722674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1723674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
1724674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                StringBuffer buf = new StringBuffer();
1725674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                d >>= 28;
1726674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                while (d-- > 0) {
1727674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    buf.append('[');
1728674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1729674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if ((t & Frame.BASE_KIND) == Frame.OBJECT) {
1730674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    buf.append('L');
1731674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    buf.append(cw.typeTable[t & Frame.BASE_VALUE].strVal1);
1732674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    buf.append(';');
1733674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                } else {
1734674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    switch (t & 0xF) {
1735674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        case 1:
1736674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            buf.append('I');
1737674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            break;
1738674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        case 2:
1739674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            buf.append('F');
1740674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            break;
1741674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        case 3:
1742674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            buf.append('D');
1743674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            break;
1744674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        case 9:
1745674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            buf.append('Z');
1746674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            break;
1747674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        case 10:
1748674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            buf.append('B');
1749674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            break;
1750674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        case 11:
1751674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            buf.append('C');
1752674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            break;
1753674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        case 12:
1754674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            buf.append('S');
1755674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            break;
1756674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        default:
1757674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            buf.append('J');
1758674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
1759674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1760674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stackMap.putByte(7).putShort(cw.newClass(buf.toString()));
1761674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1762674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1763674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1764674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1765674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private void writeFrameType(final Object type) {
1766674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (type instanceof String) {
1767674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            stackMap.putByte(7).putShort(cw.newClass((String) type));
1768674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else if (type instanceof Integer) {
1769674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            stackMap.putByte(((Integer) type).intValue());
1770674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else {
1771674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            stackMap.putByte(8).putShort(((Label) type).position);
1772674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1773674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1774674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1775674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // ------------------------------------------------------------------------
1776674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // Utility methods: dump bytecode array
1777674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // ------------------------------------------------------------------------
1778674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1779674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1780674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Returns the size of the bytecode of this method.
1781674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1782674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @return the size of the bytecode of this method.
1783674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1784674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    final int getSize() {
1785674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (classReaderOffset != 0) {
1786674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return 6 + classReaderLength;
1787674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1788674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (resize) {
1789674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // replaces the temporary jump opcodes introduced by Label.resolve.
1790674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (ClassReader.RESIZE) {
1791674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                resizeInstructions();
1792674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
1793674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                throw new RuntimeException("Method code too large!");
1794674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1795674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1796674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int size = 8;
1797674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (code.length > 0) {
1798674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            cw.newUTF8("Code");
1799674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            size += 18 + code.length + 8 * handlerCount;
1800674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (localVar != null) {
1801674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                cw.newUTF8("LocalVariableTable");
1802674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                size += 8 + localVar.length;
1803674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1804674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (localVarType != null) {
1805674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                cw.newUTF8("LocalVariableTypeTable");
1806674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                size += 8 + localVarType.length;
1807674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1808674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (lineNumber != null) {
1809674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                cw.newUTF8("LineNumberTable");
1810674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                size += 8 + lineNumber.length;
1811674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1812674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (stackMap != null) {
1813674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6;
1814674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                cw.newUTF8(zip ? "StackMapTable" : "StackMap");
1815674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                size += 8 + stackMap.length;
1816674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1817674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (cattrs != null) {
1818674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                size += cattrs.getSize(cw,
1819674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        code.data,
1820674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        code.length,
1821674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        maxStack,
1822674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        maxLocals);
1823674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1824674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1825674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (exceptionCount > 0) {
1826674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            cw.newUTF8("Exceptions");
1827674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            size += 8 + 2 * exceptionCount;
1828674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1829674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if ((access & Opcodes.ACC_SYNTHETIC) != 0
1830674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                && (cw.version & 0xffff) < Opcodes.V1_5)
1831674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        {
1832674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            cw.newUTF8("Synthetic");
1833674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            size += 6;
1834674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1835674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
1836674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            cw.newUTF8("Deprecated");
1837674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            size += 6;
1838674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1839674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.SIGNATURES && signature != null) {
1840674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            cw.newUTF8("Signature");
1841674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            cw.newUTF8(signature);
1842674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            size += 8;
1843674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1844674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.ANNOTATIONS && annd != null) {
1845674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            cw.newUTF8("AnnotationDefault");
1846674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            size += 6 + annd.length;
1847674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1848674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.ANNOTATIONS && anns != null) {
1849674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            cw.newUTF8("RuntimeVisibleAnnotations");
1850674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            size += 8 + anns.getSize();
1851674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1852674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.ANNOTATIONS && ianns != null) {
1853674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            cw.newUTF8("RuntimeInvisibleAnnotations");
1854674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            size += 8 + ianns.getSize();
1855674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1856674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.ANNOTATIONS && panns != null) {
1857674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            cw.newUTF8("RuntimeVisibleParameterAnnotations");
1858674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            size += 7 + 2 * (panns.length - synthetics);
1859674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            for (int i = panns.length - 1; i >= synthetics; --i) {
1860674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                size += panns[i] == null ? 0 : panns[i].getSize();
1861674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1862674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1863674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.ANNOTATIONS && ipanns != null) {
1864674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            cw.newUTF8("RuntimeInvisibleParameterAnnotations");
1865674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            size += 7 + 2 * (ipanns.length - synthetics);
1866674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            for (int i = ipanns.length - 1; i >= synthetics; --i) {
1867674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                size += ipanns[i] == null ? 0 : ipanns[i].getSize();
1868674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1869674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1870674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (attrs != null) {
1871674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            size += attrs.getSize(cw, null, 0, -1, -1);
1872674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1873674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return size;
1874674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
1875674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
1876674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
1877674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Puts the bytecode of this method in the given byte vector.
1878674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
1879674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param out the byte vector into which the bytecode of this method must be
1880674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        copied.
1881674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
1882674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    final void put(final ByteVector out) {
1883674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        out.putShort(access).putShort(name).putShort(desc);
1884674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (classReaderOffset != 0) {
1885674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength);
1886674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return;
1887674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1888674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int attributeCount = 0;
1889674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (code.length > 0) {
1890674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ++attributeCount;
1891674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1892674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (exceptionCount > 0) {
1893674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ++attributeCount;
1894674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1895674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if ((access & Opcodes.ACC_SYNTHETIC) != 0
1896674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                && (cw.version & 0xffff) < Opcodes.V1_5)
1897674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        {
1898674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ++attributeCount;
1899674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1900674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
1901674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ++attributeCount;
1902674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1903674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.SIGNATURES && signature != null) {
1904674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ++attributeCount;
1905674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1906674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.ANNOTATIONS && annd != null) {
1907674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ++attributeCount;
1908674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1909674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.ANNOTATIONS && anns != null) {
1910674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ++attributeCount;
1911674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1912674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.ANNOTATIONS && ianns != null) {
1913674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ++attributeCount;
1914674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1915674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.ANNOTATIONS && panns != null) {
1916674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ++attributeCount;
1917674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1918674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.ANNOTATIONS && ipanns != null) {
1919674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ++attributeCount;
1920674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1921674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (attrs != null) {
1922674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            attributeCount += attrs.getCount();
1923674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
1924674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        out.putShort(attributeCount);
1925674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (code.length > 0) {
1926674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            int size = 12 + code.length + 8 * handlerCount;
1927674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (localVar != null) {
1928674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                size += 8 + localVar.length;
1929674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1930674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (localVarType != null) {
1931674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                size += 8 + localVarType.length;
1932674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1933674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (lineNumber != null) {
1934674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                size += 8 + lineNumber.length;
1935674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1936674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (stackMap != null) {
1937674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                size += 8 + stackMap.length;
1938674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1939674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (cattrs != null) {
1940674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                size += cattrs.getSize(cw,
1941674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        code.data,
1942674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        code.length,
1943674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        maxStack,
1944674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        maxLocals);
1945674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1946674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            out.putShort(cw.newUTF8("Code")).putInt(size);
1947674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            out.putShort(maxStack).putShort(maxLocals);
1948674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            out.putInt(code.length).putByteArray(code.data, 0, code.length);
1949674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            out.putShort(handlerCount);
1950674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (handlerCount > 0) {
1951674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                Handler h = firstHandler;
1952674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                while (h != null) {
1953674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    out.putShort(h.start.position)
1954674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            .putShort(h.end.position)
1955674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            .putShort(h.handler.position)
1956674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            .putShort(h.type);
1957674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    h = h.next;
1958674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
1959674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1960674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            attributeCount = 0;
1961674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (localVar != null) {
1962674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                ++attributeCount;
1963674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1964674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (localVarType != null) {
1965674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                ++attributeCount;
1966674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1967674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (lineNumber != null) {
1968674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                ++attributeCount;
1969674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1970674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (stackMap != null) {
1971674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                ++attributeCount;
1972674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1973674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (cattrs != null) {
1974674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                attributeCount += cattrs.getCount();
1975674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1976674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            out.putShort(attributeCount);
1977674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (localVar != null) {
1978674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                out.putShort(cw.newUTF8("LocalVariableTable"));
1979674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                out.putInt(localVar.length + 2).putShort(localVarCount);
1980674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                out.putByteArray(localVar.data, 0, localVar.length);
1981674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1982674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (localVarType != null) {
1983674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                out.putShort(cw.newUTF8("LocalVariableTypeTable"));
1984674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                out.putInt(localVarType.length + 2).putShort(localVarTypeCount);
1985674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                out.putByteArray(localVarType.data, 0, localVarType.length);
1986674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1987674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (lineNumber != null) {
1988674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                out.putShort(cw.newUTF8("LineNumberTable"));
1989674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                out.putInt(lineNumber.length + 2).putShort(lineNumberCount);
1990674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                out.putByteArray(lineNumber.data, 0, lineNumber.length);
1991674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1992674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (stackMap != null) {
1993674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6;
1994674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                out.putShort(cw.newUTF8(zip ? "StackMapTable" : "StackMap"));
1995674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                out.putInt(stackMap.length + 2).putShort(frameCount);
1996674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                out.putByteArray(stackMap.data, 0, stackMap.length);
1997674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
1998674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (cattrs != null) {
1999674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out);
2000674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
2001674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
2002674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (exceptionCount > 0) {
2003674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            out.putShort(cw.newUTF8("Exceptions"))
2004674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    .putInt(2 * exceptionCount + 2);
2005674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            out.putShort(exceptionCount);
2006674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            for (int i = 0; i < exceptionCount; ++i) {
2007674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                out.putShort(exceptions[i]);
2008674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
2009674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
2010674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if ((access & Opcodes.ACC_SYNTHETIC) != 0
2011674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                && (cw.version & 0xffff) < Opcodes.V1_5)
2012674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        {
2013674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            out.putShort(cw.newUTF8("Synthetic")).putInt(0);
2014674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
2015674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
2016674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            out.putShort(cw.newUTF8("Deprecated")).putInt(0);
2017674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
2018674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.SIGNATURES && signature != null) {
2019674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            out.putShort(cw.newUTF8("Signature"))
2020674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    .putInt(2)
2021674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    .putShort(cw.newUTF8(signature));
2022674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
2023674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.ANNOTATIONS && annd != null) {
2024674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            out.putShort(cw.newUTF8("AnnotationDefault"));
2025674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            out.putInt(annd.length);
2026674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            out.putByteArray(annd.data, 0, annd.length);
2027674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
2028674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.ANNOTATIONS && anns != null) {
2029674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
2030674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            anns.put(out);
2031674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
2032674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.ANNOTATIONS && ianns != null) {
2033674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
2034674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ianns.put(out);
2035674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
2036674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.ANNOTATIONS && panns != null) {
2037674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations"));
2038674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            AnnotationWriter.put(panns, synthetics, out);
2039674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
2040674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (ClassReader.ANNOTATIONS && ipanns != null) {
2041674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            out.putShort(cw.newUTF8("RuntimeInvisibleParameterAnnotations"));
2042674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            AnnotationWriter.put(ipanns, synthetics, out);
2043674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
2044674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (attrs != null) {
2045674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            attrs.put(cw, null, 0, -1, -1, out);
2046674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
2047674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
2048674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
2049674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // ------------------------------------------------------------------------
2050674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // Utility methods: instruction resizing (used to handle GOTO_W and JSR_W)
2051674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // ------------------------------------------------------------------------
2052674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
2053674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
2054674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Resizes and replaces the temporary instructions inserted by
2055674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * {@link Label#resolve} for wide forward jumps, while keeping jump offsets
2056674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * and instruction addresses consistent. This may require to resize other
2057674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * existing instructions, or even to introduce new instructions: for
2058674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * example, increasing the size of an instruction by 2 at the middle of a
2059674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * method can increases the offset of an IFEQ instruction from 32766 to
2060674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W
2061674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * 32765. This, in turn, may require to increase the size of another jump
2062674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * instruction, and so on... All these operations are handled automatically
2063674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * by this method. <p> <i>This method must be called after all the method
2064674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * that is being built has been visited</i>. In particular, the
2065674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * {@link Label Label} objects used to construct the method are no longer
2066674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * valid after this method has been called.
2067674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
2068674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private void resizeInstructions() {
2069674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        byte[] b = code.data; // bytecode of the method
2070674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int u, v, label; // indexes in b
2071674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int i, j; // loop indexes
2072674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        /*
2073674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * 1st step: As explained above, resizing an instruction may require to
2074674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * resize another one, which may require to resize yet another one, and
2075674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * so on. The first step of the algorithm consists in finding all the
2076674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * instructions that need to be resized, without modifying the code.
2077674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * This is done by the following "fix point" algorithm:
2078674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         *
2079674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * Parse the code to find the jump instructions whose offset will need
2080674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * more than 2 bytes to be stored (the future offset is computed from
2081674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * the current offset and from the number of bytes that will be inserted
2082674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * or removed between the source and target instructions). For each such
2083674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * instruction, adds an entry in (a copy of) the indexes and sizes
2084674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * arrays (if this has not already been done in a previous iteration!).
2085674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         *
2086674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * If at least one entry has been added during the previous step, go
2087674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * back to the beginning, otherwise stop.
2088674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         *
2089674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * In fact the real algorithm is complicated by the fact that the size
2090674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * of TABLESWITCH and LOOKUPSWITCH instructions depends on their
2091674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * position in the bytecode (because of padding). In order to ensure the
2092674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * convergence of the algorithm, the number of bytes to be added or
2093674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * removed from these instructions is over estimated during the previous
2094674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * loop, and computed exactly only after the loop is finished (this
2095674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         * requires another pass to parse the bytecode of the method).
2096674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         */
2097674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int[] allIndexes = new int[0]; // copy of indexes
2098674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int[] allSizes = new int[0]; // copy of sizes
2099674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        boolean[] resize; // instructions to be resized
2100674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int newOffset; // future offset of a jump instruction
2101674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
2102674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        resize = new boolean[code.length];
2103674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
2104674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done
2105674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int state = 3;
2106674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        do {
2107674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (state == 3) {
2108674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                state = 2;
2109674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
2110674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            u = 0;
2111674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            while (u < b.length) {
2112674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                int opcode = b[u] & 0xFF; // opcode of current instruction
2113674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                int insert = 0; // bytes to be added after this instruction
2114674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
2115674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                switch (ClassWriter.TYPE[opcode]) {
2116674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case ClassWriter.NOARG_INSN:
2117674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case ClassWriter.IMPLVAR_INSN:
2118674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        u += 1;
2119674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        break;
2120674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case ClassWriter.LABEL_INSN:
2121674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        if (opcode > 201) {
2122674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            // converts temporary opcodes 202 to 217, 218 and
2123674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            // 219 to IFEQ ... JSR (inclusive), IFNULL and
2124674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            // IFNONNULL
2125674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            opcode = opcode < 218 ? opcode - 49 : opcode - 20;
2126674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            label = u + readUnsignedShort(b, u + 1);
2127674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        } else {
2128674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            label = u + readShort(b, u + 1);
2129674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        }
2130674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        newOffset = getNewOffset(allIndexes, allSizes, u, label);
2131674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        if (newOffset < Short.MIN_VALUE
2132674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                || newOffset > Short.MAX_VALUE)
2133674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        {
2134674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            if (!resize[u]) {
2135674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                if (opcode == Opcodes.GOTO
2136674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                        || opcode == Opcodes.JSR)
2137674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                {
2138674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                    // two additional bytes will be required to
2139674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                    // replace this GOTO or JSR instruction with
2140674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                    // a GOTO_W or a JSR_W
2141674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                    insert = 2;
2142674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                } else {
2143674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                    // five additional bytes will be required to
2144674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                    // replace this IFxxx <l> instruction with
2145674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                    // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx
2146674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                    // is the "opposite" opcode of IFxxx (i.e.,
2147674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                    // IFNE for IFEQ) and where <l'> designates
2148674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                    // the instruction just after the GOTO_W.
2149674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                    insert = 5;
2150674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                }
2151674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                resize[u] = true;
2152674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            }
2153674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        }
2154674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        u += 3;
2155674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        break;
2156674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case ClassWriter.LABELW_INSN:
2157674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        u += 5;
2158674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        break;
2159674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case ClassWriter.TABL_INSN:
2160674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        if (state == 1) {
2161674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            // true number of bytes to be added (or removed)
2162674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            // from this instruction = (future number of padding
2163674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            // bytes - current number of padding byte) -
2164674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            // previously over estimated variation =
2165674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            // = ((3 - newOffset%4) - (3 - u%4)) - u%4
2166674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            // = (-newOffset%4 + u%4) - u%4
2167674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            // = -(newOffset & 3)
2168674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            newOffset = getNewOffset(allIndexes, allSizes, 0, u);
2169674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            insert = -(newOffset & 3);
2170674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        } else if (!resize[u]) {
2171674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            // over estimation of the number of bytes to be
2172674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            // added to this instruction = 3 - current number
2173674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3
2174674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            insert = u & 3;
2175674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            resize[u] = true;
2176674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        }
2177674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // skips instruction
2178674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        u = u + 4 - (u & 3);
2179674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12;
2180674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        break;
2181674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case ClassWriter.LOOK_INSN:
2182674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        if (state == 1) {
2183674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            // like TABL_INSN
2184674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            newOffset = getNewOffset(allIndexes, allSizes, 0, u);
2185674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            insert = -(newOffset & 3);
2186674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        } else if (!resize[u]) {
2187674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            // like TABL_INSN
2188674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            insert = u & 3;
2189674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            resize[u] = true;
2190674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        }
2191674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // skips instruction
2192674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        u = u + 4 - (u & 3);
2193674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        u += 8 * readInt(b, u + 4) + 8;
2194674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        break;
2195674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case ClassWriter.WIDE_INSN:
2196674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        opcode = b[u + 1] & 0xFF;
2197674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        if (opcode == Opcodes.IINC) {
2198674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            u += 6;
2199674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        } else {
2200674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            u += 4;
2201674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        }
2202674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        break;
2203674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case ClassWriter.VAR_INSN:
2204674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case ClassWriter.SBYTE_INSN:
2205674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case ClassWriter.LDC_INSN:
2206674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        u += 2;
2207674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        break;
2208674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case ClassWriter.SHORT_INSN:
2209674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case ClassWriter.LDCW_INSN:
2210674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case ClassWriter.FIELDORMETH_INSN:
2211674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case ClassWriter.TYPE_INSN:
2212674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case ClassWriter.IINC_INSN:
2213674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        u += 3;
2214674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        break;
2215674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    case ClassWriter.ITFMETH_INSN:
2216674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        u += 5;
2217674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        break;
2218674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // case ClassWriter.MANA_INSN:
2219674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    default:
2220674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        u += 4;
2221674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        break;
2222674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
2223674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (insert != 0) {
2224674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // adds a new (u, insert) entry in the allIndexes and
2225674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // allSizes arrays
2226674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    int[] newIndexes = new int[allIndexes.length + 1];
2227674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    int[] newSizes = new int[allSizes.length + 1];
2228674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    System.arraycopy(allIndexes,
2229674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            0,
2230674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            newIndexes,
2231674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            0,
2232674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            allIndexes.length);
2233674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length);
2234674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newIndexes[allIndexes.length] = u;
2235674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newSizes[allSizes.length] = insert;
2236674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    allIndexes = newIndexes;
2237674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    allSizes = newSizes;
2238674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    if (insert > 0) {
2239674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        state = 3;
2240674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
2241674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
2242674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
2243674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (state < 3) {
2244674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                --state;
2245674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
2246674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } while (state != 0);
2247674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
2248674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // 2nd step:
2249674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // copies the bytecode of the method into a new bytevector, updates the
2250674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // offsets, and inserts (or removes) bytes as requested.
2251674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
2252674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        ByteVector newCode = new ByteVector(code.length);
2253674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
2254674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        u = 0;
2255674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        while (u < code.length) {
2256674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            int opcode = b[u] & 0xFF;
2257674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            switch (ClassWriter.TYPE[opcode]) {
2258674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case ClassWriter.NOARG_INSN:
2259674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case ClassWriter.IMPLVAR_INSN:
2260674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newCode.putByte(opcode);
2261674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    u += 1;
2262674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    break;
2263674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case ClassWriter.LABEL_INSN:
2264674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    if (opcode > 201) {
2265674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // changes temporary opcodes 202 to 217 (inclusive), 218
2266674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // and 219 to IFEQ ... JSR (inclusive), IFNULL and
2267674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // IFNONNULL
2268674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        opcode = opcode < 218 ? opcode - 49 : opcode - 20;
2269674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        label = u + readUnsignedShort(b, u + 1);
2270674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    } else {
2271674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        label = u + readShort(b, u + 1);
2272674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
2273674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newOffset = getNewOffset(allIndexes, allSizes, u, label);
2274674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    if (resize[u]) {
2275674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
2276674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is
2277674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
2278674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // and where <l'> designates the instruction just after
2279674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // the GOTO_W.
2280674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        if (opcode == Opcodes.GOTO) {
2281674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            newCode.putByte(200); // GOTO_W
2282674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        } else if (opcode == Opcodes.JSR) {
2283674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            newCode.putByte(201); // JSR_W
2284674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        } else {
2285674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            newCode.putByte(opcode <= 166
2286674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                    ? ((opcode + 1) ^ 1) - 1
2287674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                    : opcode ^ 1);
2288674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            newCode.putShort(8); // jump offset
2289674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            newCode.putByte(200); // GOTO_W
2290674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            // newOffset now computed from start of GOTO_W
2291674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            newOffset -= 3;
2292674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        }
2293674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        newCode.putInt(newOffset);
2294674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    } else {
2295674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        newCode.putByte(opcode);
2296674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        newCode.putShort(newOffset);
2297674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
2298674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    u += 3;
2299674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    break;
2300674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case ClassWriter.LABELW_INSN:
2301674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    label = u + readInt(b, u + 1);
2302674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newOffset = getNewOffset(allIndexes, allSizes, u, label);
2303674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newCode.putByte(opcode);
2304674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newCode.putInt(newOffset);
2305674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    u += 5;
2306674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    break;
2307674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case ClassWriter.TABL_INSN:
2308674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // skips 0 to 3 padding bytes
2309674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    v = u;
2310674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    u = u + 4 - (v & 3);
2311674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // reads and copies instruction
2312674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newCode.putByte(Opcodes.TABLESWITCH);
2313674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newCode.length += (4 - newCode.length % 4) % 4;
2314674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    label = v + readInt(b, u);
2315674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    u += 4;
2316674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newOffset = getNewOffset(allIndexes, allSizes, v, label);
2317674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newCode.putInt(newOffset);
2318674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    j = readInt(b, u);
2319674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    u += 4;
2320674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newCode.putInt(j);
2321674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    j = readInt(b, u) - j + 1;
2322674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    u += 4;
2323674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newCode.putInt(readInt(b, u - 4));
2324674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    for (; j > 0; --j) {
2325674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        label = v + readInt(b, u);
2326674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        u += 4;
2327674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        newOffset = getNewOffset(allIndexes, allSizes, v, label);
2328674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        newCode.putInt(newOffset);
2329674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
2330674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    break;
2331674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case ClassWriter.LOOK_INSN:
2332674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // skips 0 to 3 padding bytes
2333674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    v = u;
2334674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    u = u + 4 - (v & 3);
2335674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // reads and copies instruction
2336674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newCode.putByte(Opcodes.LOOKUPSWITCH);
2337674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newCode.length += (4 - newCode.length % 4) % 4;
2338674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    label = v + readInt(b, u);
2339674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    u += 4;
2340674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newOffset = getNewOffset(allIndexes, allSizes, v, label);
2341674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newCode.putInt(newOffset);
2342674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    j = readInt(b, u);
2343674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    u += 4;
2344674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newCode.putInt(j);
2345674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    for (; j > 0; --j) {
2346674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        newCode.putInt(readInt(b, u));
2347674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        u += 4;
2348674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        label = v + readInt(b, u);
2349674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        u += 4;
2350674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        newOffset = getNewOffset(allIndexes, allSizes, v, label);
2351674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        newCode.putInt(newOffset);
2352674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
2353674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    break;
2354674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case ClassWriter.WIDE_INSN:
2355674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    opcode = b[u + 1] & 0xFF;
2356674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    if (opcode == Opcodes.IINC) {
2357674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        newCode.putByteArray(b, u, 6);
2358674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        u += 6;
2359674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    } else {
2360674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        newCode.putByteArray(b, u, 4);
2361674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        u += 4;
2362674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
2363674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    break;
2364674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case ClassWriter.VAR_INSN:
2365674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case ClassWriter.SBYTE_INSN:
2366674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case ClassWriter.LDC_INSN:
2367674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newCode.putByteArray(b, u, 2);
2368674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    u += 2;
2369674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    break;
2370674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case ClassWriter.SHORT_INSN:
2371674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case ClassWriter.LDCW_INSN:
2372674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case ClassWriter.FIELDORMETH_INSN:
2373674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case ClassWriter.TYPE_INSN:
2374674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case ClassWriter.IINC_INSN:
2375674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newCode.putByteArray(b, u, 3);
2376674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    u += 3;
2377674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    break;
2378674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                case ClassWriter.ITFMETH_INSN:
2379674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newCode.putByteArray(b, u, 5);
2380674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    u += 5;
2381674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    break;
2382674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // case MANA_INSN:
2383674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                default:
2384674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newCode.putByteArray(b, u, 4);
2385674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    u += 4;
2386674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    break;
2387674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
2388674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
2389674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
2390674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // recomputes the stack map frames
2391674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (frameCount > 0) {
2392674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (compute == FRAMES) {
2393674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                frameCount = 0;
2394674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                stackMap = null;
2395674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                previousFrame = null;
2396674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                frame = null;
2397674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                Frame f = new Frame();
2398674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                f.owner = labels;
2399674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                Type[] args = Type.getArgumentTypes(descriptor);
2400674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                f.initInputFrame(cw, access, args, maxLocals);
2401674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                visitFrame(f);
2402674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                Label l = labels;
2403674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                while (l != null) {
2404674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    /*
2405674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                     * here we need the original label position. getNewOffset
2406674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                     * must therefore never have been called for this label.
2407674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                     */
2408674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    u = l.position - 3;
2409674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    if ((l.status & Label.STORE) != 0 || (u >= 0 && resize[u]))
2410674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    {
2411674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        getNewOffset(allIndexes, allSizes, l);
2412674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // TODO update offsets in UNINITIALIZED values
2413674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        visitFrame(l.frame);
2414674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
2415674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    l = l.successor;
2416674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
2417674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
2418674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                /*
2419674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * Resizing an existing stack map frame table is really hard.
2420674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * Not only the table must be parsed to update the offets, but
2421674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * new frames may be needed for jump instructions that were
2422674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * inserted by this method. And updating the offsets or
2423674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * inserting frames can change the format of the following
2424674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * frames, in case of packed frames. In practice the whole table
2425674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * must be recomputed. For this the frames are marked as
2426674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * potentially invalid. This will cause the whole class to be
2427674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * reread and rewritten with the COMPUTE_FRAMES option (see the
2428674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * ClassWriter.toByteArray method). This is not very efficient
2429674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * but is much easier and requires much less code than any other
2430674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 * method I can think of.
2431674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 */
2432674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                cw.invalidFrames = true;
2433674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
2434674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
2435674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // updates the exception handler block labels
2436674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        Handler h = firstHandler;
2437674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        while (h != null) {
2438674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            getNewOffset(allIndexes, allSizes, h.start);
2439674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            getNewOffset(allIndexes, allSizes, h.end);
2440674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            getNewOffset(allIndexes, allSizes, h.handler);
2441674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            h = h.next;
2442674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
2443674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // updates the instructions addresses in the
2444674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // local var and line number tables
2445674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        for (i = 0; i < 2; ++i) {
2446674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ByteVector bv = i == 0 ? localVar : localVarType;
2447674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (bv != null) {
2448674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                b = bv.data;
2449674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                u = 0;
2450674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                while (u < bv.length) {
2451674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    label = readUnsignedShort(b, u);
2452674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newOffset = getNewOffset(allIndexes, allSizes, 0, label);
2453674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    writeShort(b, u, newOffset);
2454674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    label += readUnsignedShort(b, u + 2);
2455674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    newOffset = getNewOffset(allIndexes, allSizes, 0, label)
2456674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            - newOffset;
2457674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    writeShort(b, u + 2, newOffset);
2458674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    u += 10;
2459674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
2460674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
2461674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
2462674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (lineNumber != null) {
2463674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            b = lineNumber.data;
2464674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            u = 0;
2465674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            while (u < lineNumber.length) {
2466674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                writeShort(b, u, getNewOffset(allIndexes,
2467674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        allSizes,
2468674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        0,
2469674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        readUnsignedShort(b, u)));
2470674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                u += 4;
2471674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
2472674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
2473674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // updates the labels of the other attributes
2474674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        Attribute attr = cattrs;
2475674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        while (attr != null) {
2476674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            Label[] labels = attr.getLabels();
2477674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (labels != null) {
2478674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                for (i = labels.length - 1; i >= 0; --i) {
2479674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    getNewOffset(allIndexes, allSizes, labels[i]);
2480674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
2481674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
2482674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            attr = attr.next;
2483674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
2484674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
2485674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // replaces old bytecodes with new ones
2486674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        code = newCode;
2487674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
2488674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
2489674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
2490674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Reads an unsigned short value in the given byte array.
2491674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
2492674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param b a byte array.
2493674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param index the start index of the value to be read.
2494674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @return the read value.
2495674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
2496674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static int readUnsignedShort(final byte[] b, final int index) {
2497674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
2498674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
2499674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
2500674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
2501674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Reads a signed short value in the given byte array.
2502674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
2503674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param b a byte array.
2504674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param index the start index of the value to be read.
2505674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @return the read value.
2506674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
2507674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static short readShort(final byte[] b, final int index) {
2508674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
2509674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
2510674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
2511674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
2512674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Reads a signed int value in the given byte array.
2513674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
2514674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param b a byte array.
2515674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param index the start index of the value to be read.
2516674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @return the read value.
2517674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
2518674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static int readInt(final byte[] b, final int index) {
2519674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)
2520674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
2521674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
2522674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
2523674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
2524674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Writes a short value in the given byte array.
2525674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
2526674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param b a byte array.
2527674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param index where the first byte of the short value must be written.
2528674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param s the value to be written in the given byte array.
2529674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
2530674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static void writeShort(final byte[] b, final int index, final int s) {
2531674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        b[index] = (byte) (s >>> 8);
2532674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        b[index + 1] = (byte) s;
2533674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
2534674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
2535674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
2536674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Computes the future value of a bytecode offset. <p> Note: it is possible
2537674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * to have several entries for the same instruction in the <tt>indexes</tt>
2538674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * and <tt>sizes</tt>: two entries (index=a,size=b) and (index=a,size=b')
2539674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * are equivalent to a single entry (index=a,size=b+b').
2540674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
2541674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param indexes current positions of the instructions to be resized. Each
2542674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        instruction must be designated by the index of its <i>last</i>
2543674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        byte, plus one (or, in other words, by the index of the <i>first</i>
2544674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        byte of the <i>next</i> instruction).
2545674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param sizes the number of bytes to be <i>added</i> to the above
2546674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        instructions. More precisely, for each i < <tt>len</tt>,
2547674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        <tt>sizes</tt>[i] bytes will be added at the end of the
2548674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        instruction designated by <tt>indexes</tt>[i] or, if
2549674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        <tt>sizes</tt>[i] is negative, the <i>last</i> |<tt>sizes[i]</tt>|
2550674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        bytes of the instruction will be removed (the instruction size
2551674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        <i>must not</i> become negative or null).
2552674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param begin index of the first byte of the source instruction.
2553674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param end index of the first byte of the target instruction.
2554674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @return the future value of the given bytecode offset.
2555674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
2556674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static int getNewOffset(
2557674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int[] indexes,
2558674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int[] sizes,
2559674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int begin,
2560674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int end)
2561674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
2562674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int offset = end - begin;
2563674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        for (int i = 0; i < indexes.length; ++i) {
2564674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (begin < indexes[i] && indexes[i] <= end) {
2565674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // forward jump
2566674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                offset += sizes[i];
2567674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else if (end < indexes[i] && indexes[i] <= begin) {
2568674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // backward jump
2569674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                offset -= sizes[i];
2570674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
2571674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
2572674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return offset;
2573674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
2574674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
2575674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
2576674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Updates the offset of the given label.
2577674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
2578674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param indexes current positions of the instructions to be resized. Each
2579674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        instruction must be designated by the index of its <i>last</i>
2580674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        byte, plus one (or, in other words, by the index of the <i>first</i>
2581674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        byte of the <i>next</i> instruction).
2582674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param sizes the number of bytes to be <i>added</i> to the above
2583674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        instructions. More precisely, for each i < <tt>len</tt>,
2584674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        <tt>sizes</tt>[i] bytes will be added at the end of the
2585674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        instruction designated by <tt>indexes</tt>[i] or, if
2586674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        <tt>sizes</tt>[i] is negative, the <i>last</i> |<tt>sizes[i]</tt>|
2587674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        bytes of the instruction will be removed (the instruction size
2588674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *        <i>must not</i> become negative or null).
2589674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @param label the label whose offset must be updated.
2590674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
2591674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static void getNewOffset(
2592674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int[] indexes,
2593674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final int[] sizes,
2594674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Label label)
2595674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    {
2596674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if ((label.status & Label.RESIZED) == 0) {
2597674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            label.position = getNewOffset(indexes, sizes, 0, label.position);
2598674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            label.status |= Label.RESIZED;
2599674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
2600674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
2601674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen}
2602