changeset 5176:af59b4dfc9e4

compilation queue changes: * new CiCompilationStatistics * added new HotSpot compilation policy (-XX:CompilationPolicyChoice=4) * compile queue prioritizing (-G:+PriorityCompileQueue) * low-priority compilation threads (-G:+SlowCompileThreads) * dynamic compilation thread priority adjustment (-G:+DynamicCompilePriority)
author Lukas Stadler <lukas.stadler@jku.at>
date Thu, 29 Mar 2012 18:43:30 +0200
parents a8c5283a835c
children a26b6248d398
files graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.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/HotSpotMethodResolved.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolvedImpl.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectFieldNode.java graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiCompilationStatistics.java hotspot/.cproject hotspot/.project src/cpu/x86/vm/templateInterpreter_x86_64.cpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/graal/graalCompiler.cpp src/share/vm/graal/graalVMToCompiler.cpp src/share/vm/graal/graalVMToCompiler.hpp src/share/vm/oops/methodKlass.cpp src/share/vm/oops/methodOop.hpp src/share/vm/runtime/arguments.cpp src/share/vm/runtime/compilationPolicy.cpp src/share/vm/runtime/compilationPolicy.hpp
diffstat 22 files changed, 646 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Thu Mar 29 13:23:34 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Thu Mar 29 18:43:30 2012 +0200
@@ -87,6 +87,12 @@
     public static int     MatureExecutionsPerSwitchCase      = 1;
     public static int     MatureExecutionsTypeProfile        = 1;
 
+    // comilation queue
+    public static boolean PriorityCompileQueue               = true;
+    public static int     SlowQueueCutoff                    = 100000;
+    public static boolean SlowCompileThreads                 = false;
+    public static boolean DynamicCompilePriority             = true;
+
     //rematerialize settings
     public static float   MinimumUsageProbability            = 0.95f;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu Mar 29 13:23:34 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu Mar 29 18:43:30 2012 +0200
@@ -22,40 +22,73 @@
  */
 package com.oracle.graal.hotspot;
 
+import java.io.*;
 import java.util.concurrent.*;
 
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.hotspot.ri.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.criutils.*;
 
 
-public final class CompilationTask implements Runnable {
+public final class CompilationTask implements Runnable, Comparable<CompilationTask> {
+
+    private volatile boolean cancelled;
 
     private final Compiler compiler;
     private final PhasePlan plan;
-    private final RiResolvedMethod method;
+    private final HotSpotMethodResolved method;
     private final OptimisticOptimizations optimisticOpts;
+    private final int id;
+    private final int priority;
 
-    public static CompilationTask create(Compiler compiler, PhasePlan plan, OptimisticOptimizations optimisticOpts, RiResolvedMethod method) {
-        return new CompilationTask(compiler, plan, optimisticOpts, method);
+    public static CompilationTask create(Compiler compiler, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotMethodResolved method, int id, int priority) {
+        return new CompilationTask(compiler, plan, optimisticOpts, method, id, priority);
     }
 
-    private CompilationTask(Compiler compiler, PhasePlan plan, OptimisticOptimizations optimisticOpts, RiResolvedMethod method) {
+    private CompilationTask(Compiler compiler, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotMethodResolved method, int id, int priority) {
         this.compiler = compiler;
         this.plan = plan;
         this.method = method;
         this.optimisticOpts = optimisticOpts;
+        this.id = id;
+        this.priority = priority;
+    }
+
+    public RiResolvedMethod method() {
+        return method;
+    }
+
+    public int priority() {
+        return priority;
     }
 
+    public void cancel() {
+        cancelled = true;
+    }
+
+    private static PrintStream out = System.out;
+
     public void run() {
+        if (cancelled) {
+            return;
+        }
+        if (GraalOptions.DynamicCompilePriority) {
+            int threadPriority = priority < GraalOptions.SlowQueueCutoff ? Thread.NORM_PRIORITY : Thread.MIN_PRIORITY;
+            if (Thread.currentThread().getPriority() != threadPriority) {
+//                out.print(threadPriority);
+                Thread.currentThread().setPriority(threadPriority);
+            }
+        }
+        CiCompilationStatistics stats = CiCompilationStatistics.create(method);
         try {
             final boolean printCompilation = GraalOptions.PrintCompilation && !TTY.isSuppressed();
             if (printCompilation) {
-                TTY.println(String.format("Graal %-70s %-45s %-50s ...", method.holder().name(), method.name(), method.signature().asString()));
+                TTY.println(String.format("%-6d Graal %-70s %-45s %-50s ...", id, method.holder().name(), method.name(), method.signature().asString()));
             }
 
             CiTargetMethod result = null;
@@ -72,7 +105,7 @@
             } finally {
                 filter.remove();
                 if (printCompilation) {
-                    TTY.println(String.format("Graal %-70s %-45s %-50s | %4dnodes %5dB", "", "", "", 0, (result != null ? result.targetCodeSize() : -1)));
+                    TTY.println(String.format("%-6d Graal %-70s %-45s %-50s | %4dnodes %5dB", id, "", "", "", 0, (result != null ? result.targetCodeSize() : -1)));
                 }
             }
             compiler.getRuntime().installMethod(method, result);
@@ -88,6 +121,21 @@
                 System.exit(-1);
             }
         }
+        stats.finish(method);
+        if (method.currentTask() == this) {
+            method.setCurrentTask(null);
+        }
+    }
+
+    @Override
+    public int compareTo(CompilationTask o) {
+        if (priority < o.priority) {
+            return -1;
+        }
+        if (priority > o.priority) {
+            return 1;
+        }
+        return id < o.id ? -1 : (id > o.id ? 1 : 0);
     }
 
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java	Thu Mar 29 13:23:34 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java	Thu Mar 29 18:43:30 2012 +0200
@@ -37,6 +37,15 @@
             return new CompilerThread(r);
         }
     };
+    public static final ThreadFactory LOW_PRIORITY_FACTORY = new ThreadFactory() {
+
+        @Override
+        public Thread newThread(Runnable r) {
+            CompilerThread thread = new CompilerThread(r);
+            thread.setPriority(MIN_PRIORITY);
+            return thread;
+        }
+    };
 
     private CompilerThread(Runnable r) {
         super(r);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Thu Mar 29 13:23:34 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Thu Mar 29 18:43:30 2012 +0200
@@ -32,7 +32,7 @@
  */
 public interface VMToCompiler {
 
-    boolean compileMethod(HotSpotMethodResolved method, int entryBCI, boolean blocking) throws Throwable;
+    boolean compileMethod(HotSpotMethodResolved method, int entryBCI, boolean blocking, int priority) throws Throwable;
 
     void shutdownCompiler() throws Throwable;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Thu Mar 29 13:23:34 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Thu Mar 29 18:43:30 2012 +0200
@@ -26,6 +26,7 @@
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
 
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
@@ -62,6 +63,8 @@
     public final HotSpotTypePrimitive typeVoid;
 
     private ThreadPoolExecutor compileQueue;
+    private ThreadPoolExecutor slowCompileQueue;
+    private AtomicInteger compileTaskIds = new AtomicInteger();
 
     public VMToCompilerImpl(Compiler compiler) {
         this.compiler = compiler;
@@ -92,7 +95,6 @@
             HotSpotDebugConfig hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter);
             Debug.setConfig(hotspotDebugConfig);
         }
-
         // Install intrinsics.
         final HotSpotRuntime runtime = (HotSpotRuntime) compiler.getCompiler().runtime;
         if (GraalOptions.Intrinsify) {
@@ -111,7 +113,23 @@
         }
 
         // Create compilation queue.
-        compileQueue = new ThreadPoolExecutor(GraalOptions.Threads, GraalOptions.Threads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), CompilerThread.FACTORY);
+        final BlockingQueue<Runnable> queue;
+        if (GraalOptions.PriorityCompileQueue) {
+            queue = new PriorityBlockingQueue<>();
+        } else {
+            queue = new LinkedBlockingQueue<>();
+        }
+        compileQueue = new ThreadPoolExecutor(GraalOptions.Threads, GraalOptions.Threads, 0L, TimeUnit.MILLISECONDS, queue, CompilerThread.FACTORY);
+
+        if (GraalOptions.SlowCompileThreads) {
+            final BlockingQueue<Runnable> slowQueue;
+            if (GraalOptions.PriorityCompileQueue) {
+                slowQueue = new PriorityBlockingQueue<>();
+            } else {
+                slowQueue = new LinkedBlockingQueue<>();
+            }
+            slowCompileQueue = new ThreadPoolExecutor(GraalOptions.Threads, GraalOptions.Threads, 0L, TimeUnit.MILLISECONDS, slowQueue, CompilerThread.LOW_PRIORITY_FACTORY);
+        }
 
         // Create queue status printing thread.
         if (GraalOptions.PrintQueue) {
@@ -120,7 +138,11 @@
                 @Override
                 public void run() {
                     while (true) {
-                        TTY.println(compileQueue.toString());
+                        if (slowCompileQueue == null) {
+                            TTY.println(compileQueue.toString());
+                        } else {
+                            TTY.println("fast: " + compileQueue.toString() + " slow: " + slowCompileQueue);
+                        }
                         try {
                             Thread.sleep(1000);
                         } catch (InterruptedException e) {
@@ -157,7 +179,8 @@
 
         // Compile until the queue is empty.
         int z = 0;
-        while (compileQueue.getCompletedTaskCount() < Math.max(3, compileQueue.getTaskCount())) {
+        while (compileQueue.getCompletedTaskCount() < Math.max(3, compileQueue.getTaskCount()) || (
+                        slowCompileQueue != null && slowCompileQueue.getCompletedTaskCount() < Math.max(3, slowCompileQueue.getTaskCount()))) {
             Thread.sleep(100);
             while (z < compileQueue.getCompletedTaskCount() / 100) {
                 ++z;
@@ -165,19 +188,24 @@
                 TTY.flush();
             }
         }
+        CiCompilationStatistics.clear("bootstrap");
 
         TTY.println(" in %d ms", System.currentTimeMillis() - startTime);
         System.gc();
+        CiCompilationStatistics.clear("bootstrap2");
     }
 
     private void enqueue(Method m) throws Throwable {
         RiMethod riMethod = compiler.getRuntime().getRiMethod(m);
         assert !Modifier.isAbstract(((HotSpotMethodResolved) riMethod).accessFlags()) && !Modifier.isNative(((HotSpotMethodResolved) riMethod).accessFlags()) : riMethod;
-        compileMethod((HotSpotMethodResolved) riMethod, 0, false);
+        compileMethod((HotSpotMethodResolved) riMethod, 0, false, 10);
     }
 
     public void shutdownCompiler() throws Throwable {
         compileQueue.shutdown();
+        if (slowCompileQueue != null) {
+            slowCompileQueue.shutdown();
+        }
 
         if (Debug.isEnabled()) {
             List<DebugValueMap> topLevelMaps = DebugValueMap.getTopLevelMaps();
@@ -211,6 +239,7 @@
                 }
             }
         }
+        CiCompilationStatistics.clear("final");
     }
 
     private void flattenChildren(DebugValueMap map, DebugValueMap globalMap) {
@@ -272,7 +301,7 @@
     }
 
     @Override
-    public boolean compileMethod(final HotSpotMethodResolved method, final int entryBCI, boolean blocking) throws Throwable {
+    public boolean compileMethod(final HotSpotMethodResolved method, final int entryBCI, boolean blocking, int priority) throws Throwable {
         if (Thread.currentThread() instanceof CompilerThread) {
             if (method.holder().name().contains("java/util/concurrent")) {
                 // This is required to avoid deadlocking a compiler thread. The issue is that a
@@ -283,13 +312,30 @@
             }
         }
 
+        CompilationTask current = method.currentTask();
+        if (current != null) {
+            if (GraalOptions.PriorityCompileQueue) {
+                // normally compilation tasks will only be re-queued when they get a priority boost, so cancel the old task and add a new one
+                current.cancel();
+            } else {
+                // without a prioritizing compile queue it makes no sense to re-queue the compilation task
+                return true;
+            }
+        }
+
         final OptimisticOptimizations optimisticOpts = new OptimisticOptimizations(method);
-        Runnable task = CompilationTask.create(compiler, createHotSpotSpecificPhasePlan(optimisticOpts), optimisticOpts, method);
+        int id = compileTaskIds.incrementAndGet();
+        CompilationTask task = CompilationTask.create(compiler, createHotSpotSpecificPhasePlan(optimisticOpts), optimisticOpts, method, id, priority);
         if (blocking) {
             task.run();
         } else {
             try {
-                compileQueue.execute(task);
+                method.setCurrentTask(task);
+                if (GraalOptions.SlowCompileThreads && priority > GraalOptions.SlowQueueCutoff) {
+                    slowCompileQueue.execute(task);
+                } else {
+                    compileQueue.execute(task);
+                }
             } catch (RejectedExecutionException e) {
                 // The compile queue was already shut down.
                 return false;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolved.java	Thu Mar 29 13:23:34 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolved.java	Thu Mar 29 18:43:30 2012 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.ri;
 
 import com.oracle.max.cri.ri.*;
+import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.server.*;
 
 public interface HotSpotMethodResolved extends RiResolvedMethod, Remote {
@@ -30,4 +31,7 @@
     RiResolvedMethod uniqueConcreteMethod();
     void dumpProfile();
     int vtableEntryOffset();
+
+    void setCurrentTask(CompilationTask task);
+    CompilationTask currentTask();
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolvedImpl.java	Thu Mar 29 13:23:34 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolvedImpl.java	Thu Mar 29 18:43:30 2012 +0200
@@ -31,6 +31,7 @@
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.criutils.*;
 import com.oracle.graal.compiler.*;
+import com.oracle.graal.hotspot.*;
 import com.oracle.graal.java.bytecode.*;
 
 /**
@@ -59,6 +60,8 @@
     private boolean canBeInlined;
     private int compilationComplexity;
 
+    private CompilationTask currentTask;
+
     private HotSpotMethodResolvedImpl() {
         super(null);
         throw new IllegalStateException("this constructor is never actually called, because the objects are allocated from within the VM");
@@ -362,4 +365,14 @@
     public int vtableEntryOffset() {
         return compiler.getVMEntries().RiMethod_vtableEntryOffset(this);
     }
+
+    @Override
+    public void setCurrentTask(CompilationTask task) {
+        currentTask = task;
+    }
+
+    @Override
+    public CompilationTask currentTask() {
+        return currentTask;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Thu Mar 29 13:23:34 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Thu Mar 29 18:43:30 2012 +0200
@@ -59,10 +59,14 @@
     }
 
     public StructuredGraph(String name, RiResolvedMethod method) {
+        this(name, method, uniqueGraphIds.incrementAndGet());
+    }
+
+    private StructuredGraph(String name, RiResolvedMethod method, long graphId) {
         super(name);
         this.start = add(new BeginNode());
         this.method = method;
-        this.graphId = uniqueGraphIds.incrementAndGet();
+        this.graphId = graphId;
     }
 
     public StructuredGraph(RiResolvedMethod method) {
@@ -88,7 +92,7 @@
 
     @Override
     public StructuredGraph copy(String newName) {
-        StructuredGraph copy = new StructuredGraph(newName);
+        StructuredGraph copy = new StructuredGraph(newName, method, graphId);
         HashMap<Node, Node> replacements = new HashMap<>();
         replacements.put(start, copy.start);
         copy.addDuplicates(getNodes(), replacements);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectFieldNode.java	Thu Mar 29 13:23:34 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectFieldNode.java	Thu Mar 29 18:43:30 2012 +0200
@@ -34,7 +34,7 @@
     @Input private ValueNode lastState;
     @Input private ValueNode input;
 
-    private int index;
+    @Data private int index;
 
     public VirtualObjectNode object() {
         return object;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiCompilationStatistics.java	Thu Mar 29 18:43:30 2012 +0200
@@ -0,0 +1,211 @@
+/*
+ * 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.max.cri.ci;
+
+import java.io.*;
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import com.oracle.max.cri.ri.*;
+
+@SuppressWarnings("unused")
+public final class CiCompilationStatistics {
+
+    private static final long RESOLUTION = 100000000;
+    private static final boolean TIMELINE_ENABLED = System.getProperty("stats.timeline.file") != null;
+    private static final boolean COMPILATIONSTATS_ENABLED = System.getProperty("stats.compilations.file") != null;
+    private static final boolean ENABLED = TIMELINE_ENABLED || COMPILATIONSTATS_ENABLED;
+
+    private static final CiCompilationStatistics DUMMY = new CiCompilationStatistics(null);
+
+    private static ConcurrentLinkedDeque<CiCompilationStatistics> list = new ConcurrentLinkedDeque<>();
+
+    private static final ThreadLocal<Deque<CiCompilationStatistics>> current = new ThreadLocal<Deque<CiCompilationStatistics>>() {
+
+        @Override
+        protected Deque<CiCompilationStatistics> initialValue() {
+            return new ArrayDeque<>();
+        }
+    };
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.FIELD)
+    private static @interface AbsoluteTimeValue {
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.FIELD)
+    private static @interface TimeValue {
+    }
+
+    private static long zeroTime = System.nanoTime();
+
+    private final String holder;
+    private final String name;
+    private final String signature;
+    @AbsoluteTimeValue
+    private final long startTime;
+    @TimeValue
+    private long duration;
+    private int startInvCount;
+    private int endInvCount;
+    private int bytecodeCount;
+    private int codeSize;
+    private int deoptCount;
+
+    private CiCompilationStatistics(RiResolvedMethod method) {
+        if (method != null) {
+            holder = CiUtil.format("%H", method);
+            name = method.name();
+            signature = CiUtil.format("%p", method);
+            startTime = System.nanoTime();
+            startInvCount = method.invocationCount();
+            bytecodeCount = method.codeSize();
+        } else {
+            holder = "";
+            name = "";
+            signature = "";
+            startTime = 0;
+        }
+    }
+
+    public void finish(RiResolvedMethod method) {
+        if (ENABLED) {
+            duration = System.nanoTime() - startTime;
+            endInvCount = method.invocationCount();
+            codeSize = method.compiledCodeSize();
+            if (current.get().getLast() != this) {
+                throw new RuntimeException("mismatch in finish()");
+            }
+            current.get().removeLast();
+        }
+    }
+
+    public static CiCompilationStatistics current() {
+        return current.get().isEmpty() ? null : current.get().getLast();
+    }
+
+    public static CiCompilationStatistics create(RiResolvedMethod method) {
+        if (ENABLED) {
+            CiCompilationStatistics stats = new CiCompilationStatistics(method);
+            list.add(stats);
+            current.get().addLast(stats);
+            return stats;
+        } else {
+            return DUMMY;
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    public static void clear(String dumpName) {
+        if (!ENABLED) {
+            return;
+        }
+        try {
+            ConcurrentLinkedDeque<CiCompilationStatistics> snapshot = list;
+            long snapshotZeroTime = zeroTime;
+
+            list = new ConcurrentLinkedDeque<>();
+            zeroTime = System.nanoTime();
+
+            Date now = new Date();
+            String dateString = (now.getYear() + 1900) + "_" + (now.getMonth() + 1) + "_" + now.getDate() + " " + now.getHours() + "_" + now.getMinutes() + "_" + now.getSeconds();
+            try (PrintStream out = new PrintStream("compilations " + dateString + " " + dumpName + ".csv")) {
+                // output the list of all compilations
+
+                Field[] declaredFields = CiCompilationStatistics.class.getDeclaredFields();
+                ArrayList<Field> fields = new ArrayList<>();
+                for (Field field : declaredFields) {
+                    if (!Modifier.isStatic(field.getModifiers())) {
+                        fields.add(field);
+                    }
+                }
+                for (Field field : fields) {
+                    out.print(field.getName() + ";");
+                }
+                out.println();
+                for (CiCompilationStatistics stats : snapshot) {
+                    for (Field field : fields) {
+                        if (field.isAnnotationPresent(AbsoluteTimeValue.class)) {
+                            double value = (field.getLong(stats) - snapshotZeroTime) / 1000000d;
+                            out.print(String.format(Locale.ENGLISH, "%.3f", value) + ";");
+                        } else if (field.isAnnotationPresent(TimeValue.class)) {
+                            double value = field.getLong(stats) / 1000000d;
+                            out.print(String.format(Locale.ENGLISH, "%.3f", value) + ";");
+                        } else {
+                            out.print(field.get(stats) + ";");
+                        }
+                    }
+                    out.println();
+                }
+            }
+
+            String timelineFile = System.getProperty("stats.timeline.file");
+            if (timelineFile == null || timelineFile.isEmpty()) {
+                timelineFile = "timeline " + dateString;
+            }
+            try (FileOutputStream fos = new FileOutputStream(timelineFile + " " + dumpName + ".csv", true); PrintStream out = new PrintStream(fos)) {
+
+                long[] timeSpent = new long[10000];
+                int maxTick = 0;
+                for (CiCompilationStatistics stats : snapshot) {
+                    long start = stats.startTime - snapshotZeroTime;
+                    long duration = stats.duration;
+                    if (start < 0) {
+                        duration -= -start;
+                        start = 0;
+                    }
+
+                    int tick = (int) (start / RESOLUTION);
+                    long timeLeft = RESOLUTION - (start % RESOLUTION);
+
+                    while (tick < timeSpent.length && duration > 0) {
+                        if (tick > maxTick) {
+                            maxTick = tick;
+                        }
+                        timeSpent[tick] += Math.min(timeLeft, duration);
+                        duration -= timeLeft;
+                        tick++;
+                        timeLeft = RESOLUTION;
+                    }
+                }
+                String timelineName = System.getProperty("stats.timeline.name");
+                if (timelineName != null && !timelineName.isEmpty()) {
+                    out.print(timelineName + ";");
+                }
+                for (int i = 0; i <= maxTick; i++) {
+                    out.print((timeSpent[i] * 100 / RESOLUTION) + ";");
+                }
+                out.println();
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public void setDeoptCount(int count) {
+        this.deoptCount = count;
+    }
+}
--- a/hotspot/.cproject	Thu Mar 29 13:23:34 2012 +0200
+++ b/hotspot/.cproject	Thu Mar 29 18:43:30 2012 +0200
@@ -80,7 +80,162 @@
 			<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
 			<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
 			<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
-			<storageModule moduleId="scannerConfiguration"/>
+		</cconfiguration>
+		<cconfiguration id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1753195001">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1753195001" moduleId="org.eclipse.cdt.core.settings" name="product">
+				<externalSettings/>
+				<extensions>
+					<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactName="hotspot" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1753195001" name="product" parent="org.eclipse.cdt.build.core.emptycfg">
+					<folderInfo id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1753195001." name="/" resourcePath="">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.base.1094071149" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base">
+							<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.1366986655" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
+							<builder arguments="${workspace_loc:/hotspot}/../mxtool/mx build" autoBuildTarget="product" buildPath="${workspace_loc:/hotspot}/.." cleanBuildTarget="clean" command="bash" enableAutoBuild="true" enableCleanBuild="false" enabledIncrementalBuild="false" id="cdt.managedbuild.target.gnu.builder.base.831826345" incrementalBuildTarget="jvmg1" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" parallelizationNumber="1" superClass="cdt.managedbuild.target.gnu.builder.base">
+								<outputEntries>
+									<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name=""/>
+								</outputEntries>
+							</builder>
+							<tool id="cdt.managedbuild.tool.gnu.archiver.base.1222329151" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.235939569" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
+								<option id="gnu.cpp.compiler.option.include.paths.2124509243" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths"/>
+								<option id="gnu.cpp.compiler.option.preprocessor.def.77729074" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="VM_LITTLE_ENDIAN=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+									<listOptionValue builtIn="false" value="AMD64=1"/>
+									<listOptionValue builtIn="false" value="LINUX=1"/>
+									<listOptionValue builtIn="false" value="TARGET_ARCH_x86=1"/>
+									<listOptionValue builtIn="false" value="TARGET_COMPILER_gcc=1"/>
+									<listOptionValue builtIn="false" value="TARGET_OS_FAMILY_linux=1"/>
+									<listOptionValue builtIn="false" value="TARGET_OS_ARCH_linux_x86=1"/>
+									<listOptionValue builtIn="false" value="TARGET_ARCH_MODEL_x86_64=1"/>
+									<listOptionValue builtIn="false" value="GRAAL=1"/>
+								</option>
+								<option id="gnu.cpp.compiler.option.preprocessor.undef.1117494475" name="Undefined symbols (-U)" superClass="gnu.cpp.compiler.option.preprocessor.undef"/>
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1168038805" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.2110455043" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
+								<option id="gnu.c.compiler.option.preprocessor.def.symbols.1595255663" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="VM_LITTLE_ENDIAN=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+									<listOptionValue builtIn="false" value="AMD64=1"/>
+								</option>
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1261515555" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.base.1541095" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.578894321" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.721919005" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.base.1944481961" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.284566020" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+						</toolChain>
+					</folderInfo>
+					<sourceEntries>
+						<entry excluding="cpu/vm/templateTable_x86_32.cpp|cpu/vm/templateInterpreter_x86_32.cpp|cpu/vm/stubRoutines_x86_32.cpp|cpu/vm/stubGenerator_x86_32.cpp|cpu/vm/sharedRuntime_x86_32.cpp|cpu/vm/jniFastGetField_x86_32.cpp|cpu/vm/interpreterRT_x86_32.cpp|cpu/vm/interpreter_x86_32.cpp|cpu/vm/interp_masm_x86_32.cpp|cpu/vm/vtableStubs_x86_32.cpp|vm/opto" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
+					</sourceEntries>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+			<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+			<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
+			<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+		</cconfiguration>
+		<cconfiguration id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1753195001.200970051">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1753195001.200970051" moduleId="org.eclipse.cdt.core.settings" name="debug">
+				<externalSettings/>
+				<extensions>
+					<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactName="hotspot" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1753195001.200970051" name="debug" parent="org.eclipse.cdt.build.core.emptycfg">
+					<folderInfo id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1753195001.200970051." name="/" resourcePath="">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.base.85322399" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base">
+							<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.369211282" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
+							<builder arguments="${workspace_loc:/hotspot}/../mxtool/mx build" autoBuildTarget="debug" buildPath="${workspace_loc:/hotspot}/.." cleanBuildTarget="clean" command="bash" enableAutoBuild="true" enableCleanBuild="false" enabledIncrementalBuild="false" id="cdt.managedbuild.target.gnu.builder.base.944057404" incrementalBuildTarget="jvmg1" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" parallelizationNumber="1" superClass="cdt.managedbuild.target.gnu.builder.base">
+								<outputEntries>
+									<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name=""/>
+								</outputEntries>
+							</builder>
+							<tool id="cdt.managedbuild.tool.gnu.archiver.base.1620577294" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1333497405" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
+								<option id="gnu.cpp.compiler.option.include.paths.323539230" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths"/>
+								<option id="gnu.cpp.compiler.option.preprocessor.def.150327888" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="VM_LITTLE_ENDIAN=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+									<listOptionValue builtIn="false" value="AMD64=1"/>
+									<listOptionValue builtIn="false" value="LINUX=1"/>
+									<listOptionValue builtIn="false" value="TARGET_ARCH_x86=1"/>
+									<listOptionValue builtIn="false" value="TARGET_COMPILER_gcc=1"/>
+									<listOptionValue builtIn="false" value="TARGET_OS_FAMILY_linux=1"/>
+									<listOptionValue builtIn="false" value="TARGET_OS_ARCH_linux_x86=1"/>
+									<listOptionValue builtIn="false" value="TARGET_ARCH_MODEL_x86_64=1"/>
+									<listOptionValue builtIn="false" value="GRAAL=1"/>
+								</option>
+								<option id="gnu.cpp.compiler.option.preprocessor.undef.1178030129" name="Undefined symbols (-U)" superClass="gnu.cpp.compiler.option.preprocessor.undef"/>
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1729844380" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.1253851174" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
+								<option id="gnu.c.compiler.option.preprocessor.def.symbols.1067842050" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_LP64=1"/>
+									<listOptionValue builtIn="false" value="COMPILER1=1"/>
+									<listOptionValue builtIn="false" value="VM_LITTLE_ENDIAN=1"/>
+									<listOptionValue builtIn="false" value="ASSERT=1"/>
+									<listOptionValue builtIn="false" value="_REENTRANT=1"/>
+									<listOptionValue builtIn="false" value="DEBUG=1"/>
+									<listOptionValue builtIn="false" value="AMD64=1"/>
+								</option>
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.2133987017" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.base.1778246187" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.1574482902" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.15191548" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.base.187448222" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.181490524" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+						</toolChain>
+					</folderInfo>
+					<sourceEntries>
+						<entry excluding="cpu/vm/templateTable_x86_32.cpp|cpu/vm/templateInterpreter_x86_32.cpp|cpu/vm/stubRoutines_x86_32.cpp|cpu/vm/stubGenerator_x86_32.cpp|cpu/vm/sharedRuntime_x86_32.cpp|cpu/vm/jniFastGetField_x86_32.cpp|cpu/vm/interpreterRT_x86_32.cpp|cpu/vm/interpreter_x86_32.cpp|cpu/vm/interp_masm_x86_32.cpp|cpu/vm/vtableStubs_x86_32.cpp|vm/opto" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
+					</sourceEntries>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+			<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+			<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
+			<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
 		</cconfiguration>
 	</storageModule>
 	<storageModule moduleId="cdtBuildSystem" version="4.0.0">
--- a/hotspot/.project	Thu Mar 29 13:23:34 2012 +0200
+++ b/hotspot/.project	Thu Mar 29 18:43:30 2012 +0200
@@ -23,7 +23,7 @@
 				</dictionary>
 				<dictionary>
 					<key>org.eclipse.cdt.make.core.autoBuildTarget</key>
-					<value>ide-build-target</value>
+					<value>product</value>
 				</dictionary>
 				<dictionary>
 					<key>org.eclipse.cdt.make.core.buildArguments</key>
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Thu Mar 29 13:23:34 2012 +0200
+++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Thu Mar 29 18:43:30 2012 +0200
@@ -36,6 +36,7 @@
 #include "prims/jvmtiExport.hpp"
 #include "prims/jvmtiThreadState.hpp"
 #include "runtime/arguments.hpp"
+#include "runtime/compilationPolicy.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/frame.inline.hpp"
 #include "runtime/sharedRuntime.hpp"
@@ -286,6 +287,15 @@
 // Helpers for commoning out cases in the various type of method entries.
 //
 
+#ifdef GRAAL
+
+void graal_initialize_time(JavaThread* thread) {
+  frame fr = thread->last_frame();
+  assert(fr.is_interpreted_frame(), "must come from interpreter");
+  fr.interpreter_frame_method()->set_graal_invocation_time(os::javaTimeNanos());
+}
+
+#endif // GRAAL
 
 // increment invocation count & check for overflow
 //
@@ -330,9 +340,30 @@
       __ incrementl(Address(rbx,
                             methodOopDesc::interpreter_invocation_counter_offset()));
     }
+
+#ifdef GRAAL
+    if (CompilationPolicyChoice == 4) {
+      Label not_zero;
+      __ testl(rcx, InvocationCounter::count_mask_value);
+      __ jcc(Assembler::notZero, not_zero);
+
+      __ push(rcx);
+      __ call_VM(noreg, CAST_FROM_FN_PTR(address, graal_initialize_time), rdx, false);
+      __ set_method_data_pointer_for_bcp();
+      __ get_method(rbx);
+      __ pop(rcx);
+
+      __ testl(rcx, InvocationCounter::count_mask_value);
+      __ jcc(Assembler::zero, not_zero);
+      __ stop("unexpected counter value in rcx");
+
+      __ bind(not_zero);
+    }
+#endif // GRAAL
+
     // Update standard invocation counters
+
     __ movl(rax, backedge_counter);   // load backedge counter
-
     __ incrementl(rcx, InvocationCounter::count_increment);
     __ andl(rax, InvocationCounter::count_mask_value); // mask out the status bits
 
--- a/src/share/vm/classfile/vmSymbols.hpp	Thu Mar 29 13:23:34 2012 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Thu Mar 29 18:43:30 2012 +0200
@@ -317,7 +317,7 @@
   template(bootstrap_name,                            "bootstrap")                                                      \
   template(shutdownCompiler_name,                     "shutdownCompiler")                                               \
   template(compileMethod_name,                        "compileMethod")                                                  \
-  template(compileMethod_signature,                   "(Lcom/oracle/graal/hotspot/ri/HotSpotMethodResolved;IZ)Z")   \
+  template(compileMethod_signature,                   "(Lcom/oracle/graal/hotspot/ri/HotSpotMethodResolved;IZI)Z")      \
   template(setOption_name,                            "setOption")                                                      \
   template(setDefaultOptions_name,                    "setDefaultOptions")                                              \
   template(setOption_signature,                       "(Ljava/lang/String;)Z")                                          \
@@ -344,10 +344,10 @@
   template(createCiConstantObject_name,               "createCiConstantObject")                                         \
   template(createCiConstantObject_signature,          "(Ljava/lang/Object;)Lcom/oracle/max/cri/ci/CiConstant;")         \
   template(getVMExits_name,                           "getVMExits")                                                     \
-  template(getVMExits_signature,                      "()Lcom/oracle/graal/hotspot/bridge/VMToCompiler;")           \
+  template(getVMExits_signature,                      "()Lcom/oracle/graal/hotspot/bridge/VMToCompiler;")               \
   template(getInstance_name,                          "getInstance")                                                    \
   template(initialize_name,                           "initialize")                                                     \
-  template(getInstance_signature,                     "()Lcom/oracle/graal/hotspot/Compiler;")                      \
+  template(getInstance_signature,                     "()Lcom/oracle/graal/hotspot/Compiler;")                          \
   template(forObject_name,                            "forObject")                                                      \
   template(callbackInternal_name,                     "callbackInternal")                                               \
   template(callback_signature,                        "(Ljava/lang/Object;)Ljava/lang/Object;")                         \
--- a/src/share/vm/graal/graalCompiler.cpp	Thu Mar 29 13:23:34 2012 +0200
+++ b/src/share/vm/graal/graalCompiler.cpp	Thu Mar 29 18:43:30 2012 +0200
@@ -164,7 +164,7 @@
   JavaThread::current()->set_env(NULL);
   JavaThread::current()->set_compiling(true);
   Handle hotspot_method = GraalCompiler::createHotSpotMethodResolved(method, CHECK);
-  jboolean success = VMToCompiler::compileMethod(hotspot_method, entry_bci, blocking);
+  jboolean success = VMToCompiler::compileMethod(hotspot_method, entry_bci, blocking, method->graal_priority());
   JavaThread::current()->set_compiling(false);
   JavaThread::current()->set_env(current_env);
   if (success != JNI_TRUE) {
--- a/src/share/vm/graal/graalVMToCompiler.cpp	Thu Mar 29 13:23:34 2012 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.cpp	Thu Mar 29 18:43:30 2012 +0200
@@ -97,7 +97,7 @@
   check_pending_exception("Error while calling setDefaultOptions");
 }
 
-jboolean VMToCompiler::compileMethod(Handle hotspot_method, int entry_bci, jboolean blocking) {
+jboolean VMToCompiler::compileMethod(Handle hotspot_method, int entry_bci, jboolean blocking, int priority) {
   assert(!hotspot_method.is_null(), "just checking");
   Thread* THREAD = Thread::current();
   JavaValue result(T_BOOLEAN);
@@ -106,6 +106,7 @@
   args.push_oop(hotspot_method);
   args.push_int(entry_bci);
   args.push_int(blocking);
+  args.push_int(priority);
   JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::compileMethod_name(), vmSymbols::compileMethod_signature(), &args, THREAD);
   check_pending_exception("Error while calling compileMethod");
   return result.get_jboolean();
--- a/src/share/vm/graal/graalVMToCompiler.hpp	Thu Mar 29 13:23:34 2012 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.hpp	Thu Mar 29 18:43:30 2012 +0200
@@ -51,7 +51,7 @@
   static void setDefaultOptions();
 
   // public abstract boolean compileMethod(long vmId, String name, int entry_bci, boolean blocking);
-  static jboolean compileMethod(Handle hotspot_method, int entry_bci, jboolean blocking);
+  static jboolean compileMethod(Handle hotspot_method, int entry_bci, jboolean blocking, int priority);
 
   // public abstract void shutdownCompiler();
   static void shutdownCompiler();
--- a/src/share/vm/oops/methodKlass.cpp	Thu Mar 29 13:23:34 2012 +0200
+++ b/src/share/vm/oops/methodKlass.cpp	Thu Mar 29 18:43:30 2012 +0200
@@ -109,6 +109,8 @@
   m->clear_number_of_breakpoints();
 #ifdef GRAAL
   m->set_graal_mirror(NULL);
+  m->set_graal_invocation_time(0);
+  m->set_graal_priority(1000000);
 #endif
 
 #ifdef TIERED
--- a/src/share/vm/oops/methodOop.hpp	Thu Mar 29 13:23:34 2012 +0200
+++ b/src/share/vm/oops/methodOop.hpp	Thu Mar 29 18:43:30 2012 +0200
@@ -131,8 +131,11 @@
   InvocationCounter _invocation_counter;         // Incremented before each activation of the method - used to trigger frequency-based optimizations
   InvocationCounter _backedge_counter;           // Incremented before each backedge taken - used to trigger frequencey-based optimizations
 
-  // com/oracle/graal/hotspot/HotSpotMethodResolved mirroring this method
-  oop               _graal_mirror;
+#ifdef GRAAL
+  oop               _graal_mirror;               // com/oracle/graal/hotspot/HotSpotMethodResolved mirroring this method
+  jlong             _graal_invocation_time;
+  int               _graal_priority;
+#endif
 #ifdef TIERED
   jlong             _prev_time;                   // Previous time the rate was acquired
   float             _rate;                        // Events (invocation and backedge counter increments) per millisecond
@@ -333,10 +336,18 @@
   int invocation_count();
   int backedge_count();
 
+#ifdef GRAAL
   // graal mirror
   oop graal_mirror() const               { return _graal_mirror; }
   void set_graal_mirror(oop m)           { oop_store((oop*) &_graal_mirror, m); }
 
+  void set_graal_invocation_time(jlong time) { _graal_invocation_time = time; }
+  jlong graal_invocation_time()          { return _graal_invocation_time; }
+
+  void set_graal_priority(int prio)      { _graal_priority = prio; }
+  int graal_priority()                   { return _graal_priority; }
+#endif // GRAAL
+
   bool was_executed_more_than(int n);
   bool was_never_executed()                      { return !was_executed_more_than(0); }
 
@@ -565,6 +576,10 @@
     return byte_offset_of(methodOopDesc, _method_data);
   }
   static ByteSize interpreter_invocation_counter_offset() { return byte_offset_of(methodOopDesc, _interpreter_invocation_count); }
+#ifdef GRAAL
+  static ByteSize graal_invocation_time_offset() { return byte_offset_of(methodOopDesc, _graal_invocation_time); }
+  static ByteSize graal_priority_offset()        { return byte_offset_of(methodOopDesc, _graal_priority); }
+#endif
 #ifndef PRODUCT
   static ByteSize compiled_invocation_counter_offset() { return byte_offset_of(methodOopDesc, _compiled_invocation_count); }
 #endif // not PRODUCT
@@ -730,8 +745,10 @@
   // Garbage collection support
   oop*  adr_constMethod() const                  { return (oop*)&_constMethod;     }
   oop*  adr_constants() const                    { return (oop*)&_constants;       }
+  oop*  adr_method_data() const                  { return (oop*)&_method_data;     }
+#ifdef GRAAL
   oop*  adr_graal_mirror() const                 { return (oop*)&_graal_mirror;    }
-  oop*  adr_method_data() const                  { return (oop*)&_method_data;     }
+#endif
 };
 
 
--- a/src/share/vm/runtime/arguments.cpp	Thu Mar 29 13:23:34 2012 +0200
+++ b/src/share/vm/runtime/arguments.cpp	Thu Mar 29 18:43:30 2012 +0200
@@ -3231,7 +3231,7 @@
     set_tiered_flags();
   } else {
     // Check if the policy is valid. Policies 0 and 1 are valid for non-tiered setup.
-    if (CompilationPolicyChoice >= 2) {
+    if (CompilationPolicyChoice >= 2 && CompilationPolicyChoice < 4) {
       vm_exit_during_initialization(
         "Incompatible compilation policy selected", NULL);
     }
--- a/src/share/vm/runtime/compilationPolicy.cpp	Thu Mar 29 13:23:34 2012 +0200
+++ b/src/share/vm/runtime/compilationPolicy.cpp	Thu Mar 29 18:43:30 2012 +0200
@@ -80,8 +80,15 @@
     Unimplemented();
 #endif
     break;
+  case 4:
+#if defined(GRAAL)
+    CompilationPolicy::set_policy(new GraalCompPolicy());
+#else
+    Unimplemented();
+#endif
+    break;
   default:
-    fatal("CompilationPolicyChoice must be in the range: [0-3]");
+    fatal("CompilationPolicyChoice must be in the range: [0-4]");
   }
   CompilationPolicy::policy()->initialize();
 }
@@ -201,6 +208,7 @@
 }
 
 void NonTieredCompPolicy::reset_counter_for_back_branch_event(methodHandle m) {
+  GRAAL_ONLY(assert(false, "unexpected"));
   // Delay next back-branch event but pump up invocation counter to triger
   // whole method compilation.
   InvocationCounter* i = m->invocation_counter();
@@ -418,6 +426,56 @@
     NOT_PRODUCT(trace_osr_completion(m->lookup_osr_nmethod_for(bci, CompLevel_highest_tier, true));)
   }
 }
+
+// GraalCompPolicy - compile current method
+
+#ifdef GRAAL
+
+void GraalCompPolicy::method_invocation_event(methodHandle m, JavaThread* thread) {
+  int hot_count = m->invocation_count();
+  jlong hot_time = m->graal_invocation_time();
+  reset_counter_for_invocation_event(m);
+
+  if (is_compilation_enabled() && can_be_compiled(m)) {
+    nmethod* nm = m->code();
+    if (nm == NULL) {
+      if (hot_count > 1) {
+        jlong current_time = os::javaTimeNanos();
+        int time_per_call = (int) ((current_time - hot_time) / hot_count);
+        m->set_graal_invocation_time(current_time);
+        if (m->queued_for_compilation()) {
+          if (time_per_call < (m->graal_priority() / 5)) {
+            m->set_graal_priority(time_per_call);
+            m->clear_queued_for_compilation();
+          }
+        } else {
+          if (time_per_call < m->graal_priority()) {
+            m->set_graal_priority(time_per_call);
+          }
+        }
+      }
+      if (!m->queued_for_compilation()) {
+        CompileBroker::compile_method(m, InvocationEntryBci, CompLevel_highest_tier, m, hot_count, "count", thread);
+      }
+    }
+  } else {
+  }
+}
+
+void GraalCompPolicy::method_back_branch_event(methodHandle m, int bci, JavaThread* thread) {
+  int hot_count = m->backedge_count();
+  const char* comment = "backedge_count";
+
+  if (is_compilation_enabled() && !m->is_not_osr_compilable() && can_be_compiled(m)) {
+    CompileBroker::compile_method(m, bci, CompLevel_highest_tier,
+                                  m, hot_count, comment, thread);
+    NOT_PRODUCT(trace_osr_completion(m->lookup_osr_nmethod_for(bci, CompLevel_highest_tier, true));)
+  }
+}
+
+#endif // GRAAL
+
+
 // StackWalkCompPolicy - walk up stack to find a suitable method to compile
 
 #if defined(COMPILER2) || defined(GRAAL)
--- a/src/share/vm/runtime/compilationPolicy.hpp	Thu Mar 29 13:23:34 2012 +0200
+++ b/src/share/vm/runtime/compilationPolicy.hpp	Thu Mar 29 18:43:30 2012 +0200
@@ -116,6 +116,14 @@
   virtual void method_back_branch_event(methodHandle m, int bci, JavaThread* thread);
 };
 
+#ifdef GRAAL
+class GraalCompPolicy : public NonTieredCompPolicy {
+ public:
+  virtual void method_invocation_event(methodHandle m, JavaThread* thread);
+  virtual void method_back_branch_event(methodHandle m, int bci, JavaThread* thread);
+};
+#endif // GRAAL
+
 // StackWalkCompPolicy - existing C2 policy
 
 #if defined(COMPILER2) || defined(GRAAL)