changeset 3510:cca4ea9b9064

Add materialized variant of instanceof in xir, use it to implement Conditional(InstanceOf)
author Gilles Duboscq <gilles.duboscq@oracle.com>
date Mon, 08 Aug 2011 18:38:24 +0200
parents 3fe8c149b0b6
children 5f3d12c9f300
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Conditional.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ConvertConditionalPhase.java graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java
diffstat 5 files changed, 70 insertions(+), 96 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Mon Aug 08 17:14:44 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Mon Aug 08 18:38:24 2011 +0200
@@ -553,6 +553,13 @@
         instr.setFalseSuccessor(falseSuccessor);
     }
 
+    public void emitMaterializeInstanceOf(MaterializeNode materialize, Value resultValue, LIRDebugInfo info) {
+        TypeCheck x = (TypeCheck) materialize.condition();
+        XirArgument obj = toXirArgument(x.object());
+        XirSnippet snippet = xir.genMaterializeInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), x.targetClass());
+        emitXir(snippet, resultValue, info, null, true);
+    }
+
 
     public void emitConstantBranch(boolean value, LIRBlock trueSuccessorBlock, LIRBlock falseSuccessorBlock, LIRDebugInfo info) {
         if (value) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Mon Aug 08 17:14:44 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Mon Aug 08 18:38:24 2011 +0200
@@ -136,8 +136,6 @@
             graph.stopRecordModifications();
         }
 
-        new ConvertConditionalPhase().apply(graph);
-
         new LoweringPhase(compilation.runtime).apply(graph);
         if (GraalOptions.Lower) {
             new MemoryPhase().apply(graph);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Conditional.java	Mon Aug 08 17:14:44 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Conditional.java	Mon Aug 08 18:38:24 2011 +0200
@@ -208,7 +208,6 @@
             Conditional conditional = (Conditional) n;
             BooleanNode condition = conditional.condition();
 
-            CiVariable result = generator.createResultVariable(conditional);
             // try to use cmp + cmov first
             Condition cond = null;
             CiValue left = null;
@@ -242,13 +241,24 @@
                 right = CiConstant.NULL_OBJECT;
                 cond = Condition.NE;
             } else if (condition instanceof Constant) {
-                generator.lir().move(result, condition.asConstant());
+                generator.lir().move(generator.createResultVariable(conditional), condition.asConstant());
+            } else if (condition instanceof InstanceOf) {
+                if (conditional instanceof MaterializeNode) {
+                    generator.emitMaterializeInstanceOf((MaterializeNode) conditional, conditional, null);
+                } else {
+                    generator.emitMaterializeInstanceOf((MaterializeNode) conditional, condition, null);
+                    left = condition.operand();
+                    right = CiConstant.INT_1;
+                    cond = Condition.EQ;
+                }
             } else {
                 throw Util.shouldNotReachHere("Currently not implemented because we can not create blocks during LIRGen : " + condition);
             }
-            CiValue tVal = generator.makeOperand(conditional.trueValue());
-            CiValue fVal = generator.makeOperand(conditional.falseValue());
+
             if (cond != null) {
+                CiVariable result = generator.createResultVariable(conditional);
+                CiValue tVal = generator.makeOperand(conditional.trueValue());
+                CiValue fVal = generator.makeOperand(conditional.falseValue());
                 if (negate) {
                     cond = cond.negate();
                 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ConvertConditionalPhase.java	Mon Aug 08 17:14:44 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2011, 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.max.graal.compiler.phases;
-
-import com.oracle.max.graal.compiler.ir.*;
-import com.oracle.max.graal.compiler.ir.Conditional.ConditionalStructure;
-import com.oracle.max.graal.compiler.schedule.*;
-import com.oracle.max.graal.graph.*;
-
-
-/**
- * Temporary phase that converts Conditional/Materialize Nodes that can not be LIRGenered properly for now.
- * Currently LIRGenerating something like
- * BRANCHcc L1 // (compare, instanceof...)
- * mov res, fVal
- * jmp L2
- * L1:
- * mov res, tVal
- * L2:
- *
- * or
- *
- * mov res, tVal
- * BRANCHcc L1:
- * mov res, fVal
- * L1:
- *
- * may create a few problems around register allocation:
- * - in the first construct, register allocation may decide to spill an other variable to allocate res, resulting ina spilling that is done only in one branch :
- * BRANCHcc L1 // (compare, instanceof...)
- * mov SpillSplot, res
- * mov res, fVal
- * jmp L2
- * L1:
- * mov res, tVal
- * L2:
- *
- * - in the second construct the register allocator will thing that the first definition of res is not used and BRANCHcc may need some temporary register
- * the allocator could then allocate the same register for res and this temporary
- */
-public class ConvertConditionalPhase extends Phase {
-
-    @Override
-    protected void run(Graph graph) {
-        IdentifyBlocksPhase schedule = null;
-        for (Conditional conditional  : graph.getNodes(Conditional.class)) {
-            BooleanNode condition = conditional.condition();
-            while (condition instanceof NegateBooleanNode) {
-                condition = ((NegateBooleanNode) condition).value();
-            }
-            if (!(condition instanceof Compare || condition instanceof IsNonNull || condition instanceof NegateBooleanNode || condition instanceof Constant)) {
-                ConditionalStructure conditionalStructure = Conditional.createConditionalStructure(condition, conditional.trueValue(), conditional.falseValue());
-                // schedule the if...
-                if (schedule == null) {
-                    schedule = new IdentifyBlocksPhase(false, false);
-                    schedule.apply(graph);
-                }
-                schedule.assignBlockToNode(conditional);
-                Block block = schedule.getNodeToBlock().get(conditional);
-                Anchor prev = block.createAnchor();
-                FixedNode next = prev.next();
-                prev.setNext(null);
-                conditionalStructure.merge.setNext(next);
-                prev.setNext(conditionalStructure.ifNode);
-                conditional.replaceAndDelete(conditionalStructure.phi);
-            }
-        }
-    }
-}
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java	Mon Aug 08 17:14:44 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java	Mon Aug 08 18:38:24 2011 +0200
@@ -36,7 +36,6 @@
 import com.sun.cri.ri.*;
 import com.sun.cri.ri.RiType.*;
 import com.sun.cri.xir.*;
-import com.sun.cri.xir.CiXirAssembler.XirLabel;
 import com.sun.cri.xir.CiXirAssembler.*;
 
 public class HotSpotXirGenerator implements RiXirGenerator {
@@ -667,6 +666,49 @@
         }
     };
 
+    private SimpleTemplates materializeInstanceOfTemplates = new SimpleTemplates(NULL_CHECK) {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags) {
+            XirOperand result = asm.restart(CiKind.Int);
+            XirParameter object = asm.createInputParameter("object", CiKind.Object);
+            final XirOperand hub;
+            hub = asm.createConstantInputParameter("hub", CiKind.Object);
+
+            XirOperand objHub = asm.createTemp("objHub", CiKind.Object);
+
+            XirLabel slowPath = asm.createOutOfLineLabel("slow path");
+            XirLabel trueSucc = asm.createInlineLabel("ok");
+            XirLabel falseSucc = asm.createInlineLabel("ko");
+            XirLabel end = asm.createInlineLabel("end");
+
+            if (is(NULL_CHECK, flags)) {
+                // null isn't "instanceof" anything
+                asm.jeq(falseSucc, object, asm.o(null));
+            }
+
+            asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false);
+            // if we get an exact match: succeed immediately
+            asm.jeq(trueSucc, objHub, hub);
+            asm.jmp(slowPath);
+
+            asm.bindInline(trueSucc);
+            asm.mov(result, asm.i(1));
+            asm.jmp(end);
+            asm.bindInline(falseSucc);
+            asm.mov(result, asm.i(0));
+            asm.bindInline(end);
+
+            // -- out of line -------------------------------------------------------
+            asm.bindOutOfLine(slowPath);
+            checkSubtype(asm, objHub, objHub, hub);
+            asm.jeq(falseSucc, objHub, asm.o(null));
+            asm.jmp(trueSucc);
+
+            return asm.finishTemplate("instanceof");
+        }
+    };
+
     private XirOperand genArrayLength(CiXirAssembler asm, XirOperand array, boolean implicitNullException) {
         XirOperand length = asm.createTemp("length", CiKind.Int);
         genArrayLength(asm, length, array, implicitNullException);
@@ -1189,6 +1231,12 @@
     }
 
     @Override
+    public XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument object, XirArgument hub, RiType type) {
+        assert type.isResolved();
+        return new XirSnippet(materializeInstanceOfTemplates.get(site), object, hub);
+    }
+
+    @Override
     public XirSnippet genArrayLoad(XirSite site, XirArgument array, XirArgument index, XirArgument length, CiKind elementKind, RiType elementType) {
         if (length == null || !site.requiresBoundsCheck()) {
             return new XirSnippet(arrayLoadTemplates.get(site, elementKind), array, index);