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.*; 28 import jdk.incubator.code.op.CoreOp; 29 import jdk.incubator.code.interpreter.Interpreter; 30 import java.lang.invoke.MethodHandles; 31 import jdk.incubator.code.type.JavaType; 32 import java.util.List; 33 34 import static jdk.incubator.code.op.CoreOp.*; 35 import static jdk.incubator.code.type.FunctionType.functionType; 36 import static jdk.incubator.code.type.JavaType.INT; 37 38 /* 39 * @test 40 * @modules jdk.incubator.code 41 * @run testng TestInline 42 */ 43 44 public class TestInline { 45 46 @Test 47 public void testInline() { 48 Quoted q = (int a, int b) -> a + b; 49 CoreOp.ClosureOp cop = (CoreOp.ClosureOp) q.op(); 50 51 // functional type = (int)int 52 CoreOp.FuncOp f = func("f", functionType(INT, INT)) 53 .body(fblock -> { 54 Block.Parameter i = fblock.parameters().get(0); 55 56 Op.Result fortyTwo = fblock.op(constant(INT, 42)); 57 58 var cb = fblock.inline(cop, List.of(i, fortyTwo), Block.Builder.INLINE_RETURN); 59 Assert.assertEquals(fblock, cb); 60 }); 61 62 f.writeTo(System.out); 63 64 int ir = (int) Interpreter.invoke(MethodHandles.lookup(), f, 1); 65 Assert.assertEquals(ir, 43); 66 } 67 68 @Test 69 public void testInlineVar() { 70 Quoted q = (int a, int b) -> a + b; 71 CoreOp.ClosureOp cop = (CoreOp.ClosureOp) q.op(); 72 73 // functional type = (int)int 74 CoreOp.FuncOp f = func("f", functionType(INT, INT)) 75 .body(fblock -> { 76 Block.Parameter i = fblock.parameters().get(0); 77 78 Op.Result fortyTwo = fblock.op(constant(INT, 42)); 79 80 Op.Result v = fblock.op(var(fblock.op(constant(INT, 0)))); 81 82 var cb = fblock.inline(cop, List.of(i, fortyTwo), (b, value) -> { 83 b.op(varStore(v, value)); 84 }); 85 Assert.assertEquals(fblock, cb); 86 87 fblock.op(_return(fblock.op(varLoad(v)))); 88 }); 89 90 f.writeTo(System.out); 91 92 int ir = (int) Interpreter.invoke(MethodHandles.lookup(), f, 1); 93 Assert.assertEquals(ir, 43); 94 } 95 96 97 @Test 98 public void testInlineLowerMultipleReturn() { 99 Quoted q = (int a, int b) -> { 100 if (a < 10) { 101 return a + b; 102 } 103 return a - b; 104 }; 105 CoreOp.ClosureOp cop = (CoreOp.ClosureOp) q.op(); 106 cop.writeTo(System.out); 107 CoreOp.ClosureOp lcop = cop.transform(CopyContext.create(), OpTransformer.LOWERING_TRANSFORMER); 108 lcop.writeTo(System.out); 109 110 // functional type = (int)int 111 CoreOp.FuncOp f = func("f", functionType(INT, INT)) 112 .body(fblock -> { 113 Block.Parameter i = fblock.parameters().get(0); 114 115 Op.Result fortyTwo = fblock.op(constant(INT, 42)); 116 117 var cb = fblock.inline(lcop, List.of(i, fortyTwo), Block.Builder.INLINE_RETURN); 118 Assert.assertNotEquals(fblock, cb); 119 }); 120 f.writeTo(System.out); 121 122 int ir = (int) Interpreter.invoke(MethodHandles.lookup(), f, 1); 123 Assert.assertEquals(ir, 43); 124 } 125 126 @Test 127 public void testInlineLowerMultipleReturnVar() { 128 Quoted q = (int a, int b) -> { 129 if (a < 10) { 130 return a + b; 131 } 132 return a - b; 133 }; 134 CoreOp.ClosureOp cop = (CoreOp.ClosureOp) q.op(); 135 cop.writeTo(System.out); 136 CoreOp.ClosureOp lcop = cop.transform(CopyContext.create(), OpTransformer.LOWERING_TRANSFORMER); 137 lcop.writeTo(System.out); 138 139 // functional type = (int)int 140 CoreOp.FuncOp f = func("f", functionType(INT, INT)) 141 .body(fblock -> { 142 Block.Parameter i = fblock.parameters().get(0); 143 144 Op.Result fortyTwo = fblock.op(constant(INT, 42)); 145 146 Op.Result v = fblock.op(var(fblock.op(constant(INT, 0)))); 147 148 var cb = fblock.inline(lcop, List.of(i, fortyTwo), (b, value) -> { 149 b.op(varStore(v, value)); 150 }); 151 Assert.assertNotEquals(fblock, cb); 152 153 cb.op(_return(cb.op(varLoad(v)))); 154 }); 155 f.writeTo(System.out); 156 157 int ir = (int) Interpreter.invoke(MethodHandles.lookup(), f, 1); 158 Assert.assertEquals(ir, 43); 159 } 160 161 @Test 162 public void testInlineMultipleReturnLower() { 163 Quoted q = (int a, int b) -> { 164 if (a < 10) { 165 return a + b; 166 } 167 return a - b; 168 }; 169 CoreOp.ClosureOp cop = (CoreOp.ClosureOp) q.op(); 170 cop.writeTo(System.out); 171 172 CoreOp.FuncOp f = func("f", functionType(INT, INT)) 173 .body(fblock -> { 174 Block.Parameter i = fblock.parameters().get(0); 175 176 Op.Result fortyTwo = fblock.op(constant(INT, 42)); 177 178 var cb = fblock.inline(cop, List.of(i, fortyTwo), Block.Builder.INLINE_RETURN); 179 Assert.assertEquals(fblock, cb); 180 }); 181 f.writeTo(System.out); 182 183 f = f.transform(OpTransformer.LOWERING_TRANSFORMER); 184 f.writeTo(System.out); 185 186 int ir = (int) Interpreter.invoke(MethodHandles.lookup(), f, 1); 187 Assert.assertEquals(ir, 43); 188 } 189 190 @Test 191 public void testInlineVoid() { 192 Quoted q = (int[] a) -> { 193 a[0] = 42; 194 return; 195 }; 196 CoreOp.ClosureOp cop = (CoreOp.ClosureOp) q.op(); 197 198 // functional type = (int)int 199 CoreOp.FuncOp f = func("f", functionType(JavaType.VOID, JavaType.type(int[].class))) 200 .body(fblock -> { 201 Block.Parameter a = fblock.parameters().get(0); 202 203 var cb = fblock.inline(cop, List.of(a), Block.Builder.INLINE_RETURN); 204 Assert.assertEquals(fblock, cb); 205 }); 206 207 f.writeTo(System.out); 208 209 int[] a = new int[1]; 210 Interpreter.invoke(MethodHandles.lookup(), f, a); 211 Assert.assertEquals(a[0], 42); 212 } 213 214 }