001/* 002 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.hotspot.stubs; 024 025import static com.oracle.graal.graphbuilderconf.IntrinsicContext.CompilationContext.*; 026 027import java.lang.reflect.*; 028 029import jdk.internal.jvmci.common.*; 030import com.oracle.graal.debug.*; 031import com.oracle.graal.debug.Debug.*; 032import jdk.internal.jvmci.meta.*; 033 034import com.oracle.graal.graphbuilderconf.*; 035import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; 036import com.oracle.graal.hotspot.*; 037import com.oracle.graal.hotspot.meta.*; 038import com.oracle.graal.java.*; 039import com.oracle.graal.nodes.*; 040import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; 041import com.oracle.graal.nodes.StructuredGraph.GuardsStage; 042import com.oracle.graal.nodes.spi.*; 043import com.oracle.graal.phases.*; 044import com.oracle.graal.phases.common.*; 045import com.oracle.graal.phases.tiers.*; 046import com.oracle.graal.replacements.*; 047import com.oracle.graal.replacements.Snippet.ConstantParameter; 048 049/** 050 * Base class for a stub defined by a snippet. 051 */ 052public abstract class SnippetStub extends Stub implements Snippets { 053 054 protected final ResolvedJavaMethod method; 055 056 /** 057 * Creates a new snippet stub. 058 * 059 * @param snippetMethodName name of the single {@link Snippet} annotated method in the class of 060 * this object 061 * @param linkage linkage details for a call to the stub 062 */ 063 public SnippetStub(String snippetMethodName, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { 064 this(null, snippetMethodName, providers, linkage); 065 } 066 067 /** 068 * Creates a new snippet stub. 069 * 070 * @param snippetDeclaringClass this class in which the {@link Snippet} annotated method is 071 * declared. If {@code null}, this the class of this object is used. 072 * @param snippetMethodName name of the single {@link Snippet} annotated method in 073 * {@code snippetDeclaringClass} 074 * @param linkage linkage details for a call to the stub 075 */ 076 public SnippetStub(Class<? extends Snippets> snippetDeclaringClass, String snippetMethodName, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { 077 super(providers, linkage); 078 Method javaMethod = SnippetTemplate.AbstractTemplates.findMethod(snippetDeclaringClass == null ? getClass() : snippetDeclaringClass, snippetMethodName, null); 079 this.method = providers.getMetaAccess().lookupJavaMethod(javaMethod); 080 } 081 082 @SuppressWarnings("all") 083 private static boolean assertionsEnabled() { 084 boolean enabled = false; 085 assert enabled = true; 086 return enabled; 087 } 088 089 public static final ThreadLocal<StructuredGraph> SnippetGraphUnderConstruction = assertionsEnabled() ? new ThreadLocal<>() : null; 090 091 @Override 092 protected StructuredGraph getGraph() { 093 Plugins defaultPlugins = providers.getGraphBuilderPlugins(); 094 MetaAccessProvider metaAccess = providers.getMetaAccess(); 095 Plugins plugins = new Plugins(defaultPlugins); 096 plugins.prependParameterPlugin(new ConstantBindingParameterPlugin(makeConstArgs(), metaAccess, providers.getSnippetReflection())); 097 GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); 098 099 // Stubs cannot have optimistic assumptions since they have 100 // to be valid for the entire run of the VM. Nor can they be 101 // evolved or have breakpoints. 102 final StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO); 103 graph.disableInlinedMethodRecording(); 104 graph.disableUnsafeAccessTracking(); 105 106 if (SnippetGraphUnderConstruction != null) { 107 assert SnippetGraphUnderConstruction.get() == null : SnippetGraphUnderConstruction.get().toString() + " " + graph; 108 SnippetGraphUnderConstruction.set(graph); 109 } 110 111 try { 112 IntrinsicContext initialIntrinsicContext = new IntrinsicContext(method, method, INLINE_AFTER_PARSING); 113 new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), config, OptimisticOptimizations.NONE, initialIntrinsicContext).apply(graph); 114 115 } finally { 116 if (SnippetGraphUnderConstruction != null) { 117 SnippetGraphUnderConstruction.set(null); 118 } 119 } 120 121 graph.setGuardsStage(GuardsStage.FLOATING_GUARDS); 122 try (Scope s = Debug.scope("LoweringStub", graph)) { 123 new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, new PhaseContext(providers)); 124 } catch (Throwable e) { 125 throw Debug.handle(e); 126 } 127 128 return graph; 129 } 130 131 protected boolean checkConstArg(int index, String expectedName) { 132 assert method.getParameterAnnotation(ConstantParameter.class, index) != null : String.format("parameter %d of %s is expected to be constant", index, method.format("%H.%n(%p)")); 133 LocalVariableTable lvt = method.getLocalVariableTable(); 134 if (lvt != null) { 135 Local local = lvt.getLocal(index, 0); 136 assert local != null; 137 String actualName = local.getName(); 138 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); 139 } 140 return true; 141 } 142 143 protected Object[] makeConstArgs() { 144 int count = method.getSignature().getParameterCount(false); 145 Object[] args = new Object[count]; 146 for (int i = 0; i < args.length; i++) { 147 if (method.getParameterAnnotation(ConstantParameter.class, i) != null) { 148 args[i] = getConstantParameterValue(i, null); 149 } 150 } 151 return args; 152 } 153 154 protected Object getConstantParameterValue(int index, String name) { 155 throw new JVMCIError("%s must override getConstantParameterValue() to provide a value for parameter %d%s", getClass().getName(), index, name == null ? "" : " (" + name + ")"); 156 } 157 158 @Override 159 protected Object debugScopeContext() { 160 return getInstalledCodeOwner(); 161 } 162 163 @Override 164 public ResolvedJavaMethod getInstalledCodeOwner() { 165 return method; 166 } 167 168 @Override 169 public String toString() { 170 return "Stub<" + getInstalledCodeOwner().format("%h.%n") + ">"; 171 } 172}