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