rlm@10
|
1 /***
|
rlm@10
|
2 * ASM: a very small and fast Java bytecode manipulation framework
|
rlm@10
|
3 * Copyright (c) 2000-2005 INRIA, France Telecom
|
rlm@10
|
4 * All rights reserved.
|
rlm@10
|
5 *
|
rlm@10
|
6 * Redistribution and use in source and binary forms, with or without
|
rlm@10
|
7 * modification, are permitted provided that the following conditions
|
rlm@10
|
8 * are met:
|
rlm@10
|
9 * 1. Redistributions of source code must retain the above copyright
|
rlm@10
|
10 * notice, this list of conditions and the following disclaimer.
|
rlm@10
|
11 * 2. Redistributions in binary form must reproduce the above copyright
|
rlm@10
|
12 * notice, this list of conditions and the following disclaimer in the
|
rlm@10
|
13 * documentation and/or other materials provided with the distribution.
|
rlm@10
|
14 * 3. Neither the name of the copyright holders nor the names of its
|
rlm@10
|
15 * contributors may be used to endorse or promote products derived from
|
rlm@10
|
16 * this software without specific prior written permission.
|
rlm@10
|
17 *
|
rlm@10
|
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
rlm@10
|
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
rlm@10
|
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
rlm@10
|
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
rlm@10
|
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
rlm@10
|
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
rlm@10
|
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
rlm@10
|
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
rlm@10
|
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
rlm@10
|
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
rlm@10
|
28 * THE POSSIBILITY OF SUCH DAMAGE.
|
rlm@10
|
29 */
|
rlm@10
|
30 package clojure.asm;
|
rlm@10
|
31
|
rlm@10
|
32 /**
|
rlm@10
|
33 * Information about the input and output stack map frames of a basic block.
|
rlm@10
|
34 *
|
rlm@10
|
35 * @author Eric Bruneton
|
rlm@10
|
36 */
|
rlm@10
|
37 final class Frame{
|
rlm@10
|
38
|
rlm@10
|
39 /*
|
rlm@10
|
40 * Frames are computed in a two steps process: during the visit of each
|
rlm@10
|
41 * instruction, the state of the frame at the end of current basic block is
|
rlm@10
|
42 * updated by simulating the action of the instruction on the previous state
|
rlm@10
|
43 * of this so called "output frame". In visitMaxs, a fix point algorithm is
|
rlm@10
|
44 * used to compute the "input frame" of each basic block, i.e. the stack map
|
rlm@10
|
45 * frame at the begining of the basic block, starting from the input frame
|
rlm@10
|
46 * of the first basic block (which is computed from the method descriptor),
|
rlm@10
|
47 * and by using the previously computed output frames to compute the input
|
rlm@10
|
48 * state of the other blocks.
|
rlm@10
|
49 *
|
rlm@10
|
50 * All output and input frames are stored as arrays of integers. Reference
|
rlm@10
|
51 * and array types are represented by an index into a type table (which is
|
rlm@10
|
52 * not the same as the constant pool of the class, in order to avoid adding
|
rlm@10
|
53 * unnecessary constants in the pool - not all computed frames will end up
|
rlm@10
|
54 * being stored in the stack map table). This allows very fast type
|
rlm@10
|
55 * comparisons.
|
rlm@10
|
56 *
|
rlm@10
|
57 * Output stack map frames are computed relatively to the input frame of the
|
rlm@10
|
58 * basic block, which is not yet known when output frames are computed. It
|
rlm@10
|
59 * is therefore necessary to be able to represent abstract types such as
|
rlm@10
|
60 * "the type at position x in the input frame locals" or "the type at
|
rlm@10
|
61 * position x from the top of the input frame stack" or even "the type at
|
rlm@10
|
62 * position x in the input frame, with y more (or less) array dimensions".
|
rlm@10
|
63 * This explains the rather complicated type format used in output frames.
|
rlm@10
|
64 *
|
rlm@10
|
65 * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a
|
rlm@10
|
66 * signed number of array dimensions (from -8 to 7). KIND is either BASE,
|
rlm@10
|
67 * LOCAL or STACK. BASE is used for types that are not relative to the input
|
rlm@10
|
68 * frame. LOCAL is used for types that are relative to the input local
|
rlm@10
|
69 * variable types. STACK is used for types that are relative to the input
|
rlm@10
|
70 * stack types. VALUE depends on KIND. For LOCAL types, it is an index in
|
rlm@10
|
71 * the input local variable types. For STACK types, it is a position
|
rlm@10
|
72 * relatively to the top of input frame stack. For BASE types, it is either
|
rlm@10
|
73 * one of the constants defined in FrameVisitor, or for OBJECT and
|
rlm@10
|
74 * UNINITIALIZED types, a tag and an index in the type table.
|
rlm@10
|
75 *
|
rlm@10
|
76 * Output frames can contain types of any kind and with a positive or
|
rlm@10
|
77 * negative dimension (and even unassigned types, represented by 0 - which
|
rlm@10
|
78 * does not correspond to any valid type value). Input frames can only
|
rlm@10
|
79 * contain BASE types of positive or null dimension. In all cases the type
|
rlm@10
|
80 * table contains only internal type names (array type descriptors are
|
rlm@10
|
81 * forbidden - dimensions must be represented through the DIM field).
|
rlm@10
|
82 *
|
rlm@10
|
83 * The LONG and DOUBLE types are always represented by using two slots (LONG +
|
rlm@10
|
84 * TOP or DOUBLE + TOP), for local variable types as well as in the operand
|
rlm@10
|
85 * stack. This is necessary to be able to simulate DUPx_y instructions,
|
rlm@10
|
86 * whose effect would be dependent on the actual type values if types were
|
rlm@10
|
87 * always represented by a single slot in the stack (and this is not
|
rlm@10
|
88 * possible, since actual type values are not always known - cf LOCAL and
|
rlm@10
|
89 * STACK type kinds).
|
rlm@10
|
90 */
|
rlm@10
|
91
|
rlm@10
|
92 /**
|
rlm@10
|
93 * Mask to get the dimension of a frame type. This dimension is a signed
|
rlm@10
|
94 * integer between -8 and 7.
|
rlm@10
|
95 */
|
rlm@10
|
96 final static int DIM = 0xF0000000;
|
rlm@10
|
97
|
rlm@10
|
98 /**
|
rlm@10
|
99 * Constant to be added to a type to get a type with one more dimension.
|
rlm@10
|
100 */
|
rlm@10
|
101 final static int ARRAY_OF = 0x10000000;
|
rlm@10
|
102
|
rlm@10
|
103 /**
|
rlm@10
|
104 * Constant to be added to a type to get a type with one less dimension.
|
rlm@10
|
105 */
|
rlm@10
|
106 final static int ELEMENT_OF = 0xF0000000;
|
rlm@10
|
107
|
rlm@10
|
108 /**
|
rlm@10
|
109 * Mask to get the kind of a frame type.
|
rlm@10
|
110 *
|
rlm@10
|
111 * @see #BASE
|
rlm@10
|
112 * @see #LOCAL
|
rlm@10
|
113 * @see #STACK
|
rlm@10
|
114 */
|
rlm@10
|
115 final static int KIND = 0xF000000;
|
rlm@10
|
116
|
rlm@10
|
117 /**
|
rlm@10
|
118 * Mask to get the value of a frame type.
|
rlm@10
|
119 */
|
rlm@10
|
120 final static int VALUE = 0xFFFFFF;
|
rlm@10
|
121
|
rlm@10
|
122 /**
|
rlm@10
|
123 * Mask to get the kind of base types.
|
rlm@10
|
124 */
|
rlm@10
|
125 final static int BASE_KIND = 0xFF00000;
|
rlm@10
|
126
|
rlm@10
|
127 /**
|
rlm@10
|
128 * Mask to get the value of base types.
|
rlm@10
|
129 */
|
rlm@10
|
130 final static int BASE_VALUE = 0xFFFFF;
|
rlm@10
|
131
|
rlm@10
|
132 /**
|
rlm@10
|
133 * Kind of the types that are not relative to an input stack map frame.
|
rlm@10
|
134 */
|
rlm@10
|
135 final static int BASE = 0x1000000;
|
rlm@10
|
136
|
rlm@10
|
137 /**
|
rlm@10
|
138 * Base kind of the base reference types. The BASE_VALUE of such types is an
|
rlm@10
|
139 * index into the type table.
|
rlm@10
|
140 */
|
rlm@10
|
141 final static int OBJECT = BASE | 0x700000;
|
rlm@10
|
142
|
rlm@10
|
143 /**
|
rlm@10
|
144 * Base kind of the uninitialized base types. The BASE_VALUE of such types
|
rlm@10
|
145 * in an index into the type table (the Item at that index contains both an
|
rlm@10
|
146 * instruction offset and an internal class name).
|
rlm@10
|
147 */
|
rlm@10
|
148 final static int UNINITIALIZED = BASE | 0x800000;
|
rlm@10
|
149
|
rlm@10
|
150 /**
|
rlm@10
|
151 * Kind of the types that are relative to the local variable types of an
|
rlm@10
|
152 * input stack map frame. The value of such types is a local variable index.
|
rlm@10
|
153 */
|
rlm@10
|
154 private final static int LOCAL = 0x2000000;
|
rlm@10
|
155
|
rlm@10
|
156 /**
|
rlm@10
|
157 * Kind of the the types that are relative to the stack of an input stack
|
rlm@10
|
158 * map frame. The value of such types is a position relatively to the top of
|
rlm@10
|
159 * this stack.
|
rlm@10
|
160 */
|
rlm@10
|
161 private final static int STACK = 0x3000000;
|
rlm@10
|
162
|
rlm@10
|
163 /**
|
rlm@10
|
164 * The TOP type. This is a BASE type.
|
rlm@10
|
165 */
|
rlm@10
|
166 final static int TOP = BASE | 0;
|
rlm@10
|
167
|
rlm@10
|
168 /**
|
rlm@10
|
169 * The BOOLEAN type. This is a BASE type mainly used for array types.
|
rlm@10
|
170 */
|
rlm@10
|
171 final static int BOOLEAN = BASE | 9;
|
rlm@10
|
172
|
rlm@10
|
173 /**
|
rlm@10
|
174 * The BYTE type. This is a BASE type mainly used for array types.
|
rlm@10
|
175 */
|
rlm@10
|
176 final static int BYTE = BASE | 10;
|
rlm@10
|
177
|
rlm@10
|
178 /**
|
rlm@10
|
179 * The CHAR type. This is a BASE type mainly used for array types.
|
rlm@10
|
180 */
|
rlm@10
|
181 final static int CHAR = BASE | 11;
|
rlm@10
|
182
|
rlm@10
|
183 /**
|
rlm@10
|
184 * The SHORT type. This is a BASE type mainly used for array types.
|
rlm@10
|
185 */
|
rlm@10
|
186 final static int SHORT = BASE | 12;
|
rlm@10
|
187
|
rlm@10
|
188 /**
|
rlm@10
|
189 * The INTEGER type. This is a BASE type.
|
rlm@10
|
190 */
|
rlm@10
|
191 final static int INTEGER = BASE | 1;
|
rlm@10
|
192
|
rlm@10
|
193 /**
|
rlm@10
|
194 * The FLOAT type. This is a BASE type.
|
rlm@10
|
195 */
|
rlm@10
|
196 final static int FLOAT = BASE | 2;
|
rlm@10
|
197
|
rlm@10
|
198 /**
|
rlm@10
|
199 * The DOUBLE type. This is a BASE type.
|
rlm@10
|
200 */
|
rlm@10
|
201 final static int DOUBLE = BASE | 3;
|
rlm@10
|
202
|
rlm@10
|
203 /**
|
rlm@10
|
204 * The LONG type. This is a BASE type.
|
rlm@10
|
205 */
|
rlm@10
|
206 final static int LONG = BASE | 4;
|
rlm@10
|
207
|
rlm@10
|
208 /**
|
rlm@10
|
209 * The NULL type. This is a BASE type.
|
rlm@10
|
210 */
|
rlm@10
|
211 final static int NULL = BASE | 5;
|
rlm@10
|
212
|
rlm@10
|
213 /**
|
rlm@10
|
214 * The UNINITIALIZED_THIS type. This is a BASE type.
|
rlm@10
|
215 */
|
rlm@10
|
216 final static int UNINITIALIZED_THIS = BASE | 6;
|
rlm@10
|
217
|
rlm@10
|
218 /**
|
rlm@10
|
219 * The stack size variation corresponding to each JVM instruction. This
|
rlm@10
|
220 * stack variation is equal to the size of the values produced by an
|
rlm@10
|
221 * instruction, minus the size of the values consumed by this instruction.
|
rlm@10
|
222 */
|
rlm@10
|
223 final static int[] SIZE;
|
rlm@10
|
224
|
rlm@10
|
225 /**
|
rlm@10
|
226 * Computes the stack size variation corresponding to each JVM instruction.
|
rlm@10
|
227 */
|
rlm@10
|
228 static
|
rlm@10
|
229 {
|
rlm@10
|
230 int i;
|
rlm@10
|
231 int[] b = new int[202];
|
rlm@10
|
232 String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD"
|
rlm@10
|
233 + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD"
|
rlm@10
|
234 + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED"
|
rlm@10
|
235 + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
|
rlm@10
|
236 for(i = 0; i < b.length; ++i)
|
rlm@10
|
237 {
|
rlm@10
|
238 b[i] = s.charAt(i) - 'E';
|
rlm@10
|
239 }
|
rlm@10
|
240 SIZE = b;
|
rlm@10
|
241
|
rlm@10
|
242 // code to generate the above string
|
rlm@10
|
243 //
|
rlm@10
|
244 // int NA = 0; // not applicable (unused opcode or variable size opcode)
|
rlm@10
|
245 //
|
rlm@10
|
246 // b = new int[] {
|
rlm@10
|
247 // 0, //NOP, // visitInsn
|
rlm@10
|
248 // 1, //ACONST_NULL, // -
|
rlm@10
|
249 // 1, //ICONST_M1, // -
|
rlm@10
|
250 // 1, //ICONST_0, // -
|
rlm@10
|
251 // 1, //ICONST_1, // -
|
rlm@10
|
252 // 1, //ICONST_2, // -
|
rlm@10
|
253 // 1, //ICONST_3, // -
|
rlm@10
|
254 // 1, //ICONST_4, // -
|
rlm@10
|
255 // 1, //ICONST_5, // -
|
rlm@10
|
256 // 2, //LCONST_0, // -
|
rlm@10
|
257 // 2, //LCONST_1, // -
|
rlm@10
|
258 // 1, //FCONST_0, // -
|
rlm@10
|
259 // 1, //FCONST_1, // -
|
rlm@10
|
260 // 1, //FCONST_2, // -
|
rlm@10
|
261 // 2, //DCONST_0, // -
|
rlm@10
|
262 // 2, //DCONST_1, // -
|
rlm@10
|
263 // 1, //BIPUSH, // visitIntInsn
|
rlm@10
|
264 // 1, //SIPUSH, // -
|
rlm@10
|
265 // 1, //LDC, // visitLdcInsn
|
rlm@10
|
266 // NA, //LDC_W, // -
|
rlm@10
|
267 // NA, //LDC2_W, // -
|
rlm@10
|
268 // 1, //ILOAD, // visitVarInsn
|
rlm@10
|
269 // 2, //LLOAD, // -
|
rlm@10
|
270 // 1, //FLOAD, // -
|
rlm@10
|
271 // 2, //DLOAD, // -
|
rlm@10
|
272 // 1, //ALOAD, // -
|
rlm@10
|
273 // NA, //ILOAD_0, // -
|
rlm@10
|
274 // NA, //ILOAD_1, // -
|
rlm@10
|
275 // NA, //ILOAD_2, // -
|
rlm@10
|
276 // NA, //ILOAD_3, // -
|
rlm@10
|
277 // NA, //LLOAD_0, // -
|
rlm@10
|
278 // NA, //LLOAD_1, // -
|
rlm@10
|
279 // NA, //LLOAD_2, // -
|
rlm@10
|
280 // NA, //LLOAD_3, // -
|
rlm@10
|
281 // NA, //FLOAD_0, // -
|
rlm@10
|
282 // NA, //FLOAD_1, // -
|
rlm@10
|
283 // NA, //FLOAD_2, // -
|
rlm@10
|
284 // NA, //FLOAD_3, // -
|
rlm@10
|
285 // NA, //DLOAD_0, // -
|
rlm@10
|
286 // NA, //DLOAD_1, // -
|
rlm@10
|
287 // NA, //DLOAD_2, // -
|
rlm@10
|
288 // NA, //DLOAD_3, // -
|
rlm@10
|
289 // NA, //ALOAD_0, // -
|
rlm@10
|
290 // NA, //ALOAD_1, // -
|
rlm@10
|
291 // NA, //ALOAD_2, // -
|
rlm@10
|
292 // NA, //ALOAD_3, // -
|
rlm@10
|
293 // -1, //IALOAD, // visitInsn
|
rlm@10
|
294 // 0, //LALOAD, // -
|
rlm@10
|
295 // -1, //FALOAD, // -
|
rlm@10
|
296 // 0, //DALOAD, // -
|
rlm@10
|
297 // -1, //AALOAD, // -
|
rlm@10
|
298 // -1, //BALOAD, // -
|
rlm@10
|
299 // -1, //CALOAD, // -
|
rlm@10
|
300 // -1, //SALOAD, // -
|
rlm@10
|
301 // -1, //ISTORE, // visitVarInsn
|
rlm@10
|
302 // -2, //LSTORE, // -
|
rlm@10
|
303 // -1, //FSTORE, // -
|
rlm@10
|
304 // -2, //DSTORE, // -
|
rlm@10
|
305 // -1, //ASTORE, // -
|
rlm@10
|
306 // NA, //ISTORE_0, // -
|
rlm@10
|
307 // NA, //ISTORE_1, // -
|
rlm@10
|
308 // NA, //ISTORE_2, // -
|
rlm@10
|
309 // NA, //ISTORE_3, // -
|
rlm@10
|
310 // NA, //LSTORE_0, // -
|
rlm@10
|
311 // NA, //LSTORE_1, // -
|
rlm@10
|
312 // NA, //LSTORE_2, // -
|
rlm@10
|
313 // NA, //LSTORE_3, // -
|
rlm@10
|
314 // NA, //FSTORE_0, // -
|
rlm@10
|
315 // NA, //FSTORE_1, // -
|
rlm@10
|
316 // NA, //FSTORE_2, // -
|
rlm@10
|
317 // NA, //FSTORE_3, // -
|
rlm@10
|
318 // NA, //DSTORE_0, // -
|
rlm@10
|
319 // NA, //DSTORE_1, // -
|
rlm@10
|
320 // NA, //DSTORE_2, // -
|
rlm@10
|
321 // NA, //DSTORE_3, // -
|
rlm@10
|
322 // NA, //ASTORE_0, // -
|
rlm@10
|
323 // NA, //ASTORE_1, // -
|
rlm@10
|
324 // NA, //ASTORE_2, // -
|
rlm@10
|
325 // NA, //ASTORE_3, // -
|
rlm@10
|
326 // -3, //IASTORE, // visitInsn
|
rlm@10
|
327 // -4, //LASTORE, // -
|
rlm@10
|
328 // -3, //FASTORE, // -
|
rlm@10
|
329 // -4, //DASTORE, // -
|
rlm@10
|
330 // -3, //AASTORE, // -
|
rlm@10
|
331 // -3, //BASTORE, // -
|
rlm@10
|
332 // -3, //CASTORE, // -
|
rlm@10
|
333 // -3, //SASTORE, // -
|
rlm@10
|
334 // -1, //POP, // -
|
rlm@10
|
335 // -2, //POP2, // -
|
rlm@10
|
336 // 1, //DUP, // -
|
rlm@10
|
337 // 1, //DUP_X1, // -
|
rlm@10
|
338 // 1, //DUP_X2, // -
|
rlm@10
|
339 // 2, //DUP2, // -
|
rlm@10
|
340 // 2, //DUP2_X1, // -
|
rlm@10
|
341 // 2, //DUP2_X2, // -
|
rlm@10
|
342 // 0, //SWAP, // -
|
rlm@10
|
343 // -1, //IADD, // -
|
rlm@10
|
344 // -2, //LADD, // -
|
rlm@10
|
345 // -1, //FADD, // -
|
rlm@10
|
346 // -2, //DADD, // -
|
rlm@10
|
347 // -1, //ISUB, // -
|
rlm@10
|
348 // -2, //LSUB, // -
|
rlm@10
|
349 // -1, //FSUB, // -
|
rlm@10
|
350 // -2, //DSUB, // -
|
rlm@10
|
351 // -1, //IMUL, // -
|
rlm@10
|
352 // -2, //LMUL, // -
|
rlm@10
|
353 // -1, //FMUL, // -
|
rlm@10
|
354 // -2, //DMUL, // -
|
rlm@10
|
355 // -1, //IDIV, // -
|
rlm@10
|
356 // -2, //LDIV, // -
|
rlm@10
|
357 // -1, //FDIV, // -
|
rlm@10
|
358 // -2, //DDIV, // -
|
rlm@10
|
359 // -1, //IREM, // -
|
rlm@10
|
360 // -2, //LREM, // -
|
rlm@10
|
361 // -1, //FREM, // -
|
rlm@10
|
362 // -2, //DREM, // -
|
rlm@10
|
363 // 0, //INEG, // -
|
rlm@10
|
364 // 0, //LNEG, // -
|
rlm@10
|
365 // 0, //FNEG, // -
|
rlm@10
|
366 // 0, //DNEG, // -
|
rlm@10
|
367 // -1, //ISHL, // -
|
rlm@10
|
368 // -1, //LSHL, // -
|
rlm@10
|
369 // -1, //ISHR, // -
|
rlm@10
|
370 // -1, //LSHR, // -
|
rlm@10
|
371 // -1, //IUSHR, // -
|
rlm@10
|
372 // -1, //LUSHR, // -
|
rlm@10
|
373 // -1, //IAND, // -
|
rlm@10
|
374 // -2, //LAND, // -
|
rlm@10
|
375 // -1, //IOR, // -
|
rlm@10
|
376 // -2, //LOR, // -
|
rlm@10
|
377 // -1, //IXOR, // -
|
rlm@10
|
378 // -2, //LXOR, // -
|
rlm@10
|
379 // 0, //IINC, // visitIincInsn
|
rlm@10
|
380 // 1, //I2L, // visitInsn
|
rlm@10
|
381 // 0, //I2F, // -
|
rlm@10
|
382 // 1, //I2D, // -
|
rlm@10
|
383 // -1, //L2I, // -
|
rlm@10
|
384 // -1, //L2F, // -
|
rlm@10
|
385 // 0, //L2D, // -
|
rlm@10
|
386 // 0, //F2I, // -
|
rlm@10
|
387 // 1, //F2L, // -
|
rlm@10
|
388 // 1, //F2D, // -
|
rlm@10
|
389 // -1, //D2I, // -
|
rlm@10
|
390 // 0, //D2L, // -
|
rlm@10
|
391 // -1, //D2F, // -
|
rlm@10
|
392 // 0, //I2B, // -
|
rlm@10
|
393 // 0, //I2C, // -
|
rlm@10
|
394 // 0, //I2S, // -
|
rlm@10
|
395 // -3, //LCMP, // -
|
rlm@10
|
396 // -1, //FCMPL, // -
|
rlm@10
|
397 // -1, //FCMPG, // -
|
rlm@10
|
398 // -3, //DCMPL, // -
|
rlm@10
|
399 // -3, //DCMPG, // -
|
rlm@10
|
400 // -1, //IFEQ, // visitJumpInsn
|
rlm@10
|
401 // -1, //IFNE, // -
|
rlm@10
|
402 // -1, //IFLT, // -
|
rlm@10
|
403 // -1, //IFGE, // -
|
rlm@10
|
404 // -1, //IFGT, // -
|
rlm@10
|
405 // -1, //IFLE, // -
|
rlm@10
|
406 // -2, //IF_ICMPEQ, // -
|
rlm@10
|
407 // -2, //IF_ICMPNE, // -
|
rlm@10
|
408 // -2, //IF_ICMPLT, // -
|
rlm@10
|
409 // -2, //IF_ICMPGE, // -
|
rlm@10
|
410 // -2, //IF_ICMPGT, // -
|
rlm@10
|
411 // -2, //IF_ICMPLE, // -
|
rlm@10
|
412 // -2, //IF_ACMPEQ, // -
|
rlm@10
|
413 // -2, //IF_ACMPNE, // -
|
rlm@10
|
414 // 0, //GOTO, // -
|
rlm@10
|
415 // 1, //JSR, // -
|
rlm@10
|
416 // 0, //RET, // visitVarInsn
|
rlm@10
|
417 // -1, //TABLESWITCH, // visiTableSwitchInsn
|
rlm@10
|
418 // -1, //LOOKUPSWITCH, // visitLookupSwitch
|
rlm@10
|
419 // -1, //IRETURN, // visitInsn
|
rlm@10
|
420 // -2, //LRETURN, // -
|
rlm@10
|
421 // -1, //FRETURN, // -
|
rlm@10
|
422 // -2, //DRETURN, // -
|
rlm@10
|
423 // -1, //ARETURN, // -
|
rlm@10
|
424 // 0, //RETURN, // -
|
rlm@10
|
425 // NA, //GETSTATIC, // visitFieldInsn
|
rlm@10
|
426 // NA, //PUTSTATIC, // -
|
rlm@10
|
427 // NA, //GETFIELD, // -
|
rlm@10
|
428 // NA, //PUTFIELD, // -
|
rlm@10
|
429 // NA, //INVOKEVIRTUAL, // visitMethodInsn
|
rlm@10
|
430 // NA, //INVOKESPECIAL, // -
|
rlm@10
|
431 // NA, //INVOKESTATIC, // -
|
rlm@10
|
432 // NA, //INVOKEINTERFACE, // -
|
rlm@10
|
433 // NA, //UNUSED, // NOT VISITED
|
rlm@10
|
434 // 1, //NEW, // visitTypeInsn
|
rlm@10
|
435 // 0, //NEWARRAY, // visitIntInsn
|
rlm@10
|
436 // 0, //ANEWARRAY, // visitTypeInsn
|
rlm@10
|
437 // 0, //ARRAYLENGTH, // visitInsn
|
rlm@10
|
438 // NA, //ATHROW, // -
|
rlm@10
|
439 // 0, //CHECKCAST, // visitTypeInsn
|
rlm@10
|
440 // 0, //INSTANCEOF, // -
|
rlm@10
|
441 // -1, //MONITORENTER, // visitInsn
|
rlm@10
|
442 // -1, //MONITOREXIT, // -
|
rlm@10
|
443 // NA, //WIDE, // NOT VISITED
|
rlm@10
|
444 // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn
|
rlm@10
|
445 // -1, //IFNULL, // visitJumpInsn
|
rlm@10
|
446 // -1, //IFNONNULL, // -
|
rlm@10
|
447 // NA, //GOTO_W, // -
|
rlm@10
|
448 // NA, //JSR_W, // -
|
rlm@10
|
449 // };
|
rlm@10
|
450 // for (i = 0; i < b.length; ++i) {
|
rlm@10
|
451 // System.err.print((char)('E' + b[i]));
|
rlm@10
|
452 // }
|
rlm@10
|
453 // System.err.println();
|
rlm@10
|
454 }
|
rlm@10
|
455
|
rlm@10
|
456 /**
|
rlm@10
|
457 * The label (i.e. basic block) to which these input and output stack map
|
rlm@10
|
458 * frames correspond.
|
rlm@10
|
459 */
|
rlm@10
|
460 Label owner;
|
rlm@10
|
461
|
rlm@10
|
462 /**
|
rlm@10
|
463 * The input stack map frame locals.
|
rlm@10
|
464 */
|
rlm@10
|
465 int[] inputLocals;
|
rlm@10
|
466
|
rlm@10
|
467 /**
|
rlm@10
|
468 * The input stack map frame stack.
|
rlm@10
|
469 */
|
rlm@10
|
470 int[] inputStack;
|
rlm@10
|
471
|
rlm@10
|
472 /**
|
rlm@10
|
473 * The output stack map frame locals.
|
rlm@10
|
474 */
|
rlm@10
|
475 private int[] outputLocals;
|
rlm@10
|
476
|
rlm@10
|
477 /**
|
rlm@10
|
478 * The output stack map frame stack.
|
rlm@10
|
479 */
|
rlm@10
|
480 private int[] outputStack;
|
rlm@10
|
481
|
rlm@10
|
482 /**
|
rlm@10
|
483 * Relative size of the output stack. The exact semantics of this field
|
rlm@10
|
484 * depends on the algorithm that is used.
|
rlm@10
|
485 * <p/>
|
rlm@10
|
486 * When only the maximum stack size is computed, this field is the size of
|
rlm@10
|
487 * the output stack relatively to the top of the input stack.
|
rlm@10
|
488 * <p/>
|
rlm@10
|
489 * When the stack map frames are completely computed, this field is the
|
rlm@10
|
490 * actual number of types in {@link #outputStack}.
|
rlm@10
|
491 */
|
rlm@10
|
492 private int outputStackTop;
|
rlm@10
|
493
|
rlm@10
|
494 /**
|
rlm@10
|
495 * Number of types that are initialized in the basic block.
|
rlm@10
|
496 *
|
rlm@10
|
497 * @see #initializations
|
rlm@10
|
498 */
|
rlm@10
|
499 private int initializationCount;
|
rlm@10
|
500
|
rlm@10
|
501 /**
|
rlm@10
|
502 * The types that are initialized in the basic block. A constructor
|
rlm@10
|
503 * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace
|
rlm@10
|
504 * <i>every occurence</i> of this type in the local variables and in the
|
rlm@10
|
505 * operand stack. This cannot be done during the first phase of the
|
rlm@10
|
506 * algorithm since, during this phase, the local variables and the operand
|
rlm@10
|
507 * stack are not completely computed. It is therefore necessary to store the
|
rlm@10
|
508 * types on which constructors are invoked in the basic block, in order to
|
rlm@10
|
509 * do this replacement during the second phase of the algorithm, where the
|
rlm@10
|
510 * frames are fully computed. Note that this array can contain types that
|
rlm@10
|
511 * are relative to input locals or to the input stack (see below for the
|
rlm@10
|
512 * description of the algorithm).
|
rlm@10
|
513 */
|
rlm@10
|
514 private int[] initializations;
|
rlm@10
|
515
|
rlm@10
|
516 /**
|
rlm@10
|
517 * Returns the output frame local variable type at the given index.
|
rlm@10
|
518 *
|
rlm@10
|
519 * @param local the index of the local that must be returned.
|
rlm@10
|
520 * @return the output frame local variable type at the given index.
|
rlm@10
|
521 */
|
rlm@10
|
522 private int get(final int local){
|
rlm@10
|
523 if(outputLocals == null || local >= outputLocals.length)
|
rlm@10
|
524 {
|
rlm@10
|
525 // this local has never been assigned in this basic block,
|
rlm@10
|
526 // so it is still equal to its value in the input frame
|
rlm@10
|
527 return LOCAL | local;
|
rlm@10
|
528 }
|
rlm@10
|
529 else
|
rlm@10
|
530 {
|
rlm@10
|
531 int type = outputLocals[local];
|
rlm@10
|
532 if(type == 0)
|
rlm@10
|
533 {
|
rlm@10
|
534 // this local has never been assigned in this basic block,
|
rlm@10
|
535 // so it is still equal to its value in the input frame
|
rlm@10
|
536 type = outputLocals[local] = LOCAL | local;
|
rlm@10
|
537 }
|
rlm@10
|
538 return type;
|
rlm@10
|
539 }
|
rlm@10
|
540 }
|
rlm@10
|
541
|
rlm@10
|
542 /**
|
rlm@10
|
543 * Sets the output frame local variable type at the given index.
|
rlm@10
|
544 *
|
rlm@10
|
545 * @param local the index of the local that must be set.
|
rlm@10
|
546 * @param type the value of the local that must be set.
|
rlm@10
|
547 */
|
rlm@10
|
548 private void set(final int local, final int type){
|
rlm@10
|
549 // creates and/or resizes the output local variables array if necessary
|
rlm@10
|
550 if(outputLocals == null)
|
rlm@10
|
551 {
|
rlm@10
|
552 outputLocals = new int[10];
|
rlm@10
|
553 }
|
rlm@10
|
554 int n = outputLocals.length;
|
rlm@10
|
555 if(local >= n)
|
rlm@10
|
556 {
|
rlm@10
|
557 int[] t = new int[Math.max(local + 1, 2 * n)];
|
rlm@10
|
558 System.arraycopy(outputLocals, 0, t, 0, n);
|
rlm@10
|
559 outputLocals = t;
|
rlm@10
|
560 }
|
rlm@10
|
561 // sets the local variable
|
rlm@10
|
562 outputLocals[local] = type;
|
rlm@10
|
563 }
|
rlm@10
|
564
|
rlm@10
|
565 /**
|
rlm@10
|
566 * Pushes a new type onto the output frame stack.
|
rlm@10
|
567 *
|
rlm@10
|
568 * @param type the type that must be pushed.
|
rlm@10
|
569 */
|
rlm@10
|
570 private void push(final int type){
|
rlm@10
|
571 // creates and/or resizes the output stack array if necessary
|
rlm@10
|
572 if(outputStack == null)
|
rlm@10
|
573 {
|
rlm@10
|
574 outputStack = new int[10];
|
rlm@10
|
575 }
|
rlm@10
|
576 int n = outputStack.length;
|
rlm@10
|
577 if(outputStackTop >= n)
|
rlm@10
|
578 {
|
rlm@10
|
579 int[] t = new int[Math.max(outputStackTop + 1, 2 * n)];
|
rlm@10
|
580 System.arraycopy(outputStack, 0, t, 0, n);
|
rlm@10
|
581 outputStack = t;
|
rlm@10
|
582 }
|
rlm@10
|
583 // pushes the type on the output stack
|
rlm@10
|
584 outputStack[outputStackTop++] = type;
|
rlm@10
|
585 // updates the maximun height reached by the output stack, if needed
|
rlm@10
|
586 int top = owner.inputStackTop + outputStackTop;
|
rlm@10
|
587 if(top > owner.outputStackMax)
|
rlm@10
|
588 {
|
rlm@10
|
589 owner.outputStackMax = top;
|
rlm@10
|
590 }
|
rlm@10
|
591 }
|
rlm@10
|
592
|
rlm@10
|
593 /**
|
rlm@10
|
594 * Pushes a new type onto the output frame stack.
|
rlm@10
|
595 *
|
rlm@10
|
596 * @param cw the ClassWriter to which this label belongs.
|
rlm@10
|
597 * @param desc the descriptor of the type to be pushed. Can also be a method
|
rlm@10
|
598 * descriptor (in this case this method pushes its return type onto
|
rlm@10
|
599 * the output frame stack).
|
rlm@10
|
600 */
|
rlm@10
|
601 private void push(final ClassWriter cw, final String desc){
|
rlm@10
|
602 int type = type(cw, desc);
|
rlm@10
|
603 if(type != 0)
|
rlm@10
|
604 {
|
rlm@10
|
605 push(type);
|
rlm@10
|
606 if(type == LONG || type == DOUBLE)
|
rlm@10
|
607 {
|
rlm@10
|
608 push(TOP);
|
rlm@10
|
609 }
|
rlm@10
|
610 }
|
rlm@10
|
611 }
|
rlm@10
|
612
|
rlm@10
|
613 /**
|
rlm@10
|
614 * Returns the int encoding of the given type.
|
rlm@10
|
615 *
|
rlm@10
|
616 * @param cw the ClassWriter to which this label belongs.
|
rlm@10
|
617 * @param desc a type descriptor.
|
rlm@10
|
618 * @return the int encoding of the given type.
|
rlm@10
|
619 */
|
rlm@10
|
620 private int type(final ClassWriter cw, final String desc){
|
rlm@10
|
621 String t;
|
rlm@10
|
622 int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
|
rlm@10
|
623 switch(desc.charAt(index))
|
rlm@10
|
624 {
|
rlm@10
|
625 case'V':
|
rlm@10
|
626 return 0;
|
rlm@10
|
627 case'Z':
|
rlm@10
|
628 case'C':
|
rlm@10
|
629 case'B':
|
rlm@10
|
630 case'S':
|
rlm@10
|
631 case'I':
|
rlm@10
|
632 return INTEGER;
|
rlm@10
|
633 case'F':
|
rlm@10
|
634 return FLOAT;
|
rlm@10
|
635 case'J':
|
rlm@10
|
636 return LONG;
|
rlm@10
|
637 case'D':
|
rlm@10
|
638 return DOUBLE;
|
rlm@10
|
639 case'L':
|
rlm@10
|
640 // stores the internal name, not the descriptor!
|
rlm@10
|
641 t = desc.substring(index + 1, desc.length() - 1);
|
rlm@10
|
642 return OBJECT | cw.addType(t);
|
rlm@10
|
643 // case '[':
|
rlm@10
|
644 default:
|
rlm@10
|
645 // extracts the dimensions and the element type
|
rlm@10
|
646 int data;
|
rlm@10
|
647 int dims = index + 1;
|
rlm@10
|
648 while(desc.charAt(dims) == '[')
|
rlm@10
|
649 {
|
rlm@10
|
650 ++dims;
|
rlm@10
|
651 }
|
rlm@10
|
652 switch(desc.charAt(dims))
|
rlm@10
|
653 {
|
rlm@10
|
654 case'Z':
|
rlm@10
|
655 data = BOOLEAN;
|
rlm@10
|
656 break;
|
rlm@10
|
657 case'C':
|
rlm@10
|
658 data = CHAR;
|
rlm@10
|
659 break;
|
rlm@10
|
660 case'B':
|
rlm@10
|
661 data = BYTE;
|
rlm@10
|
662 break;
|
rlm@10
|
663 case'S':
|
rlm@10
|
664 data = SHORT;
|
rlm@10
|
665 break;
|
rlm@10
|
666 case'I':
|
rlm@10
|
667 data = INTEGER;
|
rlm@10
|
668 break;
|
rlm@10
|
669 case'F':
|
rlm@10
|
670 data = FLOAT;
|
rlm@10
|
671 break;
|
rlm@10
|
672 case'J':
|
rlm@10
|
673 data = LONG;
|
rlm@10
|
674 break;
|
rlm@10
|
675 case'D':
|
rlm@10
|
676 data = DOUBLE;
|
rlm@10
|
677 break;
|
rlm@10
|
678 // case 'L':
|
rlm@10
|
679 default:
|
rlm@10
|
680 // stores the internal name, not the descriptor
|
rlm@10
|
681 t = desc.substring(dims + 1, desc.length() - 1);
|
rlm@10
|
682 data = OBJECT | cw.addType(t);
|
rlm@10
|
683 }
|
rlm@10
|
684 return (dims - index) << 28 | data;
|
rlm@10
|
685 }
|
rlm@10
|
686 }
|
rlm@10
|
687
|
rlm@10
|
688 /**
|
rlm@10
|
689 * Pops a type from the output frame stack and returns its value.
|
rlm@10
|
690 *
|
rlm@10
|
691 * @return the type that has been popped from the output frame stack.
|
rlm@10
|
692 */
|
rlm@10
|
693 private int pop(){
|
rlm@10
|
694 if(outputStackTop > 0)
|
rlm@10
|
695 {
|
rlm@10
|
696 return outputStack[--outputStackTop];
|
rlm@10
|
697 }
|
rlm@10
|
698 else
|
rlm@10
|
699 {
|
rlm@10
|
700 // if the output frame stack is empty, pops from the input stack
|
rlm@10
|
701 return STACK | -(--owner.inputStackTop);
|
rlm@10
|
702 }
|
rlm@10
|
703 }
|
rlm@10
|
704
|
rlm@10
|
705 /**
|
rlm@10
|
706 * Pops the given number of types from the output frame stack.
|
rlm@10
|
707 *
|
rlm@10
|
708 * @param elements the number of types that must be popped.
|
rlm@10
|
709 */
|
rlm@10
|
710 private void pop(final int elements){
|
rlm@10
|
711 if(outputStackTop >= elements)
|
rlm@10
|
712 {
|
rlm@10
|
713 outputStackTop -= elements;
|
rlm@10
|
714 }
|
rlm@10
|
715 else
|
rlm@10
|
716 {
|
rlm@10
|
717 // if the number of elements to be popped is greater than the number
|
rlm@10
|
718 // of elements in the output stack, clear it, and pops the remaining
|
rlm@10
|
719 // elements from the input stack.
|
rlm@10
|
720 owner.inputStackTop -= elements - outputStackTop;
|
rlm@10
|
721 outputStackTop = 0;
|
rlm@10
|
722 }
|
rlm@10
|
723 }
|
rlm@10
|
724
|
rlm@10
|
725 /**
|
rlm@10
|
726 * Pops a type from the output frame stack.
|
rlm@10
|
727 *
|
rlm@10
|
728 * @param desc the descriptor of the type to be popped. Can also be a method
|
rlm@10
|
729 * descriptor (in this case this method pops the types corresponding
|
rlm@10
|
730 * to the method arguments).
|
rlm@10
|
731 */
|
rlm@10
|
732 private void pop(final String desc){
|
rlm@10
|
733 char c = desc.charAt(0);
|
rlm@10
|
734 if(c == '(')
|
rlm@10
|
735 {
|
rlm@10
|
736 pop((MethodWriter.getArgumentsAndReturnSizes(desc) >> 2) - 1);
|
rlm@10
|
737 }
|
rlm@10
|
738 else if(c == 'J' || c == 'D')
|
rlm@10
|
739 {
|
rlm@10
|
740 pop(2);
|
rlm@10
|
741 }
|
rlm@10
|
742 else
|
rlm@10
|
743 {
|
rlm@10
|
744 pop(1);
|
rlm@10
|
745 }
|
rlm@10
|
746 }
|
rlm@10
|
747
|
rlm@10
|
748 /**
|
rlm@10
|
749 * Adds a new type to the list of types on which a constructor is invoked in
|
rlm@10
|
750 * the basic block.
|
rlm@10
|
751 *
|
rlm@10
|
752 * @param var a type on a which a constructor is invoked.
|
rlm@10
|
753 */
|
rlm@10
|
754 private void init(final int var){
|
rlm@10
|
755 // creates and/or resizes the initializations array if necessary
|
rlm@10
|
756 if(initializations == null)
|
rlm@10
|
757 {
|
rlm@10
|
758 initializations = new int[2];
|
rlm@10
|
759 }
|
rlm@10
|
760 int n = initializations.length;
|
rlm@10
|
761 if(initializationCount >= n)
|
rlm@10
|
762 {
|
rlm@10
|
763 int[] t = new int[Math.max(initializationCount + 1, 2 * n)];
|
rlm@10
|
764 System.arraycopy(initializations, 0, t, 0, n);
|
rlm@10
|
765 initializations = t;
|
rlm@10
|
766 }
|
rlm@10
|
767 // stores the type to be initialized
|
rlm@10
|
768 initializations[initializationCount++] = var;
|
rlm@10
|
769 }
|
rlm@10
|
770
|
rlm@10
|
771 /**
|
rlm@10
|
772 * Replaces the given type with the appropriate type if it is one of the
|
rlm@10
|
773 * types on which a constructor is invoked in the basic block.
|
rlm@10
|
774 *
|
rlm@10
|
775 * @param cw the ClassWriter to which this label belongs.
|
rlm@10
|
776 * @param t a type
|
rlm@10
|
777 * @return t or, if t is one of the types on which a constructor is invoked
|
rlm@10
|
778 * in the basic block, the type corresponding to this constructor.
|
rlm@10
|
779 */
|
rlm@10
|
780 private int init(final ClassWriter cw, final int t){
|
rlm@10
|
781 int s;
|
rlm@10
|
782 if(t == UNINITIALIZED_THIS)
|
rlm@10
|
783 {
|
rlm@10
|
784 s = OBJECT | cw.addType(cw.thisName);
|
rlm@10
|
785 }
|
rlm@10
|
786 else if((t & (DIM | BASE_KIND)) == UNINITIALIZED)
|
rlm@10
|
787 {
|
rlm@10
|
788 String type = cw.typeTable[t & BASE_VALUE].strVal1;
|
rlm@10
|
789 s = OBJECT | cw.addType(type);
|
rlm@10
|
790 }
|
rlm@10
|
791 else
|
rlm@10
|
792 {
|
rlm@10
|
793 return t;
|
rlm@10
|
794 }
|
rlm@10
|
795 for(int j = 0; j < initializationCount; ++j)
|
rlm@10
|
796 {
|
rlm@10
|
797 int u = initializations[j];
|
rlm@10
|
798 int dim = u & DIM;
|
rlm@10
|
799 int kind = u & KIND;
|
rlm@10
|
800 if(kind == LOCAL)
|
rlm@10
|
801 {
|
rlm@10
|
802 u = dim + inputLocals[u & VALUE];
|
rlm@10
|
803 }
|
rlm@10
|
804 else if(kind == STACK)
|
rlm@10
|
805 {
|
rlm@10
|
806 u = dim + inputStack[inputStack.length - (u & VALUE)];
|
rlm@10
|
807 }
|
rlm@10
|
808 if(t == u)
|
rlm@10
|
809 {
|
rlm@10
|
810 return s;
|
rlm@10
|
811 }
|
rlm@10
|
812 }
|
rlm@10
|
813 return t;
|
rlm@10
|
814 }
|
rlm@10
|
815
|
rlm@10
|
816 /**
|
rlm@10
|
817 * Initializes the input frame of the first basic block from the method
|
rlm@10
|
818 * descriptor.
|
rlm@10
|
819 *
|
rlm@10
|
820 * @param cw the ClassWriter to which this label belongs.
|
rlm@10
|
821 * @param access the access flags of the method to which this label belongs.
|
rlm@10
|
822 * @param args the formal parameter types of this method.
|
rlm@10
|
823 * @param maxLocals the maximum number of local variables of this method.
|
rlm@10
|
824 */
|
rlm@10
|
825 void initInputFrame(
|
rlm@10
|
826 final ClassWriter cw,
|
rlm@10
|
827 final int access,
|
rlm@10
|
828 final Type[] args,
|
rlm@10
|
829 final int maxLocals){
|
rlm@10
|
830 inputLocals = new int[maxLocals];
|
rlm@10
|
831 inputStack = new int[0];
|
rlm@10
|
832 int i = 0;
|
rlm@10
|
833 if((access & Opcodes.ACC_STATIC) == 0)
|
rlm@10
|
834 {
|
rlm@10
|
835 if((access & MethodWriter.ACC_CONSTRUCTOR) == 0)
|
rlm@10
|
836 {
|
rlm@10
|
837 inputLocals[i++] = OBJECT | cw.addType(cw.thisName);
|
rlm@10
|
838 }
|
rlm@10
|
839 else
|
rlm@10
|
840 {
|
rlm@10
|
841 inputLocals[i++] = UNINITIALIZED_THIS;
|
rlm@10
|
842 }
|
rlm@10
|
843 }
|
rlm@10
|
844 for(int j = 0; j < args.length; ++j)
|
rlm@10
|
845 {
|
rlm@10
|
846 int t = type(cw, args[j].getDescriptor());
|
rlm@10
|
847 inputLocals[i++] = t;
|
rlm@10
|
848 if(t == LONG || t == DOUBLE)
|
rlm@10
|
849 {
|
rlm@10
|
850 inputLocals[i++] = TOP;
|
rlm@10
|
851 }
|
rlm@10
|
852 }
|
rlm@10
|
853 while(i < maxLocals)
|
rlm@10
|
854 {
|
rlm@10
|
855 inputLocals[i++] = TOP;
|
rlm@10
|
856 }
|
rlm@10
|
857 }
|
rlm@10
|
858
|
rlm@10
|
859 /**
|
rlm@10
|
860 * Simulates the action of the given instruction on the output stack frame.
|
rlm@10
|
861 *
|
rlm@10
|
862 * @param opcode the opcode of the instruction.
|
rlm@10
|
863 * @param arg the operand of the instruction, if any.
|
rlm@10
|
864 * @param cw the class writer to which this label belongs.
|
rlm@10
|
865 * @param item the operand of the instructions, if any.
|
rlm@10
|
866 */
|
rlm@10
|
867 void execute(
|
rlm@10
|
868 final int opcode,
|
rlm@10
|
869 final int arg,
|
rlm@10
|
870 final ClassWriter cw,
|
rlm@10
|
871 final Item item){
|
rlm@10
|
872 int t1, t2, t3, t4;
|
rlm@10
|
873 switch(opcode)
|
rlm@10
|
874 {
|
rlm@10
|
875 case Opcodes.NOP:
|
rlm@10
|
876 case Opcodes.INEG:
|
rlm@10
|
877 case Opcodes.LNEG:
|
rlm@10
|
878 case Opcodes.FNEG:
|
rlm@10
|
879 case Opcodes.DNEG:
|
rlm@10
|
880 case Opcodes.I2B:
|
rlm@10
|
881 case Opcodes.I2C:
|
rlm@10
|
882 case Opcodes.I2S:
|
rlm@10
|
883 case Opcodes.GOTO:
|
rlm@10
|
884 case Opcodes.RETURN:
|
rlm@10
|
885 break;
|
rlm@10
|
886 case Opcodes.ACONST_NULL:
|
rlm@10
|
887 push(NULL);
|
rlm@10
|
888 break;
|
rlm@10
|
889 case Opcodes.ICONST_M1:
|
rlm@10
|
890 case Opcodes.ICONST_0:
|
rlm@10
|
891 case Opcodes.ICONST_1:
|
rlm@10
|
892 case Opcodes.ICONST_2:
|
rlm@10
|
893 case Opcodes.ICONST_3:
|
rlm@10
|
894 case Opcodes.ICONST_4:
|
rlm@10
|
895 case Opcodes.ICONST_5:
|
rlm@10
|
896 case Opcodes.BIPUSH:
|
rlm@10
|
897 case Opcodes.SIPUSH:
|
rlm@10
|
898 case Opcodes.ILOAD:
|
rlm@10
|
899 push(INTEGER);
|
rlm@10
|
900 break;
|
rlm@10
|
901 case Opcodes.LCONST_0:
|
rlm@10
|
902 case Opcodes.LCONST_1:
|
rlm@10
|
903 case Opcodes.LLOAD:
|
rlm@10
|
904 push(LONG);
|
rlm@10
|
905 push(TOP);
|
rlm@10
|
906 break;
|
rlm@10
|
907 case Opcodes.FCONST_0:
|
rlm@10
|
908 case Opcodes.FCONST_1:
|
rlm@10
|
909 case Opcodes.FCONST_2:
|
rlm@10
|
910 case Opcodes.FLOAD:
|
rlm@10
|
911 push(FLOAT);
|
rlm@10
|
912 break;
|
rlm@10
|
913 case Opcodes.DCONST_0:
|
rlm@10
|
914 case Opcodes.DCONST_1:
|
rlm@10
|
915 case Opcodes.DLOAD:
|
rlm@10
|
916 push(DOUBLE);
|
rlm@10
|
917 push(TOP);
|
rlm@10
|
918 break;
|
rlm@10
|
919 case Opcodes.LDC:
|
rlm@10
|
920 switch(item.type)
|
rlm@10
|
921 {
|
rlm@10
|
922 case ClassWriter.INT:
|
rlm@10
|
923 push(INTEGER);
|
rlm@10
|
924 break;
|
rlm@10
|
925 case ClassWriter.LONG:
|
rlm@10
|
926 push(LONG);
|
rlm@10
|
927 push(TOP);
|
rlm@10
|
928 break;
|
rlm@10
|
929 case ClassWriter.FLOAT:
|
rlm@10
|
930 push(FLOAT);
|
rlm@10
|
931 break;
|
rlm@10
|
932 case ClassWriter.DOUBLE:
|
rlm@10
|
933 push(DOUBLE);
|
rlm@10
|
934 push(TOP);
|
rlm@10
|
935 break;
|
rlm@10
|
936 case ClassWriter.CLASS:
|
rlm@10
|
937 push(OBJECT | cw.addType("java/lang/Class"));
|
rlm@10
|
938 break;
|
rlm@10
|
939 // case ClassWriter.STR:
|
rlm@10
|
940 default:
|
rlm@10
|
941 push(OBJECT | cw.addType("java/lang/String"));
|
rlm@10
|
942 }
|
rlm@10
|
943 break;
|
rlm@10
|
944 case Opcodes.ALOAD:
|
rlm@10
|
945 push(get(arg));
|
rlm@10
|
946 break;
|
rlm@10
|
947 case Opcodes.IALOAD:
|
rlm@10
|
948 case Opcodes.BALOAD:
|
rlm@10
|
949 case Opcodes.CALOAD:
|
rlm@10
|
950 case Opcodes.SALOAD:
|
rlm@10
|
951 pop(2);
|
rlm@10
|
952 push(INTEGER);
|
rlm@10
|
953 break;
|
rlm@10
|
954 case Opcodes.LALOAD:
|
rlm@10
|
955 case Opcodes.D2L:
|
rlm@10
|
956 pop(2);
|
rlm@10
|
957 push(LONG);
|
rlm@10
|
958 push(TOP);
|
rlm@10
|
959 break;
|
rlm@10
|
960 case Opcodes.FALOAD:
|
rlm@10
|
961 pop(2);
|
rlm@10
|
962 push(FLOAT);
|
rlm@10
|
963 break;
|
rlm@10
|
964 case Opcodes.DALOAD:
|
rlm@10
|
965 case Opcodes.L2D:
|
rlm@10
|
966 pop(2);
|
rlm@10
|
967 push(DOUBLE);
|
rlm@10
|
968 push(TOP);
|
rlm@10
|
969 break;
|
rlm@10
|
970 case Opcodes.AALOAD:
|
rlm@10
|
971 pop(1);
|
rlm@10
|
972 t1 = pop();
|
rlm@10
|
973 push(ELEMENT_OF + t1);
|
rlm@10
|
974 break;
|
rlm@10
|
975 case Opcodes.ISTORE:
|
rlm@10
|
976 case Opcodes.FSTORE:
|
rlm@10
|
977 case Opcodes.ASTORE:
|
rlm@10
|
978 t1 = pop();
|
rlm@10
|
979 set(arg, t1);
|
rlm@10
|
980 if(arg > 0)
|
rlm@10
|
981 {
|
rlm@10
|
982 t2 = get(arg - 1);
|
rlm@10
|
983 // if t2 is of kind STACK or LOCAL we cannot know its size!
|
rlm@10
|
984 if(t2 == LONG || t2 == DOUBLE)
|
rlm@10
|
985 {
|
rlm@10
|
986 set(arg - 1, TOP);
|
rlm@10
|
987 }
|
rlm@10
|
988 }
|
rlm@10
|
989 break;
|
rlm@10
|
990 case Opcodes.LSTORE:
|
rlm@10
|
991 case Opcodes.DSTORE:
|
rlm@10
|
992 pop(1);
|
rlm@10
|
993 t1 = pop();
|
rlm@10
|
994 set(arg, t1);
|
rlm@10
|
995 set(arg + 1, TOP);
|
rlm@10
|
996 if(arg > 0)
|
rlm@10
|
997 {
|
rlm@10
|
998 t2 = get(arg - 1);
|
rlm@10
|
999 // if t2 is of kind STACK or LOCAL we cannot know its size!
|
rlm@10
|
1000 if(t2 == LONG || t2 == DOUBLE)
|
rlm@10
|
1001 {
|
rlm@10
|
1002 set(arg - 1, TOP);
|
rlm@10
|
1003 }
|
rlm@10
|
1004 }
|
rlm@10
|
1005 break;
|
rlm@10
|
1006 case Opcodes.IASTORE:
|
rlm@10
|
1007 case Opcodes.BASTORE:
|
rlm@10
|
1008 case Opcodes.CASTORE:
|
rlm@10
|
1009 case Opcodes.SASTORE:
|
rlm@10
|
1010 case Opcodes.FASTORE:
|
rlm@10
|
1011 case Opcodes.AASTORE:
|
rlm@10
|
1012 pop(3);
|
rlm@10
|
1013 break;
|
rlm@10
|
1014 case Opcodes.LASTORE:
|
rlm@10
|
1015 case Opcodes.DASTORE:
|
rlm@10
|
1016 pop(4);
|
rlm@10
|
1017 break;
|
rlm@10
|
1018 case Opcodes.POP:
|
rlm@10
|
1019 case Opcodes.IFEQ:
|
rlm@10
|
1020 case Opcodes.IFNE:
|
rlm@10
|
1021 case Opcodes.IFLT:
|
rlm@10
|
1022 case Opcodes.IFGE:
|
rlm@10
|
1023 case Opcodes.IFGT:
|
rlm@10
|
1024 case Opcodes.IFLE:
|
rlm@10
|
1025 case Opcodes.IRETURN:
|
rlm@10
|
1026 case Opcodes.FRETURN:
|
rlm@10
|
1027 case Opcodes.ARETURN:
|
rlm@10
|
1028 case Opcodes.TABLESWITCH:
|
rlm@10
|
1029 case Opcodes.LOOKUPSWITCH:
|
rlm@10
|
1030 case Opcodes.ATHROW:
|
rlm@10
|
1031 case Opcodes.MONITORENTER:
|
rlm@10
|
1032 case Opcodes.MONITOREXIT:
|
rlm@10
|
1033 case Opcodes.IFNULL:
|
rlm@10
|
1034 case Opcodes.IFNONNULL:
|
rlm@10
|
1035 pop(1);
|
rlm@10
|
1036 break;
|
rlm@10
|
1037 case Opcodes.POP2:
|
rlm@10
|
1038 case Opcodes.IF_ICMPEQ:
|
rlm@10
|
1039 case Opcodes.IF_ICMPNE:
|
rlm@10
|
1040 case Opcodes.IF_ICMPLT:
|
rlm@10
|
1041 case Opcodes.IF_ICMPGE:
|
rlm@10
|
1042 case Opcodes.IF_ICMPGT:
|
rlm@10
|
1043 case Opcodes.IF_ICMPLE:
|
rlm@10
|
1044 case Opcodes.IF_ACMPEQ:
|
rlm@10
|
1045 case Opcodes.IF_ACMPNE:
|
rlm@10
|
1046 case Opcodes.LRETURN:
|
rlm@10
|
1047 case Opcodes.DRETURN:
|
rlm@10
|
1048 pop(2);
|
rlm@10
|
1049 break;
|
rlm@10
|
1050 case Opcodes.DUP:
|
rlm@10
|
1051 t1 = pop();
|
rlm@10
|
1052 push(t1);
|
rlm@10
|
1053 push(t1);
|
rlm@10
|
1054 break;
|
rlm@10
|
1055 case Opcodes.DUP_X1:
|
rlm@10
|
1056 t1 = pop();
|
rlm@10
|
1057 t2 = pop();
|
rlm@10
|
1058 push(t1);
|
rlm@10
|
1059 push(t2);
|
rlm@10
|
1060 push(t1);
|
rlm@10
|
1061 break;
|
rlm@10
|
1062 case Opcodes.DUP_X2:
|
rlm@10
|
1063 t1 = pop();
|
rlm@10
|
1064 t2 = pop();
|
rlm@10
|
1065 t3 = pop();
|
rlm@10
|
1066 push(t1);
|
rlm@10
|
1067 push(t3);
|
rlm@10
|
1068 push(t2);
|
rlm@10
|
1069 push(t1);
|
rlm@10
|
1070 break;
|
rlm@10
|
1071 case Opcodes.DUP2:
|
rlm@10
|
1072 t1 = pop();
|
rlm@10
|
1073 t2 = pop();
|
rlm@10
|
1074 push(t2);
|
rlm@10
|
1075 push(t1);
|
rlm@10
|
1076 push(t2);
|
rlm@10
|
1077 push(t1);
|
rlm@10
|
1078 break;
|
rlm@10
|
1079 case Opcodes.DUP2_X1:
|
rlm@10
|
1080 t1 = pop();
|
rlm@10
|
1081 t2 = pop();
|
rlm@10
|
1082 t3 = pop();
|
rlm@10
|
1083 push(t2);
|
rlm@10
|
1084 push(t1);
|
rlm@10
|
1085 push(t3);
|
rlm@10
|
1086 push(t2);
|
rlm@10
|
1087 push(t1);
|
rlm@10
|
1088 break;
|
rlm@10
|
1089 case Opcodes.DUP2_X2:
|
rlm@10
|
1090 t1 = pop();
|
rlm@10
|
1091 t2 = pop();
|
rlm@10
|
1092 t3 = pop();
|
rlm@10
|
1093 t4 = pop();
|
rlm@10
|
1094 push(t2);
|
rlm@10
|
1095 push(t1);
|
rlm@10
|
1096 push(t4);
|
rlm@10
|
1097 push(t3);
|
rlm@10
|
1098 push(t2);
|
rlm@10
|
1099 push(t1);
|
rlm@10
|
1100 break;
|
rlm@10
|
1101 case Opcodes.SWAP:
|
rlm@10
|
1102 t1 = pop();
|
rlm@10
|
1103 t2 = pop();
|
rlm@10
|
1104 push(t1);
|
rlm@10
|
1105 push(t2);
|
rlm@10
|
1106 break;
|
rlm@10
|
1107 case Opcodes.IADD:
|
rlm@10
|
1108 case Opcodes.ISUB:
|
rlm@10
|
1109 case Opcodes.IMUL:
|
rlm@10
|
1110 case Opcodes.IDIV:
|
rlm@10
|
1111 case Opcodes.IREM:
|
rlm@10
|
1112 case Opcodes.IAND:
|
rlm@10
|
1113 case Opcodes.IOR:
|
rlm@10
|
1114 case Opcodes.IXOR:
|
rlm@10
|
1115 case Opcodes.ISHL:
|
rlm@10
|
1116 case Opcodes.ISHR:
|
rlm@10
|
1117 case Opcodes.IUSHR:
|
rlm@10
|
1118 case Opcodes.L2I:
|
rlm@10
|
1119 case Opcodes.D2I:
|
rlm@10
|
1120 case Opcodes.FCMPL:
|
rlm@10
|
1121 case Opcodes.FCMPG:
|
rlm@10
|
1122 pop(2);
|
rlm@10
|
1123 push(INTEGER);
|
rlm@10
|
1124 break;
|
rlm@10
|
1125 case Opcodes.LADD:
|
rlm@10
|
1126 case Opcodes.LSUB:
|
rlm@10
|
1127 case Opcodes.LMUL:
|
rlm@10
|
1128 case Opcodes.LDIV:
|
rlm@10
|
1129 case Opcodes.LREM:
|
rlm@10
|
1130 case Opcodes.LAND:
|
rlm@10
|
1131 case Opcodes.LOR:
|
rlm@10
|
1132 case Opcodes.LXOR:
|
rlm@10
|
1133 pop(4);
|
rlm@10
|
1134 push(LONG);
|
rlm@10
|
1135 push(TOP);
|
rlm@10
|
1136 break;
|
rlm@10
|
1137 case Opcodes.FADD:
|
rlm@10
|
1138 case Opcodes.FSUB:
|
rlm@10
|
1139 case Opcodes.FMUL:
|
rlm@10
|
1140 case Opcodes.FDIV:
|
rlm@10
|
1141 case Opcodes.FREM:
|
rlm@10
|
1142 case Opcodes.L2F:
|
rlm@10
|
1143 case Opcodes.D2F:
|
rlm@10
|
1144 pop(2);
|
rlm@10
|
1145 push(FLOAT);
|
rlm@10
|
1146 break;
|
rlm@10
|
1147 case Opcodes.DADD:
|
rlm@10
|
1148 case Opcodes.DSUB:
|
rlm@10
|
1149 case Opcodes.DMUL:
|
rlm@10
|
1150 case Opcodes.DDIV:
|
rlm@10
|
1151 case Opcodes.DREM:
|
rlm@10
|
1152 pop(4);
|
rlm@10
|
1153 push(DOUBLE);
|
rlm@10
|
1154 push(TOP);
|
rlm@10
|
1155 break;
|
rlm@10
|
1156 case Opcodes.LSHL:
|
rlm@10
|
1157 case Opcodes.LSHR:
|
rlm@10
|
1158 case Opcodes.LUSHR:
|
rlm@10
|
1159 pop(3);
|
rlm@10
|
1160 push(LONG);
|
rlm@10
|
1161 push(TOP);
|
rlm@10
|
1162 break;
|
rlm@10
|
1163 case Opcodes.IINC:
|
rlm@10
|
1164 set(arg, INTEGER);
|
rlm@10
|
1165 break;
|
rlm@10
|
1166 case Opcodes.I2L:
|
rlm@10
|
1167 case Opcodes.F2L:
|
rlm@10
|
1168 pop(1);
|
rlm@10
|
1169 push(LONG);
|
rlm@10
|
1170 push(TOP);
|
rlm@10
|
1171 break;
|
rlm@10
|
1172 case Opcodes.I2F:
|
rlm@10
|
1173 pop(1);
|
rlm@10
|
1174 push(FLOAT);
|
rlm@10
|
1175 break;
|
rlm@10
|
1176 case Opcodes.I2D:
|
rlm@10
|
1177 case Opcodes.F2D:
|
rlm@10
|
1178 pop(1);
|
rlm@10
|
1179 push(DOUBLE);
|
rlm@10
|
1180 push(TOP);
|
rlm@10
|
1181 break;
|
rlm@10
|
1182 case Opcodes.F2I:
|
rlm@10
|
1183 case Opcodes.ARRAYLENGTH:
|
rlm@10
|
1184 case Opcodes.INSTANCEOF:
|
rlm@10
|
1185 pop(1);
|
rlm@10
|
1186 push(INTEGER);
|
rlm@10
|
1187 break;
|
rlm@10
|
1188 case Opcodes.LCMP:
|
rlm@10
|
1189 case Opcodes.DCMPL:
|
rlm@10
|
1190 case Opcodes.DCMPG:
|
rlm@10
|
1191 pop(4);
|
rlm@10
|
1192 push(INTEGER);
|
rlm@10
|
1193 break;
|
rlm@10
|
1194 case Opcodes.JSR:
|
rlm@10
|
1195 case Opcodes.RET:
|
rlm@10
|
1196 throw new RuntimeException("JSR/RET are not supported with computeFrames option");
|
rlm@10
|
1197 case Opcodes.GETSTATIC:
|
rlm@10
|
1198 push(cw, item.strVal3);
|
rlm@10
|
1199 break;
|
rlm@10
|
1200 case Opcodes.PUTSTATIC:
|
rlm@10
|
1201 pop(item.strVal3);
|
rlm@10
|
1202 break;
|
rlm@10
|
1203 case Opcodes.GETFIELD:
|
rlm@10
|
1204 pop(1);
|
rlm@10
|
1205 push(cw, item.strVal3);
|
rlm@10
|
1206 break;
|
rlm@10
|
1207 case Opcodes.PUTFIELD:
|
rlm@10
|
1208 pop(item.strVal3);
|
rlm@10
|
1209 pop();
|
rlm@10
|
1210 break;
|
rlm@10
|
1211 case Opcodes.INVOKEVIRTUAL:
|
rlm@10
|
1212 case Opcodes.INVOKESPECIAL:
|
rlm@10
|
1213 case Opcodes.INVOKESTATIC:
|
rlm@10
|
1214 case Opcodes.INVOKEINTERFACE:
|
rlm@10
|
1215 pop(item.strVal3);
|
rlm@10
|
1216 if(opcode != Opcodes.INVOKESTATIC)
|
rlm@10
|
1217 {
|
rlm@10
|
1218 t1 = pop();
|
rlm@10
|
1219 if(opcode == Opcodes.INVOKESPECIAL
|
rlm@10
|
1220 && item.strVal2.charAt(0) == '<')
|
rlm@10
|
1221 {
|
rlm@10
|
1222 init(t1);
|
rlm@10
|
1223 }
|
rlm@10
|
1224 }
|
rlm@10
|
1225 push(cw, item.strVal3);
|
rlm@10
|
1226 break;
|
rlm@10
|
1227 case Opcodes.NEW:
|
rlm@10
|
1228 push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
|
rlm@10
|
1229 break;
|
rlm@10
|
1230 case Opcodes.NEWARRAY:
|
rlm@10
|
1231 pop();
|
rlm@10
|
1232 switch(arg)
|
rlm@10
|
1233 {
|
rlm@10
|
1234 case Opcodes.T_BOOLEAN:
|
rlm@10
|
1235 push(ARRAY_OF | BOOLEAN);
|
rlm@10
|
1236 break;
|
rlm@10
|
1237 case Opcodes.T_CHAR:
|
rlm@10
|
1238 push(ARRAY_OF | CHAR);
|
rlm@10
|
1239 break;
|
rlm@10
|
1240 case Opcodes.T_BYTE:
|
rlm@10
|
1241 push(ARRAY_OF | BYTE);
|
rlm@10
|
1242 break;
|
rlm@10
|
1243 case Opcodes.T_SHORT:
|
rlm@10
|
1244 push(ARRAY_OF | SHORT);
|
rlm@10
|
1245 break;
|
rlm@10
|
1246 case Opcodes.T_INT:
|
rlm@10
|
1247 push(ARRAY_OF | INTEGER);
|
rlm@10
|
1248 break;
|
rlm@10
|
1249 case Opcodes.T_FLOAT:
|
rlm@10
|
1250 push(ARRAY_OF | FLOAT);
|
rlm@10
|
1251 break;
|
rlm@10
|
1252 case Opcodes.T_DOUBLE:
|
rlm@10
|
1253 push(ARRAY_OF | DOUBLE);
|
rlm@10
|
1254 break;
|
rlm@10
|
1255 // case Opcodes.T_LONG:
|
rlm@10
|
1256 default:
|
rlm@10
|
1257 push(ARRAY_OF | LONG);
|
rlm@10
|
1258 break;
|
rlm@10
|
1259 }
|
rlm@10
|
1260 break;
|
rlm@10
|
1261 case Opcodes.ANEWARRAY:
|
rlm@10
|
1262 String s = item.strVal1;
|
rlm@10
|
1263 pop();
|
rlm@10
|
1264 if(s.charAt(0) == '[')
|
rlm@10
|
1265 {
|
rlm@10
|
1266 push(cw, "[" + s);
|
rlm@10
|
1267 }
|
rlm@10
|
1268 else
|
rlm@10
|
1269 {
|
rlm@10
|
1270 push(ARRAY_OF | OBJECT | cw.addType(s));
|
rlm@10
|
1271 }
|
rlm@10
|
1272 break;
|
rlm@10
|
1273 case Opcodes.CHECKCAST:
|
rlm@10
|
1274 s = item.strVal1;
|
rlm@10
|
1275 pop();
|
rlm@10
|
1276 if(s.charAt(0) == '[')
|
rlm@10
|
1277 {
|
rlm@10
|
1278 push(cw, s);
|
rlm@10
|
1279 }
|
rlm@10
|
1280 else
|
rlm@10
|
1281 {
|
rlm@10
|
1282 push(OBJECT | cw.addType(s));
|
rlm@10
|
1283 }
|
rlm@10
|
1284 break;
|
rlm@10
|
1285 // case Opcodes.MULTIANEWARRAY:
|
rlm@10
|
1286 default:
|
rlm@10
|
1287 pop(arg);
|
rlm@10
|
1288 push(cw, item.strVal1);
|
rlm@10
|
1289 break;
|
rlm@10
|
1290 }
|
rlm@10
|
1291 }
|
rlm@10
|
1292
|
rlm@10
|
1293 /**
|
rlm@10
|
1294 * Merges the input frame of the given basic block with the input and output
|
rlm@10
|
1295 * frames of this basic block. Returns <tt>true</tt> if the input frame of
|
rlm@10
|
1296 * the given label has been changed by this operation.
|
rlm@10
|
1297 *
|
rlm@10
|
1298 * @param cw the ClassWriter to which this label belongs.
|
rlm@10
|
1299 * @param frame the basic block whose input frame must be updated.
|
rlm@10
|
1300 * @param edge the kind of the {@link Edge} between this label and 'label'.
|
rlm@10
|
1301 * See {@link Edge#info}.
|
rlm@10
|
1302 * @return <tt>true</tt> if the input frame of the given label has been
|
rlm@10
|
1303 * changed by this operation.
|
rlm@10
|
1304 */
|
rlm@10
|
1305 boolean merge(final ClassWriter cw, final Frame frame, final int edge){
|
rlm@10
|
1306 boolean changed = false;
|
rlm@10
|
1307 int i, s, dim, kind, t;
|
rlm@10
|
1308
|
rlm@10
|
1309 int nLocal = inputLocals.length;
|
rlm@10
|
1310 int nStack = inputStack.length;
|
rlm@10
|
1311 if(frame.inputLocals == null)
|
rlm@10
|
1312 {
|
rlm@10
|
1313 frame.inputLocals = new int[nLocal];
|
rlm@10
|
1314 changed = true;
|
rlm@10
|
1315 }
|
rlm@10
|
1316
|
rlm@10
|
1317 for(i = 0; i < nLocal; ++i)
|
rlm@10
|
1318 {
|
rlm@10
|
1319 if(outputLocals != null && i < outputLocals.length)
|
rlm@10
|
1320 {
|
rlm@10
|
1321 s = outputLocals[i];
|
rlm@10
|
1322 if(s == 0)
|
rlm@10
|
1323 {
|
rlm@10
|
1324 t = inputLocals[i];
|
rlm@10
|
1325 }
|
rlm@10
|
1326 else
|
rlm@10
|
1327 {
|
rlm@10
|
1328 dim = s & DIM;
|
rlm@10
|
1329 kind = s & KIND;
|
rlm@10
|
1330 if(kind == LOCAL)
|
rlm@10
|
1331 {
|
rlm@10
|
1332 t = dim + inputLocals[s & VALUE];
|
rlm@10
|
1333 }
|
rlm@10
|
1334 else if(kind == STACK)
|
rlm@10
|
1335 {
|
rlm@10
|
1336 t = dim + inputStack[nStack - (s & VALUE)];
|
rlm@10
|
1337 }
|
rlm@10
|
1338 else
|
rlm@10
|
1339 {
|
rlm@10
|
1340 t = s;
|
rlm@10
|
1341 }
|
rlm@10
|
1342 }
|
rlm@10
|
1343 }
|
rlm@10
|
1344 else
|
rlm@10
|
1345 {
|
rlm@10
|
1346 t = inputLocals[i];
|
rlm@10
|
1347 }
|
rlm@10
|
1348 if(initializations != null)
|
rlm@10
|
1349 {
|
rlm@10
|
1350 t = init(cw, t);
|
rlm@10
|
1351 }
|
rlm@10
|
1352 changed |= merge(cw, t, frame.inputLocals, i);
|
rlm@10
|
1353 }
|
rlm@10
|
1354
|
rlm@10
|
1355 if(edge > 0)
|
rlm@10
|
1356 {
|
rlm@10
|
1357 for(i = 0; i < nLocal; ++i)
|
rlm@10
|
1358 {
|
rlm@10
|
1359 t = inputLocals[i];
|
rlm@10
|
1360 changed |= merge(cw, t, frame.inputLocals, i);
|
rlm@10
|
1361 }
|
rlm@10
|
1362 if(frame.inputStack == null)
|
rlm@10
|
1363 {
|
rlm@10
|
1364 frame.inputStack = new int[1];
|
rlm@10
|
1365 changed = true;
|
rlm@10
|
1366 }
|
rlm@10
|
1367 changed |= merge(cw, edge, frame.inputStack, 0);
|
rlm@10
|
1368 return changed;
|
rlm@10
|
1369 }
|
rlm@10
|
1370
|
rlm@10
|
1371 int nInputStack = inputStack.length + owner.inputStackTop;
|
rlm@10
|
1372 if(frame.inputStack == null)
|
rlm@10
|
1373 {
|
rlm@10
|
1374 frame.inputStack = new int[nInputStack + outputStackTop];
|
rlm@10
|
1375 changed = true;
|
rlm@10
|
1376 }
|
rlm@10
|
1377
|
rlm@10
|
1378 for(i = 0; i < nInputStack; ++i)
|
rlm@10
|
1379 {
|
rlm@10
|
1380 t = inputStack[i];
|
rlm@10
|
1381 if(initializations != null)
|
rlm@10
|
1382 {
|
rlm@10
|
1383 t = init(cw, t);
|
rlm@10
|
1384 }
|
rlm@10
|
1385 changed |= merge(cw, t, frame.inputStack, i);
|
rlm@10
|
1386 }
|
rlm@10
|
1387 for(i = 0; i < outputStackTop; ++i)
|
rlm@10
|
1388 {
|
rlm@10
|
1389 s = outputStack[i];
|
rlm@10
|
1390 dim = s & DIM;
|
rlm@10
|
1391 kind = s & KIND;
|
rlm@10
|
1392 if(kind == LOCAL)
|
rlm@10
|
1393 {
|
rlm@10
|
1394 t = dim + inputLocals[s & VALUE];
|
rlm@10
|
1395 }
|
rlm@10
|
1396 else if(kind == STACK)
|
rlm@10
|
1397 {
|
rlm@10
|
1398 t = dim + inputStack[nStack - (s & VALUE)];
|
rlm@10
|
1399 }
|
rlm@10
|
1400 else
|
rlm@10
|
1401 {
|
rlm@10
|
1402 t = s;
|
rlm@10
|
1403 }
|
rlm@10
|
1404 if(initializations != null)
|
rlm@10
|
1405 {
|
rlm@10
|
1406 t = init(cw, t);
|
rlm@10
|
1407 }
|
rlm@10
|
1408 changed |= merge(cw, t, frame.inputStack, nInputStack + i);
|
rlm@10
|
1409 }
|
rlm@10
|
1410 return changed;
|
rlm@10
|
1411 }
|
rlm@10
|
1412
|
rlm@10
|
1413 /**
|
rlm@10
|
1414 * Merges the type at the given index in the given type array with the given
|
rlm@10
|
1415 * type. Returns <tt>true</tt> if the type array has been modified by this
|
rlm@10
|
1416 * operation.
|
rlm@10
|
1417 *
|
rlm@10
|
1418 * @param cw the ClassWriter to which this label belongs.
|
rlm@10
|
1419 * @param t the type with which the type array element must be merged.
|
rlm@10
|
1420 * @param types an array of types.
|
rlm@10
|
1421 * @param index the index of the type that must be merged in 'types'.
|
rlm@10
|
1422 * @return <tt>true</tt> if the type array has been modified by this
|
rlm@10
|
1423 * operation.
|
rlm@10
|
1424 */
|
rlm@10
|
1425 private boolean merge(
|
rlm@10
|
1426 final ClassWriter cw,
|
rlm@10
|
1427 int t,
|
rlm@10
|
1428 final int[] types,
|
rlm@10
|
1429 final int index){
|
rlm@10
|
1430 int u = types[index];
|
rlm@10
|
1431 if(u == t)
|
rlm@10
|
1432 {
|
rlm@10
|
1433 // if the types are equal, merge(u,t)=u, so there is no change
|
rlm@10
|
1434 return false;
|
rlm@10
|
1435 }
|
rlm@10
|
1436 if((t & ~DIM) == NULL)
|
rlm@10
|
1437 {
|
rlm@10
|
1438 if(u == NULL)
|
rlm@10
|
1439 {
|
rlm@10
|
1440 return false;
|
rlm@10
|
1441 }
|
rlm@10
|
1442 t = NULL;
|
rlm@10
|
1443 }
|
rlm@10
|
1444 if(u == 0)
|
rlm@10
|
1445 {
|
rlm@10
|
1446 // if types[index] has never been assigned, merge(u,t)=t
|
rlm@10
|
1447 types[index] = t;
|
rlm@10
|
1448 return true;
|
rlm@10
|
1449 }
|
rlm@10
|
1450 int v;
|
rlm@10
|
1451 if((u & BASE_KIND) == OBJECT || (u & DIM) != 0)
|
rlm@10
|
1452 {
|
rlm@10
|
1453 // if u is a reference type of any dimension
|
rlm@10
|
1454 if(t == NULL)
|
rlm@10
|
1455 {
|
rlm@10
|
1456 // if t is the NULL type, merge(u,t)=u, so there is no change
|
rlm@10
|
1457 return false;
|
rlm@10
|
1458 }
|
rlm@10
|
1459 else if((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND)))
|
rlm@10
|
1460 {
|
rlm@10
|
1461 if((u & BASE_KIND) == OBJECT)
|
rlm@10
|
1462 {
|
rlm@10
|
1463 // if t is also a reference type, and if u and t have the
|
rlm@10
|
1464 // same dimension merge(u,t) = dim(t) | common parent of the
|
rlm@10
|
1465 // element types of u and t
|
rlm@10
|
1466 v = (t & DIM) | OBJECT
|
rlm@10
|
1467 | cw.getMergedType(t & BASE_VALUE, u & BASE_VALUE);
|
rlm@10
|
1468 }
|
rlm@10
|
1469 else
|
rlm@10
|
1470 {
|
rlm@10
|
1471 // if u and t are array types, but not with the same element
|
rlm@10
|
1472 // type, merge(u,t)=java/lang/Object
|
rlm@10
|
1473 v = OBJECT | cw.addType("java/lang/Object");
|
rlm@10
|
1474 }
|
rlm@10
|
1475 }
|
rlm@10
|
1476 else if((t & BASE_KIND) == OBJECT || (t & DIM) != 0)
|
rlm@10
|
1477 {
|
rlm@10
|
1478 // if t is any other reference or array type,
|
rlm@10
|
1479 // merge(u,t)=java/lang/Object
|
rlm@10
|
1480 v = OBJECT | cw.addType("java/lang/Object");
|
rlm@10
|
1481 }
|
rlm@10
|
1482 else
|
rlm@10
|
1483 {
|
rlm@10
|
1484 // if t is any other type, merge(u,t)=TOP
|
rlm@10
|
1485 v = TOP;
|
rlm@10
|
1486 }
|
rlm@10
|
1487 }
|
rlm@10
|
1488 else if(u == NULL)
|
rlm@10
|
1489 {
|
rlm@10
|
1490 // if u is the NULL type, merge(u,t)=t,
|
rlm@10
|
1491 // or TOP if t is not a reference type
|
rlm@10
|
1492 v = (t & BASE_KIND) == OBJECT || (t & DIM) != 0 ? t : TOP;
|
rlm@10
|
1493 }
|
rlm@10
|
1494 else
|
rlm@10
|
1495 {
|
rlm@10
|
1496 // if u is any other type, merge(u,t)=TOP whatever t
|
rlm@10
|
1497 v = TOP;
|
rlm@10
|
1498 }
|
rlm@10
|
1499 if(u != v)
|
rlm@10
|
1500 {
|
rlm@10
|
1501 types[index] = v;
|
rlm@10
|
1502 return true;
|
rlm@10
|
1503 }
|
rlm@10
|
1504 return false;
|
rlm@10
|
1505 }
|
rlm@10
|
1506 }
|