1 /*
  2  * Copyright (c) 2024, 2026, 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 import jdk.incubator.code.Reflect;
 25 import java.util.ArrayList;
 26 import java.util.List;
 27 
 28 /*
 29  * @test
 30  * @summary Smoke test for code reflection with method calls.
 31  * @modules jdk.incubator.code
 32  * @build MethodCallTest
 33  * @build CodeReflectionTester
 34  * @run main CodeReflectionTester MethodCallTest
 35  */
 36 
 37 public class MethodCallTest {
 38 
 39     void m() {
 40     }
 41 
 42     int m_int() {
 43         return 0;
 44     }
 45 
 46     @Reflect
 47     @IR("""
 48             func @"test1" (%0 : java.type:"MethodCallTest")java.type:"void" -> {
 49                 invoke %0 @java.ref:"MethodCallTest::m():void";
 50                 return;
 51             };
 52             """)
 53     void test1() {
 54         m();
 55     }
 56 
 57     @Reflect
 58     @IR("""
 59             func @"test2" (%0 : java.type:"MethodCallTest")java.type:"void" -> {
 60                 invoke %0 @java.ref:"MethodCallTest::m():void";
 61                 return;
 62             };
 63             """)
 64     void test2() {
 65         this.m();
 66     }
 67 
 68     @Reflect
 69     @IR("""
 70             func @"test2_1" (%0 : java.type:"MethodCallTest")java.type:"void" -> {
 71                 invoke %0 @java.ref:"MethodCallTest::m():void";
 72                 return;
 73             };
 74             """)
 75     void test2_1() {
 76         MethodCallTest.this.m();
 77     }
 78 
 79     @Reflect
 80     @IR("""
 81             func @"test3" (%0 : java.type:"MethodCallTest")java.type:"int" -> {
 82                 %1 : java.type:"int" = invoke %0 @java.ref:"MethodCallTest::m_int():int";
 83                 return %1;
 84             };
 85             """)
 86     int test3() {
 87         return m_int();
 88     }
 89 
 90 
 91     static void ms() {
 92     }
 93 
 94     @Reflect
 95     @IR("""
 96             func @"test4" (%0 : java.type:"MethodCallTest")java.type:"void" -> {
 97                 invoke @java.ref:"MethodCallTest::ms():void";
 98                 return;
 99             };
100             """)
101     void test4() {
102         ms();
103     }
104 
105     @Reflect
106     @IR("""
107             func @"test4_1" (%0 : java.type:"MethodCallTest")java.type:"void" -> {
108                 invoke @java.ref:"MethodCallTest::ms():void";
109                 return;
110             };
111             """)
112     void test4_1() {
113         MethodCallTest.ms();
114     }
115 
116     @Reflect
117     @IR("""
118             func @"test4_2" (%0 : java.type:"MethodCallTest")java.type:"java.util.List<java.lang.String>" -> {
119                 %1 : java.type:"java.util.List<java.lang.String>" = invoke @java.ref:"java.util.List::of():java.util.List";
120                 return %1;
121             };
122             """)
123     List<String> test4_2() {
124         return List.of();
125     }
126 
127     String m(int i, String s, List<Number> l) {
128         return s;
129     }
130 
131     @Reflect
132     @IR("""
133             func @"test5" (%0 : java.type:"MethodCallTest", %1 : java.type:"java.util.List<java.lang.Number>")java.type:"void" -> {
134                 %2 : Var<java.type:"java.util.List<java.lang.Number>"> = var %1 @"l";
135                 %3 : java.type:"int" = constant @1;
136                 %4 : java.type:"java.lang.String" = constant @"1";
137                 %5 : java.type:"java.util.List<java.lang.Number>" = var.load %2;
138                 %6 : java.type:"java.lang.String" = invoke %0 %3 %4 %5 @java.ref:"MethodCallTest::m(int, java.lang.String, java.util.List):java.lang.String";
139                 %7 : Var<java.type:"java.lang.String"> = var %6 @"s";
140                 return;
141             };
142             """)
143     void test5(List<Number> l) {
144         String s = m(1, "1", l);
145     }
146 
147 
148     static class A {
149         B b;
150 
151         B m() {
152             return null;
153         }
154     }
155 
156     static class B {
157         C m() {
158             return null;
159         }
160     }
161 
162     static class C {
163         int m() {
164             return 0;
165         }
166     }
167 
168     @Reflect
169     @IR("""
170             func @"test6" (%0 : java.type:"MethodCallTest", %1 : java.type:"MethodCallTest$A")java.type:"void" -> {
171                 %2 : Var<java.type:"MethodCallTest$A"> = var %1 @"a";
172                 %3 : java.type:"MethodCallTest$A" = var.load %2;
173                 %4 : java.type:"MethodCallTest$B" = invoke %3 @java.ref:"MethodCallTest$A::m():MethodCallTest$B";
174                 %5 : java.type:"MethodCallTest$C" = invoke %4 @java.ref:"MethodCallTest$B::m():MethodCallTest$C";
175                 %6 : java.type:"int" = invoke %5 @java.ref:"MethodCallTest$C::m():int";
176                 return;
177             };
178             """)
179     void test6(A a) {
180         a.m().m().m();
181     }
182 
183     @Reflect
184     @IR("""
185             func @"test7" (%0 : java.type:"MethodCallTest", %1 : java.type:"MethodCallTest$A")java.type:"void" -> {
186                 %2 : Var<java.type:"MethodCallTest$A"> = var %1 @"a";
187                 %3 : java.type:"MethodCallTest$A" = var.load %2;
188                 %4 : java.type:"MethodCallTest$B" = field.load %3 @java.ref:"MethodCallTest$A::b:MethodCallTest$B";
189                 %5 : java.type:"MethodCallTest$C" = invoke %4 @java.ref:"MethodCallTest$B::m():MethodCallTest$C";
190                 return;
191             };
192             """)
193     void test7(A a) {
194         a.b.m();
195     }
196 
197     @Reflect
198     @IR("""
199             func @"test8" (%0 : java.type:"MethodCallTest", %1 : java.type:"java.lang.String")java.type:"void" -> {
200                 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
201                 %3 : java.type:"java.io.PrintStream" = field.load @java.ref:"java.lang.System::out:java.io.PrintStream";
202                 %4 : java.type:"java.lang.String" = var.load %2;
203                 invoke %3 %4 @java.ref:"java.io.PrintStream::println(java.lang.String):void";
204                 return;
205             };
206             """)
207     void test8(String s) {
208         System.out.println(s);
209     }
210 
211     static class X {
212         int x;
213         void x() {}
214 
215         static void sx() {}
216     }
217 
218     static class Y extends X {
219         void y() {}
220         static void sy() {}
221 
222         @Reflect
223         @IR("""
224                 func @"test" (%0 : java.type:"MethodCallTest$Y")java.type:"void" -> {
225                     invoke %0 @java.ref:"MethodCallTest$Y::x():void";
226                     invoke %0 @java.ref:"MethodCallTest$Y::y():void";
227                     invoke @java.ref:"MethodCallTest$Y::sx():void";
228                     invoke @java.ref:"MethodCallTest$Y::sy():void";
229                     invoke @java.ref:"MethodCallTest$Y::sx():void";
230                     invoke @java.ref:"MethodCallTest$Y::sy():void";
231                     return;
232                 };
233                 """)
234         void test() {
235             x();
236             y();
237 
238             sx();
239             sy();
240 
241             Y.sx();
242             Y.sy();
243         }
244     }
245 
246     @Reflect
247     @IR("""
248             func @"test9" (%0 : java.type:"MethodCallTest$Y")java.type:"void" -> {
249                 %1 : Var<java.type:"MethodCallTest$Y"> = var %0 @"y";
250                 %2 : java.type:"MethodCallTest$Y" = var.load %1;
251                 invoke %2 @java.ref:"MethodCallTest$Y::x():void";
252                 %3 : java.type:"MethodCallTest$Y" = var.load %1;
253                 invoke %3 @java.ref:"MethodCallTest$Y::y():void";
254                 %4 : java.type:"MethodCallTest$Y" = var.load %1;
255                 invoke @java.ref:"MethodCallTest$Y::sx():void";
256                 %5 : java.type:"MethodCallTest$Y" = var.load %1;
257                 invoke @java.ref:"MethodCallTest$Y::sy():void";
258                 invoke @java.ref:"MethodCallTest$Y::sx():void";
259                 invoke @java.ref:"MethodCallTest$Y::sy():void";
260                 return;
261             };
262             """)
263     static void test9(Y y) {
264         y.x();
265         y.y();
266 
267         y.sx();
268         y.sy();
269 
270         Y.sx();
271         Y.sy();
272     }
273 
274     @Reflect
275     @IR("""
276             func @"test10" (%0 : java.type:"java.util.ArrayList<java.lang.String>")java.type:"void" -> {
277                 %1 : Var<java.type:"java.util.ArrayList<java.lang.String>"> = var %0 @"al";
278                 %2 : java.type:"java.util.ArrayList<java.lang.String>" = var.load %1;
279                 %3 : java.type:"int" = constant @0;
280                 %4 : java.type:"java.lang.String" = invoke %2 %3 @java.ref:"java.util.ArrayList::get(int):java.lang.Object";
281                 %5 : java.type:"java.lang.String" = cast %4 @java.type:"java.lang.String";
282                 %6 : Var<java.type:"java.lang.String"> = var %5 @"s";
283                 %7 : java.type:"java.util.ArrayList<java.lang.String>" = var.load %1;
284                 %8 : Var<java.type:"java.util.List<java.lang.String>"> = var %7 @"l";
285                 %9 : java.type:"java.util.List<java.lang.String>" = var.load %8;
286                 %10 : java.type:"int" = constant @0;
287                 %11 : java.type:"java.lang.String" = invoke %9 %10 @java.ref:"java.util.List::get(int):java.lang.Object";
288                 %12 : java.type:"java.lang.String" = cast %11 @java.type:"java.lang.String";
289                 var.store %6 %12;
290                 return;
291             };
292             """)
293     static void test10(ArrayList<String> al) {
294         String s = al.get(0);
295         List<String> l = al;
296         s = l.get(0);
297     }
298 
299     @Reflect
300     @IR("""
301             func @"test11" (%0 : java.type:"java.lang.Object[]")java.type:"java.lang.Object[]" -> {
302                 %1 : Var<java.type:"java.lang.Object[]"> = var %0 @"values";
303                 %2 : java.type:"java.lang.Object[]" = var.load %1;
304                 %3 : java.type:"java.lang.Object[]" = invoke %2 @java.ref:"java.lang.Object[]::clone():java.lang.Object";
305                 %4 : java.type:"java.lang.Object[]" = cast %3 @java.type:"java.lang.Object[]";
306                 return %4;
307             };
308             """)
309     static Object[] test11(Object[] values) {
310         return values.clone();
311     }
312 
313     @Reflect
314     @IR("""
315             func @"test12" (%0 : java.type:"int[]")java.type:"int[]" -> {
316                 %1 : Var<java.type:"int[]"> = var %0 @"values";
317                 %2 : java.type:"int[]" = var.load %1;
318                 %3 : java.type:"int[]" = invoke %2 @java.ref:"int[]::clone():java.lang.Object";
319                 %4 : java.type:"int[]" = cast %3 @java.type:"int[]";
320                 return %4;
321             };
322             """)
323     static int[] test12(int[] values) {
324         return values.clone();
325     }
326 
327 
328     @Reflect
329     @IR("""
330             func @"test13" (%0 : java.type:"java.lang.Comparable<java.lang.String>[]")java.type:"java.lang.Comparable<java.lang.String>[]" -> {
331                 %1 : Var<java.type:"java.lang.Comparable<java.lang.String>[]"> = var %0 @"values";
332                 %2 : java.type:"java.lang.Comparable<java.lang.String>[]" = var.load %1;
333                 %3 : java.type:"java.lang.Comparable<java.lang.String>[]" = invoke %2 @java.ref:"java.lang.Comparable[]::clone():java.lang.Object";
334                 %4 : java.type:"java.lang.Comparable<java.lang.String>[]" = cast %3 @java.type:"java.lang.Comparable[]";
335                 return %4;
336             };
337             """)
338     static Comparable<String>[] test13(Comparable<String>[] values) {
339         return values.clone();
340     }
341 
342     @Reflect
343     @IR("""
344             func @"test14" (%0 : java.type:"java.lang.Object[]")java.type:"java.lang.Class<? extends java.lang.Object[]>" -> {
345                 %1 : Var<java.type:"java.lang.Object[]"> = var %0 @"values";
346                 %2 : java.type:"java.lang.Object[]" = var.load %1;
347                 %3 : java.type:"java.lang.Class<? extends java.lang.Object[]>" = invoke %2 @java.ref:"java.lang.Object::getClass():java.lang.Class";
348                 return %3;
349             };
350             """)
351     static Class<? extends Object[]> test14(Object[] values) {
352         return values.getClass();
353     }
354 
355     @Reflect
356     @IR("""
357             func @"test15" (%0 : java.type:"int[]")java.type:"java.lang.Class<? extends int[]>" -> {
358                 %1 : Var<java.type:"int[]"> = var %0 @"values";
359                 %2 : java.type:"int[]" = var.load %1;
360                 %3 : java.type:"java.lang.Class<? extends int[]>" = invoke %2 @java.ref:"java.lang.Object::getClass():java.lang.Class";
361                 return %3;
362             };
363             """)
364     static Class<? extends int[]> test15(int[] values) {
365         return values.getClass();
366     }
367 
368 
369     @Reflect
370     @IR("""
371             func @"test16" (%0 : java.type:"java.lang.Comparable<java.lang.String>[]")java.type:"java.lang.Class<? extends java.lang.Comparable[]>" -> {
372                 %1 : Var<java.type:"java.lang.Comparable<java.lang.String>[]"> = var %0 @"values";
373                 %2 : java.type:"java.lang.Comparable<java.lang.String>[]" = var.load %1;
374                 %3 : java.type:"java.lang.Class<? extends java.lang.Comparable[]>" = invoke %2 @java.ref:"java.lang.Object::getClass():java.lang.Class";
375                 return %3;
376             };
377             """)
378     static Class<? extends Comparable[]> test16(Comparable<String>[] values) {
379         return values.getClass();
380     }
381 
382     @Reflect
383     @IR("""
384             func @"test17" (%0 : java.type:"MethodCallTest")java.type:"java.lang.Class<? extends MethodCallTest>" -> {
385                 %1 : java.type:"java.lang.Class<? extends MethodCallTest>" = invoke %0 @java.ref:"java.lang.Object::getClass():java.lang.Class";
386                 return %1;
387             };
388             """)
389     Class<? extends MethodCallTest> test17() {
390         return getClass();
391     }
392 
393     @Reflect
394     @IR("""
395             func @"test18" (%0 : java.type:"MethodCallTest")java.type:"java.lang.Class<? extends MethodCallTest>" -> {
396                 %1 : Var<java.type:"MethodCallTest"> = var %0 @"rec";
397                 %2 : java.type:"MethodCallTest" = var.load %1;
398                 %3 : java.type:"java.lang.Class<? extends MethodCallTest>" = invoke %2 @java.ref:"java.lang.Object::getClass():java.lang.Class";
399                 return %3;
400             };
401             """)
402     static Class<? extends MethodCallTest> test18(MethodCallTest rec) {
403         return rec.getClass();
404     }
405 
406     @Reflect
407     @IR("""
408             func @"test19" (%0 : java.type:"java.lang.Enum<?>")java.type:"java.lang.Class<?>" -> {
409                 %1 : Var<java.type:"java.lang.Enum<?>"> = var %0 @"value";
410                 %2 : java.type:"java.lang.Enum<?>" = var.load %1;
411                 %3 : java.type:"java.lang.Class<? extends java.lang.Enum<?>>" = invoke %2 @java.ref:"java.lang.Enum::getDeclaringClass():java.lang.Class";
412                 return %3;
413             };
414             """)
415     static Class<?> test19(Enum<?> value) {
416         return value.getDeclaringClass(); // check no stack overflow when normalizing recursive capture type
417     }
418 }