253 HotSpotProviders providers = (HotSpotProviders) replacements.getProviders().copyWith(new HotSpotSubstrateConstantReflectionProvider(replacements.getProviders().getConstantReflection())); |
260 HotSpotProviders providers = (HotSpotProviders) replacements.getProviders().copyWith(new HotSpotSubstrateConstantReflectionProvider(replacements.getProviders().getConstantReflection())); |
254 this.snippetReplacements = new HotSpotSnippetReplacementsImpl(replacements, providers.copyWith(copy)); |
261 this.snippetReplacements = new HotSpotSnippetReplacementsImpl(replacements, providers.copyWith(copy)); |
255 this.snippetReplacements.setGraphBuilderPlugins(copy); |
262 this.snippetReplacements.setGraphBuilderPlugins(copy); |
256 } |
263 } |
257 |
264 |
|
265 synchronized void registerMethodSubstitution(MethodSubstitutionPlugin plugin) { |
|
266 knownPlugins.add(plugin); |
|
267 } |
|
268 |
|
269 void registerConditionalPlugin(InvocationPlugin plugin) { |
|
270 conditionalPlugins.add(plugin); |
|
271 } |
|
272 |
|
273 synchronized void checkRegistered(MethodSubstitutionPlugin plugin) { |
|
274 if (!knownPlugins.contains(plugin)) { |
|
275 throw new GraalError("missing plugin should have been registered during construction"); |
|
276 } |
|
277 } |
|
278 |
258 /** |
279 /** |
259 * Compiles the snippet and stores the graph. |
280 * Compiles the snippet and stores the graph. |
260 */ |
281 */ |
261 synchronized void registerMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, OptionValues options) { |
282 private synchronized void registerMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, OptionValues options) { |
262 ResolvedJavaMethod method = plugin.getSubstitute(snippetReplacements.getProviders().getMetaAccess()); |
283 ResolvedJavaMethod method = plugin.getSubstitute(snippetReplacements.getProviders().getMetaAccess()); |
263 assert method.getAnnotation(MethodSubstitution.class) != null : "MethodSubstitution must be annotated with @" + MethodSubstitution.class.getSimpleName(); |
284 assert method.getAnnotation(MethodSubstitution.class) != null : "MethodSubstitution must be annotated with @" + MethodSubstitution.class.getSimpleName(); |
264 StructuredGraph subst = buildGraph(method, original, null, true, false, context, options); |
285 String originalMethodString = plugin.originalMethodAsString(); |
|
286 StructuredGraph subst = buildGraph(method, original, originalMethodString, null, true, false, context, options); |
265 snippetMethods.add(method); |
287 snippetMethods.add(method); |
266 originalMethods.put(methodKey(method), methodKey(original)); |
288 originalMethods.put(methodKey(method), originalMethodString); |
267 preparedSnippetGraphs.put(plugin.toString() + context, subst); |
289 preparedSnippetGraphs.put(plugin.toString() + context, subst); |
268 } |
290 } |
269 |
291 |
270 static class EncodedSnippets { |
292 static class EncodedSnippets { |
271 private byte[] snippetEncoding; |
293 private byte[] snippetEncoding; |
368 protected IntrinsicContext getIntrinsic() { |
390 protected IntrinsicContext getIntrinsic() { |
369 return intrinsic; |
391 return intrinsic; |
370 } |
392 } |
371 } |
393 } |
372 |
394 |
373 private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean requireInlining, boolean trackNodeSourcePosition, |
395 private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, String originalMethodString, Object receiver, boolean requireInlining, boolean trackNodeSourcePosition, |
374 IntrinsicContext.CompilationContext context, OptionValues options) { |
396 IntrinsicContext.CompilationContext context, OptionValues options) { |
375 assert method.hasBytecodes() : "Snippet must not be abstract or native"; |
397 assert method.hasBytecodes() : "Snippet must not be abstract or native"; |
376 Object[] args = null; |
398 Object[] args = null; |
377 if (receiver != null) { |
399 if (receiver != null) { |
378 args = new Object[method.getSignature().getParameterCount(true)]; |
400 args = new Object[method.getSignature().getParameterCount(true)]; |
379 args[0] = receiver; |
401 args[0] = receiver; |
380 } |
402 } |
381 try (DebugContext debug = openDebugContext("Snippet_", method, options)) { |
403 // To get dumping out from this context during image building, it's necessary to pass the |
|
404 // dumping options directly to the VM, otherwise they aren't available during initialization |
|
405 // of the backend. Use this: |
|
406 // |
|
407 // -J-Dgraal.Dump=SymbolicSnippetEncoder_:2 -J-Dgraal.PrintGraph=File |
|
408 // -J-Dgraal.DebugStubsAndSnippets=true |
|
409 try (DebugContext debug = openDebugContext("SymbolicSnippetEncoder_", method, options)) { |
382 StructuredGraph graph = snippetReplacements.makeGraph(debug, snippetReplacements.getDefaultReplacementBytecodeProvider(), method, args, original, trackNodeSourcePosition, null, context); |
410 StructuredGraph graph = snippetReplacements.makeGraph(debug, snippetReplacements.getDefaultReplacementBytecodeProvider(), method, args, original, trackNodeSourcePosition, null, context); |
383 |
411 |
384 // Check if all methods which should be inlined are really inlined. |
412 // Check if all methods which should be inlined are really inlined. |
385 for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.TYPE)) { |
413 for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.TYPE)) { |
386 ResolvedJavaMethod callee = callTarget.targetMethod(); |
414 ResolvedJavaMethod callee = callTarget.targetMethod(); |
387 if (requireInlining && !delayedInvocationPluginMethods.contains(callee) && !Objects.equals(callee, original)) { |
415 if (requireInlining && !delayedInvocationPluginMethods.contains(callee) && !Objects.equals(callee, original)) { |
388 throw GraalError.shouldNotReachHere("method " + callee.format("%H.%n") + " not inlined in snippet " + method.getName() + " (maybe not final?)"); |
416 throw GraalError.shouldNotReachHere("method " + callee.format("%H.%n") + " not inlined in snippet " + method.getName() + " (maybe not final?)"); |
389 } |
417 } |
390 } |
418 } |
391 assert verifySnippetEncodeDecode(method, original, trackNodeSourcePosition, graph); |
419 assert verifySnippetEncodeDecode(debug, method, original, originalMethodString, trackNodeSourcePosition, graph); |
392 debug.dump(DebugContext.VERBOSE_LEVEL, graph, "After buildGraph"); |
420 debug.dump(DebugContext.VERBOSE_LEVEL, graph, "After buildGraph"); |
393 return graph; |
421 return graph; |
394 } |
422 } |
395 } |
423 } |
396 |
424 |
424 } |
452 } |
425 } |
453 } |
426 } |
454 } |
427 |
455 |
428 @SuppressWarnings("try") |
456 @SuppressWarnings("try") |
429 private boolean verifySnippetEncodeDecode(ResolvedJavaMethod method, ResolvedJavaMethod original, boolean trackNodeSourcePosition, StructuredGraph graph) { |
457 private boolean verifySnippetEncodeDecode(DebugContext debug, ResolvedJavaMethod method, ResolvedJavaMethod original, String originalMethodString, boolean trackNodeSourcePosition, |
|
458 StructuredGraph graph) { |
430 // Verify the encoding and decoding process |
459 // Verify the encoding and decoding process |
431 EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch); |
460 EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch); |
432 |
461 |
433 try (DebugContext debug = snippetReplacements.openDebugContext("VerifySnippetEncodeDecode_", method, graph.getOptions())) { |
462 HotSpotProviders originalProvider = (HotSpotProviders) snippetReplacements.getProviders(); |
434 HotSpotProviders originalProvider = (HotSpotProviders) snippetReplacements.getProviders(); |
463 |
435 |
464 SnippetReflectionProvider snippetReflection = originalProvider.getSnippetReflection(); |
436 SnippetReflectionProvider snippetReflection = originalProvider.getSnippetReflection(); |
465 SymbolicSnippetEncoder.HotSpotSubstrateConstantReflectionProvider constantReflection = new SymbolicSnippetEncoder.HotSpotSubstrateConstantReflectionProvider( |
437 SymbolicSnippetEncoder.HotSpotSubstrateConstantReflectionProvider constantReflection = new SymbolicSnippetEncoder.HotSpotSubstrateConstantReflectionProvider( |
466 originalProvider.getConstantReflection()); |
438 originalProvider.getConstantReflection()); |
467 HotSpotProviders newProviders = new HotSpotProviders(originalProvider.getMetaAccess(), originalProvider.getCodeCache(), constantReflection, |
439 HotSpotProviders newProviders = new HotSpotProviders(originalProvider.getMetaAccess(), originalProvider.getCodeCache(), constantReflection, |
468 originalProvider.getConstantFieldProvider(), originalProvider.getForeignCalls(), originalProvider.getLowerer(), null, originalProvider.getSuites(), |
440 originalProvider.getConstantFieldProvider(), originalProvider.getForeignCalls(), originalProvider.getLowerer(), null, originalProvider.getSuites(), |
469 originalProvider.getRegisters(), snippetReflection, originalProvider.getWordTypes(), originalProvider.getGraphBuilderPlugins(), originalProvider.getGC()); |
441 originalProvider.getRegisters(), snippetReflection, originalProvider.getWordTypes(), originalProvider.getGraphBuilderPlugins(), originalProvider.getGC()); |
470 HotSpotSnippetReplacementsImpl filteringReplacements = new HotSpotSnippetReplacementsImpl(newProviders, snippetReflection, |
442 HotSpotSnippetReplacementsImpl filteringReplacements = new HotSpotSnippetReplacementsImpl(newProviders, snippetReflection, |
471 originalProvider.getReplacements().getDefaultReplacementBytecodeProvider(), originalProvider.getCodeCache().getTarget()); |
443 originalProvider.getReplacements().getDefaultReplacementBytecodeProvider(), originalProvider.getCodeCache().getTarget()); |
472 filteringReplacements.setGraphBuilderPlugins(originalProvider.getReplacements().getGraphBuilderPlugins()); |
444 filteringReplacements.setGraphBuilderPlugins(originalProvider.getReplacements().getGraphBuilderPlugins()); |
473 try (DebugContext.Scope scaope = debug.scope("VerifySnippetEncodeDecode", graph)) { |
445 try (DebugContext.Scope scaope = debug.scope("VerifySnippetEncodeDecode", graph)) { |
474 for (int i = 0; i < encodedGraph.getNumObjects(); i++) { |
446 for (int i = 0; i < encodedGraph.getNumObjects(); i++) { |
475 filterSnippetObject(encodedGraph.getObject(i)); |
447 filterSnippetObject(encodedGraph.getObject(i)); |
476 } |
448 } |
477 StructuredGraph snippet = filteringReplacements.makeGraph(debug, filteringReplacements.getDefaultReplacementBytecodeProvider(), method, null, original, |
449 StructuredGraph snippet = filteringReplacements.makeGraph(debug, filteringReplacements.getDefaultReplacementBytecodeProvider(), method, null, original, |
478 trackNodeSourcePosition, null); |
450 trackNodeSourcePosition, null); |
479 SymbolicEncodedGraph symbolicGraph = new SymbolicEncodedGraph(encodedGraph, method.getDeclaringClass(), originalMethodString); |
451 SymbolicEncodedGraph symbolicGraph = new SymbolicEncodedGraph(encodedGraph, method.getDeclaringClass(), original != null ? methodKey(original) : null); |
480 StructuredGraph decodedSnippet = decodeSnippetGraph(symbolicGraph, original != null ? original : method, originalReplacements, null, |
452 StructuredGraph decodedSnippet = decodeSnippetGraph(symbolicGraph, original != null ? original : method, originalReplacements, null, |
481 StructuredGraph.AllowAssumptions.ifNonNull(graph.getAssumptions()), graph.getOptions()); |
453 StructuredGraph.AllowAssumptions.ifNonNull(graph.getAssumptions()), graph.getOptions()); |
482 String snippetString = getCanonicalGraphString(snippet, true, false); |
454 String snippetString = getCanonicalGraphString(snippet, true, false); |
483 String decodedSnippetString = getCanonicalGraphString(decodedSnippet, true, false); |
455 String decodedSnippetString = getCanonicalGraphString(decodedSnippet, true, false); |
484 if (snippetString.equals(decodedSnippetString)) { |
456 if (snippetString.equals(decodedSnippetString)) { |
485 debug.log("Snippet decode for %s produces exactly same graph", method); |
457 debug.log("Snippet decode for %s produces exactly same graph", method); |
486 debug.dump(DebugContext.VERBOSE_LEVEL, decodedSnippet, "Decoded snippet graph for %s", method); |
458 debug.dump(DebugContext.VERBOSE_LEVEL, decodedSnippet, "Decoded snippet graph for %s", method); |
487 } else { |
459 } else { |
488 debug.log("Snippet decode for %s produces different graph", method); |
460 debug.log("Snippet decode for %s produces different graph", method); |
489 debug.log("%s", compareGraphStrings(snippet, snippetString, decodedSnippet, decodedSnippetString)); |
461 debug.log("%s", compareGraphStrings(snippet, snippetString, decodedSnippet, decodedSnippetString)); |
490 debug.dump(DebugContext.VERBOSE_LEVEL, snippet, "Snippet graph for %s", method); |
462 debug.dump(DebugContext.VERBOSE_LEVEL, snippet, "Snippet graph for %s", method); |
491 debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Encoded snippet graph for %s", method); |
463 debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Encoded snippet graph for %s", method); |
492 debug.dump(DebugContext.VERBOSE_LEVEL, decodedSnippet, "Decoded snippet graph for %s", method); |
464 debug.dump(DebugContext.VERBOSE_LEVEL, decodedSnippet, "Decoded snippet graph for %s", method); |
493 } |
465 } |
494 } catch (Throwable t) { |
466 } catch (Throwable t) { |
495 throw debug.handle(t); |
467 throw debug.handle(t); |
|
468 } |
|
469 } |
496 } |
470 return true; |
497 return true; |
471 } |
498 } |
472 |
499 |
473 /** |
500 /** |
474 * If there are new graphs waiting to be encoded, reencode all the graphs and return the result. |
501 * If there are new graphs waiting to be encoded, reencode all the graphs and return the result. |
475 */ |
502 */ |
476 @SuppressWarnings("try") |
503 @SuppressWarnings("try") |
477 private synchronized EncodedSnippets maybeEncodeSnippets(OptionValues options) { |
504 private synchronized EncodedSnippets maybeEncodeSnippets(OptionValues options) { |
|
505 Set<MethodSubstitutionPlugin> plugins = this.knownPlugins; |
|
506 if (preparedPlugins != plugins.size()) { |
|
507 for (MethodSubstitutionPlugin plugin : plugins) { |
|
508 ResolvedJavaMethod original = plugin.getOriginalMethod(originalReplacements.getProviders().getMetaAccess()); |
|
509 registerMethodSubstitution(plugin, original, INLINE_AFTER_PARSING, options); |
|
510 if (!original.isNative()) { |
|
511 registerMethodSubstitution(plugin, original, ROOT_COMPILATION, options); |
|
512 } |
|
513 } |
|
514 preparedPlugins = plugins.size(); |
|
515 } |
478 Map<String, StructuredGraph> graphs = this.preparedSnippetGraphs; |
516 Map<String, StructuredGraph> graphs = this.preparedSnippetGraphs; |
479 if (encodedGraphs != graphs.size()) { |
517 if (encodedGraphs != graphs.size()) { |
480 DebugContext debug = openDebugContext("SnippetEncoder", null, options); |
518 DebugContext debug = openDebugContext("SnippetEncoder", null, options); |
481 try (DebugContext.Scope scope = debug.scope("SnippetSupportEncode")) { |
519 try (DebugContext.Scope scope = debug.scope("SnippetSupportEncode")) { |
482 encodedGraphs = graphs.size(); |
520 encodedGraphs = graphs.size(); |
1026 IntrinsicContext initialIntrinsicContext) { |
1064 IntrinsicContext initialIntrinsicContext) { |
1027 return new HotSpotSnippetGraphBuilderPhase(providers, graphBuilderConfig, optimisticOpts, initialIntrinsicContext); |
1065 return new HotSpotSnippetGraphBuilderPhase(providers, graphBuilderConfig, optimisticOpts, initialIntrinsicContext); |
1028 } |
1066 } |
1029 } |
1067 } |
1030 |
1068 |
1031 static class HotSpotSnippetGraphBuilderPhase extends GraphBuilderPhase.Instance { |
1069 class HotSpotSnippetGraphBuilderPhase extends GraphBuilderPhase.Instance { |
1032 HotSpotSnippetGraphBuilderPhase(Providers theProviders, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) { |
1070 HotSpotSnippetGraphBuilderPhase(Providers theProviders, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) { |
1033 super(theProviders, graphBuilderConfig, optimisticOpts, initialIntrinsicContext); |
1071 super(theProviders, graphBuilderConfig, optimisticOpts, initialIntrinsicContext); |
1034 } |
1072 } |
1035 |
1073 |
1036 @Override |
1074 @Override |
1037 protected BytecodeParser createBytecodeParser(StructuredGraph graph, BytecodeParser parent, ResolvedJavaMethod method, int entryBCI, IntrinsicContext intrinsicContext) { |
1075 protected BytecodeParser createBytecodeParser(StructuredGraph graph, BytecodeParser parent, ResolvedJavaMethod method, int entryBCI, IntrinsicContext intrinsicContext) { |
1038 return new HotSpotSnippetBytecodeParser(this, graph, parent, method, entryBCI, intrinsicContext); |
1076 return new HotSpotSnippetBytecodeParser(this, graph, parent, method, entryBCI, intrinsicContext); |
1039 } |
1077 } |
1040 } |
1078 } |
1041 |
1079 |
1042 static class HotSpotSnippetBytecodeParser extends BytecodeParser { |
1080 class HotSpotSnippetBytecodeParser extends BytecodeParser { |
1043 HotSpotSnippetBytecodeParser(GraphBuilderPhase.Instance graphBuilderInstance, StructuredGraph graph, BytecodeParser parent, ResolvedJavaMethod method, int entryBCI, |
1081 HotSpotSnippetBytecodeParser(GraphBuilderPhase.Instance graphBuilderInstance, StructuredGraph graph, BytecodeParser parent, ResolvedJavaMethod method, int entryBCI, |
1044 IntrinsicContext intrinsicContext) { |
1082 IntrinsicContext intrinsicContext) { |
1045 super(graphBuilderInstance, graph, parent, method, entryBCI, intrinsicContext); |
1083 super(graphBuilderInstance, graph, parent, method, entryBCI, intrinsicContext); |
1046 } |
1084 } |
1047 |
1085 |