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 import org.testng.Assert;
 25 import org.testng.annotations.Test;
 26 
 27 import jdk.incubator.code.OpTransformer;
 28 import jdk.incubator.code.dialect.core.CoreOp;
 29 import jdk.incubator.code.Op;
 30 import jdk.incubator.code.bytecode.BytecodeGenerator;
 31 
 32 import java.lang.invoke.MethodHandle;
 33 import java.lang.invoke.MethodHandles;
 34 import java.lang.reflect.Method;
 35 import jdk.incubator.code.CodeReflection;
 36 import java.util.Optional;
 37 import java.util.stream.Stream;
 38 
 39 /*
 40  * @test
 41  * @modules jdk.incubator.code
 42  * @run testng TestSlots
 43  */
 44 
 45 public class TestSlots {
 46     @CodeReflection
 47     static double f(double i, double j) {
 48         i = i + j;
 49 
 50         double k = 4.0;
 51         k += i;
 52         return k;
 53     }
 54 
 55     @Test
 56     public void testF() throws Throwable {
 57         CoreOp.FuncOp f = getFuncOp("f");
 58 
 59         MethodHandle mh = generate(f);
 60 
 61         Assert.assertEquals(f(1.0d, 2.0d), (double) mh.invoke(1.0d, 2.0d));
 62     }
 63 
 64     @CodeReflection
 65     static double f2(double x, double y) {
 66         return x * (-Math.sin(x * y) + y) * 4.0d;
 67     }
 68 
 69     @Test
 70     public void testF2() throws Throwable {
 71         CoreOp.FuncOp f = getFuncOp("f2");
 72 
 73         MethodHandle mh = generate(f);
 74 
 75         Assert.assertEquals(f2(1.0d, 2.0d), (double) mh.invoke(1.0d, 2.0d));
 76     }
 77 
 78     @CodeReflection
 79     static double f3(/* independent */ double x, int y) {
 80         /* dependent */
 81         double o = 1.0;
 82         for (int i = 0; i < y; i = i + 1) {
 83             if (i > 1) {
 84                 if (i < 5) {
 85                     o = o * x;
 86                 }
 87             }
 88         }
 89         return o;
 90     }
 91 
 92     @Test
 93     public void testF3() throws Throwable {
 94         CoreOp.FuncOp f = getFuncOp("f3");
 95 
 96         MethodHandle mh = generate(f);
 97 
 98         for (int i = 0; i < 7; i++) {
 99             Assert.assertEquals(f3(2.0d, i), (double) mh.invoke(2.0d, i));
100         }
101     }
102 
103     @CodeReflection
104     static int f4(/* Unused */ int a, int b) {
105         return b;
106     }
107 
108     @Test
109     public void testF4() throws Throwable {
110         CoreOp.FuncOp f = getFuncOp("f4");
111 
112         MethodHandle mh;
113         try {
114             mh = generate(f);
115         } catch (VerifyError e) {
116             Assert.fail("invalid class file generated", e);
117             return;
118         }
119 
120         Assert.assertEquals(f4(1, 2), (int) mh.invoke(1, 2));
121     }
122 
123     @CodeReflection
124     static double f5(/* Unused */ double a, double b) {
125         return b;
126     }
127 
128     @Test
129     public void testF5() throws Throwable {
130         CoreOp.FuncOp f = getFuncOp("f5");
131 
132         MethodHandle mh;
133         try {
134             mh = generate(f);
135         } catch (VerifyError e) {
136             Assert.fail("invalid class file generated", e);
137             return;
138         }
139 
140         Assert.assertEquals(f5(1.0, 2.0), (double) mh.invoke(1.0, 2.0));
141     }
142 
143     static MethodHandle generate(CoreOp.FuncOp f) {
144         System.out.println(f.toText());
145 
146         CoreOp.FuncOp lf = f.transform(OpTransformer.LOWERING_TRANSFORMER);
147         System.out.println(lf.toText());
148 
149         return BytecodeGenerator.generate(MethodHandles.lookup(), lf);
150     }
151 
152     static CoreOp.FuncOp getFuncOp(String name) {
153         Optional<Method> om = Stream.of(TestSlots.class.getDeclaredMethods())
154                 .filter(m -> m.getName().equals(name))
155                 .findFirst();
156 
157         Method m = om.get();
158         return Op.ofMethod(m).get();
159     }
160 
161 }