changeset 13203:401e1473c546

Truffle: Implemented basic tracing of truffle compiler tree expansion (-G:+TraceTruffleExpansion, -G:+TraceTruffleExpansionSource)
author Christian Humer <christian.humer@gmail.com>
date Sat, 30 Nov 2013 19:09:55 +0100
parents 8b14bab15757
children bef512e42262 2b9fcffd6f36
files graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java
diffstat 3 files changed, 198 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Sat Nov 30 19:05:44 2013 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Sat Nov 30 19:09:55 2013 +0100
@@ -81,7 +81,6 @@
         this.skippedExceptionTypes = TruffleCompilerImpl.getSkippedExceptionTypes(providers.getMetaAccess());
         this.cache = runtime.getGraphCache();
         this.truffleCache = truffleCache;
-
         try {
             executeHelperMethod = providers.getMetaAccess().lookupJavaMethod(OptimizedCallTarget.class.getDeclaredMethod("executeHelper", PackedFrame.class, Arguments.class));
         } catch (NoSuchMethodException ex) {
@@ -182,6 +181,10 @@
 
     private void expandTree(StructuredGraph graph, Assumptions assumptions) {
         PhaseContext phaseContext = new PhaseContext(providers, assumptions);
+        TruffleExpansionLogger expansionLogger = null;
+        if (TraceTruffleExpansion.getValue()) {
+            expansionLogger = new TruffleExpansionLogger(graph);
+        }
         boolean changed;
         do {
             changed = false;
@@ -212,7 +215,13 @@
                     if (inlineGraph != null) {
                         int nodeCountBefore = graph.getNodeCount();
                         Mark mark = graph.getMark();
-                        InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, false);
+                        if (TraceTruffleExpansion.getValue()) {
+                            expansionLogger.preExpand(methodCallTargetNode, inlineGraph);
+                        }
+                        Map<Node, Node> inlined = InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, false);
+                        if (TraceTruffleExpansion.getValue()) {
+                            expansionLogger.postExpand(inlined);
+                        }
                         if (Debug.isDumpEnabled()) {
                             int nodeCountAfter = graph.getNodeCount();
                             Debug.dump(graph, "After inlining %s %+d (%d)", methodCallTargetNode.targetMethod().toString(), nodeCountAfter - nodeCountBefore, nodeCountAfter);
@@ -231,6 +240,10 @@
                 }
             }
         } while (changed);
+
+        if (TraceTruffleExpansion.getValue()) {
+            expansionLogger.print();
+        }
     }
 
     private StructuredGraph parseGraph(final ResolvedJavaMethod targetMethod, final NodeInputList<ValueNode> arguments, final Assumptions assumptions, final PhaseContext phaseContext) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Sat Nov 30 19:05:44 2013 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Sat Nov 30 19:09:55 2013 +0100
@@ -82,6 +82,10 @@
     @Option(help = "")
     public static final OptionValue<Boolean> TraceTruffleCompilationDetails = new OptionValue<>(false);
     @Option(help = "")
+    public static final OptionValue<Boolean> TraceTruffleExpansion = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> TraceTruffleExpansionSource = new OptionValue<>(false);
+    @Option(help = "")
     public static final OptionValue<Boolean> TraceTruffleCacheDetails = new OptionValue<>(false);
     @Option(help = "")
     public static final OptionValue<Boolean> TraceTruffleCompilationExceptions = new OptionValue<>(true);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java	Sat Nov 30 19:09:55 2013 +0100
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.Map.Entry;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+
+public class TruffleExpansionLogger {
+
+    private final ExpansionTree root;
+    private final Map<MethodCallTargetNode, ExpansionTree> callToParentTree = new HashMap<>();
+
+    public TruffleExpansionLogger(StructuredGraph graph) {
+        root = new ExpansionTree(null, null, graph.method(), -1);
+        registerParentInCalls(root, graph);
+    }
+
+    public void preExpand(MethodCallTargetNode callTarget, StructuredGraph inliningGraph) {
+        ResolvedJavaMethod sourceMethod = callTarget.invoke().getState().method();
+
+        int sourceMethodBci = callTarget.invoke().bci();
+        ResolvedJavaMethod targetMethod = callTarget.targetMethod();
+        Object targetReceiver = null;
+        if (!Modifier.isStatic(sourceMethod.getModifiers())) {
+            targetReceiver = callTarget.arguments().first().asConstant().asObject();
+        }
+
+        ExpansionTree parent = callToParentTree.get(callTarget);
+        assert parent != null;
+        callToParentTree.remove(callTarget);
+        ExpansionTree tree = new ExpansionTree(parent, targetReceiver, targetMethod, sourceMethodBci);
+        registerParentInCalls(tree, inliningGraph);
+    }
+
+    @SuppressWarnings("unchecked")
+    public void postExpand(Map<Node, Node> states) {
+        Iterable<Entry<Node, Node>> entries;
+        if (states instanceof NodeMap) {
+            entries = ((NodeMap<Node>) states).entries();
+        } else {
+            entries = states.entrySet();
+        }
+
+        for (Entry<Node, Node> entry : entries) {
+            Node key = entry.getKey();
+            Node value = entry.getValue();
+
+            if (value instanceof MethodCallTargetNode && callToParentTree.containsKey(key)) {
+                callToParentTree.put((MethodCallTargetNode) value, callToParentTree.get(key));
+                callToParentTree.remove(key);
+            }
+        }
+    }
+
+    private void registerParentInCalls(ExpansionTree parentTree, StructuredGraph graph) {
+        for (MethodCallTargetNode target : graph.getNodes(MethodCallTargetNode.class)) {
+            callToParentTree.put(target, parentTree);
+        }
+    }
+
+    public void print() {
+        root.print(System.out);
+    }
+
+    private static final class ExpansionTree implements Comparable<ExpansionTree> {
+
+        private final ExpansionTree parent;
+        private final Object targetReceiver;
+        private final ResolvedJavaMethod targetMethod;
+        private final int parentBci;
+        private final List<ExpansionTree> children = new ArrayList<>();
+
+        public ExpansionTree(ExpansionTree parent, Object receiver, ResolvedJavaMethod targetMethod, int parentBci) {
+            this.parent = parent;
+            this.targetReceiver = receiver;
+            this.targetMethod = targetMethod;
+            this.parentBci = parentBci;
+            if (parent != null) {
+                parent.children.add(this);
+            }
+        }
+
+        public int compareTo(ExpansionTree o) {
+            if (parent == o.parent) {
+                return parentBci - o.parentBci;
+            }
+            return 0;
+        }
+
+        public void print(PrintStream p) {
+            print(p, "");
+        }
+
+        private void print(PrintStream p, String indent) {
+            StackTraceElement targetElement = targetMethod.asStackTraceElement(0);
+            StackTraceElement sourceElement = null;
+
+            ExpansionTree currentParent = this.parent;
+            if (currentParent != null) {
+                sourceElement = currentParent.targetMethod.asStackTraceElement(parentBci);
+            }
+
+            String className = targetElement.getClassName();
+            int lastIndex = className.lastIndexOf('.');
+            if (lastIndex != -1) {
+                className = className.substring(lastIndex + 1, className.length());
+            }
+
+            lastIndex = className.lastIndexOf('$');
+            if (lastIndex != -1) {
+                className = className.substring(lastIndex + 1, className.length());
+            }
+
+            String constantType = "";
+            if (targetReceiver != null) {
+                if (!targetReceiver.getClass().getSimpleName().equals(className)) {
+                    constantType = "<" + targetReceiver.getClass().getSimpleName() + ">";
+                }
+            }
+
+            String sourceSource = "";
+            String targetSource = "";
+            if (TruffleCompilerOptions.TraceTruffleExpansionSource.getValue()) {
+                sourceSource = formatSource(sourceElement);
+                targetSource = formatSource(targetElement);
+            }
+            p.printf("%s%s %s%s.%s%s%n", indent, sourceSource, className, constantType, targetMethod.getName(), targetSource);
+
+            Collections.sort(children);
+
+            for (ExpansionTree child : children) {
+                child.print(p, indent + "  ");
+            }
+        }
+
+        private static String formatSource(StackTraceElement e) {
+            if (e == null) {
+                return "";
+            }
+            if (e.getFileName() != null) {
+                if (e.getLineNumber() >= 0) {
+                    return String.format("(%s:%d)", e.getFileName(), e.getLineNumber());
+                } else {
+                    return String.format("(%s)", e.getFileName(), e.getLineNumber());
+                }
+            } else {
+                return String.format("(Unknown Source)", e.getFileName(), e.getLineNumber());
+            }
+        }
+    }
+
+}