changeset 9795:d734ee4f9738

Merge.
author Doug Simon <doug.simon@oracle.com>
date Wed, 22 May 2013 22:13:30 +0200
parents 7f92277c3a37 (current diff) e92fdf3e1558 (diff)
children 4f2d8bf3dfb8
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyValueUsage.java
diffstat 24 files changed, 176 insertions(+), 122 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java	Wed May 22 22:13:30 2013 +0200
@@ -213,7 +213,8 @@
     public boolean equals(Object obj) {
         if (obj instanceof Register) {
             Register other = (Register) obj;
-            if (number == other.number && name.equals(other.name)) {
+            if (number == other.number) {
+                assert name.equals(other.name);
                 assert encoding == other.encoding;
                 assert registerCategory == other.registerCategory;
                 return true;
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java	Wed May 22 22:13:30 2013 +0200
@@ -120,7 +120,7 @@
     }
 
     public static boolean sameRegister(Value v1, Value v2) {
-        return isRegister(v1) && isRegister(v2) && asRegister(v1) == asRegister(v2);
+        return isRegister(v1) && isRegister(v2) && asRegister(v1).equals(asRegister(v2));
     }
 
     public static boolean sameRegister(Value v1, Value v2, Value v3) {
@@ -128,7 +128,7 @@
     }
 
     public static boolean differentRegisters(Value v1, Value v2) {
-        return !isRegister(v1) || !isRegister(v2) || asRegister(v1) != asRegister(v2);
+        return !isRegister(v1) || !isRegister(v2) || !asRegister(v1).equals(asRegister(v2));
     }
 
     public static boolean differentRegisters(Value v1, Value v2, Value v3) {
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java	Wed May 22 22:13:30 2013 +0200
@@ -147,7 +147,8 @@
             } else {
                 Kind componentKind = type.getComponentType().getKind().getStackKind();
                 for (int i = 0; i < values.length; i++) {
-                    assert values[i].getKind().getStackKind() == componentKind : values[i].getKind() + " != " + componentKind;
+                    assert values[i].getKind().getStackKind() == componentKind || componentKind.getBitCount() >= values[i].getKind().getStackKind().getBitCount() : values[i].getKind() + " != " +
+                                    componentKind;
                 }
             }
 
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Wed May 22 22:13:30 2013 +0200
@@ -362,8 +362,12 @@
             case Char:
             case Short:
                 return 16;
+            case Float:
+                return 32;
             case Int:
                 return 32;
+            case Double:
+                return 64;
             case Long:
                 return 64;
             default:
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Address.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Address.java	Wed May 22 22:13:30 2013 +0200
@@ -114,11 +114,11 @@
         StringBuilder s = new StringBuilder();
         s.append("[");
         String sep = "";
-        if (getBase() != Register.None) {
+        if (!getBase().equals(Register.None)) {
             s.append(getBase());
             sep = " + ";
         }
-        if (getIndex() != Register.None) {
+        if (!getIndex().equals(Register.None)) {
             s.append(sep).append(getIndex()).append(" * ").append(getScale().value);
             sep = " + ";
         }
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Wed May 22 22:13:30 2013 +0200
@@ -216,7 +216,7 @@
     }
 
     protected void emitOperandHelper(Register reg, AMD64Address addr) {
-        assert reg != Register.None;
+        assert !reg.equals(Register.None);
         emitOperandHelper(encode(reg), addr);
     }
 
@@ -230,14 +230,14 @@
         AMD64Address.Scale scale = addr.getScale();
         int disp = addr.getDisplacement();
 
-        if (base == Register.Frame) {
+        if (base.equals(Register.Frame)) {
             assert frameRegister != null : "cannot use register " + Register.Frame + " in assembler with null register configuration";
             base = frameRegister;
         }
 
-        if (base == AMD64.rip) { // also matches Placeholder
+        if (base.equals(AMD64.rip)) { // also matches Placeholder
             // [00 000 101] disp32
-            assert index == Register.None : "cannot use RIP relative addressing with index register";
+            assert index.equals(Register.None) : "cannot use RIP relative addressing with index register";
             emitByte(0x05 | regenc);
             emitInt(disp);
         } else if (base.isValid()) {
@@ -245,28 +245,28 @@
             if (index.isValid()) {
                 int indexenc = encode(index) << 3;
                 // [base + indexscale + disp]
-                if (disp == 0 && base != rbp && (base != r13)) {
+                if (disp == 0 && !base.equals(rbp) && !base.equals(r13)) {
                     // [base + indexscale]
                     // [00 reg 100][ss index base]
-                    assert index != rsp : "illegal addressing mode";
+                    assert !index.equals(rsp) : "illegal addressing mode";
                     emitByte(0x04 | regenc);
                     emitByte(scale.log2 << 6 | indexenc | baseenc);
                 } else if (isByte(disp)) {
                     // [base + indexscale + imm8]
                     // [01 reg 100][ss index base] imm8
-                    assert index != rsp : "illegal addressing mode";
+                    assert !index.equals(rsp) : "illegal addressing mode";
                     emitByte(0x44 | regenc);
                     emitByte(scale.log2 << 6 | indexenc | baseenc);
                     emitByte(disp & 0xFF);
                 } else {
                     // [base + indexscale + disp32]
                     // [10 reg 100][ss index base] disp32
-                    assert index != rsp : "illegal addressing mode";
+                    assert !index.equals(rsp) : "illegal addressing mode";
                     emitByte(0x84 | regenc);
                     emitByte(scale.log2 << 6 | indexenc | baseenc);
                     emitInt(disp);
                 }
-            } else if (base == rsp || (base == r12)) {
+            } else if (base.equals(rsp) || base.equals(r12)) {
                 // [rsp + disp]
                 if (disp == 0) {
                     // [rsp]
@@ -288,8 +288,8 @@
                 }
             } else {
                 // [base + disp]
-                assert base != rsp && (base != r12) : "illegal addressing mode";
-                if (disp == 0 && base != rbp && (base != r13)) {
+                assert !base.equals(rsp) && !base.equals(r12) : "illegal addressing mode";
+                if (disp == 0 && !base.equals(rbp) && !base.equals(r13)) {
                     // [base]
                     // [00 reg base]
                     emitByte(0x00 | regenc | baseenc);
@@ -310,7 +310,7 @@
                 int indexenc = encode(index) << 3;
                 // [indexscale + disp]
                 // [00 reg 100][ss index 101] disp32
-                assert index != rsp : "illegal addressing mode";
+                assert !index.equals(rsp) : "illegal addressing mode";
                 emitByte(0x04 | regenc);
                 emitByte(scale.log2 << 6 | indexenc | 0x05);
                 emitInt(disp);
@@ -531,7 +531,7 @@
             // cmpxchg r,[m] is equivalent to X86.rax, = CAS (m, X86.rax, r)
             cmpl(rax, adr);
             movl(rax, adr);
-            if (reg != rax) {
+            if (reg.equals(rax)) {
                 Label l = new Label();
                 jccb(ConditionFlag.NotEqual, l);
                 movl(adr, reg);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed May 22 22:13:30 2013 +0200
@@ -125,7 +125,8 @@
         } else {
             Debug.dump(graph, "initial state");
         }
-        new VerifyValueUsage(runtime).apply(graph);
+        new VerifyUsageWithEquals(runtime, Value.class).apply(graph);
+        new VerifyUsageWithEquals(runtime, Register.class).apply(graph);
 
         if (GraalOptions.OptCanonicalizer) {
             new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Wed May 22 22:13:30 2013 +0200
@@ -654,12 +654,12 @@
             int number = availableReg.number;
             if (usePos[number] >= intervalTo) {
                 // this register is free for the full interval
-                if (minFullReg == null || availableReg == hint || (usePos[number] < usePos[minFullReg.number] && minFullReg != hint)) {
+                if (minFullReg == null || availableReg.equals(hint) || (usePos[number] < usePos[minFullReg.number] && !minFullReg.equals(hint))) {
                     minFullReg = availableReg;
                 }
             } else if (usePos[number] > regNeededUntil) {
                 // this register is at least free until regNeededUntil
-                if (maxPartialReg == null || availableReg == hint || (usePos[number] > usePos[maxPartialReg.number] && maxPartialReg != hint)) {
+                if (maxPartialReg == null || availableReg.equals(hint) || (usePos[number] > usePos[maxPartialReg.number] && !maxPartialReg.equals(hint))) {
                     maxPartialReg = availableReg;
                 }
             }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java	Wed May 22 22:13:30 2013 +0200
@@ -53,7 +53,7 @@
             masm.movq(rbp, (AMD64Address) tasm.asAddress(savedRbp));
         } else {
             Register framePointer = asRegister(savedRbp);
-            if (framePointer != rbp) {
+            if (!framePointer.equals(rbp)) {
                 masm.movq(rbp, framePointer);
             }
         }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java	Wed May 22 22:13:30 2013 +0200
@@ -61,13 +61,13 @@
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
         tasm.recordMark(Marks.MARK_INLINE_INVOKE);
         Register callReg = asRegister(targetAddress);
-        assert callReg != METHOD;
+        assert !callReg.equals(METHOD);
         AMD64Call.indirectCall(tasm, masm, callReg, callTarget, state);
     }
 
     @Override
     protected void verify() {
         super.verify();
-        assert asRegister(metaspaceMethod) == METHOD;
+        assert asRegister(metaspaceMethod).equals(METHOD);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Wed May 22 22:13:30 2013 +0200
@@ -184,8 +184,8 @@
                 bailout.printStackTrace(TTY.cachedOut);
             }
         } catch (Throwable t) {
+            t.printStackTrace(TTY.cachedOut);
             if (GraalOptions.ExitVMOnException) {
-                t.printStackTrace(TTY.cachedOut);
                 System.exit(-1);
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java	Wed May 22 22:13:30 2013 +0200
@@ -273,9 +273,20 @@
             ValueNode[] args = replacementArguments.toArray(new ValueNode[replacementArguments.size()]);
             callTarget = new SelfReplacingMethodCallTargetNode(invokeKind, targetMethod, targetArguments, returnType, replacementTargetMethod, args, replacementReturnType);
         }
+        graph().add(callTarget);
 
-        graph().add(callTarget);
-        InvokeNode invoke = graph().add(new InvokeNode(callTarget, getBci()));
+        // The call target can have a different return type than the invoker,
+        // e.g. the target returns an Object but the invoker void. In this case
+        // we need to use the stamp of the invoker. Note: always using the
+        // invoker's stamp would be wrong because it's a less concrete type
+        // (usually java.lang.Object).
+        InvokeNode invoke;
+        if (callTarget.returnStamp().kind() != stamp().kind()) {
+            invoke = new InvokeNode(callTarget, getBci(), stamp());
+        } else {
+            invoke = new InvokeNode(callTarget, getBci());
+        }
+        graph().add(invoke);
         invoke.setStateAfter(stateAfter());
         return invoke;
     }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Wed May 22 22:13:30 2013 +0200
@@ -273,7 +273,7 @@
         protected void verify() {
             super.verify();
             // left input in rax, right input in any register but rax and rdx, result quotient in rax, result remainder in rdx
-            assert asRegister(x) == AMD64.rax;
+            assert asRegister(x).equals(AMD64.rax);
             assert differentRegisters(y, AMD64.rax.asValue(), AMD64.rdx.asValue());
             verifyKind(opcode, divResult, x, y);
             verifyKind(opcode, remResult, x, y);
@@ -360,9 +360,9 @@
                 case IMUL: masm.imull(asIntReg(dst), asIntReg(src)); break;
                 case IOR:  masm.orl(asIntReg(dst),   asIntReg(src)); break;
                 case IXOR: masm.xorl(asIntReg(dst),  asIntReg(src)); break;
-                case ISHL: assert asIntReg(src) == AMD64.rcx; masm.shll(asIntReg(dst)); break;
-                case ISHR: assert asIntReg(src) == AMD64.rcx; masm.sarl(asIntReg(dst)); break;
-                case IUSHR: assert asIntReg(src) == AMD64.rcx; masm.shrl(asIntReg(dst)); break;
+                case ISHL: assert asIntReg(src).equals(AMD64.rcx); masm.shll(asIntReg(dst)); break;
+                case ISHR: assert asIntReg(src).equals(AMD64.rcx); masm.sarl(asIntReg(dst)); break;
+                case IUSHR: assert asIntReg(src).equals(AMD64.rcx); masm.shrl(asIntReg(dst)); break;
 
                 case LADD: masm.addq(asLongReg(dst),  asLongReg(src)); break;
                 case LSUB: masm.subq(asLongReg(dst),  asLongReg(src)); break;
@@ -370,9 +370,9 @@
                 case LAND: masm.andq(asLongReg(dst),  asLongReg(src)); break;
                 case LOR:  masm.orq(asLongReg(dst),   asLongReg(src)); break;
                 case LXOR: masm.xorq(asLongReg(dst),  asLongReg(src)); break;
-                case LSHL: assert asIntReg(src) == AMD64.rcx; masm.shlq(asLongReg(dst)); break;
-                case LSHR: assert asIntReg(src) == AMD64.rcx; masm.sarq(asLongReg(dst)); break;
-                case LUSHR: assert asIntReg(src) == AMD64.rcx; masm.shrq(asLongReg(dst)); break;
+                case LSHL: assert asIntReg(src).equals(AMD64.rcx); masm.shlq(asLongReg(dst)); break;
+                case LSHR: assert asIntReg(src).equals(AMD64.rcx); masm.sarq(asLongReg(dst)); break;
+                case LUSHR: assert asIntReg(src).equals(AMD64.rcx); masm.shrq(asLongReg(dst)); break;
 
                 case FADD: masm.addss(asFloatReg(dst), asFloatReg(src)); break;
                 case FSUB: masm.subss(asFloatReg(dst), asFloatReg(src)); break;
@@ -556,6 +556,6 @@
             || (opcode.name().startsWith("L") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Long)
             || (opcode.name().startsWith("F") && result.getKind() == Kind.Float && x.getKind() == Kind.Float && y.getKind() == Kind.Float)
             || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double)
-            || (opcode.name().matches(".U?SH.") && result.getKind() == x.getKind() && y.getKind() == Kind.Int && (isConstant(y) || asRegister(y) == AMD64.rcx));
+            || (opcode.name().matches(".U?SH.") && result.getKind() == x.getKind() && y.getKind() == Kind.Int && (isConstant(y) || asRegister(y).equals(AMD64.rcx)));
     }
 }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Wed May 22 22:13:30 2013 +0200
@@ -404,7 +404,7 @@
 
     private static void cmove(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, ConditionFlag cond, Value other) {
         if (isRegister(other)) {
-            assert asRegister(other) != asRegister(result) : "other already overwritten by previous move";
+            assert !asRegister(other).equals(asRegister(result)) : "other already overwritten by previous move";
             switch (other.getKind()) {
                 case Int:  masm.cmovl(cond, asRegister(result), asRegister(other)); break;
                 case Long: masm.cmovq(cond, asRegister(result), asRegister(other)); break;
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Wed May 22 22:13:30 2013 +0200
@@ -526,7 +526,7 @@
     }
 
     protected static void compareAndSwap(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
-        assert asRegister(cmpValue) == AMD64.rax && asRegister(result) == AMD64.rax;
+        assert asRegister(cmpValue).equals(AMD64.rax) && asRegister(result).equals(AMD64.rax);
 
         if (tasm.target.isMP) {
             masm.lock();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Wed May 22 22:13:30 2013 +0200
@@ -30,6 +30,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.Stamp;
 import com.oracle.graal.nodes.util.*;
 
 /**
@@ -48,11 +49,22 @@
     /**
      * Constructs a new Invoke instruction.
      * 
+     * @param callTarget the target method being called
      * @param bci the bytecode index of the original invoke (used for debug infos)
-     * @param callTarget the target method being called
      */
     public InvokeNode(CallTargetNode callTarget, int bci) {
-        super(callTarget.returnStamp());
+        this(callTarget, bci, callTarget.returnStamp());
+    }
+
+    /**
+     * Constructs a new Invoke instruction.
+     * 
+     * @param callTarget the target method being called
+     * @param bci the bytecode index of the original invoke (used for debug infos)
+     * @param stamp the stamp to be used for this value
+     */
+    public InvokeNode(CallTargetNode callTarget, int bci, Stamp stamp) {
+        super(stamp);
         this.callTarget = callTarget;
         this.bci = bci;
         this.polymorphic = false;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Wed May 22 22:13:30 2013 +0200
@@ -61,12 +61,6 @@
 
     @Override
     public boolean inferStamp() {
-        if (stamp() instanceof ObjectStamp && object().objectStamp().alwaysNull() && objectStamp().nonNull()) {
-            // a null value flowing into a nonNull PiNode should be guarded by a type/isNull guard,
-            // but the
-            // compiler might see this situation before the branch is deleted
-            return false;
-        }
         return updateStamp(stamp().join(object().stamp()));
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Wed May 22 22:13:30 2013 +0200
@@ -60,7 +60,7 @@
      * @return true if the stamp has changed, false otherwise.
      */
     protected final boolean updateStamp(Stamp newStamp) {
-        if (newStamp.equals(stamp)) {
+        if (newStamp == null || newStamp.equals(stamp)) {
             return false;
         } else {
             stamp = newStamp;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Wed May 22 22:13:30 2013 +0200
@@ -52,12 +52,6 @@
         if (stamp() == StampFactory.forNodeIntrinsic()) {
             return false;
         }
-        if (object().objectStamp().alwaysNull() && objectStamp().nonNull()) {
-            // a null value flowing into a nonNull UnsafeCastNode should be guarded by a type/isNull
-            // guard, but the
-            // compiler might see this situation before the branch is deleted
-            return false;
-        }
         return updateStamp(stamp().join(object().stamp()));
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Wed May 22 22:13:30 2013 +0200
@@ -69,9 +69,6 @@
 
     @Override
     public boolean inferStamp() {
-        if (object().objectStamp().alwaysNull() && objectStamp().nonNull()) {
-            return false;
-        }
         return updateStamp(stamp().join(object().stamp()));
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java	Wed May 22 22:13:30 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.type;
 
+import java.lang.reflect.*;
+
 import com.oracle.graal.api.meta.*;
 
 public class ObjectStamp extends Stamp {
@@ -33,14 +35,29 @@
 
     public ObjectStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) {
         super(Kind.Object);
-        assert !exactType || type != null;
-        assert !(nonNull && alwaysNull);
+        assert isValid(type, exactType, nonNull, alwaysNull);
         this.type = type;
         this.exactType = exactType;
         this.nonNull = nonNull;
         this.alwaysNull = alwaysNull;
     }
 
+    public static boolean isValid(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) {
+        if (exactType && type == null) {
+            return false;
+        }
+
+        if (exactType && Modifier.isAbstract(type.getModifiers()) && !type.isArray()) {
+            return false;
+        }
+
+        if (nonNull && alwaysNull) {
+            return false;
+        }
+
+        return true;
+    }
+
     @Override
     public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
         if (type != null) {
@@ -152,12 +169,19 @@
                 joinType = type;
             }
         }
+
         if (joinType == type && joinExactType == exactType && joinNonNull == nonNull && joinAlwaysNull == alwaysNull) {
             return this;
         } else if (joinType == other.type && joinExactType == other.exactType && joinNonNull == other.nonNull && joinAlwaysNull == other.alwaysNull) {
             return other;
         } else {
-            return new ObjectStamp(joinType, joinExactType, joinNonNull, joinAlwaysNull);
+            if (isValid(joinType, joinExactType, joinNonNull, joinAlwaysNull)) {
+                return new ObjectStamp(joinType, joinExactType, joinNonNull, joinAlwaysNull);
+            } else {
+                // This situation can happen in case the compiler wants to join two contradicting
+                // stamps.
+                return null;
+            }
         }
     }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Wed May 22 17:47:24 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Wed May 22 22:13:30 2013 +0200
@@ -255,7 +255,7 @@
                         callerHasMoreInformationAboutArguments = true;
                     } else {
                         Stamp joinedStamp = localNode.stamp().join(arg.stamp());
-                        if (!joinedStamp.equals(localNode.stamp())) {
+                        if (joinedStamp != null && !joinedStamp.equals(localNode.stamp())) {
                             localNode.setStamp(joinedStamp);
                             callerHasMoreInformationAboutArguments = true;
                         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java	Wed May 22 22:13:30 2013 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.verify;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.phases.*;
+
+public class VerifyUsageWithEquals extends VerifyPhase {
+
+    private MetaAccessProvider runtime;
+    private Class<?> klass;
+
+    public VerifyUsageWithEquals(MetaAccessProvider runtime, Class<?> klass) {
+        this.runtime = runtime;
+        this.klass = klass;
+    }
+
+    private boolean isAssignableType(ValueNode node) {
+        if (node.stamp() instanceof ObjectStamp) {
+            ResolvedJavaType valueType = runtime.lookupJavaType(klass);
+            ResolvedJavaType nodeType = node.objectStamp().type();
+
+            if (valueType.isAssignableFrom(nodeType)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static boolean isNullConstant(ValueNode node) {
+        return node.isConstant() && node.asConstant().isNull();
+    }
+
+    private boolean checkUsage(ValueNode x, ValueNode y) {
+        return isAssignableType(x) && !isNullConstant(y);
+    }
+
+    private static boolean isEqualsMethod(StructuredGraph graph) {
+        Signature signature = graph.method().getSignature();
+        return graph.method().getName().equals("equals") && signature.getParameterCount(false) == 1 && signature.getParameterKind(0).equals(Kind.Object);
+    }
+
+    @Override
+    protected boolean verify(StructuredGraph graph) {
+        for (ObjectEqualsNode cn : graph.getNodes().filter(ObjectEqualsNode.class)) {
+            if (!isEqualsMethod(graph)) {
+                // bail out if we compare an object of type klass with == or != (except null checks)
+                assert !(checkUsage(cn.x(), cn.y()) && checkUsage(cn.y(), cn.x())) : "VerifyUsage of " + klass.getName() + ": " + cn.x() + " or " + cn.y() + " in " + graph.method() +
+                                " uses object identity. Should use equals() instead.";
+            }
+        }
+        return true;
+    }
+}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyValueUsage.java	Wed May 22 17:47:24 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.verify;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.phases.*;
-
-public class VerifyValueUsage extends VerifyPhase {
-
-    private MetaAccessProvider runtime;
-
-    public VerifyValueUsage(MetaAccessProvider runtime) {
-        this.runtime = runtime;
-    }
-
-    private boolean checkType(ValueNode node) {
-        if (node.stamp() instanceof ObjectStamp) {
-            ResolvedJavaType valueType = runtime.lookupJavaType(Value.class);
-            ResolvedJavaType nodeType = node.objectStamp().type();
-
-            if (valueType.isAssignableFrom(nodeType)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    protected boolean verify(StructuredGraph graph) {
-        for (ObjectEqualsNode cn : graph.getNodes().filter(ObjectEqualsNode.class)) {
-            Signature signature = graph.method().getSignature();
-            if (!(graph.method().getName().equals("equals") && signature.getParameterCount(false) == 1 && signature.getParameterKind(0).equals(Kind.Object))) {
-                assert !((checkType(cn.x()) && !(cn.y() instanceof ConstantNode)) || (checkType(cn.y()) && !(cn.x() instanceof ConstantNode))) : "VerifyValueUsage: " + cn.x() + " or " + cn.y() +
-                                " in " + graph.method() + " uses object identity. Should use equals() instead.";
-            }
-        }
-        return true;
-    }
-}