1 /* 2 * Copyright (c) 2009, 2011, 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 package com.oracle.graal.compiler.hsail; 25 26 import com.oracle.graal.api.code.CompilationResult; 27 import java.lang.reflect.Method; 28 29 import com.amd.okra.OkraContext; 30 import com.amd.okra.OkraKernel; 31 import com.oracle.graal.hotspot.HotSpotGraalRuntime; 32 import com.oracle.graal.hotspot.HotSpotVMConfig; 33 import com.oracle.graal.hotspot.amd64.AMD64HotSpotRuntime; 34 import com.oracle.graal.api.meta.*; 35 import com.oracle.graal.api.runtime.Graal; 36 import com.oracle.graal.java.GraphBuilderConfiguration; 37 import com.oracle.graal.java.GraphBuilderPhase; 38 import com.oracle.graal.nodes.StructuredGraph; 39 import com.oracle.graal.nodes.java.MethodCallTargetNode; 40 import com.oracle.graal.nodes.spi.Replacements; 41 import com.oracle.graal.phases.OptimisticOptimizations; 42 import com.oracle.graal.graph.Node; 43 import com.oracle.graal.graph.iterators.*; 44 import com.oracle.graal.compiler.target.Backend; 45 import com.oracle.graal.nodes.spi.GraalCodeCacheProvider; 46 import com.oracle.graal.debug.*; 47 48 /** 49 * Implements compile and dispatch of Java code containing lambda constructs. Currently only used by 50 * JDK interception code that offloads to the GPU. 51 */ 52 public class ForEachToGraal implements CompileAndDispatch { 53 54 protected final GraalCodeCacheProvider runtime; 55 protected final Replacements replacements; 56 protected final Backend backend; 57 58 public ForEachToGraal() { 59 this.runtime = Graal.getRequiredCapability(GraalCodeCacheProvider.class); 60 this.replacements = Graal.getRequiredCapability(Replacements.class); 61 this.backend = Graal.getRequiredCapability(Backend.class); 62 } 63 64 private static CompilationResult getCompiledLambda(Class consumerClass) { 65 /** 66 * Find the accept() method in the IntConsumer, then use Graal API to find the target lambda 67 * that accept will call. 68 */ 69 Method[] icMethods = consumerClass.getMethods(); 70 Method acceptMethod = null; 71 for (Method m : icMethods) { 72 if (m.getName().equals("accept") && acceptMethod == null) { 73 acceptMethod = m; 74 } 75 } 76 HotSpotVMConfig config = HotSpotGraalRuntime.graalRuntime().getConfig(); 77 AMD64HotSpotRuntime hsruntime = new AMD64HotSpotRuntime(config, HotSpotGraalRuntime.graalRuntime()); 78 ResolvedJavaMethod rm = hsruntime.lookupJavaMethod(acceptMethod); 79 StructuredGraph graph = new StructuredGraph(rm); 80 new GraphBuilderPhase(hsruntime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); 81 NodeIterable<Node> nin = graph.getNodes(); 82 ResolvedJavaMethod lambdaMethod = null; 83 for (Node n : nin) { 84 if (n instanceof MethodCallTargetNode) { 85 lambdaMethod = ((MethodCallTargetNode) n).targetMethod(); 86 Debug.log("target ... " + lambdaMethod); 87 break; 88 } 89 } 90 if (lambdaMethod == null) { 91 // Did not find call in Consumer.accept. 92 Debug.log("Should not Reach here, did not find call in accept()"); 93 return null; 94 } 95 // Now that we have the target lambda, compile it. 96 HSAILCompilationResult hsailCompResult = HSAILCompilationResult.getHSAILCompilationResult(lambdaMethod); 97 if (hsailCompResult != null) { 98 hsailCompResult.dumpCompilationResult(); 99 } 100 return hsailCompResult.getCompilationResult(); 101 } 102 103 // Implementations of the CompileAndDispatch interface. 104 @Override 105 public Object createKernel(Class<?> consumerClass) { 106 try { 107 CompilationResult result = getCompiledLambda(consumerClass); 108 if (result != null) { 109 String code = new String(new String(result.getTargetCode(), 0, result.getTargetCodeSize())); 110 OkraContext okraContext = new OkraContext(); 111 OkraKernel okraKernel = new OkraKernel(okraContext, code, "&run"); 112 if (okraKernel.isValid()) { 113 return okraKernel; 114 } 115 } 116 } catch (Throwable e) { 117 // Note: Graal throws Errors. We want to revert to regular Java in these cases. 118 Debug.log("WARNING:Graal compilation failed."); 119 e.printStackTrace(); 120 return null; 121 } 122 // If we got this far, return null. 123 return null; 124 } 125 126 @Override 127 public boolean dispatchKernel(Object kernel, int jobSize, Object[] args) { 128 if (!(kernel instanceof OkraKernel)) { 129 Debug.log("unknown kernel for dispatchKernel"); 130 return false; 131 } 132 OkraKernel okraKernel = (OkraKernel) kernel; 133 okraKernel.setLaunchAttributes(jobSize); 134 int status = okraKernel.dispatchWithArgs(args); 135 return (status == 0); 136 } 137 }