use of org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext in project graal by oracle.
the class HotSpotGraalCompiler method getIntrinsicGraph.
/**
* Gets a graph produced from the intrinsic for a given method that can be compiled and
* installed for the method.
*
* @param method
* @param compilationId
* @param options
* @param debug
* @return an intrinsic graph that can be compiled and installed for {@code method} or null
*/
@SuppressWarnings("try")
public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, HotSpotProviders providers, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) {
Replacements replacements = providers.getReplacements();
Bytecode subst = replacements.getSubstitutionBytecode(method);
if (subst != null) {
ResolvedJavaMethod substMethod = subst.getMethod();
assert !substMethod.equals(method);
StructuredGraph graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.YES).method(substMethod).compilationId(compilationId).build();
try (DebugContext.Scope scope = debug.scope("GetIntrinsicGraph", graph)) {
Plugins plugins = new Plugins(providers.getGraphBuilderPlugins());
GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins);
IntrinsicContext initialReplacementContext = new IntrinsicContext(method, substMethod, subst.getOrigin(), ROOT_COMPILATION);
new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), providers.getConstantFieldProvider(), config, OptimisticOptimizations.NONE, initialReplacementContext).apply(graph);
assert !graph.isFrozen();
return graph;
} catch (Throwable e) {
debug.handle(e);
}
}
return null;
}
use of org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext in project graal by oracle.
the class BytecodeParser method inline.
private boolean inline(ResolvedJavaMethod targetMethod, ResolvedJavaMethod inlinedMethod, BytecodeProvider intrinsicBytecodeProvider, ValueNode[] args) {
IntrinsicContext intrinsic = this.intrinsicContext;
if (intrinsic == null && !graphBuilderConfig.insertFullInfopoints() && targetMethod.equals(inlinedMethod) && (targetMethod.getModifiers() & (STATIC | SYNCHRONIZED)) == 0 && tryFastInlineAccessor(args, targetMethod)) {
return true;
}
if (intrinsic != null && intrinsic.isCallToOriginal(targetMethod)) {
if (intrinsic.isCompilationRoot()) {
// A root compiled intrinsic needs to deoptimize
// if the slow path is taken. During frame state
// assignment, the deopt node will get its stateBefore
// from the start node of the intrinsic
append(new DeoptimizeNode(InvalidateRecompile, RuntimeConstraint));
printInlining(targetMethod, inlinedMethod, true, "compilation root (bytecode parsing)");
return true;
} else {
if (intrinsic.getOriginalMethod().isNative()) {
printInlining(targetMethod, inlinedMethod, false, "native method (bytecode parsing)");
return false;
}
if (canInlinePartialIntrinsicExit() && InlinePartialIntrinsicExitDuringParsing.getValue(options)) {
// Otherwise inline the original method. Any frame state created
// during the inlining will exclude frame(s) in the
// intrinsic method (see FrameStateBuilder.create(int bci)).
notifyBeforeInline(inlinedMethod);
printInlining(targetMethod, inlinedMethod, true, "partial intrinsic exit (bytecode parsing)");
parseAndInlineCallee(intrinsic.getOriginalMethod(), args, null);
notifyAfterInline(inlinedMethod);
return true;
} else {
printInlining(targetMethod, inlinedMethod, false, "partial intrinsic exit (bytecode parsing)");
return false;
}
}
} else {
boolean isIntrinsic = intrinsicBytecodeProvider != null;
if (intrinsic == null && isIntrinsic) {
assert !inlinedMethod.equals(targetMethod);
intrinsic = new IntrinsicContext(targetMethod, inlinedMethod, intrinsicBytecodeProvider, INLINE_DURING_PARSING);
}
if (inlinedMethod.hasBytecodes()) {
notifyBeforeInline(inlinedMethod);
printInlining(targetMethod, inlinedMethod, true, "inline method (bytecode parsing)");
parseAndInlineCallee(inlinedMethod, args, intrinsic);
notifyAfterInline(inlinedMethod);
} else {
printInlining(targetMethod, inlinedMethod, false, "no bytecodes (abstract or native) (bytecode parsing)");
return false;
}
}
return true;
}
use of org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext in project graal by oracle.
the class BytecodeParser method parseAndInlineCallee.
protected void parseAndInlineCallee(ResolvedJavaMethod targetMethod, ValueNode[] args, IntrinsicContext calleeIntrinsicContext) {
FixedWithNextNode calleeBeforeUnwindNode = null;
ValueNode calleeUnwindValue = null;
try (IntrinsicScope s = calleeIntrinsicContext != null && !parsingIntrinsic() ? new IntrinsicScope(this, targetMethod.getSignature().toParameterKinds(!targetMethod.isStatic()), args) : null) {
BytecodeParser parser = graphBuilderInstance.createBytecodeParser(graph, this, targetMethod, INVOCATION_ENTRY_BCI, calleeIntrinsicContext);
FrameStateBuilder startFrameState = new FrameStateBuilder(parser, parser.code, graph);
if (!targetMethod.isStatic()) {
args[0] = nullCheckedValue(args[0]);
}
startFrameState.initializeFromArgumentsArray(args);
parser.build(this.lastInstr, startFrameState);
if (parser.returnDataList == null) {
/* Callee does not return. */
lastInstr = null;
} else {
ValueNode calleeReturnValue;
MergeNode returnMergeNode = null;
if (s != null) {
s.returnDataList = parser.returnDataList;
}
if (parser.returnDataList.size() == 1) {
/* Callee has a single return, we can continue parsing at that point. */
ReturnToCallerData singleReturnData = parser.returnDataList.get(0);
lastInstr = singleReturnData.beforeReturnNode;
calleeReturnValue = singleReturnData.returnValue;
} else {
assert parser.returnDataList.size() > 1;
/* Callee has multiple returns, we need to insert a control flow merge. */
returnMergeNode = graph.add(new MergeNode());
calleeReturnValue = ValueMergeUtil.mergeValueProducers(returnMergeNode, parser.returnDataList, returnData -> returnData.beforeReturnNode, returnData -> returnData.returnValue);
}
if (calleeReturnValue != null) {
frameState.push(targetMethod.getSignature().getReturnKind().getStackKind(), calleeReturnValue);
}
if (returnMergeNode != null) {
returnMergeNode.setStateAfter(createFrameState(stream.nextBCI(), returnMergeNode));
lastInstr = finishInstruction(returnMergeNode, frameState);
}
}
/*
* Propagate any side effects into the caller when parsing intrinsics.
*/
if (parser.frameState.isAfterSideEffect() && parsingIntrinsic()) {
for (StateSplit sideEffect : parser.frameState.sideEffects()) {
frameState.addSideEffect(sideEffect);
}
}
calleeBeforeUnwindNode = parser.getBeforeUnwindNode();
if (calleeBeforeUnwindNode != null) {
calleeUnwindValue = parser.getUnwindValue();
assert calleeUnwindValue != null;
}
}
/*
* Method handleException will call createTarget, which wires this exception edge to the
* corresponding exception dispatch block in the caller. In the case where it wires to the
* caller's unwind block, any FrameState created meanwhile, e.g., FrameState for
* LoopExitNode, would be instantiated with AFTER_EXCEPTION_BCI. Such frame states should
* not be fixed by IntrinsicScope.close, as they denote the states of the caller. Thus, the
* following code should be placed outside the IntrinsicScope, so that correctly created
* FrameStates are not replaced.
*/
if (calleeBeforeUnwindNode != null) {
calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci(), false));
}
}
use of org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext in project graal by oracle.
the class SnippetStub method getGraph.
@Override
@SuppressWarnings("try")
protected StructuredGraph getGraph(DebugContext debug, CompilationIdentifier compilationId) {
Plugins defaultPlugins = providers.getGraphBuilderPlugins();
MetaAccessProvider metaAccess = providers.getMetaAccess();
SnippetReflectionProvider snippetReflection = providers.getSnippetReflection();
Plugins plugins = new Plugins(defaultPlugins);
plugins.prependParameterPlugin(new ConstantBindingParameterPlugin(makeConstArgs(), metaAccess, snippetReflection));
GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins);
// Stubs cannot have optimistic assumptions since they have
// to be valid for the entire run of the VM.
final StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).compilationId(compilationId).build();
try (DebugContext.Scope outer = debug.scope("SnippetStub", graph)) {
graph.disableUnsafeAccessTracking();
IntrinsicContext initialIntrinsicContext = new IntrinsicContext(method, method, getReplacementsBytecodeProvider(), INLINE_AFTER_PARSING);
GraphBuilderPhase.Instance instance = new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), providers.getConstantFieldProvider(), config, OptimisticOptimizations.NONE, initialIntrinsicContext);
instance.apply(graph);
for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) {
int index = param.index();
if (method.getParameterAnnotation(NonNullParameter.class, index) != null) {
param.setStamp(param.stamp(NodeView.DEFAULT).join(StampFactory.objectNonNull()));
}
}
new RemoveValueProxyPhase().apply(graph);
graph.setGuardsStage(GuardsStage.FLOATING_GUARDS);
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
PhaseContext context = new PhaseContext(providers);
canonicalizer.apply(graph, context);
new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
} catch (Throwable e) {
throw debug.handle(e);
}
return graph;
}
use of org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext in project graal by oracle.
the class GraphKit method inline.
/**
* Inlines a given invocation to a method. The graph of the inlined method is processed in the
* same manner as for snippets and method substitutions.
*/
public void inline(InvokeNode invoke) {
ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod();
MetaAccessProvider metaAccess = providers.getMetaAccess();
Plugins plugins = new Plugins(graphBuilderPlugins);
GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins);
StructuredGraph calleeGraph = new StructuredGraph.Builder(invoke.getOptions(), invoke.getDebug()).method(method).build();
if (invoke.graph().trackNodeSourcePosition()) {
calleeGraph.setTrackNodeSourcePosition();
}
IntrinsicContext initialReplacementContext = new IntrinsicContext(method, method, providers.getReplacements().getDefaultReplacementBytecodeProvider(), INLINE_AFTER_PARSING);
GraphBuilderPhase.Instance instance = new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), providers.getConstantFieldProvider(), config, OptimisticOptimizations.NONE, initialReplacementContext);
instance.apply(calleeGraph);
// Remove all frame states from inlinee
calleeGraph.clearAllStateAfter();
new DeadCodeEliminationPhase(Optionality.Required).apply(calleeGraph);
InliningUtil.inline(invoke, calleeGraph, false, method);
}
Aggregations