1 /* 2 * Copyright (c) 2012, 2016, 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 package org.graalvm.compiler.hotspot.stubs; 24 25 import static org.graalvm.compiler.nodes.StructuredGraph.NO_PROFILING_INFO; 26 import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; 27 28 import java.lang.reflect.Method; 29 30 import org.graalvm.compiler.api.replacements.Snippet; 31 import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; 32 import org.graalvm.compiler.core.common.CompilationIdentifier; 33 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; 34 import org.graalvm.compiler.debug.Debug; 35 import org.graalvm.compiler.debug.Debug.Scope; 36 import org.graalvm.compiler.debug.GraalError; 37 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; 38 import org.graalvm.compiler.hotspot.meta.HotSpotProviders; 39 import org.graalvm.compiler.java.GraphBuilderPhase; 40 import org.graalvm.compiler.nodes.StructuredGraph; 41 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 42 import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; 43 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; 44 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; 45 import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; 46 import org.graalvm.compiler.nodes.spi.LoweringTool; 47 import org.graalvm.compiler.phases.OptimisticOptimizations; 48 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 49 import org.graalvm.compiler.phases.common.LoweringPhase; 50 import org.graalvm.compiler.phases.tiers.PhaseContext; 51 import org.graalvm.compiler.replacements.ConstantBindingParameterPlugin; 52 import org.graalvm.compiler.replacements.SnippetTemplate; 53 import org.graalvm.compiler.replacements.Snippets; 54 55 import jdk.vm.ci.meta.Local; 56 import jdk.vm.ci.meta.LocalVariableTable; 57 import jdk.vm.ci.meta.MetaAccessProvider; 58 import jdk.vm.ci.meta.ResolvedJavaMethod; 59 60 /** 61 * Base class for a stub defined by a snippet. 62 */ 63 public abstract class SnippetStub extends Stub implements Snippets { 64 65 protected final ResolvedJavaMethod method; 66 67 /** 68 * Creates a new snippet stub. 69 * 70 * @param snippetMethodName name of the single {@link Snippet} annotated method in the class of 71 * this object 72 * @param linkage linkage details for a call to the stub 73 */ 74 public SnippetStub(String snippetMethodName, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { 75 this(null, snippetMethodName, providers, linkage); 76 } 77 78 /** 79 * Creates a new snippet stub. 80 * 81 * @param snippetDeclaringClass this class in which the {@link Snippet} annotated method is 82 * declared. If {@code null}, this the class of this object is used. 83 * @param snippetMethodName name of the single {@link Snippet} annotated method in 84 * {@code snippetDeclaringClass} 85 * @param linkage linkage details for a call to the stub 86 */ 87 public SnippetStub(Class<? extends Snippets> snippetDeclaringClass, String snippetMethodName, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { 88 super(providers, linkage); 89 Method javaMethod = SnippetTemplate.AbstractTemplates.findMethod(snippetDeclaringClass == null ? getClass() : snippetDeclaringClass, snippetMethodName, null); 90 this.method = providers.getMetaAccess().lookupJavaMethod(javaMethod); 91 } 92 93 @SuppressWarnings("all") 94 private static boolean assertionsEnabled() { 95 boolean enabled = false; 96 assert enabled = true; 97 return enabled; 98 } 99 100 public static final ThreadLocal<StructuredGraph> SnippetGraphUnderConstruction = assertionsEnabled() ? new ThreadLocal<>() : null; 101 102 @Override 103 @SuppressWarnings("try") 104 protected StructuredGraph getGraph(CompilationIdentifier compilationId) { 105 Plugins defaultPlugins = providers.getGraphBuilderPlugins(); 106 MetaAccessProvider metaAccess = providers.getMetaAccess(); 107 SnippetReflectionProvider snippetReflection = providers.getSnippetReflection(); 108 109 Plugins plugins = new Plugins(defaultPlugins); 110 plugins.prependParameterPlugin(new ConstantBindingParameterPlugin(makeConstArgs(), metaAccess, snippetReflection)); 111 GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); 112 113 // Stubs cannot have optimistic assumptions since they have 114 // to be valid for the entire run of the VM. 115 final StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, NO_PROFILING_INFO, compilationId); 116 try (Scope outer = Debug.scope("SnippetStub", graph)) { 117 graph.disableUnsafeAccessTracking(); 118 119 if (SnippetGraphUnderConstruction != null) { 120 assert SnippetGraphUnderConstruction.get() == null : SnippetGraphUnderConstruction.get().toString() + " " + graph; 121 SnippetGraphUnderConstruction.set(graph); 122 } 123 124 try { 125 IntrinsicContext initialIntrinsicContext = new IntrinsicContext(method, method, providers.getReplacements().getReplacementBytecodeProvider(), INLINE_AFTER_PARSING); 126 GraphBuilderPhase.Instance instance = new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), 127 providers.getConstantReflection(), providers.getConstantFieldProvider(), 128 config, OptimisticOptimizations.NONE, 129 initialIntrinsicContext); 130 instance.apply(graph); 131 132 } finally { 133 if (SnippetGraphUnderConstruction != null) { 134 SnippetGraphUnderConstruction.set(null); 135 } 136 } 137 138 graph.setGuardsStage(GuardsStage.FLOATING_GUARDS); 139 CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); 140 PhaseContext context = new PhaseContext(providers); 141 canonicalizer.apply(graph, context); 142 new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); 143 } catch (Throwable e) { 144 throw Debug.handle(e); 145 } 146 147 return graph; 148 } 149 150 protected boolean checkConstArg(int index, String expectedName) { 151 assert method.getParameterAnnotation(ConstantParameter.class, index) != null : String.format("parameter %d of %s is expected to be constant", index, method.format("%H.%n(%p)")); 152 LocalVariableTable lvt = method.getLocalVariableTable(); 153 if (lvt != null) { 154 Local local = lvt.getLocal(index, 0); 155 assert local != null; 156 String actualName = local.getName(); 157 assert actualName.equals(expectedName) : String.format("parameter %d of %s is expected to be named %s, not %s", index, method.format("%H.%n(%p)"), expectedName, actualName); 158 } 159 return true; 160 } 161 162 protected Object[] makeConstArgs() { 163 int count = method.getSignature().getParameterCount(false); 164 Object[] args = new Object[count]; 165 for (int i = 0; i < args.length; i++) { 166 if (method.getParameterAnnotation(ConstantParameter.class, i) != null) { 167 args[i] = getConstantParameterValue(i, null); 168 } 169 } 170 return args; 171 } 172 173 protected Object getConstantParameterValue(int index, String name) { 174 throw new GraalError("%s must override getConstantParameterValue() to provide a value for parameter %d%s", getClass().getName(), index, name == null ? "" : " (" + name + ")"); 175 } 176 177 @Override 178 protected Object debugScopeContext() { 179 return getInstalledCodeOwner(); 180 } 181 182 @Override 183 public ResolvedJavaMethod getInstalledCodeOwner() { 184 return method; 185 } 186 187 @Override 188 public String toString() { 189 return "Stub<" + getInstalledCodeOwner().format("%h.%n") + ">"; 190 } 191 }