view src/clojure/asm/Frame.java @ 10:ef7dbbd6452c

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