# HG changeset patch # User Christian Humer # Date 1414413741 -3600 # Node ID c5c80abc3fc6cc3abce772cd7e90b85e656a01d5 # Parent d7e40b20b030a9fad9f820fff41257357cc607a2 Truffle: add support for a CompilationListener in GraalTruffleRuntime. diff -r d7e40b20b030 -r c5c80abc3fc6 graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java --- 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 diff -r d7e40b20b030 -r c5c80abc3fc6 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleCompilationListener.java --- /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); +} diff -r d7e40b20b030 -r c5c80abc3fc6 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java --- 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 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 iterateFrames(FrameInstanceVisitor 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)); + } + + } } diff -r d7e40b20b030 -r c5c80abc3fc6 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java --- 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) { diff -r d7e40b20b030 -r c5c80abc3fc6 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- 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,