# HG changeset patch # User Lukas Stadler # Date 1328260653 -3600 # Node ID be4914c1c799a9b09e0f451969c3310d069e4a75 # Parent 730fab2457b832d40d8dc990b4c14415697fadcb add hints to InstanceOfNode and CheckCastNode diff -r 730fab2457b8 -r be4914c1c799 graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java Fri Feb 03 10:08:57 2012 +0100 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java Fri Feb 03 10:17:33 2012 +0100 @@ -77,11 +77,11 @@ XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, RiType type); - XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type); + XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type, XirArgument[] hintHubs, boolean hintsExact); - XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, RiType type); + XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, RiType type, XirArgument[] hintHubs, boolean hintsExact); - XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type); + XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type, XirArgument[] hintHubs, boolean hintsExact); XirSnippet genArrayLoad(XirSite site, XirArgument array, XirArgument index, CiKind elementKind, RiType elementType); diff -r 730fab2457b8 -r be4914c1c799 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Fri Feb 03 10:08:57 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Fri Feb 03 10:17:33 2012 +0100 @@ -126,6 +126,7 @@ public static int MatureInvocationCount = 100; public static boolean GenSafepoints = true; public static boolean GenLoopSafepoints = true; + public static boolean UseInstanceOfHints = true; public static boolean GenAssertionCode = ____; public static boolean AlignCallsForPatching = true; diff -r 730fab2457b8 -r be4914c1c799 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 Fri Feb 03 10:08:57 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Fri Feb 03 10:17:33 2012 +0100 @@ -480,12 +480,27 @@ @Override public void visitCheckCast(CheckCastNode x) { - XirSnippet snippet = xir.genCheckCast(site(x), toXirArgument(x.object()), toXirArgument(x.targetClassInstruction()), x.targetClass()); + XirArgument[] hints = getTypeCheckHints(x); + XirSnippet snippet = xir.genCheckCast(site(x), toXirArgument(x.object()), toXirArgument(x.targetClassInstruction()), x.targetClass(), 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); @@ -739,8 +754,9 @@ } 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()); + XirSnippet snippet = xir.genInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), x.targetClass(), hints, x.hintsExact()); emitXir(snippet, x, info, null, false, x.negated() ? falseSuccessor : trueSuccessor, x.negated() ? trueSuccessor : falseSuccessor); } @@ -782,10 +798,11 @@ } 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()); + XirSnippet snippet = xir.genMaterializeInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), trueArg, falseArg, x.targetClass(), hints, x.hintsExact()); return (Variable) emitXir(snippet, null, null, false); } diff -r 730fab2457b8 -r be4914c1c799 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java Fri Feb 03 10:08:57 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java Fri Feb 03 10:17:33 2012 +0100 @@ -637,10 +637,10 @@ } }; - private SimpleTemplates checkCastTemplates = new SimpleTemplates(NULL_CHECK) { + private IndexTemplates checkCastTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { + protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { asm.restart(CiKind.Void); XirParameter object = asm.createInputParameter("object", CiKind.Object); final XirOperand hub; @@ -657,14 +657,34 @@ } asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); - // if we get an exact match: succeed immediately - asm.jneq(slowPath, objHub, hub); - asm.bindInline(end); + if (hintCount == 0) { + assert !is(EXACT_HINTS, flags); + checkSubtype(asm, objHub, objHub, hub); + asm.jeq(slowPath, objHub, asm.o(null)); + asm.bindInline(end); - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(slowPath); - checkSubtype(asm, objHub, objHub, hub); - asm.jneq(end, objHub, asm.o(null)); + // -- out of line ------------------------------------------------------- + asm.bindOutOfLine(slowPath); + } else { + // if we get an exact match: succeed immediately + for (int i = 0; i < hintCount; i++) { + XirParameter hintHub = asm.createInputParameter("hintHub" + i, CiKind.Object); + if (i < hintCount - 1) { + asm.jeq(end, objHub, hintHub); + } else { + asm.jneq(slowPath, objHub, hintHub); + } + } + asm.bindInline(end); + + // -- out of line ------------------------------------------------------- + asm.bindOutOfLine(slowPath); + if (!is(EXACT_HINTS, flags)) { + checkSubtype(asm, objHub, objHub, hub); + asm.jneq(end, objHub, asm.o(null)); + } + } + XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); asm.mov(scratch, wordConst(asm, 2)); @@ -675,10 +695,10 @@ } }; - private SimpleTemplates instanceOfTemplates = new SimpleTemplates(NULL_CHECK) { + private IndexTemplates instanceOfTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { + protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { asm.restart(CiKind.Void); XirParameter object = asm.createInputParameter("object", CiKind.Object); final XirOperand hub; @@ -686,7 +706,6 @@ XirOperand objHub = asm.createTemp("objHub", CiKind.Object); - XirLabel slowPath = asm.createOutOfLineLabel("slow path"); XirLabel trueSucc = asm.createInlineLabel(XirLabel.TrueSuccessor); XirLabel falseSucc = asm.createInlineLabel(XirLabel.FalseSuccessor); @@ -696,24 +715,48 @@ } 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); + if (hintCount == 0) { + assert !is(EXACT_HINTS, flags); + checkSubtype(asm, objHub, objHub, hub); + asm.jeq(falseSucc, objHub, asm.o(null)); + asm.jmp(trueSucc); + } else { + XirLabel slowPath = null; - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(slowPath); - checkSubtype(asm, objHub, objHub, hub); - asm.jeq(falseSucc, objHub, asm.o(null)); - asm.jmp(trueSucc); + // if we get an exact match: succeed immediately + for (int i = 0; i < hintCount; i++) { + XirParameter hintHub = asm.createInputParameter("hintHub" + i, CiKind.Object); + if (i < hintCount - 1) { + asm.jeq(trueSucc, objHub, hintHub); + } else { + if (is(EXACT_HINTS, flags)) { + asm.jneq(falseSucc, objHub, hintHub); + asm.jmp(trueSucc); + } else { + slowPath = asm.createOutOfLineLabel("slow path"); + asm.jneq(slowPath, objHub, hintHub); + asm.jmp(trueSucc); + } + } + } + + // -- out of line ------------------------------------------------------- + if (slowPath != null) { + asm.bindOutOfLine(slowPath); + checkSubtype(asm, objHub, objHub, hub); + asm.jeq(falseSucc, objHub, asm.o(null)); + asm.jmp(trueSucc); + } + } return asm.finishTemplate("instanceof"); } }; - private SimpleTemplates materializeInstanceOfTemplates = new SimpleTemplates(NULL_CHECK) { + private IndexTemplates materializeInstanceOfTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { + protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { XirOperand result = asm.restart(CiKind.Int); XirParameter object = asm.createInputParameter("object", CiKind.Object); final XirOperand hub; @@ -723,10 +766,8 @@ XirOperand objHub = asm.createTemp("objHub", CiKind.Object); - XirLabel slowPath = asm.createOutOfLineLabel("slow path"); - XirLabel trueSucc = asm.createInlineLabel("ok"); + XirLabel end = asm.createInlineLabel("end"); XirLabel falseSucc = asm.createInlineLabel("ko"); - XirLabel end = asm.createInlineLabel("end"); if (is(NULL_CHECK, flags)) { // null isn't "instanceof" anything @@ -734,22 +775,45 @@ } 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.mov(result, trueValue); + + if (hintCount == 0) { + assert !is(EXACT_HINTS, flags); + checkSubtype(asm, objHub, objHub, hub); + asm.jneq(end, objHub, asm.o(null)); + asm.bindInline(falseSucc); + asm.mov(result, falseValue); + asm.bindInline(end); + } else { + XirLabel slowPath = null; - asm.bindInline(trueSucc); - asm.mov(result, trueValue); - asm.jmp(end); - asm.bindInline(falseSucc); - asm.mov(result, falseValue); - asm.bindInline(end); + // if we get an exact match: succeed immediately + for (int i = 0; i < hintCount; i++) { + XirParameter hintHub = asm.createInputParameter("hintHub" + i, CiKind.Object); + if (i < hintCount - 1) { + asm.jeq(end, objHub, hintHub); + } else { + if (is(EXACT_HINTS, flags)) { + asm.jeq(end, objHub, hintHub); + } else { + slowPath = asm.createOutOfLineLabel("slow path"); + asm.jeq(end, objHub, hintHub); + asm.jmp(slowPath); + } + } + } + asm.bindInline(falseSucc); + asm.mov(result, falseValue); + asm.bindInline(end); - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(slowPath); - checkSubtype(asm, objHub, objHub, hub); - asm.jeq(falseSucc, objHub, asm.o(null)); - asm.jmp(trueSucc); + // -- out of line ------------------------------------------------------- + if (slowPath != null) { + asm.bindOutOfLine(slowPath); + checkSubtype(asm, objHub, objHub, hub); + asm.jeq(falseSucc, objHub, asm.o(null)); + asm.jmp(end); + } + } return asm.finishTemplate("instanceof"); } @@ -1253,18 +1317,56 @@ } @Override - public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type) { - return new XirSnippet(checkCastTemplates.get(site), receiver, hub); + 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) { + return new XirSnippet(checkCastTemplates.get(site, 0), receiver, hub); + } else { + XirArgument[] params = new XirArgument[hintHubs.length + 2]; + params[0] = receiver; + params[1] = hub; + for (int i = 0; i < hintHubs.length; i++) { + params[i + 2] = hintHubs[i]; + } + XirTemplate template = hintsExact ? checkCastTemplates.get(site, hintHubs.length, EXACT_HINTS) : checkCastTemplates.get(site, hintHubs.length); + return new XirSnippet(template, params); + } } @Override - public XirSnippet genInstanceOf(XirSite site, XirArgument object, XirArgument hub, RiType type) { - return new XirSnippet(instanceOfTemplates.get(site), object, hub); + 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) { + return new XirSnippet(instanceOfTemplates.get(site, 0), object, hub); + } else { + XirArgument[] params = new XirArgument[hintHubs.length + 2]; + params[0] = object; + params[1] = hub; + for (int i = 0; i < hintHubs.length; i++) { + params[i + 2] = hintHubs[i]; + } + XirTemplate template = hintsExact ? instanceOfTemplates.get(site, hintHubs.length, EXACT_HINTS) : instanceOfTemplates.get(site, hintHubs.length); + return new XirSnippet(template, params); + } } @Override - public XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument object, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type) { - return new XirSnippet(materializeInstanceOfTemplates.get(site), object, hub, trueValue, falseValue); + 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) { + return new XirSnippet(materializeInstanceOfTemplates.get(site, 0), object, hub, trueValue, falseValue); + } else { + XirArgument[] params = new XirArgument[hintHubs.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]; + } + XirTemplate template = hintsExact ? materializeInstanceOfTemplates.get(site, hintHubs.length, EXACT_HINTS) : materializeInstanceOfTemplates.get(site, hintHubs.length); + return new XirSnippet(template, params); + } } @Override diff -r 730fab2457b8 -r be4914c1c799 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/TemplateFlag.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/TemplateFlag.java Fri Feb 03 10:08:57 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/TemplateFlag.java Fri Feb 03 10:17:33 2012 +0100 @@ -23,7 +23,7 @@ package com.oracle.max.graal.hotspot.ri; enum TemplateFlag { - NULL_CHECK, READ_BARRIER, WRITE_BARRIER, STORE_CHECK, BOUNDS_CHECK, GIVEN_LENGTH, INPUTS_DIFFERENT, INPUTS_SAME, STATIC_METHOD, SYNCHRONIZED; + NULL_CHECK, READ_BARRIER, WRITE_BARRIER, STORE_CHECK, BOUNDS_CHECK, GIVEN_LENGTH, INPUTS_DIFFERENT, INPUTS_SAME, STATIC_METHOD, SYNCHRONIZED, EXACT_HINTS; private static final long FIRST_FLAG = 0x0000000100000000L; public static final long FLAGS_MASK = 0x0000FFFF00000000L; diff -r 730fab2457b8 -r be4914c1c799 graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java Fri Feb 03 10:08:57 2012 +0100 +++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java Fri Feb 03 10:17:33 2012 +0100 @@ -711,8 +711,43 @@ RiType type = lookupType(cpi, INSTANCEOF); ValueNode object = frameState.apop(); if (type instanceof RiResolvedType) { - ConstantNode hub = appendConstant(((RiResolvedType) type).getEncoding(RiType.Representation.ObjectHub)); - frameState.ipush(append(MaterializeNode.create(currentGraph.unique(new InstanceOfNode(hub, (RiResolvedType) type, object, false)), currentGraph))); + RiResolvedType resolvedType = (RiResolvedType) type; + ConstantNode hub = appendConstant(resolvedType.getEncoding(RiType.Representation.ObjectHub)); + + final InstanceOfNode instanceOfNode; + if (!GraalOptions.UseInstanceOfHints) { + 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); + } 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); + } else { + RiTypeProfile typeProfile = method.typeProfile(bci()); + if (typeProfile != null && typeProfile.types != null && typeProfile.types.length > 0) { + ArrayList hintInstructions = new ArrayList<>(typeProfile.types.length); + RiResolvedType[] hints = new RiResolvedType[typeProfile.types.length]; + int hintCount = 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); + } else { + instanceOfNode = new InstanceOfNode(hub, (RiResolvedType) type, object, false); + } + } + } + } + frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode), currentGraph))); } else { PlaceholderNode trueSucc = currentGraph.add(new PlaceholderNode()); DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile)); diff -r 730fab2457b8 -r be4914c1c799 graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/CheckCastNode.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/CheckCastNode.java Fri Feb 03 10:08:57 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/CheckCastNode.java Fri Feb 03 10:17:33 2012 +0100 @@ -22,8 +22,11 @@ */ package com.oracle.max.graal.nodes.java; +import java.util.*; + import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.graph.*; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.extended.*; import com.oracle.max.graal.nodes.spi.*; @@ -32,10 +35,14 @@ /** * The {@code CheckCastNode} represents a {@link Bytecodes#CHECKCAST}. */ -public final class CheckCastNode extends TypeCheckNode implements Canonicalizable, LIRLowerable { +public final class CheckCastNode extends TypeCheckNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType { @Input protected final AnchorNode anchor; + public AnchorNode anchor() { + return anchor; + } + /** * Creates a new CheckCast instruction. * @@ -44,7 +51,12 @@ * @param object the instruction producing the object */ public CheckCastNode(AnchorNode anchor, ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object) { - super(targetClassInstruction, targetClass, object, targetClass == null ? StampFactory.forKind(CiKind.Object) : StampFactory.declared(targetClass)); + this(anchor, targetClassInstruction, targetClass, object, null, EMPTY_HINTS, false); + } + + public CheckCastNode(AnchorNode anchor, ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, List hintInstructions, RiResolvedType[] hints, boolean hintsExact) { + super(targetClassInstruction, targetClass, object, hintInstructions, hints, hintsExact, targetClass == null ? StampFactory.forKind(CiKind.Object) : StampFactory.declared(targetClass)); + assert targetClass != null; this.anchor = anchor; } diff -r 730fab2457b8 -r be4914c1c799 graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/InstanceOfNode.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/InstanceOfNode.java Fri Feb 03 10:08:57 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/InstanceOfNode.java Fri Feb 03 10:17:33 2012 +0100 @@ -22,6 +22,9 @@ */ package com.oracle.max.graal.nodes.java; +import java.lang.reflect.*; +import java.util.*; + import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; import com.oracle.max.graal.nodes.*; @@ -48,7 +51,11 @@ * @param object the instruction producing the object input to this instruction */ public InstanceOfNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, boolean negated) { - super(targetClassInstruction, targetClass, object, StampFactory.illegal()); + this(targetClassInstruction, targetClass, object, null, EMPTY_HINTS, false, negated); + } + + public InstanceOfNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, List hintInstructions, RiResolvedType[] hints, boolean hintsExact, boolean negated) { + super(targetClassInstruction, targetClass, object, hintInstructions, hints, hintsExact, StampFactory.illegal()); this.negated = negated; assert targetClass != null; } @@ -59,8 +66,23 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { - if (object().exactType() != null) { - boolean result = object().exactType().isSubtypeOf(targetClass()); + RiResolvedType exact = object().exactType(); + + if (exact == null) { + if (object().declaredType() != null) { + if (Modifier.isFinal(object().declaredType().accessFlags()) || object().declaredType().isArrayClass()) { + exact = object().declaredType(); + } else if (tool.assumptions() != null) { + exact = object().declaredType().uniqueConcreteSubtype(); + if (exact != null) { + tool.assumptions().recordConcreteSubtype(object().declaredType(), exact); + } + } + } + } + + if (exact != null) { + boolean result = exact.isSubtypeOf(targetClass()); if (result != negated) { // The instanceof check reduces to a null check. return graph().unique(new NullCheckNode(object(), false)); @@ -78,11 +100,17 @@ assert false : "non-null constants are always expected to provide an exactType"; } } + 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 this; } @Override public BooleanNode negate() { - return graph().unique(new InstanceOfNode(targetClassInstruction(), targetClass(), object(), !negated)); + return graph().unique(new InstanceOfNode(targetClassInstruction(), targetClass(), object(), hintInstructions(), hints(), hintsExact(), !negated)); } } diff -r 730fab2457b8 -r be4914c1c799 graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/TypeCheckNode.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/TypeCheckNode.java Fri Feb 03 10:08:57 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/TypeCheckNode.java Fri Feb 03 10:17:33 2012 +0100 @@ -22,7 +22,10 @@ */ package com.oracle.max.graal.nodes.java; +import java.util.*; + import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.graph.*; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.type.*; @@ -31,9 +34,13 @@ */ public abstract class TypeCheckNode extends BooleanNode { + protected static final RiResolvedType[] EMPTY_HINTS = new RiResolvedType[0]; @Input private ValueNode object; @Input private ValueNode targetClassInstruction; + @Input private final NodeInputList hintInstructions; @Data private final RiResolvedType targetClass; + @Data private final RiResolvedType[] hints; + @Data private final boolean hintsExact; /** * Creates a new TypeCheckNode. @@ -42,11 +49,14 @@ * @param object the node which produces the object * @param kind the result type of this node */ - public TypeCheckNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, Stamp stamp) { + public TypeCheckNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, List hintInstructions, 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; } public ValueNode object() { @@ -64,4 +74,16 @@ public RiResolvedType targetClass() { return targetClass; } + + public NodeInputList hintInstructions() { + return hintInstructions; + } + + public RiResolvedType[] hints() { + return hints; + } + + public boolean hintsExact() { + return hintsExact; + } }