diff --git a/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/StandalonePointsToAnalysis.java b/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/StandalonePointsToAnalysis.java index 8a1d4ce05f4d..4a957f777cdf 100644 --- a/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/StandalonePointsToAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/StandalonePointsToAnalysis.java @@ -70,7 +70,7 @@ public void initializeMetaData(AnalysisType type) { public void onTypeInitialized(AnalysisType type) { AnalysisMethod clinitMethod = type.getClassInitializer(); if (clinitMethod != null && !addedClinits.contains(clinitMethod)) { - addRootMethod(clinitMethod, true).registerAsImplementationInvoked(); + addRootMethod(clinitMethod, true).registerAsImplementationInvoked(type); addedClinits.add(clinitMethod); } } diff --git a/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/features/StandaloneAnalysisFeatureImpl.java b/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/features/StandaloneAnalysisFeatureImpl.java index 3d72bf4b593f..2fc327e67d00 100644 --- a/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/features/StandaloneAnalysisFeatureImpl.java +++ b/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/features/StandaloneAnalysisFeatureImpl.java @@ -241,11 +241,11 @@ public void registerAsUnsafeAccessed(AnalysisField aField, UnsafePartitionKind p } public void registerAsInvoked(Executable method, boolean invokeSpecial) { - registerAsInvoked(getMetaAccess().lookupJavaMethod(method), invokeSpecial); + registerAsInvoked(getMetaAccess().lookupJavaMethod(method), invokeSpecial, "registered from standalone feature"); } - public void registerAsInvoked(AnalysisMethod aMethod, boolean invokeSpecial) { - bb.addRootMethod(aMethod, invokeSpecial).registerAsImplementationInvoked(); + public void registerAsInvoked(AnalysisMethod aMethod, boolean invokeSpecial, Object reason) { + bb.addRootMethod(aMethod, invokeSpecial).registerAsImplementationInvoked(reason); } public void registerUnsafeFieldsRecomputed(Class clazz) { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java index 6d63c8270f60..05d507a89270 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java @@ -313,7 +313,7 @@ public AnalysisMethod addRootMethod(AnalysisMethod aMethod, boolean invokeSpecia */ postTask(() -> { pointsToMethod.registerAsDirectRootMethod(); - pointsToMethod.registerAsImplementationInvoked(null); + pointsToMethod.registerAsImplementationInvoked("root method"); MethodFlowsGraph methodFlowsGraph = analysisPolicy.staticRootMethodGraph(this, pointsToMethod); for (int idx = 0; idx < paramCount; idx++) { AnalysisType declaredParamType = (AnalysisType) signature.getParameterType(idx, declaringClass); diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/CallSiteSensitiveMethodTypeFlow.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/CallSiteSensitiveMethodTypeFlow.java index 907cb3034378..afc02392b32f 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/CallSiteSensitiveMethodTypeFlow.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/CallSiteSensitiveMethodTypeFlow.java @@ -53,10 +53,6 @@ public CallSiteSensitiveMethodTypeFlow(OptionValues options, PointsToAnalysisMet /** * Add the context, if not already added, and return the method flows clone from that context. */ - public MethodFlowsGraph addContext(PointsToAnalysis bb, AnalysisContext calleeContext) { - return addContext(bb, calleeContext, null); - } - public MethodFlowsGraph addContext(PointsToAnalysis bb, AnalysisContext calleeContext, InvokeTypeFlow reason) { /* Ensure that the method is parsed before attempting to clone it. */ diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlow.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlow.java index c9af7992e368..217df680591a 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlow.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlow.java @@ -94,7 +94,7 @@ private synchronized void createFlowsGraph(PointsToAnalysis bb, InvokeTypeFlow r parsingReason = reason; try { MethodTypeFlowBuilder builder = bb.createMethodTypeFlowBuilder(bb, method); - builder.apply(); + builder.apply(PointsToAnalysisMethod.unwrapInvokeReason(parsingReason)); returnedParameterIndex = computeReturnedParameterIndex(builder.graph); bb.numParsedGraphs.incrementAndGet(); diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java index a6663a611ff6..402b48c0c024 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java @@ -179,10 +179,10 @@ public MethodTypeFlowBuilder(PointsToAnalysis bb, StructuredGraph graph) { } @SuppressWarnings("try") - private boolean parse() { + private boolean parse(Object reason) { AnalysisParsedGraph analysisParsedGraph = method.ensureGraphParsed(bb); if (analysisParsedGraph.isIntrinsic()) { - method.registerAsIntrinsicMethod(); + method.registerAsIntrinsicMethod(reason); } if (analysisParsedGraph.getEncodedGraph() == null) { @@ -394,7 +394,7 @@ private static void registerForeignCall(PointsToAnalysis bb, ForeignCallDescript targetMethod.ifPresent(analysisMethod -> bb.addRootMethod(analysisMethod, true)); } - protected void apply() { + protected void apply(Object reason) { // assert method.getAnnotation(Fold.class) == null : method; if (AnnotationAccess.isAnnotationPresent(method, NodeIntrinsic.class)) { graph.getDebug().log("apply MethodTypeFlow on node intrinsic %s", method); @@ -417,7 +417,7 @@ protected void apply() { return; } - if (!parse()) { + if (!parse(reason)) { return; } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/context/bytecode/BytecodeSensitiveAnalysisPolicy.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/context/bytecode/BytecodeSensitiveAnalysisPolicy.java index 9dad79a85bed..642e567feb08 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/context/bytecode/BytecodeSensitiveAnalysisPolicy.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/context/bytecode/BytecodeSensitiveAnalysisPolicy.java @@ -338,7 +338,7 @@ public AbstractStaticInvokeTypeFlow createStaticInvokeTypeFlow(BytecodePosition @Override public MethodFlowsGraph staticRootMethodGraph(PointsToAnalysis bb, PointsToAnalysisMethod pointsToMethod) { - return ((CallSiteSensitiveMethodTypeFlow) pointsToMethod.getTypeFlow()).addContext(bb, contextPolicy.emptyContext()); + return ((CallSiteSensitiveMethodTypeFlow) pointsToMethod.getTypeFlow()).addContext(bb, contextPolicy.emptyContext(), null); } @Override diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java index 7ee56afbb990..5823972ecfd2 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java @@ -36,6 +36,7 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; @@ -80,17 +81,17 @@ public abstract class AnalysisMethod extends AnalysisElement implements WrappedJ private static final AtomicIntegerFieldUpdater isDirectRootMethodUpdater = AtomicIntegerFieldUpdater .newUpdater(AnalysisMethod.class, "isDirectRootMethod"); - private static final AtomicIntegerFieldUpdater isInvokedUpdater = AtomicIntegerFieldUpdater - .newUpdater(AnalysisMethod.class, "isInvoked"); + private static final AtomicReferenceFieldUpdater isInvokedUpdater = AtomicReferenceFieldUpdater + .newUpdater(AnalysisMethod.class, Object.class, "isInvoked"); - private static final AtomicIntegerFieldUpdater isImplementationInvokedUpdater = AtomicIntegerFieldUpdater - .newUpdater(AnalysisMethod.class, "isImplementationInvoked"); + private static final AtomicReferenceFieldUpdater isImplementationInvokedUpdater = AtomicReferenceFieldUpdater + .newUpdater(AnalysisMethod.class, Object.class, "isImplementationInvoked"); - private static final AtomicIntegerFieldUpdater isIntrinsicMethodUpdater = AtomicIntegerFieldUpdater - .newUpdater(AnalysisMethod.class, "isIntrinsicMethod"); + private static final AtomicReferenceFieldUpdater isIntrinsicMethodUpdater = AtomicReferenceFieldUpdater + .newUpdater(AnalysisMethod.class, Object.class, "isIntrinsicMethod"); - private static final AtomicIntegerFieldUpdater isInlinedUpdater = AtomicIntegerFieldUpdater - .newUpdater(AnalysisMethod.class, "isInlined"); + private static final AtomicReferenceFieldUpdater isInlinedUpdater = AtomicReferenceFieldUpdater + .newUpdater(AnalysisMethod.class, Object.class, "isInlined"); public final ResolvedJavaMethod wrapped; @@ -108,10 +109,10 @@ public abstract class AnalysisMethod extends AnalysisElement implements WrappedJ /** Direct (special or static) invoked method registered as root. */ @SuppressWarnings("unused") private volatile int isDirectRootMethod; private Object entryPointData; - @SuppressWarnings("unused") private volatile int isInvoked; - @SuppressWarnings("unused") private volatile int isImplementationInvoked; - @SuppressWarnings("unused") private volatile int isIntrinsicMethod; - @SuppressWarnings("unused") private volatile int isInlined; + @SuppressWarnings("unused") private volatile Object isInvoked; + @SuppressWarnings("unused") private volatile Object isImplementationInvoked; + @SuppressWarnings("unused") private volatile Object isIntrinsicMethod; + @SuppressWarnings("unused") private volatile Object isInlined; private final AtomicReference parsedGraphCacheState = new AtomicReference<>(GRAPH_CACHE_UNPARSED); private static final Object GRAPH_CACHE_UNPARSED = "unparsed"; @@ -260,8 +261,9 @@ public int getId() { * builder plugin}. Such a method is treated similar to an invoked method. For example, method * resolution must be able to find the method (otherwise the intrinsification would not work). */ - public void registerAsIntrinsicMethod() { - AtomicUtils.atomicMarkAndRun(this, isIntrinsicMethodUpdater, this::onReachable); + public void registerAsIntrinsicMethod(Object reason) { + assert isValidReason(reason) : "Registering a method as intrinsic needs to provide a valid reason, found: " + reason; + AtomicUtils.atomicSetAndRun(this, reason, isIntrinsicMethodUpdater, this::onReachable); } public void registerAsEntryPoint(Object newEntryPointData) { @@ -274,11 +276,13 @@ public void registerAsEntryPoint(Object newEntryPointData) { startTrackInvocations(); } - public boolean registerAsInvoked() { - return AtomicUtils.atomicMark(this, isInvokedUpdater); + public boolean registerAsInvoked(Object reason) { + assert isValidReason(reason) : "Registering a method as invoked needs to provide a valid reason, found: " + reason; + return AtomicUtils.atomicSet(this, reason, isInvokedUpdater); } - public boolean registerAsImplementationInvoked() { + public boolean registerAsImplementationInvoked(Object reason) { + assert isValidReason(reason) : "Registering a method as implementation invoked needs to provide a valid reason, found: " + reason; assert !Modifier.isAbstract(getModifiers()); /* @@ -290,11 +294,12 @@ public boolean registerAsImplementationInvoked() { * return before the class gets marked as reachable. */ getDeclaringClass().registerAsReachable("declared method " + this.format("%H.%n(%p)") + " is registered as implementation invoked"); - return AtomicUtils.atomicMarkAndRun(this, isImplementationInvokedUpdater, this::onReachable); + return AtomicUtils.atomicSetAndRun(this, reason, isImplementationInvokedUpdater, this::onReachable); } - public void registerAsInlined() { - AtomicUtils.atomicMarkAndRun(this, isInlinedUpdater, this::onReachable); + public void registerAsInlined(Object reason) { + assert isValidReason(reason) : "Registering a method as inlined needs to provide a valid reason, found: " + reason; + AtomicUtils.atomicSetAndRun(this, reason, isInlinedUpdater, this::onReachable); } /** Get the set of all callers for this method, as inferred by the static analysis. */ @@ -324,7 +329,7 @@ public boolean isIntrinsicMethod() { * as invoked also makes the declaring class reachable. * * Class is always marked as reachable regardless of the success of the atomic mark, same reason - * as in {@link AnalysisMethod#registerAsImplementationInvoked()}. + * as in {@link AnalysisMethod#registerAsImplementationInvoked(Object)}. */ public boolean registerAsVirtualRootMethod() { getDeclaringClass().registerAsReachable("declared method " + this.format("%H.%n(%p)") + " is registered as virtual root"); diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/PointsToAnalysisMethod.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/PointsToAnalysisMethod.java index e4d10009bf1f..4dfafe1a8053 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/PointsToAnalysisMethod.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/PointsToAnalysisMethod.java @@ -26,8 +26,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicReference; import com.oracle.graal.pointsto.PointsToAnalysis; @@ -48,8 +48,8 @@ public class PointsToAnalysisMethod extends AnalysisMethod { private MethodTypeFlow typeFlow; - private ConcurrentMap invokedBy; - private ConcurrentMap implementationInvokedBy; + private Set invokedBy; + private Set implementationInvokedBy; /** * Unique, per method, context insensitive invoke. The context insensitive invoke uses the * receiver type of the method, i.e., its declaring-class. Therefore, this invoke will link with @@ -66,10 +66,10 @@ public class PointsToAnalysisMethod extends AnalysisMethod { @Override public void startTrackInvocations() { if (invokedBy == null) { - invokedBy = new ConcurrentHashMap<>(); + invokedBy = ConcurrentHashMap.newKeySet(); } if (implementationInvokedBy == null) { - implementationInvokedBy = new ConcurrentHashMap<>(); + implementationInvokedBy = ConcurrentHashMap.newKeySet(); } } @@ -77,24 +77,44 @@ public MethodTypeFlow getTypeFlow() { return typeFlow; } - public boolean registerAsInvoked(InvokeTypeFlow invoke) { - if (invokedBy != null && invoke != null) { - invokedBy.put(invoke, Boolean.TRUE); + @Override + public boolean registerAsInvoked(Object reason) { + assert reason instanceof InvokeTypeFlow || reason instanceof String; + if (invokedBy != null && reason instanceof InvokeTypeFlow) { + invokedBy.add((InvokeTypeFlow) reason); + } + return super.registerAsInvoked(unwrapInvokeReason(reason)); + } + + @Override + public boolean registerAsImplementationInvoked(Object reason) { + assert reason instanceof InvokeTypeFlow || reason instanceof String; + if (implementationInvokedBy != null && reason instanceof InvokeTypeFlow) { + implementationInvokedBy.add((InvokeTypeFlow) reason); } - return super.registerAsInvoked(); + return super.registerAsImplementationInvoked(unwrapInvokeReason(reason)); } - public boolean registerAsImplementationInvoked(InvokeTypeFlow invoke) { - if (implementationInvokedBy != null && invoke != null) { - implementationInvokedBy.put(invoke, Boolean.TRUE); + /** + * In general the reason for a method invocation is an {@link InvokeTypeFlow}. Special and + * virtual root methods have the corresponding context-insensitive invoke reason set. Static + * root method doesn't have any reason set. + */ + public static Object unwrapInvokeReason(Object reason) { + if (reason == null) { + return "static root method"; + } + if (reason instanceof InvokeTypeFlow) { + BytecodePosition source = ((InvokeTypeFlow) reason).getSource(); + return source != null ? source : "root method"; } - return super.registerAsImplementationInvoked(); + return reason; } @Override public List getInvokeLocations() { List locations = new ArrayList<>(); - for (InvokeTypeFlow invoke : implementationInvokedBy.keySet()) { + for (InvokeTypeFlow invoke : implementationInvokedBy) { if (InvokeTypeFlow.isContextInsensitiveVirtualInvoke(invoke)) { locations.addAll(((AbstractVirtualInvokeTypeFlow) invoke).getInvokeLocations()); } else if (invoke.getSource() != null) { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysis.java index b470238cecdb..de6441e37df8 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysis.java @@ -28,7 +28,6 @@ import java.util.Deque; import java.util.concurrent.ConcurrentHashMap; -import com.oracle.graal.pointsto.BigBang; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; @@ -52,6 +51,7 @@ import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import org.graalvm.compiler.replacements.PEGraphDecoder; +import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.flow.AnalysisParsedGraph; import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.svm.util.ClassUtil; @@ -278,7 +278,9 @@ protected void finishInlining(MethodScope is) { if (callerScope.policyScope != null) { policy.commitCalleeScope(callerScope.policyScope, inlineScope.policyScope); } - ((AnalysisMethod) invokeData.callTarget.targetMethod()).registerAsInlined(); + Object reason = graph.currentNodeSourcePosition() != null ? graph.currentNodeSourcePosition() : graph.method(); + + ((AnalysisMethod) invokeData.callTarget.targetMethod()).registerAsInlined(reason); super.finishInlining(inlineScope); } diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/DirectMethodProcessingHandler.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/DirectMethodProcessingHandler.java index d63642edb581..ec7ad2afc984 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/DirectMethodProcessingHandler.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/DirectMethodProcessingHandler.java @@ -27,6 +27,7 @@ import java.lang.reflect.Modifier; import java.util.Optional; +import jdk.vm.ci.code.BytecodePosition; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallSignature; import org.graalvm.compiler.graph.Node; @@ -135,13 +136,14 @@ private static void analyzeStructuredGraph(ReachabilityAnalysisEngine bb, Reacha if (targetMethod == null || AnnotationAccess.isAnnotationPresent(targetMethod, Node.NodeIntrinsic.class)) { continue; } + BytecodePosition reason = AbstractAnalysisEngine.sourcePosition(node.asNode()); if (method != null) { - method.addInvoke(new ReachabilityInvokeInfo(targetMethod, AbstractAnalysisEngine.sourcePosition(node.asNode()), kind.isDirect())); + method.addInvoke(new ReachabilityInvokeInfo(targetMethod, reason, kind.isDirect())); } if (kind.isDirect()) { - bb.markMethodImplementationInvoked(targetMethod); + bb.markMethodImplementationInvoked(targetMethod, reason); } else { - bb.markMethodInvoked(targetMethod); + bb.markMethodInvoked(targetMethod, reason); } } else if (n instanceof FrameState) { FrameState node = (FrameState) n; @@ -159,10 +161,11 @@ private static void analyzeStructuredGraph(ReachabilityAnalysisEngine bb, Reacha } else if (n instanceof MacroInvokable) { MacroInvokable node = (MacroInvokable) n; ReachabilityAnalysisMethod targetMethod = (ReachabilityAnalysisMethod) node.getTargetMethod(); + BytecodePosition reason = AbstractAnalysisEngine.syntheticSourcePosition(node.asNode(), method); if (node.getInvokeKind().isDirect()) { - bb.markMethodImplementationInvoked(targetMethod); + bb.markMethodImplementationInvoked(targetMethod, reason); } else { - bb.markMethodInvoked(targetMethod); + bb.markMethodInvoked(targetMethod, reason); } } else if (n instanceof ForeignCall) { handleForeignCall(bb, ((ForeignCall) n).getDescriptor()); diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummaryBasedHandler.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummaryBasedHandler.java index 45e361766412..7a9a0ab32520 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummaryBasedHandler.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/MethodSummaryBasedHandler.java @@ -77,10 +77,10 @@ public void processGraph(ReachabilityAnalysisEngine bb, StructuredGraph graph) { */ private static void processSummary(ReachabilityAnalysisEngine bb, ReachabilityAnalysisMethod method, MethodSummary summary) { for (AnalysisMethod invokedMethod : summary.invokedMethods) { - bb.markMethodInvoked((ReachabilityAnalysisMethod) invokedMethod); + bb.markMethodInvoked((ReachabilityAnalysisMethod) invokedMethod, method); } for (AnalysisMethod invokedMethod : summary.implementationInvokedMethods) { - bb.markMethodImplementationInvoked((ReachabilityAnalysisMethod) invokedMethod); + bb.markMethodImplementationInvoked((ReachabilityAnalysisMethod) invokedMethod, method); } for (AnalysisType type : summary.accessedTypes) { bb.registerTypeAsReachable(type, method); diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysisEngine.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysisEngine.java index 5ca3ac399d63..b80201bf7487 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysisEngine.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysisEngine.java @@ -56,8 +56,8 @@ /** * Core class of the Reachability Analysis. Contains the crucial part: resolving virtual methods. * The resolving is done in two directions. Whenever a new method is marked as virtually invoked, - * see {@link #onMethodInvoked(ReachabilityAnalysisMethod)}, and whenever a new type is marked as - * instantiated, see {@link #onTypeInstantiated(ReachabilityAnalysisType)}. + * see {@link #onMethodInvoked(ReachabilityAnalysisMethod, Object)}, and whenever a new type is + * marked as instantiated, see {@link #onTypeInstantiated(ReachabilityAnalysisType,Object)}. * * @see MethodSummary * @see MethodSummaryProvider @@ -142,28 +142,28 @@ public AnalysisMethod addRootMethod(AnalysisMethod m, boolean invokeSpecial) { if (!method.registerAsDirectRootMethod()) { return method; } - markMethodImplementationInvoked(method); + markMethodImplementationInvoked(method, "root method"); } else if (invokeSpecial) { AnalysisError.guarantee(!method.isAbstract(), "Abstract methods cannot be registered as special invoke entry point."); if (!method.registerAsDirectRootMethod()) { return method; } - markMethodImplementationInvoked(method); + markMethodImplementationInvoked(method, "root method"); } else { if (!method.registerAsVirtualRootMethod()) { return method; } - markMethodInvoked(method); + markMethodInvoked(method, "root method"); } return method; } - public void markMethodImplementationInvoked(ReachabilityAnalysisMethod method) { + public void markMethodImplementationInvoked(ReachabilityAnalysisMethod method, Object reason) { // Unlinked methods cannot be parsed if (!method.getWrapped().getDeclaringClass().isLinked()) { return; } - if (!method.registerAsImplementationInvoked()) { + if (!method.registerAsImplementationInvoked(reason)) { return; } schedule(() -> onMethodImplementationInvoked(method)); @@ -185,7 +185,7 @@ public boolean registerTypeAsInHeap(AnalysisType t, Object reason) { return false; } if (type.registerAsInstantiated()) { - schedule(() -> onTypeInstantiated(type)); + schedule(() -> onTypeInstantiated(type, reason)); } return true; } @@ -197,7 +197,7 @@ public boolean registerTypeAsAllocated(AnalysisType t, Object reason) { return false; } if (type.registerAsInstantiated()) { - schedule(() -> onTypeInstantiated(type)); + schedule(() -> onTypeInstantiated(type, reason)); } return true; } @@ -222,11 +222,11 @@ public void handleEmbeddedConstant(ReachabilityAnalysisMethod method, JavaConsta * We collect all instantiated subtypes of each type and then use this set to resolve the * virtual call. */ - private void onMethodInvoked(ReachabilityAnalysisMethod method) { + private void onMethodInvoked(ReachabilityAnalysisMethod method, Object reason) { ReachabilityAnalysisType clazz = method.getDeclaringClass(); if (method.isStatic()) { - markMethodImplementationInvoked(method); + markMethodImplementationInvoked(method, reason); return; } @@ -236,7 +236,7 @@ private void onMethodInvoked(ReachabilityAnalysisMethod method) { if (resolvedMethod == null) { continue; } - markMethodImplementationInvoked(resolvedMethod); + markMethodImplementationInvoked(resolvedMethod, reason); } } @@ -250,23 +250,23 @@ private void onMethodInvoked(ReachabilityAnalysisMethod method) { * NUMBER_OF_INVOKED_METHODS_ON_TYPE). and is one of the places that we should try to optimize * in near future. */ - private void onTypeInstantiated(ReachabilityAnalysisType type) { + private void onTypeInstantiated(ReachabilityAnalysisType type, Object reason) { type.forAllSuperTypes(current -> { Set invokedMethods = ((ReachabilityAnalysisType) current).getInvokedVirtualMethods(); for (ReachabilityAnalysisMethod curr : invokedMethods) { ReachabilityAnalysisMethod method = type.resolveConcreteMethod(curr, current); if (method != null) { - markMethodImplementationInvoked(method); + markMethodImplementationInvoked(method, reason); } } }); } - public void markMethodInvoked(ReachabilityAnalysisMethod method) { - if (!method.registerAsInvoked()) { + public void markMethodInvoked(ReachabilityAnalysisMethod method, Object reason) { + if (!method.registerAsInvoked(reason)) { return; } - schedule(() -> onMethodInvoked(method)); + schedule(() -> onMethodInvoked(method, reason)); } @Override diff --git a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysisMethod.java b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysisMethod.java index 784f5279a203..c247159e0574 100644 --- a/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysisMethod.java +++ b/substratevm/src/com.oracle.graal.reachability/src/com/oracle/graal/reachability/ReachabilityAnalysisMethod.java @@ -104,8 +104,8 @@ public void addCaller(BytecodePosition bytecodePosition) { } @Override - public boolean registerAsInvoked() { - if (super.registerAsInvoked()) { + public boolean registerAsInvoked(Object invokeReason) { + if (super.registerAsInvoked(invokeReason)) { if (!isStatic()) { getDeclaringClass().addInvokedVirtualMethod(this); } @@ -126,7 +126,7 @@ public ReachabilityAnalysisType getDeclaringClass() { public static StructuredGraph getDecodedGraph(ReachabilityAnalysisEngine bb, ReachabilityAnalysisMethod method) { AnalysisParsedGraph analysisParsedGraph = method.ensureGraphParsed(bb); if (analysisParsedGraph.isIntrinsic()) { - method.registerAsIntrinsicMethod(); + method.registerAsIntrinsicMethod("reachability analysis engine"); } AnalysisError.guarantee(analysisParsedGraph.getEncodedGraph() != null, "Cannot provide a summary for %s.", method.getQualifiedName()); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/AnalysisGraphBuilderPhase.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/AnalysisGraphBuilderPhase.java index 13a9b772a33f..f18c16a77fdc 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/AnalysisGraphBuilderPhase.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/AnalysisGraphBuilderPhase.java @@ -24,7 +24,6 @@ */ package com.oracle.svm.hosted.phases; -import com.oracle.graal.pointsto.infrastructure.AnalysisConstantPool; import org.graalvm.compiler.core.common.BootstrapMethodIntrospection; import org.graalvm.compiler.java.BytecodeParser; import org.graalvm.compiler.java.GraphBuilderPhase; @@ -40,6 +39,7 @@ import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.word.WordTypes; +import com.oracle.graal.pointsto.infrastructure.AnalysisConstantPool; import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.util.ModuleSupport; @@ -69,11 +69,15 @@ protected AnalysisBytecodeParser(GraphBuilderPhase.Instance graphBuilderInstance protected boolean tryInvocationPlugin(InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType) { boolean result = super.tryInvocationPlugin(invokeKind, args, targetMethod, resultType); if (result) { - ((AnalysisMethod) targetMethod).registerAsIntrinsicMethod(); + ((AnalysisMethod) targetMethod).registerAsIntrinsicMethod(nonNullReason(graph.currentNodeSourcePosition())); } return result; } + private static Object nonNullReason(Object reason) { + return reason == null ? "Unknown invocation location." : reason; + } + @Override protected boolean applyInvocationPlugin(InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType, InvocationPlugin plugin) { Class accessingClass = plugin.getClass();