# HG changeset patch # User Gilles Duboscq # Date 1312821504 -7200 # Node ID cca4ea9b90643933541634d2cbc08c749649d423 # Parent 3fe8c149b0b614155732db2c9c1415efd274a345 Add materialized variant of instanceof in xir, use it to implement Conditional(InstanceOf) diff -r 3fe8c149b0b6 -r cca4ea9b9064 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java --- 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) { diff -r 3fe8c149b0b6 -r cca4ea9b9064 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java --- 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); diff -r 3fe8c149b0b6 -r cca4ea9b9064 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Conditional.java --- 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(); } diff -r 3fe8c149b0b6 -r cca4ea9b9064 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ConvertConditionalPhase.java --- 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); - } - } - } -} diff -r 3fe8c149b0b6 -r cca4ea9b9064 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java --- 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);