Search in sources :

Example 6 with ProfileSource

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

the class BytecodeParser method genSwitch.

private void genSwitch(BytecodeSwitch bs) {
    int bci = bci();
    ValueNode value = frameState.pop(JavaKind.Int);
    int nofCases = bs.numberOfCases();
    int nofCasesPlusDefault = nofCases + 1;
    double[] keyProbabilities = switchProbability(nofCasesPlusDefault, bci);
    EconomicMap<Integer, SuccessorInfo> bciToBlockSuccessorIndex = EconomicMap.create(Equivalence.DEFAULT);
    for (int i = 0; i < currentBlock.getSuccessorCount(); i++) {
        assert !bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci);
        bciToBlockSuccessorIndex.put(currentBlock.getSuccessor(i).startBci, new SuccessorInfo(i));
    }
    ArrayList<BciBlock> actualSuccessors = new ArrayList<>();
    int[] keys = new int[nofCases];
    int[] keySuccessors = new int[nofCasesPlusDefault];
    int deoptSuccessorIndex = SWITCH_DEOPT_UNSEEN;
    int nextSuccessorIndex = 0;
    boolean constantValue = value.isConstant();
    for (int i = 0; i < nofCasesPlusDefault; i++) {
        if (i < nofCases) {
            keys[i] = bs.keyAt(i);
        }
        if (!constantValue && isNeverExecutedCode(keyProbabilities[i])) {
            deoptSuccessorIndex = SWITCH_DEOPT_SEEN;
            keySuccessors[i] = SWITCH_DEOPT_SEEN;
        } else {
            int targetBci = i < nofCases ? bs.targetAt(i) : bs.defaultTarget();
            SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci);
            if (info.actualIndex < 0) {
                info.actualIndex = nextSuccessorIndex++;
                actualSuccessors.add(currentBlock.getSuccessor(info.blockIndex));
            }
            keySuccessors[i] = info.actualIndex;
        }
    }
    /*
         * When the profile indicates a case is never taken, the above code will cause the case to
         * deopt should it be subsequently encountered. However, the case may share code with
         * another case that is taken according to the profile.
         *
         * For example:
         * // @formatter:off
         * switch (opcode) {
         *     case GOTO:
         *     case GOTO_W: {
         *         // emit goto code
         *         break;
         *     }
         * }
         * // @formatter:on
         *
         * The profile may indicate the GOTO_W case is never taken, and thus a deoptimization stub
         * will be emitted. There might be optimization opportunity if additional branching based
         * on opcode is within the case block. Specially, if there is only single case that
         * reaches a target, we have better chance cutting out unused branches. Otherwise,
         * it might be beneficial routing to the same code instead of deopting.
         *
         * The following code rewires deoptimization stub to existing resolved branch target if
         * the target is connected by more than 1 cases.
         *
         * If this operation rewires every deoptimization seen to an existing branch, care is
         * taken that we do not spawn a branch that will never be taken.
         */
    if (deoptSuccessorIndex == SWITCH_DEOPT_SEEN) {
        int[] connectedCases = new int[nextSuccessorIndex + 1];
        for (int i = 0; i < nofCasesPlusDefault; i++) {
            connectedCases[keySuccessors[i] + 1]++;
        }
        for (int i = 0; i < nofCasesPlusDefault; i++) {
            if (keySuccessors[i] == SWITCH_DEOPT_SEEN) {
                int targetBci = i < nofCases ? bs.targetAt(i) : bs.defaultTarget();
                SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci);
                int rewiredIndex = info.actualIndex;
                if (rewiredIndex >= 0 && connectedCases[rewiredIndex + 1] > 1) {
                    // Rewire
                    keySuccessors[i] = info.actualIndex;
                } else {
                    if (deoptSuccessorIndex == SWITCH_DEOPT_SEEN) {
                        // Spawn deopt successor if needed.
                        deoptSuccessorIndex = nextSuccessorIndex++;
                        actualSuccessors.add(null);
                    }
                    keySuccessors[i] = deoptSuccessorIndex;
                }
            }
        }
    }
    ProfileSource profileSource = getSwitchProfileSource(bci);
    genIntegerSwitch(value, actualSuccessors, keys, keyProbabilities, keySuccessors, profileSource);
}
Also used : ProfileSource(org.graalvm.compiler.nodes.ProfileData.ProfileSource) ValueNode(org.graalvm.compiler.nodes.ValueNode) ArrayList(java.util.ArrayList) BciBlock(org.graalvm.compiler.java.BciBlockMapping.BciBlock) RuntimeConstraint(jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint)

Aggregations

ProfileSource (org.graalvm.compiler.nodes.ProfileData.ProfileSource)6 ValueNode (org.graalvm.compiler.nodes.ValueNode)2 ArrayList (java.util.ArrayList)1 RuntimeConstraint (jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint)1 IntegerStamp (org.graalvm.compiler.core.common.type.IntegerStamp)1 PrimitiveStamp (org.graalvm.compiler.core.common.type.PrimitiveStamp)1 Stamp (org.graalvm.compiler.core.common.type.Stamp)1 NodeSourcePosition (org.graalvm.compiler.graph.NodeSourcePosition)1 BciBlock (org.graalvm.compiler.java.BciBlockMapping.BciBlock)1 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)1 ControlSplitNode (org.graalvm.compiler.nodes.ControlSplitNode)1 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)1 LoopEndNode (org.graalvm.compiler.nodes.LoopEndNode)1 LoopExitNode (org.graalvm.compiler.nodes.LoopExitNode)1 BranchProbabilityData (org.graalvm.compiler.nodes.ProfileData.BranchProbabilityData)1 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)1 SignExtendNode (org.graalvm.compiler.nodes.calc.SignExtendNode)1 IntegerSwitchNode (org.graalvm.compiler.nodes.extended.IntegerSwitchNode)1