Search in sources :

Example 16 with FixedGuardNode

use of org.graalvm.compiler.nodes.FixedGuardNode 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 17 with FixedGuardNode

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

the class StandardGraphBuilderPlugins method registerMethodHandleImplPlugins.

private static void registerMethodHandleImplPlugins(InvocationPlugins plugins, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) {
    Registration r = new Registration(plugins, "java.lang.invoke.MethodHandleImpl", bytecodeProvider);
    r.register2("profileBoolean", boolean.class, int[].class, new InvocationPlugin() {

        @Override
        public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode result, ValueNode counters) {
            if (result.isConstant()) {
                b.push(JavaKind.Boolean, result);
                return true;
            }
            if (counters.isConstant()) {
                ValueNode newResult = result;
                int[] ctrs = snippetReflection.asObject(int[].class, (JavaConstant) counters.asConstant());
                if (ctrs != null && ctrs.length == 2) {
                    int falseCount = ctrs[0];
                    int trueCount = ctrs[1];
                    int totalCount = trueCount + falseCount;
                    if (totalCount == 0) {
                        b.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter));
                    } else if (falseCount == 0 || trueCount == 0) {
                        boolean expected = falseCount == 0;
                        LogicNode condition = b.addWithInputs(IntegerEqualsNode.create(b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), null, result, b.add(ConstantNode.forBoolean(!expected)), NodeView.DEFAULT));
                        b.append(new FixedGuardNode(condition, DeoptimizationReason.UnreachedCode, DeoptimizationAction.InvalidateReprofile, true));
                        newResult = b.add(ConstantNode.forBoolean(expected));
                    } else {
                    // We cannot use BranchProbabilityNode here since there's no guarantee
                    // the result of MethodHandleImpl.profileBoolean() is used as the
                    // test in an `if` statement (as required by BranchProbabilityNode).
                    }
                }
                b.addPush(JavaKind.Boolean, newResult);
                return true;
            }
            return false;
        }
    });
}
Also used : FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) GraphBuilderContext(org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext) Registration(org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration) ValueNode(org.graalvm.compiler.nodes.ValueNode) InvocationPlugin(org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin) Receiver(org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver) JavaConstant(jdk.vm.ci.meta.JavaConstant) DeoptimizeNode(org.graalvm.compiler.nodes.DeoptimizeNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) ResolvedJavaMethod(jdk.vm.ci.meta.ResolvedJavaMethod)

Example 18 with FixedGuardNode

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

the class VirtualFrameGetNode method virtualize.

@Override
public void virtualize(VirtualizerTool tool) {
    ValueNode tagAlias = tool.getAlias(frame.virtualFrameTagArray);
    ValueNode dataAlias = tool.getAlias(TruffleCompilerRuntime.getRuntime().getJavaKindForFrameSlotKind(accessTag) == JavaKind.Object ? frame.virtualFrameObjectArray : frame.virtualFramePrimitiveArray);
    if (tagAlias instanceof VirtualObjectNode && dataAlias instanceof VirtualObjectNode) {
        VirtualObjectNode tagVirtual = (VirtualObjectNode) tagAlias;
        VirtualObjectNode dataVirtual = (VirtualObjectNode) dataAlias;
        if (frameSlotIndex < tagVirtual.entryCount() && frameSlotIndex < dataVirtual.entryCount()) {
            ValueNode actualTag = tool.getEntry(tagVirtual, frameSlotIndex);
            if (!actualTag.isConstant() || actualTag.asJavaConstant().asInt() != accessTag) {
                /*
                     * We cannot constant fold the tag-check immediately, so we need to create a
                     * guard comparing the actualTag with the accessTag.
                     */
                LogicNode comparison = new IntegerEqualsNode(actualTag, getConstant(accessTag));
                tool.addNode(comparison);
                tool.addNode(new FixedGuardNode(comparison, DeoptimizationReason.RuntimeConstraint, DeoptimizationAction.InvalidateRecompile));
            }
            ValueNode dataEntry = tool.getEntry(dataVirtual, frameSlotIndex);
            if (dataEntry.getStackKind() == getStackKind()) {
                tool.replaceWith(dataEntry);
                return;
            }
        }
    }
    /*
         * We could "virtualize" to a UnsafeLoadNode here that remains a memory access. However,
         * that could prevent further escape analysis for parts of the method that actually matter.
         * So we just deoptimize.
         */
    insertDeoptimization(tool);
}
Also used : VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) IntegerEqualsNode(org.graalvm.compiler.nodes.calc.IntegerEqualsNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) LogicNode(org.graalvm.compiler.nodes.LogicNode)

Example 19 with FixedGuardNode

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

the class BytecodeParser method genIf.

protected void genIf(LogicNode conditionInput, BciBlock trueBlockInput, BciBlock falseBlockInput, double probabilityInput) {
    BciBlock trueBlock = trueBlockInput;
    BciBlock falseBlock = falseBlockInput;
    LogicNode condition = conditionInput;
    double probability = probabilityInput;
    FrameState stateBefore = null;
    ProfilingPlugin profilingPlugin = this.graphBuilderConfig.getPlugins().getProfilingPlugin();
    if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
        stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
    }
    // Remove a logic negation node.
    if (condition instanceof LogicNegationNode) {
        LogicNegationNode logicNegationNode = (LogicNegationNode) condition;
        BciBlock tmpBlock = trueBlock;
        trueBlock = falseBlock;
        falseBlock = tmpBlock;
        probability = 1 - probability;
        condition = logicNegationNode.getValue();
    }
    if (condition instanceof LogicConstantNode) {
        genConstantTargetIf(trueBlock, falseBlock, condition);
    } else {
        if (condition.graph() == null) {
            condition = genUnique(condition);
        }
        if (isNeverExecutedCode(probability)) {
            append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, true));
            if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
                profilingPlugin.profileGoto(this, method, bci(), falseBlock.startBci, stateBefore);
            }
            appendGoto(falseBlock);
            return;
        } else if (isNeverExecutedCode(1 - probability)) {
            append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, false));
            if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
                profilingPlugin.profileGoto(this, method, bci(), trueBlock.startBci, stateBefore);
            }
            appendGoto(trueBlock);
            return;
        }
        if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
            profilingPlugin.profileIf(this, method, bci(), condition, trueBlock.startBci, falseBlock.startBci, stateBefore);
        }
        int oldBci = stream.currentBCI();
        int trueBlockInt = checkPositiveIntConstantPushed(trueBlock);
        if (trueBlockInt != -1) {
            int falseBlockInt = checkPositiveIntConstantPushed(falseBlock);
            if (falseBlockInt != -1) {
                if (tryGenConditionalForIf(trueBlock, falseBlock, condition, oldBci, trueBlockInt, falseBlockInt)) {
                    return;
                }
            }
        }
        this.controlFlowSplit = true;
        FixedNode trueSuccessor = createTarget(trueBlock, frameState, false, false);
        FixedNode falseSuccessor = createTarget(falseBlock, frameState, false, true);
        ValueNode ifNode = genIfNode(condition, trueSuccessor, falseSuccessor, probability);
        postProcessIfNode(ifNode);
        append(ifNode);
    }
}
Also used : FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) LogicNegationNode(org.graalvm.compiler.nodes.LogicNegationNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) LogicConstantNode(org.graalvm.compiler.nodes.LogicConstantNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) FrameState(org.graalvm.compiler.nodes.FrameState) BciBlock(org.graalvm.compiler.java.BciBlockMapping.BciBlock) RuntimeConstraint(jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint) ProfilingPlugin(org.graalvm.compiler.nodes.graphbuilderconf.ProfilingPlugin)

Example 20 with FixedGuardNode

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

the class BytecodeParser method guardIntrinsic.

/**
 * Weaves a test of the receiver type to ensure the dispatch will select {@code targetMethod}
 * and not another method that overrides it. This should only be called if there is an intrinsic
 * (i.e., an {@link InvocationPlugin}) for {@code targetMethod} and the invocation is indirect.
 *
 * The control flow woven around the intrinsic is as follows:
 *
 * <pre>
 *  if (LoadMethod(LoadHub(receiver)) == targetMethod) {
 *       <intrinsic for targetMethod>
 *  } else {
 *       <virtual call to targetMethod>
 *  }
 * </pre>
 *
 * The {@code else} branch is woven by {@link #afterInvocationPluginExecution}.
 *
 * @return {@code null} if the intrinsic cannot be used otherwise an object to be used by
 *         {@link #afterInvocationPluginExecution} to weave code for the non-intrinsic branch
 */
protected IntrinsicGuard guardIntrinsic(ValueNode[] args, ResolvedJavaMethod targetMethod, InvocationPluginReceiver pluginReceiver) {
    ValueNode intrinsicReceiver = args[0];
    ResolvedJavaType receiverType = StampTool.typeOrNull(intrinsicReceiver);
    if (receiverType == null) {
        // The verifier guarantees it to be at least type declaring targetMethod
        receiverType = targetMethod.getDeclaringClass();
    }
    ResolvedJavaMethod resolvedMethod = receiverType.resolveMethod(targetMethod, method.getDeclaringClass());
    if (resolvedMethod == null || resolvedMethod.equals(targetMethod)) {
        assert resolvedMethod == null || targetMethod.getDeclaringClass().isAssignableFrom(resolvedMethod.getDeclaringClass());
        Mark mark = graph.getMark();
        FixedWithNextNode currentLastInstr = lastInstr;
        ValueNode nonNullReceiver = pluginReceiver.get();
        Stamp methodStamp = stampProvider.createMethodStamp();
        LoadHubNode hub = graph.unique(new LoadHubNode(stampProvider, nonNullReceiver));
        LoadMethodNode actual = append(new LoadMethodNode(methodStamp, targetMethod, receiverType, method.getDeclaringClass(), hub));
        ConstantNode expected = graph.unique(ConstantNode.forConstant(methodStamp, targetMethod.getEncoding(), getMetaAccess()));
        LogicNode compare = graph.addOrUniqueWithInputs(CompareNode.createCompareNode(constantReflection, metaAccess, options, null, CanonicalCondition.EQ, actual, expected, NodeView.DEFAULT));
        JavaTypeProfile profile = null;
        if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) {
            profile = profilingInfo.getTypeProfile(bci());
            if (profile != null) {
                JavaTypeProfile newProfile = adjustProfileForInvocationPlugin(profile, targetMethod);
                if (newProfile != profile) {
                    if (newProfile.getTypes().length == 0) {
                        // All profiled types select the intrinsic so
                        // emit a fixed guard instead of an if-then-else.
                        lastInstr = append(new FixedGuardNode(compare, TypeCheckedInliningViolated, InvalidateReprofile, false));
                        return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, null, null);
                    }
                } else {
                    // No profiled types select the intrinsic so emit a virtual call
                    return null;
                }
                profile = newProfile;
            }
        }
        AbstractBeginNode intrinsicBranch = graph.add(new BeginNode());
        AbstractBeginNode nonIntrinsicBranch = graph.add(new BeginNode());
        append(new IfNode(compare, intrinsicBranch, nonIntrinsicBranch, FAST_PATH_PROBABILITY));
        lastInstr = intrinsicBranch;
        return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, nonIntrinsicBranch, profile);
    } else {
        // Receiver selects an overriding method so emit a virtual call
        return null;
    }
}
Also used : FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) LoadHubNode(org.graalvm.compiler.nodes.extended.LoadHubNode) ObjectStamp(org.graalvm.compiler.core.common.type.ObjectStamp) Stamp(org.graalvm.compiler.core.common.type.Stamp) IntegerStamp(org.graalvm.compiler.core.common.type.IntegerStamp) Mark(org.graalvm.compiler.graph.Graph.Mark) IfNode(org.graalvm.compiler.nodes.IfNode) LoadMethodNode(org.graalvm.compiler.nodes.extended.LoadMethodNode) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) LogicConstantNode(org.graalvm.compiler.nodes.LogicConstantNode) BeginNode(org.graalvm.compiler.nodes.BeginNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) KillingBeginNode(org.graalvm.compiler.nodes.KillingBeginNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) JavaTypeProfile(jdk.vm.ci.meta.JavaTypeProfile) ValueNode(org.graalvm.compiler.nodes.ValueNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) ResolvedJavaMethod(jdk.vm.ci.meta.ResolvedJavaMethod)

Aggregations

FixedGuardNode (org.graalvm.compiler.nodes.FixedGuardNode)31 LogicNode (org.graalvm.compiler.nodes.LogicNode)25 ValueNode (org.graalvm.compiler.nodes.ValueNode)24 ResolvedJavaType (jdk.vm.ci.meta.ResolvedJavaType)10 ObjectStamp (org.graalvm.compiler.core.common.type.ObjectStamp)8 TypeReference (org.graalvm.compiler.core.common.type.TypeReference)8 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)8 ResolvedJavaMethod (jdk.vm.ci.meta.ResolvedJavaMethod)7 Stamp (org.graalvm.compiler.core.common.type.Stamp)7 JavaConstant (jdk.vm.ci.meta.JavaConstant)6 DebugCloseable (org.graalvm.compiler.debug.DebugCloseable)5 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)5 RuntimeConstraint (jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint)4 IntegerStamp (org.graalvm.compiler.core.common.type.IntegerStamp)4 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)4 FixedNode (org.graalvm.compiler.nodes.FixedNode)4 IfNode (org.graalvm.compiler.nodes.IfNode)4 LogicConstantNode (org.graalvm.compiler.nodes.LogicConstantNode)4 PiNode (org.graalvm.compiler.nodes.PiNode)4 InvocationPlugin (org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin)4