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.isReflectable=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.isReflectable=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.isReflectable=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.isReflectable=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.isReflectable=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 static class ParamContext {
103 IntUnaryOperator captureContext(int x) {
104 return (@Reflect IntUnaryOperator) y -> x + y;
105 }
106 }
107
108 @IR("""
109 func @"f" (%0 : Var<java.type:"int">)java.type:"void" -> {
110 %1 : java.type:"java.util.function.IntUnaryOperator" = lambda @lambda.isReflectable=true (%2 : java.type:"int")java.type:"int" -> {
111 %3 : Var<java.type:"int"> = var %2 @"y";
112 %4 : java.type:"int" = var.load %0;
113 %5 : java.type:"int" = var.load %3;
114 %6 : java.type:"int" = add %4 %5;
115 return %6;
116 };
117 return;
118 };
119 """)
120 static final IntUnaryOperator QUOTED_CAPTURE_PARAM = new ParamContext().captureContext(42);
121
122 static class Context {
123 int x, y;
124
125 IntUnaryOperator capture() {
126 return (@Reflect IntUnaryOperator) z -> x + y + z;
127 }
128 }
129
130 @IR("""
131 func @"f" (%0 : java.type:"ReflectableLambdaTest$Context")java.type:"void" -> {
132 %1 : java.type:"java.util.function.IntUnaryOperator" = lambda @lambda.isReflectable=true (%2 : java.type:"int")java.type:"int" -> {
133 %3 : Var<java.type:"int"> = var %2 @"z";
134 %4 : java.type:"int" = field.load %0 @java.ref:"ReflectableLambdaTest$Context::x:int";
135 %5 : java.type:"int" = field.load %0 @java.ref:"ReflectableLambdaTest$Context::y:int";
136 %6 : java.type:"int" = add %4 %5;
137 %7 : java.type:"int" = var.load %3;
138 %8 : java.type:"int" = add %6 %7;
139 return %8;
140 };
141 return;
142 };
143 """)
144 static final IntUnaryOperator QUOTED_CAPTURE_FIELD = new Context().capture();
145
146 @Reflect
147 @IR("""
148 func @"captureParam" (%0 : java.type:"int")java.type:"void" -> {
149 %1 : Var<java.type:"int"> = var %0 @"x";
150 %2 : java.type:"java.util.function.IntUnaryOperator" = lambda @lambda.isReflectable=true (%3 : java.type:"int")java.type:"int" -> {
151 %4 : Var<java.type:"int"> = var %3 @"y";
152 %5 : java.type:"int" = var.load %1;
153 %6 : java.type:"int" = var.load %4;
154 %7 : java.type:"int" = add %5 %6;
155 return %7;
156 };
157 %8 : Var<java.type:"java.util.function.IntUnaryOperator"> = var %2 @"op";
158 return;
159 };
160 """)
161 static void captureParam(int x) {
162 IntUnaryOperator op = (@Reflect IntUnaryOperator) y -> x + y;
163 }
164
165 int x, y;
166
167 @Reflect
168 @IR("""
169 func @"captureField" (%0 : java.type:"ReflectableLambdaTest")java.type:"void" -> {
170 %1 : java.type:"java.util.function.IntUnaryOperator" = lambda @lambda.isReflectable=true (%2 : java.type:"int")java.type:"int" -> {
171 %3 : Var<java.type:"int"> = var %2 @"z";
172 %4 : java.type:"int" = field.load %0 @java.ref:"ReflectableLambdaTest::x:int";
173 %5 : java.type:"int" = field.load %0 @java.ref:"ReflectableLambdaTest::y:int";
174 %6 : java.type:"int" = add %4 %5;
175 %7 : java.type:"int" = var.load %3;
176 %8 : java.type:"int" = add %6 %7;
177 return %8;
178 };
179 %9 : Var<java.type:"java.util.function.IntUnaryOperator"> = var %1 @"op";
180 return;
181 };
182 """)
183 void captureField() {
184 IntUnaryOperator op = (@Reflect IntUnaryOperator) z -> x + y + z;
185 }
186
187 static void m() {
188 }
189
190 @IR("""
191 func @"f" ()java.type:"void" -> {
192 %0 : java.type:"java.lang.Runnable" = lambda @lambda.isReflectable=true ()java.type:"void" -> {
193 invoke @java.ref:"ReflectableLambdaTest::m():void";
194 return;
195 };
196 return;
197 };
198 """)
199 static final Runnable QUOTED_NO_PARAM_VOID_REF = (@Reflect Runnable) ReflectableLambdaTest::m;
200
201 static int g(int i) {
202 return i;
203 }
204
205 @IR("""
206 func @"f" ()java.type:"void" -> {
207 %0 : java.type:"java.util.function.IntUnaryOperator" = lambda @lambda.isReflectable=true (%1 : java.type:"int")java.type:"int" -> {
208 %2 : Var<java.type:"int"> = var %1 @"x$0";
209 %3 : java.type:"int" = var.load %2;
210 %4 : java.type:"int" = invoke %3 @java.ref:"ReflectableLambdaTest::g(int):int";
211 return %4;
212 };
213 return;
214 };
215 """)
216 static final IntUnaryOperator QUOTED_INT_PARAM_INT_RET_REF = (@Reflect IntUnaryOperator) ReflectableLambdaTest::g;
217
218 @IR("""
219 func @"f" ()java.type:"void" -> {
220 %0 : java.type:"java.util.function.IntFunction<int[]>" = lambda @lambda.isReflectable=true (%1 : java.type:"int")java.type:"int[]" -> {
221 %2 : Var<java.type:"int"> = var %1 @"x$0";
222 %3 : java.type:"int" = var.load %2;
223 %4 : java.type:"int[]" = new %3 @java.ref:"int[]::(int)";
224 return %4;
225 };
226 return;
227 };
228 """)
229 static final IntFunction<int[]> QUOTED_INT_PARAM_ARR_RET_REF = (@Reflect IntFunction<int[]>) int[]::new;
230
231 static class ContextRef {
232 int g(int i) {
233 return i;
234 }
235
236 IntUnaryOperator capture() {
237 return (@Reflect IntUnaryOperator) this::g;
238 }
239 }
240
241 @IR("""
242 func @"f" (%0 : java.type:"ReflectableLambdaTest$ContextRef")java.type:"void" -> {
243 %1 : java.type:"java.util.function.IntUnaryOperator" = lambda @lambda.isReflectable=true (%2 : java.type:"int")java.type:"int" -> {
244 %3 : Var<java.type:"int"> = var %2 @"x$0";
245 %4 : java.type:"int" = var.load %3;
246 %5 : java.type:"int" = invoke %0 %4 @java.ref:"ReflectableLambdaTest$ContextRef::g(int):int";
247 return %5;
248 };
249 return;
250 };
251 """)
252 static final IntUnaryOperator QUOTED_CAPTURE_THIS_REF = new ContextRef().capture();
253 }