1 import jdk.incubator.code.Block;
  2 import jdk.incubator.code.CodeTransformer;
  3 import jdk.incubator.code.Op;
  4 import jdk.incubator.code.Reflect;
  5 import jdk.incubator.code.Value;
  6 import jdk.incubator.code.dialect.core.CoreOp;
  7 import jdk.incubator.code.dialect.core.Inliner;
  8 import jdk.incubator.code.dialect.java.JavaOp;
  9 import org.junit.jupiter.api.Assertions;
 10 import org.junit.jupiter.api.Test;
 11 
 12 import java.lang.invoke.MethodHandles;
 13 import java.util.ArrayList;
 14 import java.util.List;
 15 import java.util.function.BiConsumer;
 16 import java.util.function.Consumer;
 17 import java.util.function.IntConsumer;
 18 
 19 /*
 20  * @test
 21  * @modules jdk.incubator.code
 22  * @library lib
 23  * @run junit TestTryOpWithExceptionRegion
 24  * @run junit/othervm -Dbabylon.tryFinally=sharedDispatch TestTryOpWithExceptionRegion
 25  * @run main Unreflect TestTryOpWithExceptionRegion
 26  * @run junit TestTryOpWithExceptionRegion
 27  * @run junit/othervm -Dbabylon.tryFinally=sharedDispatch TestTryOpWithExceptionRegion
 28  */
 29 public class TestTryOpWithExceptionRegion {
 30     @Reflect
 31     static void m(IntConsumer c) {
 32         try {
 33             c.accept(0);
 34             n(c);
 35         } catch (IllegalArgumentException ex) {
 36             c.accept(4);
 37         } finally {
 38             c.accept(5);
 39         }
 40     }
 41 
 42     @Reflect
 43     private static void n(IntConsumer c) {
 44         try {
 45             c.accept(1);
 46         } catch (IllegalStateException ex) {
 47             c.accept(2);
 48         } finally {
 49             c.accept(3);
 50         }
 51     }
 52 
 53     @Test
 54     void testTryOpEnclosingExceptionRegion() throws NoSuchMethodException {
 55         // lower n + inline it in m
 56         CoreOp.FuncOp n = Op.ofMethod(this.getClass().getDeclaredMethod("n", IntConsumer.class)).get();
 57         CoreOp.FuncOp ln = n.transform(CodeTransformer.LOWERING_TRANSFORMER);
 58         CoreOp.FuncOp m = Op.ofMethod(this.getClass().getDeclaredMethod("m", IntConsumer.class)).get();
 59         CoreOp.FuncOp m2 = m.transform((b, o) -> {
 60             if (o instanceof JavaOp.InvokeOp iop && iop.invokeReference().name().equals("n")) {
 61                 return Inliner.inline(b, ln, b.context().getValues(m.parameters()));
 62             } else {
 63                 b.add(o);
 64                 return b;
 65             }
 66         });
 67         System.out.println(m2.toText());
 68 
 69         Consumer<IntConsumer> test = testConsumer(
 70                 c -> Interpreter.invoke(MethodHandles.lookup(), m2, c),
 71                 TestTryOpWithExceptionRegion::m
 72         );
 73         test.accept(i -> {
 74             if (i == 1) throw new IllegalStateException();
 75         });
 76 
 77         test.accept(i -> {
 78             if (i == 1) throw new IllegalArgumentException();
 79         });
 80     }
 81 
 82     @Test
 83     void testTryOpEnclosedByExceptionRegion() throws NoSuchMethodException {
 84         // lower m + inline n
 85         CoreOp.FuncOp m = Op.ofMethod(this.getClass().getDeclaredMethod("m", IntConsumer.class)).get();
 86         CoreOp.FuncOp lm = m.transform(CodeTransformer.LOWERING_TRANSFORMER);
 87         CoreOp.FuncOp n = Op.ofMethod(this.getClass().getDeclaredMethod("n", IntConsumer.class)).get();
 88         CoreOp.FuncOp lm2 = lm.transform((b, o) -> {
 89             if (o instanceof JavaOp.InvokeOp iop && iop.invokeReference().name().equals("n")) {
 90                 return Inliner.inline(b, n, b.context().getValues(lm.parameters()));
 91             } else {
 92                 b.add(o);
 93                 return b;
 94             }
 95         });
 96 
 97         Consumer<IntConsumer> test = testConsumer(
 98                 c -> Interpreter.invoke(MethodHandles.lookup(), lm2, c),
 99                 TestTryOpWithExceptionRegion::m
100         );
101         test.accept(i -> {
102             if (i == 1) throw new IllegalStateException();
103         });
104 
105         test.accept(i -> {
106             if (i == 1) throw new IllegalArgumentException();
107         });
108     }
109 
110     static Consumer<IntConsumer> testConsumer(Consumer<IntConsumer> actualR, Consumer<IntConsumer> expectedR) {
111         return c -> {
112             List<Integer> actual = new ArrayList<>();
113             IntConsumer actualC = actual::add;
114             Throwable actualT = null;
115             try {
116                 actualR.accept(actualC.andThen(c));
117             } catch (Interpreter.InterpreterException e) {
118                 throw e;
119             } catch (Throwable t) {
120                 actualT = t;
121                 if (t instanceof AssertionError) {
122                     t.printStackTrace();
123                 }
124             }
125 
126             List<Integer> expected = new ArrayList<>();
127             IntConsumer expectedC = expected::add;
128             Throwable expectedT = null;
129             try {
130                 expectedR.accept(expectedC.andThen(c));
131             } catch (Throwable t) {
132                 expectedT = t;
133             }
134 
135             Assertions.assertEquals(
136                     expectedT != null ? expectedT.getClass() : null, actualT != null ? actualT.getClass() : null
137             );
138             Assertions.assertEquals(expected, actual);
139         };
140     }
141 }