diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/CallTreeInfo.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/CallTreeInfo.java index 0ed531bea9bb..9a84a0c8a8ef 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/CallTreeInfo.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/CallTreeInfo.java @@ -53,8 +53,7 @@ public final class CallTreeInfo { private final Map runtimeCompilations; private Map runtimeCandidateMap; private Map analysisMethodMap; - private boolean callTreeInitialized = false; - private boolean callTraceInitialized = false; + private boolean initialized = false; private CallTreeInfo(Map runtimeCompilations) { this.runtimeCompilations = runtimeCompilations; @@ -82,12 +81,7 @@ public static CallTreeInfo create(AnalysisUniverse aUniverse, Map(); runtimeCandidateMap = new HashMap<>(); @@ -131,22 +125,22 @@ private void initializeCallTraceInfo() { } } - public void initializeCallTreeInfo(Set registeredRoots) { - if (callTreeInitialized) { + public void initialize(Set registeredRoots) { + if (initialized) { return; } - initializeCallTraceInfo(); - callTreeInitialized = true; + initializeCallerInfo(); + initialized = true; // ensure invokeInfo calculated Queue 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); } @@ -189,8 +183,8 @@ public void initializeCallTreeInfo(Set 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 registeredRuntimeCompilations) { + callTreeInfo.initialize(registeredRuntimeCompilations); MethodNode methodNode = callTreeInfo.analysisMethodMap.get(method); if (methodNode == null) { return UNKNOWN_TRACE; @@ -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 registeredRuntimeCompilations) { + callTreeInfo.initialize(registeredRuntimeCompilations); InvokeNode invokeNode = callTreeInfo.runtimeCandidateMap.get(candidate); if (invokeNode == null) { return UNKNOWN_TRACE; @@ -214,26 +208,48 @@ public static String[] getCallTrace(CallTreeInfo callTreeInfo, RuntimeCompilatio } private static void findCallTraceHelper(ArrayList trace, MethodNode first) { - Set 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 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 registeredRuntimeCompilations) { - info.initializeCallTreeInfo(registeredRuntimeCompilations); + info.initialize(registeredRuntimeCompilations); System.out.println("depth;method;invoke position"); for (MethodNode methodNode : info.analysisMethodMap.values()) { @@ -255,7 +271,7 @@ private static void printCallTreeNode(MethodNode node) { } public static void printDeepestPath(CallTreeInfo info, Set registeredRuntimeCompilations) { - info.initializeCallTreeInfo(registeredRuntimeCompilations); + info.initialize(registeredRuntimeCompilations); Optional deepestNode = info.analysisMethodMap.values().stream().max(Comparator.comparingInt(t -> t.trace == null ? -1 : t.trace.level)); diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompilationFeature.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompilationFeature.java index 2ed14e40d39d..e110574e9b3b 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompilationFeature.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompilationFeature.java @@ -300,6 +300,14 @@ public void initializeAnalysisProviders(BigBang bb, Function 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); } }