# HG changeset patch # User Christian Humer # Date 1385834995 -3600 # Node ID 401e1473c54675ca687147f27c24c0c6d3472545 # Parent 8b14bab157575f8bec079629fba07add74c96909 Truffle: Implemented basic tracing of truffle compiler tree expansion (-G:+TraceTruffleExpansion, -G:+TraceTruffleExpansionSource) diff -r 8b14bab15757 -r 401e1473c546 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- 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 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 arguments, final Assumptions assumptions, final PhaseContext phaseContext) { diff -r 8b14bab15757 -r 401e1473c546 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java --- 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 TraceTruffleCompilationDetails = new OptionValue<>(false); @Option(help = "") + public static final OptionValue TraceTruffleExpansion = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue TraceTruffleExpansionSource = new OptionValue<>(false); + @Option(help = "") public static final OptionValue TraceTruffleCacheDetails = new OptionValue<>(false); @Option(help = "") public static final OptionValue TraceTruffleCompilationExceptions = new OptionValue<>(true); diff -r 8b14bab15757 -r 401e1473c546 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java --- /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 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 states) { + Iterable> entries; + if (states instanceof NodeMap) { + entries = ((NodeMap) states).entries(); + } else { + entries = states.entrySet(); + } + + for (Entry 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 { + + private final ExpansionTree parent; + private final Object targetReceiver; + private final ResolvedJavaMethod targetMethod; + private final int parentBci; + private final List 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()); + } + } + } + +}