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