changeset 12709:d2d0c44662bb

Truffle: refactored CompilationProfile to separate the profile and the policy in separate classes.
author Christian Humer <christian.humer@gmail.com>
date Thu, 07 Nov 2013 16:21:06 +0100
parents 85bab2227295
children 60142b15ed42
files graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationPolicy.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationProfile.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultCompilationPolicy.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TimedCompilationPolicy.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningImpl.java
diffstat 6 files changed, 240 insertions(+), 125 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationPolicy.java	Thu Nov 07 15:10:09 2013 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationPolicy.java	Thu Nov 07 16:21:06 2013 +0100
@@ -22,96 +22,8 @@
  */
 package com.oracle.graal.truffle;
 
-import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
-
-public class CompilationPolicy {
-
-    private int invokeCounter;
-    private int originalInvokeCounter;
-    private int loopAndInvokeCounter;
-    private long prevTimestamp;
-
-    private final int compilationThreshold;
-    private final String name;
-
-    public CompilationPolicy(final int compilationThreshold, final int initialInvokeCounter, final String name) {
-        this.invokeCounter = initialInvokeCounter;
-        this.loopAndInvokeCounter = compilationThreshold;
-        this.originalInvokeCounter = compilationThreshold;
-        this.prevTimestamp = System.nanoTime();
-
-        this.compilationThreshold = compilationThreshold;
-        this.name = name;
-    }
-
-    public String getName() {
-        return this.name;
-    }
-
-    public int getInvokeCounter() {
-        return invokeCounter;
-    }
-
-    public int getOriginalInvokeCounter() {
-        return originalInvokeCounter;
-    }
-
-    public int getLoopAndInvokeCounter() {
-        return loopAndInvokeCounter;
-    }
-
-    public void reportCompilationInvalidated() {
-        int invalidationReprofileCount = TruffleInvalidationReprofileCount.getValue();
-        invokeCounter = invalidationReprofileCount;
-        if (TruffleFunctionInlining.getValue()) {
-            originalInvokeCounter += invalidationReprofileCount;
-        }
-    }
+public interface CompilationPolicy {
 
-    public void reportInterpreterCall() {
-        invokeCounter--;
-        loopAndInvokeCounter--;
-    }
-
-    public void reportCallInlined(int minInvokesAfterInlining) {
-        invokeCounter = minInvokesAfterInlining;
-        int inliningReprofileCount = TruffleInliningReprofileCount.getValue();
-        loopAndInvokeCounter = inliningReprofileCount;
-        originalInvokeCounter = inliningReprofileCount;
-    }
-
-    public void reportLoopCount(int count) {
-        loopAndInvokeCounter = Math.max(0, loopAndInvokeCounter - count);
-    }
-
-    public void notifyNodeReplaced() {
-        // delay compilation until tree is deemed stable enough
-        int replaceBackoff = TruffleReplaceReprofileCount.getValue();
-        if (loopAndInvokeCounter < replaceBackoff) {
-            loopAndInvokeCounter = replaceBackoff;
-        }
-    }
+    boolean shouldCompile(CompilationProfile profile);
 
-    public boolean shouldCompileOrInline() {
-        if (invokeCounter <= 0 && loopAndInvokeCounter <= 0) {
-            if (TruffleUseTimeForCompilationDecision.getValue()) {
-                long timestamp = System.nanoTime();
-                long timespan = (timestamp - prevTimestamp);
-                if (timespan < (TruffleCompilationDecisionTime.getValue())) {
-                    return true;
-                }
-                this.loopAndInvokeCounter = compilationThreshold;
-                this.originalInvokeCounter = compilationThreshold;
-                this.prevTimestamp = timestamp;
-                if (TruffleCompilationDecisionTimePrintFail.getValue()) {
-                    // Checkstyle: stop
-                    System.out.println(name + ": timespan  " + (timespan / 1000000) + " ms  larger than threshold");
-                    // Checkstyle: resume
-                }
-            } else {
-                return true;
-            }
-        }
-        return false;
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationProfile.java	Thu Nov 07 16:21:06 2013 +0100
@@ -0,0 +1,127 @@
+/*
+ * 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 static com.oracle.graal.truffle.TruffleCompilerOptions.*;
+
+public class CompilationProfile {
+
+    private static final int MIN_INVOKES_AFTER_INLINING = 2;
+
+    private int invokeCounter;
+    private int originalInvokeCounter;
+    private int loopAndInvokeCounter;
+    /**
+     * Number of times an installed code for this tree was invalidated.
+     */
+    private int invalidationCount;
+
+    /**
+     * Number of times a node was replaced in this tree.
+     */
+    private int nodeReplaceCount;
+
+    private long previousTimestamp;
+
+    private final int compilationThreshold;
+    private final String name;
+
+    public CompilationProfile(final int compilationThreshold, final int initialInvokeCounter, final String name) {
+        this.invokeCounter = initialInvokeCounter;
+        this.loopAndInvokeCounter = compilationThreshold;
+        this.originalInvokeCounter = compilationThreshold;
+        this.previousTimestamp = System.nanoTime();
+
+        this.compilationThreshold = compilationThreshold;
+        this.name = name;
+    }
+
+    public long getPreviousTimestamp() {
+        return previousTimestamp;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public int getInvalidationCount() {
+        return invalidationCount;
+    }
+
+    public int getNodeReplaceCount() {
+        return nodeReplaceCount;
+    }
+
+    public int getInvokeCounter() {
+        return invokeCounter;
+    }
+
+    public int getOriginalInvokeCounter() {
+        return originalInvokeCounter;
+    }
+
+    public int getLoopAndInvokeCounter() {
+        return loopAndInvokeCounter;
+    }
+
+    void reportTiminingFailed(long timestamp) {
+        this.loopAndInvokeCounter = compilationThreshold;
+        this.originalInvokeCounter = compilationThreshold;
+        this.previousTimestamp = timestamp;
+    }
+
+    void reportInvalidated() {
+        invalidationCount++;
+        int invalidationReprofileCount = TruffleInvalidationReprofileCount.getValue();
+        invokeCounter = invalidationReprofileCount;
+        if (TruffleFunctionInlining.getValue()) {
+            originalInvokeCounter += invalidationReprofileCount;
+        }
+    }
+
+    void reportInterpreterCall() {
+        invokeCounter--;
+        loopAndInvokeCounter--;
+    }
+
+    void reportInliningPerformed() {
+        invokeCounter = MIN_INVOKES_AFTER_INLINING;
+        int inliningReprofileCount = TruffleInliningReprofileCount.getValue();
+        loopAndInvokeCounter = inliningReprofileCount;
+        originalInvokeCounter = inliningReprofileCount;
+    }
+
+    void reportLoopCount(int count) {
+        loopAndInvokeCounter = Math.max(0, loopAndInvokeCounter - count);
+    }
+
+    void reportNodeReplaced() {
+        nodeReplaceCount++;
+        // delay compilation until tree is deemed stable enough
+        int replaceBackoff = TruffleReplaceReprofileCount.getValue();
+        if (loopAndInvokeCounter < replaceBackoff) {
+            loopAndInvokeCounter = replaceBackoff;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultCompilationPolicy.java	Thu Nov 07 16:21:06 2013 +0100
@@ -0,0 +1,31 @@
+/*
+ * 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;
+
+public class DefaultCompilationPolicy implements CompilationPolicy {
+
+    public boolean shouldCompile(CompilationProfile profile) {
+        return profile.getInvokeCounter() <= 0 && profile.getLoopAndInvokeCounter() <= 0;
+    }
+
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Thu Nov 07 15:10:09 2013 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Thu Nov 07 16:21:06 2013 +0100
@@ -41,45 +41,41 @@
 public final class OptimizedCallTarget extends DefaultCallTarget implements FrameFactory, LoopCountReceiver, ReplaceObserver {
 
     private static final PrintStream OUT = TTY.out().out();
-    private static final int MIN_INVOKES_AFTER_INLINING = 2;
+
+    private InstalledCode installedCode;
+    private Future<InstalledCode> installedCodeTask;
+    private final TruffleCompiler compiler;
+    private final CompilationProfile compilationProfile;
+    private final CompilationPolicy compilationPolicy;
+    private final TruffleInlining inlining;
+    private boolean disableCompilation;
+    private int callCount;
 
     protected OptimizedCallTarget(RootNode rootNode, FrameDescriptor descriptor, TruffleCompiler compiler, int invokeCounter, int compilationThreshold) {
         super(rootNode, descriptor);
         this.compiler = compiler;
-        this.compilationPolicy = new CompilationPolicy(compilationThreshold, invokeCounter, rootNode.toString());
+        this.compilationProfile = new CompilationProfile(compilationThreshold, invokeCounter, rootNode.toString());
         this.inlining = new TruffleInliningImpl();
         this.rootNode.setCallTarget(this);
 
+        if (TruffleUseTimeForCompilationDecision.getValue()) {
+            compilationPolicy = new TimedCompilationPolicy();
+        } else {
+            compilationPolicy = new DefaultCompilationPolicy();
+        }
+
         if (TruffleCallTargetProfiling.getValue()) {
             registerCallTarget(this);
         }
     }
 
-    private InstalledCode installedCode;
-    private Future<InstalledCode> installedCodeTask;
-    private final TruffleCompiler compiler;
-    private final CompilationPolicy compilationPolicy;
-    private final TruffleInlining inlining;
-    private boolean disableCompilation;
-    private int callCount;
-
-    /**
-     * Number of times an installed code for this tree was invalidated.
-     */
-    private int invalidationCount;
-
-    /**
-     * Number of times a node was replaced in this tree.
-     */
-    private int nodeReplaceCount;
-
     @Override
     public Object call(PackedFrame caller, Arguments args) {
         return callHelper(caller, args);
     }
 
-    CompilationPolicy getCompilationPolicy() {
-        return compilationPolicy;
+    public CompilationProfile getCompilationProfile() {
+        return compilationProfile;
     }
 
     private Object callHelper(PackedFrame caller, Arguments args) {
@@ -115,10 +111,10 @@
         if (m != null) {
             CompilerAsserts.neverPartOfCompilation();
             installedCode = null;
-            invalidationCount++;
-            compilationPolicy.reportCompilationInvalidated();
+            compilationProfile.reportInvalidated();
             if (TraceTruffleCompilation.getValue()) {
-                OUT.printf("[truffle] invalidated %-48s |Inv# %d                                     |Replace# %d\n", rootNode, invalidationCount, nodeReplaceCount);
+                OUT.printf("[truffle] invalidated %-48s |Inv# %d                                     |Replace# %d\n", rootNode, compilationProfile.getInvalidationCount(),
+                                compilationProfile.getNodeReplaceCount());
             }
         }
 
@@ -126,14 +122,14 @@
         if (task != null) {
             task.cancel(true);
             this.installedCodeTask = null;
-            compilationPolicy.reportCompilationInvalidated();
+            compilationProfile.reportInvalidated();
         }
     }
 
     private Object interpreterCall(PackedFrame caller, Arguments args) {
         CompilerAsserts.neverPartOfCompilation();
-        compilationPolicy.reportInterpreterCall();
-        if (disableCompilation || !compilationPolicy.shouldCompileOrInline()) {
+        compilationProfile.reportInterpreterCall();
+        if (disableCompilation || !compilationPolicy.shouldCompile(compilationProfile)) {
             return executeHelper(caller, args);
         } else {
             return compileOrInline(caller, args);
@@ -154,7 +150,7 @@
         }
 
         if (TruffleFunctionInlining.getValue() && inline()) {
-            compilationPolicy.reportCallInlined(MIN_INVOKES_AFTER_INLINING);
+            compilationProfile.reportInliningPerformed();
             return call(caller, args);
         } else {
             compile();
@@ -214,14 +210,13 @@
 
     @Override
     public void reportLoopCount(int count) {
-        compilationPolicy.reportLoopCount(count);
+        compilationProfile.reportLoopCount(count);
     }
 
     @Override
     public void nodeReplaced() {
-        nodeReplaceCount++;
+        compilationProfile.reportNodeReplaced();
         invalidate();
-        compilationPolicy.notifyNodeReplaced();
     }
 
     private static void resetProfiling() {
@@ -259,13 +254,13 @@
             String comment = callTarget.installedCode == null ? " int" : "";
             comment += callTarget.disableCompilation ? " fail" : "";
             OUT.printf("%-50s | %10d | %15d | %15d | %10d | %3d%s\n", callTarget.getRootNode(), callTarget.callCount, inlinedCallSiteCount, notInlinedCallSiteCount, nodeCount,
-                            callTarget.invalidationCount, comment);
+                            callTarget.getCompilationProfile().getInvalidationCount(), comment);
 
             totalCallCount += callTarget.callCount;
             totalInlinedCallSiteCount += inlinedCallSiteCount;
             totalNotInlinedCallSiteCount += notInlinedCallSiteCount;
             totalNodeCount += nodeCount;
-            totalInvalidationCount += callTarget.invalidationCount;
+            totalInvalidationCount += callTarget.getCompilationProfile().getInvalidationCount();
         }
         OUT.printf("%-50s | %10d | %15d | %15d | %10d | %3d\n", "Total", totalCallCount, totalInlinedCallSiteCount, totalNotInlinedCallSiteCount, totalNodeCount, totalInvalidationCount);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TimedCompilationPolicy.java	Thu Nov 07 16:21:06 2013 +0100
@@ -0,0 +1,50 @@
+/*
+ * 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 static com.oracle.graal.truffle.TruffleCompilerOptions.*;
+
+public class TimedCompilationPolicy extends DefaultCompilationPolicy {
+
+    @Override
+    public boolean shouldCompile(CompilationProfile profile) {
+        if (super.shouldCompile(profile)) {
+            long timestamp = System.nanoTime();
+            long prevTimestamp = profile.getPreviousTimestamp();
+            long timespan = (timestamp - prevTimestamp);
+            if (timespan < (TruffleCompilationDecisionTime.getValue())) {
+                return true;
+            }
+            // TODO shouldCompile should not modify the compilation profile
+            // maybe introduce another method?
+            profile.reportTiminingFailed(timestamp);
+            if (TruffleCompilationDecisionTimePrintFail.getValue()) {
+                // Checkstyle: stop
+                System.out.println(profile.getName() + ": timespan  " + (timespan / 1000000) + " ms  larger than threshold");
+                // Checkstyle: resume
+            }
+        }
+        return false;
+    }
+
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningImpl.java	Thu Nov 07 15:10:09 2013 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningImpl.java	Thu Nov 07 16:21:06 2013 +0100
@@ -105,7 +105,7 @@
 
         public InliningPolicy(OptimizedCallTarget caller) {
             this.callerNodeCount = NodeUtil.countNodes(caller.getRootNode());
-            this.callerInvocationCount = caller.getCompilationPolicy().getOriginalInvokeCounter();
+            this.callerInvocationCount = caller.getCompilationProfile().getOriginalInvokeCounter();
         }
 
         public boolean continueInlining() {