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