SnippetStub.java revision 13083:b9a173f12fe6
17661Sjbachorik/* 211884Sykantser * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. 37661Sjbachorik * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 47661Sjbachorik * 57661Sjbachorik * This code is free software; you can redistribute it and/or modify it 67661Sjbachorik * under the terms of the GNU General Public License version 2 only, as 77661Sjbachorik * published by the Free Software Foundation. 87661Sjbachorik * 97661Sjbachorik * This code is distributed in the hope that it will be useful, but WITHOUT 107661Sjbachorik * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 117661Sjbachorik * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 127661Sjbachorik * version 2 for more details (a copy is included in the LICENSE file that 137661Sjbachorik * accompanied this code). 147661Sjbachorik * 157661Sjbachorik * You should have received a copy of the GNU General Public License version 167661Sjbachorik * 2 along with this work; if not, write to the Free Software Foundation, 177661Sjbachorik * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 187661Sjbachorik * 197661Sjbachorik * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 207661Sjbachorik * or visit www.oracle.com if you need additional information or have any 217661Sjbachorik * questions. 227661Sjbachorik */ 237661Sjbachorikpackage org.graalvm.compiler.hotspot.stubs; 247661Sjbachorik 257661Sjbachorikimport static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; 267661Sjbachorik 277661Sjbachorikimport java.lang.reflect.Method; 287661Sjbachorik 297661Sjbachorikimport org.graalvm.compiler.api.replacements.Snippet; 307661Sjbachorikimport org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; 3116958Siignatyevimport org.graalvm.compiler.api.replacements.Snippet.NonNullParameter; 327661Sjbachorikimport org.graalvm.compiler.api.replacements.SnippetReflectionProvider; 337661Sjbachorikimport org.graalvm.compiler.bytecode.BytecodeProvider; 3410189Sjbachorikimport org.graalvm.compiler.core.common.CompilationIdentifier; 357661Sjbachorikimport org.graalvm.compiler.core.common.type.StampFactory; 367661Sjbachorikimport org.graalvm.compiler.debug.Debug; 377661Sjbachorikimport org.graalvm.compiler.debug.Debug.Scope; 387661Sjbachorikimport org.graalvm.compiler.debug.GraalError; 397661Sjbachorikimport org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; 407661Sjbachorikimport org.graalvm.compiler.hotspot.meta.HotSpotProviders; 417661Sjbachorikimport org.graalvm.compiler.java.GraphBuilderPhase; 427661Sjbachorikimport org.graalvm.compiler.nodes.ParameterNode; 437661Sjbachorikimport org.graalvm.compiler.nodes.StructuredGraph; 447661Sjbachorikimport org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; 457661Sjbachorikimport org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; 467661Sjbachorikimport org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; 477661Sjbachorikimport org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; 487661Sjbachorikimport org.graalvm.compiler.nodes.spi.LoweringTool; 497661Sjbachorikimport org.graalvm.compiler.options.OptionValues; 507661Sjbachorikimport org.graalvm.compiler.phases.OptimisticOptimizations; 517661Sjbachorikimport org.graalvm.compiler.phases.common.CanonicalizerPhase; 527661Sjbachorikimport org.graalvm.compiler.phases.common.LoweringPhase; 537661Sjbachorikimport org.graalvm.compiler.phases.common.RemoveValueProxyPhase; 547661Sjbachorikimport org.graalvm.compiler.phases.tiers.PhaseContext; 557661Sjbachorikimport org.graalvm.compiler.replacements.ConstantBindingParameterPlugin; 567661Sjbachorikimport org.graalvm.compiler.replacements.SnippetTemplate; 577661Sjbachorikimport org.graalvm.compiler.replacements.Snippets; 587661Sjbachorik 597661Sjbachorikimport jdk.vm.ci.meta.Local; 607661Sjbachorikimport jdk.vm.ci.meta.LocalVariableTable; 617661Sjbachorikimport jdk.vm.ci.meta.MetaAccessProvider; 627661Sjbachorikimport jdk.vm.ci.meta.ResolvedJavaMethod; 637661Sjbachorik 647661Sjbachorik/** 657661Sjbachorik * Base class for a stub defined by a snippet. 667661Sjbachorik */ 677661Sjbachorikpublic abstract class SnippetStub extends Stub implements Snippets { 687661Sjbachorik 697661Sjbachorik protected final ResolvedJavaMethod method; 707661Sjbachorik 717661Sjbachorik /** 727661Sjbachorik * Creates a new snippet stub. 737661Sjbachorik * 747661Sjbachorik * @param snippetMethodName name of the single {@link Snippet} annotated method in the class of 757661Sjbachorik * this object 767661Sjbachorik * @param linkage linkage details for a call to the stub 777661Sjbachorik */ 787661Sjbachorik public SnippetStub(String snippetMethodName, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { 797661Sjbachorik this(null, snippetMethodName, options, providers, linkage); 807661Sjbachorik } 817661Sjbachorik 827661Sjbachorik /** 837661Sjbachorik * Creates a new snippet stub. 847661Sjbachorik * 857661Sjbachorik * @param snippetDeclaringClass this class in which the {@link Snippet} annotated method is 86 * declared. If {@code null}, this the class of this object is used. 87 * @param snippetMethodName name of the single {@link Snippet} annotated method in 88 * {@code snippetDeclaringClass} 89 * @param linkage linkage details for a call to the stub 90 */ 91 public SnippetStub(Class<? extends Snippets> snippetDeclaringClass, String snippetMethodName, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { 92 super(options, providers, linkage); 93 Method javaMethod = SnippetTemplate.AbstractTemplates.findMethod(snippetDeclaringClass == null ? getClass() : snippetDeclaringClass, snippetMethodName, null); 94 this.method = providers.getMetaAccess().lookupJavaMethod(javaMethod); 95 } 96 97 @Override 98 @SuppressWarnings("try") 99 protected StructuredGraph getGraph(CompilationIdentifier compilationId) { 100 Plugins defaultPlugins = providers.getGraphBuilderPlugins(); 101 MetaAccessProvider metaAccess = providers.getMetaAccess(); 102 SnippetReflectionProvider snippetReflection = providers.getSnippetReflection(); 103 104 Plugins plugins = new Plugins(defaultPlugins); 105 plugins.prependParameterPlugin(new ConstantBindingParameterPlugin(makeConstArgs(), metaAccess, snippetReflection)); 106 GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); 107 108 // Stubs cannot have optimistic assumptions since they have 109 // to be valid for the entire run of the VM. 110 final StructuredGraph graph = new StructuredGraph.Builder(options).method(method).compilationId(compilationId).build(); 111 try (Scope outer = Debug.scope("SnippetStub", graph)) { 112 graph.disableUnsafeAccessTracking(); 113 114 IntrinsicContext initialIntrinsicContext = new IntrinsicContext(method, method, getReplacementsBytecodeProvider(), INLINE_AFTER_PARSING); 115 GraphBuilderPhase.Instance instance = new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), 116 providers.getConstantReflection(), providers.getConstantFieldProvider(), 117 config, OptimisticOptimizations.NONE, 118 initialIntrinsicContext); 119 instance.apply(graph); 120 121 for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) { 122 int index = param.index(); 123 if (method.getParameterAnnotation(NonNullParameter.class, index) != null) { 124 param.setStamp(param.stamp().join(StampFactory.objectNonNull())); 125 } 126 } 127 128 new RemoveValueProxyPhase().apply(graph); 129 graph.setGuardsStage(GuardsStage.FLOATING_GUARDS); 130 CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); 131 PhaseContext context = new PhaseContext(providers); 132 canonicalizer.apply(graph, context); 133 new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); 134 } catch (Throwable e) { 135 throw Debug.handle(e); 136 } 137 138 return graph; 139 } 140 141 protected BytecodeProvider getReplacementsBytecodeProvider() { 142 return providers.getReplacements().getDefaultReplacementBytecodeProvider(); 143 } 144 145 protected boolean checkConstArg(int index, String expectedName) { 146 assert method.getParameterAnnotation(ConstantParameter.class, index) != null : String.format("parameter %d of %s is expected to be constant", index, method.format("%H.%n(%p)")); 147 LocalVariableTable lvt = method.getLocalVariableTable(); 148 if (lvt != null) { 149 Local local = lvt.getLocal(index, 0); 150 assert local != null; 151 String actualName = local.getName(); 152 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); 153 } 154 return true; 155 } 156 157 protected Object[] makeConstArgs() { 158 int count = method.getSignature().getParameterCount(false); 159 Object[] args = new Object[count]; 160 for (int i = 0; i < args.length; i++) { 161 if (method.getParameterAnnotation(ConstantParameter.class, i) != null) { 162 args[i] = getConstantParameterValue(i, null); 163 } 164 } 165 return args; 166 } 167 168 protected Object getConstantParameterValue(int index, String name) { 169 throw new GraalError("%s must override getConstantParameterValue() to provide a value for parameter %d%s", getClass().getName(), index, name == null ? "" : " (" + name + ")"); 170 } 171 172 @Override 173 protected Object debugScopeContext() { 174 return getInstalledCodeOwner(); 175 } 176 177 @Override 178 public ResolvedJavaMethod getInstalledCodeOwner() { 179 return method; 180 } 181 182 @Override 183 public String toString() { 184 return "Stub<" + getInstalledCodeOwner().format("%h.%n") + ">"; 185 } 186} 187