changeset 5177:a26b6248d398

added graph caching (-G:+CacheGraphs)
author Lukas Stadler <lukas.stadler@jku.at>
date Thu, 29 Mar 2012 18:55:45 +0200
parents af59b4dfc9e4
children 5715abb8e29a
files graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/graph/GraphCache.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/Compiler.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/BoxingEliminationTest.java graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/EscapeAnalysisTest.java graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/IfBoxingEliminationTest.java graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeExceptionTest.java graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeTest.java graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/MonitorTest.java
diffstat 16 files changed, 272 insertions(+), 104 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Mar 29 18:43:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Mar 29 18:55:45 2012 +0200
@@ -29,6 +29,7 @@
 import com.oracle.graal.alloc.simple.*;
 import com.oracle.graal.compiler.alloc.*;
 import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.graph.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.compiler.schedule.*;
@@ -74,18 +75,29 @@
         this.backend = backend;
     }
 
-    public CiTargetMethod compileMethod(final RiResolvedMethod method, final StructuredGraph graph, int osrBCI, final PhasePlan plan, final OptimisticOptimizations optimisticOpts) {
+
+    public CiTargetMethod compileMethod(final RiResolvedMethod method, final StructuredGraph graph, int osrBCI, final GraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts) {
         assert (method.accessFlags() & Modifier.NATIVE) == 0 : "compiling native methods is not supported";
         if (osrBCI != -1) {
             throw new CiBailout("No OSR supported");
         }
+        if (cache != null) {
+            long[] deoptedGraphs = runtime.getDeoptedLeafGraphIds();
+            if (deoptedGraphs != null) {
+                if (deoptedGraphs.length == 0) {
+                    cache.clear();
+                } else {
+                    cache.removeGraphs(deoptedGraphs);
+                }
+            }
+        }
 
         return Debug.scope("GraalCompiler", new Object[] {graph, method, this}, new Callable<CiTargetMethod>() {
             public CiTargetMethod call() {
                 final CiAssumptions assumptions = GraalOptions.OptAssumptions ? new CiAssumptions() : null;
                 final LIR lir = Debug.scope("FrontEnd", new Callable<LIR>() {
                     public LIR call() {
-                        return emitHIR(graph, assumptions, plan, optimisticOpts);
+                        return emitHIR(graph, assumptions, cache, plan, optimisticOpts);
                     }
                 });
                 final FrameMap frameMap = Debug.scope("BackEnd", lir, new Callable<FrameMap>() {
@@ -105,7 +117,7 @@
     /**
      * Builds the graph, optimizes it.
      */
-    public LIR emitHIR(StructuredGraph graph, CiAssumptions assumptions, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
+    public LIR emitHIR(StructuredGraph graph, CiAssumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
 
         if (graph.start().next() == null) {
             plan.runPhases(PhasePosition.AFTER_PARSING, graph);
@@ -137,7 +149,7 @@
         }
 
         if (GraalOptions.Inline && !plan.isPhaseDisabled(InliningPhase.class)) {
-            new InliningPhase(target, runtime, null, assumptions, plan, optimisticOpts).apply(graph);
+            new InliningPhase(target, runtime, null, assumptions, cache, plan, optimisticOpts).apply(graph);
             new DeadCodeEliminationPhase().apply(graph);
             new PhiStampPhase().apply(graph);
         }
@@ -157,7 +169,7 @@
         }
 
         if (GraalOptions.EscapeAnalysis && !plan.isPhaseDisabled(EscapeAnalysisPhase.class)) {
-            new EscapeAnalysisPhase(target, runtime, assumptions, plan, optimisticOpts).apply(graph);
+            new EscapeAnalysisPhase(target, runtime, assumptions, cache, plan, optimisticOpts).apply(graph);
             new PhiStampPhase().apply(graph);
             if (GraalOptions.OptCanonicalizer) {
                 new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Thu Mar 29 18:43:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Thu Mar 29 18:55:45 2012 +0200
@@ -34,16 +34,12 @@
     private static final boolean ____ = false;
     // Checkstyle: resume
 
-
-
-
     public static int     Threads                            = 4;
     public static boolean Lower                              = true;
 
     // inlining settings
     public static boolean Inline                             = true;
     public static boolean Intrinsify                         = true;
-    public static boolean CacheGraphs                        = ____;
            static boolean InlineMonomorphicCalls             = true;
            static boolean InlinePolymorphicCalls             = true;
            static boolean InlineMegamorphicCalls             = ____;
@@ -93,6 +89,11 @@
     public static boolean SlowCompileThreads                 = false;
     public static boolean DynamicCompilePriority             = true;
 
+    // graph caching
+    public static boolean CacheGraphs                        = true;
+    public static int     GraphCacheSize                     = 1000;
+    public static boolean PrintGraphCache                    = ____;
+
     //rematerialize settings
     public static float   MinimumUsageProbability            = 0.95f;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/graph/GraphCache.java	Thu Mar 29 18:55:45 2012 +0200
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.graph;
+
+import java.io.*;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.max.cri.ri.*;
+
+public class GraphCache {
+    private static final PrintStream out = System.out;
+    private final boolean dump;
+    private boolean enabled = true;
+
+    private final AtomicLong hitCounter = new AtomicLong();
+    private final AtomicLong missCounter = new AtomicLong();
+    private final AtomicLong removeHitCounter = new AtomicLong();
+    private final AtomicLong removeMissCounter = new AtomicLong();
+    private final AtomicLong putCounter = new AtomicLong();
+
+    private class LRUCache extends LinkedHashMap<RiResolvedMethod, Long> {
+        private static final long serialVersionUID = -3973307040793397840L;
+
+        public LRUCache(int initialCapacity) {
+            super(initialCapacity * 2, 0.75f, false);
+        }
+        @Override
+        protected boolean removeEldestEntry(Entry<RiResolvedMethod, Long> eldest) {
+            if (size() > GraalOptions.GraphCacheSize) {
+                graphs.remove(eldest.getValue());
+                cachedGraphIds.remove(eldest.getKey());
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+    }
+
+    private final Map<RiResolvedMethod, Long> currentGraphIds = Collections.synchronizedMap(new LRUCache(GraalOptions.GraphCacheSize));
+
+    private final ConcurrentHashMap<Long, StructuredGraph> graphs = new ConcurrentHashMap<>();
+    private final ConcurrentHashMap<Long, RiResolvedMethod> cachedGraphIds = new ConcurrentHashMap<>();
+
+
+    public GraphCache(boolean dump) {
+        this.dump = dump;
+
+        if (dump) {
+            Runtime.getRuntime().addShutdownHook(new Thread() {
+                @Override
+                public void run() {
+                    out.println("put: " + putCounter.get());
+                    out.println("get hit: " + hitCounter.get());
+                    out.println("get miss: " + missCounter.get());
+                    out.println("remove hit: " + removeHitCounter.get());
+                    out.println("remove miss: " + removeMissCounter.get());
+                }
+            });
+        }
+    }
+
+    public void enable() {
+        enabled = true;
+    }
+
+    public StructuredGraph get(RiResolvedMethod method) {
+        if (!enabled) {
+            return null;
+        }
+        Long currentId = currentGraphIds.get(method);
+        StructuredGraph result = null;
+        if (currentId != null) {
+            result = graphs.get(currentId);
+        }
+
+        if (dump) {
+            if (result == null) {
+                missCounter.incrementAndGet();
+            } else {
+                hitCounter.incrementAndGet();
+            }
+//            if (result == null) {
+//                out.println("miss: " + missCounter.incrementAndGet() + " " + method);
+//            } else {
+//                out.println("hit: " + hitCounter.incrementAndGet() + " " + method);
+//            }
+        }
+        return result;
+    }
+
+    public void put(StructuredGraph graph) {
+        if (!enabled) {
+            return;
+        }
+        assert graph.method() != null;
+        Long currentId = currentGraphIds.get(graph.method());
+        if (currentId != null) {
+            graphs.remove(currentId);
+            cachedGraphIds.remove(currentId);
+        }
+        currentGraphIds.put(graph.method(), graph.graphId());
+        cachedGraphIds.put(graph.graphId(), graph.method());
+        graphs.put(graph.graphId(), graph);
+
+        if (dump) {
+            putCounter.incrementAndGet();
+//            out.println("put: " + putCounter.incrementAndGet() + " (size: " + graphs.size() + ")");
+        }
+    }
+
+    public void clear() {
+        graphs.clear();
+        currentGraphIds.clear();
+        cachedGraphIds.clear();
+        hitCounter.set(0);
+        missCounter.set(0);
+        removeHitCounter.set(0);
+        removeMissCounter.set(0);
+        putCounter.set(0);
+    }
+
+    public void removeGraphs(long[] deoptedGraphs) {
+        for (long graphId : deoptedGraphs) {
+            graphs.remove(graphId);
+            RiResolvedMethod method = cachedGraphIds.get(graphId);
+            if (method != null) {
+                cachedGraphIds.remove(graphId);
+                currentGraphIds.remove(method);
+            }
+            if (dump) {
+                if (method != null) {
+                    removeHitCounter.incrementAndGet();
+                } else {
+                    removeMissCounter.incrementAndGet();
+                }
+//                if (method != null) {
+//                    out.println("remove hit: " + removeHitCounter.incrementAndGet() + " (" + graphId + " " + method + ")");
+//                } else {
+//                    out.println("remove miss: " + removeMissCounter.incrementAndGet() + " (" + graphId + ")");
+//                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java	Thu Mar 29 18:43:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java	Thu Mar 29 18:55:45 2012 +0200
@@ -214,13 +214,15 @@
     private final CiTarget target;
     private final GraalRuntime runtime;
     private final CiAssumptions assumptions;
+    private final GraphCache cache;
     private final PhasePlan plan;
     private final OptimisticOptimizations optimisticOpts;
 
-    public EscapeAnalysisPhase(CiTarget target, GraalRuntime runtime, CiAssumptions assumptions, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
+    public EscapeAnalysisPhase(CiTarget target, GraalRuntime runtime, CiAssumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
         this.runtime = runtime;
         this.target = target;
         this.assumptions = assumptions;
+        this.cache = cache;
         this.plan = plan;
         this.optimisticOpts = optimisticOpts;
     }
@@ -389,7 +391,7 @@
             if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
                 TTY.println("Trying inlining to get a non-escaping object for %s", node);
             }
-            new InliningPhase(target, runtime, invokes, assumptions, plan, optimisticOpts).apply(graph);
+            new InliningPhase(target, runtime, invokes, assumptions, cache, plan, optimisticOpts).apply(graph);
             new DeadCodeEliminationPhase().apply(graph);
             if (node.isDeleted()) {
                 if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java	Thu Mar 29 18:43:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java	Thu Mar 29 18:55:45 2012 +0200
@@ -22,11 +22,14 @@
  */
 package com.oracle.graal.compiler.phases;
 
+import java.lang.reflect.*;
 import java.util.*;
+import java.util.concurrent.*;
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.graph.*;
 import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.compiler.util.*;
 import com.oracle.graal.compiler.util.InliningUtil.InlineInfo;
@@ -54,6 +57,7 @@
     private CiAssumptions assumptions;
 
     private final PhasePlan plan;
+    private final GraphCache cache;
     private final WeightComputationPolicy weightComputationPolicy;
     private final InliningPolicy inliningPolicy;
     private final OptimisticOptimizations optimisticOpts;
@@ -63,11 +67,12 @@
     private static final DebugMetric metricInliningConsidered = Debug.metric("InliningConsidered");
     private static final DebugMetric metricInliningStoppedByMaxDesiredSize = Debug.metric("InliningStoppedByMaxDesiredSize");
 
-    public InliningPhase(CiTarget target, GraalRuntime runtime, Collection<? extends Invoke> hints, CiAssumptions assumptions, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
+    public InliningPhase(CiTarget target, GraalRuntime runtime, Collection<? extends Invoke> hints, CiAssumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
         this.target = target;
         this.runtime = runtime;
         this.hints = hints;
         this.assumptions = assumptions;
+        this.cache = cache;
         this.plan = plan;
         this.optimisticOpts = optimisticOpts;
         this.weightComputationPolicy = createWeightComputationPolicy();
@@ -98,9 +103,9 @@
                     if (GraalOptions.OptCanonicalizer) {
                         new CanonicalizerPhase(target, runtime, true, assumptions).apply(graph);
                     }
-                    if (GraalOptions.Intrinsify) {
-                        new IntrinsificationPhase(runtime).apply(graph);
-                    }
+//                    if (GraalOptions.Intrinsify) {
+//                        new IntrinsificationPhase(runtime).apply(graph);
+//                    }
                     metricInliningPerformed.increment();
                 } catch (CiBailout bailout) {
                     // TODO determine if we should really bail out of the whole compilation.
@@ -151,23 +156,47 @@
 
     public static final Map<RiMethod, Integer> parsedMethods = new HashMap<>();
 
+
+
+    private static final DebugMetric metricInliningRuns = Debug.metric("Runs");
+
     @Override
-    public StructuredGraph buildGraph(RiResolvedMethod method) {
-        StructuredGraph newGraph = new StructuredGraph(method);
+    public StructuredGraph buildGraph(final RiResolvedMethod method) {
+        final StructuredGraph newGraph = new StructuredGraph(method);
+
+        return Debug.scope("buildInlineGraph", this, new Callable<StructuredGraph>() {
 
-        if (plan != null) {
-            plan.runPhases(PhasePosition.AFTER_PARSING, newGraph);
-        }
-        assert newGraph.start().next() != null : "graph needs to be populated during PhasePosition.AFTER_PARSING";
+            public StructuredGraph call() {
+                metricInliningRuns.increment();
+                if (GraalOptions.CacheGraphs && cache != null) {
+                    StructuredGraph cachedGraph = cache.get(method);
+                    if (cachedGraph != null) {
+                        return cachedGraph;
+                    }
+                }
+
 
-        if (GraalOptions.ProbabilityAnalysis) {
-            new DeadCodeEliminationPhase().apply(newGraph);
-            new ComputeProbabilityPhase().apply(newGraph);
-        }
-        if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(target, runtime, assumptions).apply(newGraph);
-        }
-        return newGraph;
+                if (plan != null) {
+                    plan.runPhases(PhasePosition.AFTER_PARSING, newGraph);
+                }
+                assert newGraph.start().next() != null : "graph needs to be populated during PhasePosition.AFTER_PARSING";
+
+                if (GraalOptions.ProbabilityAnalysis) {
+                    new DeadCodeEliminationPhase().apply(newGraph);
+                    new ComputeProbabilityPhase().apply(newGraph);
+                }
+                if (GraalOptions.OptCanonicalizer) {
+                    new CanonicalizerPhase(target, runtime, assumptions).apply(newGraph);
+                }
+                if (GraalOptions.Intrinsify) {
+                    new IntrinsificationPhase(runtime).apply(newGraph);
+                }
+                if (GraalOptions.CacheGraphs && cache != null) {
+                    cache.put(newGraph);
+                }
+                return newGraph;
+            }
+        });
     }
 
     @Override
@@ -230,9 +259,9 @@
         }
     }
 
-    private WeightComputationPolicy createWeightComputationPolicy() {
+    private static WeightComputationPolicy createWeightComputationPolicy() {
         switch(GraalOptions.WeightComputationPolicy) {
-            case 0: return new ExecutionCountBasedWeightComputationPolicy();
+            case 0: throw new GraalInternalError("removed because of invokation counter changes");
             case 1: return new BytecodeSizeBasedWeightComputationPolicy();
             case 2: return new ComplexityBasedWeightComputationPolicy();
             default:
@@ -315,7 +344,7 @@
             double maxSize = GraalOptions.MaximumGreedyInlineSize;
             if (GraalOptions.InliningBonusPerTransferredValue != 0) {
                 RiSignature signature = info.invoke.callTarget().targetMethod().signature();
-                int transferredValues = signature.argumentCount(true);
+                int transferredValues = signature.argumentCount(!Modifier.isStatic(info.invoke.callTarget().targetMethod().accessFlags()));
                 if (signature.returnKind(false) != CiKind.Void) {
                     transferredValues++;
                 }
@@ -352,67 +381,6 @@
         double computeWeight(RiResolvedMethod caller, RiResolvedMethod method, Invoke invoke, boolean preferredInvoke);
     }
 
-    private class ExecutionCountBasedWeightComputationPolicy implements WeightComputationPolicy {
-        @Override
-        public double computeWeight(RiResolvedMethod caller, RiResolvedMethod method, Invoke invoke, boolean preferredInvoke) {
-            double ratio;
-            if (preferredInvoke) {
-                ratio = 1000000;
-            } else {
-                if (GraalOptions.ProbabilityAnalysis) {
-                    ratio = invoke.node().probability();
-                } else {
-                    RiProfilingInfo profilingInfo = method.profilingInfo();
-                    int executionCount = profilingInfo.getExecutionCount(invoke.bci());
-                    if (executionCount > 0) {
-                        RiResolvedMethod parent = invoke.stateAfter().method();
-                        ratio = executionCount / (float) parent.invocationCount();
-                    } else {
-                        ratio = 1;
-                    }
-                }
-            }
-
-            final double normalSize;
-            // TODO (lstadler) get rid of this magic, it's here to emulate the old behavior for the time being
-            if (ratio < 0.01) {
-                ratio = 0.01;
-            }
-            if (ratio < 0.5) {
-                normalSize = 10 * ratio / 0.5;
-            } else if (ratio < 2) {
-                normalSize = 10 + (35 - 10) * (ratio - 0.5) / 1.5;
-            } else if (ratio < 20) {
-                normalSize = 35;
-            } else if (ratio < 40) {
-                normalSize = 35 + (350 - 35) * (ratio - 20) / 20;
-            } else {
-                normalSize = 350;
-            }
-
-            int count;
-            if (GraalOptions.ParseBeforeInlining) {
-                if (!parsedMethods.containsKey(method)) {
-                    StructuredGraph newGraph = new StructuredGraph(method);
-                    if (plan != null) {
-                        plan.runPhases(PhasePosition.AFTER_PARSING, newGraph);
-                    }
-                    if (GraalOptions.OptCanonicalizer) {
-                        new CanonicalizerPhase(target, runtime, assumptions).apply(newGraph);
-                    }
-                    count = graphComplexity(newGraph);
-                    parsedMethods.put(method, count);
-                } else {
-                    count = parsedMethods.get(method);
-                }
-            } else {
-                count = method.codeSize();
-            }
-
-            return count / normalSize;
-        }
-    }
-
     private static class BytecodeSizeBasedWeightComputationPolicy implements WeightComputationPolicy {
         @Override
         public double computeWeight(RiResolvedMethod caller, RiResolvedMethod method, Invoke invoke, boolean preferredInvoke) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu Mar 29 18:43:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu Mar 29 18:55:45 2012 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.hotspot;
 
-import java.io.*;
 import java.util.concurrent.*;
 
 import com.oracle.graal.compiler.*;
@@ -71,7 +70,7 @@
         cancelled = true;
     }
 
-    private static PrintStream out = System.out;
+//    private static PrintStream out = System.out;
 
     public void run() {
         if (cancelled) {
@@ -99,7 +98,7 @@
                     @Override
                     public CiTargetMethod call() throws Exception {
                         StructuredGraph graph = new StructuredGraph(method);
-                        return compiler.getCompiler().compileMethod(method, graph, -1, plan, optimisticOpts);
+                        return compiler.getCompiler().compileMethod(method, graph, -1, compiler.getCache(), plan, optimisticOpts);
                     }
                 });
             } finally {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/Compiler.java	Thu Mar 29 18:43:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/Compiler.java	Thu Mar 29 18:55:45 2012 +0200
@@ -25,6 +25,7 @@
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.graph.*;
 import com.oracle.graal.cri.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.ri.*;
@@ -38,5 +39,6 @@
     HotSpotVMConfig getConfig();
     GraalRuntime getRuntime();
     CiTarget getTarget();
+    GraphCache getCache();
 
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerImpl.java	Thu Mar 29 18:43:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerImpl.java	Thu Mar 29 18:55:45 2012 +0200
@@ -30,6 +30,7 @@
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.cri.xir.*;
 import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.graph.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.cri.*;
 import com.oracle.graal.hotspot.bridge.*;
@@ -91,6 +92,7 @@
     private HotSpotRuntime runtime;
     private GraalCompiler compiler;
     private CiTarget target;
+    private volatile GraphCache cache;
 
     private final HotSpotVMConfig config;
 
@@ -161,11 +163,19 @@
             generator.initialize(backend.newXirAssembler());
 
             compiler = new GraalCompiler(getRuntime(), getTarget(), backend, generator);
+            if (GraalOptions.CacheGraphs) {
+                cache = new GraphCache(GraalOptions.PrintGraphCache);
+            }
         }
         return compiler;
     }
 
     @Override
+    public GraphCache getCache() {
+        return cache;
+    }
+
+    @Override
     public CompilerToVM getVMEntries() {
         return vmEntries;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Thu Mar 29 18:43:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Thu Mar 29 18:55:45 2012 +0200
@@ -191,6 +191,10 @@
         CiCompilationStatistics.clear("bootstrap");
 
         TTY.println(" in %d ms", System.currentTimeMillis() - startTime);
+        if (compiler.getCache() != null) {
+            compiler.getCache().clear();
+            compiler.getCache().enable();
+        }
         System.gc();
         CiCompilationStatistics.clear("bootstrap2");
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Thu Mar 29 18:43:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Thu Mar 29 18:55:45 2012 +0200
@@ -453,7 +453,7 @@
         final PhasePlan plan = new PhasePlan();
         GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime(), GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
         plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
-        return compiler.getCompiler().compileMethod(method, graph, -1, plan, OptimisticOptimizations.ALL);
+        return compiler.getCompiler().compileMethod(method, graph, -1, compiler.getCache(), plan, OptimisticOptimizations.ALL);
     }
 
     @Override
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/BoxingEliminationTest.java	Thu Mar 29 18:43:30 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/BoxingEliminationTest.java	Thu Mar 29 18:55:45 2012 +0200
@@ -125,7 +125,7 @@
                     hints.add(invoke);
                 }
 
-                new InliningPhase(null, runtime(), hints, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
+                new InliningPhase(null, runtime(), hints, null, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
                 new CanonicalizerPhase(null, runtime(), null).apply(graph);
                 Debug.dump(graph, "Graph");
                 new BoxingEliminationPhase().apply(graph);
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/EscapeAnalysisTest.java	Thu Mar 29 18:43:30 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/EscapeAnalysisTest.java	Thu Mar 29 18:55:45 2012 +0200
@@ -122,10 +122,10 @@
             n.node().setProbability(100000);
         }
 
-        new InliningPhase(null, runtime(), null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+        new InliningPhase(null, runtime(), null, null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
         Debug.dump(graph, "Graph");
-        new EscapeAnalysisPhase(null, runtime(), null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+        new EscapeAnalysisPhase(null, runtime(), null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
         Debug.dump(graph, "Graph");
         int retCount = 0;
         for (ReturnNode ret : graph.getNodes(ReturnNode.class)) {
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/IfBoxingEliminationTest.java	Thu Mar 29 18:43:30 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/IfBoxingEliminationTest.java	Thu Mar 29 18:55:45 2012 +0200
@@ -85,7 +85,7 @@
                 for (Invoke invoke : graph.getInvokes()) {
                     hints.add(invoke);
                 }
-                new InliningPhase(null, runtime(), hints, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
+                new InliningPhase(null, runtime(), hints, null, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
                 new CanonicalizerPhase(null, runtime(), null).apply(graph);
                 new PhiStampPhase().apply(graph);
                 new CanonicalizerPhase(null, runtime(), null).apply(graph);
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeExceptionTest.java	Thu Mar 29 18:43:30 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeExceptionTest.java	Thu Mar 29 18:55:45 2012 +0200
@@ -63,7 +63,7 @@
         for (Invoke invoke : graph.getInvokes()) {
             hints.add(invoke);
         }
-        new InliningPhase(null, runtime(), hints, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+        new InliningPhase(null, runtime(), hints, null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
         new CanonicalizerPhase(null, runtime(), null).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
     }
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeTest.java	Thu Mar 29 18:43:30 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeTest.java	Thu Mar 29 18:55:45 2012 +0200
@@ -82,7 +82,7 @@
         for (Invoke invoke : graph.getInvokes()) {
             hints.add(invoke);
         }
-        new InliningPhase(null, runtime(), hints, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+        new InliningPhase(null, runtime(), hints, null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
         new CanonicalizerPhase(null, runtime(), null).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
         StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/MonitorTest.java	Thu Mar 29 18:43:30 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/MonitorTest.java	Thu Mar 29 18:55:45 2012 +0200
@@ -94,7 +94,7 @@
         for (Invoke invoke : graph.getInvokes()) {
             hints.add(invoke);
         }
-        new InliningPhase(null, runtime(), hints, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+        new InliningPhase(null, runtime(), hints, null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
         new CanonicalizerPhase(null, runtime(), null).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
         return graph;