changeset 12594:890bea7925fd

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Thu, 17 Oct 2013 16:01:04 +0200
parents 561217cf2ac5 (diff) 237aff48d57e (current diff)
children 36f39d0c9875
files graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntimeFactory.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotGraalRuntime.java graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotGraalRuntime.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntimeFactory.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotForeignCallsProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java
diffstat 6 files changed, 170 insertions(+), 104 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java	Wed Oct 16 11:46:05 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java	Thu Oct 17 16:01:04 2013 +0200
@@ -84,8 +84,20 @@
         return getObjectUnsafe(slot);
     }
 
+    private Object[] getLocals() {
+        return CompilerDirectives.unsafeCast(locals, Object[].class, true);
+    }
+
+    private long[] getPrimitiveLocals() {
+        return CompilerDirectives.unsafeCast(this.primitiveLocals, long[].class, true);
+    }
+
+    private byte[] getTags() {
+        return CompilerDirectives.unsafeCast(tags, byte[].class, true);
+    }
+
     private Object getObjectUnsafe(FrameSlot slot) {
-        return CompilerDirectives.unsafeGetObject(locals, (long) slot.getIndex() * Unsafe.ARRAY_OBJECT_INDEX_SCALE + Unsafe.ARRAY_OBJECT_BASE_OFFSET, true, slot);
+        return CompilerDirectives.unsafeGetObject(getLocals(), (long) slot.getIndex() * Unsafe.ARRAY_OBJECT_INDEX_SCALE + Unsafe.ARRAY_OBJECT_BASE_OFFSET, true, slot);
     }
 
     @Override
@@ -95,7 +107,7 @@
     }
 
     private void setObjectUnsafe(FrameSlot slot, Object value) {
-        CompilerDirectives.unsafePutObject(locals, (long) slot.getIndex() * Unsafe.ARRAY_OBJECT_INDEX_SCALE + Unsafe.ARRAY_OBJECT_BASE_OFFSET, value, slot);
+        CompilerDirectives.unsafePutObject(getLocals(), (long) slot.getIndex() * Unsafe.ARRAY_OBJECT_INDEX_SCALE + Unsafe.ARRAY_OBJECT_BASE_OFFSET, value, slot);
     }
 
     @Override
@@ -105,7 +117,7 @@
     }
 
     private byte getByteUnsafe(FrameSlot slot) {
-        return CompilerDirectives.unsafeGetByte(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot);
+        return CompilerDirectives.unsafeGetByte(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot);
     }
 
     @Override
@@ -115,7 +127,7 @@
     }
 
     private void setByteUnsafe(FrameSlot slot, byte value) {
-        CompilerDirectives.unsafePutByte(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value, slot);
+        CompilerDirectives.unsafePutByte(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value, slot);
     }
 
     @Override
@@ -125,7 +137,7 @@
     }
 
     private boolean getBooleanUnsafe(FrameSlot slot) {
-        return CompilerDirectives.unsafeGetBoolean(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot);
+        return CompilerDirectives.unsafeGetBoolean(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot);
     }
 
     @Override
@@ -135,7 +147,7 @@
     }
 
     private void setBooleanUnsafe(FrameSlot slot, boolean value) {
-        CompilerDirectives.unsafePutBoolean(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value, slot);
+        CompilerDirectives.unsafePutBoolean(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value, slot);
     }
 
     @Override
@@ -145,7 +157,7 @@
     }
 
     private float getFloatUnsafe(FrameSlot slot) {
-        return CompilerDirectives.unsafeGetFloat(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot);
+        return CompilerDirectives.unsafeGetFloat(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot);
     }
 
     @Override
@@ -155,7 +167,7 @@
     }
 
     private void setFloatUnsafe(FrameSlot slot, float value) {
-        CompilerDirectives.unsafePutFloat(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value, slot);
+        CompilerDirectives.unsafePutFloat(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value, slot);
     }
 
     @Override
@@ -165,7 +177,7 @@
     }
 
     private long getLongUnsafe(FrameSlot slot) {
-        return CompilerDirectives.unsafeGetLong(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot);
+        return CompilerDirectives.unsafeGetLong(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot);
     }
 
     @Override
@@ -175,7 +187,7 @@
     }
 
     private void setLongUnsafe(FrameSlot slot, long value) {
-        CompilerDirectives.unsafePutLong(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value, slot);
+        CompilerDirectives.unsafePutLong(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value, slot);
     }
 
     @Override
@@ -185,7 +197,7 @@
     }
 
     private int getIntUnsafe(FrameSlot slot) {
-        return CompilerDirectives.unsafeGetInt(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot);
+        return CompilerDirectives.unsafeGetInt(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot);
     }
 
     @Override
@@ -195,7 +207,7 @@
     }
 
     private void setIntUnsafe(FrameSlot slot, int value) {
-        CompilerDirectives.unsafePutInt(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value, slot);
+        CompilerDirectives.unsafePutInt(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value, slot);
     }
 
     @Override
@@ -205,7 +217,7 @@
     }
 
     private double getDoubleUnsafe(FrameSlot slot) {
-        return CompilerDirectives.unsafeGetDouble(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot);
+        return CompilerDirectives.unsafeGetDouble(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot);
     }
 
     @Override
@@ -215,7 +227,7 @@
     }
 
     private void setDoubleUnsafe(FrameSlot slot, double value) {
-        CompilerDirectives.unsafePutDouble(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value, slot);
+        CompilerDirectives.unsafePutDouble(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value, slot);
     }
 
     @Override
@@ -225,25 +237,25 @@
 
     private void verifySet(FrameSlot slot, FrameSlotKind accessKind) {
         int slotIndex = slot.getIndex();
-        if (slotIndex >= tags.length) {
+        if (slotIndex >= getTags().length) {
             CompilerDirectives.transferToInterpreter();
             resize();
         }
-        tags[slotIndex] = (byte) accessKind.ordinal();
+        getTags()[slotIndex] = (byte) accessKind.ordinal();
     }
 
     private void verifyGet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException {
         int slotIndex = slot.getIndex();
-        if (slotIndex >= tags.length) {
+        if (slotIndex >= getTags().length) {
             CompilerDirectives.transferToInterpreter();
             resize();
         }
-        byte tag = this.tags[slotIndex];
+        byte tag = this.getTags()[slotIndex];
         if (accessKind == FrameSlotKind.Object ? tag != 0 : tag != accessKind.ordinal()) {
             CompilerDirectives.transferToInterpreter();
             if (slot.getKind() == accessKind || tag == 0) {
                 descriptor.getTypeConversion().updateFrameSlot(this, slot, getValue(slot));
-                if (tags[slotIndex] == accessKind.ordinal()) {
+                if (getTags()[slotIndex] == accessKind.ordinal()) {
                     return;
                 }
             }
@@ -254,11 +266,11 @@
     @Override
     public Object getValue(FrameSlot slot) {
         int slotIndex = slot.getIndex();
-        if (slotIndex >= tags.length) {
+        if (slotIndex >= getTags().length) {
             CompilerDirectives.transferToInterpreter();
             resize();
         }
-        byte tag = tags[slotIndex];
+        byte tag = getTags()[slotIndex];
         if (tag == FrameSlotKind.Boolean.ordinal()) {
             return getBooleanUnsafe(slot);
         } else if (tag == FrameSlotKind.Byte.ordinal()) {
@@ -291,10 +303,10 @@
     @Override
     public boolean isInitialized(FrameSlot slot) {
         int slotIndex = slot.getIndex();
-        if (slotIndex >= tags.length) {
+        if (slotIndex >= getTags().length) {
             CompilerDirectives.transferToInterpreter();
             resize();
         }
-        return tags[slotIndex] != 0;
+        return getTags()[slotIndex] != 0;
     }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Wed Oct 16 11:46:05 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Thu Oct 17 16:01:04 2013 +0200
@@ -26,10 +26,10 @@
 
 import java.io.*;
 import java.util.*;
+import java.util.concurrent.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.hotspot.meta.*;
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.impl.*;
@@ -54,21 +54,22 @@
         }
     }
 
-    private HotSpotNmethod compiledMethod;
+    private InstalledCode installedCode;
+    private Future<InstalledCode> installedCodeTask;
     private final TruffleCompiler compiler;
     private final CompilationPolicy compilationPolicy;
+    private boolean disableCompilation;
+    private int callCount;
 
-    private boolean disableCompilation;
-
-    private int callCount;
+    /**
+     * Number of times an installed code for this tree was invalidated.
+     */
     private int invalidationCount;
-    private int replaceCount;
-    long timeCompilationStarted;
-    long timePartialEvaluationFinished;
-    long timeCompilationFinished;
-    int codeSize;
-    int nodeCountPartialEval;
-    int nodeCountLowered;
+
+    /**
+     * Number of times a node was replaced in this tree.
+     */
+    private int nodeReplaceCount;
 
     @Override
     public Object call(PackedFrame caller, Arguments args) {
@@ -79,9 +80,9 @@
         if (TruffleCallTargetProfiling.getValue()) {
             callCount++;
         }
-        if (CompilerDirectives.injectBranchProbability(CompilerDirectives.FASTPATH_PROBABILITY, compiledMethod != null)) {
+        if (CompilerDirectives.injectBranchProbability(CompilerDirectives.FASTPATH_PROBABILITY, installedCode != null)) {
             try {
-                return compiledMethod.execute(this, caller, args);
+                return installedCode.execute(this, caller, args);
             } catch (InvalidInstalledCodeException ex) {
                 return compiledCodeInvalidated(caller, args);
             }
@@ -91,15 +92,28 @@
     }
 
     private Object compiledCodeInvalidated(PackedFrame caller, Arguments args) {
-        CompilerAsserts.neverPartOfCompilation();
-        compiledMethod = null;
-        invalidationCount++;
-        compilationPolicy.compilationInvalidated();
-        if (TraceTruffleCompilation.getValue()) {
-            OUT.printf("[truffle] invalidated %-48s |Alive %5.0fms |Inv# %d                                     |Replace# %d\n", rootNode, (System.nanoTime() - timeCompilationFinished) / 1e6,
-                            invalidationCount, replaceCount);
+        invalidate();
+        return call(caller, args);
+    }
+
+    private void invalidate() {
+        InstalledCode m = this.installedCode;
+        if (m != null) {
+            CompilerAsserts.neverPartOfCompilation();
+            installedCode = null;
+            invalidationCount++;
+            compilationPolicy.compilationInvalidated();
+            if (TraceTruffleCompilation.getValue()) {
+                OUT.printf("[truffle] invalidated %-48s |Inv# %d                                     |Replace# %d\n", rootNode, invalidationCount, nodeReplaceCount);
+            }
         }
-        return call(caller, args);
+
+        Future<InstalledCode> task = this.installedCodeTask;
+        if (task != null) {
+            task.cancel(true);
+            this.installedCodeTask = null;
+            compilationPolicy.compilationInvalidated();
+        }
     }
 
     private Object interpreterCall(PackedFrame caller, Arguments args) {
@@ -108,19 +122,55 @@
         if (disableCompilation || !compilationPolicy.compileOrInline()) {
             return executeHelper(caller, args);
         } else {
-            compileOrInline();
-            return call(caller, args);
+            return compileOrInline(caller, args);
         }
     }
 
-    private void compileOrInline() {
+    private Object compileOrInline(PackedFrame caller, Arguments args) {
+        if (installedCodeTask != null) {
+            // There is already a compilation running.
+            if (installedCodeTask.isCancelled()) {
+                installedCodeTask = null;
+            } else {
+                if (installedCodeTask.isDone()) {
+                    receiveInstalledCode();
+                }
+                return executeHelper(caller, args);
+            }
+        }
+
         if (TruffleFunctionInlining.getValue() && inline()) {
             compilationPolicy.inlined(MIN_INVOKES_AFTER_INLINING);
+            return call(caller, args);
         } else {
             compile();
+            return executeHelper(caller, args);
         }
     }
 
+    private void receiveInstalledCode() {
+        try {
+            this.installedCode = installedCodeTask.get();
+            if (TruffleCallTargetProfiling.getValue()) {
+                resetProfiling();
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            disableCompilation = true;
+            OUT.printf("[truffle] opt failed %-48s  %s\n", rootNode, e.getMessage());
+            if (e.getCause() instanceof BailoutException) {
+                // Bailout => move on.
+            } else {
+                if (TraceTruffleCompilationExceptions.getValue()) {
+                    e.printStackTrace(OUT);
+                }
+                if (TruffleCompilationExceptionsAreFatal.getValue()) {
+                    System.exit(-1);
+                }
+            }
+        }
+        installedCodeTask = null;
+    }
+
     public boolean inline() {
         CompilerAsserts.neverPartOfCompilation();
         return new InliningHelper(this).inline();
@@ -128,36 +178,9 @@
 
     public void compile() {
         CompilerAsserts.neverPartOfCompilation();
-        try {
-            compiledMethod = (HotSpotNmethod) compiler.compile(this);
-            if (compiledMethod == null) {
-                throw new BailoutException(String.format("code installation failed (codeSize=%s)", codeSize));
-            } else {
-                if (TraceTruffleCompilation.getValue()) {
-                    int nodeCountTruffle = NodeUtil.countNodes(rootNode);
-                    OUT.printf("[truffle] optimized %-50s |Nodes %7d |Time %5.0f(%4.0f+%-4.0f)ms |Nodes %5d/%5d |CodeSize %d\n", rootNode, nodeCountTruffle,
-                                    (timeCompilationFinished - timeCompilationStarted) / 1e6, (timePartialEvaluationFinished - timeCompilationStarted) / 1e6,
-                                    (timeCompilationFinished - timePartialEvaluationFinished) / 1e6, nodeCountPartialEval, nodeCountLowered, codeSize);
-                }
-                if (TruffleCallTargetProfiling.getValue()) {
-                    resetProfiling();
-                }
-            }
-        } catch (Throwable e) {
-            disableCompilation = true;
-            if (TraceTruffleCompilation.getValue()) {
-                if (e instanceof BailoutException) {
-                    OUT.printf("[truffle] opt bailout %-48s  %s\n", rootNode, e.getMessage());
-                } else {
-                    OUT.printf("[truffle] opt failed %-49s  %s\n", rootNode, e.toString());
-                    if (TraceTruffleCompilationExceptions.getValue()) {
-                        e.printStackTrace(OUT);
-                    }
-                    if (TruffleCompilationExceptionsAreFatal.getValue()) {
-                        System.exit(-1);
-                    }
-                }
-            }
+        this.installedCodeTask = compiler.compile(this);
+        if (!TruffleBackgroundCompilation.getValue()) {
+            receiveInstalledCode();
         }
     }
 
@@ -182,13 +205,8 @@
 
     @Override
     public void nodeReplaced() {
-        replaceCount++;
-        if (compiledMethod != null) {
-            if (compiledMethod.isValid()) {
-                compiledMethod.invalidate();
-            }
-            compiledMethod = null;
-        }
+        nodeReplaceCount++;
+        invalidate();
         compilationPolicy.nodeReplaced();
     }
 
@@ -402,7 +420,7 @@
             int notInlinedCallSiteCount = InliningHelper.getInlinableCallSites(callTarget).size();
             int nodeCount = NodeUtil.countNodes(callTarget.rootNode);
             int inlinedCallSiteCount = NodeUtil.countNodes(callTarget.rootNode, InlinedCallSite.class);
-            String comment = callTarget.compiledMethod == null ? " int" : "";
+            String comment = callTarget.installedCode == null ? " int" : "";
             comment += callTarget.disableCompilation ? " fail" : "";
             OUT.printf("%-50s | %10d | %15d | %15d | %10d | %3d%s\n", callTarget.getRootNode(), callTarget.callCount, inlinedCallSiteCount, notInlinedCallSiteCount, nodeCount,
                             callTarget.invalidationCount, comment);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Wed Oct 16 11:46:05 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Thu Oct 17 16:01:04 2013 +0200
@@ -132,6 +132,10 @@
                 // Make sure frame does not escape.
                 expandTree(graph, assumptions);
 
+                if (Thread.interrupted()) {
+                    return;
+                }
+
                 new VerifyFrameDoesNotEscapePhase().apply(graph, false);
 
                 if (TraceTruffleCompilationDetails.getValue() && constantReceivers != null) {
@@ -219,6 +223,10 @@
                     }
                 }
 
+                if (Thread.interrupted()) {
+                    return;
+                }
+
                 if (graph.getNodeCount() > TruffleCompilerOptions.TruffleGraphMaxNodes.getValue()) {
                     throw new BailoutException("Truffle compilation is exceeding maximum node count: " + graph.getNodeCount());
                 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompiler.java	Wed Oct 16 11:46:05 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompiler.java	Thu Oct 17 16:01:04 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.truffle;
 
+import java.util.concurrent.*;
+
 import com.oracle.graal.api.code.*;
 
 /**
@@ -30,5 +32,5 @@
  */
 public interface TruffleCompiler {
 
-    InstalledCode compile(OptimizedCallTarget node);
+    Future<InstalledCode> compile(OptimizedCallTarget node);
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Wed Oct 16 11:46:05 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Thu Oct 17 16:01:04 2013 +0200
@@ -23,7 +23,9 @@
 package com.oracle.graal.truffle;
 
 import static com.oracle.graal.api.code.CodeUtil.*;
+import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
 
+import java.io.*;
 import java.util.*;
 import java.util.concurrent.*;
 
@@ -54,6 +56,8 @@
  */
 public class TruffleCompilerImpl implements TruffleCompiler {
 
+    private static final PrintStream OUT = TTY.out().out();
+
     private final Providers providers;
     private final Suites suites;
     private final PartialEvaluator partialEvaluator;
@@ -61,6 +65,7 @@
     private final ResolvedJavaType[] skippedExceptionTypes;
     private final HotSpotGraalRuntime runtime;
     private final TruffleCache truffleCache;
+    private final ThreadPoolExecutor compileQueue;
 
     private static final Class[] SKIPPED_EXCEPTION_CLASSES = new Class[]{SlowPathException.class, UnexpectedResultException.class, ArithmeticException.class};
 
@@ -75,6 +80,9 @@
         this.runtime = HotSpotGraalRuntime.runtime();
         this.skippedExceptionTypes = getSkippedExceptionTypes(providers.getMetaAccess());
 
+        // Create compilation queue.
+        compileQueue = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), CompilerThread.FACTORY);
+
         final GraphBuilderConfiguration config = GraphBuilderConfiguration.getEagerDefault();
         config.setSkippedExceptionTypes(skippedExceptionTypes);
         this.truffleCache = new TruffleCache(providers, config, TruffleCompilerImpl.Optimizations);
@@ -94,15 +102,22 @@
         return skippedExceptionTypes;
     }
 
-    public InstalledCode compile(final OptimizedCallTarget compilable) {
-        Object[] debug = new Object[]{new DebugDumpScope("Truffle: " + compilable)};
-        return Debug.scope("Truffle", debug, new Callable<InstalledCode>() {
+    public Future<InstalledCode> compile(final OptimizedCallTarget compilable) {
+        Future<InstalledCode> future = compileQueue.submit(new Callable<InstalledCode>() {
 
             @Override
             public InstalledCode call() throws Exception {
-                return compileMethodImpl(compilable);
+                Object[] debug = new Object[]{new DebugDumpScope("Truffle: " + compilable)};
+                return Debug.scope("Truffle", debug, new Callable<InstalledCode>() {
+
+                    @Override
+                    public InstalledCode call() throws Exception {
+                        return compileMethodImpl(compilable);
+                    }
+                });
             }
         });
+        return future;
     }
 
     public static final DebugTimer PartialEvaluationTime = Debug.timer("PartialEvaluationTime");
@@ -115,24 +130,35 @@
         config.setSkippedExceptionTypes(skippedExceptionTypes);
         runtime.evictDeoptedGraphs();
 
-        compilable.timeCompilationStarted = System.nanoTime();
+        long timeCompilationStarted = System.nanoTime();
         Assumptions assumptions = new Assumptions(true);
         try (TimerCloseable a = PartialEvaluationTime.start()) {
             graph = partialEvaluator.createGraph(compilable, assumptions);
         }
-        compilable.timePartialEvaluationFinished = System.nanoTime();
-        compilable.nodeCountPartialEval = graph.getNodeCount();
-        InstalledCode compiledMethod = compileMethodHelper(graph, config, compilable, assumptions);
-        compilable.timeCompilationFinished = System.nanoTime();
-        compilable.nodeCountLowered = graph.getNodeCount();
+        if (Thread.interrupted()) {
+            return null;
+        }
+        long timePartialEvaluationFinished = System.nanoTime();
+        int nodeCountPartialEval = graph.getNodeCount();
+        InstalledCode compiledMethod = compileMethodHelper(graph, config, assumptions);
+        long timeCompilationFinished = System.nanoTime();
+        int nodeCountLowered = graph.getNodeCount();
+
+        if (compiledMethod == null) {
+            throw new BailoutException("Could not install method, code cache is full!");
+        }
+
+        if (TraceTruffleCompilation.getValue()) {
+            int nodeCountTruffle = NodeUtil.countNodes(compilable.getRootNode());
+            System.out.println(compiledMethod.getCode());
+            OUT.printf("[truffle] optimized %-50s %d |Nodes %7d |Time %5.0f(%4.0f+%-4.0f)ms |Nodes %5d/%5d |CodeSize %d\n", compilable.getRootNode(), compilable.hashCode(), nodeCountTruffle,
+                            (timeCompilationFinished - timeCompilationStarted) / 1e6, (timePartialEvaluationFinished - timeCompilationStarted) / 1e6,
+                            (timeCompilationFinished - timePartialEvaluationFinished) / 1e6, nodeCountPartialEval, nodeCountLowered, compiledMethod.getCode().length);
+        }
         return compiledMethod;
     }
 
     public InstalledCode compileMethodHelper(final StructuredGraph graph, final GraphBuilderConfiguration config, final Assumptions assumptions) {
-        return compileMethodHelper(graph, config, null, assumptions);
-    }
-
-    public InstalledCode compileMethodHelper(final StructuredGraph graph, final GraphBuilderConfiguration config, final OptimizedCallTarget compilable, final Assumptions assumptions) {
         final PhasePlan plan = createPhasePlan(config);
 
         Debug.scope("TruffleFinal", graph, new Runnable() {
@@ -193,9 +219,6 @@
         if (Debug.isLogEnabled()) {
             Debug.log(providers.getCodeCache().disassemble(result, compiledMethod));
         }
-        if (compilable != null) {
-            compilable.codeSize = result.getTargetCodeSize();
-        }
         return compiledMethod;
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Wed Oct 16 11:46:05 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Thu Oct 17 16:01:04 2013 +0200
@@ -71,6 +71,9 @@
     public static final OptionValue<Boolean> TruffleUseTimeForCompilationDecision = new OptionValue<>(false);
     @Option(help = "")
     public static final OptionValue<Integer> TruffleCompilationDecisionTime = new OptionValue<>(100);
+    @Option(help = "")
+    public static final OptionValue<Boolean> TruffleBackgroundCompilation = new OptionValue<>(true);
+    
     // tracing
     @Option(help = "")
     public static final OptionValue<Boolean> TraceTruffleCompilation = new OptionValue<>(true);