# HG changeset patch # User Tom Rodriguez # Date 1393441827 28800 # Node ID aba77882e3149d29d8284f7cdae206c0bdd8e548 # Parent 57a2d00ef7718635269c61c623cef296a2c1d8e1 be more careful with clinit of CompilationTask diff -r 57a2d00ef771 -r aba77882e314 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- 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 withinEnqueue = new ThreadLocal() { + private static final ThreadLocal withinEnqueue = new ThreadLocal() { @Override protected Boolean initialValue() { @@ -62,6 +68,22 @@ } }; + public static final boolean isWithinEnqueue() { + // It's possible this can be called before the 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. */ diff -r 57a2d00ef771 -r aba77882e314 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- 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() { @@ -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); } }