changeset 14728:d09194f75dd4

Merge.
author Doug Simon <doug.simon@oracle.com>
date Mon, 24 Mar 2014 23:50:48 +0100
parents 8b772174c514 (current diff) ba7b08d90fde (diff)
children 8db730993642
files
diffstat 13 files changed, 363 insertions(+), 74 deletions(-) [+]
line wrap: on
line diff
--- a/README.md	Mon Mar 24 23:50:18 2014 +0100
+++ b/README.md	Mon Mar 24 23:50:48 2014 +0100
@@ -23,10 +23,11 @@
    Compilation with Graal is only done by explicit requests to the
    Graal API. This is how Truffle uses Graal.
    
-2. The 'graal' configuration is a VM where all compilation is performed
-   by Graal and no other compilers are built into the VM binary. This
-   VM will bootstrap Graal itself at startup unless the -XX:-BootstrapGraal
-   VM option is given.   
+2. The 'graal' configuration is a VM where normal compilations are performed
+   by Graal. This VM will bootstrap Graal itself at startup unless the
+   -XX:-BootstrapGraal. Note that if tiered compilation is enabled, Graal
+   will be used at the last tier while C1 will be used for the first compiled
+   tiers.
 
 Unless you use the --vm option with the build command, you will be presented
 with a dialogue to choose one of the above VM configurations for the build
@@ -78,5 +79,3 @@
 
 These configurations aim to match as closely as possible the
 VM(s) included in the OpenJDK binaries one can download.
- No newline at end of file
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/CompilerThread.java	Mon Mar 24 23:50:48 2014 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler;
+
+import com.oracle.graal.compiler.CompilerThreadFactory.*;
+import com.oracle.graal.debug.*;
+
+/**
+ * A compiler thread is a daemon thread that runs at {@link Thread#MAX_PRIORITY} and executes in the
+ * context of a thread-local {@linkplain GraalDebugConfig debug configuration}.
+ */
+public class CompilerThread extends Thread {
+
+    private final DebugConfigAccess debugConfigAccess;
+
+    public CompilerThread(Runnable r, String namePrefix, DebugConfigAccess debugConfigAccess) {
+        super(r);
+        this.setName(namePrefix + "-" + this.getId());
+        this.setPriority(Thread.MAX_PRIORITY);
+        this.setDaemon(true);
+        this.debugConfigAccess = debugConfigAccess;
+    }
+
+    @Override
+    public void run() {
+        GraalDebugConfig debugConfig = debugConfigAccess.getDebugConfig();
+        try {
+            super.run();
+        } finally {
+            if (debugConfig != null) {
+                for (DebugDumpHandler dumpHandler : debugConfig.dumpHandlers()) {
+                    try {
+                        dumpHandler.close();
+                    } catch (Throwable t) {
+                    }
+                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/CompilerThreadFactory.java	Mon Mar 24 23:50:18 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/CompilerThreadFactory.java	Mon Mar 24 23:50:48 2014 +0100
@@ -53,38 +53,4 @@
     public Thread newThread(Runnable r) {
         return new CompilerThread(r, threadNamePrefix, debugConfigAccess);
     }
-
-    /**
-     * A compiler thread is a daemon thread that runs at {@link Thread#MAX_PRIORITY} and executes in
-     * the context of a thread-local {@linkplain GraalDebugConfig debug configuration}.
-     */
-    public static class CompilerThread extends Thread {
-
-        private final DebugConfigAccess debugConfigAccess;
-
-        public CompilerThread(Runnable r, String namePrefix, DebugConfigAccess debugConfigAccess) {
-            super(r);
-            this.setName(namePrefix + "-" + this.getId());
-            this.setPriority(Thread.MAX_PRIORITY);
-            this.setDaemon(true);
-            this.debugConfigAccess = debugConfigAccess;
-        }
-
-        @Override
-        public void run() {
-            GraalDebugConfig debugConfig = debugConfigAccess.getDebugConfig();
-            try {
-                super.run();
-            } finally {
-                if (debugConfig != null) {
-                    for (DebugDumpHandler dumpHandler : debugConfig.dumpHandlers()) {
-                        try {
-                            dumpHandler.close();
-                        } catch (Throwable t) {
-                        }
-                    }
-                }
-            }
-        }
-    }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Mon Mar 24 23:50:18 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Mon Mar 24 23:50:48 2014 +0100
@@ -25,15 +25,29 @@
 import static com.oracle.graal.phases.GraalOptions.*;
 
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 
 public class LowTier extends PhaseSuite<LowTierContext> {
 
+    static class Options {
+
+        // @formatter:off
+        @Option(help = "")
+        public static final OptionValue<Boolean> ProfileCompiledMethods = new OptionValue<>(false);
+        // @formatter:on
+
+    }
+
     public LowTier() {
         CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!ImmutableCode.getValue());
 
+        if (Options.ProfileCompiledMethods.getValue()) {
+            appendPhase(new ProfileCompiledMethodsPhase());
+        }
+
         appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER));
 
         appendPhase(new RemoveValueProxyPhase());
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Mon Mar 24 23:50:18 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Mon Mar 24 23:50:48 2014 +0100
@@ -31,6 +31,9 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.hsail.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.hsail.*;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.*;
@@ -45,7 +48,7 @@
 /**
  * The HotSpot specific portion of the HSAIL LIR generator.
  */
-public class HSAILHotSpotLIRGenerator extends HSAILLIRGenerator {
+public class HSAILHotSpotLIRGenerator extends HSAILLIRGenerator implements HotSpotLIRGenerator {
 
     private final HotSpotVMConfig config;
 
@@ -54,6 +57,11 @@
         this.config = config;
     }
 
+    @Override
+    public HotSpotProviders getProviders() {
+        return (HotSpotProviders) super.getProviders();
+    }
+
     private int getLogMinObjectAlignment() {
         return config.logMinObjAlignment();
     }
@@ -87,6 +95,41 @@
         return true;
     }
 
+    @Override
+    public StackSlot getLockSlot(int lockDepth) {
+        throw GraalInternalError.shouldNotReachHere("NYI");
+    }
+
+    @Override
+    public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
+        throw GraalInternalError.shouldNotReachHere("NYI");
+    }
+
+    @Override
+    public void emitPrefetchAllocate(ValueNode address, ValueNode distance) {
+        throw GraalInternalError.shouldNotReachHere("NYI");
+    }
+
+    @Override
+    public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) {
+        throw GraalInternalError.shouldNotReachHere("NYI");
+    }
+
+    @Override
+    public void emitPatchReturnAddress(ValueNode address) {
+        throw GraalInternalError.shouldNotReachHere("NYI");
+    }
+
+    @Override
+    public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) {
+        throw GraalInternalError.shouldNotReachHere("NYI");
+    }
+
+    @Override
+    public void emitTailcall(Value[] args, Value address) {
+        throw GraalInternalError.shouldNotReachHere("NYI");
+    }
+
     /**
      * Appends either a {@link CompareAndSwapOp} or a {@link CompareAndSwapCompressedOp} depending
      * on whether the memory location of a given {@link LoweredCompareAndSwapNode} contains a
@@ -163,6 +206,9 @@
                 if (isCompressed) {
                     if ((c.getKind() == Kind.Object) && c.isNull()) {
                         append(new StoreConstantOp(Kind.Int, storeAddress, Constant.forInt(0), state));
+                    } else if (c.getKind() == Kind.Long) {
+                        Constant value = compress(c, config.getKlassEncoding());
+                        append(new StoreConstantOp(Kind.Int, storeAddress, value, state));
                     } else {
                         throw GraalInternalError.shouldNotReachHere("can't handle: " + access);
                     }
@@ -226,4 +272,14 @@
         // this version of emitForeignCall not used for now
     }
 
+    /**
+     * @return a compressed version of the incoming constant lifted from AMD64HotSpotLIRGenerator
+     */
+    protected static Constant compress(Constant c, CompressEncoding encoding) {
+        if (c.getKind() == Kind.Long) {
+            return Constant.forIntegerKind(Kind.Int, (int) (((c.asLong() - encoding.base) >> encoding.shift) & 0xffffffffL), c.getPrimitiveAnnotation());
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Mon Mar 24 23:50:18 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Mon Mar 24 23:50:48 2014 +0100
@@ -39,7 +39,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.CompilerThreadFactory.CompilerThread;
+import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.debug.internal.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Mon Mar 24 23:50:18 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Mon Mar 24 23:50:48 2014 +0100
@@ -33,7 +33,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.CompilerThreadFactory.CompilerThread;
 import com.oracle.graal.compiler.CompilerThreadFactory.DebugConfigAccess;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Mon Mar 24 23:50:18 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Mon Mar 24 23:50:48 2014 +0100
@@ -23,7 +23,6 @@
 package com.oracle.graal.hotspot.debug;
 
 import java.io.*;
-import java.text.*;
 import java.util.*;
 import java.util.concurrent.*;
 import java.util.concurrent.atomic.*;
@@ -36,8 +35,8 @@
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.HeapAccess.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.debug.*;
 import com.oracle.graal.nodes.extended.*;
@@ -83,6 +82,8 @@
         //@formatter:off
         @Option(help = "Turn on the benchmark counters, and displays the results on VM shutdown")
         private static final OptionValue<Boolean> GenericDynamicCounters = new OptionValue<>(false);
+        @Option(help = "Turn on the benchmark counters, and displays the results every n milliseconds")
+        private static final OptionValue<Integer> TimedDynamicCounters = new OptionValue<>(-1);
 
         @Option(help = "Turn on the benchmark counters, and listen for specific patterns on System.out/System.err:%n" +
                        "Format: (err|out),start pattern,end pattern (~ matches multiple digits)%n" +
@@ -109,7 +110,8 @@
         }
         String name = counter.getName();
         String group = counter.getGroup();
-        name = counter.isWithContext() ? name + " @ " + counter.graph().graphId() + ":" + MetaUtil.format("%h.%n", counter.graph().method()) + "#" + group : name + "#" + group;
+        name = counter.isWithContext() && counter.graph().method() != null ? name + " @ " + counter.graph().graphId() + ":" + MetaUtil.format("%h.%n", counter.graph().method()) + "#" + group : name +
+                        "#" + group;
         Integer index = indexes.get(name);
         if (index == null) {
             synchronized (BenchmarkCounters.class) {
@@ -129,15 +131,15 @@
         return index;
     }
 
-    public static synchronized void dump(PrintStream out, double seconds, long[] counters) {
+    public static synchronized void dump(PrintStream out, double seconds, long[] counters, int maxRows) {
         if (!groups.isEmpty()) {
             out.println("====== dynamic counters (" + staticCounters.size() + " in total) ======");
             for (String group : new TreeSet<>(groups)) {
                 if (group != null) {
                     if (DUMP_STATIC) {
-                        dumpCounters(out, seconds, counters, true, group);
+                        dumpCounters(out, seconds, counters, true, group, maxRows);
                     }
-                    dumpCounters(out, seconds, counters, false, group);
+                    dumpCounters(out, seconds, counters, false, group, maxRows);
                 }
             }
             out.println("============================");
@@ -150,9 +152,10 @@
         delta = counters;
     }
 
-    private static synchronized void dumpCounters(PrintStream out, double seconds, long[] counters, boolean staticCounter, String group) {
+    private static synchronized void dumpCounters(PrintStream out, double seconds, long[] counters, boolean staticCounter, String group, int maxRows) {
         TreeMap<Long, String> sorted = new TreeMap<>();
 
+        // collect the numbers
         long[] array;
         if (staticCounter) {
             array = new long[indexes.size()];
@@ -165,6 +168,7 @@
                 array[i] -= delta[i];
             }
         }
+        // sort the counters by putting them into a sorted map
         long sum = 0;
         for (Map.Entry<String, Integer> entry : indexes.entrySet()) {
             int index = entry.getValue();
@@ -175,41 +179,51 @@
         }
 
         if (sum > 0) {
-            NumberFormat format = NumberFormat.getInstance(Locale.US);
             long cutoff = sorted.size() < 10 ? 1 : Math.max(1, sum / 100);
+            int cnt = sorted.size();
+
+            // remove everything below cutoff and keep at most maxRows
+            Iterator<Map.Entry<Long, String>> iter = sorted.entrySet().iterator();
+            while (iter.hasNext()) {
+                Map.Entry<Long, String> entry = iter.next();
+                long counter = entry.getKey() / array.length;
+                if (counter < cutoff || cnt > maxRows) {
+                    iter.remove();
+                }
+                cnt--;
+            }
+
             if (staticCounter) {
                 out.println("=========== " + group + " (static counters):");
                 for (Map.Entry<Long, String> entry : sorted.entrySet()) {
                     long counter = entry.getKey() / array.length;
-                    if (counter >= cutoff) {
-                        out.println(format.format(counter) + " \t" + ((counter * 200 + 1) / sum / 2) + "% \t" + entry.getValue());
-                    }
+                    out.format(Locale.US, "%,19d %3d%%  %s\n", counter, percentage(counter, sum), entry.getValue());
                 }
-                out.println(sum + ": total");
+                out.format(Locale.US, "%,19d total\n", sum);
             } else {
                 if (group.startsWith("~")) {
                     out.println("=========== " + group + " (dynamic counters), time = " + seconds + " s:");
                     for (Map.Entry<Long, String> entry : sorted.entrySet()) {
                         long counter = entry.getKey() / array.length;
-                        if (counter >= cutoff) {
-                            out.println(format.format((long) (counter / seconds)) + "/s \t" + ((counter * 200 + 1) / sum / 2) + "% \t" + entry.getValue());
-                        }
+                        out.format(Locale.US, "%,19d/s %3d%%  %s\n", (long) (counter / seconds), percentage(counter, sum), entry.getValue());
                     }
-                    out.println(format.format((long) (sum / seconds)) + "/s: total");
+                    out.format(Locale.US, "%,19d/s total\n", (long) (sum / seconds));
                 } else {
                     out.println("=========== " + group + " (dynamic counters):");
                     for (Map.Entry<Long, String> entry : sorted.entrySet()) {
                         long counter = entry.getKey() / array.length;
-                        if (counter >= cutoff) {
-                            out.println(format.format(counter) + " \t" + ((counter * 200 + 1) / sum / 2) + "% \t" + entry.getValue());
-                        }
+                        out.format(Locale.US, "%,19d %3d%%  %s\n", counter, percentage(counter, sum), entry.getValue());
                     }
-                    out.println(format.format(sum) + ": total");
+                    out.format(Locale.US, "%,19d total\n", sum);
                 }
             }
         }
     }
 
+    private static long percentage(long counter, long sum) {
+        return (counter * 200 + 1) / sum / 2;
+    }
+
     public abstract static class CallbackOutputStream extends OutputStream {
 
         protected final PrintStream delegate;
@@ -282,7 +296,7 @@
                     case 2:
                         if (waitingForEnd) {
                             waitingForEnd = false;
-                            BenchmarkCounters.dump(delegate, (System.nanoTime() - startTime) / 1000000000d, compilerToVM.collectCounters());
+                            BenchmarkCounters.dump(delegate, (System.nanoTime() - startTime) / 1000000000d, compilerToVM.collectCounters(), 100);
                         }
                         break;
                 }
@@ -309,20 +323,43 @@
         if (Options.GenericDynamicCounters.getValue()) {
             enabled = true;
         }
-        if (Options.GenericDynamicCounters.getValue() || Options.BenchmarkDynamicCounters.getValue() != null) {
+        if (Options.TimedDynamicCounters.getValue() > 0) {
+            Thread thread = new Thread() {
+                long lastTime = System.nanoTime();
+                PrintStream out = System.out;
+
+                @Override
+                public void run() {
+                    while (true) {
+                        try {
+                            Thread.sleep(Options.TimedDynamicCounters.getValue());
+                        } catch (InterruptedException e) {
+                        }
+                        long time = System.nanoTime();
+                        dump(out, (time - lastTime) / 1000000000d, compilerToVM.collectCounters(), 10);
+                        lastTime = time;
+                    }
+                }
+            };
+            thread.setDaemon(true);
+            thread.setPriority(Thread.MAX_PRIORITY);
+            thread.start();
+            enabled = true;
+        }
+        if (enabled) {
             clear(compilerToVM.collectCounters());
         }
     }
 
     public static void shutdown(CompilerToVM compilerToVM, long compilerStartTime) {
         if (Options.GenericDynamicCounters.getValue()) {
-            dump(System.out, (System.nanoTime() - compilerStartTime) / 1000000000d, compilerToVM.collectCounters());
+            dump(System.out, (System.nanoTime() - compilerStartTime) / 1000000000d, compilerToVM.collectCounters(), 100);
         }
     }
 
     public static void lower(DynamicCounterNode counter, HotSpotRegistersProvider registers, HotSpotVMConfig config, Kind wordKind) {
         StructuredGraph graph = counter.graph();
-        if (excludedClassPrefix == null || !counter.graph().method().getDeclaringClass().getName().startsWith(excludedClassPrefix)) {
+        if (excludedClassPrefix == null || (counter.graph().method() != null && !counter.graph().method().getDeclaringClass().getName().startsWith(excludedClassPrefix))) {
 
             ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), wordKind, true, false));
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Mon Mar 24 23:50:18 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Mon Mar 24 23:50:48 2014 +0100
@@ -88,6 +88,9 @@
                     }
                     for (int i = 0; i < mergePredecessors.size(); ++i) {
                         AbstractEndNode mergePredecessor = mergePredecessors.get(i);
+                        if (!mergePredecessor.isAlive()) {
+                            break;
+                        }
                         if (xs[i] == null) {
                             continue;
                         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java	Mon Mar 24 23:50:48 2014 +0100
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.common;
+
+import java.util.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.debug.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.graph.*;
+import com.oracle.graal.phases.schedule.*;
+
+/**
+ * This phase add counters for the dynamically executed number of nodes. Incrementing the counter
+ * for each node would be too costly, so this phase takes the compromise that it trusts split
+ * probabilities, but not loop frequencies. This means that it will insert counters at the start of
+ * a method and at each loop header.
+ * 
+ * A schedule is created so that floating nodes can also be taken into account. The weight of a node
+ * is determined heuristically in the
+ * {@link ProfileCompiledMethodsPhase#getNodeWeight(ScheduledNode)} method.
+ * 
+ * Additionally, there's a second counter that's only increased for code sections without invokes.
+ */
+public class ProfileCompiledMethodsPhase extends Phase {
+
+    private static final String GROUP_NAME = "~profiled weight";
+    private static final String GROUP_NAME_WITHOUT = "~profiled weight (invoke-free sections)";
+
+    private static final boolean WITH_SECTION_HEADER = false;
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        ComputeProbabilityClosure closure = new ComputeProbabilityClosure(graph);
+        NodesToDoubles probabilities = closure.apply();
+        SchedulePhase schedule = new SchedulePhase();
+        schedule.apply(graph, false);
+
+        ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true);
+        for (Loop loop : cfg.getLoops()) {
+            double loopProbability = probabilities.get(loop.loopBegin());
+            if (loopProbability > (1D / Integer.MAX_VALUE)) {
+                addSectionCounters(loop.loopBegin(), loop.blocks, loop.children, schedule, probabilities);
+            }
+        }
+        addSectionCounters(graph.start(), Arrays.asList(cfg.getBlocks()), Arrays.asList(cfg.getLoops()), schedule, probabilities);
+    }
+
+    private static void addSectionCounters(FixedWithNextNode start, Collection<Block> sectionBlocks, Collection<Loop> childLoops, SchedulePhase schedule, NodesToDoubles probabilities) {
+        HashSet<Block> blocks = new HashSet<>(sectionBlocks);
+        for (Loop loop : childLoops) {
+            blocks.removeAll(loop.blocks);
+        }
+        double weight = getSectionWeight(schedule, probabilities, blocks) / probabilities.get(start);
+        DynamicCounterNode.addCounterBefore(GROUP_NAME, sectionHead(start), (long) weight, true, start.next());
+        if (!hasInvoke(blocks)) {
+            DynamicCounterNode.addCounterBefore(GROUP_NAME_WITHOUT, sectionHead(start), (long) weight, true, start.next());
+        }
+    }
+
+    private static String sectionHead(Node node) {
+        if (WITH_SECTION_HEADER) {
+            return node.toString();
+        } else {
+            return "";
+        }
+    }
+
+    private static double getSectionWeight(SchedulePhase schedule, NodesToDoubles probabilities, Collection<Block> blocks) {
+        double count = 0;
+        for (Block block : blocks) {
+            double blockProbability = probabilities.get(block.getBeginNode());
+            for (ScheduledNode node : schedule.getBlockToNodesMap().get(block)) {
+                count += blockProbability * getNodeWeight(node);
+            }
+        }
+        return count;
+    }
+
+    private static double getNodeWeight(ScheduledNode node) {
+        if (node instanceof MergeNode) {
+            return ((MergeNode) node).phiPredecessorCount();
+        } else if (node instanceof AbstractBeginNode || node instanceof AbstractEndNode || node instanceof MonitorIdNode || node instanceof ConstantNode || node instanceof ParameterNode ||
+                        node instanceof CallTargetNode || node instanceof ValueProxy || node instanceof VirtualObjectNode || node instanceof ReinterpretNode) {
+            return 0;
+        } else if (node instanceof AccessMonitorNode) {
+            return 10;
+        } else if (node instanceof Access) {
+            return 2;
+        } else if (node instanceof LogicNode || node instanceof ConvertNode || node instanceof BinaryNode || node instanceof NotNode) {
+            return 1;
+        } else if (node instanceof IntegerDivNode || node instanceof FloatDivNode || node instanceof IntegerRemNode || node instanceof FloatRemNode) {
+            return 10;
+        } else if (node instanceof IntegerMulNode || node instanceof FloatMulNode) {
+            return 3;
+        } else if (node instanceof Invoke) {
+            return 5;
+        } else if (node instanceof IfNode || node instanceof SafepointNode) {
+            return 1;
+        } else if (node instanceof SwitchNode) {
+            return node.successors().count();
+        } else if (node instanceof ReturnNode || node instanceof UnwindNode || node instanceof DeoptimizeNode) {
+            return node.successors().count();
+        } else if (node instanceof AbstractNewObjectNode) {
+            return 10;
+        }
+        return 2;
+    }
+
+    private static boolean hasInvoke(Collection<Block> blocks) {
+        boolean hasInvoke = false;
+        for (Block block : blocks) {
+            for (FixedNode fixed : block.getNodes()) {
+                if (fixed instanceof Invoke) {
+                    hasInvoke = true;
+                }
+            }
+        }
+        return hasInvoke;
+    }
+}
--- a/mx/mx_graal.py	Mon Mar 24 23:50:18 2014 +0100
+++ b/mx/mx_graal.py	Mon Mar 24 23:50:48 2014 +0100
@@ -647,11 +647,17 @@
             env.setdefault('ALT_BOOTDIR', mx.java().jdk)
 
             # extract latest release tag for graal
-            tags = [x.split(' ')[0] for x in subprocess.check_output(['hg', 'tags']).split('\n') if x.startswith("graal-")]
+            try:
+                tags = [x.split(' ')[0] for x in subprocess.check_output(['hg', 'tags']).split('\n') if x.startswith("graal-")]
+            except:
+                # not a mercurial repository or hg commands are not available.
+                tags = None
+
             if tags:
                 # extract the most recent tag
                 tag = sorted(tags, key=lambda e: [int(x) for x in e[len("graal-"):].split('.')], reverse=True)[0]
                 env.setdefault('USER_RELEASE_SUFFIX', tag)
+
             if not mx._opts.verbose:
                 runCmd.append('MAKE_VERBOSE=')
             env['JAVA_HOME'] = jdk
--- a/src/share/vm/classfile/systemDictionary.hpp	Mon Mar 24 23:50:18 2014 +0100
+++ b/src/share/vm/classfile/systemDictionary.hpp	Mon Mar 24 23:50:48 2014 +0100
@@ -184,6 +184,7 @@
   do_klass(Long_klass,                                  java_lang_Long,                            Pre                 ) \
                                                                                                                          \
   /* Support for Graal */                                                                                                \
+  do_klass(CompilerThread_klass,                  com_oracle_graal_compiler_CompilerThread,                     Opt) \
   do_klass(BitSet_klass,                          java_util_BitSet,                                             Opt) \
   /* graal.hotspot */                                                                                                \
   do_klass(HotSpotCompiledCode_klass,             com_oracle_graal_hotspot_HotSpotCompiledCode,                 Opt) \
@@ -203,7 +204,6 @@
   do_klass(HotSpotResolvedJavaMethod_klass,       com_oracle_graal_hotspot_meta_HotSpotResolvedJavaMethod,      Opt) \
   do_klass(HotSpotResolvedObjectType_klass,       com_oracle_graal_hotspot_meta_HotSpotResolvedObjectType,      Opt) \
   do_klass(HotSpotMonitorValue_klass,             com_oracle_graal_hotspot_meta_HotSpotMonitorValue,            Opt) \
-  do_klass(CompilerThread_klass,                  com_oracle_graal_hotspot_CompilerThread,                      Opt) \
   /* graal.api.code */                                                                                               \
   do_klass(Assumptions_klass,                     com_oracle_graal_api_code_Assumptions,                        Opt) \
   do_klass(Assumptions_ConcreteMethod_klass,      com_oracle_graal_api_code_Assumptions_ConcreteMethod,         Opt) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Mon Mar 24 23:50:18 2014 +0100
+++ b/src/share/vm/classfile/vmSymbols.hpp	Mon Mar 24 23:50:48 2014 +0100
@@ -288,10 +288,11 @@
   NOT_LP64(  do_alias(intptr_signature,               int_signature)  )                           \
   LP64_ONLY( do_alias(intptr_signature,               long_signature) )                           \
   template(selectAlternative_signature, "(ZLjava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle;") \
-                                                                                                                                       \
-  /* Support for Graal */                                                                                                              \
-  template(java_util_BitSet,	                                       "java/util/BitSet")                                               \
-  /* graal.hotspot */                                                                                                                  \
+                                                                                                                                      \
+  /* Support for Graal */                                                                                                             \
+  template(com_oracle_graal_compiler_CompilerThread,                 "com/oracle/graal/compiler/CompilerThread")                      \
+  template(java_util_BitSet,	                                       "java/util/BitSet")                                              \
+  /* graal.hotspot */                                                                                                                 \
   template(com_oracle_graal_hotspot_HotSpotGraalRuntime,             "com/oracle/graal/hotspot/HotSpotGraalRuntime")                  \
   template(com_oracle_graal_hotspot_HotSpotKlassOop,                 "com/oracle/graal/hotspot/HotSpotKlassOop")                      \
   template(com_oracle_graal_hotspot_HotSpotOptions,                  "com/oracle/graal/hotspot/HotSpotOptions")                       \
@@ -314,7 +315,6 @@
   template(com_oracle_graal_hotspot_meta_HotSpotResolvedJavaMethod,  "com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod")       \
   template(com_oracle_graal_hotspot_meta_HotSpotResolvedObjectType,  "com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType")       \
   template(com_oracle_graal_hotspot_meta_HotSpotMonitorValue,        "com/oracle/graal/hotspot/meta/HotSpotMonitorValue")             \
-  template(com_oracle_graal_hotspot_CompilerThread,                  "com/oracle/graal/hotspot/CompilerThread")                       \
   /* graal.api.meta */                                                                                                                \
   template(com_oracle_graal_api_meta_Constant,                       "com/oracle/graal/api/meta/Constant")                            \
   template(com_oracle_graal_api_meta_ConstantPool,                   "com/oracle/graal/api/meta/ConstantPool")                        \