# HG changeset patch # User Lukas Stadler # Date 1333039410 -7200 # Node ID af59b4dfc9e443ca1a37776de24c39699602f2a0 # Parent a8c5283a835cca3e1a5436c367bda9dea8fe574d 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) diff -r a8c5283a835c -r af59b4dfc9e4 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java --- 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; diff -r a8c5283a835c -r af59b4dfc9e4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java 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 { + + 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); } } diff -r a8c5283a835c -r af59b4dfc9e4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java --- 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); diff -r a8c5283a835c -r af59b4dfc9e4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java --- 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; diff -r a8c5283a835c -r af59b4dfc9e4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java 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(), CompilerThread.FACTORY); + final BlockingQueue 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 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 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; diff -r a8c5283a835c -r af59b4dfc9e4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolved.java --- 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(); } diff -r a8c5283a835c -r af59b4dfc9e4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolvedImpl.java --- 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; + } } diff -r a8c5283a835c -r af59b4dfc9e4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java --- 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 replacements = new HashMap<>(); replacements.put(start, copy.start); copy.addDuplicates(getNodes(), replacements); diff -r a8c5283a835c -r af59b4dfc9e4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectFieldNode.java --- 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; diff -r a8c5283a835c -r af59b4dfc9e4 graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiCompilationStatistics.java --- /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 list = new ConcurrentLinkedDeque<>(); + + private static final ThreadLocal> current = new ThreadLocal>() { + + @Override + protected Deque 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 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 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; + } +} diff -r a8c5283a835c -r af59b4dfc9e4 hotspot/.cproject --- 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 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r a8c5283a835c -r af59b4dfc9e4 hotspot/.project --- 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 @@ org.eclipse.cdt.make.core.autoBuildTarget - ide-build-target + product org.eclipse.cdt.make.core.buildArguments diff -r a8c5283a835c -r af59b4dfc9e4 src/cpu/x86/vm/templateInterpreter_x86_64.cpp --- 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 diff -r a8c5283a835c -r af59b4dfc9e4 src/share/vm/classfile/vmSymbols.hpp --- 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;") \ diff -r a8c5283a835c -r af59b4dfc9e4 src/share/vm/graal/graalCompiler.cpp --- 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) { diff -r a8c5283a835c -r af59b4dfc9e4 src/share/vm/graal/graalVMToCompiler.cpp --- 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(); diff -r a8c5283a835c -r af59b4dfc9e4 src/share/vm/graal/graalVMToCompiler.hpp --- 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(); diff -r a8c5283a835c -r af59b4dfc9e4 src/share/vm/oops/methodKlass.cpp --- 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 diff -r a8c5283a835c -r af59b4dfc9e4 src/share/vm/oops/methodOop.hpp --- 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 }; diff -r a8c5283a835c -r af59b4dfc9e4 src/share/vm/runtime/arguments.cpp --- 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); } diff -r a8c5283a835c -r af59b4dfc9e4 src/share/vm/runtime/compilationPolicy.cpp --- 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) diff -r a8c5283a835c -r af59b4dfc9e4 src/share/vm/runtime/compilationPolicy.hpp --- 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)