|
67 | 67 | import jdk.vm.ci.meta.ResolvedJavaType;
|
68 | 68 |
|
69 | 69 | public final class CallTreePrinter {
|
| 70 | + private static Set<String> printMethods = new HashSet<>(); |
| 71 | + private static Set<Integer> printedID = new HashSet<>(); |
| 72 | + private static boolean printAll = false; |
70 | 73 |
|
71 | 74 | public static final Pattern CAMEL_CASE_PATTERN = Pattern.compile(
|
72 | 75 | "\\b[a-zA-Z]|[A-Z]|\\.");
|
73 | 76 |
|
74 |
| - public static void print(BigBang bb, String reportsPath, String reportName) { |
| 77 | + public static void print(BigBang bb, String printCallTreeMethods, String reportsPath, String reportName) { |
75 | 78 | CallTreePrinter printer = new CallTreePrinter(bb);
|
76 | 79 | printer.buildCallTree();
|
77 |
| - |
| 80 | + Arrays.stream(printCallTreeMethods.split(",")).forEach(printMethods::add); |
| 81 | + if (printCallTreeMethods.length() == 0) { |
| 82 | + printAll = true; |
| 83 | + } |
78 | 84 | ReportUtils.report("call tree", reportsPath, "call_tree_" + reportName, "txt",
|
79 | 85 | printer::printMethods);
|
80 | 86 | ReportUtils.report("list of used methods", reportsPath, "used_methods_" + reportName, "txt",
|
@@ -241,42 +247,65 @@ private void printMethods(PrintWriter out) {
|
241 | 247 | while (iterator.hasNext()) {
|
242 | 248 | MethodNode node = iterator.next();
|
243 | 249 | boolean lastEntryPoint = !iterator.hasNext();
|
244 |
| - out.format("%s%s %s %n", lastEntryPoint ? LAST_CHILD : CHILD, "entry", node.format()); |
245 |
| - printCallTreeNode(out, lastEntryPoint ? EMPTY_INDENT : CONNECTING_INDENT, node); |
| 250 | + printCallTreeNode(out, lastEntryPoint ? EMPTY_INDENT : CONNECTING_INDENT, node, false, lastEntryPoint ? LAST_CHILD : CHILD); |
246 | 251 | }
|
247 | 252 | out.println();
|
248 | 253 | }
|
249 | 254 |
|
250 |
| - private static void printCallTreeNode(PrintWriter out, String prefix, MethodNode node) { |
| 255 | + private static void printCallTreeNode(PrintWriter out, String prefix, MethodNode node, boolean shouldPrint, String beginning) { |
| 256 | + boolean print = shouldPrint; |
| 257 | + if (!shouldPrint) { |
| 258 | + String methodName = node.method.getQualifiedName(); |
| 259 | + if (printAll || printMethods.remove(methodName)) { |
| 260 | + print = true; |
| 261 | + out.format("%s%s %s %n", beginning, printAll ? "entry" : "filtered start", node.format()); |
| 262 | + } |
| 263 | + } |
251 | 264 |
|
252 | 265 | for (int invokeIdx = 0; invokeIdx < node.invokes.size(); invokeIdx++) {
|
253 | 266 | InvokeNode invoke = node.invokes.get(invokeIdx);
|
254 | 267 | boolean lastInvoke = invokeIdx == node.invokes.size() - 1;
|
255 | 268 | if (invoke.isDirectInvoke) {
|
256 | 269 | if (invoke.callees.size() > 0) {
|
257 | 270 | Node calleeNode = invoke.callees.get(0);
|
258 |
| - out.format("%s%s%s %s @bci=%s %n", prefix, (lastInvoke ? LAST_CHILD : CHILD), |
259 |
| - "directly calls", calleeNode.format(), invoke.formatLocation()); |
260 |
| - if (calleeNode instanceof MethodNode) { |
261 |
| - printCallTreeNode(out, prefix + (lastInvoke ? EMPTY_INDENT : CONNECTING_INDENT), (MethodNode) calleeNode); |
| 271 | + boolean isNative = invoke.targetMethod.wrapped.getClass().getName().equals("com.oracle.svm.jni.hosted.JNINativeCallWrapperMethod"); |
| 272 | + if (print) { |
| 273 | + calleeNode = extendNodeReference(calleeNode); |
| 274 | + out.format("%s%s%s %s @bci=%s %s %n", prefix, (lastInvoke ? LAST_CHILD : CHILD), |
| 275 | + "directly calls", calleeNode.format(), invoke.formatLocation(), isNative ? "(Native Method)" : ""); |
| 276 | + } |
| 277 | + if (!isNative && calleeNode instanceof MethodNode) { |
| 278 | + printCallTreeNode(out, prefix + (lastInvoke ? EMPTY_INDENT : CONNECTING_INDENT), (MethodNode) calleeNode, print, beginning); |
262 | 279 | }
|
263 | 280 | }
|
264 | 281 | } else {
|
265 |
| - out.format("%s%s%s %s @bci=%s%n", prefix, (lastInvoke ? LAST_CHILD : CHILD), |
266 |
| - "virtually calls", invoke.formatTarget(), invoke.formatLocation()); |
| 282 | + if (print) { |
| 283 | + out.format("%s%s%s %s @bci=%s%n", prefix, (lastInvoke ? LAST_CHILD : CHILD), |
| 284 | + "virtually calls", invoke.formatTarget(), invoke.formatLocation()); |
| 285 | + } |
267 | 286 | for (int calleeIdx = 0; calleeIdx < invoke.callees.size(); calleeIdx++) {
|
268 | 287 | boolean lastCallee = calleeIdx == invoke.callees.size() - 1;
|
269 | 288 | Node calleeNode = invoke.callees.get(calleeIdx);
|
270 |
| - out.format("%s%s%s %s %n", prefix + (lastInvoke ? EMPTY_INDENT : CONNECTING_INDENT), (lastCallee ? LAST_CHILD : CHILD), |
271 |
| - "is overridden by", calleeNode.format()); |
| 289 | + if (print) { |
| 290 | + calleeNode = extendNodeReference(calleeNode); |
| 291 | + out.format("%s%s%s %s %n", prefix + (lastInvoke ? EMPTY_INDENT : CONNECTING_INDENT), (lastCallee ? LAST_CHILD : CHILD), |
| 292 | + "is overridden by", calleeNode.format()); |
| 293 | + } |
272 | 294 | if (calleeNode instanceof MethodNode) {
|
273 |
| - printCallTreeNode(out, prefix + (lastInvoke ? EMPTY_INDENT : CONNECTING_INDENT) + (lastCallee ? EMPTY_INDENT : CONNECTING_INDENT), (MethodNode) calleeNode); |
| 295 | + printCallTreeNode(out, prefix + (lastInvoke ? EMPTY_INDENT : CONNECTING_INDENT) + (lastCallee ? EMPTY_INDENT : CONNECTING_INDENT), (MethodNode) calleeNode, print, beginning); |
274 | 296 | }
|
275 | 297 | }
|
276 | 298 | }
|
277 | 299 | }
|
278 | 300 | }
|
279 | 301 |
|
| 302 | + private static Node extendNodeReference(Node calleeNode) { |
| 303 | + if (calleeNode instanceof MethodNodeReference && printedID.add(((MethodNodeReference) calleeNode).methodNode.id)) { |
| 304 | + return ((MethodNodeReference) calleeNode).methodNode; |
| 305 | + } |
| 306 | + return calleeNode; |
| 307 | + } |
| 308 | + |
280 | 309 | private void printUsedMethods(PrintWriter out) {
|
281 | 310 | List<String> methodsList = new ArrayList<>();
|
282 | 311 | for (ResolvedJavaMethod method : methodToNode.keySet()) {
|
|
0 commit comments