Skip to content

Commit

Permalink
[GR-50840] try to use calltree for call traces.
Browse files Browse the repository at this point in the history
PullRequest: graal/16450
  • Loading branch information
teshull committed Dec 22, 2023
2 parents bc42507 + 09e500a commit 25a40ea
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ public final class CallTreeInfo {
private final Map<AnalysisMethod, RuntimeCompiledMethod> runtimeCompilations;
private Map<RuntimeCompilationCandidate, InvokeNode> runtimeCandidateMap;
private Map<AnalysisMethod, MethodNode> analysisMethodMap;
private boolean callTreeInitialized = false;
private boolean callTraceInitialized = false;
private boolean initialized = false;

private CallTreeInfo(Map<AnalysisMethod, RuntimeCompiledMethod> runtimeCompilations) {
this.runtimeCompilations = runtimeCompilations;
Expand Down Expand Up @@ -82,12 +81,7 @@ public static CallTreeInfo create(AnalysisUniverse aUniverse, Map<AnalysisMethod
return new CallTreeInfo(runtimeCompilations);
}

private void initializeCallTraceInfo() {
if (callTraceInitialized) {
return;
}

callTraceInitialized = true;
private void initializeCallerInfo() {
analysisMethodMap = new HashMap<>();
runtimeCandidateMap = new HashMap<>();

Expand Down Expand Up @@ -131,22 +125,22 @@ private void initializeCallTraceInfo() {
}
}

public void initializeCallTreeInfo(Set<AnalysisMethod> registeredRoots) {
if (callTreeInitialized) {
public void initialize(Set<AnalysisMethod> registeredRoots) {
if (initialized) {
return;
}

initializeCallTraceInfo();
callTreeInitialized = true;
initializeCallerInfo();
initialized = true;

// ensure invokeInfo calculated

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

public static String[] getCallTrace(CallTreeInfo callTreeInfo, AnalysisMethod method) {
callTreeInfo.initializeCallTraceInfo();
static String[] getCallTrace(CallTreeInfo callTreeInfo, AnalysisMethod method, Set<AnalysisMethod> registeredRuntimeCompilations) {
callTreeInfo.initialize(registeredRuntimeCompilations);
MethodNode methodNode = callTreeInfo.analysisMethodMap.get(method);
if (methodNode == null) {
return UNKNOWN_TRACE;
Expand All @@ -201,8 +195,8 @@ public static String[] getCallTrace(CallTreeInfo callTreeInfo, AnalysisMethod me
return trace.toArray(EMPTY_STRING);
}

public static String[] getCallTrace(CallTreeInfo callTreeInfo, RuntimeCompilationCandidate candidate) {
callTreeInfo.initializeCallTraceInfo();
static String[] getCallTrace(CallTreeInfo callTreeInfo, RuntimeCompilationCandidate candidate, Set<AnalysisMethod> registeredRuntimeCompilations) {
callTreeInfo.initialize(registeredRuntimeCompilations);
InvokeNode invokeNode = callTreeInfo.runtimeCandidateMap.get(candidate);
if (invokeNode == null) {
return UNKNOWN_TRACE;
Expand All @@ -214,26 +208,48 @@ public static String[] getCallTrace(CallTreeInfo callTreeInfo, RuntimeCompilatio
}

private static void findCallTraceHelper(ArrayList<String> trace, MethodNode first) {
Set<MethodNode> covered = new HashSet<>();
MethodNode current = first;
covered.add(current);

while (current != null) {
// find parent
MethodNode parent = null;
for (InvokeNode caller : current.getCallers()) {
if (covered.add(caller.method)) {
if (first.trace != null) {
/*
* If there is a known trace from root, then we can return this
*/
MethodNode current = first;
while (current != null) {
MethodNode parent = null;
InvokeNode caller = current.trace.invokeParent;
if (caller != null) {
parent = caller.method;
trace.add(caller.position.toString());
break;
}
current = parent;
}
trace.add("[Root]");

} else {
/*
* Otherwise we will walk an arbitrary caller until there is not a caller or we
* encounter a cycle.
*/
Set<MethodNode> covered = new HashSet<>();
MethodNode current = first;
covered.add(current);

while (current != null) {
// find parent
MethodNode parent = null;
for (InvokeNode caller : current.getCallers()) {
if (covered.add(caller.method)) {
parent = caller.method;
trace.add(caller.position.toString());
break;
}
}
current = parent;
}
current = parent;
}
}

public static void printCallTree(CallTreeInfo info, Set<AnalysisMethod> registeredRuntimeCompilations) {
info.initializeCallTreeInfo(registeredRuntimeCompilations);
info.initialize(registeredRuntimeCompilations);

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

public static void printDeepestPath(CallTreeInfo info, Set<AnalysisMethod> registeredRuntimeCompilations) {
info.initializeCallTreeInfo(registeredRuntimeCompilations);
info.initialize(registeredRuntimeCompilations);

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,14 @@ public void initializeAnalysisProviders(BigBang bb, Function<ConstantFieldProvid
analysisProviders = customHostedProviders;
}

public String[] getCallTrace(CallTreeInfo callTreeInfo, AnalysisMethod method) {
return CallTreeInfo.getCallTrace(callTreeInfo, method, registeredRuntimeCompilations);
}

public String[] getCallTrace(CallTreeInfo callTreeInfo, RuntimeCompilationCandidate candidate) {
return CallTreeInfo.getCallTrace(callTreeInfo, candidate, registeredRuntimeCompilations);
}

public CallTreeInfo getCallTreeInfo() {
VMError.guarantee(callTreeMetadata != null);
return callTreeMetadata;
Expand Down Expand Up @@ -577,7 +585,7 @@ public void reportAnalysisError(AnalysisUniverse aUniverse, Throwable t) {
System.out.println("Parsing failed on a special method version: " + errorMethod.format("%H.%n"));
System.out.println("Method reachability trace");
if (failingRuntimeMethod != null) {
Arrays.stream(CallTreeInfo.getCallTrace(treeInfo, failingRuntimeMethod)).forEach(System.out::println);
Arrays.stream(CallTreeInfo.getCallTrace(treeInfo, failingRuntimeMethod, registeredRuntimeCompilations)).forEach(System.out::println);
} else {
System.out.println("trace unavailable");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -804,7 +804,7 @@ private void checkBlockList(CallTreeInfo treeInfo) {
tempTargetAllowlistMethods.contains(candidate.getTargetMethod()) &&
!isBlocklisted(candidate.getImplementationMethod());
if (!tempAllow) {
BlocklistViolationInfo violation = new BlocklistViolationInfo(candidate, CallTreeInfo.getCallTrace(treeInfo, candidate));
BlocklistViolationInfo violation = new BlocklistViolationInfo(candidate, runtimeCompilation.getCallTrace(treeInfo, candidate));
blocklistViolations.add(violation);
}
}
Expand Down Expand Up @@ -846,7 +846,7 @@ private void checkBlockList(CallTreeInfo treeInfo) {
for (RuntimeCompilationCandidate violation : warnViolations) {
System.out.println("Suspicious method: " + violation.getImplementationMethod().format("%H.%n(%p)"));
System.out.println("trace:");
for (String item : CallTreeInfo.getCallTrace(treeInfo, violation)) {
for (String item : runtimeCompilation.getCallTrace(treeInfo, violation)) {
System.out.println(" " + item);
}
}
Expand All @@ -857,7 +857,7 @@ private void checkBlockList(CallTreeInfo treeInfo) {
for (Pair<ResolvedJavaMethod, String> violation : neverPartOfCompilationViolations) {
System.out.println("called from");
System.out.println("(inlined call path): " + violation.getRight());
for (String item : CallTreeInfo.getCallTrace(treeInfo, (AnalysisMethod) violation.getLeft())) {
for (String item : runtimeCompilation.getCallTrace(treeInfo, (AnalysisMethod) violation.getLeft())) {
System.out.println(" " + item);
}
}
Expand Down

0 comments on commit 25a40ea

Please sign in to comment.