1 /* 2 * Copyright (c) 2011, 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 24 25 package org.graalvm.compiler.replacements; 26 27 import static org.graalvm.compiler.core.common.GraalOptions.UseSnippetGraphCache; 28 import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM; 29 import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing; 30 import static org.graalvm.compiler.java.BytecodeParserOptions.InlineIntrinsicsDuringParsing; 31 import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createIntrinsicInlineInfo; 32 import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; 33 import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required; 34 35 import java.util.Collections; 36 import java.util.List; 37 import java.util.concurrent.ConcurrentHashMap; 38 import java.util.concurrent.ConcurrentMap; 39 import java.util.concurrent.atomic.AtomicInteger; 40 41 import jdk.internal.vm.compiler.collections.EconomicMap; 42 import jdk.internal.vm.compiler.collections.Equivalence; 43 import org.graalvm.compiler.api.replacements.Fold; 44 import org.graalvm.compiler.api.replacements.MethodSubstitution; 45 import org.graalvm.compiler.api.replacements.Snippet; 46 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; 47 import org.graalvm.compiler.api.replacements.SnippetTemplateCache; 48 import org.graalvm.compiler.bytecode.Bytecode; 49 import org.graalvm.compiler.bytecode.BytecodeProvider; 50 import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; 51 import org.graalvm.compiler.core.common.GraalOptions; 52 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; 53 import org.graalvm.compiler.debug.DebugCloseable; 54 import org.graalvm.compiler.debug.DebugContext; 55 import org.graalvm.compiler.debug.DebugContext.Description; 56 import org.graalvm.compiler.debug.DebugHandlersFactory; 57 import org.graalvm.compiler.debug.GraalError; 58 import org.graalvm.compiler.debug.TimerKey; 59 import org.graalvm.compiler.graph.Node; 60 import org.graalvm.compiler.graph.NodeSourcePosition; 61 import org.graalvm.compiler.graph.Node.NodeIntrinsic; 62 import org.graalvm.compiler.java.GraphBuilderPhase; 63 import org.graalvm.compiler.java.GraphBuilderPhase.Instance; 64 import org.graalvm.compiler.nodes.CallTargetNode; 65 import org.graalvm.compiler.nodes.Invoke; 66 import org.graalvm.compiler.nodes.StateSplit; 67 import org.graalvm.compiler.nodes.StructuredGraph; 68 import org.graalvm.compiler.nodes.ValueNode; 69 import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin; 70 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; 71 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; 72 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; 73 import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; 74 import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; 75 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; 76 import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; 77 import org.graalvm.compiler.nodes.java.MethodCallTargetNode; 78 import org.graalvm.compiler.nodes.spi.Replacements; 79 import org.graalvm.compiler.nodes.spi.StampProvider; 80 import org.graalvm.compiler.options.OptionValues; 81 import org.graalvm.compiler.phases.OptimisticOptimizations; 82 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 83 import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase; 84 import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; 85 import org.graalvm.compiler.phases.tiers.PhaseContext; 86 import org.graalvm.compiler.phases.util.Providers; 87 import org.graalvm.compiler.word.Word; 88 import org.graalvm.compiler.word.WordOperationPlugin; 89 90 import jdk.vm.ci.code.TargetDescription; 91 import jdk.vm.ci.meta.ConstantReflectionProvider; 92 import jdk.vm.ci.meta.MetaAccessProvider; 93 import jdk.vm.ci.meta.ResolvedJavaMethod; 94 import jdk.vm.ci.meta.ResolvedJavaType; 95 96 public class ReplacementsImpl implements Replacements, InlineInvokePlugin { 97 98 protected final OptionValues options; 99 public final Providers providers; 100 public final SnippetReflectionProvider snippetReflection; 101 public final TargetDescription target; 102 private GraphBuilderConfiguration.Plugins graphBuilderPlugins; 103 private final DebugHandlersFactory debugHandlersFactory; 104 105 @Override getOptions()106 public OptionValues getOptions() { 107 return options; 108 } 109 110 /** 111 * The preprocessed replacement graphs. 112 */ 113 protected final ConcurrentMap<ResolvedJavaMethod, StructuredGraph> graphs; 114 115 /** 116 * The default {@link BytecodeProvider} to use for accessing the bytecode of a replacement if 117 * the replacement doesn't provide another {@link BytecodeProvider}. 118 */ 119 protected final BytecodeProvider defaultBytecodeProvider; 120 setGraphBuilderPlugins(GraphBuilderConfiguration.Plugins plugins)121 public void setGraphBuilderPlugins(GraphBuilderConfiguration.Plugins plugins) { 122 assert this.graphBuilderPlugins == null; 123 this.graphBuilderPlugins = plugins; 124 } 125 126 @Override getGraphBuilderPlugins()127 public GraphBuilderConfiguration.Plugins getGraphBuilderPlugins() { 128 return graphBuilderPlugins; 129 } 130 hasGeneratedInvocationPluginAnnotation(ResolvedJavaMethod method)131 protected boolean hasGeneratedInvocationPluginAnnotation(ResolvedJavaMethod method) { 132 return method.getAnnotation(Node.NodeIntrinsic.class) != null || method.getAnnotation(Fold.class) != null; 133 } 134 hasGenericInvocationPluginAnnotation(ResolvedJavaMethod method)135 protected boolean hasGenericInvocationPluginAnnotation(ResolvedJavaMethod method) { 136 return method.getAnnotation(Word.Operation.class) != null; 137 } 138 139 private static final int MAX_GRAPH_INLINING_DEPTH = 100; // more than enough 140 141 /** 142 * Determines whether a given method should be inlined based on whether it has a substitution or 143 * whether the inlining context is already within a substitution. 144 * 145 * @return an object specifying how {@code method} is to be inlined or null if it should not be 146 * inlined based on substitution related criteria 147 */ 148 @Override shouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args)149 public InlineInfo shouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { 150 Bytecode subst = getSubstitutionBytecode(method); 151 if (subst != null) { 152 if (b.parsingIntrinsic() || InlineDuringParsing.getValue(b.getOptions()) || InlineIntrinsicsDuringParsing.getValue(b.getOptions())) { 153 // Forced inlining of intrinsics 154 return createIntrinsicInlineInfo(subst.getMethod(), method, subst.getOrigin()); 155 } 156 return null; 157 } 158 if (b.parsingIntrinsic()) { 159 assert b.getDepth() < MAX_GRAPH_INLINING_DEPTH : "inlining limit exceeded"; 160 161 // Force inlining when parsing replacements 162 return createIntrinsicInlineInfo(method, null, defaultBytecodeProvider); 163 } else { 164 assert method.getAnnotation(NodeIntrinsic.class) == null : String.format("@%s method %s must only be called from within a replacement%n%s", NodeIntrinsic.class.getSimpleName(), 165 method.format("%h.%n"), b); 166 } 167 return null; 168 } 169 170 @Override 171 public void notifyNotInlined(GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) { 172 if (b.parsingIntrinsic()) { 173 IntrinsicContext intrinsic = b.getIntrinsic(); 174 if (!intrinsic.isCallToOriginal(method)) { 175 if (hasGeneratedInvocationPluginAnnotation(method)) { 176 throw new GraalError("%s should have been handled by a %s", method.format("%H.%n(%p)"), GeneratedInvocationPlugin.class.getSimpleName()); 177 } 178 if (hasGenericInvocationPluginAnnotation(method)) { 179 throw new GraalError("%s should have been handled by %s", method.format("%H.%n(%p)"), WordOperationPlugin.class.getSimpleName()); 180 } 181 182 throw new GraalError("All non-recursive calls in the intrinsic %s must be inlined or intrinsified: found call to %s", 183 intrinsic.getIntrinsicMethod().format("%H.%n(%p)"), method.format("%h.%n(%p)")); 184 } 185 } 186 } 187 188 // This map is key'ed by a class name instead of a Class object so that 189 // it is stable across VM executions (in support of replay compilation). 190 private final EconomicMap<String, SnippetTemplateCache> snippetTemplateCache; 191 192 public ReplacementsImpl(OptionValues options, DebugHandlersFactory debugHandlersFactory, Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, 193 TargetDescription target) { 194 this.options = options; 195 this.providers = providers.copyWith(this); 196 this.snippetReflection = snippetReflection; 197 this.target = target; 198 this.graphs = new ConcurrentHashMap<>(); 199 this.snippetTemplateCache = EconomicMap.create(Equivalence.DEFAULT); 200 this.defaultBytecodeProvider = bytecodeProvider; 201 this.debugHandlersFactory = debugHandlersFactory; 202 203 } 204 205 private static final TimerKey SnippetPreparationTime = DebugContext.timer("SnippetPreparationTime"); 206 207 @Override 208 public StructuredGraph getSnippet(ResolvedJavaMethod method, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) { 209 return getSnippet(method, null, args, trackNodeSourcePosition, replaceePosition); 210 } 211 212 private static final AtomicInteger nextDebugContextId = new AtomicInteger(); 213 214 protected DebugContext openDebugContext(String idPrefix, ResolvedJavaMethod method) { 215 DebugContext outer = DebugContext.forCurrentThread(); 216 Description description = new Description(method, idPrefix + nextDebugContextId.incrementAndGet()); 217 List<DebugHandlersFactory> factories = debugHandlersFactory == null ? Collections.emptyList() : Collections.singletonList(debugHandlersFactory); 218 return DebugContext.create(options, description, outer.getGlobalMetrics(), DEFAULT_LOG_STREAM, factories); 219 } 220 221 @Override 222 @SuppressWarnings("try") 223 public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) { 224 assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName(); 225 assert method.hasBytecodes() : "Snippet must not be abstract or native"; 226 227 StructuredGraph graph = UseSnippetGraphCache.getValue(options) ? graphs.get(method) : null; 228 if (graph == null || (trackNodeSourcePosition && !graph.trackNodeSourcePosition())) { 229 try (DebugContext debug = openDebugContext("Snippet_", method); 230 DebugCloseable a = SnippetPreparationTime.start(debug)) { 231 StructuredGraph newGraph = makeGraph(debug, defaultBytecodeProvider, method, args, recursiveEntry, trackNodeSourcePosition, replaceePosition); 232 DebugContext.counter("SnippetNodeCount[%#s]", method).add(newGraph.getDebug(), newGraph.getNodeCount()); 233 if (!UseSnippetGraphCache.getValue(options) || args != null) { 234 return newGraph; 235 } 236 newGraph.freeze(); 237 if (graph != null) { 238 graphs.replace(method, graph, newGraph); 239 } else { 240 graphs.putIfAbsent(method, newGraph); 241 } 242 graph = graphs.get(method); 243 } 244 } 245 assert !trackNodeSourcePosition || graph.trackNodeSourcePosition(); 246 return graph; 247 } 248 249 @Override 250 public void registerSnippet(ResolvedJavaMethod method, boolean trackNodeSourcePosition) { 251 // No initialization needed as snippet graphs are created on demand in getSnippet 252 } 253 254 @Override 255 public boolean hasSubstitution(ResolvedJavaMethod method, int invokeBci) { 256 InvocationPlugin plugin = graphBuilderPlugins.getInvocationPlugins().lookupInvocation(method); 257 return plugin != null && (!plugin.inlineOnly() || invokeBci >= 0); 258 } 259 260 @Override getDefaultReplacementBytecodeProvider()261 public BytecodeProvider getDefaultReplacementBytecodeProvider() { 262 return defaultBytecodeProvider; 263 } 264 265 @Override getSubstitutionBytecode(ResolvedJavaMethod method)266 public Bytecode getSubstitutionBytecode(ResolvedJavaMethod method) { 267 InvocationPlugin plugin = graphBuilderPlugins.getInvocationPlugins().lookupInvocation(method); 268 if (plugin instanceof MethodSubstitutionPlugin) { 269 MethodSubstitutionPlugin msPlugin = (MethodSubstitutionPlugin) plugin; 270 ResolvedJavaMethod substitute = msPlugin.getSubstitute(providers.getMetaAccess()); 271 return msPlugin.getBytecodeProvider().getBytecode(substitute); 272 } 273 return null; 274 } 275 276 @Override getSubstitution(ResolvedJavaMethod method, int invokeBci, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition)277 public StructuredGraph getSubstitution(ResolvedJavaMethod method, int invokeBci, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) { 278 StructuredGraph result; 279 InvocationPlugin plugin = graphBuilderPlugins.getInvocationPlugins().lookupInvocation(method); 280 if (plugin != null && (!plugin.inlineOnly() || invokeBci >= 0)) { 281 MetaAccessProvider metaAccess = providers.getMetaAccess(); 282 if (plugin instanceof MethodSubstitutionPlugin) { 283 MethodSubstitutionPlugin msPlugin = (MethodSubstitutionPlugin) plugin; 284 ResolvedJavaMethod substitute = msPlugin.getSubstitute(metaAccess); 285 StructuredGraph graph = UseSnippetGraphCache.getValue(options) ? graphs.get(substitute) : null; 286 if (graph == null || graph.trackNodeSourcePosition() != trackNodeSourcePosition) { 287 try (DebugContext debug = openDebugContext("Substitution_", method)) { 288 graph = makeGraph(debug, msPlugin.getBytecodeProvider(), substitute, null, method, trackNodeSourcePosition, replaceePosition); 289 if (!UseSnippetGraphCache.getValue(options)) { 290 return graph; 291 } 292 graph.freeze(); 293 graphs.putIfAbsent(substitute, graph); 294 graph = graphs.get(substitute); 295 } 296 } 297 assert graph.isFrozen(); 298 result = graph; 299 } else { 300 Bytecode code = new ResolvedJavaMethodBytecode(method); 301 ConstantReflectionProvider constantReflection = providers.getConstantReflection(); 302 ConstantFieldProvider constantFieldProvider = providers.getConstantFieldProvider(); 303 StampProvider stampProvider = providers.getStampProvider(); 304 try (DebugContext debug = openDebugContext("Substitution_", method)) { 305 result = new IntrinsicGraphBuilder(options, debug, metaAccess, constantReflection, constantFieldProvider, stampProvider, code, invokeBci).buildGraph(plugin); 306 } 307 } 308 } else { 309 result = null; 310 } 311 return result; 312 } 313 314 /** 315 * Creates a preprocessed graph for a snippet or method substitution. 316 * 317 * @param bytecodeProvider how to access the bytecode of {@code method} 318 * @param method the snippet or method substitution for which a graph will be created 319 * @param args 320 * @param original the original method if {@code method} is a {@linkplain MethodSubstitution 321 * substitution} otherwise null 322 * @param trackNodeSourcePosition 323 */ makeGraph(DebugContext debug, BytecodeProvider bytecodeProvider, ResolvedJavaMethod method, Object[] args, ResolvedJavaMethod original, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition)324 public StructuredGraph makeGraph(DebugContext debug, BytecodeProvider bytecodeProvider, ResolvedJavaMethod method, Object[] args, ResolvedJavaMethod original, boolean trackNodeSourcePosition, 325 NodeSourcePosition replaceePosition) { 326 return createGraphMaker(method, original).makeGraph(debug, bytecodeProvider, args, trackNodeSourcePosition, replaceePosition); 327 } 328 329 /** 330 * Can be overridden to return an object that specializes various parts of graph preprocessing. 331 */ createGraphMaker(ResolvedJavaMethod substitute, ResolvedJavaMethod original)332 protected GraphMaker createGraphMaker(ResolvedJavaMethod substitute, ResolvedJavaMethod original) { 333 return new GraphMaker(this, substitute, original); 334 } 335 336 /** 337 * Creates and preprocesses a graph for a replacement. 338 */ 339 public static class GraphMaker { 340 341 /** The replacements object that the graphs are created for. */ 342 protected final ReplacementsImpl replacements; 343 344 /** 345 * The method for which a graph is being created. 346 */ 347 protected final ResolvedJavaMethod method; 348 349 /** 350 * The original method which {@link #method} is substituting. Calls to {@link #method} or 351 * {@link #substitutedMethod} will be replaced with a forced inline of 352 * {@link #substitutedMethod}. 353 */ 354 protected final ResolvedJavaMethod substitutedMethod; 355 GraphMaker(ReplacementsImpl replacements, ResolvedJavaMethod substitute, ResolvedJavaMethod substitutedMethod)356 protected GraphMaker(ReplacementsImpl replacements, ResolvedJavaMethod substitute, ResolvedJavaMethod substitutedMethod) { 357 this.replacements = replacements; 358 this.method = substitute; 359 this.substitutedMethod = substitutedMethod; 360 } 361 362 @SuppressWarnings("try") makeGraph(DebugContext debug, BytecodeProvider bytecodeProvider, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition)363 public StructuredGraph makeGraph(DebugContext debug, BytecodeProvider bytecodeProvider, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) { 364 try (DebugContext.Scope s = debug.scope("BuildSnippetGraph", method)) { 365 assert method.hasBytecodes() : method; 366 StructuredGraph graph = buildInitialGraph(debug, bytecodeProvider, method, args, trackNodeSourcePosition, replaceePosition); 367 368 finalizeGraph(graph); 369 370 debug.dump(DebugContext.INFO_LEVEL, graph, "%s: Final", method.getName()); 371 372 return graph; 373 } catch (Throwable e) { 374 throw debug.handle(e); 375 } 376 } 377 378 /** 379 * Does final processing of a snippet graph. 380 */ finalizeGraph(StructuredGraph graph)381 protected void finalizeGraph(StructuredGraph graph) { 382 if (!GraalOptions.SnippetCounters.getValue(replacements.options) || graph.getNodes().filter(SnippetCounterNode.class).isEmpty()) { 383 int sideEffectCount = 0; 384 assert (sideEffectCount = graph.getNodes().filter(e -> hasSideEffect(e)).count()) >= 0; 385 new ConvertDeoptimizeToGuardPhase().apply(graph, null); 386 assert sideEffectCount == graph.getNodes().filter(e -> hasSideEffect(e)).count() : "deleted side effecting node"; 387 388 new DeadCodeEliminationPhase(Required).apply(graph); 389 } else { 390 // ConvertDeoptimizeToGuardPhase will eliminate snippet counters on paths 391 // that terminate in a deopt so we disable it if the graph contains 392 // snippet counters. The trade off is that we miss out on guard 393 // coalescing opportunities. 394 } 395 } 396 397 /** 398 * Filter nodes which have side effects and shouldn't be deleted from snippets when 399 * converting deoptimizations to guards. Currently this only allows exception constructors 400 * to be eliminated to cover the case when Java assertions are in the inlined code. 401 * 402 * @param node 403 * @return true for nodes that have side effects and are unsafe to delete 404 */ hasSideEffect(Node node)405 private boolean hasSideEffect(Node node) { 406 if (node instanceof StateSplit) { 407 if (((StateSplit) node).hasSideEffect()) { 408 if (node instanceof Invoke) { 409 CallTargetNode callTarget = ((Invoke) node).callTarget(); 410 if (callTarget instanceof MethodCallTargetNode) { 411 ResolvedJavaMethod targetMethod = ((MethodCallTargetNode) callTarget).targetMethod(); 412 if (targetMethod.isConstructor()) { 413 ResolvedJavaType throwableType = replacements.providers.getMetaAccess().lookupJavaType(Throwable.class); 414 return !throwableType.isAssignableFrom(targetMethod.getDeclaringClass()); 415 } 416 } 417 } 418 // Not an exception constructor call 419 return true; 420 } 421 } 422 // Not a StateSplit 423 return false; 424 } 425 426 /** 427 * Builds the initial graph for a replacement. 428 */ 429 @SuppressWarnings("try") buildInitialGraph(DebugContext debug, BytecodeProvider bytecodeProvider, final ResolvedJavaMethod methodToParse, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition)430 protected StructuredGraph buildInitialGraph(DebugContext debug, BytecodeProvider bytecodeProvider, final ResolvedJavaMethod methodToParse, Object[] args, boolean trackNodeSourcePosition, 431 NodeSourcePosition replaceePosition) { 432 // Replacements cannot have optimistic assumptions since they have 433 // to be valid for the entire run of the VM. 434 final StructuredGraph graph = new StructuredGraph.Builder(replacements.options, debug).method(methodToParse).trackNodeSourcePosition(trackNodeSourcePosition).callerContext( 435 replaceePosition).build(); 436 437 // Replacements are not user code so they do not participate in unsafe access 438 // tracking 439 graph.disableUnsafeAccessTracking(); 440 441 try (DebugContext.Scope s = debug.scope("buildInitialGraph", graph)) { 442 MetaAccessProvider metaAccess = replacements.providers.getMetaAccess(); 443 444 Plugins plugins = new Plugins(replacements.graphBuilderPlugins); 445 GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); 446 if (args != null) { 447 plugins.prependParameterPlugin(new ConstantBindingParameterPlugin(args, metaAccess, replacements.snippetReflection)); 448 } 449 450 IntrinsicContext initialIntrinsicContext = null; 451 Snippet snippetAnnotation = method.getAnnotation(Snippet.class); 452 if (snippetAnnotation == null) { 453 // Post-parse inlined intrinsic 454 initialIntrinsicContext = new IntrinsicContext(substitutedMethod, method, bytecodeProvider, INLINE_AFTER_PARSING); 455 } else { 456 // Snippet 457 ResolvedJavaMethod original = substitutedMethod != null ? substitutedMethod : method; 458 initialIntrinsicContext = new IntrinsicContext(original, method, bytecodeProvider, INLINE_AFTER_PARSING, snippetAnnotation.allowPartialIntrinsicArgumentMismatch()); 459 } 460 461 createGraphBuilder(metaAccess, replacements.providers.getStampProvider(), replacements.providers.getConstantReflection(), replacements.providers.getConstantFieldProvider(), config, 462 OptimisticOptimizations.NONE, initialIntrinsicContext).apply(graph); 463 464 new CanonicalizerPhase().apply(graph, new PhaseContext(replacements.providers)); 465 } catch (Throwable e) { 466 throw debug.handle(e); 467 } 468 return graph; 469 } 470 createGraphBuilder(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext)471 protected Instance createGraphBuilder(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, 472 GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) { 473 return new GraphBuilderPhase.Instance(metaAccess, stampProvider, constantReflection, constantFieldProvider, graphBuilderConfig, optimisticOpts, 474 initialIntrinsicContext); 475 } 476 } 477 478 @Override registerSnippetTemplateCache(SnippetTemplateCache templates)479 public void registerSnippetTemplateCache(SnippetTemplateCache templates) { 480 assert snippetTemplateCache.get(templates.getClass().getName()) == null; 481 snippetTemplateCache.put(templates.getClass().getName(), templates); 482 } 483 484 @Override getSnippetTemplateCache(Class<T> templatesClass)485 public <T extends SnippetTemplateCache> T getSnippetTemplateCache(Class<T> templatesClass) { 486 SnippetTemplateCache ret = snippetTemplateCache.get(templatesClass.getName()); 487 return templatesClass.cast(ret); 488 } 489 } 490