Mercurial > hg > truffle
changeset 14027:aba77882e314
be more careful with clinit of CompilationTask
author | Tom Rodriguez <tom.rodriguez@oracle.com> |
---|---|
date | Wed, 26 Feb 2014 11:10:27 -0800 |
parents | 57a2d00ef771 |
children | fad977c86a88 |
files | graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java |
diffstat | 2 files changed, 27 insertions(+), 18 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Wed Feb 26 15:56:11 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Wed Feb 26 11:10:27 2014 -0800 @@ -30,6 +30,7 @@ import static com.oracle.graal.phases.GraalOptions.*; import static com.oracle.graal.phases.common.InliningUtil.*; +import java.io.*; import java.lang.reflect.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; @@ -52,9 +53,14 @@ public class CompilationTask implements Runnable, Comparable { + // Keep static finals in a group with withinEnqueue as the last one. CompilationTask can be + // called from within it's own clinit so it needs to be careful about accessing state. Once + // withinEnqueue is non-null we assume that CompilationTask is fully initialized. + private static final AtomicLong uniqueTaskIds = new AtomicLong(); + private static final DebugMetric BAILOUTS = Debug.metric("Bailouts"); - public static final ThreadLocal<Boolean> withinEnqueue = new ThreadLocal<Boolean>() { + private static final ThreadLocal<Boolean> withinEnqueue = new ThreadLocal<Boolean>() { @Override protected Boolean initialValue() { @@ -62,6 +68,22 @@ } }; + public static final boolean isWithinEnqueue() { + // It's possible this can be called before the <clinit> has completed so check for null + return withinEnqueue == null || withinEnqueue.get(); + } + + public static class BeginEnqueue implements Closeable { + public BeginEnqueue() { + assert !withinEnqueue.get(); + withinEnqueue.set(Boolean.TRUE); + } + + public void close() { + withinEnqueue.set(Boolean.FALSE); + } + } + private enum CompilationStatus { Queued, Running, Finished } @@ -74,8 +96,6 @@ private StructuredGraph graph; - private static final AtomicLong uniqueTaskIds = new AtomicLong(); - /** * A long representing the sequence number of this task. Used for sorting the compile queue. */
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Wed Feb 26 15:56:11 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Wed Feb 26 11:10:27 2014 -0800 @@ -248,14 +248,10 @@ // Compile until the queue is empty. int z = 0; while (true) { - try { - assert !CompilationTask.withinEnqueue.get(); - CompilationTask.withinEnqueue.set(Boolean.TRUE); + try (CompilationTask.BeginEnqueue beginEnqueue = new CompilationTask.BeginEnqueue()) { if (compileQueue.getCompletedTaskCount() >= Math.max(3, compileQueue.getTaskCount())) { break; } - } finally { - CompilationTask.withinEnqueue.set(Boolean.FALSE); } Thread.sleep(100); @@ -325,9 +321,7 @@ } public void shutdownCompiler() throws Exception { - try { - assert !CompilationTask.withinEnqueue.get(); - CompilationTask.withinEnqueue.set(Boolean.TRUE); + try (CompilationTask.BeginEnqueue beginEnqueue = new CompilationTask.BeginEnqueue()) { // We have to use a privileged action here because shutting down the compiler might be // called from user code which very likely contains unprivileged frames. AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { @@ -336,8 +330,6 @@ return null; } }); - } finally { - CompilationTask.withinEnqueue.set(Boolean.FALSE); } printDebugValues(ResetDebugValuesAfterBootstrap.getValue() ? "application" : null, false); @@ -537,7 +529,7 @@ return; } - if (CompilationTask.withinEnqueue.get()) { + if (CompilationTask.isWithinEnqueue()) { // This is required to avoid deadlocking a compiler thread. The issue is that a // java.util.concurrent.BlockingQueue is used to implement the compilation worker // queues. If a compiler thread triggers a compilation, then it may be blocked trying @@ -547,8 +539,7 @@ // Don't allow blocking compiles from CompilerThreads boolean block = blocking && !(Thread.currentThread() instanceof CompilerThread); - CompilationTask.withinEnqueue.set(Boolean.TRUE); - try { + try (CompilationTask.BeginEnqueue beginEnqueue = new CompilationTask.BeginEnqueue()) { if (method.tryToQueueForCompilation()) { assert method.isQueuedForCompilation(); @@ -565,8 +556,6 @@ // The compile queue was already shut down. } } - } finally { - CompilationTask.withinEnqueue.set(Boolean.FALSE); } }