use of org.graalvm.compiler.nodes.java.MethodCallTargetNode in project graal by oracle.
the class PartialEvaluator method fastPartialEvaluation.
@SuppressWarnings({ "try", "unused" })
private void fastPartialEvaluation(CompilableTruffleAST compilable, TruffleInliningPlan inliningDecision, StructuredGraph graph, PhaseContext baseContext, HighTierContext tierContext) {
DebugContext debug = graph.getDebug();
doGraphPE(compilable, graph, tierContext, inliningDecision);
debug.dump(DebugContext.BASIC_LEVEL, graph, "After Partial Evaluation");
graph.maybeCompress();
// Perform deoptimize to guard conversion.
new ConvertDeoptimizeToGuardPhase().apply(graph, tierContext);
for (MethodCallTargetNode methodCallTargetNode : graph.getNodes(MethodCallTargetNode.TYPE)) {
StructuredGraph inlineGraph = providers.getReplacements().getSubstitution(methodCallTargetNode.targetMethod(), methodCallTargetNode.invoke().bci(), graph.trackNodeSourcePosition(), methodCallTargetNode.asNode().getNodeSourcePosition());
if (inlineGraph != null) {
InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, true, methodCallTargetNode.targetMethod());
}
}
// Perform conditional elimination.
new ConditionalEliminationPhase(false).apply(graph, tierContext);
canonicalizer.apply(graph, tierContext);
// Do single partial escape and canonicalization pass.
try (DebugContext.Scope pe = debug.scope("TrufflePartialEscape", graph)) {
new PartialEscapePhase(TruffleCompilerOptions.getValue(TruffleIterativePartialEscape), canonicalizer, graph.getOptions()).apply(graph, tierContext);
} catch (Throwable t) {
debug.handle(t);
}
// recompute loop frequencies now that BranchProbabilities have had time to canonicalize
ComputeLoopFrequenciesClosure.compute(graph);
applyInstrumentationPhases(graph, tierContext);
graph.maybeCompress();
PerformanceInformationHandler.reportPerformanceWarnings(compilable, graph);
}
use of org.graalvm.compiler.nodes.java.MethodCallTargetNode in project graal by oracle.
the class SpecialInvokeTypeFlow method onObservedUpdate.
@Override
public void onObservedUpdate(BigBang bb) {
assert this.isClone();
/*
* Initialize the callee lazily so that if the invoke flow is not reached in this context,
* i.e. for this clone, there is no callee linked.
*/
if (callee == null) {
MethodCallTargetNode target = (MethodCallTargetNode) invoke.callTarget();
callee = ((AnalysisMethod) target.targetMethod()).getTypeFlow();
// set the callee in the original invoke too
((DirectInvokeTypeFlow) originalInvoke).callee = callee;
}
TypeState invokeState = getReceiver().getState();
for (AnalysisObject receiverObject : invokeState.objects()) {
AnalysisContext calleeContext = bb.contextPolicy().calleeContext(bb, receiverObject, callerContext, callee);
MethodFlowsGraph calleeFlows = callee.addContext(bb, calleeContext, this);
if (calleesFlows.putIfAbsent(calleeFlows, Boolean.TRUE) == null) {
linkCallee(bb, false, calleeFlows);
}
updateReceiver(bb, calleeFlows, receiverObject);
}
}
use of org.graalvm.compiler.nodes.java.MethodCallTargetNode in project graal by oracle.
the class RuntimeStrengthenStampsPhase method processMethod.
@SuppressWarnings("try")
private void processMethod(CallTreeNode node, Deque<CallTreeNode> worklist, BigBang bb) {
AnalysisMethod method = node.implementationMethod;
assert method.isImplementationInvoked();
if (node.graph == null) {
if (method.getAnnotation(Fold.class) != null || method.getAnnotation(NodeIntrinsic.class) != null) {
VMError.shouldNotReachHere("Parsing method annotated with @Fold or @NodeIntrinsic: " + method.format("%H.%n(%p)"));
}
boolean parse = false;
DebugContext debug = bb.getDebug();
StructuredGraph graph = method.buildGraph(debug, method, hostedProviders, Purpose.PREPARE_RUNTIME_COMPILATION);
if (graph == null) {
if (!method.hasBytecodes()) {
return;
}
parse = true;
graph = new StructuredGraph.Builder(debug.getOptions(), debug, AllowAssumptions.YES).method(method).build();
}
try (DebugContext.Scope scope = debug.scope("RuntimeCompile", graph)) {
if (parse) {
RuntimeGraphBuilderPhase builderPhase = new RuntimeGraphBuilderPhase(hostedProviders.getMetaAccess(), hostedProviders.getStampProvider(), hostedProviders.getConstantReflection(), hostedProviders.getConstantFieldProvider(), graphBuilderConfig, optimisticOpts, null, hostedProviders.getWordTypes(), deoptimizeOnExceptionPredicate, node);
builderPhase.apply(graph);
}
if (graph.getNodes(StackValueNode.TYPE).isNotEmpty()) {
/*
* Stack allocated memory is not seen by the deoptimization code, i.e., it is
* not copied in case of deoptimization. Also, pointers to it can be used for
* arbitrary address arithmetic, so we would not know how to update derived
* pointers into stack memory during deoptimization. Therefore, we cannot allow
* methods that allocate stack memory for runtime compilation. To remove this
* limitation, we would need to change how we handle stack allocated memory in
* Graal.
*/
return;
}
PhaseContext phaseContext = new PhaseContext(hostedProviders);
new CanonicalizerPhase().apply(graph, phaseContext);
new ConvertDeoptimizeToGuardPhase().apply(graph, phaseContext);
graphEncoder.prepare(graph);
node.graph = graph;
} catch (Throwable ex) {
debug.handle(ex);
}
}
assert node.graph != null;
List<MethodCallTargetNode> callTargets = node.graph.getNodes(MethodCallTargetNode.TYPE).snapshot();
callTargets.sort((t1, t2) -> Integer.compare(t1.invoke().bci(), t2.invoke().bci()));
for (MethodCallTargetNode targetNode : callTargets) {
AnalysisMethod targetMethod = (AnalysisMethod) targetNode.targetMethod();
AnalysisMethod callerMethod = (AnalysisMethod) targetNode.invoke().stateAfter().getMethod();
InvokeTypeFlow invokeFlow = callerMethod.getTypeFlow().getOriginalMethodFlows().getInvoke(targetNode.invoke().bci());
if (invokeFlow == null) {
continue;
}
Collection<AnalysisMethod> allImplementationMethods = invokeFlow.getCallees();
/*
* Eventually we want to remove all invokes that are unreachable, i.e., have no
* implementation. But the analysis is iterative, and we don't know here if we have
* already reached the fixed point. So we only collect unreachable invokes here, and
* remove them after the analysis has finished.
*/
if (allImplementationMethods.size() == 0) {
node.unreachableInvokes.add(targetNode.invoke());
} else {
node.unreachableInvokes.remove(targetNode.invoke());
}
List<AnalysisMethod> implementationMethods = new ArrayList<>();
for (AnalysisMethod implementationMethod : allImplementationMethods) {
/* Filter out all the implementation methods that have already been processed. */
if (!methods.containsKey(implementationMethod)) {
implementationMethods.add(implementationMethod);
}
}
if (implementationMethods.size() > 0) {
/* Sort to make printing order and method discovery order deterministic. */
implementationMethods.sort((m1, m2) -> m1.format("%H.%n(%p)").compareTo(m2.format("%H.%n(%p)")));
String sourceReference = buildSourceReference(targetNode.invoke().stateAfter());
for (AnalysisMethod implementationMethod : implementationMethods) {
CallTreeNode calleeNode = new CallTreeNode(implementationMethod, targetMethod, node, node.level + 1, sourceReference);
if (includeCalleePredicate.includeCallee(calleeNode, implementationMethods)) {
assert !methods.containsKey(implementationMethod);
methods.put(implementationMethod, calleeNode);
worklist.add(calleeNode);
node.children.add(calleeNode);
objectReplacer.createMethod(implementationMethod);
}
/*
* We must compile all methods which may be called. It may be the case that a
* call target does not reach the compile queue by default, e.g. if it is
* inlined at image generation but not at runtime compilation.
*/
CompilationInfoSupport.singleton().registerForcedCompilation(implementationMethod);
}
}
}
}
use of org.graalvm.compiler.nodes.java.MethodCallTargetNode in project graal by oracle.
the class RuntimeStrengthenStampsPhase method printStaticTruffleBoundaries.
private void printStaticTruffleBoundaries() {
HashSet<ResolvedJavaMethod> foundBoundaries = new HashSet<>();
int callSiteCount = 0;
int calleeCount = 0;
for (CallTreeNode node : methods.values()) {
StructuredGraph graph = node.graph;
for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.TYPE)) {
ResolvedJavaMethod targetMethod = callTarget.targetMethod();
TruffleBoundary truffleBoundary = targetMethod.getAnnotation(TruffleBoundary.class);
if (truffleBoundary != null) {
++callSiteCount;
if (foundBoundaries.contains(targetMethod)) {
// nothing to do
} else {
foundBoundaries.add(targetMethod);
System.out.println("Truffle boundary found: " + targetMethod);
calleeCount++;
}
}
}
}
System.out.println(String.format("Number of Truffle call boundaries: %d, number of unique called methods outside the boundary: %d", callSiteCount, calleeCount));
}
use of org.graalvm.compiler.nodes.java.MethodCallTargetNode in project graal by oracle.
the class DefaultHotSpotLoweringProvider method lowerInvoke.
private void lowerInvoke(Invoke invoke, LoweringTool tool, StructuredGraph graph) {
if (invoke.callTarget() instanceof MethodCallTargetNode) {
MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget();
NodeInputList<ValueNode> parameters = callTarget.arguments();
ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0);
if (!callTarget.isStatic() && receiver.stamp(NodeView.DEFAULT) instanceof ObjectStamp && !StampTool.isPointerNonNull(receiver)) {
ValueNode nonNullReceiver = createNullCheckedValue(receiver, invoke.asNode(), tool);
parameters.set(0, nonNullReceiver);
receiver = nonNullReceiver;
}
JavaType[] signature = callTarget.targetMethod().getSignature().toParameterTypes(callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass());
LoweredCallTargetNode loweredCallTarget = null;
OptionValues options = graph.getOptions();
if (InlineVTableStubs.getValue(options) && callTarget.invokeKind().isIndirect() && (AlwaysInlineVTableStubs.getValue(options) || invoke.isPolymorphic())) {
HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod();
ResolvedJavaType receiverType = invoke.getReceiverType();
if (hsMethod.isInVirtualMethodTable(receiverType)) {
JavaKind wordKind = runtime.getTarget().wordJavaKind;
ValueNode hub = createReadHub(graph, receiver, tool);
ReadNode metaspaceMethod = createReadVirtualMethod(graph, hub, hsMethod, receiverType);
// We use LocationNode.ANY_LOCATION for the reads that access the
// compiled code entry as HotSpot does not guarantee they are final
// values.
int methodCompiledEntryOffset = runtime.getVMConfig().methodCompiledEntryOffset;
AddressNode address = createOffsetAddress(graph, metaspaceMethod, methodCompiledEntryOffset);
ReadNode compiledEntry = graph.add(new ReadNode(address, any(), StampFactory.forKind(wordKind), BarrierType.NONE));
loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters.toArray(new ValueNode[parameters.size()]), callTarget.returnStamp(), signature, callTarget.targetMethod(), HotSpotCallingConventionType.JavaCall, callTarget.invokeKind()));
graph.addBeforeFixed(invoke.asNode(), metaspaceMethod);
graph.addAfterFixed(metaspaceMethod, compiledEntry);
}
}
if (loweredCallTarget == null) {
loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters.toArray(new ValueNode[parameters.size()]), callTarget.returnStamp(), signature, callTarget.targetMethod(), HotSpotCallingConventionType.JavaCall, callTarget.invokeKind()));
}
callTarget.replaceAndDelete(loweredCallTarget);
}
}
Aggregations