changeset 16066:f59498d6e8b1

Merged
author Christian Wirth <christian.wirth@oracle.com>
date Fri, 06 Jun 2014 21:36:56 +0200
parents 87414e322d45 (current diff) 03eda0a202e9 (diff)
children 915ebb306fcc
files
diffstat 19 files changed, 114 insertions(+), 98 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Fri Jun 06 15:13:56 2014 +0200
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Fri Jun 06 21:36:56 2014 +0200
@@ -185,7 +185,7 @@
     }
 
     private void emitArithImm8(int op, Register dst, int imm8) {
-        int encode = prefixAndEncode(op, dst.encoding, true);
+        int encode = prefixAndEncode(op, false, dst.encoding, true);
         emitByte(0x80);
         emitByte(0xC0 | encode);
         emitByte(imm8);
@@ -560,7 +560,7 @@
     }
 
     public final void cmpb(Register dst, Register src) {
-        int encode = prefixAndEncode(dst.encoding, src.encoding, true);
+        int encode = prefixAndEncode(dst.encoding, true, src.encoding, true);
         emitByte(0x3A);
         emitByte(0xC0 | encode);
     }
@@ -1137,7 +1137,7 @@
     }
 
     public final void movsbl(Register dst, Register src) {
-        int encode = prefixAndEncode(dst.encoding, src.encoding, true);
+        int encode = prefixAndEncode(dst.encoding, false, src.encoding, true);
         emitByte(0x0F);
         emitByte(0xBE);
         emitByte(0xC0 | encode);
@@ -2042,17 +2042,17 @@
     }
 
     private int prefixAndEncode(int dstEnc, int srcEnc) {
-        return prefixAndEncode(dstEnc, srcEnc, false);
+        return prefixAndEncode(dstEnc, false, srcEnc, false);
     }
 
-    private int prefixAndEncode(int dstEncoding, int srcEncoding, boolean byteinst) {
+    private int prefixAndEncode(int dstEncoding, boolean dstIsByte, int srcEncoding, boolean srcIsByte) {
         int srcEnc = srcEncoding;
         int dstEnc = dstEncoding;
         if (dstEnc < 8) {
             if (srcEnc >= 8) {
                 emitByte(Prefix.REXB);
                 srcEnc -= 8;
-            } else if (byteinst && (srcEnc >= 4 || dstEnc >= 4)) {
+            } else if ((srcIsByte && srcEnc >= 4) || (dstIsByte && dstEnc >= 4)) {
                 emitByte(Prefix.REX);
             }
         } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java	Fri Jun 06 15:13:56 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java	Fri Jun 06 21:36:56 2014 +0200
@@ -73,7 +73,7 @@
                 break;
             }
 
-            LoopTransformations.peel(osrLoop, true);
+            LoopTransformations.peel(osrLoop);
             for (Node usage : osr.usages().snapshot()) {
                 ProxyNode proxy = (ProxyNode) usage;
                 proxy.replaceAndDelete(proxy.value());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java	Fri Jun 06 15:13:56 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java	Fri Jun 06 21:36:56 2014 +0200
@@ -20,6 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+//JaCoCo Exclude
 package com.oracle.graal.hotspot.replacements;
 
 import static com.oracle.graal.api.meta.LocationIdentity.*;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Fri Jun 06 15:13:56 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Fri Jun 06 21:36:56 2014 +0200
@@ -57,9 +57,9 @@
         return loop;
     }
 
-    public abstract LoopFragment duplicate(boolean createExitFrameStates);
+    public abstract LoopFragment duplicate();
 
-    public abstract void insertBefore(LoopEx l, boolean createExitFrameStates);
+    public abstract void insertBefore(LoopEx l);
 
     public void disconnect() {
         // TODO (gd) possibly abstract
@@ -299,7 +299,7 @@
      * Merges the early exits (i.e. loop exits) that were duplicated as part of this fragment, with
      * the original fragment's exits.
      */
-    protected void mergeEarlyExits(boolean createExitFrameStates) {
+    protected void mergeEarlyExits() {
         assert isDuplicate();
         StructuredGraph graph = graph();
         for (BeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().lirLoop().getExits())) {
@@ -325,24 +325,19 @@
             FrameState state = null;
             if (exitState != null) {
                 state = exitState;
+                exitState = exitState.duplicateWithVirtualState();
+                loopEarlyExit.setStateAfter(exitState);
                 merge.setStateAfter(state);
-
-                if (createExitFrameStates) {
-                    exitState = exitState.duplicateWithVirtualState();
-                    loopEarlyExit.setStateAfter(exitState);
-                    /*
-                     * Using the old exit's state as the merge's state is necessary because some of
-                     * the VirtualState nodes contained in the old exit's state may be shared by
-                     * other dominated VirtualStates. Those dominated virtual states need to see the
-                     * proxy->phi update that are applied below.
-                     * 
-                     * We now update the original fragment's nodes accordingly:
-                     */
-                    state.applyToVirtual(node -> original.nodes.clearAndGrow(node));
-                    exitState.applyToVirtual(node -> original.nodes.markAndGrow(node));
-                } else {
-                    loopEarlyExit.setStateAfter(null);
-                }
+                /*
+                 * Using the old exit's state as the merge's state is necessary because some of the
+                 * VirtualState nodes contained in the old exit's state may be shared by other
+                 * dominated VirtualStates. Those dominated virtual states need to see the
+                 * proxy->phi update that are applied below.
+                 *
+                 * We now update the original fragment's nodes accordingly:
+                 */
+                state.applyToVirtual(node -> original.nodes.clearAndGrow(node));
+                exitState.applyToVirtual(node -> original.nodes.markAndGrow(node));
             }
             FrameState finalExitState = exitState;
 
@@ -378,7 +373,7 @@
                     if (merge.isPhiAtMerge(usage)) {
                         return false;
                     }
-                    if (finalExitState != null && usage instanceof VirtualState) {
+                    if (usage instanceof VirtualState) {
                         VirtualState stateUsage = (VirtualState) usage;
                         if (finalExitState.isPartOfThisState(stateUsage)) {
                             return false;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Fri Jun 06 15:13:56 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Fri Jun 06 21:36:56 2014 +0200
@@ -63,7 +63,7 @@
     }
 
     @Override
-    public LoopFragmentInside duplicate(boolean createExitFrameStates) {
+    public LoopFragmentInside duplicate() {
         assert !isDuplicate();
         return new LoopFragmentInside(this);
     }
@@ -85,14 +85,14 @@
     }
 
     @Override
-    public void insertBefore(LoopEx loop, boolean createExitFrameStates) {
+    public void insertBefore(LoopEx loop) {
         assert this.isDuplicate() && this.original().loop() == loop;
 
         patchNodes(dataFixBefore);
 
         BeginNode end = mergeEnds();
 
-        mergeEarlyExits(createExitFrameStates);
+        mergeEarlyExits();
 
         original().patchPeeling(this);
 
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInsideBefore.java	Fri Jun 06 15:13:56 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInsideBefore.java	Fri Jun 06 21:36:56 2014 +0200
@@ -45,7 +45,7 @@
     }
 
     @Override
-    public LoopFragmentInsideBefore duplicate(boolean createExitFrameStates) {
+    public LoopFragmentInsideBefore duplicate() {
         return new LoopFragmentInsideBefore(this);
     }
 
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInsideFrom.java	Fri Jun 06 15:13:56 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInsideFrom.java	Fri Jun 06 21:36:56 2014 +0200
@@ -45,7 +45,7 @@
     }
 
     @Override
-    public LoopFragmentInsideFrom duplicate(boolean createExitFrameStates) {
+    public LoopFragmentInsideFrom duplicate() {
         return new LoopFragmentInsideFrom(this);
     }
 
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java	Fri Jun 06 15:13:56 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java	Fri Jun 06 21:36:56 2014 +0200
@@ -39,18 +39,18 @@
     }
 
     @Override
-    public LoopFragmentWhole duplicate(boolean createExitFrameStates) {
+    public LoopFragmentWhole duplicate() {
         LoopFragmentWhole loopFragmentWhole = new LoopFragmentWhole(this);
-        loopFragmentWhole.reify(createExitFrameStates);
+        loopFragmentWhole.reify();
         return loopFragmentWhole;
     }
 
-    private void reify(boolean createExitFrameStates) {
+    private void reify() {
         assert this.isDuplicate();
 
         patchNodes(null);
 
-        mergeEarlyExits(createExitFrameStates);
+        mergeEarlyExits();
     }
 
     @Override
@@ -102,7 +102,7 @@
     }
 
     @Override
-    public void insertBefore(LoopEx loop, boolean createExitFrameStates) {
+    public void insertBefore(LoopEx loop) {
         // TODO Auto-generated method stub
 
     }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Fri Jun 06 15:13:56 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Fri Jun 06 21:36:56 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -44,14 +44,14 @@
 
     public static void invert(LoopEx loop, FixedNode point) {
         LoopFragmentInsideBefore head = loop.insideBefore(point);
-        LoopFragmentInsideBefore duplicate = head.duplicate(true);
+        LoopFragmentInsideBefore duplicate = head.duplicate();
         head.disconnect();
-        head.insertBefore(loop, true);
+        head.insertBefore(loop);
         duplicate.appendInside(loop);
     }
 
-    public static void peel(LoopEx loop, boolean createExitFrameStates) {
-        loop.inside().duplicate(createExitFrameStates).insertBefore(loop, createExitFrameStates);
+    public static void peel(LoopEx loop) {
+        loop.inside().duplicate().insertBefore(loop);
     }
 
     public static void fullUnroll(LoopEx loop, PhaseContext context, CanonicalizerPhase canonicalizer) {
@@ -61,7 +61,7 @@
         StructuredGraph graph = loopBegin.graph();
         while (!loopBegin.isDeleted()) {
             Mark mark = graph.getMark();
-            peel(loop, false);
+            peel(loop);
             canonicalizer.applyIncremental(graph, context, mark);
             loopBegin.removeDeadPhis();
             loop.invalidateFragments();
@@ -88,7 +88,7 @@
         while (successors.hasNext()) {
             Position position = successors.nextPosition();
             // create a new loop duplicate, connect it and simplify it
-            LoopFragmentWhole duplicateLoop = originalLoop.duplicate(true);
+            LoopFragmentWhole duplicateLoop = originalLoop.duplicate();
             controlSplitClass.set(newControlSplit, position, BeginNode.begin(duplicateLoop.entryPoint()));
             ControlSplitNode duplicatedControlSplit = duplicateLoop.getDuplicatedNode(controlSplitNode);
             graph.removeSplitPropagate(duplicatedControlSplit, (BeginNode) controlSplitClass.get(duplicatedControlSplit, position));
@@ -105,8 +105,8 @@
         }
         // TODO (gd) implement counted loop
         LoopFragmentWhole main = loop.whole();
-        LoopFragmentWhole prologue = main.duplicate(true);
-        prologue.insertBefore(loop, false);
+        LoopFragmentWhole prologue = main.duplicate();
+        prologue.insertBefore(loop);
         // CountedLoopBeginNode counted = prologue.countedLoop();
         // StructuredGraph graph = (StructuredGraph) counted.graph();
         // ValueNode tripCountPrologue = counted.tripCount();
@@ -115,7 +115,7 @@
         // graph.replaceFloating(tripCountMain, "tripCountMain - (tripCountPrologue % factor)");
         LoopFragmentInside inside = loop.inside();
         for (int i = 0; i < factor; i++) {
-            inside.duplicate(false).appendInside(loop);
+            inside.duplicate().appendInside(loop);
         }
     }
 
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java	Fri Jun 06 15:13:56 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java	Fri Jun 06 21:36:56 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -43,7 +43,7 @@
                 for (LoopEx loop : data.outterFirst()) {
                     if (LoopPolicies.shouldPeel(loop, probabilities)) {
                         Debug.log("Peeling %s", loop);
-                        LoopTransformations.peel(loop, true);
+                        LoopTransformations.peel(loop);
                         Debug.dump(graph, "After peeling %s", loop);
                     }
                 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java	Fri Jun 06 15:13:56 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java	Fri Jun 06 21:36:56 2014 +0200
@@ -20,6 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+//JaCoCo Exclude
 package com.oracle.graal.nodes.java;
 
 import java.lang.reflect.*;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java	Fri Jun 06 15:13:56 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java	Fri Jun 06 21:36:56 2014 +0200
@@ -28,10 +28,15 @@
 import com.oracle.graal.api.meta.ResolvedJavaMethod;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.common.CanonicalizerPhase;
 import com.oracle.graal.phases.common.inlining.InliningUtil;
 import com.oracle.graal.phases.common.inlining.info.elem.Inlineable;
 import com.oracle.graal.phases.common.inlining.info.elem.InlineableMacroNode;
 import com.oracle.graal.phases.common.inlining.info.elem.InlineableGraph;
+import com.oracle.graal.phases.common.inlining.walker.CallsiteHolder;
+import com.oracle.graal.phases.common.inlining.walker.CallsiteHolderDummy;
+import com.oracle.graal.phases.common.inlining.walker.CallsiteHolderExplorable;
+import com.oracle.graal.phases.tiers.HighTierContext;
 
 public abstract class AbstractInlineInfo implements InlineInfo {
 
@@ -80,4 +85,22 @@
             }
         }
     }
+
+    public final void populateInlinableElements(HighTierContext context, Assumptions calleeAssumptions, CanonicalizerPhase canonicalizer) {
+        for (int i = 0; i < numberOfMethods(); i++) {
+            Inlineable elem = Inlineable.getInlineableElement(methodAt(i), invoke, context.replaceAssumptions(calleeAssumptions), canonicalizer);
+            setInlinableElement(i, elem);
+        }
+    }
+
+    public final CallsiteHolder buildCallsiteHolderForElement(int index, double invokeProbability, double invokeRelevance) {
+        Inlineable elem = inlineableElementAt(index);
+        if (elem instanceof InlineableGraph) {
+            InlineableGraph ig = (InlineableGraph) elem;
+            return new CallsiteHolderExplorable(ig.getGraph(), invokeProbability * probabilityAt(index), invokeRelevance * relevanceAt(index));
+        } else {
+            assert elem instanceof InlineableMacroNode;
+            return CallsiteHolderDummy.DUMMY_CALLSITE_HOLDER;
+        }
+    }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/InlineInfo.java	Fri Jun 06 15:13:56 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/InlineInfo.java	Fri Jun 06 21:36:56 2014 +0200
@@ -30,7 +30,10 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.Invoke;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.phases.common.CanonicalizerPhase;
 import com.oracle.graal.phases.common.inlining.info.elem.Inlineable;
+import com.oracle.graal.phases.common.inlining.walker.CallsiteHolder;
+import com.oracle.graal.phases.tiers.HighTierContext;
 import com.oracle.graal.phases.util.Providers;
 
 /**
@@ -82,4 +85,8 @@
     void tryToDevirtualizeInvoke(MetaAccessProvider metaAccess, Assumptions assumptions);
 
     boolean shouldInline();
+
+    void populateInlinableElements(HighTierContext context, Assumptions calleeAssumptions, CanonicalizerPhase canonicalizer);
+
+    CallsiteHolder buildCallsiteHolderForElement(int index, double invokeProbability, double invokeRelevance);
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderDummy.java	Fri Jun 06 15:13:56 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderDummy.java	Fri Jun 06 21:36:56 2014 +0200
@@ -33,7 +33,10 @@
  */
 public final class CallsiteHolderDummy extends CallsiteHolder {
 
-    public CallsiteHolderDummy() {
+    public static final CallsiteHolderDummy DUMMY_CALLSITE_HOLDER = new CallsiteHolderDummy();
+
+    private CallsiteHolderDummy() {
+        // no instances other than the singleton
     }
 
     @Override
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java	Fri Jun 06 15:13:56 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java	Fri Jun 06 21:36:56 2014 +0200
@@ -51,6 +51,7 @@
 import java.util.function.ToDoubleFunction;
 
 import static com.oracle.graal.compiler.common.GraalOptions.*;
+import static com.oracle.graal.phases.common.inlining.walker.CallsiteHolderDummy.DUMMY_CALLSITE_HOLDER;
 
 /**
  * Holds the data for building the callee graphs recursively: graphs and invocations (each
@@ -58,7 +59,6 @@
  */
 public class InliningData {
 
-    private static final CallsiteHolder DUMMY_CALLSITE_HOLDER = new CallsiteHolderDummy();
     // Metrics
     private static final DebugMetric metricInliningPerformed = Debug.metric("InliningPerformed");
     private static final DebugMetric metricInliningRuns = Debug.metric("InliningRuns");
@@ -88,7 +88,7 @@
 
         Assumptions rootAssumptions = context.getAssumptions();
         invocationQueue.push(new MethodInvocation(null, rootAssumptions, 1.0, 1.0));
-        pushExplorableGraph(rootGraph, 1.0, 1.0);
+        graphQueue.push(new CallsiteHolderExplorable(rootGraph, 1.0, 1.0));
     }
 
     private String checkTargetConditionsHelper(ResolvedJavaMethod method) {
@@ -378,7 +378,8 @@
     /**
      * @return true iff inlining was actually performed
      */
-    private boolean tryToInline(CallsiteHolderExplorable callerCallsiteHolder, MethodInvocation calleeInvocation, MethodInvocation parentInvocation, int inliningDepth) {
+    private boolean tryToInline(MethodInvocation calleeInvocation, MethodInvocation parentInvocation, int inliningDepth) {
+        CallsiteHolderExplorable callerCallsiteHolder = (CallsiteHolderExplorable) currentGraph();
         InlineInfo calleeInfo = calleeInvocation.callee();
         assert callerCallsiteHolder.containsInvoke(calleeInfo.invoke());
         Assumptions callerAssumptions = parentInvocation.assumptions();
@@ -404,10 +405,11 @@
         Invoke invoke = callsiteHolder.popInvoke();
         MethodInvocation callerInvocation = currentInvocation();
         Assumptions parentAssumptions = callerInvocation.assumptions();
-        Assumptions calleeAssumptions = new Assumptions(parentAssumptions.useOptimisticAssumptions());
-        InlineInfo info = populateInlineInfo(invoke, parentAssumptions, calleeAssumptions);
+        InlineInfo info = getInlineInfo(invoke, parentAssumptions);
 
         if (info != null) {
+            Assumptions calleeAssumptions = new Assumptions(parentAssumptions.useOptimisticAssumptions());
+            info.populateInlinableElements(context, calleeAssumptions, canonicalizer);
             double invokeProbability = callsiteHolder.invokeProbability(invoke);
             double invokeRelevance = callsiteHolder.invokeRelevance(invoke);
             MethodInvocation methodInvocation = new MethodInvocation(info, calleeAssumptions, invokeProbability, invokeRelevance);
@@ -415,34 +417,10 @@
         }
     }
 
-    private InlineInfo populateInlineInfo(Invoke invoke, Assumptions parentAssumptions, Assumptions calleeAssumptions) {
-        InlineInfo info = getInlineInfo(invoke, parentAssumptions);
-        if (info == null) {
-            return null;
-        }
-        for (int i = 0; i < info.numberOfMethods(); i++) {
-            Inlineable elem = Inlineable.getInlineableElement(info.methodAt(i), info.invoke(), context.replaceAssumptions(calleeAssumptions), canonicalizer);
-            info.setInlinableElement(i, elem);
-        }
-        return info;
-    }
-
     public int graphCount() {
         return graphQueue.size();
     }
 
-    private void pushExplorableGraph(StructuredGraph graph, double probability, double relevance) {
-        assert graph != null;
-        assert !contains(graph);
-        graphQueue.push(new CallsiteHolderExplorable(graph, probability, relevance));
-        assert graphQueue.size() <= maxGraphs;
-    }
-
-    private void pushDummyGraph() {
-        graphQueue.push(DUMMY_CALLSITE_HOLDER);
-        assert graphQueue.size() <= maxGraphs;
-    }
-
     public boolean hasUnprocessedGraphs() {
         return !graphQueue.isEmpty();
     }
@@ -492,13 +470,10 @@
         double invokeProbability = methodInvocation.probability();
         double invokeRelevance = methodInvocation.relevance();
         for (int i = 0; i < info.numberOfMethods(); i++) {
-            Inlineable elem = info.inlineableElementAt(i);
-            if (elem instanceof InlineableGraph) {
-                pushExplorableGraph(((InlineableGraph) elem).getGraph(), invokeProbability * info.probabilityAt(i), invokeRelevance * info.relevanceAt(i));
-            } else {
-                assert elem instanceof InlineableMacroNode;
-                pushDummyGraph();
-            }
+            CallsiteHolder ch = info.buildCallsiteHolderForElement(i, invokeProbability, invokeRelevance);
+            assert (ch == DUMMY_CALLSITE_HOLDER) || !contains(ch.graph());
+            graphQueue.push(ch);
+            assert graphQueue.size() <= maxGraphs;
         }
     }
 
@@ -546,6 +521,7 @@
     }
 
     private boolean contains(StructuredGraph graph) {
+        assert graph != null;
         for (CallsiteHolder info : graphQueue) {
             if (info.graph() == graph) {
                 return true;
@@ -593,7 +569,7 @@
             popInvocation();
             final MethodInvocation parentInvoke = currentInvocation();
             try (Debug.Scope s = Debug.scope("Inlining", inliningContext())) {
-                return tryToInline((CallsiteHolderExplorable) currentGraph(), currentInvocation, parentInvoke, inliningDepth() + 1);
+                return tryToInline(currentInvocation, parentInvoke, inliningDepth() + 1);
             } catch (Throwable e) {
                 throw Debug.handle(e);
             }
--- a/mx/mx_graal.py	Fri Jun 06 15:13:56 2014 +0200
+++ b/mx/mx_graal.py	Fri Jun 06 21:36:56 2014 +0200
@@ -1804,7 +1804,7 @@
 
     path = join(_graal_home, 'lib', 'hcfdis-1.jar')
     if not exists(path):
-        mx.download(path, ['http://lafo.ssw.uni-linz.ac.at/hcfdis-1.jar'])
+        mx.download(path, ['http://lafo.ssw.uni-linz.ac.at/hcfdis-2.jar'])
     mx.run_java(['-jar', path] + args.files)
 
     if args.map is not None:
--- a/mxtool/mx.py	Fri Jun 06 15:13:56 2014 +0200
+++ b/mxtool/mx.py	Fri Jun 06 21:36:56 2014 +0200
@@ -1978,8 +1978,9 @@
             if not self.jdtJar:
                 mainJava = java()
                 if not args.error_prone:
-                    self.logCompilation('javac')
-                    javacCmd = [mainJava.javac, '-g', '-J-Xmx1g', '-source', compliance, '-target', compliance, '-classpath', cp, '-d', outputDir, '-bootclasspath', jdk.bootclasspath(), '-endorseddirs', jdk.endorseddirs(), '-extdirs', jdk.extdirs()]
+                    javac = args.alt_javac if args.alt_javac else mainJava.javac
+                    self.logCompilation('javac' if not args.alt_javac else args.alt_javac)
+                    javacCmd = [javac, '-g', '-J-Xmx1g', '-source', compliance, '-target', compliance, '-classpath', cp, '-d', outputDir, '-bootclasspath', jdk.bootclasspath(), '-endorseddirs', jdk.endorseddirs(), '-extdirs', jdk.extdirs()]
                     if jdk.debug_port is not None:
                         javacCmd += ['-J-Xdebug', '-J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(jdk.debug_port)]
                     javacCmd += processorArgs
@@ -2063,10 +2064,11 @@
     parser.add_argument('--no-native', action='store_false', dest='native', help='do not build native projects')
     parser.add_argument('--jdt-warning-as-error', action='store_true', help='convert all Eclipse batch compiler warnings to errors')
     parser.add_argument('--jdt-show-task-tags', action='store_true', help='show task tags as Eclipse batch compiler warnings')
+    parser.add_argument('--alt-javac', dest='alt_javac', help='path to alternative javac executable', metavar='<path>')
     compilerSelect = parser.add_mutually_exclusive_group()
     compilerSelect.add_argument('--error-prone', dest='error_prone', help='path to error-prone.jar', metavar='<path>')
     compilerSelect.add_argument('--jdt', help='path to ecj.jar, the Eclipse batch compiler', default=_defaultEcjPath(), metavar='<path>')
-    compilerSelect.add_argument('--force-javac', action='store_true', dest='javac', help='use javac despite ecj.jar is found or not')
+    compilerSelect.add_argument('--force-javac', action='store_true', dest='javac', help='use javac whether ecj.jar is found or not')
 
     if suppliedParser:
         parser.add_argument('remainder', nargs=REMAINDER, metavar='...')
--- a/src/cpu/x86/vm/assembler_x86.cpp	Fri Jun 06 15:13:56 2014 +0200
+++ b/src/cpu/x86/vm/assembler_x86.cpp	Fri Jun 06 21:36:56 2014 +0200
@@ -1824,7 +1824,7 @@
 
 void Assembler::movsbl(Register dst, Register src) { // movsxb
   NOT_LP64(assert(src->has_byte_register(), "must have byte register"));
-  int encode = prefix_and_encode(dst->encoding(), src->encoding(), true);
+  int encode = prefix_and_encode(dst->encoding(), false, src->encoding(), true);
   emit_int8(0x0F);
   emit_int8((unsigned char)0xBE);
   emit_int8((unsigned char)(0xC0 | encode));
@@ -1916,8 +1916,13 @@
 }
 
 void Assembler::movzbl(Register dst, Register src) { // movzxb
-  NOT_LP64(assert(src->has_byte_register(), "must have byte register"));
-  int encode = prefix_and_encode(dst->encoding(), src->encoding(), true);
+#ifdef _LP64
+  // Requires the REX.W prefix to be able to access source register rsi and rdi
+  int encode = prefixq_and_encode(dst->encoding(), src->encoding());
+#else
+  assert(src->has_byte_register(), "must have byte register");
+  int encode = prefix_and_encode(dst->encoding(), src->encoding());
+#endif
   emit_int8(0x0F);
   emit_int8((unsigned char)0xB6);
   emit_int8(0xC0 | encode);
@@ -4562,12 +4567,12 @@
   return reg_enc;
 }
 
-int Assembler::prefix_and_encode(int dst_enc, int src_enc, bool byteinst) {
+int Assembler::prefix_and_encode(int dst_enc, bool dst_is_byte, int src_enc, bool src_is_byte) {
   if (dst_enc < 8) {
     if (src_enc >= 8) {
       prefix(REX_B);
       src_enc -= 8;
-    } else if (byteinst && (src_enc >= 4 || dst_enc >= 4)) {
+    } else if ((src_is_byte && src_enc >= 4) || (dst_is_byte && dst_enc >= 4)) {
       prefix(REX);
     }
   } else {
--- a/src/cpu/x86/vm/assembler_x86.hpp	Fri Jun 06 15:13:56 2014 +0200
+++ b/src/cpu/x86/vm/assembler_x86.hpp	Fri Jun 06 21:36:56 2014 +0200
@@ -556,7 +556,10 @@
   int prefix_and_encode(int reg_enc, bool byteinst = false);
   int prefixq_and_encode(int reg_enc);
 
-  int prefix_and_encode(int dst_enc, int src_enc, bool byteinst = false);
+  int prefix_and_encode(int dst_enc, int src_enc) {
+    return prefix_and_encode(dst_enc, false, src_enc, false);
+  }
+  int prefix_and_encode(int dst_enc, bool dst_is_byte, int src_enc, bool src_is_byte);
   int prefixq_and_encode(int dst_enc, int src_enc);
 
   void prefix(Register reg);