Search in sources :

Example 1 with ValueAnchorNode

use of org.graalvm.compiler.nodes.extended.ValueAnchorNode in project graal by oracle.

the class MethodHandleNode method maybeCastArgument.

/**
 * Inserts a node to cast the argument at index to the given type if the given type is more
 * concrete than the argument type.
 *
 * @param adder
 * @param index of the argument to be cast
 * @param type the type the argument should be cast to
 */
private static void maybeCastArgument(GraphAdder adder, ValueNode[] arguments, int index, JavaType type) {
    ValueNode argument = arguments[index];
    if (type instanceof ResolvedJavaType && !((ResolvedJavaType) type).isJavaLangObject()) {
        Assumptions assumptions = adder.getAssumptions();
        TypeReference targetType = TypeReference.create(assumptions, (ResolvedJavaType) type);
        /*
             * When an argument is a Word type, we can have a mismatch of primitive/object types
             * here. Not inserting a PiNode is a safe fallback, and Word types need no additional
             * type information anyway.
             */
        if (targetType != null && !targetType.getType().isPrimitive() && !argument.getStackKind().isPrimitive()) {
            ResolvedJavaType argumentType = StampTool.typeOrNull(argument.stamp(NodeView.DEFAULT));
            if (argumentType == null || (argumentType.isAssignableFrom(targetType.getType()) && !argumentType.equals(targetType.getType()))) {
                LogicNode inst = InstanceOfNode.createAllowNull(targetType, argument, null, null);
                assert !inst.isAlive();
                if (!inst.isTautology()) {
                    inst = adder.add(inst);
                    AnchoringNode guardAnchor = adder.getGuardAnchor();
                    DeoptimizationReason reason = DeoptimizationReason.ClassCastException;
                    DeoptimizationAction action = DeoptimizationAction.InvalidateRecompile;
                    JavaConstant speculation = JavaConstant.NULL_POINTER;
                    GuardingNode guard;
                    if (guardAnchor == null) {
                        FixedGuardNode fixedGuard = adder.add(new FixedGuardNode(inst, reason, action, speculation, false));
                        guard = fixedGuard;
                    } else {
                        GuardNode newGuard = adder.add(new GuardNode(inst, guardAnchor, reason, action, false, speculation));
                        adder.add(new ValueAnchorNode(newGuard));
                        guard = newGuard;
                    }
                    ValueNode valueNode = adder.add(PiNode.create(argument, StampFactory.object(targetType), guard.asNode()));
                    arguments[index] = valueNode;
                }
            }
        }
    }
}
Also used : GuardNode(org.graalvm.compiler.nodes.GuardNode) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) AnchoringNode(org.graalvm.compiler.nodes.extended.AnchoringNode) JavaConstant(jdk.vm.ci.meta.JavaConstant) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Assumptions(jdk.vm.ci.meta.Assumptions) ValueAnchorNode(org.graalvm.compiler.nodes.extended.ValueAnchorNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) TypeReference(org.graalvm.compiler.core.common.type.TypeReference) DeoptimizationAction(jdk.vm.ci.meta.DeoptimizationAction) DeoptimizationReason(jdk.vm.ci.meta.DeoptimizationReason) GuardingNode(org.graalvm.compiler.nodes.extended.GuardingNode)

Example 2 with ValueAnchorNode

use of org.graalvm.compiler.nodes.extended.ValueAnchorNode in project graal by oracle.

the class ConditionAnchorNode method lower.

@Override
public void lower(LoweringTool tool) {
    if (graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
        ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(null));
        graph().replaceFixedWithFixed(this, newAnchor);
    }
}
Also used : ValueAnchorNode(org.graalvm.compiler.nodes.extended.ValueAnchorNode)

Example 3 with ValueAnchorNode

use of org.graalvm.compiler.nodes.extended.ValueAnchorNode in project graal by oracle.

the class DevirtualizeCallsPhase method singleCallee.

private static void singleCallee(HostedMethod singleCallee, StructuredGraph graph, Invoke invoke, SubstrateMethodCallTargetNode callTarget) {
    /*
         * The invoke has only one callee, i.e., the call can be devirtualized to this callee. This
         * allows later inlining of the callee.
         *
         * We have to be careful to guard the improvement of the receiver type that is implied by
         * the devirtualization: The callee assumes that the receiver type is the type that declares
         * the callee. While this is true for all parts of the callee, it does not necessarily hold
         * for all parts of the caller. So we need to ensure that after a possible inlining no parts
         * of the callee float out to parts of the caller where the receiver type assumption does
         * not hold. Since we do not know where in the caller a possible type check is performed, we
         * anchor the receiver to the place of the original invoke.
         */
    ValueAnchorNode anchor = graph.add(new ValueAnchorNode(null));
    graph.addBeforeFixed(invoke.asNode(), anchor);
    Stamp anchoredReceiverStamp = StampFactory.object(TypeReference.createWithoutAssumptions(singleCallee.getDeclaringClass()));
    ValueNode anchoredReceiver = graph.unique(new PiNode(invoke.getReceiver(), anchoredReceiverStamp, anchor));
    invoke.callTarget().replaceFirstInput(invoke.getReceiver(), anchoredReceiver);
    assert callTarget.invokeKind() == InvokeKind.Virtual || callTarget.invokeKind() == InvokeKind.Interface;
    callTarget.setInvokeKind(InvokeKind.Special);
    callTarget.setTargetMethod(singleCallee);
}
Also used : Stamp(org.graalvm.compiler.core.common.type.Stamp) ValueAnchorNode(org.graalvm.compiler.nodes.extended.ValueAnchorNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) PiNode(org.graalvm.compiler.nodes.PiNode)

Example 4 with ValueAnchorNode

use of org.graalvm.compiler.nodes.extended.ValueAnchorNode in project graal by oracle.

the class LoopEx method detectCounted.

public boolean detectCounted() {
    LoopBeginNode loopBegin = loopBegin();
    FixedNode next = loopBegin.next();
    while (next instanceof FixedGuardNode || next instanceof ValueAnchorNode || next instanceof FullInfopointNode) {
        next = ((FixedWithNextNode) next).next();
    }
    if (next instanceof IfNode) {
        IfNode ifNode = (IfNode) next;
        boolean negated = false;
        if (!loopBegin.isLoopExit(ifNode.falseSuccessor())) {
            if (!loopBegin.isLoopExit(ifNode.trueSuccessor())) {
                return false;
            }
            negated = true;
        }
        LogicNode ifTest = ifNode.condition();
        if (!(ifTest instanceof IntegerLessThanNode) && !(ifTest instanceof IntegerEqualsNode)) {
            if (ifTest instanceof IntegerBelowNode) {
                ifTest.getDebug().log("Ignored potential Counted loop at %s with |<|", loopBegin);
            }
            return false;
        }
        CompareNode lessThan = (CompareNode) ifTest;
        Condition condition = null;
        InductionVariable iv = null;
        ValueNode limit = null;
        if (isOutsideLoop(lessThan.getX())) {
            iv = getInductionVariables().get(lessThan.getY());
            if (iv != null) {
                condition = lessThan.condition().asCondition().mirror();
                limit = lessThan.getX();
            }
        } else if (isOutsideLoop(lessThan.getY())) {
            iv = getInductionVariables().get(lessThan.getX());
            if (iv != null) {
                condition = lessThan.condition().asCondition();
                limit = lessThan.getY();
            }
        }
        if (condition == null) {
            return false;
        }
        if (negated) {
            condition = condition.negate();
        }
        boolean oneOff = false;
        switch(condition) {
            case EQ:
                return false;
            case NE:
                {
                    if (!iv.isConstantStride() || Math.abs(iv.constantStride()) != 1) {
                        return false;
                    }
                    IntegerStamp initStamp = (IntegerStamp) iv.initNode().stamp(NodeView.DEFAULT);
                    IntegerStamp limitStamp = (IntegerStamp) limit.stamp(NodeView.DEFAULT);
                    if (iv.direction() == Direction.Up) {
                        if (initStamp.upperBound() > limitStamp.lowerBound()) {
                            return false;
                        }
                    } else if (iv.direction() == Direction.Down) {
                        if (initStamp.lowerBound() < limitStamp.upperBound()) {
                            return false;
                        }
                    } else {
                        return false;
                    }
                    break;
                }
            case LE:
                oneOff = true;
                if (iv.direction() != Direction.Up) {
                    return false;
                }
                break;
            case LT:
                if (iv.direction() != Direction.Up) {
                    return false;
                }
                break;
            case GE:
                oneOff = true;
                if (iv.direction() != Direction.Down) {
                    return false;
                }
                break;
            case GT:
                if (iv.direction() != Direction.Down) {
                    return false;
                }
                break;
            default:
                throw GraalError.shouldNotReachHere();
        }
        counted = new CountedLoopInfo(this, iv, ifNode, limit, oneOff, negated ? ifNode.falseSuccessor() : ifNode.trueSuccessor());
        return true;
    }
    return false;
}
Also used : Condition(org.graalvm.compiler.core.common.calc.Condition) IntegerEqualsNode(org.graalvm.compiler.nodes.calc.IntegerEqualsNode) IntegerBelowNode(org.graalvm.compiler.nodes.calc.IntegerBelowNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) IfNode(org.graalvm.compiler.nodes.IfNode) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) FullInfopointNode(org.graalvm.compiler.nodes.FullInfopointNode) CompareNode(org.graalvm.compiler.nodes.calc.CompareNode) IntegerStamp(org.graalvm.compiler.core.common.type.IntegerStamp) ValueAnchorNode(org.graalvm.compiler.nodes.extended.ValueAnchorNode) IntegerLessThanNode(org.graalvm.compiler.nodes.calc.IntegerLessThanNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) LogicNode(org.graalvm.compiler.nodes.LogicNode)

Example 5 with ValueAnchorNode

use of org.graalvm.compiler.nodes.extended.ValueAnchorNode in project graal by oracle.

the class MethodCallTargetNode method tryCheckCastSingleImplementor.

private boolean tryCheckCastSingleImplementor(ValueNode receiver, TypeReference speculatedType) {
    ResolvedJavaType singleImplementor = speculatedType.getType();
    if (singleImplementor != null) {
        ResolvedJavaMethod singleImplementorMethod = singleImplementor.resolveConcreteMethod(targetMethod(), invoke().getContextType());
        if (singleImplementorMethod != null) {
            /**
             * We have an invoke on an interface with a single implementor. We can replace this
             * with an invoke virtual.
             *
             * To do so we need to ensure two properties: 1) the receiver must implement the
             * interface (declaredReceiverType). The verifier does not prove this so we need a
             * dynamic check. 2) we need to ensure that there is still only one implementor of
             * this interface, i.e. that we are calling the right method. We could do this with
             * an assumption but as we need an instanceof check anyway we can verify both
             * properties by checking of the receiver is an instance of the single implementor.
             */
            ValueAnchorNode anchor = new ValueAnchorNode(null);
            if (anchor != null) {
                graph().add(anchor);
                graph().addBeforeFixed(invoke().asNode(), anchor);
            }
            LogicNode condition = graph().addOrUniqueWithInputs(InstanceOfNode.create(speculatedType, receiver, getProfile(), anchor));
            FixedGuardNode guard = graph().add(new FixedGuardNode(condition, DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile, false));
            graph().addBeforeFixed(invoke().asNode(), guard);
            ValueNode valueNode = graph().addOrUnique(new PiNode(receiver, StampFactory.objectNonNull(speculatedType), guard));
            arguments().set(0, valueNode);
            if (speculatedType.isExact()) {
                setInvokeKind(InvokeKind.Special);
            } else {
                setInvokeKind(InvokeKind.Virtual);
            }
            setTargetMethod(singleImplementorMethod);
            return true;
        }
    }
    return false;
}
Also used : FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) ValueAnchorNode(org.graalvm.compiler.nodes.extended.ValueAnchorNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) PiNode(org.graalvm.compiler.nodes.PiNode) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) ResolvedJavaMethod(jdk.vm.ci.meta.ResolvedJavaMethod)

Aggregations

ValueAnchorNode (org.graalvm.compiler.nodes.extended.ValueAnchorNode)5 ValueNode (org.graalvm.compiler.nodes.ValueNode)4 FixedGuardNode (org.graalvm.compiler.nodes.FixedGuardNode)3 LogicNode (org.graalvm.compiler.nodes.LogicNode)3 ResolvedJavaType (jdk.vm.ci.meta.ResolvedJavaType)2 PiNode (org.graalvm.compiler.nodes.PiNode)2 Assumptions (jdk.vm.ci.meta.Assumptions)1 DeoptimizationAction (jdk.vm.ci.meta.DeoptimizationAction)1 DeoptimizationReason (jdk.vm.ci.meta.DeoptimizationReason)1 JavaConstant (jdk.vm.ci.meta.JavaConstant)1 ResolvedJavaMethod (jdk.vm.ci.meta.ResolvedJavaMethod)1 Condition (org.graalvm.compiler.core.common.calc.Condition)1 IntegerStamp (org.graalvm.compiler.core.common.type.IntegerStamp)1 Stamp (org.graalvm.compiler.core.common.type.Stamp)1 TypeReference (org.graalvm.compiler.core.common.type.TypeReference)1 FixedNode (org.graalvm.compiler.nodes.FixedNode)1 FullInfopointNode (org.graalvm.compiler.nodes.FullInfopointNode)1 GuardNode (org.graalvm.compiler.nodes.GuardNode)1 IfNode (org.graalvm.compiler.nodes.IfNode)1 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)1