Skip to content

Commit 25a40ea

Browse files
committed
[GR-50840] try to use calltree for call traces.
PullRequest: graal/16450
2 parents bc42507 + 09e500a commit 25a40ea

File tree

3 files changed

+59
-35
lines changed

3 files changed

+59
-35
lines changed

substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/CallTreeInfo.java

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ public final class CallTreeInfo {
5353
private final Map<AnalysisMethod, RuntimeCompiledMethod> runtimeCompilations;
5454
private Map<RuntimeCompilationCandidate, InvokeNode> runtimeCandidateMap;
5555
private Map<AnalysisMethod, MethodNode> analysisMethodMap;
56-
private boolean callTreeInitialized = false;
57-
private boolean callTraceInitialized = false;
56+
private boolean initialized = false;
5857

5958
private CallTreeInfo(Map<AnalysisMethod, RuntimeCompiledMethod> runtimeCompilations) {
6059
this.runtimeCompilations = runtimeCompilations;
@@ -82,12 +81,7 @@ public static CallTreeInfo create(AnalysisUniverse aUniverse, Map<AnalysisMethod
8281
return new CallTreeInfo(runtimeCompilations);
8382
}
8483

85-
private void initializeCallTraceInfo() {
86-
if (callTraceInitialized) {
87-
return;
88-
}
89-
90-
callTraceInitialized = true;
84+
private void initializeCallerInfo() {
9185
analysisMethodMap = new HashMap<>();
9286
runtimeCandidateMap = new HashMap<>();
9387

@@ -131,22 +125,22 @@ private void initializeCallTraceInfo() {
131125
}
132126
}
133127

134-
public void initializeCallTreeInfo(Set<AnalysisMethod> registeredRoots) {
135-
if (callTreeInitialized) {
128+
public void initialize(Set<AnalysisMethod> registeredRoots) {
129+
if (initialized) {
136130
return;
137131
}
138132

139-
initializeCallTraceInfo();
140-
callTreeInitialized = true;
133+
initializeCallerInfo();
134+
initialized = true;
141135

142136
// ensure invokeInfo calculated
143137

144138
Queue<MethodNode> worklist = new LinkedList<>();
145139
/*
146-
* First initialize all nodes with no callers.
140+
* First initialize all nodes which are registered roots
147141
*/
148142
for (var methodNode : analysisMethodMap.values()) {
149-
if (methodNode.getCallers().isEmpty() || registeredRoots.contains(methodNode.method.getMultiMethod(ORIGINAL_METHOD))) {
143+
if (registeredRoots.contains(methodNode.method.getMultiMethod(ORIGINAL_METHOD))) {
150144
worklist.add(methodNode);
151145
methodNode.trace = new TraceInfo(0, new BytecodePosition(null, methodNode.method, BytecodeFrame.UNKNOWN_BCI), null);
152146
}
@@ -189,8 +183,8 @@ public void initializeCallTreeInfo(Set<AnalysisMethod> registeredRoots) {
189183
private static final String[] UNKNOWN_TRACE = new String[]{"Unknown"};
190184
private static final String[] EMPTY_STRING = new String[0];
191185

192-
public static String[] getCallTrace(CallTreeInfo callTreeInfo, AnalysisMethod method) {
193-
callTreeInfo.initializeCallTraceInfo();
186+
static String[] getCallTrace(CallTreeInfo callTreeInfo, AnalysisMethod method, Set<AnalysisMethod> registeredRuntimeCompilations) {
187+
callTreeInfo.initialize(registeredRuntimeCompilations);
194188
MethodNode methodNode = callTreeInfo.analysisMethodMap.get(method);
195189
if (methodNode == null) {
196190
return UNKNOWN_TRACE;
@@ -201,8 +195,8 @@ public static String[] getCallTrace(CallTreeInfo callTreeInfo, AnalysisMethod me
201195
return trace.toArray(EMPTY_STRING);
202196
}
203197

204-
public static String[] getCallTrace(CallTreeInfo callTreeInfo, RuntimeCompilationCandidate candidate) {
205-
callTreeInfo.initializeCallTraceInfo();
198+
static String[] getCallTrace(CallTreeInfo callTreeInfo, RuntimeCompilationCandidate candidate, Set<AnalysisMethod> registeredRuntimeCompilations) {
199+
callTreeInfo.initialize(registeredRuntimeCompilations);
206200
InvokeNode invokeNode = callTreeInfo.runtimeCandidateMap.get(candidate);
207201
if (invokeNode == null) {
208202
return UNKNOWN_TRACE;
@@ -214,26 +208,48 @@ public static String[] getCallTrace(CallTreeInfo callTreeInfo, RuntimeCompilatio
214208
}
215209

216210
private static void findCallTraceHelper(ArrayList<String> trace, MethodNode first) {
217-
Set<MethodNode> covered = new HashSet<>();
218-
MethodNode current = first;
219-
covered.add(current);
220-
221-
while (current != null) {
222-
// find parent
223-
MethodNode parent = null;
224-
for (InvokeNode caller : current.getCallers()) {
225-
if (covered.add(caller.method)) {
211+
if (first.trace != null) {
212+
/*
213+
* If there is a known trace from root, then we can return this
214+
*/
215+
MethodNode current = first;
216+
while (current != null) {
217+
MethodNode parent = null;
218+
InvokeNode caller = current.trace.invokeParent;
219+
if (caller != null) {
226220
parent = caller.method;
227221
trace.add(caller.position.toString());
228-
break;
229222
}
223+
current = parent;
224+
}
225+
trace.add("[Root]");
226+
227+
} else {
228+
/*
229+
* Otherwise we will walk an arbitrary caller until there is not a caller or we
230+
* encounter a cycle.
231+
*/
232+
Set<MethodNode> covered = new HashSet<>();
233+
MethodNode current = first;
234+
covered.add(current);
235+
236+
while (current != null) {
237+
// find parent
238+
MethodNode parent = null;
239+
for (InvokeNode caller : current.getCallers()) {
240+
if (covered.add(caller.method)) {
241+
parent = caller.method;
242+
trace.add(caller.position.toString());
243+
break;
244+
}
245+
}
246+
current = parent;
230247
}
231-
current = parent;
232248
}
233249
}
234250

235251
public static void printCallTree(CallTreeInfo info, Set<AnalysisMethod> registeredRuntimeCompilations) {
236-
info.initializeCallTreeInfo(registeredRuntimeCompilations);
252+
info.initialize(registeredRuntimeCompilations);
237253

238254
System.out.println("depth;method;invoke position");
239255
for (MethodNode methodNode : info.analysisMethodMap.values()) {
@@ -255,7 +271,7 @@ private static void printCallTreeNode(MethodNode node) {
255271
}
256272

257273
public static void printDeepestPath(CallTreeInfo info, Set<AnalysisMethod> registeredRuntimeCompilations) {
258-
info.initializeCallTreeInfo(registeredRuntimeCompilations);
274+
info.initialize(registeredRuntimeCompilations);
259275

260276
Optional<MethodNode> deepestNode = info.analysisMethodMap.values().stream().max(Comparator.comparingInt(t -> t.trace == null ? -1 : t.trace.level));
261277

substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompilationFeature.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,14 @@ public void initializeAnalysisProviders(BigBang bb, Function<ConstantFieldProvid
300300
analysisProviders = customHostedProviders;
301301
}
302302

303+
public String[] getCallTrace(CallTreeInfo callTreeInfo, AnalysisMethod method) {
304+
return CallTreeInfo.getCallTrace(callTreeInfo, method, registeredRuntimeCompilations);
305+
}
306+
307+
public String[] getCallTrace(CallTreeInfo callTreeInfo, RuntimeCompilationCandidate candidate) {
308+
return CallTreeInfo.getCallTrace(callTreeInfo, candidate, registeredRuntimeCompilations);
309+
}
310+
303311
public CallTreeInfo getCallTreeInfo() {
304312
VMError.guarantee(callTreeMetadata != null);
305313
return callTreeMetadata;
@@ -577,7 +585,7 @@ public void reportAnalysisError(AnalysisUniverse aUniverse, Throwable t) {
577585
System.out.println("Parsing failed on a special method version: " + errorMethod.format("%H.%n"));
578586
System.out.println("Method reachability trace");
579587
if (failingRuntimeMethod != null) {
580-
Arrays.stream(CallTreeInfo.getCallTrace(treeInfo, failingRuntimeMethod)).forEach(System.out::println);
588+
Arrays.stream(CallTreeInfo.getCallTrace(treeInfo, failingRuntimeMethod, registeredRuntimeCompilations)).forEach(System.out::println);
581589
} else {
582590
System.out.println("trace unavailable");
583591
}

substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleFeature.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -804,7 +804,7 @@ private void checkBlockList(CallTreeInfo treeInfo) {
804804
tempTargetAllowlistMethods.contains(candidate.getTargetMethod()) &&
805805
!isBlocklisted(candidate.getImplementationMethod());
806806
if (!tempAllow) {
807-
BlocklistViolationInfo violation = new BlocklistViolationInfo(candidate, CallTreeInfo.getCallTrace(treeInfo, candidate));
807+
BlocklistViolationInfo violation = new BlocklistViolationInfo(candidate, runtimeCompilation.getCallTrace(treeInfo, candidate));
808808
blocklistViolations.add(violation);
809809
}
810810
}
@@ -846,7 +846,7 @@ private void checkBlockList(CallTreeInfo treeInfo) {
846846
for (RuntimeCompilationCandidate violation : warnViolations) {
847847
System.out.println("Suspicious method: " + violation.getImplementationMethod().format("%H.%n(%p)"));
848848
System.out.println("trace:");
849-
for (String item : CallTreeInfo.getCallTrace(treeInfo, violation)) {
849+
for (String item : runtimeCompilation.getCallTrace(treeInfo, violation)) {
850850
System.out.println(" " + item);
851851
}
852852
}
@@ -857,7 +857,7 @@ private void checkBlockList(CallTreeInfo treeInfo) {
857857
for (Pair<ResolvedJavaMethod, String> violation : neverPartOfCompilationViolations) {
858858
System.out.println("called from");
859859
System.out.println("(inlined call path): " + violation.getRight());
860-
for (String item : CallTreeInfo.getCallTrace(treeInfo, (AnalysisMethod) violation.getLeft())) {
860+
for (String item : runtimeCompilation.getCallTrace(treeInfo, (AnalysisMethod) violation.getLeft())) {
861861
System.out.println(" " + item);
862862
}
863863
}

0 commit comments

Comments
 (0)