|
54 | 54 |
|
55 | 55 | public final class CallTreePrinter {
|
56 | 56 |
|
57 |
| - public static void print(BigBang bigbang, String path, String reportName) { |
| 57 | + private static Set<String> printMethods = new HashSet<>(); |
| 58 | + private static Set<Integer> printedID = new HashSet<>(); |
| 59 | + private static boolean printAll = false; |
| 60 | + |
| 61 | + public static void print(BigBang bigbang, String printCallTreeMethods, String path, String reportName) { |
58 | 62 | CallTreePrinter printer = new CallTreePrinter(bigbang);
|
59 | 63 | printer.buildCallTree();
|
60 |
| - |
| 64 | + Arrays.stream(printCallTreeMethods.split(",")).forEach(printMethods::add); |
| 65 | + if (printCallTreeMethods.length() == 0) { |
| 66 | + printAll = true; |
| 67 | + } |
61 | 68 | ReportUtils.report("call tree", path + File.separatorChar + "reports", "call_tree_" + reportName, "txt",
|
62 | 69 | writer -> printer.printMethods(writer));
|
63 | 70 | ReportUtils.report("list of used methods", path + File.separatorChar + "reports", "used_methods_" + reportName, "txt",
|
@@ -222,40 +229,58 @@ private void printMethods(PrintWriter out) {
|
222 | 229 | while (iterator.hasNext()) {
|
223 | 230 | MethodNode node = iterator.next();
|
224 | 231 | boolean lastEntryPoint = !iterator.hasNext();
|
225 |
| - out.format("%s%s %s %n", lastEntryPoint ? LAST_CHILD : CHILD, "entry", node.format()); |
226 |
| - printCallTreeNode(out, lastEntryPoint ? EMPTY_INDENT : CONNECTING_INDENT, node); |
| 232 | + printCallTreeNode(out, lastEntryPoint ? EMPTY_INDENT : CONNECTING_INDENT, node, false, lastEntryPoint ? LAST_CHILD : CHILD); |
227 | 233 | }
|
228 | 234 | out.println();
|
229 | 235 | }
|
230 | 236 |
|
231 |
| - private static void printCallTreeNode(PrintWriter out, String prefix, MethodNode node) { |
| 237 | + private static void printCallTreeNode(PrintWriter out, String prefix, MethodNode node, boolean shouldPrint, String beginning) { |
| 238 | + boolean print = shouldPrint; |
| 239 | + if (!shouldPrint) { |
| 240 | + String methodName = node.method.getQualifiedName(); |
| 241 | + if (printAll || printMethods.remove(methodName)) { |
| 242 | + print = true; |
| 243 | + out.format("%s%s %s %n", beginning, "entry", node.format()); |
| 244 | + } |
| 245 | + } |
232 | 246 |
|
233 | 247 | for (int invokeIdx = 0; invokeIdx < node.invokes.size(); invokeIdx++) {
|
234 | 248 | InvokeNode invoke = node.invokes.get(invokeIdx);
|
235 | 249 | boolean lastInvoke = invokeIdx == node.invokes.size() - 1;
|
236 | 250 | if (invoke.isDirectInvoke) {
|
237 | 251 | if (invoke.callees.size() > 0) {
|
238 | 252 | Node calleeNode = invoke.callees.get(0);
|
239 |
| - out.format("%s%s%s %s @bci=%s %n", prefix, (lastInvoke ? LAST_CHILD : CHILD), |
240 |
| - "directly calls", calleeNode.format(), invoke.formatLocation()); |
241 |
| - if (calleeNode instanceof MethodNode) { |
242 |
| - printCallTreeNode(out, prefix + (lastInvoke ? EMPTY_INDENT : CONNECTING_INDENT), (MethodNode) calleeNode); |
| 253 | + boolean isNative = invoke.targetMethod.wrapped.getClass().getName().equals("com.oracle.svm.jni.hosted.JNINativeCallWrapperMethod"); |
| 254 | + if (print) { |
| 255 | + if (calleeNode instanceof MethodNodeReference && printedID.add(((MethodNodeReference) calleeNode).methodNode.id)) { |
| 256 | + calleeNode = ((MethodNodeReference) calleeNode).methodNode; |
| 257 | + } |
| 258 | + out.format("%s%s%s %s @bci=%s %s %n", prefix, (lastInvoke ? LAST_CHILD : CHILD), |
| 259 | + "directly calls", calleeNode.format(), invoke.formatLocation(), isNative ? "(Native Method)" : ""); |
| 260 | + } |
| 261 | + if (!isNative && calleeNode instanceof MethodNode) { |
| 262 | + printCallTreeNode(out, prefix + (lastInvoke ? EMPTY_INDENT : CONNECTING_INDENT), (MethodNode) calleeNode, print, null); |
243 | 263 | }
|
244 | 264 | }
|
245 | 265 | } else {
|
246 |
| - out.format("%s%s%s %s @bci=%s%n", prefix, (lastInvoke ? LAST_CHILD : CHILD), |
247 |
| - "virtually calls", invoke.formatTarget(), invoke.formatLocation()); |
| 266 | + if (print) { |
| 267 | + out.format("%s%s%s %s @bci=%s%n", prefix, (lastInvoke ? LAST_CHILD : CHILD), |
| 268 | + "virtually calls", invoke.formatTarget(), invoke.formatLocation()); |
| 269 | + } |
248 | 270 | for (int calleeIdx = 0; calleeIdx < invoke.callees.size(); calleeIdx++) {
|
249 | 271 | boolean lastCallee = calleeIdx == invoke.callees.size() - 1;
|
250 | 272 | Node calleeNode = invoke.callees.get(calleeIdx);
|
251 |
| - out.format("%s%s%s %s %n", prefix + (lastInvoke ? EMPTY_INDENT : CONNECTING_INDENT), (lastCallee ? LAST_CHILD : CHILD), |
252 |
| - "is overridden by", calleeNode.format()); |
| 273 | + if (print) { |
| 274 | + out.format("%s%s%s %s %n", prefix + (lastInvoke ? EMPTY_INDENT : CONNECTING_INDENT), (lastCallee ? LAST_CHILD : CHILD), |
| 275 | + "is overridden by", calleeNode.format()); |
| 276 | + } |
253 | 277 | if (calleeNode instanceof MethodNode) {
|
254 |
| - printCallTreeNode(out, prefix + (lastInvoke ? EMPTY_INDENT : CONNECTING_INDENT) + (lastCallee ? EMPTY_INDENT : CONNECTING_INDENT), (MethodNode) calleeNode); |
| 278 | + printCallTreeNode(out, prefix + (lastInvoke ? EMPTY_INDENT : CONNECTING_INDENT) + (lastCallee ? EMPTY_INDENT : CONNECTING_INDENT), (MethodNode) calleeNode, print, null); |
255 | 279 | }
|
256 | 280 | }
|
257 | 281 | }
|
258 | 282 | }
|
| 283 | + |
259 | 284 | }
|
260 | 285 |
|
261 | 286 | private void printUsedMethods(PrintWriter out) {
|
|
0 commit comments