changeset 18199:c5c80abc3fc6

Truffle: add support for a CompilationListener in GraalTruffleRuntime.
author Christian Humer <christian.humer@gmail.com>
date Mon, 27 Oct 2014 13:42:21 +0100
parents d7e40b20b030
children 62de94d5cf73
files graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleCompilationListener.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java
diffstat 5 files changed, 154 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Mon Oct 27 13:42:21 2014 +0100
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Mon Oct 27 13:42:21 2014 +0100
@@ -205,7 +205,7 @@
             @Override
             public void run() {
                 try (Scope s = Debug.scope("Truffle", new TruffleDebugJavaMethod(optimizedCallTarget))) {
-                    truffleCompiler.compileMethodImpl(optimizedCallTarget);
+                    truffleCompiler.compileMethod(optimizedCallTarget);
                     optimizedCallTarget.notifyCompilationFinished();
                 } catch (Throwable e) {
                     optimizedCallTarget.notifyCompilationFailed(e);
@@ -214,6 +214,7 @@
         };
         Future<?> future = compileQueue.submit(r);
         this.compilations.put(optimizedCallTarget, future);
+        getCompilationNotify().notifyCompilationQueued(optimizedCallTarget);
 
         if (!mayBeAsynchronous) {
             try {
@@ -231,11 +232,13 @@
     }
 
     @Override
-    public boolean cancelInstalledTask(OptimizedCallTarget optimizedCallTarget) {
+    public boolean cancelInstalledTask(OptimizedCallTarget optimizedCallTarget, Object source, CharSequence reason) {
         Future<?> codeTask = this.compilations.get(optimizedCallTarget);
         if (codeTask != null && isCompiling(optimizedCallTarget)) {
             this.compilations.remove(optimizedCallTarget);
-            return codeTask.cancel(true);
+            boolean result = codeTask.cancel(true);
+            getCompilationNotify().notifyCompilationDequeued(optimizedCallTarget, source, reason);
+            return result;
         }
         return false;
     }
@@ -266,8 +269,9 @@
     }
 
     @Override
-    public void invalidateInstalledCode(OptimizedCallTarget optimizedCallTarget) {
+    public void invalidateInstalledCode(OptimizedCallTarget optimizedCallTarget, Object source, CharSequence reason) {
         HotSpotGraalRuntime.runtime().getCompilerToVM().invalidateInstalledCode(optimizedCallTarget);
+        getCompilationNotify().notifyCompilationInvalidated(optimizedCallTarget, source, reason);
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleCompilationListener.java	Mon Oct 27 13:42:21 2014 +0100
@@ -0,0 +1,24 @@
+package com.oracle.graal.truffle;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.truffle.api.*;
+
+public interface GraalTruffleCompilationListener {
+
+    void notifyCompilationQueued(OptimizedCallTarget target);
+
+    void notifyCompilationDequeued(OptimizedCallTarget target, Object source, CharSequence reason);
+
+    void notifyCompilationFailed(OptimizedCallTarget target, StructuredGraph graph, Throwable t);
+
+    void notifyCompilationStarted(OptimizedCallTarget target);
+
+    void notifyCompilationTruffleTierFinished(OptimizedCallTarget target, StructuredGraph graph);
+
+    void notifyCompilationSuccess(OptimizedCallTarget target, StructuredGraph graph, CompilationResult result);
+
+    void notifyCompilationInvalidated(OptimizedCallTarget target, Object source, CharSequence reason);
+
+    void notifyShutdown(TruffleRuntime runtime);
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Mon Oct 27 13:42:21 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Mon Oct 27 13:42:21 2014 +0100
@@ -27,10 +27,13 @@
 import java.util.*;
 import java.util.concurrent.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.stack.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.truffle.debug.*;
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.*;
@@ -46,6 +49,13 @@
     protected ResolvedJavaMethod[] callTargetMethod;
     protected ResolvedJavaMethod[] anyFrameMethod;
 
+    private final List<GraalTruffleCompilationListener> compilationListeners = new ArrayList<>();
+    private final GraalTruffleCompilationListener compilationNotify = new DispatchTruffleCompilationListener();
+
+    public GraalTruffleRuntime() {
+        Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown));
+    }
+
     protected void lookupCallMethods(MetaAccessProvider metaAccess) {
         callNodeMethod = new ResolvedJavaMethod[]{metaAccess.lookupJavaMethod(GraalFrameInstance.CallNodeFrame.METHOD)};
         callTargetMethod = new ResolvedJavaMethod[]{metaAccess.lookupJavaMethod(GraalFrameInstance.CallTargetFrame.METHOD)};
@@ -99,6 +109,10 @@
         return new OptimizedAssumption(name);
     }
 
+    public GraalTruffleCompilationListener getCompilationNotify() {
+        return compilationNotify;
+    }
+
     @TruffleBoundary
     @Override
     public <T> T iterateFrames(FrameInstanceVisitor<T> visitor) {
@@ -187,17 +201,65 @@
 
     public abstract RootCallTarget createClonedCallTarget(OptimizedCallTarget sourceCallTarget, RootNode root);
 
+    public void addCompilationListener(GraalTruffleCompilationListener listener) {
+        compilationListeners.add(listener);
+    }
+
+    public void removeCompilationListener(GraalTruffleCompilationListener listener) {
+        compilationListeners.remove(listener);
+    }
+
+    private void shutdown() {
+        getCompilationNotify().notifyShutdown(this);
+    }
+
     public abstract Replacements getReplacements();
 
     public abstract void compile(OptimizedCallTarget optimizedCallTarget, boolean mayBeAsynchronous);
 
-    public abstract boolean cancelInstalledTask(OptimizedCallTarget optimizedCallTarget);
+    public abstract boolean cancelInstalledTask(OptimizedCallTarget optimizedCallTarget, Object source, CharSequence reason);
 
     public abstract void waitForCompilation(OptimizedCallTarget optimizedCallTarget, long timeout) throws ExecutionException, TimeoutException;
 
     public abstract boolean isCompiling(OptimizedCallTarget optimizedCallTarget);
 
-    public abstract void invalidateInstalledCode(OptimizedCallTarget optimizedCallTarget);
+    public abstract void invalidateInstalledCode(OptimizedCallTarget optimizedCallTarget, Object source, CharSequence reason);
 
     public abstract void reinstallStubs();
+
+    private final class DispatchTruffleCompilationListener implements GraalTruffleCompilationListener {
+
+        public void notifyCompilationQueued(OptimizedCallTarget target) {
+            compilationListeners.forEach(l -> l.notifyCompilationQueued(target));
+        }
+
+        public void notifyCompilationInvalidated(OptimizedCallTarget target, Object source, CharSequence reason) {
+            compilationListeners.forEach(l -> l.notifyCompilationInvalidated(target, source, reason));
+        }
+
+        public void notifyCompilationDequeued(OptimizedCallTarget target, Object source, CharSequence reason) {
+            compilationListeners.forEach(l -> l.notifyCompilationDequeued(target, source, reason));
+        }
+
+        public void notifyCompilationFailed(OptimizedCallTarget target, StructuredGraph graph, Throwable t) {
+            compilationListeners.forEach(l -> l.notifyCompilationFailed(target, graph, t));
+        }
+
+        public void notifyCompilationSuccess(OptimizedCallTarget target, StructuredGraph graph, CompilationResult result) {
+            compilationListeners.forEach(l -> l.notifyCompilationSuccess(target, graph, result));
+        }
+
+        public void notifyCompilationStarted(OptimizedCallTarget target) {
+            compilationListeners.forEach(l -> l.notifyCompilationStarted(target));
+        }
+
+        public void notifyCompilationTruffleTierFinished(OptimizedCallTarget target, StructuredGraph graph) {
+            compilationListeners.forEach(l -> l.notifyCompilationTruffleTierFinished(target, graph));
+        }
+
+        public void notifyShutdown(TruffleRuntime runtime) {
+            compilationListeners.forEach(l -> l.notifyShutdown(runtime));
+        }
+
+    }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Mon Oct 27 13:42:21 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Mon Oct 27 13:42:21 2014 +0100
@@ -276,21 +276,11 @@
 
     @Override
     public void invalidate() {
-        this.runtime.invalidateInstalledCode(this);
+        invalidate(null, null);
     }
 
-    protected void invalidate(Node oldNode, Node newNode, CharSequence reason) {
-        if (isValid()) {
-            CompilerAsserts.neverPartOfCompilation();
-            invalidate();
-            logOptimizedInvalidated(this, oldNode, newNode, reason);
-        }
-        /* Notify compiled method that have inlined this call target that the tree changed. */
-        nodeRewritingAssumption.invalidate();
-
-        if (cancelInstalledTask(oldNode, newNode, reason)) {
-            compilationProfile.reportInvalidated();
-        }
+    protected void invalidate(Node source, CharSequence reason) {
+        this.runtime.invalidateInstalledCode(this, source, reason);
     }
 
     public TruffleInlining getInlining() {
@@ -302,7 +292,7 @@
     }
 
     private boolean cancelInstalledTask(Node oldNode, Node newNode, CharSequence reason) {
-        boolean cancelled = this.runtime.cancelInstalledTask(this);
+        boolean cancelled = this.runtime.cancelInstalledTask(this, newNode, reason);
         if (cancelled) {
             notifyCompilationDequeued(oldNode, newNode, reason);
         }
@@ -442,8 +432,18 @@
 
     @Override
     public void nodeReplaced(Node oldNode, Node newNode, CharSequence reason) {
+        if (isValid()) {
+            CompilerAsserts.neverPartOfCompilation();
+            invalidate(newNode, reason);
+            logOptimizedInvalidated(this, oldNode, newNode, reason);
+        }
+        /* Notify compiled method that have inlined this call target that the tree changed. */
+        nodeRewritingAssumption.invalidate();
+
         compilationProfile.reportNodeReplaced();
-        invalidate(oldNode, newNode, reason);
+        if (cancelInstalledTask(oldNode, newNode, reason)) {
+            compilationProfile.reportInvalidated();
+        }
     }
 
     public void accept(NodeVisitor visitor, boolean includeInlinedNodes) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Mon Oct 27 13:42:21 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Mon Oct 27 13:42:21 2014 +0100
@@ -64,6 +64,7 @@
     private final GraphBuilderConfiguration config;
     private final RuntimeProvider runtime;
     private final TruffleCache truffleCache;
+    private final GraalTruffleCompilationListener compilationNotify;
 
     private static final Class<?>[] SKIPPED_EXCEPTION_CLASSES = new Class[]{UnexpectedResultException.class, SlowPathException.class, ArithmeticException.class, IllegalArgumentException.class};
 
@@ -71,9 +72,11 @@
                     OptimisticOptimizations.Optimization.RemoveNeverExecutedCode, OptimisticOptimizations.Optimization.UseTypeCheckedInlining, OptimisticOptimizations.Optimization.UseTypeCheckHints);
 
     public TruffleCompilerImpl() {
+        GraalTruffleRuntime graalTruffleRuntime = ((GraalTruffleRuntime) Truffle.getRuntime());
         this.runtime = Graal.getRequiredCapability(RuntimeProvider.class);
+        this.compilationNotify = graalTruffleRuntime.getCompilationNotify();
         this.backend = runtime.getHostBackend();
-        Replacements truffleReplacements = ((GraalTruffleRuntime) Truffle.getRuntime()).getReplacements();
+        Replacements truffleReplacements = graalTruffleRuntime.getReplacements();
         this.providers = backend.getProviders().copyWith(truffleReplacements);
         this.suites = backend.getSuites().getDefaultSuites();
 
@@ -105,45 +108,52 @@
     public static final DebugMemUseTracker CompilationMemUse = Debug.memUseTracker("TruffleCompilationMemUse");
     public static final DebugMemUseTracker CodeInstallationMemUse = Debug.memUseTracker("TruffleCodeInstallationMemUse");
 
-    public void compileMethodImpl(final OptimizedCallTarget compilable) {
-        final StructuredGraph graph;
+    public void compileMethod(final OptimizedCallTarget compilable) {
+        StructuredGraph graph = null;
+
+        compilationNotify.notifyCompilationStarted(compilable);
 
         if (TraceTruffleCompilation.getValue()) {
             OptimizedCallTargetLog.logOptimizingStart(compilable);
-
-        }
-
-        long timeCompilationStarted = System.nanoTime();
-        Assumptions assumptions = new Assumptions(true);
-
-        try (TimerCloseable a = PartialEvaluationTime.start(); Closeable c = PartialEvaluationMemUse.start()) {
-            graph = partialEvaluator.createGraph(compilable, assumptions);
-        }
-
-        if (Thread.currentThread().isInterrupted()) {
-            return;
         }
 
-        long timePartialEvaluationFinished = System.nanoTime();
-        int nodeCountPartialEval = graph.getNodeCount();
-        CompilationResult compilationResult = compileMethodHelper(graph, assumptions, compilable.toString(), compilable.getSpeculationLog(), compilable);
-        long timeCompilationFinished = System.nanoTime();
-        int nodeCountLowered = graph.getNodeCount();
+        try {
+            long timeCompilationStarted = System.nanoTime();
+            Assumptions assumptions = new Assumptions(true);
+
+            try (TimerCloseable a = PartialEvaluationTime.start(); Closeable c = PartialEvaluationMemUse.start()) {
+                graph = partialEvaluator.createGraph(compilable, assumptions);
+            }
+
+            if (Thread.currentThread().isInterrupted()) {
+                return;
+            }
+
+            compilationNotify.notifyCompilationTruffleTierFinished(compilable, graph);
 
-        if (TraceTruffleCompilation.getValue()) {
-            printTruffleCompilation(compilable, timeCompilationStarted, timePartialEvaluationFinished, nodeCountPartialEval, compilationResult, timeCompilationFinished, nodeCountLowered);
+            long timePartialEvaluationFinished = System.nanoTime();
+            int nodeCountPartialEval = graph.getNodeCount();
+            CompilationResult compilationResult = compileMethodHelper(graph, assumptions, compilable.toString(), compilable.getSpeculationLog(), compilable);
+            long timeCompilationFinished = System.nanoTime();
+            int nodeCountLowered = graph.getNodeCount();
+            if (TraceTruffleCompilation.getValue()) {
+                printTruffleCompilation(compilable, timeCompilationStarted, timePartialEvaluationFinished, nodeCountPartialEval, compilationResult, timeCompilationFinished, nodeCountLowered);
+            }
+            if (TraceTruffleCompilationAST.getValue()) {
+                OptimizedCallUtils.printCompactTree(OptimizedCallTarget.OUT, compilable);
+            }
+            if (TraceTruffleCompilationCallTree.getValue()) {
+                OptimizedCallTargetLog.log(0, "opt call tree", compilable.toString(), compilable.getDebugProperties());
+                OptimizedCallTargetLog.logTruffleCallTree(compilable);
+            }
+            if (TraceTruffleInlining.getValue()) {
+                OptimizedCallTargetLog.logInliningDecision(compilable);
+            }
+            compilationNotify.notifyCompilationSuccess(compilable, graph, compilationResult);
+        } catch (Throwable t) {
+            compilationNotify.notifyCompilationFailed(compilable, graph, t);
+            throw t;
         }
-        if (TraceTruffleCompilationAST.getValue()) {
-            OptimizedCallUtils.printCompactTree(OptimizedCallTarget.OUT, compilable);
-        }
-        if (TraceTruffleCompilationCallTree.getValue()) {
-            OptimizedCallTargetLog.log(0, "opt call tree", compilable.toString(), compilable.getDebugProperties());
-            OptimizedCallTargetLog.logTruffleCallTree(compilable);
-        }
-        if (TraceTruffleInlining.getValue()) {
-            OptimizedCallTargetLog.logInliningDecision(compilable);
-        }
-
     }
 
     private static void printTruffleCompilation(final OptimizedCallTarget compilable, long timeCompilationStarted, long timePartialEvaluationFinished, int nodeCountPartialEval,