changeset 10757:f4f46b734a4c

Merge
author Andreas Woess <andreas.woess@jku.at>
date Mon, 15 Jul 2013 15:29:01 +0200
parents 9f5a4074e36b (current diff) 7f6580db1e88 (diff)
children e82c28e94f08
files
diffstat 6 files changed, 127 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Mon Jul 15 13:36:59 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Mon Jul 15 15:29:01 2013 +0200
@@ -65,8 +65,7 @@
         if (truffleCompiler == null) {
             truffleCompiler = new TruffleCompilerImpl();
         }
-        return new OptimizedCallTarget(rootNode, frameDescriptor, truffleCompiler, TruffleCompilationThreshold.getValue(), TruffleInliningReprofileCount.getValue(),
-                        TruffleInvalidationReprofileCount.getValue());
+        return new OptimizedCallTarget(rootNode, frameDescriptor, truffleCompiler, TruffleCompilationThreshold.getValue());
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Mon Jul 15 13:36:59 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Mon Jul 15 15:29:01 2013 +0200
@@ -40,19 +40,19 @@
 public final class OptimizedCallTarget extends DefaultCallTarget implements LoopCountReceiver, FrameFactory {
 
     private static final PrintStream OUT = TTY.out().out();
+    private static final int MIN_INVOKES_AFTER_INLINING = 2;
 
-    private final int inliningReprofileCount;
-    private final int invalidationReprofileCount;
-
-    protected OptimizedCallTarget(RootNode rootNode, FrameDescriptor descriptor, TruffleCompiler compiler, int compilationThreshold, int inliningReprofileCount, int invalidationReprofileCount) {
+    protected OptimizedCallTarget(RootNode rootNode, FrameDescriptor descriptor, TruffleCompiler compiler, int compilationThreshold) {
         super(rootNode, descriptor);
         this.compiler = compiler;
         this.invokeCounter = compilationThreshold >> 7;
         this.loopAndInvokeCounter = compilationThreshold;
         this.originalInvokeCounter = compilationThreshold;
         this.rootNode.setCallTarget(this);
-        this.inliningReprofileCount = inliningReprofileCount;
-        this.invalidationReprofileCount = invalidationReprofileCount;
+
+        if (TruffleProfiling.getValue()) {
+            registerCallTarget(this);
+        }
     }
 
     private InstalledCode compiledMethod;
@@ -62,6 +62,11 @@
     private int loopAndInvokeCounter;
     private boolean disableCompilation;
 
+    // TruffleProfiling
+    private int callCount;
+    private int inlinedCallSiteCount;
+
+    // TraceTruffleCompilation
     long timeCompilationStarted;
     long timePartialEvaluationFinished;
     long timeCompilationFinished;
@@ -71,6 +76,9 @@
 
     @Override
     public Object call(PackedFrame caller, Arguments args) {
+        if (TruffleProfiling.getValue()) {
+            callCount++;
+        }
         if (CompilerDirectives.injectBranchProbability(CompilerDirectives.FASTPATH_PROBABILITY, compiledMethod != null)) {
             try {
                 return compiledMethod.execute(this, caller, args);
@@ -82,8 +90,9 @@
         }
     }
 
-    protected Object compiledCodeInvalidated(PackedFrame caller, Arguments args) {
+    private Object compiledCodeInvalidated(PackedFrame caller, Arguments args) {
         compiledMethod = null;
+        int invalidationReprofileCount = TruffleInvalidationReprofileCount.getValue();
         invokeCounter = invalidationReprofileCount;
         if (TruffleFunctionInlining.getValue()) {
             originalInvokeCounter += invalidationReprofileCount;
@@ -101,7 +110,8 @@
             return executeHelper(caller, args);
         } else {
             if (TruffleFunctionInlining.getValue() && inline()) {
-                invokeCounter = 2;
+                invokeCounter = MIN_INVOKES_AFTER_INLINING;
+                int inliningReprofileCount = TruffleInliningReprofileCount.getValue();
                 loopAndInvokeCounter = inliningReprofileCount;
                 originalInvokeCounter = inliningReprofileCount;
             } else {
@@ -112,10 +122,12 @@
     }
 
     public boolean inline() {
+        CompilerAsserts.neverPartOfCompilation();
         return new InliningHelper(this).inline();
     }
 
     public void compile() {
+        CompilerAsserts.neverPartOfCompilation();
         try {
             compiledMethod = compiler.compile(this);
             if (compiledMethod == null) {
@@ -127,6 +139,9 @@
                                     (timeCompilationFinished - timeCompilationStarted) / 1e6, (timePartialEvaluationFinished - timeCompilationStarted) / 1e6,
                                     (timeCompilationFinished - timePartialEvaluationFinished) / 1e6, nodeCountPartialEval, nodeCountLowered, codeSize);
                 }
+                if (TruffleProfiling.getValue()) {
+                    resetProfiling();
+                }
             }
         } catch (Throwable e) {
             disableCompilation = true;
@@ -202,10 +217,14 @@
 
             boolean inlined = false;
             for (InlinableCallSiteInfo inlinableCallSite : inlinableCallSites) {
-                if (policy.isWorthInlining(inlinableCallSite) && inlinableCallSite.getCallSite().inline(target)) {
+                if (!policy.isWorthInlining(inlinableCallSite)) {
+                    break;
+                }
+                if (inlinableCallSite.getCallSite().inline(target)) {
                     if (TraceTruffleInlining.getValue()) {
                         printCallSiteInfo(policy, inlinableCallSite, "inlined");
                     }
+                    target.inlinedCallSiteCount++;
                     inlined = true;
                     break;
                 }
@@ -267,7 +286,11 @@
 
                     @Override
                     public int compare(InlinableCallSiteInfo cs1, InlinableCallSiteInfo cs2) {
-                        return Double.compare(metric(cs2), metric(cs1));
+                        int result = (isWorthInlining(cs2) ? 1 : 0) - (isWorthInlining(cs1) ? 1 : 0);
+                        if (result == 0) {
+                            return Double.compare(metric(cs2), metric(cs1));
+                        }
+                        return result;
                     }
                 });
             }
@@ -313,4 +336,65 @@
             return inlinableCallSites;
         }
     }
+
+    private static void resetProfiling() {
+        for (OptimizedCallTarget callTarget : OptimizedCallTarget.callTargets.keySet()) {
+            callTarget.callCount = 0;
+        }
+    }
+
+    private static void printProfiling() {
+        List<OptimizedCallTarget> sortedCallTargets = new ArrayList<>(OptimizedCallTarget.callTargets.keySet());
+        Collections.sort(sortedCallTargets, new Comparator<OptimizedCallTarget>() {
+
+            @Override
+            public int compare(OptimizedCallTarget o1, OptimizedCallTarget o2) {
+                return o2.callCount - o1.callCount;
+            }
+        });
+
+        int totalCallCount = 0;
+        int totalInlinedCallSiteCount = 0;
+        int totalNotInlinedCallSiteCount = 0;
+        int totalNodeCount = 0;
+
+        PrintStream out = TTY.out().out();
+        out.println();
+        out.printf("%-50s | %-10s | %s / %s | %s\n", "Call Target", "Call Count", "Calls Sites Inlined", "Not Inlined", "Node Count");
+        for (OptimizedCallTarget callTarget : sortedCallTargets) {
+            if (callTarget.callCount == 0) {
+                continue;
+            }
+
+            int notInlinedCallSiteCount = InliningHelper.getInlinableCallSites(callTarget).size();
+            int nodeCount = NodeUtil.countNodes(callTarget.rootNode);
+            String comment = callTarget.compiledMethod == null ? " int" : "";
+            out.printf("%-50s | %10s | %15s | %15s | %10s%s\n", callTarget.getRootNode(), callTarget.callCount, callTarget.inlinedCallSiteCount, notInlinedCallSiteCount, nodeCount, comment);
+
+            totalCallCount += callTarget.callCount;
+            totalInlinedCallSiteCount += callTarget.inlinedCallSiteCount;
+            totalNotInlinedCallSiteCount += notInlinedCallSiteCount;
+            totalNodeCount += nodeCount;
+        }
+        out.printf("%-50s | %10s | %15s | %15s | %10s\n", "Total", totalCallCount, totalInlinedCallSiteCount, totalNotInlinedCallSiteCount, totalNodeCount);
+    }
+
+    private static void registerCallTarget(OptimizedCallTarget callTarget) {
+        callTargets.put(callTarget, 0);
+    }
+
+    private static Map<OptimizedCallTarget, Integer> callTargets;
+    static {
+        if (TruffleProfiling.getValue()) {
+            callTargets = new WeakHashMap<>();
+
+            Runtime.getRuntime().addShutdownHook(new Thread() {
+
+                @Override
+                public void run() {
+                    printProfiling();
+                }
+            });
+        }
+    }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Mon Jul 15 13:36:59 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Mon Jul 15 15:29:01 2013 +0200
@@ -64,7 +64,7 @@
     private final HotSpotGraalRuntime graalRuntime;
     private final TruffleCache truffleCache;
 
-    private static final Class[] SKIPPED_EXCEPTION_CLASSES = new Class[]{SlowPathException.class, UnexpectedResultException.class, ArithmeticException.class};
+    private static final Class[] SKIPPED_EXCEPTION_CLASSES = new Class[]{SlowPathException.class, UnexpectedResultException.class, ArithmeticException.class, InvalidInstalledCodeException.class};
 
     public static final OptimisticOptimizations Optimizations = OptimisticOptimizations.ALL.remove(OptimisticOptimizations.Optimization.UseExceptionProbability,
                     OptimisticOptimizations.Optimization.RemoveNeverExecutedCode, OptimisticOptimizations.Optimization.UseTypeCheckedInlining, OptimisticOptimizations.Optimization.UseTypeCheckHints);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Mon Jul 15 13:36:59 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Mon Jul 15 15:29:01 2013 +0200
@@ -81,5 +81,7 @@
     public static final OptionValue<Boolean> TraceTruffleInlining = new OptionValue<>(true);
     @Option(help = "")
     public static final OptionValue<Boolean> TraceTruffleInliningDetails = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> TruffleProfiling = new StableOptionValue<>(false);
     // @formatter:on
 }
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java	Mon Jul 15 13:36:59 2013 +0200
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java	Mon Jul 15 15:29:01 2013 +0200
@@ -81,7 +81,7 @@
 
     class TestRootNode extends RootNode {
 
-        @Children private ValueNode[] children;
+        @Children private final ValueNode[] children;
 
         public TestRootNode(ValueNode[] children) {
             this.children = adoptChildren(children);
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Mon Jul 15 13:36:59 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Mon Jul 15 15:29:01 2013 +0200
@@ -163,9 +163,11 @@
                 } else if (Node.class.isAssignableFrom(field.getType()) && field.getAnnotation(Child.class) != null) {
                     kind = NodeFieldKind.CHILD;
                     childOffsetsList.add(fieldOffsetProvider.objectFieldOffset(field));
+                    assert !Modifier.isFinal(field.getModifiers()) : "child field must not be final (\"" + field.getName() + "\", " + clazz + ")";
                 } else if (field.getType().isArray() && Node.class.isAssignableFrom(field.getType().getComponentType()) && field.getAnnotation(Children.class) != null) {
                     kind = NodeFieldKind.CHILDREN;
                     childrenOffsetsList.add(fieldOffsetProvider.objectFieldOffset(field));
+                    assert Modifier.isFinal(field.getModifiers()) : "children array field must be final (\"" + field.getName() + "\", " + clazz + ")";
                 } else {
                     kind = NodeFieldKind.DATA;
                 }
@@ -352,51 +354,52 @@
     public static void replaceChild(Node parent, Node oldChild, Node newChild) {
         NodeClass nodeClass = NodeClass.get(parent.getClass());
 
-        long[] fieldOffsets = nodeClass.childOffsets;
-        for (int i = 0; i < fieldOffsets.length; i++) {
-            long fieldOffset = fieldOffsets[i];
+        for (long fieldOffset : nodeClass.getChildOffsets()) {
             if (unsafe.getObject(parent, fieldOffset) == oldChild) {
-                assert assertAssignable(nodeClass, parent, oldChild, newChild);
+                assert assertAssignable(nodeClass, fieldOffset, newChild);
                 unsafe.putObject(parent, fieldOffset, newChild);
             }
         }
 
-        long[] childrenOffsets = nodeClass.childrenOffsets;
-        for (int i = 0; i < childrenOffsets.length; i++) {
-            long fieldOffset = childrenOffsets[i];
+        for (long fieldOffset : nodeClass.getChildrenOffsets()) {
             Object arrayObject = unsafe.getObject(parent, fieldOffset);
             if (arrayObject != null) {
-                assert arrayObject instanceof Node[] : "Children must be instanceof Node[] ";
+                assert arrayObject instanceof Node[] : "Children array must be instanceof Node[] ";
                 Node[] array = (Node[]) arrayObject;
-                for (int j = 0; j < array.length; j++) {
-                    if (array[j] == oldChild) {
-                        assert newChild != null && array.getClass().getComponentType().isAssignableFrom(newChild.getClass()) : "Array type does not match";
-                        array[j] = newChild;
-                        return;
+                for (int i = 0; i < array.length; i++) {
+                    if (array[i] == oldChild) {
+                        assert assertAssignable(nodeClass, fieldOffset, newChild);
+                        array[i] = newChild;
                     }
                 }
             }
         }
     }
 
-    private static boolean assertAssignable(NodeClass clazz, Node parent, Object oldValue, Object newValue) {
+    private static boolean assertAssignable(NodeClass clazz, long fieldOffset, Object newValue) {
         if (newValue == null) {
             return true;
         }
-        for (NodeField field : clazz.fields) {
-            if (field.kind != NodeFieldKind.CHILD) {
-                continue;
-            }
-            if (unsafe.getObject(parent, field.offset) == oldValue) {
-                if (!field.type.isAssignableFrom(newValue.getClass())) {
-                    assert false : "Child class " + newValue.getClass() + " is not assignable to field " + field.type.getName() + " at " + field.name + " in ";
-                    return false;
-                } else {
-                    break;
+        for (NodeField field : clazz.getFields()) {
+            if (field.getOffset() == fieldOffset) {
+                if (field.getKind() == NodeFieldKind.CHILD) {
+                    if (field.getType().isAssignableFrom(newValue.getClass())) {
+                        return true;
+                    } else {
+                        assert false : "Child class " + newValue.getClass().getName() + " is not assignable to field \"" + field.getName() + "\" of type " + field.getType().getName();
+                        return false;
+                    }
+                } else if (field.getKind() == NodeFieldKind.CHILDREN) {
+                    if (field.getType().getComponentType().isAssignableFrom(newValue.getClass())) {
+                        return true;
+                    } else {
+                        assert false : "Child class " + newValue.getClass().getName() + " is not assignable to field \"" + field.getName() + "\" of type " + field.getType().getName();
+                        return false;
+                    }
                 }
             }
         }
-        return true;
+        throw new IllegalArgumentException();
     }
 
     /** Returns all declared fields in the class hierarchy. */