66 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderTool;
67 import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
68 import org.graalvm.compiler.nodes.java.ExceptionObjectNode;
69 import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
70 import org.graalvm.compiler.nodes.spi.StampProvider;
71 import org.graalvm.compiler.nodes.type.StampTool;
72 import org.graalvm.compiler.phases.OptimisticOptimizations;
73 import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
74 import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality;
75 import org.graalvm.compiler.phases.common.inlining.InliningUtil;
76 import org.graalvm.compiler.phases.util.Providers;
77 import org.graalvm.compiler.word.WordTypes;
78 import jdk.internal.vm.compiler.word.LocationIdentity;
79
80 import jdk.vm.ci.code.BytecodeFrame;
81 import jdk.vm.ci.meta.ConstantReflectionProvider;
82 import jdk.vm.ci.meta.JavaKind;
83 import jdk.vm.ci.meta.JavaType;
84 import jdk.vm.ci.meta.MetaAccessProvider;
85 import jdk.vm.ci.meta.ResolvedJavaMethod;
86 import jdk.vm.ci.meta.Signature;
87
88 /**
89 * A utility for manually creating a graph. This will be expanded as necessary to support all
90 * subsystems that employ manual graph creation (as opposed to {@linkplain GraphBuilderPhase
91 * bytecode parsing} based graph creation).
92 */
93 public class GraphKit implements GraphBuilderTool {
94
95 protected final Providers providers;
96 protected final StructuredGraph graph;
97 protected final WordTypes wordTypes;
98 protected final GraphBuilderConfiguration.Plugins graphBuilderPlugins;
99 protected FixedWithNextNode lastFixedNode;
100
101 private final List<Structure> structures;
102
103 protected abstract static class Structure {
104 }
105
201
202 public InvokeNode createInvoke(Class<?> declaringClass, String name, ValueNode... args) {
203 return createInvoke(declaringClass, name, InvokeKind.Static, null, BytecodeFrame.UNKNOWN_BCI, args);
204 }
205
206 /**
207 * Creates and appends an {@link InvokeNode} for a call to a given method with a given set of
208 * arguments. The method is looked up via reflection based on the declaring class and name.
209 *
210 * @param declaringClass the class declaring the invoked method
211 * @param name the name of the invoked method
212 * @param args the arguments to the invocation
213 */
214 public InvokeNode createInvoke(Class<?> declaringClass, String name, InvokeKind invokeKind, FrameStateBuilder frameStateBuilder, int bci, ValueNode... args) {
215 boolean isStatic = invokeKind == InvokeKind.Static;
216 ResolvedJavaMethod method = findMethod(declaringClass, name, isStatic);
217 return createInvoke(method, invokeKind, frameStateBuilder, bci, args);
218 }
219
220 public ResolvedJavaMethod findMethod(Class<?> declaringClass, String name, boolean isStatic) {
221 ResolvedJavaMethod method = null;
222 for (Method m : declaringClass.getDeclaredMethods()) {
223 if (Modifier.isStatic(m.getModifiers()) == isStatic && m.getName().equals(name)) {
224 assert method == null : "found more than one method in " + declaringClass + " named " + name;
225 method = providers.getMetaAccess().lookupJavaMethod(m);
226 }
227 }
228 GraalError.guarantee(method != null, "Could not find %s.%s (%s)", declaringClass, name, isStatic ? "static" : "non-static");
229 return method;
230 }
231
232 public ResolvedJavaMethod findMethod(Class<?> declaringClass, String name, Class<?>... parameterTypes) {
233 try {
234 Method m = declaringClass.getDeclaredMethod(name, parameterTypes);
235 return providers.getMetaAccess().lookupJavaMethod(m);
236 } catch (NoSuchMethodException | SecurityException e) {
237 throw new AssertionError(e);
238 }
239 }
240
241 /**
242 * Creates and appends an {@link InvokeNode} for a call to a given method with a given set of
243 * arguments.
244 */
245 @SuppressWarnings("try")
339 for (InvokeNode invoke : graph.getNodes().filter(InvokeNode.class).snapshot()) {
340 inline(invoke, reason, phase);
341 }
342 }
343
344 // Clean up all code that is now dead after inlining.
345 new DeadCodeEliminationPhase().apply(graph);
346 }
347
348 /**
349 * Inlines a given invocation to a method. The graph of the inlined method is processed in the
350 * same manner as for snippets and method substitutions.
351 */
352 public void inline(InvokeNode invoke, String reason, String phase) {
353 ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod();
354
355 MetaAccessProvider metaAccess = providers.getMetaAccess();
356 Plugins plugins = new Plugins(graphBuilderPlugins);
357 GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins);
358
359 StructuredGraph calleeGraph = new StructuredGraph.Builder(invoke.getOptions(), invoke.getDebug()).method(method).trackNodeSourcePosition(invoke.graph().trackNodeSourcePosition()).build();
360 IntrinsicContext initialReplacementContext = new IntrinsicContext(method, method, providers.getReplacements().getDefaultReplacementBytecodeProvider(), INLINE_AFTER_PARSING);
361 GraphBuilderPhase.Instance instance = createGraphBuilderInstance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), providers.getConstantFieldProvider(), config,
362 OptimisticOptimizations.NONE,
363 initialReplacementContext);
364 instance.apply(calleeGraph);
365
366 // Remove all frame states from inlinee
367 calleeGraph.clearAllStateAfter();
368 new DeadCodeEliminationPhase(Optionality.Required).apply(calleeGraph);
369
370 InliningUtil.inline(invoke, calleeGraph, false, method, reason, phase);
371 }
372
373 protected GraphBuilderPhase.Instance createGraphBuilderInstance(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection,
374 ConstantFieldProvider constantFieldProvider, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) {
375 return new GraphBuilderPhase.Instance(metaAccess, stampProvider, constantReflection, constantFieldProvider, graphBuilderConfig, optimisticOpts, initialIntrinsicContext);
376 }
377
378 protected void pushStructure(Structure structure) {
379 structures.add(structure);
|
66 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderTool;
67 import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
68 import org.graalvm.compiler.nodes.java.ExceptionObjectNode;
69 import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
70 import org.graalvm.compiler.nodes.spi.StampProvider;
71 import org.graalvm.compiler.nodes.type.StampTool;
72 import org.graalvm.compiler.phases.OptimisticOptimizations;
73 import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
74 import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality;
75 import org.graalvm.compiler.phases.common.inlining.InliningUtil;
76 import org.graalvm.compiler.phases.util.Providers;
77 import org.graalvm.compiler.word.WordTypes;
78 import jdk.internal.vm.compiler.word.LocationIdentity;
79
80 import jdk.vm.ci.code.BytecodeFrame;
81 import jdk.vm.ci.meta.ConstantReflectionProvider;
82 import jdk.vm.ci.meta.JavaKind;
83 import jdk.vm.ci.meta.JavaType;
84 import jdk.vm.ci.meta.MetaAccessProvider;
85 import jdk.vm.ci.meta.ResolvedJavaMethod;
86 import jdk.vm.ci.meta.ResolvedJavaType;
87 import jdk.vm.ci.meta.Signature;
88
89 /**
90 * A utility for manually creating a graph. This will be expanded as necessary to support all
91 * subsystems that employ manual graph creation (as opposed to {@linkplain GraphBuilderPhase
92 * bytecode parsing} based graph creation).
93 */
94 public class GraphKit implements GraphBuilderTool {
95
96 protected final Providers providers;
97 protected final StructuredGraph graph;
98 protected final WordTypes wordTypes;
99 protected final GraphBuilderConfiguration.Plugins graphBuilderPlugins;
100 protected FixedWithNextNode lastFixedNode;
101
102 private final List<Structure> structures;
103
104 protected abstract static class Structure {
105 }
106
202
203 public InvokeNode createInvoke(Class<?> declaringClass, String name, ValueNode... args) {
204 return createInvoke(declaringClass, name, InvokeKind.Static, null, BytecodeFrame.UNKNOWN_BCI, args);
205 }
206
207 /**
208 * Creates and appends an {@link InvokeNode} for a call to a given method with a given set of
209 * arguments. The method is looked up via reflection based on the declaring class and name.
210 *
211 * @param declaringClass the class declaring the invoked method
212 * @param name the name of the invoked method
213 * @param args the arguments to the invocation
214 */
215 public InvokeNode createInvoke(Class<?> declaringClass, String name, InvokeKind invokeKind, FrameStateBuilder frameStateBuilder, int bci, ValueNode... args) {
216 boolean isStatic = invokeKind == InvokeKind.Static;
217 ResolvedJavaMethod method = findMethod(declaringClass, name, isStatic);
218 return createInvoke(method, invokeKind, frameStateBuilder, bci, args);
219 }
220
221 public ResolvedJavaMethod findMethod(Class<?> declaringClass, String name, boolean isStatic) {
222 ResolvedJavaType type = providers.getMetaAccess().lookupJavaType(declaringClass);
223 ResolvedJavaMethod method = null;
224 for (ResolvedJavaMethod m : type.getDeclaredMethods()) {
225 if (Modifier.isStatic(m.getModifiers()) == isStatic && m.getName().equals(name)) {
226 assert method == null : "found more than one method in " + declaringClass + " named " + name;
227 method = m;
228 }
229 }
230 GraalError.guarantee(method != null, "Could not find %s.%s (%s)", declaringClass, name, isStatic ? "static" : "non-static");
231 return method;
232 }
233
234 public ResolvedJavaMethod findMethod(Class<?> declaringClass, String name, Class<?>... parameterTypes) {
235 try {
236 Method m = declaringClass.getDeclaredMethod(name, parameterTypes);
237 return providers.getMetaAccess().lookupJavaMethod(m);
238 } catch (NoSuchMethodException | SecurityException e) {
239 throw new AssertionError(e);
240 }
241 }
242
243 /**
244 * Creates and appends an {@link InvokeNode} for a call to a given method with a given set of
245 * arguments.
246 */
247 @SuppressWarnings("try")
341 for (InvokeNode invoke : graph.getNodes().filter(InvokeNode.class).snapshot()) {
342 inline(invoke, reason, phase);
343 }
344 }
345
346 // Clean up all code that is now dead after inlining.
347 new DeadCodeEliminationPhase().apply(graph);
348 }
349
350 /**
351 * Inlines a given invocation to a method. The graph of the inlined method is processed in the
352 * same manner as for snippets and method substitutions.
353 */
354 public void inline(InvokeNode invoke, String reason, String phase) {
355 ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod();
356
357 MetaAccessProvider metaAccess = providers.getMetaAccess();
358 Plugins plugins = new Plugins(graphBuilderPlugins);
359 GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins);
360
361 StructuredGraph calleeGraph = new StructuredGraph.Builder(invoke.getOptions(), invoke.getDebug()).method(method).trackNodeSourcePosition(
362 invoke.graph().trackNodeSourcePosition()).setIsSubstitution(true).build();
363 IntrinsicContext initialReplacementContext = new IntrinsicContext(method, method, providers.getReplacements().getDefaultReplacementBytecodeProvider(), INLINE_AFTER_PARSING);
364 GraphBuilderPhase.Instance instance = createGraphBuilderInstance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), providers.getConstantFieldProvider(), config,
365 OptimisticOptimizations.NONE,
366 initialReplacementContext);
367 instance.apply(calleeGraph);
368
369 // Remove all frame states from inlinee
370 calleeGraph.clearAllStateAfter();
371 new DeadCodeEliminationPhase(Optionality.Required).apply(calleeGraph);
372
373 InliningUtil.inline(invoke, calleeGraph, false, method, reason, phase);
374 }
375
376 protected GraphBuilderPhase.Instance createGraphBuilderInstance(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection,
377 ConstantFieldProvider constantFieldProvider, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) {
378 return new GraphBuilderPhase.Instance(metaAccess, stampProvider, constantReflection, constantFieldProvider, graphBuilderConfig, optimisticOpts, initialIntrinsicContext);
379 }
380
381 protected void pushStructure(Structure structure) {
382 structures.add(structure);
|