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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package hat.optools; 26 27 import java.lang.invoke.MethodHandles; 28 import java.lang.reflect.Method; 29 import jdk.incubator.code.CopyContext; 30 import jdk.incubator.code.Op; 31 import jdk.incubator.code.Value; 32 import jdk.incubator.code.op.CoreOp; 33 import jdk.incubator.code.type.MethodRef; 34 import java.util.ArrayDeque; 35 import java.util.ArrayList; 36 import java.util.Deque; 37 import java.util.LinkedHashSet; 38 import java.util.List; 39 import java.util.Optional; 40 41 public class ModuleOpWrapper extends OpWrapper<CoreOp.ModuleOp> { 42 ModuleOpWrapper(CoreOp.ModuleOp op) { 43 super(op); 44 } 45 46 record MethodRefToEntryFuncOpCall(MethodRef methodRef, CoreOp.FuncOp funcOp) { 47 } 48 49 record Closure(Deque<MethodRefToEntryFuncOpCall> work, LinkedHashSet<MethodRef> funcsVisited, 50 List<CoreOp.FuncOp> moduleFuncOps) { 51 } 52 53 public static ModuleOpWrapper createTransitiveInvokeModule(MethodHandles.Lookup lookup, 54 Method entryPoint) { 55 Optional<CoreOp.FuncOp> codeModel = Op.ofMethod(entryPoint); 56 if (codeModel.isPresent()) { 57 return OpWrapper.wrap(createTransitiveInvokeModule(lookup, MethodRef.method(entryPoint), codeModel.get())); 58 } else { 59 return OpWrapper.wrap(CoreOp.module(List.of())); 60 } 61 } 62 /* static Method resolveToMethod(MethodHandles.Lookup lookup, MethodRef invokedMethodRef){ 63 Method invokedMethod = null; 64 try { 65 invokedMethod = invokedMethodRef.resolveToMethod(lookup); 66 } catch (ReflectiveOperationException e) { 67 throw new RuntimeException(e); 68 } 69 return invokedMethod; 70 } */ 71 72 static CoreOp.ModuleOp createTransitiveInvokeModule(MethodHandles.Lookup lookup, 73 MethodRef methodRef, CoreOp.FuncOp entryFuncOp) { 74 Closure closure = new Closure(new ArrayDeque<>(), new LinkedHashSet<>(), new ArrayList<>()); 75 closure.work.push(new MethodRefToEntryFuncOpCall(methodRef, entryFuncOp)); 76 while (!closure.work.isEmpty()) { 77 MethodRefToEntryFuncOpCall methodRefToEntryFuncOpCall = closure.work.pop(); 78 if (closure.funcsVisited.add(methodRefToEntryFuncOpCall.methodRef)) { 79 CoreOp.FuncOp tf = methodRefToEntryFuncOpCall.funcOp.transform( 80 methodRefToEntryFuncOpCall.methodRef.toString(), (blockBuilder, op) -> { 81 if (op instanceof CoreOp.InvokeOp invokeOp && OpWrapper.wrap(invokeOp) instanceof InvokeOpWrapper invokeOpWrapper) { 82 Method invokedMethod = invokeOpWrapper.method(lookup); 83 Optional<CoreOp.FuncOp> optionalInvokedFuncOp = Op.ofMethod(invokedMethod); 84 if (optionalInvokedFuncOp.isPresent() && OpWrapper.wrap(optionalInvokedFuncOp.get()) instanceof FuncOpWrapper funcOpWrapper) { 85 MethodRefToEntryFuncOpCall call = 86 new MethodRefToEntryFuncOpCall(invokeOpWrapper.methodRef(), funcOpWrapper.op()); 87 closure.work.push(call); 88 CopyContext copyContext = blockBuilder.context(); 89 List<Value> operands = copyContext.getValues(invokeOp.operands()); 90 CoreOp.FuncCallOp replacementCall = CoreOp.funcCall( 91 call.methodRef.toString(), 92 call.funcOp.invokableType(), 93 operands); 94 Op.Result replacementResult = blockBuilder.op(replacementCall); 95 copyContext.mapValue(invokeOp.result(), replacementResult); 96 // System.out.println("replaced " + call); 97 } else { 98 // System.out.println("We have no code model for " + invokeOpWrapper.methodRef()); 99 blockBuilder.op(invokeOp); 100 } 101 } else { 102 blockBuilder.op(op); 103 } 104 return blockBuilder; 105 }); 106 closure.moduleFuncOps.add(tf); 107 } 108 } 109 110 return CoreOp.module(closure.moduleFuncOps); 111 } 112 }