changeset 15910:79a0d9065849

Support direct comparison of compressed pointers.
author Roland Schatz <roland.schatz@oracle.com>
date Mon, 26 May 2014 16:13:58 +0200
parents e43591136d9f
children 03e09ed7039d
files graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCompare.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java
diffstat 4 files changed, 196 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon May 26 16:09:53 2014 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon May 26 16:13:58 2014 +0200
@@ -242,18 +242,10 @@
     public void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueLabel, LabelRef falseLabel, double trueLabelProbability) {
         boolean mirrored = emitCompare(cmpKind, left, right);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
-        switch (left.getKind().getStackKind()) {
-            case Int:
-            case Long:
-            case Object:
-                append(new BranchOp(finalCondition, trueLabel, falseLabel, trueLabelProbability));
-                break;
-            case Float:
-            case Double:
-                append(new FloatBranchOp(finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability));
-                break;
-            default:
-                throw GraalInternalError.shouldNotReachHere("" + left.getKind());
+        if (cmpKind == Kind.Float || cmpKind == Kind.Double) {
+            append(new FloatBranchOp(finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability));
+        } else {
+            append(new BranchOp(finalCondition, trueLabel, falseLabel, trueLabelProbability));
         }
     }
 
@@ -261,18 +253,10 @@
                     double trueLabelProbability) {
         boolean mirrored = emitCompareMemory(cmpKind, left, right, state);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
-        switch (left.getKind().getStackKind()) {
-            case Int:
-            case Long:
-            case Object:
-                append(new BranchOp(finalCondition, trueLabel, falseLabel, trueLabelProbability));
-                break;
-            case Float:
-            case Double:
-                append(new FloatBranchOp(finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability));
-                break;
-            default:
-                throw GraalInternalError.shouldNotReachHere("" + left.getKind());
+        if (cmpKind == Kind.Float || cmpKind == Kind.Double) {
+            append(new FloatBranchOp(finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability));
+        } else {
+            append(new BranchOp(finalCondition, trueLabel, falseLabel, trueLabelProbability));
         }
     }
 
@@ -293,18 +277,10 @@
         Condition finalCondition = mirrored ? cond.mirror() : cond;
 
         Variable result = newVariable(trueValue.getKind());
-        switch (left.getKind().getStackKind()) {
-            case Int:
-            case Long:
-            case Object:
-                append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue)));
-                break;
-            case Float:
-            case Double:
-                append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue)));
-                break;
-            default:
-                throw GraalInternalError.shouldNotReachHere("" + left.getKind());
+        if (cmpKind == Kind.Float || cmpKind == Kind.Double) {
+            append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue)));
+        } else {
+            append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue)));
         }
         return result;
     }
@@ -370,13 +346,13 @@
             emitCompareRegMemoryOp(cmpKind, left, b, state);
             mirrored = false;
         } else {
-            emitCompareMemoryConOp(cmpKind, b, a, state);
+            emitCompareMemoryConOp(cmpKind, b, (Constant) a, state);
             mirrored = true;
         }
         return mirrored;
     }
 
-    protected void emitCompareMemoryConOp(Kind kind, AMD64AddressValue address, Value value, LIRFrameState state) {
+    protected void emitCompareMemoryConOp(Kind kind, AMD64AddressValue address, Constant value, LIRFrameState state) {
         assert kind.getStackKind() == value.getKind().getStackKind();
         switch (kind) {
             case Byte:
@@ -393,6 +369,10 @@
             case Long:
                 append(new CompareMemoryOp(LCMP, kind, address, value, state));
                 break;
+            case Object:
+                assert value.isNull();
+                append(new CompareMemoryOp(ACMP, kind, address, value, state));
+                break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCompare.java	Mon May 26 16:13:58 2014 +0200
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.amd64;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.hotspot.data.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.nodes.type.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.amd64.AMD64Move.MemOp;
+import com.oracle.graal.lir.asm.*;
+
+public class AMD64HotSpotCompare {
+
+    @Opcode("NCMP")
+    public static class HotSpotCompareNarrowOp extends AMD64LIRInstruction {
+
+        @Use({REG}) protected AllocatableValue x;
+        @Use({REG, STACK}) protected AllocatableValue y;
+
+        public HotSpotCompareNarrowOp(AllocatableValue x, AllocatableValue y) {
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            if (isRegister(y)) {
+                masm.cmpl(asRegister(x), asRegister(y));
+            } else {
+                assert isStackSlot(y);
+                masm.cmpl(asRegister(x), (AMD64Address) crb.asAddress(y));
+            }
+        }
+
+        @Override
+        protected void verify() {
+            assert x.getPlatformKind() == NarrowOopStamp.NarrowOop && y.getPlatformKind() == NarrowOopStamp.NarrowOop;
+        }
+    }
+
+    @Opcode("CMP")
+    public static class HotSpotCompareConstantOp extends AMD64LIRInstruction {
+
+        @Use({REG}) protected AllocatableValue x;
+        protected Constant y;
+
+        public HotSpotCompareConstantOp(AllocatableValue x, Constant y) {
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            assert isRegister(x);
+            if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(y)) {
+                // compressed null
+                masm.testl(asRegister(x), asRegister(x));
+            } else if (y instanceof HotSpotObjectConstant) {
+                if (HotSpotObjectConstant.isCompressed(y)) {
+                    // compressed oop
+                    crb.recordInlineDataInCode(new OopData(0, HotSpotObjectConstant.asObject(y), true));
+                    masm.cmpl(asRegister(x), 0xDEADDEAD);
+                } else {
+                    // uncompressed oop
+                    AMD64Address patch = (AMD64Address) crb.recordDataReferenceInCode(new OopData(8, HotSpotObjectConstant.asObject(y), false));
+                    masm.cmpq(asRegister(x), patch);
+                }
+            } else if (y instanceof HotSpotMetaspaceConstant) {
+                if (y.getKind() == Kind.Int) {
+                    // compressed metaspace pointer
+                    crb.recordInlineDataInCode(new MetaspaceData(0, y.asInt(), HotSpotMetaspaceConstant.getMetaspaceObject(y), true));
+                    masm.cmpl(asRegister(x), y.asInt());
+                } else {
+                    // uncompressed metaspace pointer
+                    AMD64Address patch = (AMD64Address) crb.recordDataReferenceInCode(new MetaspaceData(8, y.asLong(), HotSpotObjectConstant.asObject(y), false));
+                    masm.cmpq(asRegister(x), patch);
+                }
+            } else {
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    @Opcode("CMP")
+    public static class HotSpotCompareMemoryConstantOp extends MemOp {
+
+        protected Constant y;
+
+        public HotSpotCompareMemoryConstantOp(Kind kind, AMD64AddressValue x, Constant y, LIRFrameState state) {
+            super(kind, x, state);
+            this.y = y;
+        }
+
+        @Override
+        protected void emitMemAccess(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(y)) {
+                // compressed null
+                masm.cmpl(address.toAddress(), 0);
+            } else if (y instanceof HotSpotObjectConstant) {
+                if (HotSpotObjectConstant.isCompressed(y) && crb.target.inlineObjects) {
+                    // compressed oop
+                    crb.recordInlineDataInCode(new OopData(0, HotSpotObjectConstant.asObject(y), true));
+                    masm.cmpl(address.toAddress(), 0xDEADDEAD);
+                } else {
+                    // uncompressed oop
+                    throw GraalInternalError.shouldNotReachHere();
+                }
+            } else if (y instanceof HotSpotMetaspaceConstant) {
+                if (y.getKind() == Kind.Int) {
+                    // compressed metaspace pointer
+                    crb.recordInlineDataInCode(new MetaspaceData(0, y.asInt(), HotSpotMetaspaceConstant.getMetaspaceObject(y), true));
+                    masm.cmpl(address.toAddress(), y.asInt());
+                } else {
+                    // uncompressed metaspace pointer
+                    throw GraalInternalError.shouldNotReachHere();
+                }
+            } else {
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Mon May 26 16:09:53 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Mon May 26 16:13:58 2014 +0200
@@ -643,6 +643,26 @@
     }
 
     @Override
+    protected void emitCompareOp(PlatformKind cmpKind, Variable left, Value right) {
+        if (right instanceof HotSpotConstant) {
+            append(new AMD64HotSpotCompare.HotSpotCompareConstantOp(left, (Constant) right));
+        } else if (cmpKind == NarrowOopStamp.NarrowOop) {
+            append(new AMD64HotSpotCompare.HotSpotCompareNarrowOp(left, asAllocatable(right)));
+        } else {
+            super.emitCompareOp(cmpKind, left, right);
+        }
+    }
+
+    @Override
+    protected void emitCompareMemoryConOp(Kind kind, AMD64AddressValue address, Constant value, LIRFrameState state) {
+        if (value instanceof HotSpotConstant) {
+            append(new AMD64HotSpotCompare.HotSpotCompareMemoryConstantOp(kind, address, value, state));
+        } else {
+            super.emitCompareMemoryConOp(kind, address, value, state);
+        }
+    }
+
+    @Override
     public boolean canInlineConstant(Constant c) {
         if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) {
             return true;
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Mon May 26 16:09:53 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Mon May 26 16:13:58 2014 +0200
@@ -84,7 +84,7 @@
         }
 
         @Override
-        public void emitMemAccess(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+        protected void emitMemAccess(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
             if (isRegister(y)) {
                 switch (opcode) {
                     case BCMP:
@@ -129,6 +129,13 @@
                             throw GraalInternalError.shouldNotReachHere();
                         }
                         break;
+                    case ACMP:
+                        if (asConstant(y).isNull()) {
+                            masm.cmpq(address.toAddress(), 0);
+                        } else {
+                            throw GraalInternalError.shouldNotReachHere();
+                        }
+                        break;
                     default:
                         throw GraalInternalError.shouldNotReachHere();
                 }