1 /*
2 * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /*
25 * @test
26 * @summary Smoke test for code reflection with quotable lambdas.
27 * @modules jdk.incubator.code
28 * @build ReflectableLambdaTest
29 * @build CodeReflectionTester
30 * @run main CodeReflectionTester ReflectableLambdaTest
31 */
32
33 import jdk.incubator.code.Reflect;
34 import java.util.function.IntBinaryOperator;
35 import java.util.function.IntFunction;
36 import java.util.function.IntSupplier;
37 import java.util.function.IntUnaryOperator;
38
39 public class ReflectableLambdaTest {
40 @IR("""
41 func @"f" ()java.type:"void" -> {
42 %0 : java.type:"java.lang.Runnable" = lambda @lambda.isQuotable=true ()java.type:"void" -> {
43 return;
44 };
45 return;
46 };
47 """)
48 static final Runnable QUOTED_NO_PARAM_VOID = (@Reflect Runnable) () -> {
49 };
50
51 @IR("""
52 func @"f" ()java.type:"void" -> {
53 %0 : java.type:"java.util.function.IntSupplier" = lambda @lambda.isQuotable=true ()java.type:"int" -> {
54 %1 : java.type:"int" = constant @1;
55 return %1;
56 };
57 return;
58 };
59 """)
60 static final IntSupplier QUOTED_NO_PARAM_CONST = (@Reflect IntSupplier) () -> 1;
61
62 @IR("""
63 func @"f" ()java.type:"void" -> {
64 %0 : java.type:"java.util.function.IntUnaryOperator" = lambda @lambda.isQuotable=true (%1 : java.type:"int")java.type:"int" -> {
65 %2 : Var<java.type:"int"> = var %1 @"x";
66 %3 : java.type:"int" = var.load %2;
67 return %3;
68 };
69 return;
70 };
71 """)
72 static final IntUnaryOperator QUOTED_ID = (@Reflect IntUnaryOperator) x -> x;
73
74 @IR("""
75 func @"f" ()java.type:"void" -> {
76 %0 : java.type:"java.util.function.IntBinaryOperator" = lambda @lambda.isQuotable=true (%1 : java.type:"int", %2 : java.type:"int")java.type:"int" -> {
77 %3 : Var<java.type:"int"> = var %1 @"x";
78 %4 : Var<java.type:"int"> = var %2 @"y";
79 %5 : java.type:"int" = var.load %3;
80 %6 : java.type:"int" = var.load %4;
81 %7 : java.type:"int" = add %5 %6;
82 return %7;
83 };
84 return;
85 };
86 """)
87 static final IntBinaryOperator QUOTED_PLUS = (@Reflect IntBinaryOperator) (x, y) -> x + y;
88
89 @IR("""
90 func @"f" ()java.type:"void" -> {
91 %0 : java.type:"java.lang.Runnable" = lambda @lambda.isQuotable=true ()java.type:"void" -> {
92 %1 : java.type:"java.lang.AssertionError" = new @java.ref:"java.lang.AssertionError::()";
93 throw %1;
94 };
95 return;
96 };
97 """)
98 static final Runnable QUOTED_THROW_NO_PARAM = (@Reflect Runnable) () -> {
99 throw new AssertionError();
100 };
101
102 @IR("""
103 func @"f" (%0 : Var<java.type:"int">)java.type:"void" -> {
104 %1 : java.type:"java.util.function.IntUnaryOperator" = lambda @lambda.isQuotable=true (%2 : java.type:"int")java.type:"int" -> {
105 %3 : Var<java.type:"int"> = var %2 @"y";
106 %4 : java.type:"int" = var.load %0;
107 %5 : java.type:"int" = var.load %3;
108 %6 : java.type:"int" = add %4 %5;
109 return %6;
110 };
111 return;
112 };
113 """)
114 static final IntUnaryOperator QUOTED_CAPTURE_PARAM = new Object() {
115 IntUnaryOperator captureContext(int x) {
116 return (@Reflect IntUnaryOperator) y -> x + y;
117 }
118 }.captureContext(42);
119
120 static class Context {
121 int x, y;
122
123 IntUnaryOperator capture() {
124 return (@Reflect IntUnaryOperator) z -> x + y + z;
125 }
126 }
127
128 @IR("""
129 func @"f" (%0 : java.type:"ReflectableLambdaTest$Context")java.type:"void" -> {
130 %1 : java.type:"java.util.function.IntUnaryOperator" = lambda @lambda.isQuotable=true (%2 : java.type:"int")java.type:"int" -> {
131 %3 : Var<java.type:"int"> = var %2 @"z";
132 %4 : java.type:"int" = field.load %0 @java.ref:"ReflectableLambdaTest$Context::x:int";
133 %5 : java.type:"int" = field.load %0 @java.ref:"ReflectableLambdaTest$Context::y:int";
134 %6 : java.type:"int" = add %4 %5;
135 %7 : java.type:"int" = var.load %3;
136 %8 : java.type:"int" = add %6 %7;
137 return %8;
138 };
139 return;
140 };
141 """)
142 static final IntUnaryOperator QUOTED_CAPTURE_FIELD = new Context().capture();
143
144 @Reflect
145 @IR("""
146 func @"captureParam" (%0 : java.type:"int")java.type:"void" -> {
147 %1 : Var<java.type:"int"> = var %0 @"x";
148 %2 : java.type:"java.util.function.IntUnaryOperator" = lambda @lambda.isQuotable=true (%3 : java.type:"int")java.type:"int" -> {
149 %4 : Var<java.type:"int"> = var %3 @"y";
150 %5 : java.type:"int" = var.load %1;
151 %6 : java.type:"int" = var.load %4;
152 %7 : java.type:"int" = add %5 %6;
153 return %7;
154 };
155 %8 : Var<java.type:"java.util.function.IntUnaryOperator"> = var %2 @"op";
156 return;
157 };
158 """)
159 static void captureParam(int x) {
160 IntUnaryOperator op = (@Reflect IntUnaryOperator) y -> x + y;
161 }
162
163 int x, y;
164
165 @Reflect
166 @IR("""
167 func @"captureField" (%0 : java.type:"ReflectableLambdaTest")java.type:"void" -> {
168 %1 : java.type:"java.util.function.IntUnaryOperator" = lambda @lambda.isQuotable=true (%2 : java.type:"int")java.type:"int" -> {
169 %3 : Var<java.type:"int"> = var %2 @"z";
170 %4 : java.type:"int" = field.load %0 @java.ref:"ReflectableLambdaTest::x:int";
171 %5 : java.type:"int" = field.load %0 @java.ref:"ReflectableLambdaTest::y:int";
172 %6 : java.type:"int" = add %4 %5;
173 %7 : java.type:"int" = var.load %3;
174 %8 : java.type:"int" = add %6 %7;
175 return %8;
176 };
177 %9 : Var<java.type:"java.util.function.IntUnaryOperator"> = var %1 @"op";
178 return;
179 };
180 """)
181 void captureField() {
182 IntUnaryOperator op = (@Reflect IntUnaryOperator) z -> x + y + z;
183 }
184
185 static void m() {
186 }
187
188 @IR("""
189 func @"f" ()java.type:"void" -> {
190 %0 : java.type:"java.lang.Runnable" = lambda @lambda.isQuotable=true ()java.type:"void" -> {
191 invoke @java.ref:"ReflectableLambdaTest::m():void";
192 return;
193 };
194 return;
195 };
196 """)
197 static final Runnable QUOTED_NO_PARAM_VOID_REF = (@Reflect Runnable) ReflectableLambdaTest::m;
198
199 static int g(int i) {
200 return i;
201 }
202
203 @IR("""
204 func @"f" ()java.type:"void" -> {
205 %0 : java.type:"java.util.function.IntUnaryOperator" = lambda @lambda.isQuotable=true (%1 : java.type:"int")java.type:"int" -> {
206 %2 : Var<java.type:"int"> = var %1 @"x$0";
207 %3 : java.type:"int" = var.load %2;
208 %4 : java.type:"int" = invoke %3 @java.ref:"ReflectableLambdaTest::g(int):int";
209 return %4;
210 };
211 return;
212 };
213 """)
214 static final IntUnaryOperator QUOTED_INT_PARAM_INT_RET_REF = (@Reflect IntUnaryOperator) ReflectableLambdaTest::g;
215
216 @IR("""
217 func @"f" ()java.type:"void" -> {
218 %0 : java.type:"java.util.function.IntFunction<int[]>" = lambda @lambda.isQuotable=true (%1 : java.type:"int")java.type:"int[]" -> {
219 %2 : Var<java.type:"int"> = var %1 @"x$0";
220 %3 : java.type:"int" = var.load %2;
221 %4 : java.type:"int[]" = new %3 @java.ref:"int[]::(int)";
222 return %4;
223 };
224 return;
225 };
226 """)
227 static final IntFunction<int[]> QUOTED_INT_PARAM_ARR_RET_REF = (@Reflect IntFunction<int[]>) int[]::new;
228
229 static class ContextRef {
230 int g(int i) {
231 return i;
232 }
233
234 IntUnaryOperator capture() {
235 return (@Reflect IntUnaryOperator) this::g;
236 }
237 }
238
239 @IR("""
240 func @"f" (%0 : java.type:"ReflectableLambdaTest$ContextRef")java.type:"void" -> {
241 %1 : java.type:"java.util.function.IntUnaryOperator" = lambda @lambda.isQuotable=true (%2 : java.type:"int")java.type:"int" -> {
242 %3 : Var<java.type:"int"> = var %2 @"x$0";
243 %4 : java.type:"int" = var.load %3;
244 %5 : java.type:"int" = invoke %0 %4 @java.ref:"ReflectableLambdaTest$ContextRef::g(int):int";
245 return %5;
246 };
247 return;
248 };
249 """)
250 static final IntUnaryOperator QUOTED_CAPTURE_THIS_REF = new ContextRef().capture();
251 }