changeset 4432:12558f571128

simplifications to instanceof and checkcast hints
author Lukas Stadler <lukas.stadler@jku.at>
date Fri, 03 Feb 2012 11:05:58 +0100
parents 73f56093d824
children b494d6f329a3
files graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/CheckCastNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/InstanceOfNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/TypeCheckNode.java
diffstat 7 files changed, 57 insertions(+), 81 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java	Fri Feb 03 10:21:02 2012 +0100
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java	Fri Feb 03 11:05:58 2012 +0100
@@ -77,11 +77,11 @@
 
     XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, RiType type);
 
-    XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type, XirArgument[] hintHubs, boolean hintsExact);
+    XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact);
 
-    XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, RiType type, XirArgument[] hintHubs, boolean hintsExact);
+    XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact);
 
-    XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type, XirArgument[] hintHubs, boolean hintsExact);
+    XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type, RiResolvedType[] hints, boolean hintsExact);
 
     XirSnippet genArrayLoad(XirSite site, XirArgument array, XirArgument index, CiKind elementKind, RiType elementType);
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Fri Feb 03 10:21:02 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Fri Feb 03 11:05:58 2012 +0100
@@ -480,27 +480,12 @@
 
     @Override
     public void visitCheckCast(CheckCastNode x) {
-        XirArgument[] hints = getTypeCheckHints(x);
-        XirSnippet snippet = xir.genCheckCast(site(x), toXirArgument(x.object()), toXirArgument(x.targetClassInstruction()), x.targetClass(), hints, x.hintsExact());
+        XirSnippet snippet = xir.genCheckCast(site(x), toXirArgument(x.object()), toXirArgument(x.targetClassInstruction()), x.targetClass(), x.hints(), x.hintsExact());
         emitXir(snippet, x, state(), true);
         // The result of a checkcast is the unmodified object, so no need to allocate a new variable for it.
         setResult(x, operand(x.object()));
     }
 
-    private XirArgument[] getTypeCheckHints(TypeCheckNode x) {
-        XirArgument[] hints;
-        if (!GraalOptions.UseInstanceOfHints || x.hints() == null || x.hints().length == 0) {
-            hints = new XirArgument[0];
-        } else {
-            assert x.hints().length == x.hintInstructions().size();
-            hints = new XirArgument[x.hints().length];
-            for (int i = 0; i < x.hints().length; i++) {
-                hints[i] = toXirArgument(x.hintInstructions().get(i));
-            }
-        }
-        return hints;
-    }
-
     @Override
     public void visitMonitorEnter(MonitorEnterNode x) {
         CiStackSlot lockData = frameMap.allocateStackBlock(runtime.sizeOfLockData(), false);
@@ -754,9 +739,8 @@
     }
 
     private void emitInstanceOfBranch(InstanceOfNode x, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) {
-        XirArgument[] hints = getTypeCheckHints(x);
         XirArgument obj = toXirArgument(x.object());
-        XirSnippet snippet = xir.genInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), x.targetClass(), hints, x.hintsExact());
+        XirSnippet snippet = xir.genInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), x.targetClass(), x.hints(), x.hintsExact());
         emitXir(snippet, x, info, null, false, x.negated() ? falseSuccessor : trueSuccessor, x.negated() ? trueSuccessor : falseSuccessor);
     }
 
@@ -798,11 +782,10 @@
     }
 
     private Variable emitInstanceOfConditional(InstanceOfNode x, CiValue trueValue, CiValue falseValue) {
-        XirArgument[] hints = getTypeCheckHints(x);
         XirArgument obj = toXirArgument(x.object());
         XirArgument trueArg = toXirArgument(x.negated() ? falseValue : trueValue);
         XirArgument falseArg = toXirArgument(x.negated() ? trueValue : falseValue);
-        XirSnippet snippet = xir.genMaterializeInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), trueArg, falseArg, x.targetClass(), hints, x.hintsExact());
+        XirSnippet snippet = xir.genMaterializeInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), trueArg, falseArg, x.targetClass(), x.hints(), x.hintsExact());
         return (Variable) emitXir(snippet, null, null, false);
     }
 
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java	Fri Feb 03 10:21:02 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java	Fri Feb 03 11:05:58 2012 +0100
@@ -666,13 +666,15 @@
                 // -- out of line -------------------------------------------------------
                 asm.bindOutOfLine(slowPath);
             } else {
+                XirOperand scratchObject = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10);
                 // if we get an exact match: succeed immediately
                 for (int i = 0; i < hintCount; i++) {
-                    XirParameter hintHub = asm.createInputParameter("hintHub" + i, CiKind.Object);
+                    XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, CiKind.Object);
+                    asm.mov(scratchObject, hintHub);
                     if (i < hintCount - 1) {
-                        asm.jeq(end, objHub, hintHub);
+                        asm.jeq(end, objHub, scratchObject);
                     } else {
-                        asm.jneq(slowPath, objHub, hintHub);
+                        asm.jneq(slowPath, objHub, scratchObject);
                     }
                 }
                 asm.bindInline(end);
@@ -684,8 +686,8 @@
                     asm.jneq(end, objHub, asm.o(null));
                 }
             }
+            XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10);
 
-            XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10);
             asm.mov(scratch, wordConst(asm, 2));
 
             asm.callRuntime(CiRuntimeCall.Deoptimize, null);
@@ -722,19 +724,21 @@
                 asm.jmp(trueSucc);
             } else {
                 XirLabel slowPath = null;
+                XirOperand scratchObject = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10);
 
                 // if we get an exact match: succeed immediately
                 for (int i = 0; i < hintCount; i++) {
-                    XirParameter hintHub = asm.createInputParameter("hintHub" + i, CiKind.Object);
+                    XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, CiKind.Object);
+                    asm.mov(scratchObject, hintHub);
                     if (i < hintCount - 1) {
-                        asm.jeq(trueSucc, objHub, hintHub);
+                        asm.jeq(trueSucc, objHub, scratchObject);
                     } else {
                         if (is(EXACT_HINTS, flags)) {
-                            asm.jneq(falseSucc, objHub, hintHub);
+                            asm.jneq(falseSucc, objHub, scratchObject);
                             asm.jmp(trueSucc);
                         } else {
                             slowPath = asm.createOutOfLineLabel("slow path");
-                            asm.jneq(slowPath, objHub, hintHub);
+                            asm.jneq(slowPath, objHub, scratchObject);
                             asm.jmp(trueSucc);
                         }
                     }
@@ -786,18 +790,20 @@
                 asm.bindInline(end);
             } else {
                 XirLabel slowPath = null;
+                XirOperand scratchObject = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10);
 
                 // if we get an exact match: succeed immediately
                 for (int i = 0; i < hintCount; i++) {
-                    XirParameter hintHub = asm.createInputParameter("hintHub" + i, CiKind.Object);
+                    XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, CiKind.Object);
+                    asm.mov(scratchObject, hintHub);
                     if (i < hintCount - 1) {
-                        asm.jeq(end, objHub, hintHub);
+                        asm.jeq(end, objHub, scratchObject);
                     } else {
                         if (is(EXACT_HINTS, flags)) {
-                            asm.jeq(end, objHub, hintHub);
+                            asm.jeq(end, objHub, scratchObject);
                         } else {
                             slowPath = asm.createOutOfLineLabel("slow path");
-                            asm.jeq(end, objHub, hintHub);
+                            asm.jeq(end, objHub, scratchObject);
                             asm.jmp(slowPath);
                         }
                     }
@@ -1317,54 +1323,51 @@
     }
 
     @Override
-    public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type, XirArgument[] hintHubs, boolean hintsExact) {
-        System.out.print(hintsExact ? "+" : "-");
-        if (hintHubs == null || hintHubs.length == 0) {
+    public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact) {
+        if (hints == null || hints.length == 0) {
             return new XirSnippet(checkCastTemplates.get(site, 0), receiver, hub);
         } else {
-            XirArgument[] params = new XirArgument[hintHubs.length + 2];
+            XirArgument[] params = new XirArgument[hints.length + 2];
             params[0] = receiver;
             params[1] = hub;
-            for (int i = 0; i < hintHubs.length; i++) {
-                params[i + 2] = hintHubs[i];
+            for (int i = 0; i < hints.length; i++) {
+                params[i + 2] = XirArgument.forObject(hints[i]);
             }
-            XirTemplate template = hintsExact ? checkCastTemplates.get(site, hintHubs.length, EXACT_HINTS) : checkCastTemplates.get(site, hintHubs.length);
+            XirTemplate template = hintsExact ? checkCastTemplates.get(site, hints.length, EXACT_HINTS) : checkCastTemplates.get(site, hints.length);
             return new XirSnippet(template, params);
         }
     }
 
     @Override
-    public XirSnippet genInstanceOf(XirSite site, XirArgument object, XirArgument hub, RiType type, XirArgument[] hintHubs, boolean hintsExact) {
-        System.out.print(hintsExact ? "+" : "-");
-        if (hintHubs == null || hintHubs.length == 0) {
+    public XirSnippet genInstanceOf(XirSite site, XirArgument object, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact) {
+        if (hints == null || hints.length == 0) {
             return new XirSnippet(instanceOfTemplates.get(site, 0), object, hub);
         } else {
-            XirArgument[] params = new XirArgument[hintHubs.length + 2];
+            XirArgument[] params = new XirArgument[hints.length + 2];
             params[0] = object;
             params[1] = hub;
-            for (int i = 0; i < hintHubs.length; i++) {
-                params[i + 2] = hintHubs[i];
+            for (int i = 0; i < hints.length; i++) {
+                params[i + 2] = XirArgument.forObject(hints[i]);
             }
-            XirTemplate template = hintsExact ? instanceOfTemplates.get(site, hintHubs.length, EXACT_HINTS) : instanceOfTemplates.get(site, hintHubs.length);
+            XirTemplate template = hintsExact ? instanceOfTemplates.get(site, hints.length, EXACT_HINTS) : instanceOfTemplates.get(site, hints.length);
             return new XirSnippet(template, params);
         }
     }
 
     @Override
-    public XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument object, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type, XirArgument[] hintHubs, boolean hintsExact) {
-        System.out.print(hintsExact ? "+" : "-");
-        if (hintHubs == null || hintHubs.length == 0) {
+    public XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument object, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type, RiResolvedType[] hints, boolean hintsExact) {
+        if (hints == null || hints.length == 0) {
             return new XirSnippet(materializeInstanceOfTemplates.get(site, 0), object, hub, trueValue, falseValue);
         } else {
-            XirArgument[] params = new XirArgument[hintHubs.length + 4];
+            XirArgument[] params = new XirArgument[hints.length + 4];
             params[0] = object;
             params[1] = hub;
             params[2] = trueValue;
             params[3] = falseValue;
-            for (int i = 0; i < hintHubs.length; i++) {
-                params[i + 4] = hintHubs[i];
+            for (int i = 0; i < hints.length; i++) {
+                params[i + 4] = XirArgument.forObject(hints[i]);
             }
-            XirTemplate template = hintsExact ? materializeInstanceOfTemplates.get(site, hintHubs.length, EXACT_HINTS) : materializeInstanceOfTemplates.get(site, hintHubs.length);
+            XirTemplate template = hintsExact ? materializeInstanceOfTemplates.get(site, hints.length, EXACT_HINTS) : materializeInstanceOfTemplates.get(site, hints.length);
             return new XirSnippet(template, params);
         }
     }
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java	Fri Feb 03 10:21:02 2012 +0100
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java	Fri Feb 03 11:05:58 2012 +0100
@@ -719,28 +719,23 @@
                 instanceOfNode = new InstanceOfNode(hub, (RiResolvedType) type, object, false);
             } else {
                 if (Modifier.isFinal(resolvedType.accessFlags()) || resolvedType.isArrayClass()) {
-                    instanceOfNode = new InstanceOfNode(hub, resolvedType, object, Collections.singletonList(hub), new RiResolvedType[] {resolvedType}, true, false);
+                    instanceOfNode = new InstanceOfNode(hub, resolvedType, object, new RiResolvedType[] {resolvedType}, true, false);
                 } else {
                     RiResolvedType uniqueSubtype = resolvedType.uniqueConcreteSubtype();
                     if (uniqueSubtype != null) {
-//                        TTY.println("unique concrete subtype: " + uniqueSubtype);
-                        ConstantNode subTypeHub = appendConstant(uniqueSubtype.getEncoding(RiType.Representation.ObjectHub));
-                        instanceOfNode = new InstanceOfNode(hub, resolvedType, object, Collections.singletonList(subTypeHub), new RiResolvedType[] {uniqueSubtype}, false, false);
+                        instanceOfNode = new InstanceOfNode(hub, resolvedType, object, new RiResolvedType[] {uniqueSubtype}, false, false);
                     } else {
                         RiTypeProfile typeProfile = method.typeProfile(bci());
                         if (typeProfile != null && typeProfile.types != null && typeProfile.types.length > 0) {
-                            ArrayList<ValueNode> hintInstructions = new ArrayList<>(typeProfile.types.length);
                             RiResolvedType[] hints = new RiResolvedType[typeProfile.types.length];
                             int hintCount = 0;
-
+                            int i  = 0;
                             for (RiResolvedType hint : typeProfile.types) {
-//                                TTY.println("profiled type: " + hint);
                                 if (hint.isSubtypeOf(resolvedType)) {
-                                    hintInstructions.add(appendConstant(hint.getEncoding(RiType.Representation.ObjectHub)));
                                     hints[hintCount++] = hint;
                                 }
                             }
-                            instanceOfNode = new InstanceOfNode(hub, (RiResolvedType) type, object, hintInstructions, Arrays.copyOf(hints, hintCount), false, false);
+                            instanceOfNode = new InstanceOfNode(hub, (RiResolvedType) type, object, Arrays.copyOf(hints, hintCount), false, false);
                         } else {
                             instanceOfNode = new InstanceOfNode(hub, (RiResolvedType) type, object, false);
                         }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/CheckCastNode.java	Fri Feb 03 10:21:02 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/CheckCastNode.java	Fri Feb 03 11:05:58 2012 +0100
@@ -34,6 +34,8 @@
 
 /**
  * The {@code CheckCastNode} represents a {@link Bytecodes#CHECKCAST}.
+ *
+ * The {@link #targetClass()} of a CheckCastNode can be null for array store checks!
  */
 public final class CheckCastNode extends TypeCheckNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType {
 
@@ -51,12 +53,11 @@
      * @param object the instruction producing the object
      */
     public CheckCastNode(AnchorNode anchor, ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object) {
-        this(anchor, targetClassInstruction, targetClass, object, null, EMPTY_HINTS, false);
+        this(anchor, targetClassInstruction, targetClass, object, EMPTY_HINTS, false);
     }
 
-    public CheckCastNode(AnchorNode anchor, ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, List<? extends ValueNode> hintInstructions, RiResolvedType[] hints, boolean hintsExact) {
-        super(targetClassInstruction, targetClass, object, hintInstructions, hints, hintsExact, targetClass == null ? StampFactory.forKind(CiKind.Object) : StampFactory.declared(targetClass));
-        assert targetClass != null;
+    public CheckCastNode(AnchorNode anchor, ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, RiResolvedType[] hints, boolean hintsExact) {
+        super(targetClassInstruction, targetClass, object, hints, hintsExact, targetClass == null ? StampFactory.forKind(CiKind.Object) : StampFactory.declared(targetClass));
         this.anchor = anchor;
     }
 
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/InstanceOfNode.java	Fri Feb 03 10:21:02 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/InstanceOfNode.java	Fri Feb 03 11:05:58 2012 +0100
@@ -51,11 +51,11 @@
      * @param object the instruction producing the object input to this instruction
      */
     public InstanceOfNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, boolean negated) {
-        this(targetClassInstruction, targetClass, object, null, EMPTY_HINTS, false, negated);
+        this(targetClassInstruction, targetClass, object, EMPTY_HINTS, false, negated);
     }
 
-    public InstanceOfNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, List<? extends ValueNode> hintInstructions, RiResolvedType[] hints, boolean hintsExact, boolean negated) {
-        super(targetClassInstruction, targetClass, object, hintInstructions, hints, hintsExact, StampFactory.illegal());
+    public InstanceOfNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, RiResolvedType[] hints, boolean hintsExact, boolean negated) {
+        super(targetClassInstruction, targetClass, object, hints, hintsExact, StampFactory.illegal());
         this.negated = negated;
         assert targetClass != null;
     }
@@ -103,7 +103,7 @@
         if (tool.assumptions() != null && hints() != null && targetClass() != null) {
             if (!hintsExact() && hints().length == 1 && hints()[0] == targetClass().uniqueConcreteSubtype()) {
                 tool.assumptions().recordConcreteSubtype(targetClass(), hints()[0]);
-                return graph().unique(new InstanceOfNode(targetClassInstruction(), targetClass(), object(), hintInstructions(), hints(), true, negated));
+                return graph().unique(new InstanceOfNode(targetClassInstruction(), targetClass(), object(), hints(), true, negated));
             }
         }
         return this;
@@ -111,6 +111,6 @@
 
     @Override
     public BooleanNode negate() {
-        return graph().unique(new InstanceOfNode(targetClassInstruction(), targetClass(), object(), hintInstructions(), hints(), hintsExact(), !negated));
+        return graph().unique(new InstanceOfNode(targetClassInstruction(), targetClass(), object(), hints(), hintsExact(), !negated));
     }
 }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/TypeCheckNode.java	Fri Feb 03 10:21:02 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/TypeCheckNode.java	Fri Feb 03 11:05:58 2012 +0100
@@ -37,7 +37,6 @@
     protected static final RiResolvedType[] EMPTY_HINTS = new RiResolvedType[0];
     @Input private ValueNode object;
     @Input private ValueNode targetClassInstruction;
-    @Input private final NodeInputList<ValueNode> hintInstructions;
     @Data private final RiResolvedType targetClass;
     @Data private final RiResolvedType[] hints;
     @Data private final boolean hintsExact;
@@ -49,12 +48,11 @@
      * @param object the node which produces the object
      * @param kind the result type of this node
      */
-    public TypeCheckNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, List<? extends ValueNode> hintInstructions, RiResolvedType[] hints, boolean hintsExact, Stamp stamp) {
+    public TypeCheckNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, RiResolvedType[] hints, boolean hintsExact, Stamp stamp) {
         super(stamp);
         this.targetClassInstruction = targetClassInstruction;
         this.targetClass = targetClass;
         this.object = object;
-        this.hintInstructions = new NodeInputList<>(this, hintInstructions);
         this.hints = hints;
         this.hintsExact = hintsExact;
     }
@@ -75,10 +73,6 @@
         return targetClass;
     }
 
-    public NodeInputList<ValueNode> hintInstructions() {
-        return hintInstructions;
-    }
-
     public RiResolvedType[] hints() {
         return hints;
     }