changeset 18291:5415422cb32f

Merge.
author Doug Simon <doug.simon@oracle.com>
date Thu, 06 Nov 2014 20:14:47 +0100
parents e7d219e9d01f (current diff) f1a988d9213f (diff)
children 463722cb77f8
files
diffstat 15 files changed, 169 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGELOG.md	Thu Nov 06 20:13:08 2014 +0100
+++ b/CHANGELOG.md	Thu Nov 06 20:14:47 2014 +0100
@@ -15,6 +15,7 @@
 * Renamed DirectCallNode#split to DirectCallNode#cloneCallTarget
 * Renamed DirectCallNode#isSplit to DirectCallNode#isCallTargetCloned
 * Added PrimitiveValueProfile.
+* Added -G:TruffleTimeThreshold=5000 option to defer compilation for call targets
 * ...
 
 ## Version 0.5
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Thu Nov 06 20:13:08 2014 +0100
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Thu Nov 06 20:14:47 2014 +0100
@@ -116,12 +116,13 @@
     private RootCallTarget createCallTargetImpl(OptimizedCallTarget source, RootNode rootNode) {
         CompilationPolicy compilationPolicy;
         if (acceptForCompilation(rootNode)) {
-            compilationPolicy = new CounterBasedCompilationPolicy();
+            compilationPolicy = new CounterAndTimeBasedCompilationPolicy();
         } else {
             compilationPolicy = new InterpreterOnlyCompilationPolicy();
         }
         OptimizedCallTarget target = new OptimizedCallTarget(source, rootNode, this, compilationPolicy, new HotSpotSpeculationLog());
         callTargets.put(target, null);
+
         return target;
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationProfile.java	Thu Nov 06 20:13:08 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationProfile.java	Thu Nov 06 20:14:47 2014 +0100
@@ -28,16 +28,21 @@
 
 public class CompilationProfile {
 
+    private static final int TIMESTAMP_THRESHOLD = Math.max(TruffleCompilationThreshold.getValue() / 2, 1);
+
     /**
      * Number of times an installed code for this tree was invalidated.
      */
     private int invalidationCount;
+    private int deferedCount;
 
     private int interpreterCallCount;
     private int interpreterCallAndLoopCount;
     private int compilationCallThreshold;
     private int compilationCallAndLoopThreshold;
 
+    private long timestamp;
+
     public CompilationProfile() {
         this.compilationCallThreshold = TruffleMinInvokeThreshold.getValue();
         this.compilationCallAndLoopThreshold = TruffleCompilationThreshold.getValue();
@@ -54,8 +59,8 @@
         String callsThreshold = String.format("%7d/%5d", getInterpreterCallCount(), getCompilationCallThreshold());
         String loopsThreshold = String.format("%7d/%5d", getInterpreterCallAndLoopCount(), getCompilationCallAndLoopThreshold());
         String invalidations = String.format("%5d", invalidationCount);
-        properties.put("C/T", callsThreshold);
-        properties.put("L/T", loopsThreshold);
+        properties.put("Calls/Thres", callsThreshold);
+        properties.put("CallsAndLoop/Thres", loopsThreshold);
         properties.put("Inval#", invalidations);
         return properties;
     }
@@ -72,6 +77,10 @@
         return interpreterCallCount;
     }
 
+    public int getDeferedCount() {
+        return deferedCount;
+    }
+
     public int getCompilationCallAndLoopThreshold() {
         return compilationCallAndLoopThreshold;
     }
@@ -101,6 +110,11 @@
     public void reportInterpreterCall() {
         interpreterCallCount++;
         interpreterCallAndLoopCount++;
+
+        int callsMissing = compilationCallAndLoopThreshold - interpreterCallAndLoopCount;
+        if (callsMissing == TIMESTAMP_THRESHOLD) {
+            timestamp = System.nanoTime();
+        }
     }
 
     public void reportDirectCall() {
@@ -115,8 +129,19 @@
 
     }
 
+    public void deferCompilation() {
+        ensureProfiling(0, TIMESTAMP_THRESHOLD + 1);
+        timestamp = 0;
+        deferedCount++;
+    }
+
     void reportLoopCount(int count) {
         interpreterCallAndLoopCount += count;
+
+        int callsMissing = compilationCallAndLoopThreshold - interpreterCallAndLoopCount;
+        if (callsMissing <= TIMESTAMP_THRESHOLD && callsMissing + count > TIMESTAMP_THRESHOLD) {
+            timestamp = System.nanoTime();
+        }
     }
 
     void reportNodeReplaced() {
@@ -125,4 +150,7 @@
         ensureProfiling(1, replaceBackoff);
     }
 
+    public long getTimestamp() {
+        return timestamp;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CounterAndTimeBasedCompilationPolicy.java	Thu Nov 06 20:14:47 2014 +0100
@@ -0,0 +1,49 @@
+/*
+ * 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 CounterAndTimeBasedCompilationPolicy extends CounterBasedCompilationPolicy {
+
+    private static final long threshold = TruffleTimeThreshold.getValue() * 1_000_000L;
+
+    @Override
+    public boolean shouldCompile(CompilationProfile profile) {
+        if (super.shouldCompile(profile)) {
+            long time = profile.getTimestamp();
+            if (time == 0) {
+                throw new AssertionError();
+            }
+            long timeElapsed = System.nanoTime() - time;
+            if (timeElapsed > threshold) {
+                profile.deferCompilation();
+                return false;
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleCompilationListener.java	Thu Nov 06 20:13:08 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleCompilationListener.java	Thu Nov 06 20:14:47 2014 +0100
@@ -24,18 +24,48 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.nodes.*;
 
+/**
+ * Enables implementations of this interface to listen to compilation related events of the Graal
+ * Truffle runtime. The states for a particular {@link OptimizedCallTarget} that is compiled using
+ * the Graal Truffle system can be described using the following deterministic automata: * <code>
+ * <pre>
+ * ( (split | (queue . unqueue))*
+ *    . queue . started
+ *    . (truffleTierFinished . graalTierFinished . success)
+ *      | ([truffleTierFinished] . [graalTierFinished] . failed)
+ *    . invalidate )*
+ * </pre>
+ * </code>
+ * <p>
+ * Note: <code>|</code> is the 'or' and <code>.</code> is the sequential operator. The
+ * <code>*</code> represents the Kleene Closure.
+ * </p>
+ *
+ * @see GraalTruffleRuntime#addCompilationListener(GraalTruffleCompilationListener)
+ */
 public interface GraalTruffleCompilationListener {
 
+    void notifyCompilationSplit(OptimizedDirectCallNode callNode);
+
+    /**
+     * Invoked if a call target was queued to the compilation queue.
+     */
     void notifyCompilationQueued(OptimizedCallTarget target);
 
+    /**
+     * Invoked if a call target was unqueued from the compilation queue.
+     *
+     * @param source the source object that caused the compilation to be unqueued. For example the
+     *            source {@link Node} object. May be <code>null</code>.
+     * @param reason a textual description of the reason why the compilation was unqueued. May be
+     *            <code>null</code>.
+     */
     void notifyCompilationDequeued(OptimizedCallTarget target, Object source, CharSequence reason);
 
     void notifyCompilationFailed(OptimizedCallTarget target, StructuredGraph graph, Throwable t);
 
-    void notifyCompilationSplit(OptimizedDirectCallNode callNode);
-
     void notifyCompilationStarted(OptimizedCallTarget target);
 
     void notifyCompilationTruffleTierFinished(OptimizedCallTarget target, StructuredGraph graph);
@@ -44,8 +74,24 @@
 
     void notifyCompilationSuccess(OptimizedCallTarget target, StructuredGraph graph, CompilationResult result);
 
+    /**
+     * Invoked if a compiled call target was invalidated.
+     *
+     * @param source the source object that caused the compilation to be invalidated. For example
+     *            the source {@link Node} object. May be <code>null</code>.
+     * @param reason a textual description of the reason why the compilation was invalidated. May be
+     *            <code>null</code>.
+     */
     void notifyCompilationInvalidated(OptimizedCallTarget target, Object source, CharSequence reason);
 
-    void notifyShutdown(TruffleRuntime runtime);
+    /**
+     * Invoked as the compiler gets shut down.
+     */
+    void notifyShutdown(GraalTruffleRuntime runtime);
+
+    /**
+     * Invoked as soon as the compiler is ready to use.
+     */
+    void notifyStartup(GraalTruffleRuntime runtime);
 
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Thu Nov 06 20:13:08 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Thu Nov 06 20:14:47 2014 +0100
@@ -66,6 +66,7 @@
         TraceSplittingListener.install(this);
         PrintCallTargetProfiling.install(this);
         CompilationStatisticsListener.install(this);
+        compilationNotify.notifyStartup(this);
     }
 
     protected void lookupCallMethods(MetaAccessProvider metaAccess) {
@@ -283,9 +284,13 @@
             compilationListeners.forEach(l -> l.notifyCompilationTruffleTierFinished(target, graph));
         }
 
-        public void notifyShutdown(TruffleRuntime runtime) {
+        public void notifyShutdown(GraalTruffleRuntime runtime) {
             compilationListeners.forEach(l -> l.notifyShutdown(runtime));
         }
 
+        public void notifyStartup(GraalTruffleRuntime runtime) {
+            compilationListeners.forEach(l -> l.notifyStartup(runtime));
+        }
+
     }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Thu Nov 06 20:13:08 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Thu Nov 06 20:14:47 2014 +0100
@@ -54,6 +54,7 @@
     protected final CompilationPolicy compilationPolicy;
     private final OptimizedCallTarget sourceCallTarget;
     private final AtomicInteger callSitesKnown = new AtomicInteger(0);
+
     @CompilationFinal private Class<?>[] profiledArgumentTypes;
     @CompilationFinal private Assumption profiledArgumentTypesAssumption;
     @CompilationFinal private Class<?> profiledReturnType;
@@ -238,7 +239,7 @@
             // We are called and we are still in Truffle interpreter mode.
             interpreterCall();
         } else {
-            // We come here from compiled code (i.e., we have been inlined).
+            // We come here from compiled code
         }
 
         return callRoot(args);
@@ -418,8 +419,8 @@
 
     @Override
     public void nodeReplaced(Node oldNode, Node newNode, CharSequence reason) {
+        CompilerAsserts.neverPartOfCompilation();
         if (isValid()) {
-            CompilerAsserts.neverPartOfCompilation();
             invalidate(newNode, reason);
         }
         /* Notify compiled method that have inlined this call target that the tree changed. */
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Thu Nov 06 20:13:08 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Thu Nov 06 20:14:47 2014 +0100
@@ -45,6 +45,8 @@
     public static final OptionValue<String> TruffleCompileOnly = new OptionValue<>(null);
     @Option(help = "Compile call target when call count exceeds this threshold")
     public static final OptionValue<Integer> TruffleCompilationThreshold = new OptionValue<>(1000);
+    @Option(help = "Defines the maximum timespan in milliseconds that is required for a call target to be queued for compilation.")
+    public static final OptionValue<Integer> TruffleTimeThreshold = new OptionValue<>(5000);
     @Option(help = "Minimum number of calls before a call target is compiled")
     public static final OptionValue<Integer> TruffleMinInvokeThreshold = new OptionValue<>(3);
     @Option(help = "Delay compilation after an invalidation to allow for reprofiling")
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/AbstractDebugCompilationListener.java	Thu Nov 06 20:13:08 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/AbstractDebugCompilationListener.java	Thu Nov 06 20:14:47 2014 +0100
@@ -29,7 +29,6 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.truffle.*;
-import com.oracle.truffle.api.*;
 
 public abstract class AbstractDebugCompilationListener implements GraalTruffleCompilationListener {
 
@@ -62,16 +61,20 @@
     public void notifyCompilationInvalidated(OptimizedCallTarget target, Object source, CharSequence reason) {
     }
 
-    public void notifyShutdown(TruffleRuntime runtime) {
+    public void notifyShutdown(GraalTruffleRuntime runtime) {
+    }
+
+    public void notifyStartup(GraalTruffleRuntime runtime) {
     }
 
     public static void log(int indent, String msg, String details, Map<String, Object> properties) {
+        int spaceIndent = indent * 2;
         StringBuilder sb = new StringBuilder();
         sb.append(String.format("[truffle] %-16s ", msg));
-        for (int i = 0; i < indent; i++) {
+        for (int i = 0; i < spaceIndent; i++) {
             sb.append(' ');
         }
-        sb.append(String.format("%-" + (60 - indent) + "s", details));
+        sb.append(String.format("%-" + (60 - spaceIndent) + "s", details));
         if (properties != null) {
             for (String property : properties.keySet()) {
                 Object value = properties.get(property);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/CompilationStatisticsListener.java	Thu Nov 06 20:13:08 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/CompilationStatisticsListener.java	Thu Nov 06 20:14:47 2014 +0100
@@ -34,7 +34,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.truffle.*;
 import com.oracle.graal.truffle.TruffleInlining.CallTreeNodeVisitor;
-import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.nodes.Node;
 
@@ -50,6 +49,10 @@
     private int dequeues;
     private int splits;
 
+    private final IntSummaryStatistics deferCompilations = new IntSummaryStatistics();
+    private final LongSummaryStatistics timeToQueue = new LongSummaryStatistics();
+    private final LongSummaryStatistics timeToCompilation = new LongSummaryStatistics();
+
     private final IntSummaryStatistics nodeCount = new IntSummaryStatistics();
     private final IntSummaryStatistics nodeCountTrivial = new IntSummaryStatistics();
     private final IntSummaryStatistics nodeCountNonTrivial = new IntSummaryStatistics();
@@ -105,6 +108,7 @@
         if (firstCompilation == 0) {
             firstCompilation = System.nanoTime();
         }
+        timeToQueue.accept(System.nanoTime() - target.getCompilationProfile().getTimestamp());
     }
 
     @Override
@@ -130,6 +134,9 @@
         CompilationLocal local = new CompilationLocal();
         local.compilationStarted = System.nanoTime();
         compilationLocal.set(local);
+
+        deferCompilations.accept(target.getCompilationProfile().getDeferedCount());
+        timeToCompilation.accept(local.compilationStarted - target.getCompilationProfile().getTimestamp());
     }
 
     @Override
@@ -197,8 +204,8 @@
     }
 
     @Override
-    public void notifyShutdown(TruffleRuntime runtime) {
-        printStatistics((GraalTruffleRuntime) runtime, OUT);
+    public void notifyShutdown(GraalTruffleRuntime runtime) {
+        printStatistics(runtime, OUT);
     }
 
     public void printStatistics(GraalTruffleRuntime runtime, PrintStream out) {
@@ -216,6 +223,10 @@
         printStatistic("Queue Accuracy", 1.0 - dequeues / (double) queues);
         printStatistic("Compilation Utilization", compilationTime.getSum() / (double) (endTime - firstCompilation));
         printStatistic("Remaining Compilation Queue", runtime.getQueuedCallTargets().size());
+        printStatistic("Times defered until compilation", deferCompilations);
+
+        printStatisticTime("Time to queue", timeToQueue);
+        printStatisticTime("Time to compilation", timeToCompilation);
 
         printStatisticTime("Compilation time", compilationTime);
         printStatisticTime("  Truffle Tier", compilationTimeTruffleTier);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/PrintCallTargetProfiling.java	Thu Nov 06 20:13:08 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/PrintCallTargetProfiling.java	Thu Nov 06 20:14:47 2014 +0100
@@ -40,7 +40,7 @@
     }
 
     @Override
-    public void notifyShutdown(TruffleRuntime runtime) {
+    public void notifyShutdown(GraalTruffleRuntime runtime) {
         Map<OptimizedCallTarget, List<OptimizedCallTarget>> groupedTargets = Truffle.getRuntime().getCallTargets().stream().map(target -> (OptimizedCallTarget) target).collect(
                         Collectors.groupingBy(target -> {
                             if (target.getSourceCallTarget() != null) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/TraceCompilationCallTreeListener.java	Thu Nov 06 20:13:08 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/TraceCompilationCallTreeListener.java	Thu Nov 06 20:14:47 2014 +0100
@@ -65,10 +65,10 @@
                     addASTSizeProperty(callNode.getCurrentCallTarget(), properties);
                     properties.putAll(callNode.getCurrentCallTarget().getDebugProperties());
                     properties.put("Stamp", callNode.getCurrentCallTarget().getArgumentStamp());
-                    log((depth * 2), "opt call tree", callNode.getCurrentCallTarget().toString() + dispatched, properties);
+                    log(depth, "opt call tree", callNode.getCurrentCallTarget().toString() + dispatched, properties);
                 } else if (node instanceof OptimizedIndirectCallNode) {
                     int depth = decisionStack == null ? 0 : decisionStack.size() - 1;
-                    log((depth * 2), "opt call tree", "<indirect>", new LinkedHashMap<String, Object>());
+                    log(depth, "opt call tree", "<indirect>", new LinkedHashMap<String, Object>());
                 }
                 return true;
             }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/TraceInliningListener.java	Thu Nov 06 20:13:08 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/TraceInliningListener.java	Thu Nov 06 20:14:47 2014 +0100
@@ -24,8 +24,6 @@
 
 import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
 
-import java.util.*;
-
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.truffle.*;
 
@@ -57,19 +55,11 @@
             TruffleInliningProfile profile = decision.getProfile();
             boolean inlined = decision.isInline();
             String msg = inlined ? "inline success" : "inline failed";
-            logInlinedImpl(msg, decision.getProfile().getCallNode(), profile, depth);
+            log(depth, msg, decision.getProfile().getCallNode().getCurrentCallTarget().toString(), profile.getDebugProperties());
             if (inlined) {
                 logInliningDecisionRecursive(decision, depth + 1);
             }
         }
     }
 
-    private static void logInlinedImpl(String status, OptimizedDirectCallNode callNode, TruffleInliningProfile profile, int depth) {
-        Map<String, Object> properties = new LinkedHashMap<>();
-        if (profile != null) {
-            properties.putAll(profile.getDebugProperties());
-        }
-        log((depth * 2), status, callNode.getCurrentCallTarget().toString(), properties);
-    }
-
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/TracePerformanceWarningsListener.java	Thu Nov 06 20:13:08 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/TracePerformanceWarningsListener.java	Thu Nov 06 20:14:47 2014 +0100
@@ -26,7 +26,6 @@
 
 import java.util.*;
 
-import com.oracle.graal.nodes.*;
 import com.oracle.graal.truffle.*;
 
 public final class TracePerformanceWarningsListener extends AbstractDebugCompilationListener {
@@ -40,10 +39,6 @@
         }
     }
 
-    @Override
-    public void notifyCompilationTruffleTierFinished(OptimizedCallTarget target, StructuredGraph graph) {
-    }
-
     public static boolean isEnabled() {
         return TraceTrufflePerformanceWarnings.getValue();
     }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Thu Nov 06 20:13:08 2014 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Thu Nov 06 20:14:47 2014 +0100
@@ -119,7 +119,7 @@
         VirtualUtil.trace("\nBlock: %s, preds: %s, succ: %s (", block, block.getPredecessors(), block.getSuccessors());
 
         GraphEffectList effects = blockEffects.get(block);
-        FixedWithNextNode lastFixedNode = null;
+        FixedWithNextNode lastFixedNode = block.getBeginNode().predecessor() instanceof FixedWithNextNode ? (FixedWithNextNode) block.getBeginNode().predecessor() : null;
         Iterable<? extends Node> nodes = schedule != null ? schedule.getBlockToNodesMap().get(block) : block.getNodes();
         for (Node node : nodes) {
             aliases.set(node, null);