KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > asm > commons > JSRInlinerAdapterUnitTest


1 /***
2  * ASM tests
3  * Copyright (c) 2002-2005 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 org.objectweb.asm.commons;
31
32 import junit.framework.TestCase;
33
34 import org.objectweb.asm.ClassWriter;
35 import org.objectweb.asm.Label;
36 import org.objectweb.asm.MethodVisitor;
37 import org.objectweb.asm.Opcodes;
38 import org.objectweb.asm.tree.MethodNode;
39 import org.objectweb.asm.util.TraceMethodVisitor;
40
41 /**
42  * JsrInlinerTest
43  *
44  * @author Eugene Kuleshov, Niko Matsakis, Eric Bruneton
45  */

46 public class JSRInlinerAdapterUnitTest extends TestCase {
47
48     private JSRInlinerAdapter jsr;
49     private MethodNode exp;
50     private MethodVisitor current;
51
52     protected void setUp() throws Exception JavaDoc {
53         super.setUp();
54         jsr = new JSRInlinerAdapter(null, 0, "m", "()V", null, null) {
55             public void visitEnd() {
56                 System.err.println("started w/ method:" + name);
57                 TraceMethodVisitor mv = new TraceMethodVisitor();
58                 for (int i = 0; i < instructions.size(); ++i) {
59                     instructions.get(i).accept(mv);
60                     System.err.print(Integer.toString(i + 100000).substring(1));
61                     System.err.print(" : " + mv.text.get(i));
62                 }
63                 super.visitEnd();
64                 System.err.println("finished w/ method:" + name);
65             }
66         };
67         exp = new MethodNode(0, "m", "()V", null, null);
68     }
69
70     private void setCurrent(final MethodVisitor cv) {
71         this.current = cv;
72     }
73
74     private void ICONST_0() {
75         this.current.visitInsn(Opcodes.ICONST_0);
76     }
77
78     private void ISTORE(final int var) {
79         this.current.visitVarInsn(Opcodes.ISTORE, var);
80     }
81
82     private void ALOAD(final int var) {
83         this.current.visitVarInsn(Opcodes.ALOAD, var);
84     }
85
86     private void ILOAD(final int var) {
87         this.current.visitVarInsn(Opcodes.ILOAD, var);
88     }
89
90     private void ASTORE(final int var) {
91         this.current.visitVarInsn(Opcodes.ASTORE, var);
92     }
93
94     private void RET(final int var) {
95         this.current.visitVarInsn(Opcodes.RET, var);
96     }
97
98     private void ATHROW() {
99         this.current.visitInsn(Opcodes.ATHROW);
100     }
101
102     private void ACONST_NULL() {
103         this.current.visitInsn(Opcodes.ACONST_NULL);
104     }
105
106     private void RETURN() {
107         this.current.visitInsn(Opcodes.RETURN);
108     }
109
110     private void LABEL(final Label l) {
111         this.current.visitLabel(l);
112     }
113
114     private void IINC(final int var, final int amnt) {
115         this.current.visitIincInsn(var, amnt);
116     }
117
118     private void GOTO(final Label l) {
119         this.current.visitJumpInsn(Opcodes.GOTO, l);
120     }
121
122     private void JSR(final Label l) {
123         this.current.visitJumpInsn(Opcodes.JSR, l);
124     }
125
126     private void IFNONNULL(final Label l) {
127         this.current.visitJumpInsn(Opcodes.IFNONNULL, l);
128     }
129
130     private void IFNE(final Label l) {
131         this.current.visitJumpInsn(Opcodes.IFNE, l);
132     }
133
134     private void TRYCATCH(
135         final Label start,
136         final Label end,
137         final Label handler)
138     {
139         this.current.visitTryCatchBlock(start, end, handler, null);
140     }
141
142     private void LINE(final int line, final Label start) {
143         this.current.visitLineNumber(line, start);
144     }
145
146     private void LOCALVAR(
147         final String JavaDoc name,
148         final String JavaDoc desc,
149         final int index,
150         final Label start,
151         final Label end)
152     {
153         this.current.visitLocalVariable(name, desc, null, start, end, index);
154     }
155
156     private void END(final int maxStack, final int maxLocals) {
157         this.current.visitMaxs(maxStack, maxLocals);
158         this.current.visitEnd();
159         ClassWriter cw = new ClassWriter(0);
160         cw.visit(Opcodes.V1_1,
161                 Opcodes.ACC_PUBLIC,
162                 "C",
163                 null,
164                 "java/lang/Object",
165                 null);
166         MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC,
167                 "<init>",
168                 "()V",
169                 null,
170                 null);
171         mv.visitCode();
172         mv.visitVarInsn(Opcodes.ALOAD, 0);
173         mv.visitMethodInsn(Opcodes.INVOKESPECIAL,
174                 "java/lang/Object",
175                 "<init>",
176                 "()V");
177         mv.visitInsn(Opcodes.RETURN);
178         mv.visitMaxs(1, 1);
179         mv.visitEnd();
180         ((MethodNode) this.current).accept(cw);
181         cw.visitEnd();
182         byte[] b = cw.toByteArray();
183         try {
184             TestClassLoader loader = new TestClassLoader();
185             Class JavaDoc c = loader.defineClass("C", b);
186             c.newInstance();
187         } catch (Throwable JavaDoc t) {
188             fail(t.getMessage());
189         }
190         this.current = null;
191     }
192
193     static class TestClassLoader extends ClassLoader JavaDoc {
194
195         public Class JavaDoc defineClass(final String JavaDoc name, final byte[] b) {
196             return defineClass(name, b, 0, b.length);
197         }
198     }
199
200     /**
201      * Tests a method which has the most basic <code>try{}finally</code> form
202      * imaginable:
203      *
204      * <pre>
205      * public void a() {
206      * int a = 0;
207      * try {
208      * a++;
209      * } finally {
210      * a--;
211      * }
212      * }
213      * </pre>
214      */

215     public void testBasic() {
216         {
217             Label L0 = new Label();
218             Label L1 = new Label();
219             Label L2 = new Label();
220             Label L3 = new Label();
221             Label L4 = new Label();
222
223             setCurrent(jsr);
224             ICONST_0();
225             ISTORE(1);
226
227             /* L0: body of try block */
228             LABEL(L0);
229             IINC(1, 1);
230             GOTO(L1);
231
232             /* L2: exception handler */
233             LABEL(L2);
234             ASTORE(3);
235             JSR(L3);
236             ALOAD(3);
237             ATHROW();
238
239             /* L3: subroutine */
240             LABEL(L3);
241             ASTORE(2);
242             IINC(1, -1);
243             RET(2);
244
245             /* L1: non-exceptional exit from try block */
246             LABEL(L1);
247             JSR(L3);
248             LABEL(L4); // L4
249
RETURN();
250
251             TRYCATCH(L0, L2, L2);
252             TRYCATCH(L1, L4, L2);
253
254             END(1, 4);
255         }
256
257         {
258             Label L0 = new Label();
259             Label L1 = new Label();
260             Label L2 = new Label();
261             Label L3_1a = new Label();
262             Label L3_1b = new Label();
263             Label L3_2a = new Label();
264             Label L3_2b = new Label();
265             Label L4 = new Label();
266
267             setCurrent(exp);
268             ICONST_0();
269             ISTORE(1);
270             // L0: try/catch block
271
LABEL(L0);
272             IINC(1, 1);
273             GOTO(L1);
274
275             // L2: Exception handler:
276
LABEL(L2);
277             ASTORE(3);
278             ACONST_NULL();
279             GOTO(L3_1a);
280             LABEL(L3_1b); // L3_1b;
281
ALOAD(3);
282             ATHROW();
283
284             // L1: On non-exceptional exit, try block leads here:
285
LABEL(L1);
286             ACONST_NULL();
287             GOTO(L3_2a);
288             LABEL(L3_2b); // L3_2b
289
LABEL(L4); // L4
290
RETURN();
291
292             // L3_1a: First instantiation of subroutine:
293
LABEL(L3_1a);
294             ASTORE(2);
295             IINC(1, -1);
296             GOTO(L3_1b);
297             LABEL(new Label()); // extra label emitted due to impl quirks
298

299             // L3_2a: Second instantiation of subroutine:
300
LABEL(L3_2a);
301             ASTORE(2);
302             IINC(1, -1);
303             GOTO(L3_2b);
304             LABEL(new Label()); // extra label emitted due to impl quirks
305

306             TRYCATCH(L0, L2, L2);
307             TRYCATCH(L1, L4, L2);
308
309             END(1, 4);
310         }
311
312         assertEquals(exp, jsr);
313     }
314
315     /**
316      * Tests a method which has an if/else-if w/in the finally clause:
317      *
318      * <pre>
319      * public void a() {
320      * int a = 0;
321      * try {
322      * a++;
323      * } finally {
324      * if (a == 0)
325      * a+=2;
326      * else
327      * a+=3;
328      * }
329      * }
330      * </pre>
331      */

332     public void testIfElseInFinally() {
333         {
334             Label L0 = new Label();
335             Label L1 = new Label();
336             Label L2 = new Label();
337             Label L3 = new Label();
338             Label L4 = new Label();
339             Label L5 = new Label();
340             Label L6 = new Label();
341
342             setCurrent(jsr);
343             ICONST_0();
344             ISTORE(1);
345
346             /* L0: body of try block */
347             LABEL(L0);
348             IINC(1, 1);
349             GOTO(L1);
350
351             /* L2: exception handler */
352             LABEL(L2);
353             ASTORE(3);
354             JSR(L3);
355             ALOAD(3);
356             ATHROW();
357
358             /* L3: subroutine */
359             LABEL(L3);
360             ASTORE(2);
361             ILOAD(1);
362             IFNE(L4);
363             IINC(1, 2);
364             GOTO(L5);
365             LABEL(L4); // L4: a != 0
366
IINC(1, 3);
367             LABEL(L5); // L5: common exit
368
RET(2);
369
370             /* L1: non-exceptional exit from try block */
371             LABEL(L1);
372             JSR(L3);
373             LABEL(L6); // L6 is used in the TRYCATCH below
374
RETURN();
375
376             TRYCATCH(L0, L2, L2);
377             TRYCATCH(L1, L6, L2);
378
379             END(1, 4);
380         }
381
382         {
383             Label L0 = new Label();
384             Label L1 = new Label();
385             Label L2 = new Label();
386             Label L3_1a = new Label();
387             Label L3_1b = new Label();
388             Label L3_2a = new Label();
389             Label L3_2b = new Label();
390             Label L4_1 = new Label();
391             Label L4_2 = new Label();
392             Label L5_1 = new Label();
393             Label L5_2 = new Label();
394             Label L6 = new Label();
395
396             setCurrent(exp);
397             ICONST_0();
398             ISTORE(1);
399             // L0: try/catch block
400
LABEL(L0);
401             IINC(1, 1);
402             GOTO(L1);
403
404             // L2: Exception handler:
405
LABEL(L2);
406             ASTORE(3);
407             ACONST_NULL();
408             GOTO(L3_1a);
409             LABEL(L3_1b); // L3_1b;
410
ALOAD(3);
411             ATHROW();
412
413             // L1: On non-exceptional exit, try block leads here:
414
LABEL(L1);
415             ACONST_NULL();
416             GOTO(L3_2a);
417             LABEL(L3_2b); // L3_2b
418
LABEL(L6); // L6
419
RETURN();
420
421             // L3_1a: First instantiation of subroutine:
422
LABEL(L3_1a);
423             ASTORE(2);
424             ILOAD(1);
425             IFNE(L4_1);
426             IINC(1, 2);
427             GOTO(L5_1);
428             LABEL(L4_1); // L4_1: a != 0
429
IINC(1, 3);
430             LABEL(L5_1); // L5_1: common exit
431
GOTO(L3_1b);
432             LABEL(new Label()); // extra label emitted due to impl quirks
433

434             // L3_2a: First instantiation of subroutine:
435
LABEL(L3_2a);
436             ASTORE(2);
437             ILOAD(1);
438             IFNE(L4_2);
439             IINC(1, 2);
440             GOTO(L5_2);
441             LABEL(L4_2); // L4_2: a != 0
442
IINC(1, 3);
443             LABEL(L5_2); // L5_2: common exit
444
GOTO(L3_2b);
445             LABEL(new Label()); // extra label emitted due to impl quirks
446

447             TRYCATCH(L0, L2, L2);
448             TRYCATCH(L1, L6, L2);
449
450             END(1, 4);
451         }
452
453         assertEquals(exp, jsr);
454     }
455
456     /**
457      * Tests a simple nested finally:
458      *
459      * <pre>
460      * public void a1() {
461      * int a = 0;
462      * try {
463      * a += 1;
464      * } finally {
465      * try {
466      * a += 2;
467      * } finally {
468      * a += 3;
469      * }
470      * }
471      * }
472      * </pre>
473      */

474     public void testSimpleNestedFinally() {
475         {
476             Label L0 = new Label();
477             Label L1 = new Label();
478             Label L2 = new Label();
479             Label L3 = new Label();
480             Label L4 = new Label();
481             Label L5 = new Label();
482
483             setCurrent(jsr);
484
485             ICONST_0();
486             ISTORE(1);
487
488             // L0: Body of try block:
489
LABEL(L0);
490             IINC(1, 1);
491             JSR(L3);
492             GOTO(L1);
493
494             // L2: First exception handler:
495
LABEL(L2);
496             JSR(L3);
497             ATHROW();
498
499             // L3: First subroutine:
500
LABEL(L3);
501             ASTORE(2);
502             IINC(1, 2);
503             JSR(L4);
504             RET(2);
505
506             // L5: Second exception handler:
507
LABEL(L5);
508             JSR(L4);
509             ATHROW();
510
511             // L4: Second subroutine:
512
LABEL(L4);
513             ASTORE(3);
514             IINC(1, 3);
515             RET(3);
516
517             // L1: On normal exit, try block jumps here:
518
LABEL(L1);
519             RETURN();
520
521             TRYCATCH(L0, L2, L2);
522             TRYCATCH(L3, L5, L5);
523
524             END(2, 6);
525         }
526
527         {
528             Label L0 = new Label();
529             Label L1 = new Label();
530             Label L2 = new Label();
531             Label L3_1a = new Label();
532             Label L3_1b = new Label();
533             Label L3_2a = new Label();
534             Label L3_2b = new Label();
535             Label L4_1a = new Label();
536             Label L4_1b = new Label();
537             Label L4_2a = new Label();
538             Label L4_2b = new Label();
539             Label L4_3a = new Label();
540             Label L4_3b = new Label();
541             Label L4_4a = new Label();
542             Label L4_4b = new Label();
543             Label L5_1 = new Label();
544             Label L5_2 = new Label();
545
546             setCurrent(exp);
547
548             ICONST_0();
549             ISTORE(1);
550
551             // L0: Body of try block:
552
LABEL(L0);
553             IINC(1, 1);
554             ACONST_NULL();
555             GOTO(L3_1a);
556             LABEL(L3_1b); // L3_1b
557
GOTO(L1);
558
559             // L2: First exception handler:
560
LABEL(L2);
561             ACONST_NULL();
562             GOTO(L3_2a);
563             LABEL(L3_2b); // L3_2b
564
ATHROW();
565
566             // L1: On normal exit, try block jumps here:
567
LABEL(L1);
568             RETURN();
569
570             // L3_1a: First instantiation of first subroutine:
571
LABEL(L3_1a);
572             ASTORE(2);
573             IINC(1, 2);
574             ACONST_NULL();
575             GOTO(L4_1a);
576             LABEL(L4_1b); // L4_1b
577
GOTO(L3_1b);
578             LABEL(L5_1); // L5_1
579
ACONST_NULL();
580             GOTO(L4_2a);
581             LABEL(L4_2b); // L4_2b
582
ATHROW();
583             LABEL(new Label()); // extra label emitted due to impl quirks
584

585             // L3_2a: Second instantiation of first subroutine:
586
LABEL(L3_2a);
587             ASTORE(2);
588             IINC(1, 2);
589             ACONST_NULL();
590             GOTO(L4_3a);
591             LABEL(L4_3b); // L4_3b
592
GOTO(L3_2b);
593             LABEL(L5_2); // L5_2
594
ACONST_NULL();
595             GOTO(L4_4a);
596             LABEL(L4_4b); // L4_4b
597
ATHROW();
598             LABEL(new Label()); // extra label emitted due to impl quirks
599

600             // L4_1a: First instantiation of second subroutine:
601
LABEL(L4_1a);
602             ASTORE(3);
603             IINC(1, 3);
604             GOTO(L4_1b);
605             LABEL(new Label()); // extra label emitted due to impl quirks
606

607             // L4_2a: Second instantiation of second subroutine:
608
LABEL(L4_2a);
609             ASTORE(3);
610             IINC(1, 3);
611             GOTO(L4_2b);
612             LABEL(new Label()); // extra label emitted due to impl quirks
613

614             // L4_3a: Third instantiation of second subroutine:
615
LABEL(L4_3a);
616             ASTORE(3);
617             IINC(1, 3);
618             GOTO(L4_3b);
619             LABEL(new Label()); // extra label emitted due to impl quirks
620

621             // L4_4a: Fourth instantiation of second subroutine:
622
LABEL(L4_4a);
623             ASTORE(3);
624             IINC(1, 3);
625             GOTO(L4_4b);
626             LABEL(new Label()); // extra label emitted due to impl quirks
627

628             TRYCATCH(L0, L2, L2);
629             TRYCATCH(L3_1a, L5_1, L5_1);
630             TRYCATCH(L3_2a, L5_2, L5_2);
631
632             END(2, 6);
633         }
634
635         assertEquals(exp, jsr);
636     }
637
638     /**
639      * This tests a subroutine which has no ret statement, but ends in a
640      * "return" instead.
641      *
642      * We structure this as a try/finally with a break in the finally. Because
643      * the while loop is infinite, it's clear from the byte code that the only
644      * path which reaches the RETURN instruction is through the subroutine.
645      *
646      * <pre>
647      * public void a1() {
648      * int a = 0;
649      * while (true) {
650      * try {
651      * a += 1;
652      * } finally {
653      * a += 2;
654      * break;
655      * }
656      * }
657      * }
658      * </pre>
659      */

660     public void testSubroutineWithNoRet() {
661         {
662             Label L0 = new Label();
663             Label L1 = new Label();
664             Label L2 = new Label();
665             Label L3 = new Label();
666             Label L4 = new Label();
667
668             setCurrent(jsr);
669             ICONST_0();
670             ISTORE(1);
671
672             // L0: while loop header/try block
673
LABEL(L0);
674             IINC(1, 1);
675             JSR(L1);
676             GOTO(L2);
677
678             // L3: implicit catch block
679
LABEL(L3);
680             ASTORE(2);
681             JSR(L1);
682             ALOAD(2);
683             ATHROW();
684
685             // L1: subroutine ...
686
LABEL(L1);
687             ASTORE(3);
688             IINC(1, 2);
689             GOTO(L4); // ...not that it does not return!
690

691             // L2: end of the loop... goes back to the top!
692
LABEL(L2);
693             GOTO(L0);
694
695             // L4:
696
LABEL(L4);
697             RETURN();
698
699             TRYCATCH(L0, L3, L3);
700
701             END(1, 4);
702         }
703
704         {
705             Label L0 = new Label();
706             Label L1_1a = new Label();
707             Label L1_1b = new Label();
708             Label L1_2a = new Label();
709             Label L1_2b = new Label();
710             Label L2 = new Label();
711             Label L3 = new Label();
712             Label L4_1 = new Label();
713             Label L4_2 = new Label();
714
715             setCurrent(exp);
716             ICONST_0();
717             ISTORE(1);
718
719             // L0: while loop header/try block
720
LABEL(L0);
721             IINC(1, 1);
722             ACONST_NULL();
723             GOTO(L1_1a);
724             LABEL(L1_1b); // L1_1b
725
GOTO(L2);
726
727             // L3: implicit catch block
728
LABEL(L3);
729             ASTORE(2);
730             ACONST_NULL();
731             GOTO(L1_2a);
732             LABEL(L1_2b); // L1_2b
733
ALOAD(2);
734             ATHROW();
735
736             // L2: end of the loop... goes back to the top!
737
LABEL(L2);
738             GOTO(L0);
739             LABEL(new Label()); // extra label emitted due to impl quirks
740

741             // L1_1a: first instantiation of subroutine ...
742
LABEL(L1_1a);
743             ASTORE(3);
744             IINC(1, 2);
745             GOTO(L4_1); // ...not that it does not return!
746
LABEL(L4_1);
747             RETURN();
748
749             // L1_2a: second instantiation of subroutine ...
750
LABEL(L1_2a);
751             ASTORE(3);
752             IINC(1, 2);
753             GOTO(L4_2); // ...not that it does not return!
754
LABEL(L4_2);
755             RETURN();
756
757             TRYCATCH(L0, L3, L3);
758
759             END(1, 4);
760         }
761
762         assertEquals(exp, jsr);
763     }
764
765     /**
766      * This tests a subroutine which has no ret statement, but ends in a
767      * "return" instead.
768      *
769      * <pre>
770      * JSR L0
771      * L0:
772      * ASTORE 0
773      * RETURN
774      * </pre>
775      */

776     public void testSubroutineWithNoRet2() {
777         {
778             Label L0 = new Label();
779
780             setCurrent(jsr);
781             JSR(L0);
782             LABEL(L0);
783             ASTORE(0);
784             RETURN();
785             END(1, 1);
786         }
787
788         {
789             Label L0_1a = new Label();
790             Label L0_1b = new Label();
791
792             setCurrent(exp);
793
794             ACONST_NULL();
795             GOTO(L0_1a);
796             LABEL(L0_1b);
797
798             // L0_1a: First instantiation of subroutine:
799
LABEL(L0_1a);
800             ASTORE(0);
801             RETURN();
802             LABEL(new Label()); // extra label emitted due to impl quirks
803

804             END(1, 1);
805         }
806
807         assertEquals(exp, jsr);
808     }
809
810     /**
811      * This tests a subroutine which has no ret statement, but instead exits
812      * implicitely by branching to code which is not part of the subroutine.
813      * (Sadly, this is legal)
814      *
815      * We structure this as a try/finally in a loop with a break in the finally.
816      * The loop is not trivially infinite, so the RETURN statement is reachable
817      * both from the JSR subroutine and from the main entry point.
818      *
819      * <pre>
820      * public void a1() {
821      * int a = 0;
822      * while (null == null) {
823      * try {
824      * a += 1;
825      * } finally {
826      * a += 2;
827      * break;
828      * }
829      * }
830      * }
831      * </pre>
832      */

833     public void testImplicitExit() {
834         {
835             Label L0 = new Label();
836             Label L1 = new Label();
837             Label L2 = new Label();
838             Label L3 = new Label();
839             Label L4 = new Label();
840             Label L5 = new Label();
841
842             setCurrent(jsr);
843             ICONST_0();
844             ISTORE(1);
845
846             // L5: while loop header
847
LABEL(L5);
848             ACONST_NULL();
849             IFNONNULL(L4);
850
851             // L0: try block
852
LABEL(L0);
853             IINC(1, 1);
854             JSR(L1);
855             GOTO(L2);
856
857             // L3: implicit catch block
858
LABEL(L3);
859             ASTORE(2);
860             JSR(L1);
861             ALOAD(2);
862             ATHROW();
863
864             // L1: subroutine ...
865
LABEL(L1);
866             ASTORE(3);
867             IINC(1, 2);
868             GOTO(L4); // ...not that it does not return!
869

870             // L2: end of the loop... goes back to the top!
871
LABEL(L2);
872             GOTO(L0);
873
874             // L4:
875
LABEL(L4);
876             RETURN();
877
878             TRYCATCH(L0, L3, L3);
879
880             END(1, 4);
881         }
882
883         {
884             Label L0 = new Label();
885             Label L1_1a = new Label();
886             Label L1_1b = new Label();
887             Label L1_2a = new Label();
888             Label L1_2b = new Label();
889             Label L2 = new Label();
890             Label L3 = new Label();
891             Label L4 = new Label();
892             Label L5 = new Label();
893
894             setCurrent(exp);
895             ICONST_0();
896             ISTORE(1);
897
898             // L5: while loop header
899
LABEL(L5);
900             ACONST_NULL();
901             IFNONNULL(L4);
902
903             // L0: while loop header/try block
904
LABEL(L0);
905             IINC(1, 1);
906             ACONST_NULL();
907             GOTO(L1_1a);
908             LABEL(L1_1b); // L1_1b
909
GOTO(L2);
910
911             // L3: implicit catch block
912
LABEL(L3);
913             ASTORE(2);
914             ACONST_NULL();
915             GOTO(L1_2a);
916             LABEL(L1_2b); // L1_2b
917
ALOAD(2);
918             ATHROW();
919
920             // L2: end of the loop... goes back to the top!
921
LABEL(L2);
922             GOTO(L0);
923
924             // L4: exit, not part of subroutine
925
// Note that the two subroutine instantiations branch here
926
LABEL(L4);
927             RETURN();
928
929             // L1_1a: first instantiation of subroutine ...
930
LABEL(L1_1a);
931             ASTORE(3);
932             IINC(1, 2);
933             GOTO(L4); // ...note that it does not return!
934
LABEL(new Label()); // extra label emitted due to impl quirks
935

936             // L1_2a: second instantiation of subroutine ...
937
LABEL(L1_2a);
938             ASTORE(3);
939             IINC(1, 2);
940             GOTO(L4); // ...note that it does not return!
941
LABEL(new Label()); // extra label emitted due to impl quirks
942

943             TRYCATCH(L0, L3, L3);
944
945             END(1, 4);
946         }
947
948         assertEquals(exp, jsr);
949     }
950
951     /**
952      * Tests a nested try/finally with implicit exit from one subroutine to the
953      * other subroutine. Equivalent to the following java code:
954      *
955      * <pre>
956      * void m(boolean b) {
957      * try {
958      * return;
959      * } finally {
960      * while (b) {
961      * try {
962      * return;
963      * } finally {
964      * // NOTE --- this break avoids the second return above (weird)
965      * if (b) break;
966      * }
967      * }
968      * }
969      * }
970      * </pre>
971      *
972      * This example is from the paper, "Subroutine Inlining and Bytecode
973      * Abstraction to Simplify Static and Dynamic Analysis" by Cyrille Artho and
974      * Armin Biere.
975      */

976     public void testImplicitExitToAnotherSubroutine() {
977         {
978             Label T1 = new Label();
979             Label C1 = new Label();
980             Label S1 = new Label();
981             Label L = new Label();
982             Label C2 = new Label();
983             Label S2 = new Label();
984             Label W = new Label();
985             Label X = new Label();
986
987             // variable numbers:
988
int b = 1;
989             int e1 = 2;
990             int e2 = 3;
991             int r1 = 4;
992             int r2 = 5;
993
994             setCurrent(jsr);
995
996             ICONST_0();
997             ISTORE(1);
998
999             // T1: first try:
1000
LABEL(T1);
1001            JSR(S1);
1002            RETURN();
1003
1004            // C1: exception handler for first try
1005
LABEL(C1);
1006            ASTORE(e1);
1007            JSR(S1);
1008            ALOAD(e1);
1009            ATHROW();
1010
1011            // S1: first finally handler
1012
LABEL(S1);
1013            ASTORE(r1);
1014            GOTO(W);
1015
1016            // L: body of while loop, also second try
1017
LABEL(L);
1018            JSR(S2);
1019            RETURN();
1020
1021            // C2: exception handler for second try
1022
LABEL(C2);
1023            ASTORE(e2);
1024            JSR(S2);
1025            ALOAD(e2);
1026            ATHROW();
1027
1028            // S2: second finally handler
1029
LABEL(S2);
1030            ASTORE(r2);
1031            ILOAD(b);
1032            IFNE(X);
1033            RET(r2);
1034
1035            // W: test for the while loop
1036
LABEL(W);
1037            ILOAD(b);
1038            IFNE(L); // falls through to X
1039

1040            // X: exit from finally{} block
1041
LABEL(X);
1042            RET(r1);
1043
1044            TRYCATCH(T1, C1, C1);
1045            TRYCATCH(L, C2, C2);
1046
1047            END(1, 6);
1048        }
1049
1050        {
1051            Label T1 = new Label();
1052            Label C1 = new Label();
1053            Label S1_1a = new Label();
1054            Label S1_1b = new Label();
1055            Label S1_2a = new Label();
1056            Label S1_2b = new Label();
1057            Label L_1 = new Label();
1058            Label L_2 = new Label();
1059            Label C2_1 = new Label();
1060            Label C2_2 = new Label();
1061            Label S2_1_1a = new Label();
1062            Label S2_1_1b = new Label();
1063            Label S2_1_2a = new Label();
1064            Label S2_1_2b = new Label();
1065            Label S2_2_1a = new Label();
1066            Label S2_2_1b = new Label();
1067            Label S2_2_2a = new Label();
1068            Label S2_2_2b = new Label();
1069            Label W_1 = new Label();
1070            Label W_2 = new Label();
1071            Label X_1 = new Label();
1072            Label X_2 = new Label();
1073
1074            // variable numbers:
1075
int b = 1;
1076            int e1 = 2;
1077            int e2 = 3;
1078            int r1 = 4;
1079            int r2 = 5;
1080
1081            setCurrent(exp);
1082
1083            // --- Main Subroutine ---
1084

1085            ICONST_0();
1086            ISTORE(1);
1087
1088            // T1: first try:
1089
LABEL(T1);
1090            ACONST_NULL();
1091            GOTO(S1_1a);
1092            LABEL(S1_1b);
1093            RETURN();
1094
1095            // C1: exception handler for first try
1096
LABEL(C1);
1097            ASTORE(e1);
1098            ACONST_NULL();
1099            GOTO(S1_2a);
1100            LABEL(S1_2b);
1101            ALOAD(e1);
1102            ATHROW();
1103            LABEL(new Label()); // extra label emitted due to impl quirks
1104

1105            // --- First instantiation of first subroutine ---
1106

1107            // S1: first finally handler
1108
LABEL(S1_1a);
1109            ASTORE(r1);
1110            GOTO(W_1);
1111
1112            // L_1: body of while loop, also second try
1113
LABEL(L_1);
1114            ACONST_NULL();
1115            GOTO(S2_1_1a);
1116            LABEL(S2_1_1b);
1117            RETURN();
1118
1119            // C2_1: exception handler for second try
1120
LABEL(C2_1);
1121            ASTORE(e2);
1122            ACONST_NULL();
1123            GOTO(S2_1_2a);
1124            LABEL(S2_1_2b);
1125            ALOAD(e2);
1126            ATHROW();
1127
1128            // W_1: test for the while loop
1129
LABEL(W_1);
1130            ILOAD(b);
1131            IFNE(L_1); // falls through to X_1
1132

1133            // X_1: exit from finally{} block
1134
LABEL(X_1);
1135            GOTO(S1_1b);
1136
1137            // --- Second instantiation of first subroutine ---
1138

1139            // S1: first finally handler
1140
LABEL(S1_2a);
1141            ASTORE(r1);
1142            GOTO(W_2);
1143
1144            // L_2: body of while loop, also second try
1145
LABEL(L_2);
1146            ACONST_NULL();
1147            GOTO(S2_2_1a);
1148            LABEL(S2_2_1b);
1149            RETURN();
1150
1151            // C2_2: exception handler for second try
1152
LABEL(C2_2);
1153            ASTORE(e2);
1154            ACONST_NULL();
1155            GOTO(S2_2_2a);
1156            LABEL(S2_2_2b);
1157            ALOAD(e2);
1158            ATHROW();
1159
1160            // W_2: test for the while loop
1161
LABEL(W_2);
1162            ILOAD(b);
1163            IFNE(L_2); // falls through to X_2
1164

1165            // X_2: exit from finally{} block
1166
LABEL(X_2);
1167            GOTO(S1_2b);
1168
1169            // --- Second subroutine's 4 instantiations ---
1170

1171            // S2_1_1a:
1172
LABEL(S2_1_1a);
1173            ASTORE(r2);
1174            ILOAD(b);
1175            IFNE(X_1);
1176            GOTO(S2_1_1b);
1177            LABEL(new Label()); // extra label emitted due to impl quirks
1178

1179            // S2_1_2a:
1180
LABEL(S2_1_2a);
1181            ASTORE(r2);
1182            ILOAD(b);
1183            IFNE(X_1);
1184            GOTO(S2_1_2b);
1185            LABEL(new Label()); // extra label emitted due to impl quirks
1186

1187            // S2_2_1a:
1188
LABEL(S2_2_1a);
1189            ASTORE(r2);
1190            ILOAD(b);
1191            IFNE(X_2);
1192            GOTO(S2_2_1b);
1193            LABEL(new Label()); // extra label emitted due to impl quirks
1194

1195            // S2_2_2a:
1196
LABEL(S2_2_2a);
1197            ASTORE(r2);
1198            ILOAD(b);
1199            IFNE(X_2);
1200            GOTO(S2_2_2b);
1201            LABEL(new Label()); // extra label emitted due to impl quirks
1202

1203            TRYCATCH(T1, C1, C1);
1204            TRYCATCH(L_1, C2_1, C2_1); // duplicated try/finally for each...
1205
TRYCATCH(L_2, C2_2, C2_2); // ...instantiation of first sub
1206

1207            END(1, 6);
1208        }
1209
1210        assertEquals(exp, jsr);
1211    }
1212
1213    /**
1214     * This tests two subroutines, neither of which exit. Instead, they both
1215     * branch to a common set of code which returns from the method. This code
1216     * is not reachable except through these subroutines, and since they do not
1217     * invoke each other, it must be copied into both of them.
1218     *
1219     * I don't believe this can be represented in Java.
1220     */

1221    public void testCommonCodeWhichMustBeDuplicated() {
1222        {
1223            Label L1 = new Label();
1224            Label L2 = new Label();
1225            Label L3 = new Label();
1226
1227            setCurrent(jsr);
1228            ICONST_0();
1229            ISTORE(1);
1230
1231            // Invoke the two subroutines, each twice:
1232
JSR(L1);
1233            JSR(L1);
1234            JSR(L2);
1235            JSR(L2);
1236            RETURN();
1237
1238            // L1: subroutine 1
1239
LABEL(L1);
1240            IINC(1, 1);
1241            GOTO(L3); // ...note that it does not return!
1242

1243            // L2: subroutine 2
1244
LABEL(L2);
1245            IINC(1, 2);
1246            GOTO(L3); // ...note that it does not return!
1247

1248            // L3: common code to both subroutines: exit method
1249
LABEL(L3);
1250            RETURN();
1251
1252            END(1, 2);
1253        }
1254
1255        {
1256            Label L1_1a = new Label();
1257            Label L1_1b = new Label();
1258            Label L1_2a = new Label();
1259            Label L1_2b = new Label();
1260            Label L2_1a = new Label();
1261            Label L2_1b = new Label();
1262            Label L2_2a = new Label();
1263            Label L2_2b = new Label();
1264            Label L3_1 = new Label();
1265            Label L3_2 = new Label();
1266            Label L3_3 = new Label();
1267            Label L3_4 = new Label();
1268
1269            setCurrent(exp);
1270            ICONST_0();
1271            ISTORE(1);
1272
1273            // Invoke the two subroutines, each twice:
1274
ACONST_NULL();
1275            GOTO(L1_1a);
1276            LABEL(L1_1b);
1277            ACONST_NULL();
1278            GOTO(L1_2a);
1279            LABEL(L1_2b);
1280            ACONST_NULL();
1281            GOTO(L2_1a);
1282            LABEL(L2_1b);
1283            ACONST_NULL();
1284            GOTO(L2_2a);
1285            LABEL(L2_2b);
1286            RETURN();
1287            LABEL(new Label()); // extra label emitted due to impl quirks
1288

1289            // L1_1a: instantiation 1 of subroutine 1
1290
LABEL(L1_1a);
1291            IINC(1, 1);
1292            GOTO(L3_1); // ...note that it does not return!
1293
LABEL(L3_1);
1294            RETURN();
1295
1296            // L1_2a: instantiation 2 of subroutine 1
1297
LABEL(L1_2a);
1298            IINC(1, 1);
1299            GOTO(L3_2); // ...note that it does not return!
1300
LABEL(L3_2);
1301            RETURN();
1302
1303            // L2_1a: instantiation 1 of subroutine 2
1304
LABEL(L2_1a);
1305            IINC(1, 2);
1306            GOTO(L3_3); // ...note that it does not return!
1307
LABEL(L3_3);
1308            RETURN();
1309
1310            // L2_2a: instantiation 2 of subroutine 2
1311
LABEL(L2_2a);
1312            IINC(1, 2);
1313            GOTO(L3_4); // ...note that it does not return!
1314
LABEL(L3_4);
1315            RETURN();
1316
1317            END(1, 2);
1318        }
1319
1320        assertEquals(exp, jsr);
1321    }
1322
1323    /**
1324     * This tests a simple subroutine where the control flow jumps back and
1325     * forth between the subroutine and the caller.
1326     *
1327     * This would not normally be produced by a java compiler.
1328     */

1329    public void testInterleavedCode() {
1330        {
1331            Label L1 = new Label();
1332            Label L2 = new Label();
1333            Label L3 = new Label();
1334            Label L4 = new Label();
1335
1336            setCurrent(jsr);
1337            ICONST_0();
1338            ISTORE(1);
1339
1340            // Invoke the subroutine, each twice:
1341
JSR(L1);
1342            GOTO(L2);
1343
1344            // L1: subroutine 1
1345
LABEL(L1);
1346            ASTORE(2);
1347            IINC(1, 1);
1348            GOTO(L3);
1349
1350            // L2: second part of main subroutine
1351
LABEL(L2);
1352            IINC(1, 2);
1353            GOTO(L4);
1354
1355            // L3: second part of subroutine 1
1356
LABEL(L3);
1357            IINC(1, 4);
1358            RET(2);
1359
1360            // L4: third part of main subroutine
1361
LABEL(L4);
1362            JSR(L1);
1363            RETURN();
1364
1365            END(1, 3);
1366        }
1367
1368        {
1369            Label L1_1a = new Label();
1370            Label L1_1b = new Label();
1371            Label L1_2a = new Label();
1372            Label L1_2b = new Label();
1373            Label L2 = new Label();
1374            Label L3_1 = new Label();
1375            Label L3_2 = new Label();
1376            Label L4 = new Label();
1377
1378            setCurrent(exp);
1379
1380            // Main routine:
1381
ICONST_0();
1382            ISTORE(1);
1383            ACONST_NULL();
1384            GOTO(L1_1a);
1385            LABEL(L1_1b);
1386            GOTO(L2);
1387            LABEL(L2);
1388            IINC(1, 2);
1389            GOTO(L4);
1390            LABEL(L4);
1391            ACONST_NULL();
1392            GOTO(L1_2a);
1393            LABEL(L1_2b);
1394            RETURN();
1395
1396            // L1_1: instantiation #1
1397
LABEL(L1_1a);
1398            ASTORE(2);
1399            IINC(1, 1);
1400            GOTO(L3_1);
1401            LABEL(L3_1);
1402            IINC(1, 4);
1403            GOTO(L1_1b);
1404            LABEL(new Label()); // extra label emitted due to impl quirks
1405

1406            // L1_2: instantiation #2
1407
LABEL(L1_2a);
1408            ASTORE(2);
1409            IINC(1, 1);
1410            GOTO(L3_2);
1411            LABEL(L3_2);
1412            IINC(1, 4);
1413            GOTO(L1_2b);
1414            LABEL(new Label()); // extra label emitted due to impl quirks
1415

1416            END(1, 3);
1417        }
1418
1419        assertEquals(exp, jsr);
1420    }
1421
1422    /**
1423     * Tests a nested try/finally with implicit exit from one subroutine to the
1424     * other subroutine, and with a surrounding try/catch thrown in the mix.
1425     * Equivalent to the following java code:
1426     *
1427     * <pre>
1428     * void m(int b) {
1429     * try {
1430     * try {
1431     * return;
1432     * } finally {
1433     * while (b) {
1434     * try {
1435     * return;
1436     * } finally {
1437     * // NOTE --- this break avoids the second return above (weird)
1438     * if (b) break;
1439     * }
1440     * }
1441     * }
1442     * } catch (Exception e) {
1443     * b += 3;
1444     * return;
1445     * }
1446     * }
1447     * </pre>
1448     */

1449    public void testImplicitExitInTryCatch() {
1450        {
1451            Label T1 = new Label();
1452            Label C1 = new Label();
1453            Label S1 = new Label();
1454            Label L = new Label();
1455            Label C2 = new Label();
1456            Label S2 = new Label();
1457            Label W = new Label();
1458            Label X = new Label();
1459            Label OT = new Label();
1460            Label OC = new Label();
1461
1462            // variable numbers:
1463
int b = 1;
1464            int e1 = 2;
1465            int e2 = 3;
1466            int r1 = 4;
1467            int r2 = 5;
1468
1469            setCurrent(jsr);
1470
1471            ICONST_0();
1472            ISTORE(1);
1473
1474            // OT: outermost try
1475
LABEL(OT);
1476
1477            // T1: first try:
1478
LABEL(T1);
1479            JSR(S1);
1480            RETURN();
1481
1482            // C1: exception handler for first try
1483
LABEL(C1);
1484            ASTORE(e1);
1485            JSR(S1);
1486            ALOAD(e1);
1487            ATHROW();
1488
1489            // S1: first finally handler
1490
LABEL(S1);
1491            ASTORE(r1);
1492            GOTO(W);
1493
1494            // L: body of while loop, also second try
1495
LABEL(L);
1496            JSR(S2);
1497            RETURN();
1498
1499            // C2: exception handler for second try
1500
LABEL(C2);
1501            ASTORE(e2);
1502            JSR(S2);
1503            ALOAD(e2);
1504            ATHROW();
1505
1506            // S2: second finally handler
1507
LABEL(S2);
1508            ASTORE(r2);
1509            ILOAD(b);
1510            IFNE(X);
1511            RET(r2);
1512
1513            // W: test for the while loop
1514
LABEL(W);
1515            ILOAD(b);
1516            IFNE(L); // falls through to X
1517

1518            // X: exit from finally{} block
1519
LABEL(X);
1520            RET(r1);
1521
1522            // OC: outermost catch
1523
LABEL(OC);
1524            IINC(b, 3);
1525            RETURN();
1526
1527            TRYCATCH(T1, C1, C1);
1528            TRYCATCH(L, C2, C2);
1529            TRYCATCH(OT, OC, OC);
1530
1531            END(1, 6);
1532        }
1533
1534        {
1535            Label T1 = new Label();
1536            Label C1 = new Label();
1537            Label S1_1a = new Label();
1538            Label S1_1b = new Label();
1539            Label S1_2a = new Label();
1540            Label S1_2b = new Label();
1541            Label L_1 = new Label();
1542            Label L_2 = new Label();
1543            Label C2_1 = new Label();
1544            Label C2_2 = new Label();
1545            Label S2_1_1a = new Label();
1546            Label S2_1_1b = new Label();
1547            Label S2_1_2a = new Label();
1548            Label S2_1_2b = new Label();
1549            Label S2_2_1a = new Label();
1550            Label S2_2_1b = new Label();
1551            Label S2_2_2a = new Label();
1552            Label S2_2_2b = new Label();
1553            Label W_1 = new Label();
1554            Label W_2 = new Label();
1555            Label X_1 = new Label();
1556            Label X_2 = new Label();
1557            Label OT_1 = S1_1a;
1558            Label OT_2 = S1_2a;
1559            Label OT_1_1 = S2_1_1a;
1560            Label OT_1_2 = S2_1_2a;
1561            Label OT_2_1 = S2_2_1a;
1562            Label OT_2_2 = S2_2_2a;
1563            Label OC = new Label();
1564            Label OC_1 = new Label();
1565            Label OC_2 = new Label();
1566            Label OC_1_1 = new Label();
1567            Label OC_1_2 = new Label();
1568            Label OC_2_1 = new Label();
1569            Label OC_2_2 = new Label();
1570
1571            // variable numbers:
1572
int b = 1;
1573            int e1 = 2;
1574            int e2 = 3;
1575            int r1 = 4;
1576            int r2 = 5;
1577
1578            setCurrent(exp);
1579
1580            // --- Main Subroutine ---
1581

1582            ICONST_0();
1583            ISTORE(1);
1584
1585            // T1: outermost try / first try:
1586
LABEL(T1);
1587            ACONST_NULL();
1588            GOTO(S1_1a);
1589            LABEL(S1_1b);
1590            RETURN();
1591
1592            // C1: exception handler for first try
1593
LABEL(C1);
1594            ASTORE(e1);
1595            ACONST_NULL();
1596            GOTO(S1_2a);
1597            LABEL(S1_2b);
1598            ALOAD(e1);
1599            ATHROW();
1600
1601            // OC: Outermost catch
1602
LABEL(OC);
1603            IINC(b, 3);
1604            RETURN();
1605
1606            // --- First instantiation of first subroutine ---
1607

1608            // S1: first finally handler
1609
LABEL(S1_1a);
1610            ASTORE(r1);
1611            GOTO(W_1);
1612
1613            // L_1: body of while loop, also second try
1614
LABEL(L_1);
1615            ACONST_NULL();
1616            GOTO(S2_1_1a);
1617            LABEL(S2_1_1b);
1618            RETURN();
1619
1620            // C2_1: exception handler for second try
1621
LABEL(C2_1);
1622            ASTORE(e2);
1623            ACONST_NULL();
1624            GOTO(S2_1_2a);
1625            LABEL(S2_1_2b);
1626            ALOAD(e2);
1627            ATHROW();
1628
1629            // W_1: test for the while loop
1630
LABEL(W_1);
1631            ILOAD(b);
1632            IFNE(L_1); // falls through to X_1
1633

1634            // X_1: exit from finally{} block
1635
LABEL(X_1);
1636            GOTO(S1_1b);
1637
1638            LABEL(OC_1);
1639
1640            // --- Second instantiation of first subroutine ---
1641

1642            // S1: first finally handler
1643
LABEL(S1_2a);
1644            ASTORE(r1);
1645            GOTO(W_2);
1646
1647            // L_2: body of while loop, also second try
1648
LABEL(L_2);
1649            ACONST_NULL();
1650            GOTO(S2_2_1a);
1651            LABEL(S2_2_1b);
1652            RETURN();
1653
1654            // C2_2: exception handler for second try
1655
LABEL(C2_2);
1656            ASTORE(e2);
1657            ACONST_NULL();
1658            GOTO(S2_2_2a);
1659            LABEL(S2_2_2b);
1660            ALOAD(e2);
1661            ATHROW();
1662
1663            // W_2: test for the while loop
1664
LABEL(W_2);
1665            ILOAD(b);
1666            IFNE(L_2); // falls through to X_2
1667

1668            // X_2: exit from finally{} block
1669
LABEL(X_2);
1670            GOTO(S1_2b);
1671
1672            LABEL(OC_2);
1673
1674            // --- Second subroutine's 4 instantiations ---
1675

1676            // S2_1_1a:
1677
LABEL(S2_1_1a);
1678            ASTORE(r2);
1679            ILOAD(b);
1680            IFNE(X_1);
1681            GOTO(S2_1_1b);
1682            LABEL(OC_1_1);
1683
1684            // S2_1_2a:
1685
LABEL(S2_1_2a);
1686            ASTORE(r2);
1687            ILOAD(b);
1688            IFNE(X_1);
1689            GOTO(S2_1_2b);
1690            LABEL(OC_1_2);
1691
1692            // S2_2_1a:
1693
LABEL(S2_2_1a);
1694            ASTORE(r2);
1695            ILOAD(b);
1696            IFNE(X_2);
1697            GOTO(S2_2_1b);
1698            LABEL(OC_2_1);
1699
1700            // S2_2_2a:
1701
LABEL(S2_2_2a);
1702            ASTORE(r2);
1703            ILOAD(b);
1704            IFNE(X_2);
1705            GOTO(S2_2_2b);
1706            LABEL(OC_2_2);
1707
1708            // main subroutine handlers:
1709
TRYCATCH(T1, C1, C1);
1710            TRYCATCH(T1, OC, OC);
1711
1712            // first instance of first sub try/catch handlers:
1713
TRYCATCH(L_1, C2_1, C2_1);
1714            TRYCATCH(OT_1, OC_1, OC); // note: reuses handler code from main
1715
// sub
1716

1717            // second instance of first sub try/catch handlers:
1718
TRYCATCH(L_2, C2_2, C2_2);
1719            TRYCATCH(OT_2, OC_2, OC);
1720
1721            // all 4 instances of second sub:
1722
TRYCATCH(OT_1_1, OC_1_1, OC);
1723            TRYCATCH(OT_1_2, OC_1_2, OC);
1724            TRYCATCH(OT_2_1, OC_2_1, OC);
1725            TRYCATCH(OT_2_2, OC_2_2, OC);
1726
1727            END(1, 6);
1728        }
1729
1730        assertEquals(exp, jsr);
1731    }
1732
1733    /**
1734     * Tests a method which has line numbers and local variable declarations.
1735     *
1736     * <pre>
1737     * public void a() {
1738     * 1 int a = 0;
1739     * 2 try {
1740     * 3 a++;
1741     * 4 } finally {
1742     * 5 a--;
1743     * 6 }
1744     * }
1745     * LV "a" from 1 to 6
1746     * </pre>
1747     */

1748    public void testBasicLineNumberAndLocalVars() {
1749        {
1750            Label LM1 = new Label();
1751            Label L0 = new Label();
1752            Label L1 = new Label();
1753            Label L2 = new Label();
1754            Label L3 = new Label();
1755            Label L4 = new Label();
1756
1757            setCurrent(jsr);
1758            LABEL(LM1);
1759            LINE(1, LM1);
1760            ICONST_0();
1761            ISTORE(1);
1762
1763            /* L0: body of try block */
1764            LABEL(L0);
1765            LINE(3, L0);
1766            IINC(1, 1);
1767            GOTO(L1);
1768
1769            /* L2: exception handler */
1770            LABEL(L2);
1771            ASTORE(3);
1772            JSR(L3);
1773            ALOAD(3);
1774            ATHROW();
1775
1776            /* L3: subroutine */
1777            LABEL(L3);
1778            LINE(5, L3);
1779            ASTORE(2);
1780            IINC(1, -1);
1781            RET(2);
1782
1783            /* L1: non-exceptional exit from try block */
1784            LABEL(L1);
1785            JSR(L3);
1786            LABEL(L4); // L4
1787
RETURN();
1788
1789            TRYCATCH(L0, L2, L2);
1790            TRYCATCH(L1, L4, L2);
1791            LOCALVAR("a", "I", 1, LM1, L4);
1792
1793            END(1, 4);
1794        }
1795
1796        {
1797            Label LM1 = new Label();
1798            Label L0 = new Label();
1799            Label L1 = new Label();
1800            Label L2 = new Label();
1801            Label L3_1a = new Label();
1802            Label L3_1b = new Label();
1803            Label L3_1c = new Label();
1804            Label L3_2a = new Label();
1805            Label L3_2b = new Label();
1806            Label L3_2c = new Label();
1807            Label L4 = new Label();
1808
1809            setCurrent(exp);
1810            LABEL(LM1);
1811            LINE(1, LM1);
1812            ICONST_0();
1813            ISTORE(1);
1814            // L0: try/catch block
1815
LABEL(L0);
1816            LINE(3, L0);
1817            IINC(1, 1);
1818            GOTO(L1);
1819
1820            // L2: Exception handler:
1821
LABEL(L2);
1822            ASTORE(3);
1823            ACONST_NULL();
1824            GOTO(L3_1a);
1825            LABEL(L3_1b); // L3_1b;
1826
ALOAD(3);
1827            ATHROW();
1828
1829            // L1: On non-exceptional exit, try block leads here:
1830
LABEL(L1);
1831            ACONST_NULL();
1832            GOTO(L3_2a);
1833            LABEL(L3_2b); // L3_2b
1834
LABEL(L4); // L4
1835
RETURN();
1836
1837            // L3_1a: First instantiation of subroutine:
1838
LABEL(L3_1a);
1839            LINE(5, L3_1a);
1840            ASTORE(2);
1841            IINC(1, -1);
1842            GOTO(L3_1b);
1843            LABEL(L3_1c);
1844
1845            // L3_2a: Second instantiation of subroutine:
1846
LABEL(L3_2a);
1847            LINE(5, L3_2a);
1848            ASTORE(2);
1849            IINC(1, -1);
1850            GOTO(L3_2b);
1851            LABEL(L3_2c);
1852
1853            TRYCATCH(L0, L2, L2);
1854            TRYCATCH(L1, L4, L2);
1855            LOCALVAR("a", "I", 1, LM1, L4);
1856            LOCALVAR("a", "I", 1, L3_1a, L3_1c);
1857            LOCALVAR("a", "I", 1, L3_2a, L3_2c);
1858
1859            END(1, 4);
1860        }
1861
1862        assertEquals(exp, jsr);
1863    }
1864
1865    public void assertEquals(final MethodNode exp, final MethodNode actual) {
1866        String JavaDoc textexp = getText(exp);
1867        String JavaDoc textact = getText(actual);
1868        System.err.println("Expected=" + textexp);
1869        System.err.println("Actual=" + textact);
1870        assertEquals(textexp, textact);
1871    }
1872
1873    private String JavaDoc getText(final MethodNode mn) {
1874        TraceMethodVisitor tmv = new TraceMethodVisitor(null);
1875        mn.accept(tmv);
1876
1877        StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1878        for (int i = 0; i < tmv.text.size(); i++) {
1879            sb.append(tmv.text.get(i));
1880        }
1881        return sb.toString();
1882    }
1883}
1884
Popular Tags