Search in sources :

Example 1 with DynamicDeoptimizeNode

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

the class DeoptimizationGroupingPhase method run.

@Override
protected void run(StructuredGraph graph, MidTierContext context) {
    ControlFlowGraph cfg = null;
    for (FrameState fs : graph.getNodes(FrameState.TYPE)) {
        FixedNode target = null;
        PhiNode reasonActionPhi = null;
        PhiNode speculationPhi = null;
        List<AbstractDeoptimizeNode> obsoletes = null;
        for (AbstractDeoptimizeNode deopt : fs.usages().filter(AbstractDeoptimizeNode.class)) {
            if (target == null) {
                target = deopt;
            } else {
                if (cfg == null) {
                    cfg = ControlFlowGraph.compute(graph, true, true, false, false);
                }
                AbstractMergeNode merge;
                if (target instanceof AbstractDeoptimizeNode) {
                    merge = graph.add(new MergeNode());
                    EndNode firstEnd = graph.add(new EndNode());
                    ValueNode actionAndReason = ((AbstractDeoptimizeNode) target).getActionAndReason(context.getMetaAccess());
                    ValueNode speculation = ((AbstractDeoptimizeNode) target).getSpeculation(context.getMetaAccess());
                    reasonActionPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(actionAndReason.getStackKind()), merge));
                    speculationPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(speculation.getStackKind()), merge));
                    merge.addForwardEnd(firstEnd);
                    reasonActionPhi.addInput(actionAndReason);
                    speculationPhi.addInput(speculation);
                    target.replaceAtPredecessor(firstEnd);
                    exitLoops((AbstractDeoptimizeNode) target, firstEnd, cfg);
                    merge.setNext(graph.add(new DynamicDeoptimizeNode(reasonActionPhi, speculationPhi)));
                    obsoletes = new LinkedList<>();
                    obsoletes.add((AbstractDeoptimizeNode) target);
                    target = merge;
                } else {
                    merge = (AbstractMergeNode) target;
                }
                EndNode newEnd = graph.add(new EndNode());
                merge.addForwardEnd(newEnd);
                reasonActionPhi.addInput(deopt.getActionAndReason(context.getMetaAccess()));
                speculationPhi.addInput(deopt.getSpeculation(context.getMetaAccess()));
                deopt.replaceAtPredecessor(newEnd);
                exitLoops(deopt, newEnd, cfg);
                obsoletes.add(deopt);
            }
        }
        if (obsoletes != null) {
            ((DynamicDeoptimizeNode) ((AbstractMergeNode) target).next()).setStateBefore(fs);
            for (AbstractDeoptimizeNode obsolete : obsoletes) {
                obsolete.safeDelete();
            }
        }
    }
}
Also used : ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) DynamicDeoptimizeNode(org.graalvm.compiler.nodes.DynamicDeoptimizeNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) FrameState(org.graalvm.compiler.nodes.FrameState) AbstractDeoptimizeNode(org.graalvm.compiler.nodes.AbstractDeoptimizeNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) EndNode(org.graalvm.compiler.nodes.EndNode) ControlFlowGraph(org.graalvm.compiler.nodes.cfg.ControlFlowGraph) ValueNode(org.graalvm.compiler.nodes.ValueNode)

Example 2 with DynamicDeoptimizeNode

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

the class UseTrappingNullChecksPhase method tryUseTrappingNullCheck.

private static void tryUseTrappingNullCheck(MetaAccessProvider metaAccessProvider, DynamicDeoptimizeNode deopt, long implicitNullCheckLimit) {
    Node predecessor = deopt.predecessor();
    if (predecessor instanceof AbstractMergeNode) {
        AbstractMergeNode merge = (AbstractMergeNode) predecessor;
        // Process each predecessor at the merge, unpacking the reasons and speculations as
        // needed.
        ValueNode reason = deopt.getActionAndReason();
        ValuePhiNode reasonPhi = null;
        List<ValueNode> reasons = null;
        int expectedPhis = 0;
        if (reason instanceof ValuePhiNode) {
            reasonPhi = (ValuePhiNode) reason;
            if (reasonPhi.merge() != merge) {
                return;
            }
            reasons = reasonPhi.values().snapshot();
            expectedPhis++;
        } else if (!reason.isConstant()) {
            return;
        }
        ValueNode speculation = deopt.getSpeculation();
        ValuePhiNode speculationPhi = null;
        List<ValueNode> speculations = null;
        if (speculation instanceof ValuePhiNode) {
            speculationPhi = (ValuePhiNode) speculation;
            if (speculationPhi.merge() != merge) {
                return;
            }
            speculations = speculationPhi.values().snapshot();
            expectedPhis++;
        }
        if (merge.phis().count() != expectedPhis) {
            return;
        }
        int index = 0;
        for (AbstractEndNode end : merge.cfgPredecessors().snapshot()) {
            ValueNode thisReason = reasons != null ? reasons.get(index) : reason;
            ValueNode thisSpeculation = speculations != null ? speculations.get(index++) : speculation;
            if (!thisReason.isConstant() || !thisSpeculation.isConstant() || !thisSpeculation.asConstant().equals(JavaConstant.NULL_POINTER)) {
                continue;
            }
            DeoptimizationReason deoptimizationReason = metaAccessProvider.decodeDeoptReason(thisReason.asJavaConstant());
            tryUseTrappingNullCheck(deopt, end.predecessor(), deoptimizationReason, null, implicitNullCheckLimit);
        }
    }
}
Also used : ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) DynamicDeoptimizeNode(org.graalvm.compiler.nodes.DynamicDeoptimizeNode) FixedAccessNode(org.graalvm.compiler.nodes.memory.FixedAccessNode) DeoptimizingFixedWithNextNode(org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode) BeginNode(org.graalvm.compiler.nodes.BeginNode) DeoptimizeNode(org.graalvm.compiler.nodes.DeoptimizeNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) IfNode(org.graalvm.compiler.nodes.IfNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) CompressionNode(org.graalvm.compiler.nodes.CompressionNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) AbstractDeoptimizeNode(org.graalvm.compiler.nodes.AbstractDeoptimizeNode) AddressNode(org.graalvm.compiler.nodes.memory.address.AddressNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) IsNullNode(org.graalvm.compiler.nodes.calc.IsNullNode) NullCheckNode(org.graalvm.compiler.nodes.extended.NullCheckNode) Node(org.graalvm.compiler.graph.Node) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) DeoptimizationReason(jdk.vm.ci.meta.DeoptimizationReason)

Example 3 with DynamicDeoptimizeNode

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

the class UseTrappingNullChecksPhase method replaceWithTrappingNullCheck.

private static void replaceWithTrappingNullCheck(AbstractDeoptimizeNode deopt, IfNode ifNode, LogicNode condition, DeoptimizationReason deoptimizationReason, long implicitNullCheckLimit) {
    DebugContext debug = deopt.getDebug();
    counterTrappingNullCheck.increment(debug);
    if (deopt instanceof DynamicDeoptimizeNode) {
        counterTrappingNullCheckDynamicDeoptimize.increment(debug);
    }
    if (deoptimizationReason == DeoptimizationReason.UnreachedCode) {
        counterTrappingNullCheckUnreached.increment(debug);
    }
    IsNullNode isNullNode = (IsNullNode) condition;
    AbstractBeginNode nonTrappingContinuation = ifNode.falseSuccessor();
    AbstractBeginNode trappingContinuation = ifNode.trueSuccessor();
    DeoptimizingFixedWithNextNode trappingNullCheck = null;
    FixedNode nextNonTrapping = nonTrappingContinuation.next();
    ValueNode value = isNullNode.getValue();
    if (OptImplicitNullChecks.getValue(ifNode.graph().getOptions()) && implicitNullCheckLimit > 0) {
        if (nextNonTrapping instanceof FixedAccessNode) {
            FixedAccessNode fixedAccessNode = (FixedAccessNode) nextNonTrapping;
            if (fixedAccessNode.canNullCheck()) {
                AddressNode address = fixedAccessNode.getAddress();
                ValueNode base = address.getBase();
                ValueNode index = address.getIndex();
                // intervening uncompress out of the address chain
                if (base != null && base instanceof CompressionNode) {
                    base = ((CompressionNode) base).getValue();
                }
                if (index != null && index instanceof CompressionNode) {
                    index = ((CompressionNode) index).getValue();
                }
                if (((base == value && index == null) || (base == null && index == value)) && address.getMaxConstantDisplacement() < implicitNullCheckLimit) {
                    // Opportunity for implicit null check as part of an existing read found!
                    fixedAccessNode.setStateBefore(deopt.stateBefore());
                    fixedAccessNode.setNullCheck(true);
                    deopt.graph().removeSplit(ifNode, nonTrappingContinuation);
                    trappingNullCheck = fixedAccessNode;
                    counterTrappingNullCheckExistingRead.increment(debug);
                }
            }
        }
    }
    if (trappingNullCheck == null) {
        // Need to add a null check node.
        trappingNullCheck = deopt.graph().add(new NullCheckNode(value));
        deopt.graph().replaceSplit(ifNode, trappingNullCheck, nonTrappingContinuation);
    }
    trappingNullCheck.setStateBefore(deopt.stateBefore());
    /*
         * We now have the pattern NullCheck/BeginNode/... It's possible some node is using the
         * BeginNode as a guard input, so replace guard users of the Begin with the NullCheck and
         * then remove the Begin from the graph.
         */
    nonTrappingContinuation.replaceAtUsages(InputType.Guard, trappingNullCheck);
    if (nonTrappingContinuation instanceof BeginNode) {
        GraphUtil.unlinkFixedNode(nonTrappingContinuation);
        nonTrappingContinuation.safeDelete();
    }
    GraphUtil.killCFG(trappingContinuation);
    GraphUtil.tryKillUnused(isNullNode);
}
Also used : FixedAccessNode(org.graalvm.compiler.nodes.memory.FixedAccessNode) DeoptimizingFixedWithNextNode(org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode) CompressionNode(org.graalvm.compiler.nodes.CompressionNode) IsNullNode(org.graalvm.compiler.nodes.calc.IsNullNode) NullCheckNode(org.graalvm.compiler.nodes.extended.NullCheckNode) BeginNode(org.graalvm.compiler.nodes.BeginNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) DynamicDeoptimizeNode(org.graalvm.compiler.nodes.DynamicDeoptimizeNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) AddressNode(org.graalvm.compiler.nodes.memory.address.AddressNode) DebugContext(org.graalvm.compiler.debug.DebugContext) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Aggregations

DynamicDeoptimizeNode (org.graalvm.compiler.nodes.DynamicDeoptimizeNode)3 FixedNode (org.graalvm.compiler.nodes.FixedNode)3 ValueNode (org.graalvm.compiler.nodes.ValueNode)3 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)2 AbstractDeoptimizeNode (org.graalvm.compiler.nodes.AbstractDeoptimizeNode)2 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)2 BeginNode (org.graalvm.compiler.nodes.BeginNode)2 CompressionNode (org.graalvm.compiler.nodes.CompressionNode)2 DeoptimizingFixedWithNextNode (org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode)2 ValuePhiNode (org.graalvm.compiler.nodes.ValuePhiNode)2 IsNullNode (org.graalvm.compiler.nodes.calc.IsNullNode)2 NullCheckNode (org.graalvm.compiler.nodes.extended.NullCheckNode)2 FixedAccessNode (org.graalvm.compiler.nodes.memory.FixedAccessNode)2 AddressNode (org.graalvm.compiler.nodes.memory.address.AddressNode)2 DeoptimizationReason (jdk.vm.ci.meta.DeoptimizationReason)1 DebugContext (org.graalvm.compiler.debug.DebugContext)1 Node (org.graalvm.compiler.graph.Node)1 AbstractEndNode (org.graalvm.compiler.nodes.AbstractEndNode)1 DeoptimizeNode (org.graalvm.compiler.nodes.DeoptimizeNode)1 EndNode (org.graalvm.compiler.nodes.EndNode)1