changeset 22176:2378eaca447a

Merge.
author Doug Simon <doug.simon@oracle.com>
date Thu, 09 Jul 2015 00:18:57 +0200
parents 42ee3b572280 (diff) a19ed9118dc4 (current diff)
children 8f62f2bae04e
files mx.graal/suite.py
diffstat 26 files changed, 512 insertions(+), 281 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGELOG.md	Wed Jul 08 12:40:07 2015 +0200
+++ b/CHANGELOG.md	Thu Jul 09 00:18:57 2015 +0200
@@ -5,8 +5,9 @@
 
 ## `tip`
 ### Graal
-* Add experimental support constructing low-level IR in SSA form.
-* Add experimental support for SSA linear scan register allocation.
+* Add support for constructing low-level IR in SSA form (default behavior).
+* Add support for SSA linear scan register allocation (default behavior).
+* Remove dummy parameter `includeAbstract` from `ResolvedJavaType#resolveMethod()`; The behavior is now the `includeAbstract==true` case. The `includeAbstract==false` variant is available via `resolveConcreteMethod()`.
 ...
 
 ### Truffle
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Thu Jul 09 00:18:57 2015 +0200
@@ -1263,6 +1263,14 @@
         op3(Fpop1, Fmovd, null, rs2, rd);
     }
 
+    public void fsrc2s(Register rs2, Register rd) {
+        op3(Impdep1, Fsrc2s, null, rs2, rd);
+    }
+
+    public void fsrc2d(Register rs2, Register rd) {
+        op3(Impdep1, Fsrc2d, null, rs2, rd);
+    }
+
     public void fmuls(Register rs1, Register rs2, Register rd) {
         op3(Fpop1, Fmuls, rs1, rs2, rd);
     }
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Thu Jul 09 00:18:57 2015 +0200
@@ -96,15 +96,15 @@
         }
     }
 
-    private class AMD64SpillMoveFactory implements LIRGeneratorTool.SpillMoveFactory {
+    private class AMD64SpillMoveFactory extends SpillMoveFactoryBase {
 
         @Override
-        public LIRInstruction createMove(AllocatableValue result, Value input) {
+        protected LIRInstruction createMoveIntern(AllocatableValue result, Value input) {
             return AMD64LIRGenerator.this.createMove(result, input);
         }
 
         @Override
-        public LIRInstruction createStackMove(AllocatableValue result, Value input) {
+        protected LIRInstruction createStackMoveIntern(AllocatableValue result, Value input) {
             return AMD64LIRGenerator.this.createStackMove(result, input);
         }
 
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Thu Jul 09 00:18:57 2015 +0200
@@ -287,7 +287,7 @@
     public static final OptionValue<Boolean> MatchExpressions = new OptionValue<>(true);
 
     @Option(help = "Generate SSA LIR.", type = OptionType.Debug)
-    public static final OptionValue<Boolean> SSA_LIR = new OptionValue<>(false);
+    public static final OptionValue<Boolean> SSA_LIR = new OptionValue<>(true);
 
     /**
      * Counts the various paths taken through snippets.
--- a/graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/SPARCAllocatorTest.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/SPARCAllocatorTest.java	Thu Jul 09 00:18:57 2015 +0200
@@ -40,7 +40,7 @@
 
     @Test
     public void test1() {
-        testAllocation("test1snippet", 1, 0, 0);
+        testAllocation("test1snippet", 2, 0, 0);
     }
 
     public static long test1snippet(long x) {
@@ -49,7 +49,7 @@
 
     @Test
     public void test2() {
-        testAllocation("test2snippet", 1, 0, 0);
+        testAllocation("test2snippet", 2, 0, 0);
     }
 
     public static long test2snippet(long x) {
@@ -58,7 +58,7 @@
 
     @Test
     public void test3() {
-        testAllocation("test3snippet", 3, 0, 0);
+        testAllocation("test3snippet", 4, 0, 0);
     }
 
     public static long test3snippet(long x) {
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu Jul 09 00:18:57 2015 +0200
@@ -75,15 +75,15 @@
     private Variable constantTableBase;
     private SPARCLoadConstantTableBaseOp loadConstantTableBaseOp;
 
-    private class SPARCSpillMoveFactory implements LIRGeneratorTool.SpillMoveFactory {
+    private class SPARCSpillMoveFactory extends SpillMoveFactoryBase {
 
         @Override
-        public LIRInstruction createMove(AllocatableValue result, Value input) {
+        protected LIRInstruction createMoveIntern(AllocatableValue result, Value input) {
             return SPARCLIRGenerator.this.createMove(result, input);
         }
 
         @Override
-        public LIRInstruction createStackMove(AllocatableValue result, Value input) {
+        protected LIRInstruction createStackMoveIntern(AllocatableValue result, Value input) {
             return SPARCLIRGenerator.this.createStackMove(result, input);
         }
     }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Thu Jul 09 00:18:57 2015 +0200
@@ -82,6 +82,11 @@
      */
     private StackSlot deoptimizationRescueSlot;
 
+    /**
+     * Value where the address for safepoint poll is kept.
+     */
+    private AllocatableValue safepointAddressValue;
+
     @Override
     public StackSlotValue getLockSlot(int lockDepth) {
         return getLockStack().makeLockSlot(lockDepth);
@@ -154,12 +159,11 @@
             operand = resultOperandFor(input.getLIRKind());
             emitMove(operand, input);
         }
-        append(new SPARCHotSpotReturnOp(operand, getStub() != null, runtime().getConfig()));
+        append(new SPARCHotSpotReturnOp(operand, getStub() != null, runtime().getConfig(), getSafepointAddressValue()));
     }
 
     @Override
     public void emitTailcall(Value[] args, Value address) {
-        // append(new AMD64TailcallOp(args, address));
         throw JVMCIError.unimplemented();
     }
 
@@ -477,4 +481,11 @@
             return null;
         }
     }
+
+    public AllocatableValue getSafepointAddressValue() {
+        if (this.safepointAddressValue == null) {
+            this.safepointAddressValue = newVariable(LIRKind.value(target().wordKind));
+        }
+        return this.safepointAddressValue;
+    }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java	Thu Jul 09 00:18:57 2015 +0200
@@ -132,6 +132,13 @@
     }
 
     @Override
+    protected void emitPrologue(StructuredGraph graph) {
+        super.emitPrologue(graph);
+        AllocatableValue var = getGen().getSafepointAddressValue();
+        append(new SPARCHotSpotSafepointOp.SPARCLoadSafepointPollAddress(var, getGen().config));
+    }
+
+    @Override
     public void visitFullInfopointNode(FullInfopointNode i) {
         if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) {
             Debug.log("Ignoring InfopointNode for AFTER_BCI");
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotReturnOp.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotReturnOp.java	Thu Jul 09 00:18:57 2015 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.hotspot.sparc;
 
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static jdk.internal.jvmci.code.ValueUtil.*;
 import jdk.internal.jvmci.hotspot.*;
 import jdk.internal.jvmci.meta.*;
-import jdk.internal.jvmci.sparc.*;
 
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.lir.*;
@@ -41,23 +41,23 @@
     public static final SizeEstimate SIZE = SizeEstimate.create(2);
 
     @Use({REG, ILLEGAL}) protected Value value;
+    @Use({REG}) protected Value safepointPollAddress;
     private final boolean isStub;
     private final HotSpotVMConfig config;
 
-    SPARCHotSpotReturnOp(Value value, boolean isStub, HotSpotVMConfig config) {
+    SPARCHotSpotReturnOp(Value value, boolean isStub, HotSpotVMConfig config, Value safepointPoll) {
         super(TYPE, SIZE);
         this.value = value;
         this.isStub = isStub;
         this.config = config;
+        this.safepointPollAddress = safepointPoll;
     }
 
     @Override
     public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
         if (!isStub) {
             // Every non-stub compile method must have a poll before the return.
-            // Using the same scratch register as LIR_Assembler::return_op
-            // in c1_LIRAssembler_sparc.cpp
-            SPARCHotSpotSafepointOp.emitCode(crb, masm, config, true, null, SPARC.l0);
+            SPARCHotSpotSafepointOp.emitCode(crb, masm, config, true, null, asRegister(safepointPollAddress));
         }
         ReturnOp.emitCodeHelper(crb, masm);
     }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java	Thu Jul 09 00:18:57 2015 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.sparc;
 
+import static jdk.internal.jvmci.code.ValueUtil.*;
 import static jdk.internal.jvmci.sparc.SPARC.*;
 import jdk.internal.jvmci.code.*;
 import jdk.internal.jvmci.hotspot.*;
@@ -43,30 +44,47 @@
     public static final SizeEstimate SIZE = SizeEstimate.create(9);
 
     @State protected LIRFrameState state;
-    @SuppressFBWarnings(value = "BC_IMPOSSIBLE_CAST", justification = "changed by the register allocator") @Temp({OperandFlag.REG}) private AllocatableValue temp;
-
+    @Use({OperandFlag.REG}) AllocatableValue safepointPollAddress;
     private final HotSpotVMConfig config;
 
     public SPARCHotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, LIRGeneratorTool tool) {
         super(TYPE, SIZE);
         this.state = state;
         this.config = config;
-        this.temp = tool.newVariable(LIRKind.value(tool.target().wordKind));
+        SPARCHotSpotLIRGenerator lirGen = (SPARCHotSpotLIRGenerator) tool;
+        safepointPollAddress = lirGen.getSafepointAddressValue();
     }
 
     @Override
     public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-        Register scratch = ((RegisterValue) temp).getRegister();
-        emitCode(crb, masm, config, false, state, scratch);
+        emitCode(crb, masm, config, false, state, asRegister(safepointPollAddress));
+    }
+
+    public static void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm, HotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register safepointPollAddress) {
+        crb.recordMark(atReturn ? config.MARKID_POLL_RETURN_FAR : config.MARKID_POLL_FAR);
+        if (state != null) {
+            final int pos = masm.position();
+            crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
+        }
+        masm.ldx(new SPARCAddress(safepointPollAddress, 0), g0);
     }
 
-    public static void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm, HotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) {
-        new Setx(config.safepointPollingAddress, scratch).emit(masm);
-        crb.recordMark(atReturn ? config.MARKID_POLL_RETURN_FAR : config.MARKID_POLL_FAR);
-        final int pos = masm.position();
-        masm.ldx(new SPARCAddress(scratch, 0), g0);
-        if (state != null) {
-            crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
+    public static class SPARCLoadSafepointPollAddress extends SPARCLIRInstruction {
+        public static final LIRInstructionClass<SPARCLoadSafepointPollAddress> TYPE = LIRInstructionClass.create(SPARCLoadSafepointPollAddress.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(2);
+
+        @Def({OperandFlag.REG}) protected AllocatableValue result;
+        private final HotSpotVMConfig config;
+
+        public SPARCLoadSafepointPollAddress(AllocatableValue result, HotSpotVMConfig config) {
+            super(TYPE, SIZE);
+            this.result = result;
+            this.config = config;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+            new Setx(config.safepointPollingAddress, ValueUtil.asRegister(result)).emit(masm);
         }
     }
 }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java	Thu Jul 09 00:18:57 2015 +0200
@@ -36,7 +36,7 @@
  *
  * <pre>
  *   Base       Contents
- *
+ * 
  *            :                                :  -----
  *   caller   | incoming overflow argument n   |    ^
  *   frame    :     ...                        :    | positive
@@ -106,6 +106,17 @@
         return StackSlot.get(kind, -spillSize + additionalOffset, true);
     }
 
+    @Override
+    public int offsetForStackSlot(StackSlot slot) {
+        // @formatter:off
+        assert (!slot.getRawAddFrameSize() && slot.getRawOffset() <  outgoingSize) ||
+               (slot.getRawAddFrameSize() && slot.getRawOffset()  <  0 && -slot.getRawOffset() <= spillSize) ||
+               (slot.getRawAddFrameSize() && slot.getRawOffset()  >= 0) :
+                   String.format("RawAddFrameSize: %b RawOffset: 0x%x spillSize: 0x%x outgoingSize: 0x%x", slot.getRawAddFrameSize(), slot.getRawOffset(), spillSize, outgoingSize);
+        // @formatter:on
+        return super.offsetForStackSlot(slot);
+    }
+
     /**
      * For non-leaf methods, RBP is preserved in the special stack slot required by the HotSpot
      * runtime for walking/inspecting frames of such methods.
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Thu Jul 09 00:18:57 2015 +0200
@@ -31,6 +31,7 @@
 import static com.oracle.graal.lir.sparc.SPARCMove.*;
 import static jdk.internal.jvmci.code.ValueUtil.*;
 import static jdk.internal.jvmci.sparc.SPARC.*;
+import static jdk.internal.jvmci.sparc.SPARC.CPUFeature.*;
 
 import java.util.*;
 
@@ -54,6 +55,9 @@
 import com.oracle.graal.lir.asm.*;
 
 public class SPARCControlFlow {
+    // This describes the maximum offset between the first emitted (load constant in to scratch,
+    // if does not fit into simm5 of cbcond) instruction and the final branch instruction
+    private static final int maximumSelfOffsetInstructions = 2;
 
     public static final class ReturnOp extends SPARCLIRInstruction implements BlockEndOp {
         public static final LIRInstructionClass<ReturnOp> TYPE = LIRInstructionClass.create(ReturnOp.class);
@@ -96,9 +100,6 @@
         private boolean emitted = false;
         private int delaySlotPosition = -1;
         private double trueDestinationProbability;
-        // This describes the maximum offset between the first emitted (load constant in to scratch,
-        // if does not fit into simm5 of cbcond) instruction and the final branch instruction
-        private static int maximumSelfOffsetInstructions = 2;
 
         public CompareBranchOp(SPARCCompare opcode, Value x, Value y, Condition condition, LabelRef trueDestination, LabelRef falseDestination, Kind kind, boolean unorderedIsTrue,
                         double trueDestinationProbability) {
@@ -295,26 +296,6 @@
             return hasShortJumpTarget;
         }
 
-        private static boolean isShortBranch(SPARCAssembler asm, int position, LabelHint hint, Label label) {
-            int disp = 0;
-            if (label.isBound()) {
-                disp = label.position() - position;
-            } else if (hint != null && hint.isValid()) {
-                disp = hint.getTarget() - hint.getPosition();
-            }
-            if (disp != 0) {
-                if (disp < 0) {
-                    disp -= maximumSelfOffsetInstructions * asm.target.wordSize;
-                } else {
-                    disp += maximumSelfOffsetInstructions * asm.target.wordSize;
-                }
-                return isSimm10(disp >> 2);
-            } else if (hint == null) {
-                asm.requestLabelHint(label);
-            }
-            return false;
-        }
-
         public void resetState() {
             emitted = false;
             delaySlotPosition = -1;
@@ -328,6 +309,26 @@
         }
     }
 
+    private static boolean isShortBranch(SPARCAssembler asm, int position, LabelHint hint, Label label) {
+        int disp = 0;
+        if (label.isBound()) {
+            disp = label.position() - position;
+        } else if (hint != null && hint.isValid()) {
+            disp = hint.getTarget() - hint.getPosition();
+        }
+        if (disp != 0) {
+            if (disp < 0) {
+                disp -= maximumSelfOffsetInstructions * asm.target.wordSize;
+            } else {
+                disp += maximumSelfOffsetInstructions * asm.target.wordSize;
+            }
+            return isSimm10(disp >> 2);
+        } else if (hint == null) {
+            asm.requestLabelHint(label);
+        }
+        return false;
+    }
+
     public static final class BranchOp extends SPARCLIRInstruction implements StandardOp.BranchOp {
         public static final LIRInstructionClass<BranchOp> TYPE = LIRInstructionClass.create(BranchOp.class);
         public static final SizeEstimate SIZE = SizeEstimate.create(2);
@@ -402,6 +403,7 @@
         @Alive({REG, ILLEGAL}) protected Value constantTableBase;
         @Temp({REG}) protected Value scratch;
         private final SwitchStrategy strategy;
+        private final LabelHint[] labelHints;
 
         public StrategySwitchOp(Value constantTableBase, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) {
             super(TYPE);
@@ -412,6 +414,7 @@
             this.constantTableBase = constantTableBase;
             this.key = key;
             this.scratch = scratch;
+            this.labelHints = new LabelHint[keyTargets.length];
             assert keyConstants.length == keyTargets.length;
             assert keyConstants.length == strategy.keyProbabilities.length;
         }
@@ -423,39 +426,70 @@
             BaseSwitchClosure closure = new BaseSwitchClosure(crb, masm, keyTargets, defaultTarget) {
                 @Override
                 protected void conditionalJump(int index, Condition condition, Label target) {
-                    const2reg(crb, masm, scratch, constantBaseRegister, keyConstants[index], SPARCDelayedControlTransfer.DUMMY);
+                    requestHint(masm, index);
+                    JavaConstant constant = keyConstants[index];
                     CC conditionCode;
-                    Register scratchRegister;
+                    Long bits;
                     switch (key.getKind()) {
                         case Char:
                         case Byte:
                         case Short:
                         case Int:
                             conditionCode = CC.Icc;
-                            scratchRegister = asIntReg(scratch);
+                            bits = constant.asLong();
                             break;
                         case Long: {
                             conditionCode = CC.Xcc;
-                            scratchRegister = asLongReg(scratch);
+                            bits = constant.asLong();
                             break;
                         }
                         case Object: {
                             conditionCode = crb.codeCache.getTarget().wordKind == Kind.Long ? CC.Xcc : CC.Icc;
-                            scratchRegister = asObjectReg(scratch);
+                            bits = constant.isDefaultForKind() ? 0L : null;
                             break;
                         }
                         default:
                             throw new JVMCIError("switch only supported for int, long and object");
                     }
                     ConditionFlag conditionFlag = fromCondition(conditionCode, condition, false);
-                    masm.cmp(keyRegister, scratchRegister);
-                    masm.bpcc(conditionFlag, NOT_ANNUL, target, conditionCode, PREDICT_TAKEN);
-                    masm.nop();  // delay slot
+                    LabelHint hint = labelHints[index];
+                    boolean canUseShortBranch = masm.hasFeature(CBCOND) && hint.isValid() && isShortBranch(masm, masm.position(), hint, target);
+                    if (bits != null && canUseShortBranch) {
+                        if (isSimm5(constant)) {
+                            if (conditionCode == Icc) {
+                                masm.cbcondw(conditionFlag, keyRegister, (int) (long) bits, target);
+                            } else {
+                                masm.cbcondx(conditionFlag, keyRegister, (int) (long) bits, target);
+                            }
+                        } else {
+                            Register scratchRegister = asRegister(scratch);
+                            const2reg(crb, masm, scratch, constantBaseRegister, keyConstants[index], SPARCDelayedControlTransfer.DUMMY);
+                            if (conditionCode == Icc) {
+                                masm.cbcondw(conditionFlag, keyRegister, scratchRegister, target);
+                            } else {
+                                masm.cbcondx(conditionFlag, keyRegister, scratchRegister, target);
+                            }
+                        }
+                    } else {
+                        if (bits != null && isSimm13(constant)) {
+                            masm.cmp(keyRegister, (int) (long) bits); // Cast is safe
+                        } else {
+                            Register scratchRegister = asRegister(scratch);
+                            const2reg(crb, masm, scratch, constantBaseRegister, keyConstants[index], SPARCDelayedControlTransfer.DUMMY);
+                            masm.cmp(keyRegister, scratchRegister);
+                        }
+                        masm.bpcc(conditionFlag, ANNUL, target, conditionCode, PREDICT_TAKEN);
+                        masm.nop();  // delay slot
+                    }
                 }
             };
             strategy.run(closure);
         }
 
+        private void requestHint(SPARCMacroAssembler masm, int index) {
+            labelHints[index] = masm.requestLabelHint(keyTargets[index].label());
+        }
+
         @Override
         public SizeEstimate estimateSize() {
             int constantBytes = 0;
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java	Thu Jul 09 00:18:57 2015 +0200
@@ -78,7 +78,7 @@
     public SPARCFrameMap(CodeCacheProvider codeCache, RegisterConfig registerConfig) {
         super(codeCache, registerConfig);
         // Initial spill size is set to register save area size (SPARC register window)
-        initialSpillSize = 128;
+        initialSpillSize = 0;
         spillSize = initialSpillSize;
     }
 
@@ -89,7 +89,12 @@
 
     @Override
     public int currentFrameSize() {
-        return alignFrameSize(calleeSaveAreaSize() + returnAddressSize() + outgoingSize + spillSize);
+        return alignFrameSize(calleeSaveAreaSize() + outgoingSize + spillSize);
+    }
+
+    @Override
+    protected int calleeSaveAreaSize() {
+        return SPARC.REGISTER_SAFE_AREA_SIZE;
     }
 
     @Override
@@ -115,16 +120,15 @@
         return SPARC.spillSlotSize(getTarget(), kind.getPlatformKind());
     }
 
-    /**
-     * We must add the calleSaveAreaSize() when it is a in or out parameter.
-     */
     @Override
     public int offsetForStackSlot(StackSlot slot) {
-        int offset = super.offsetForStackSlot(slot);
-        if (slot.getRawOffset() >= 0) { // If In or Out parameter
-            offset += calleeSaveAreaSize();
-        }
-        return offset;
+        // @formatter:off
+        assert (!slot.getRawAddFrameSize() && slot.getRawOffset() <  outgoingSize + SPARC.REGISTER_SAFE_AREA_SIZE) ||
+               (slot.getRawAddFrameSize() && slot.getRawOffset()  <  0 && -slot.getRawOffset() <= spillSize) ||
+               (slot.getRawAddFrameSize() && slot.getRawOffset()  >= 0) :
+                   String.format("RawAddFrameSize: %b RawOffset: 0x%x spillSize: 0x%x outgoingSize: 0x%x", slot.getRawAddFrameSize(), slot.getRawOffset(), spillSize, outgoingSize);
+        // @formatter:on
+        return super.offsetForStackSlot(slot);
     }
 
     @Override
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Thu Jul 09 00:18:57 2015 +0200
@@ -135,7 +135,7 @@
         public static final LIRInstructionClass<Move> TYPE = LIRInstructionClass.create(Move.class);
         public static final SizeEstimate SIZE = SizeEstimate.create(8);
 
-        @Def({REG, STACK}) protected AllocatableValue result;
+        @Def({REG, STACK, HINT}) protected AllocatableValue result;
         @Use({REG, STACK}) protected Value input;
 
         public Move(AllocatableValue result, Value input) {
@@ -680,14 +680,14 @@
                 break;
             case Float:
                 if (result.getPlatformKind() == Kind.Float) {
-                    masm.fmovs(src, dst);
+                    masm.fsrc2s(src, dst);
                 } else {
                     throw JVMCIError.shouldNotReachHere();
                 }
                 break;
             case Double:
                 if (result.getPlatformKind() == Kind.Double) {
-                    masm.fmovd(src, dst);
+                    masm.fsrc2d(src, dst);
                 } else {
                     throw JVMCIError.shouldNotReachHere();
                 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java	Thu Jul 09 00:18:57 2015 +0200
@@ -59,103 +59,117 @@
     }
 
     private void optimizeSpillPosition() {
-        LIRInsertionBuffer[] insertionBuffers = new LIRInsertionBuffer[allocator.ir.linearScanOrder().size()];
-        for (Interval interval : allocator.intervals()) {
-            if (interval != null && interval.isSplitParent() && interval.spillState() == SpillState.SpillInDominator) {
-                AbstractBlockBase<?> defBlock = allocator.blockForId(interval.spillDefinitionPos());
-                AbstractBlockBase<?> spillBlock = null;
-                Interval firstSpillChild = null;
-                try (Indent indent = Debug.logAndIndent("interval %s (%s)", interval, defBlock)) {
-                    for (Interval splitChild : interval.getSplitChildren()) {
-                        if (isStackSlotValue(splitChild.location())) {
-                            if (firstSpillChild == null || splitChild.from() < firstSpillChild.from()) {
-                                firstSpillChild = splitChild;
-                            } else {
-                                assert firstSpillChild.from() < splitChild.from();
-                            }
-                            // iterate all blocks where the interval has use positions
-                            for (AbstractBlockBase<?> splitBlock : blocksForInterval(splitChild)) {
-                                if (dominates(defBlock, splitBlock)) {
-                                    if (Debug.isLogEnabled()) {
-                                        Debug.log("Split interval %s, block %s", splitChild, splitBlock);
-                                    }
-                                    if (spillBlock == null) {
-                                        spillBlock = splitBlock;
-                                    } else {
-                                        spillBlock = commonDominator(spillBlock, splitBlock);
-                                        assert spillBlock != null;
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    if (spillBlock == null) {
-                        // no spill interval
-                        interval.setSpillState(SpillState.StoreAtDefinition);
-                    } else {
-                        // move out of loops
-                        if (defBlock.getLoopDepth() < spillBlock.getLoopDepth()) {
-                            spillBlock = moveSpillOutOfLoop(defBlock, spillBlock);
-                        }
+        try (Indent indent0 = Debug.logAndIndent("OptimizeSpillPositions")) {
+            LIRInsertionBuffer[] insertionBuffers = new LIRInsertionBuffer[allocator.ir.linearScanOrder().size()];
+            for (Interval interval : allocator.intervals()) {
+                optimizeInterval(insertionBuffers, interval);
+            }
+            for (LIRInsertionBuffer insertionBuffer : insertionBuffers) {
+                if (insertionBuffer != null) {
+                    assert insertionBuffer.initialized() : "Insertion buffer is nonnull but not initialized!";
+                    insertionBuffer.finish();
+                }
+            }
+        }
+    }
 
-                        /*
-                         * If the spill block is the begin of the first split child (aka the value
-                         * is on the stack) spill in the dominator.
-                         */
-                        assert firstSpillChild != null;
-                        if (!defBlock.equals(spillBlock) && spillBlock.equals(allocator.blockForId(firstSpillChild.from()))) {
-                            AbstractBlockBase<?> dom = spillBlock.getDominator();
-                            if (Debug.isLogEnabled()) {
-                                Debug.log("Spill block (%s) is the beginning of a spill child -> use dominator (%s)", spillBlock, dom);
-                            }
-                            spillBlock = dom;
-                        }
-
-                        if (!defBlock.equals(spillBlock)) {
-                            assert dominates(defBlock, spillBlock);
-                            betterSpillPos.increment();
-                            if (Debug.isLogEnabled()) {
-                                Debug.log("Better spill position found (Block %s)", spillBlock);
-                            }
-
-                            if (defBlock.probability() <= spillBlock.probability()) {
-                                // better spill block has the same probability -> do nothing
-                                interval.setSpillState(SpillState.StoreAtDefinition);
+    private void optimizeInterval(LIRInsertionBuffer[] insertionBuffers, Interval interval) {
+        if (interval == null || !interval.isSplitParent() || interval.spillState() != SpillState.SpillInDominator) {
+            return;
+        }
+        AbstractBlockBase<?> defBlock = allocator.blockForId(interval.spillDefinitionPos());
+        AbstractBlockBase<?> spillBlock = null;
+        Interval firstSpillChild = null;
+        try (Indent indent = Debug.logAndIndent("interval %s (%s)", interval, defBlock)) {
+            for (Interval splitChild : interval.getSplitChildren()) {
+                if (isStackSlotValue(splitChild.location())) {
+                    if (firstSpillChild == null || splitChild.from() < firstSpillChild.from()) {
+                        firstSpillChild = splitChild;
+                    } else {
+                        assert firstSpillChild.from() < splitChild.from();
+                    }
+                    // iterate all blocks where the interval has use positions
+                    for (AbstractBlockBase<?> splitBlock : blocksForInterval(splitChild)) {
+                        if (dominates(defBlock, splitBlock)) {
+                            Debug.log("Split interval %s, block %s", splitChild, splitBlock);
+                            if (spillBlock == null) {
+                                spillBlock = splitBlock;
                             } else {
-                                LIRInsertionBuffer insertionBuffer = insertionBuffers[spillBlock.getId()];
-                                if (insertionBuffer == null) {
-                                    insertionBuffer = new LIRInsertionBuffer();
-                                    insertionBuffers[spillBlock.getId()] = insertionBuffer;
-                                    insertionBuffer.init(allocator.ir.getLIRforBlock(spillBlock));
-                                }
-                                int spillOpId = allocator.getFirstLirInstructionId(spillBlock);
-                                // insert spill move
-                                AllocatableValue fromLocation = interval.getSplitChildAtOpId(spillOpId, OperandMode.DEF, allocator).location();
-                                AllocatableValue toLocation = LinearScan.canonicalSpillOpr(interval);
-                                LIRInstruction move = allocator.getSpillMoveFactory().createMove(toLocation, fromLocation);
-                                move.setId(LinearScan.DOMINATOR_SPILL_MOVE_ID);
-                                /*
-                                 * We can use the insertion buffer directly because we always insert
-                                 * at position 1.
-                                 */
-                                insertionBuffer.append(1, move);
-
-                                betterSpillPosWithLowerProbability.increment();
-                                interval.setSpillDefinitionPos(spillOpId);
+                                spillBlock = commonDominator(spillBlock, splitBlock);
+                                assert spillBlock != null;
                             }
-                        } else {
-                            // definition is the best choice
-                            interval.setSpillState(SpillState.StoreAtDefinition);
                         }
                     }
                 }
             }
-        }
-        for (LIRInsertionBuffer insertionBuffer : insertionBuffers) {
-            if (insertionBuffer != null) {
-                assert insertionBuffer.initialized() : "Insertion buffer is nonnull but not initialized!";
-                insertionBuffer.finish();
+            if (spillBlock == null) {
+                Debug.log("not spill interval found");
+                // no spill interval
+                interval.setSpillState(SpillState.StoreAtDefinition);
+                return;
+            }
+            Debug.log(3, "Spill block candidate (initial): %s", spillBlock);
+            // move out of loops
+            if (defBlock.getLoopDepth() < spillBlock.getLoopDepth()) {
+                spillBlock = moveSpillOutOfLoop(defBlock, spillBlock);
+            }
+            Debug.log(3, "Spill block candidate (after loop optimizaton): %s", spillBlock);
+
+            /*
+             * The spill block is the begin of the first split child (aka the value is on the
+             * stack).
+             * 
+             * The problem is that if spill block has more than one predecessor, the values at the
+             * end of the predecessors might differ. Therefore, we would need a spill move in all
+             * predecessors. To avoid this we spill in the dominator.
+             */
+            assert firstSpillChild != null;
+            if (!defBlock.equals(spillBlock) && spillBlock.equals(allocator.blockForId(firstSpillChild.from()))) {
+                AbstractBlockBase<?> dom = spillBlock.getDominator();
+                if (Debug.isLogEnabled()) {
+                    Debug.log("Spill block (%s) is the beginning of a spill child -> use dominator (%s)", spillBlock, dom);
+                }
+                spillBlock = dom;
             }
+            if (defBlock.equals(spillBlock)) {
+                Debug.log(3, "Definition is the best choice: %s", defBlock);
+                // definition is the best choice
+                interval.setSpillState(SpillState.StoreAtDefinition);
+                return;
+            }
+            assert dominates(defBlock, spillBlock);
+            betterSpillPos.increment();
+            if (Debug.isLogEnabled()) {
+                Debug.log("Better spill position found (Block %s)", spillBlock);
+            }
+
+            if (defBlock.probability() <= spillBlock.probability()) {
+                Debug.log(3, "Definition has lower probability %s (%f) is lower than spill block %s (%f)", defBlock, defBlock.probability(), spillBlock, spillBlock.probability());
+                // better spill block has the same probability -> do nothing
+                interval.setSpillState(SpillState.StoreAtDefinition);
+                return;
+            }
+
+            LIRInsertionBuffer insertionBuffer = insertionBuffers[spillBlock.getId()];
+            if (insertionBuffer == null) {
+                insertionBuffer = new LIRInsertionBuffer();
+                insertionBuffers[spillBlock.getId()] = insertionBuffer;
+                insertionBuffer.init(allocator.ir.getLIRforBlock(spillBlock));
+            }
+            int spillOpId = allocator.getFirstLirInstructionId(spillBlock);
+            // insert spill move
+            AllocatableValue fromLocation = interval.getSplitChildAtOpId(spillOpId, OperandMode.DEF, allocator).location();
+            AllocatableValue toLocation = LinearScan.canonicalSpillOpr(interval);
+            LIRInstruction move = allocator.getSpillMoveFactory().createMove(toLocation, fromLocation);
+            Debug.log(3, "Insert spill move %s", move);
+            move.setId(LinearScan.DOMINATOR_SPILL_MOVE_ID);
+            /*
+             * We can use the insertion buffer directly because we always insert at position 1.
+             */
+            insertionBuffer.append(1, move);
+
+            betterSpillPosWithLowerProbability.increment();
+            interval.setSpillDefinitionPos(spillOpId);
         }
     }
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/SSALinearScanEliminateSpillMovePhase.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/SSALinearScanEliminateSpillMovePhase.java	Thu Jul 09 00:18:57 2015 +0200
@@ -45,14 +45,16 @@
 
     @Override
     protected boolean canEliminateSpillMove(AbstractBlockBase<?> block, MoveOp move) {
-        // SSA Linear Scan might introduce moves to stack slots
         assert isVariable(move.getResult()) || LinearScanPhase.SSA_LSRA.getValue() : "Move should not be produced in a non-SSA compilation: " + move;
 
-        Interval curInterval = allocator.intervalFor(move.getResult());
-
-        if (!isRegister(curInterval.location()) && curInterval.alwaysInMemory() && !isPhiResolutionMove(block, move, curInterval)) {
-            assert isStackSlotValue(curInterval.location()) : "Not a stack slot: " + curInterval.location();
-            return true;
+        if (super.canEliminateSpillMove(block, move)) {
+            // SSA Linear Scan might introduce moves to stack slots
+            Interval curInterval = allocator.intervalFor(move.getResult());
+            assert !isRegister(curInterval.location()) && curInterval.alwaysInMemory();
+            if (!isPhiResolutionMove(block, move, curInterval)) {
+                assert isStackSlotValue(curInterval.location()) : "Not a stack slot: " + curInterval.location();
+                return true;
+            }
         }
         return false;
     }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/framemap/FrameMap.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/framemap/FrameMap.java	Thu Jul 09 00:18:57 2015 +0200
@@ -190,12 +190,6 @@
      * @return the offset of the stack slot
      */
     public int offsetForStackSlot(StackSlot slot) {
-        // @formatter:off
-        assert (!slot.getRawAddFrameSize() && slot.getRawOffset() <  outgoingSize) ||
-               (slot.getRawAddFrameSize() && slot.getRawOffset()  <  0 && -slot.getRawOffset() <= spillSize) ||
-               (slot.getRawAddFrameSize() && slot.getRawOffset()  >= 0) :
-                   String.format("RawAddFrameSize: %b RawOffset: 0x%x spillSize: 0x%x outgoingSize: 0x%x", slot.getRawAddFrameSize(), slot.getRawOffset(), spillSize, outgoingSize);
-        // @formatter:on
         if (slot.isInCallerFrame()) {
             accessesCallerFrame = true;
         }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java	Thu Jul 09 00:18:57 2015 +0200
@@ -30,17 +30,20 @@
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.compiler.common.spi.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.StackMove;
 
 public interface LIRGeneratorTool extends ArithmeticLIRGenerator, BenchmarkCounterFactory {
 
+    /**
+     * Factory for creating spill moves.
+     *
+     * The instructions returned by the methods must only depend on the input values. References to
+     * values that require interaction with register allocation are strictly forbidden.
+     */
     public interface SpillMoveFactory {
 
         LIRInstruction createMove(AllocatableValue result, Value input);
 
-        default LIRInstruction createStackMove(AllocatableValue result, Value input) {
-            return new StackMove(result, input);
-        }
+        LIRInstruction createStackMove(AllocatableValue result, Value input);
     }
 
     public abstract class BlockScope implements AutoCloseable {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/SpillMoveFactoryBase.java	Thu Jul 09 00:18:57 2015 +0200
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2015, 2015, 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.lir.gen;
+
+import static com.oracle.graal.lir.LIRValueUtil.*;
+import static jdk.internal.jvmci.code.ValueUtil.*;
+
+import java.util.*;
+
+import jdk.internal.jvmci.meta.*;
+
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.StandardOp.StackMove;
+import com.oracle.graal.lir.gen.LIRGeneratorTool.SpillMoveFactory;
+
+/**
+ * Base class for {@link SpillMoveFactory} that checks that the instructions created adhere to the
+ * contract of {@link SpillMoveFactory}.
+ */
+public abstract class SpillMoveFactoryBase implements SpillMoveFactory {
+
+    public final LIRInstruction createMove(AllocatableValue result, Value input) {
+        LIRInstruction inst = createMoveIntern(result, input);
+        assert checkResult(inst, result, input);
+        return inst;
+    }
+
+    public final LIRInstruction createStackMove(AllocatableValue result, Value input) {
+        LIRInstruction inst = createStackMoveIntern(result, input);
+        assert checkResult(inst, result, input);
+        return inst;
+    }
+
+    protected abstract LIRInstruction createMoveIntern(AllocatableValue result, Value input);
+
+    protected LIRInstruction createStackMoveIntern(AllocatableValue result, Value input) {
+        return new StackMove(result, input);
+    }
+
+    /** Closure for {@link SpillMoveFactoryBase#checkResult}. */
+    @SuppressWarnings("unused")
+    private static class CheckClosure {
+
+        private final AllocatableValue result;
+        private final Value input;
+
+        private int tempCount = 0;
+        private int aliveCount = 0;
+        private int stateCount = 0;
+        private int inputCount = 0;
+        private int outputCount = 0;
+
+        CheckClosure(AllocatableValue result, Value input) {
+            this.result = result;
+            this.input = input;
+        }
+
+        void tempProc(LIRInstruction op, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+            assert false : String.format("SpillMoveFactory: Instruction %s is not allowed to contain operand %s of mode %s", op, value, mode);
+            tempCount++;
+        }
+
+        void stateProc(LIRInstruction op, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+            assert false : String.format("SpillMoveFactory: Instruction %s is not allowed to contain operand %s of mode %s", op, value, mode);
+            stateCount++;
+        }
+
+        void aliveProc(LIRInstruction op, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+            assert !isVariable(value) && flags.contains(OperandFlag.UNINITIALIZED) : String.format("SpillMoveFactory: Instruction %s is not allowed to contain operand %s of mode %s", op, value, mode);
+            aliveCount++;
+        }
+
+        void inputProc(LIRInstruction op, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+            assert value.equals(input) || isConstant(value) : String.format("SpillMoveFactory: Instruction %s can only have %s as input, got %s", op, input, value);
+            inputCount++;
+        }
+
+        void outputProc(LIRInstruction op, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+            assert value.equals(result) : String.format("SpillMoveFactory: Instruction %s can only have %s as input, got %s", op, input, value);
+            outputCount++;
+        }
+    }
+
+    /** Checks that the instructions adheres to the contract of {@link SpillMoveFactory}. */
+    private static boolean checkResult(LIRInstruction inst, AllocatableValue result, Value input) {
+
+        SpillMoveFactoryBase.CheckClosure c = new CheckClosure(result, input);
+        inst.visitEachInput(c::inputProc);
+        inst.visitEachOutput(c::outputProc);
+        inst.visitEachAlive(c::aliveProc);
+        inst.visitEachTemp(c::tempProc);
+        inst.visitEachState(c::stateProc);
+
+        assert c.outputCount >= 1 : "no output produced" + inst;
+        assert c.stateCount == 0 : "SpillMoveFactory: instruction must not have a state: " + inst;
+        return true;
+    }
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/FixPointIntervalBuilder.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/FixPointIntervalBuilder.java	Thu Jul 09 00:18:57 2015 +0200
@@ -236,8 +236,7 @@
             if (flags.contains(OperandFlag.HINT)) {
 
                 op.forEachRegisterHint(targetValue, mode, (registerHint, valueMode, valueFlags) -> {
-                    if (isStackSlotValue(registerHint)) {
-                        assert isVirtualStackSlot(registerHint) : "Hint is not a VirtualStackSlot: " + registerHint;
+                    if (isVirtualStackSlot(registerHint)) {
                         StackInterval from = getOrCreateInterval((VirtualStackSlot) registerHint);
                         StackInterval to = getOrCreateInterval(targetValue);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java	Thu Jul 09 00:18:57 2015 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import jdk.internal.jvmci.common.*;
 import jdk.internal.jvmci.meta.*;
 import jdk.internal.jvmci.meta.Assumptions.*;
 
@@ -55,7 +56,9 @@
         this.method = method;
         assert method.isConcrete() : "Cannot load abstract method from a hub";
         assert method.hasReceiver() : "Cannot load a static method from a hub";
-        assert method.isInVirtualMethodTable(receiverType);
+        if (!method.isInVirtualMethodTable(receiverType)) {
+            throw new JVMCIError("%s does not have a vtable entry in type %s", method, receiverType);
+        }
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Thu Jul 09 00:18:57 2015 +0200
@@ -206,7 +206,7 @@
 
         ResolvedJavaType singleImplementor = declaredReceiverType.getSingleImplementor();
         if (singleImplementor != null && !singleImplementor.equals(declaredReceiverType)) {
-            ResolvedJavaMethod singleImplementorMethod = singleImplementor.resolveMethod(targetMethod(), invoke().getContextType(), true);
+            ResolvedJavaMethod singleImplementorMethod = singleImplementor.resolveMethod(targetMethod(), invoke().getContextType());
             if (singleImplementorMethod != null) {
                 /**
                  * We have an invoke on an interface with a single implementor. We can replace this
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Wed Jul 08 12:40:07 2015 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Thu Jul 09 00:18:57 2015 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.phases.common.inlining;
 
 import static com.oracle.graal.compiler.common.GraalOptions.*;
-import static com.oracle.graal.compiler.common.type.StampFactory.*;
 import static jdk.internal.jvmci.meta.DeoptimizationAction.*;
 import static jdk.internal.jvmci.meta.DeoptimizationReason.*;
 
@@ -33,7 +32,7 @@
 import jdk.internal.jvmci.code.*;
 import jdk.internal.jvmci.common.*;
 import jdk.internal.jvmci.debug.*;
-import jdk.internal.jvmci.debug.Debug.*;
+import jdk.internal.jvmci.debug.Debug.Scope;
 import jdk.internal.jvmci.meta.*;
 
 import com.oracle.graal.api.replacements.*;
@@ -646,21 +645,30 @@
     }
 
     /**
-     * Gets the receiver for an invoke, adding a guard if necessary to ensure it is non-null.
+     * Gets the receiver for an invoke, adding a guard if necessary to ensure it is non-null, and
+     * ensuring that the resulting type is compatible with the method being invoked.
      */
     public static ValueNode nonNullReceiver(Invoke invoke) {
         MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget();
         assert !callTarget.isStatic() : callTarget.targetMethod();
         StructuredGraph graph = callTarget.graph();
         ValueNode firstParam = callTarget.arguments().get(0);
-        if (firstParam.getKind() == Kind.Object && !StampTool.isPointerNonNull(firstParam)) {
-            IsNullNode condition = graph.unique(new IsNullNode(firstParam));
-            Stamp stamp = firstParam.stamp().join(objectNonNull());
-            FixedGuardNode fixedGuard = graph.add(new FixedGuardNode(condition, NullCheckException, InvalidateReprofile, true));
-            PiNode nonNullReceiver = graph.unique(new PiNode(firstParam, stamp, fixedGuard));
-            graph.addBeforeFixed(invoke.asNode(), fixedGuard);
-            callTarget.replaceFirstInput(firstParam, nonNullReceiver);
-            return nonNullReceiver;
+        if (firstParam.getKind() == Kind.Object) {
+            Stamp paramStamp = firstParam.stamp();
+            Stamp stamp = paramStamp.join(StampFactory.declaredNonNull(callTarget.targetMethod().getDeclaringClass()));
+            if (!StampTool.isPointerNonNull(firstParam)) {
+                IsNullNode condition = graph.unique(new IsNullNode(firstParam));
+                FixedGuardNode fixedGuard = graph.add(new FixedGuardNode(condition, NullCheckException, InvalidateReprofile, true));
+                PiNode nonNullReceiver = graph.unique(new PiNode(firstParam, stamp, fixedGuard));
+                graph.addBeforeFixed(invoke.asNode(), fixedGuard);
+                callTarget.replaceFirstInput(firstParam, nonNullReceiver);
+                return nonNullReceiver;
+            }
+            if (!stamp.equals(paramStamp)) {
+                PiNode cast = graph.unique(new PiNode(firstParam, stamp));
+                callTarget.replaceFirstInput(firstParam, cast);
+                return cast;
+            }
         }
         return firstParam;
     }
--- a/mx.graal/mx_graal.py	Wed Jul 08 12:40:07 2015 +0200
+++ b/mx.graal/mx_graal.py	Thu Jul 09 00:18:57 2015 +0200
@@ -36,12 +36,39 @@
 
 _suite = mx.suite('graal')
 
-_graalDeployedDist = JDKDeployedDist('GRAAL', usesJVMCIClassLoader=True)
-_graalTruffleDeployedDist = JDKDeployedDist('GRAAL_TRUFFLE', usesJVMCIClassLoader=True)
+class GraalJDKDeployedDist(JDKDeployedDist):
+    def __init__(self):
+        JDKDeployedDist.__init__(self, 'GRAAL', usesJVMCIClassLoader=True)
+
+    def onPostJdkInstall(self, jdkDir, targetDir):
+        self._updateGraalPropertiesFile(join(jdkDir, 'jre', 'lib'))
 
-_graalDeployedDist.postJdkInstall = lambda jdkDir, targetDir: _updateGraalPropertiesFile(join(jdkDir, 'jre', 'lib'))
+    def _updateGraalPropertiesFile(self, jreLibDir):
+        """
+        Updates (or creates) 'jreLibDir'/jvmci/graal.properties to set/modify the
+        graal.version property.
+        """
+        version = _suite.release_version()
+        graalProperties = join(jreLibDir, 'jvmci', 'graal.properties')
+        if not exists(graalProperties):
+            with open(graalProperties, 'w') as fp:
+                print >> fp, 'graal.version=' + version
+        else:
+            content = []
+            with open(graalProperties) as fp:
+                for line in fp:
+                    if line.startswith('graal.version='):
+                        content.append('graal.version=' + version)
+                    else:
+                        content.append(line.rstrip(os.linesep))
+            with open(graalProperties, 'w') as fp:
+                fp.write(os.linesep.join(content))
 
-mx_jvmci.jdkDeployedDists += [_graalDeployedDist, _graalTruffleDeployedDist]
+mx_jvmci.jdkDeployedDists += [
+    GraalJDKDeployedDist(),
+    JDKDeployedDist('GRAAL_TRUFFLE', usesJVMCIClassLoader=True)
+]
+
 mx_jvmci.jacocoIncludes += ['com.oracle.graal.*']
 mx_jvmci.jacocoExcludedAnnotations += ['@Snippet', '@ClassSubstitution']
 
@@ -89,27 +116,6 @@
 
     _run_benchmark(args, sanitycheck.dacapoScalaSanityWarmup.keys(), launcher)
 
-def _updateGraalPropertiesFile(jreLibDir):
-    """
-    Updates (or creates) 'jreLibDir'/jvmci/graal.properties to set/modify the
-    graal.version property.
-    """
-    version = _suite.release_version()
-    graalProperties = join(jreLibDir, 'jvmci', 'graal.properties')
-    if not exists(graalProperties):
-        with open(graalProperties, 'w') as fp:
-            print >> fp, 'graal.version=' + version
-    else:
-        content = []
-        with open(graalProperties) as fp:
-            for line in fp:
-                if line.startswith('graal.version='):
-                    content.append('graal.version=' + version)
-                else:
-                    content.append(line.rstrip(os.linesep))
-        with open(graalProperties, 'w') as fp:
-            fp.write(os.linesep.join(content))
-
 def microbench(args):
     """run JMH microbenchmark projects"""
     vmArgs, jmhArgs = mx.extract_VM_args(args, useDoubleDash=True)
@@ -160,10 +166,10 @@
         with Task('UnitTests:hosted-product', tasks) as t:
             if t: unittest(['--enable-timing', '--verbose', '--fail-fast'])
 
-    # Run unit tests on server-hosted-jvmci with -G:+SSA_LIR
+    # Run unit tests on server-hosted-jvmci with -G:-SSA_LIR
     with VM('server', 'product'):
-        with Task('UnitTestsSSA:hosted-product', tasks) as t:
-            if t: unittest(['--enable-timing', '--verbose', '--fail-fast', '-G:+SSA_LIR'])
+        with Task('UnitTestsNonSSA:hosted-product', tasks) as t:
+            if t: unittest(['--enable-timing', '--verbose', '--fail-fast', '-G:-SSA_LIR'])
     # Run ctw against rt.jar on server-hosted-jvmci
     with VM('server', 'product'):
         with Task('CTW:hosted-product', tasks) as t:
@@ -208,10 +214,10 @@
                 vm(['-XX:-TieredCompilation', '-G:RegisterPressure=' + registers, '-esa', '-version'])
 
     with VM('jvmci', 'product'):
-        with Task('BootstrapSSAWithRegisterPressure:product', tasks) as t:
+        with Task('BootstrapNonSSAWithRegisterPressure:product', tasks) as t:
             if t:
                 registers = 'o0,o1,o2,o3,f8,f9,d32,d34' if platform.processor() == 'sparc' else 'rbx,r11,r10,r14,xmm3,xmm11,xmm14'
-                vm(['-XX:-TieredCompilation', '-G:+SSA_LIR', '-G:RegisterPressure=' + registers, '-esa', '-version'])
+                vm(['-XX:-TieredCompilation', '-G:-SSA_LIR', '-G:RegisterPressure=' + registers, '-esa', '-version'])
 
     with VM('jvmci', 'product'):
         with Task('BootstrapWithImmutableCode:product', tasks) as t:
@@ -247,6 +253,8 @@
                     with Task('UnitTests:' + theVm + ':' + vmbuild, tasks) as t:
                         if t: unittest(['-XX:CompileCommand=exclude,*::run*', 'graal.api', 'java.test'])
 
+mx_jvmci.gateRunners.append(_graal_gate_runner)
+
 def deoptalot(args):
     """bootstrap a VM with DeoptimizeALot and VerifyOops on
 
@@ -267,6 +275,11 @@
 
     dacapo(['100', 'eclipse', '-esa'])
 
+"""
+Extra benchmarks to run from 'bench()'.
+"""
+extraBenchmarks = []
+
 def bench(args):
     """run benchmarks and parse their output for results
 
@@ -280,6 +293,15 @@
             del args[index]
         else:
             mx.abort('-resultfile must be followed by a file name')
+    resultFileCSV = None
+    if '-resultfilecsv' in args:
+        index = args.index('-resultfilecsv')
+        if index + 1 < len(args):
+            resultFileCSV = args[index + 1]
+            del args[index]
+            del args[index]
+        else:
+            mx.abort('-resultfilecsv must be followed by a file name')
     vm = get_vm()
     if len(args) is 0:
         args = ['all']
@@ -337,6 +359,9 @@
     if 'ctw-noinline' in args:
         benchmarks.append(sanitycheck.getCTW(vm, sanitycheck.CTWMode.NoInline))
 
+    for f in extraBenchmarks:
+        f(args, vm, benchmarks)
+
     for test in benchmarks:
         for (groupName, res) in test.bench(vm, extraVmOpts=vmArgs).items():
             group = results.setdefault(groupName, {})
@@ -345,6 +370,12 @@
     if resultFile:
         with open(resultFile, 'w') as f:
             f.write(json.dumps(results))
+    if resultFileCSV:
+        with open(resultFileCSV, 'w') as f:
+            for key1, value1 in results.iteritems():
+                f.write('%s;\n' % (str(key1)))
+                for key2, value2 in sorted(value1.iteritems()):
+                    f.write('%s; %s;\n' % (str(key2), str(value2)))
 
 def specjvm2008(args):
     """run one or more SPECjvm2008 benchmarks"""
@@ -380,17 +411,14 @@
 
     _run_benchmark(args, None, launcher)
 
-def mx_init(suite):
-    commands = {
-        'dacapo': [dacapo, '[VM options] benchmarks...|"all" [DaCapo options]'],
-        'scaladacapo': [scaladacapo, '[VM options] benchmarks...|"all" [Scala DaCapo options]'],
-        'specjvm2008': [specjvm2008, '[VM options] benchmarks...|"all" [SPECjvm2008 options]'],
-        'specjbb2013': [specjbb2013, '[VM options] [-- [SPECjbb2013 options]]'],
-        'specjbb2005': [specjbb2005, '[VM options] [-- [SPECjbb2005 options]]'],
-        'bench' : [bench, '[-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'],
-        'microbench' : [microbench, '[VM options] [-- [JMH options]]'],
-        'deoptalot' : [deoptalot, '[n]'],
-        'longtests' : [longtests, ''],
-    }
-
-    mx.update_commands(suite, commands)
+mx.update_commands(_suite, {
+    'dacapo': [dacapo, '[VM options] benchmarks...|"all" [DaCapo options]'],
+    'scaladacapo': [scaladacapo, '[VM options] benchmarks...|"all" [Scala DaCapo options]'],
+    'specjvm2008': [specjvm2008, '[VM options] benchmarks...|"all" [SPECjvm2008 options]'],
+    'specjbb2013': [specjbb2013, '[VM options] [-- [SPECjbb2013 options]]'],
+    'specjbb2005': [specjbb2005, '[VM options] [-- [SPECjbb2005 options]]'],
+    'bench' : [bench, '[-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'],
+    'microbench' : [microbench, '[VM options] [-- [JMH options]]'],
+    'deoptalot' : [deoptalot, '[n]'],
+    'longtests' : [longtests, ''],
+})
--- a/mx.graal/sanitycheck.py	Wed Jul 08 12:40:07 2015 +0200
+++ b/mx.graal/sanitycheck.py	Thu Jul 09 00:18:57 2015 +0200
@@ -26,6 +26,7 @@
 from outputparser import OutputParser, ValuesMatcher
 import re, mx, mx_graal, os, sys, StringIO, subprocess
 from os.path import isfile, join, exists
+import mx_jvmci
 
 gc = 'UseSerialGC'
 
@@ -281,7 +282,7 @@
     if vm == 'jvmci':
         args += ['-XX:+BootstrapGraal']
     if mode >= CTWMode.NoInline:
-        if not mx_graal.isJVMCIEnabled(vm):
+        if not mx_jvmci.isJVMCIEnabled(vm):
             args.append('-XX:-Inline')
         else:
             args.append('-G:CompileTheWordConfig=-Inline')
--- a/mx.graal/suite.py	Wed Jul 08 12:40:07 2015 +0200
+++ b/mx.graal/suite.py	Thu Jul 09 00:18:57 2015 +0200
@@ -1,12 +1,12 @@
 suite = {
-  "mxversion" : "4.0.0",
+  "mxversion" : "4.3.4",
   "name" : "graal",
 
   "imports" : {
     "suites": [
             {
                "name" : "jvmci",
-               "version" : "ed35cb99842854869c6a18a3626064932db32968",
+               "version" : "2ea24a36675cf5264577361bddbc2ee2517dd08d",
                "urls" : [
                     {"url" : "https://lafo.ssw.uni-linz.ac.at/hg/graal-jvmci-8", "kind" : "hg"},
                 ]
@@ -15,8 +15,9 @@
                "name" : "truffle",
                "version" : "f878f9778548f684c6f8b88e1bb7d3b49d40ce4c",
                "urls" : [
-                    {"url" : "http://lafo.ssw.uni-linz.ac.at/hg/truffle", "kind" : "hg"},
-                    {"url" : "http://lafo.ssw.uni-linz.ac.at/nexus/content/repositories/snapshots", "kind" : "binary"},
+                    {"url" : "https://lafo.ssw.uni-linz.ac.at/hg/truffle-mx2", "kind" : "hg"},
+                    # Disable reference to snapshots until they are built from truffle-mx2 or truffle-mx2 is renamed to truffle
+                    #{"url" : "http://lafo.ssw.uni-linz.ac.at/nexus/content/repositories/snapshots", "kind" : "binary"},
                 ]
             },
     ]
@@ -26,33 +27,6 @@
 
     # ------------- Libraries -------------
 
-      "JLINE" : {
-      "path" : "lib/jline-2.11.jar",
-      "urls" : [
-        "http://lafo.ssw.uni-linz.ac.at/graal-external-deps/jline-2.11.jar",
-        "https://search.maven.org/remotecontent?filepath=jline/jline/2.11/jline-2.11.jar",
-      ],
-      "sha1" : "9504d5e2da5d78237239c5226e8200ec21182040",
-    },
-
-    "HCFDIS" : {
-      "path" : "lib/hcfdis-2.jar",
-      "urls" : ["http://lafo.ssw.uni-linz.ac.at/hcfdis-2.jar"],
-      "sha1" : "bc8b2253436485e9dbaf81771c259ccfa1a24c80",
-    },
-
-    "C1VISUALIZER_DIST" : {
-      "path" : "lib/c1visualizer_2014-04-22.zip",
-      "urls" : ["https://java.net/downloads/c1visualizer/c1visualizer_2014-04-22.zip"],
-      "sha1" : "220488d87affb569b893c7201f8ce5d2b0e03141",
-    },
-
-    "JOL_INTERNALS" : {
-      "path" : "lib/jol-internals.jar",
-      "urls" : ["http://lafo.ssw.uni-linz.ac.at/truffle/jol/jol-internals.jar"],
-      "sha1" : "508bcd26a4d7c4c44048990c6ea789a3b11a62dc",
-    },
-
     "DACAPO" : {
       "path" : "lib/dacapo-9.12-bach.jar",
       "urls" : [
@@ -91,15 +65,6 @@
       "bootClassPathAgent" : "true",
     },
 
-    "VECMATH" : {
-      "path" : "lib/vecmath-1.3.1.jar",
-      "urls" : [
-        "http://lafo.ssw.uni-linz.ac.at/graal-external-deps/vecmath-1.3.1.jar",
-        "https://search.maven.org/remotecontent?filepath=java3d/vecmath/1.3.1/vecmath-1.3.1.jar",
-      ],
-      "sha1" : "a0ae4f51da409fa0c20fa0ca59e6bbc9413ae71d",
-    },
-
     "JMH" : {
       "path" : "lib/jmh-runner-1.4.2.jar",
       "sha1" : "f44bffaf237305512002303a306fc5ce3fa63f76",