Search in sources :

Example 1 with LLVMInvokeNode

use of com.oracle.truffle.llvm.runtime.nodes.func.LLVMInvokeNode in project graal by oracle.

the class LLVMDispatchBasicBlockNode method dispatchFromBasicBlock.

/**
 * The code in this function is mirrored in {@link LLVMLoopDispatchNode}, any changes need to be
 * done in both places.
 */
@ExplodeLoop(kind = LoopExplosionKind.MERGE_EXPLODE)
private Object dispatchFromBasicBlock(VirtualFrame frame, int bci, Counter counter) {
    assert counter != null;
    Object returnValue = null;
    int basicBlockIndex = bci;
    CompilerAsserts.partialEvaluationConstant(bodyNodes.length);
    try {
        outer: while (basicBlockIndex != LLVMBasicBlockNode.RETURN_FROM_FUNCTION) {
            CompilerAsserts.partialEvaluationConstant(basicBlockIndex);
            LLVMBasicBlockNode bb = bodyNodes[basicBlockIndex];
            // lazily insert the basic block into the AST
            bb.initialize();
            // the newly inserted block may have been instrumented
            bb = bodyNodes[basicBlockIndex];
            // execute all statements
            bb.execute(frame);
            // execute control flow node, write phis, null stack frame slots, and dispatch to
            // the correct successor block
            LLVMControlFlowNode controlFlowNode = bb.getTerminatingInstruction();
            if (controlFlowNode instanceof LLVMConditionalBranchNode) {
                LLVMConditionalBranchNode conditionalBranchNode = (LLVMConditionalBranchNode) controlFlowNode;
                boolean condition = conditionalBranchNode.executeCondition(frame);
                if (CompilerDirectives.injectBranchProbability(bb.getBranchProbability(LLVMConditionalBranchNode.TRUE_SUCCESSOR), condition)) {
                    bb.enterSuccessor(LLVMConditionalBranchNode.TRUE_SUCCESSOR);
                    basicBlockIndex = beforeJumpChecks(basicBlockIndex, conditionalBranchNode.getTrueSuccessor(), LLVMConditionalBranchNode.TRUE_SUCCESSOR, counter, controlFlowNode, frame);
                // continue outer;
                } else {
                    bb.enterSuccessor(LLVMConditionalBranchNode.FALSE_SUCCESSOR);
                    basicBlockIndex = beforeJumpChecks(basicBlockIndex, conditionalBranchNode.getFalseSuccessor(), LLVMConditionalBranchNode.FALSE_SUCCESSOR, counter, controlFlowNode, frame);
                }
            } else if (controlFlowNode instanceof LLVMSwitchNode) {
                LLVMSwitchNode switchNode = (LLVMSwitchNode) controlFlowNode;
                Object condition = switchNode.executeCondition(frame);
                int[] successors = switchNode.getSuccessors();
                for (int i = 0; i < successors.length - 1; i++) {
                    if (CompilerDirectives.injectBranchProbability(bb.getBranchProbability(i), switchNode.checkCase(frame, i, condition))) {
                        bb.enterSuccessor(i);
                        basicBlockIndex = beforeJumpChecks(basicBlockIndex, successors[i], i, counter, controlFlowNode, frame);
                        continue outer;
                    }
                }
                int i = successors.length - 1;
                bb.enterSuccessor(i);
                basicBlockIndex = beforeJumpChecks(basicBlockIndex, successors[i], i, counter, controlFlowNode, frame);
            } else if (controlFlowNode instanceof LLVMLoopNode) {
                LLVMLoopNode loop = (LLVMLoopNode) controlFlowNode;
                loop.executeLoop(frame);
                int successorBasicBlockIndex = frame.getInt(loopSuccessorSlot);
                // null frame
                frame.setInt(loopSuccessorSlot, 0);
                int[] successors = loop.getSuccessors();
                for (int i = 0; i < successors.length - 1; i++) {
                    if (successorBasicBlockIndex == successors[i]) {
                        basicBlockIndex = beforeJumpChecks(basicBlockIndex, successors[i], -1, counter, null, frame);
                        continue outer;
                    }
                }
                int i = successors.length - 1;
                assert successors[i] == successorBasicBlockIndex : "Could not find loop successor!";
                basicBlockIndex = beforeJumpChecks(basicBlockIndex, successors[i], -1, counter, null, frame);
            } else if (controlFlowNode instanceof LLVMIndirectBranchNode) {
                // TODO (chaeubl): we need a different approach here - this is awfully
                // inefficient (see GR-3664)
                LLVMIndirectBranchNode indirectBranchNode = (LLVMIndirectBranchNode) controlFlowNode;
                int[] successors = indirectBranchNode.getSuccessors();
                int successorBasicBlockIndex = indirectBranchNode.executeCondition(frame);
                for (int i = 0; i < successors.length - 1; i++) {
                    if (CompilerDirectives.injectBranchProbability(bb.getBranchProbability(i), successors[i] == successorBasicBlockIndex)) {
                        bb.enterSuccessor(i);
                        basicBlockIndex = beforeJumpChecks(basicBlockIndex, successors[i], i, counter, controlFlowNode, frame);
                        continue outer;
                    }
                }
                int i = successors.length - 1;
                assert successorBasicBlockIndex == successors[i];
                bb.enterSuccessor(i);
                basicBlockIndex = beforeJumpChecks(basicBlockIndex, successors[i], i, counter, indirectBranchNode, frame);
            } else if (controlFlowNode instanceof LLVMBrUnconditionalNode) {
                LLVMBrUnconditionalNode unconditionalNode = (LLVMBrUnconditionalNode) controlFlowNode;
                // required for instrumentation
                unconditionalNode.execute(frame);
                basicBlockIndex = beforeJumpChecks(basicBlockIndex, unconditionalNode.getSuccessor(), 0, counter, controlFlowNode, frame);
            } else if (controlFlowNode instanceof LLVMInvokeNode) {
                LLVMInvokeNode invokeNode = (LLVMInvokeNode) controlFlowNode;
                try {
                    invokeNode.execute(frame);
                    bb.enterSuccessor(LLVMInvokeNode.NORMAL_SUCCESSOR);
                    basicBlockIndex = beforeJumpChecks(basicBlockIndex, invokeNode.getNormalSuccessor(), LLVMInvokeNode.NORMAL_SUCCESSOR, counter, controlFlowNode, frame);
                } catch (LLVMUserException e) {
                    bb.enterSuccessor(LLVMInvokeNode.UNWIND_SUCCESSOR);
                    frame.setObject(exceptionValueSlot, e);
                    basicBlockIndex = beforeJumpChecks(basicBlockIndex, invokeNode.getUnwindSuccessor(), LLVMInvokeNode.UNWIND_SUCCESSOR, counter, controlFlowNode, frame);
                }
            } else if (controlFlowNode instanceof LLVMRetNode) {
                LLVMRetNode retNode = (LLVMRetNode) controlFlowNode;
                returnValue = retNode.execute(frame);
                assert noPhisNecessary(retNode);
                nullDeadSlots(frame, bb.nullableAfter);
                basicBlockIndex = beforeJumpChecks(basicBlockIndex, retNode.getSuccessor(), -1, counter, null, frame);
            } else if (controlFlowNode instanceof LLVMResumeNode) {
                LLVMResumeNode resumeNode = (LLVMResumeNode) controlFlowNode;
                assert noPhisNecessary(resumeNode);
                resumeNode.execute(frame);
                CompilerDirectives.transferToInterpreterAndInvalidate();
                throw new IllegalStateException("must not reach here");
            } else if (controlFlowNode instanceof LLVMUnreachableNode) {
                LLVMUnreachableNode unreachableNode = (LLVMUnreachableNode) controlFlowNode;
                assert noPhisNecessary(unreachableNode);
                unreachableNode.execute(frame);
                CompilerDirectives.transferToInterpreterAndInvalidate();
                throw new IllegalStateException("must not reach here");
            } else {
                CompilerDirectives.transferToInterpreterAndInvalidate();
                throw new UnsupportedOperationException("unexpected controlFlowNode type: " + controlFlowNode);
            }
        }
    } catch (OSRReturnException e) {
        returnValue = e.getResult();
    }
    // only report non-zero counters to reduce interpreter overhead
    int value = counter.value;
    if (CompilerDirectives.hasNextTier() && value != 0) {
        LoopNode.reportLoopCount(this, value > 0 ? value : Integer.MAX_VALUE);
    }
    assert returnValue != null;
    return returnValue;
}
Also used : LLVMControlFlowNode(com.oracle.truffle.llvm.runtime.nodes.api.LLVMControlFlowNode) LLVMUnreachableNode(com.oracle.truffle.llvm.runtime.nodes.others.LLVMUnreachableNode) LLVMInvokeNode(com.oracle.truffle.llvm.runtime.nodes.func.LLVMInvokeNode) LLVMUserException(com.oracle.truffle.llvm.runtime.except.LLVMUserException) LLVMResumeNode(com.oracle.truffle.llvm.runtime.nodes.func.LLVMResumeNode) LLVMBasicBlockNode(com.oracle.truffle.llvm.runtime.nodes.base.LLVMBasicBlockNode) ExplodeLoop(com.oracle.truffle.api.nodes.ExplodeLoop)

Example 2 with LLVMInvokeNode

use of com.oracle.truffle.llvm.runtime.nodes.func.LLVMInvokeNode in project graal by oracle.

the class LLVMLoopDispatchNode method executeRepeatingWithValue.

/**
 * The code in this function is mirrored from {@link LLVMDispatchBasicBlockNode}, any changes
 * need to be done in both places. The block id of the successor block (where to continue after
 * the loop) is stored in a frame slot.
 */
@ExplodeLoop(kind = LoopExplosionKind.MERGE_EXPLODE)
@Override
public Object executeRepeatingWithValue(VirtualFrame frame) {
    CompilerAsserts.partialEvaluationConstant(bodyNodes.length);
    int basicBlockIndex = headerId;
    // do-while loop fails at PE
    outer: while (true) {
        CompilerAsserts.partialEvaluationConstant(basicBlockIndex);
        LLVMBasicBlockNode bb = bodyNodes[indexMapping[basicBlockIndex]];
        // lazily insert the basic block into the AST
        bb.initialize();
        // the newly inserted block may have been instrumented
        bb = bodyNodes[indexMapping[basicBlockIndex]];
        // execute all statements
        bb.execute(frame);
        // execute control flow node, write phis, null stack frame slots, and dispatch to
        // the correct successor block
        LLVMControlFlowNode controlFlowNode = bb.getTerminatingInstruction();
        if (controlFlowNode instanceof LLVMConditionalBranchNode) {
            LLVMConditionalBranchNode conditionalBranchNode = (LLVMConditionalBranchNode) controlFlowNode;
            boolean condition = conditionalBranchNode.executeCondition(frame);
            if (CompilerDirectives.injectBranchProbability(bb.getBranchProbability(LLVMConditionalBranchNode.TRUE_SUCCESSOR), condition)) {
                bb.enterSuccessor(LLVMConditionalBranchNode.TRUE_SUCCESSOR);
                LLVMDispatchBasicBlockNode.nullDeadSlots(frame, bb.nullableAfter);
                LLVMDispatchBasicBlockNode.executePhis(frame, conditionalBranchNode, LLVMConditionalBranchNode.TRUE_SUCCESSOR);
                basicBlockIndex = conditionalBranchNode.getTrueSuccessor();
                LLVMDispatchBasicBlockNode.nullDeadSlots(frame, originalBodyNodes[basicBlockIndex].nullableBefore);
                if (basicBlockIndex == headerId) {
                    return RepeatingNode.CONTINUE_LOOP_STATUS;
                }
                if (!isInLoop(basicBlockIndex)) {
                    frame.setInt(successorSlot, basicBlockIndex);
                    return RepeatingNode.BREAK_LOOP_STATUS;
                }
                continue outer;
            } else {
                bb.enterSuccessor(LLVMConditionalBranchNode.FALSE_SUCCESSOR);
                LLVMDispatchBasicBlockNode.nullDeadSlots(frame, bb.nullableAfter);
                LLVMDispatchBasicBlockNode.executePhis(frame, conditionalBranchNode, LLVMConditionalBranchNode.FALSE_SUCCESSOR);
                basicBlockIndex = conditionalBranchNode.getFalseSuccessor();
                LLVMDispatchBasicBlockNode.nullDeadSlots(frame, originalBodyNodes[basicBlockIndex].nullableBefore);
                if (basicBlockIndex == headerId) {
                    return RepeatingNode.CONTINUE_LOOP_STATUS;
                }
                if (!isInLoop(basicBlockIndex)) {
                    frame.setInt(successorSlot, basicBlockIndex);
                    return RepeatingNode.BREAK_LOOP_STATUS;
                }
                continue outer;
            }
        } else if (controlFlowNode instanceof LLVMSwitchNode) {
            LLVMSwitchNode switchNode = (LLVMSwitchNode) controlFlowNode;
            Object condition = switchNode.executeCondition(frame);
            int[] successors = switchNode.getSuccessors();
            for (int i = 0; i < successors.length - 1; i++) {
                if (CompilerDirectives.injectBranchProbability(bb.getBranchProbability(i), switchNode.checkCase(frame, i, condition))) {
                    bb.enterSuccessor(i);
                    LLVMDispatchBasicBlockNode.nullDeadSlots(frame, bb.nullableAfter);
                    LLVMDispatchBasicBlockNode.executePhis(frame, switchNode, i);
                    basicBlockIndex = successors[i];
                    LLVMDispatchBasicBlockNode.nullDeadSlots(frame, originalBodyNodes[basicBlockIndex].nullableBefore);
                    if (basicBlockIndex == headerId) {
                        return RepeatingNode.CONTINUE_LOOP_STATUS;
                    }
                    if (!isInLoop(basicBlockIndex)) {
                        frame.setInt(successorSlot, basicBlockIndex);
                        return RepeatingNode.BREAK_LOOP_STATUS;
                    }
                    continue outer;
                }
            }
            int i = successors.length - 1;
            bb.enterSuccessor(i);
            LLVMDispatchBasicBlockNode.nullDeadSlots(frame, bb.nullableAfter);
            LLVMDispatchBasicBlockNode.executePhis(frame, switchNode, i);
            basicBlockIndex = successors[i];
            LLVMDispatchBasicBlockNode.nullDeadSlots(frame, originalBodyNodes[basicBlockIndex].nullableBefore);
            if (basicBlockIndex == headerId) {
                return RepeatingNode.CONTINUE_LOOP_STATUS;
            }
            if (!isInLoop(basicBlockIndex)) {
                frame.setInt(successorSlot, basicBlockIndex);
                return RepeatingNode.BREAK_LOOP_STATUS;
            }
            continue outer;
        } else if (controlFlowNode instanceof LLVMLoopNode) {
            LLVMLoopNode loop = (LLVMLoopNode) controlFlowNode;
            loop.executeLoop(frame);
            int successorBasicBlockIndex = frame.getInt(successorSlot);
            // null frame
            frame.setInt(successorSlot, 0);
            int[] successors = loop.getSuccessors();
            for (int i = 0; i < successors.length - 1; i++) {
                if (successorBasicBlockIndex == successors[i]) {
                    basicBlockIndex = successors[i];
                    if (basicBlockIndex == headerId) {
                        return RepeatingNode.CONTINUE_LOOP_STATUS;
                    }
                    if (!isInLoop(basicBlockIndex)) {
                        frame.setInt(successorSlot, basicBlockIndex);
                        return RepeatingNode.BREAK_LOOP_STATUS;
                    }
                    continue outer;
                }
            }
            int i = successors.length - 1;
            assert successors[i] == successorBasicBlockIndex : "Could not find loop successor!";
            basicBlockIndex = successors[i];
            if (basicBlockIndex == headerId) {
                return RepeatingNode.CONTINUE_LOOP_STATUS;
            }
            if (!isInLoop(basicBlockIndex)) {
                frame.setInt(successorSlot, basicBlockIndex);
                return RepeatingNode.BREAK_LOOP_STATUS;
            }
            continue outer;
        } else if (controlFlowNode instanceof LLVMIndirectBranchNode) {
            // TODO (chaeubl): we need a different approach here - this is awfully
            // inefficient (see GR-3664)
            LLVMIndirectBranchNode indirectBranchNode = (LLVMIndirectBranchNode) controlFlowNode;
            int[] successors = indirectBranchNode.getSuccessors();
            int successorBasicBlockIndex = indirectBranchNode.executeCondition(frame);
            for (int i = 0; i < successors.length - 1; i++) {
                if (CompilerDirectives.injectBranchProbability(bb.getBranchProbability(i), successors[i] == successorBasicBlockIndex)) {
                    bb.enterSuccessor(i);
                    LLVMDispatchBasicBlockNode.nullDeadSlots(frame, bb.nullableAfter);
                    LLVMDispatchBasicBlockNode.executePhis(frame, indirectBranchNode, i);
                    basicBlockIndex = successors[i];
                    LLVMDispatchBasicBlockNode.nullDeadSlots(frame, originalBodyNodes[basicBlockIndex].nullableBefore);
                    if (basicBlockIndex == headerId) {
                        return RepeatingNode.CONTINUE_LOOP_STATUS;
                    }
                    if (!isInLoop(basicBlockIndex)) {
                        frame.setInt(successorSlot, basicBlockIndex);
                        return RepeatingNode.BREAK_LOOP_STATUS;
                    }
                    continue outer;
                }
            }
            int i = successors.length - 1;
            assert successorBasicBlockIndex == successors[i];
            bb.enterSuccessor(i);
            LLVMDispatchBasicBlockNode.nullDeadSlots(frame, bb.nullableAfter);
            LLVMDispatchBasicBlockNode.executePhis(frame, indirectBranchNode, i);
            basicBlockIndex = successors[i];
            LLVMDispatchBasicBlockNode.nullDeadSlots(frame, originalBodyNodes[basicBlockIndex].nullableBefore);
            if (basicBlockIndex == headerId) {
                return RepeatingNode.CONTINUE_LOOP_STATUS;
            }
            if (!isInLoop(basicBlockIndex)) {
                frame.setInt(successorSlot, basicBlockIndex);
                return RepeatingNode.BREAK_LOOP_STATUS;
            }
            continue outer;
        } else if (controlFlowNode instanceof LLVMBrUnconditionalNode) {
            LLVMBrUnconditionalNode unconditionalNode = (LLVMBrUnconditionalNode) controlFlowNode;
            // required for instrumentation
            unconditionalNode.execute(frame);
            LLVMDispatchBasicBlockNode.nullDeadSlots(frame, bb.nullableAfter);
            LLVMDispatchBasicBlockNode.executePhis(frame, unconditionalNode, 0);
            basicBlockIndex = unconditionalNode.getSuccessor();
            LLVMDispatchBasicBlockNode.nullDeadSlots(frame, originalBodyNodes[basicBlockIndex].nullableBefore);
            if (basicBlockIndex == headerId) {
                return RepeatingNode.CONTINUE_LOOP_STATUS;
            }
            if (!isInLoop(basicBlockIndex)) {
                frame.setInt(successorSlot, basicBlockIndex);
                return RepeatingNode.BREAK_LOOP_STATUS;
            }
            continue outer;
        } else if (controlFlowNode instanceof LLVMInvokeNode) {
            LLVMInvokeNode invokeNode = (LLVMInvokeNode) controlFlowNode;
            try {
                invokeNode.execute(frame);
                bb.enterSuccessor(LLVMInvokeNode.NORMAL_SUCCESSOR);
                LLVMDispatchBasicBlockNode.nullDeadSlots(frame, bb.nullableAfter);
                LLVMDispatchBasicBlockNode.executePhis(frame, invokeNode, LLVMInvokeNode.NORMAL_SUCCESSOR);
                basicBlockIndex = invokeNode.getNormalSuccessor();
                LLVMDispatchBasicBlockNode.nullDeadSlots(frame, originalBodyNodes[basicBlockIndex].nullableBefore);
                if (basicBlockIndex == headerId) {
                    return RepeatingNode.CONTINUE_LOOP_STATUS;
                }
                if (!isInLoop(basicBlockIndex)) {
                    frame.setInt(successorSlot, basicBlockIndex);
                    return RepeatingNode.BREAK_LOOP_STATUS;
                }
                continue outer;
            } catch (LLVMUserException e) {
                bb.enterSuccessor(LLVMInvokeNode.UNWIND_SUCCESSOR);
                frame.setObject(exceptionValueSlot, e);
                LLVMDispatchBasicBlockNode.nullDeadSlots(frame, bb.nullableAfter);
                LLVMDispatchBasicBlockNode.executePhis(frame, invokeNode, LLVMInvokeNode.UNWIND_SUCCESSOR);
                basicBlockIndex = invokeNode.getUnwindSuccessor();
                LLVMDispatchBasicBlockNode.nullDeadSlots(frame, originalBodyNodes[basicBlockIndex].nullableBefore);
                if (basicBlockIndex == headerId) {
                    return RepeatingNode.CONTINUE_LOOP_STATUS;
                }
                if (!isInLoop(basicBlockIndex)) {
                    frame.setInt(successorSlot, basicBlockIndex);
                    return RepeatingNode.BREAK_LOOP_STATUS;
                }
                continue outer;
            }
        } else {
            // some control flow nodes should be never part of a loop
            CompilerDirectives.transferToInterpreterAndInvalidate();
            throw new UnsupportedOperationException("unexpected controlFlowNode type: " + controlFlowNode);
        }
    }
}
Also used : LLVMControlFlowNode(com.oracle.truffle.llvm.runtime.nodes.api.LLVMControlFlowNode) LLVMInvokeNode(com.oracle.truffle.llvm.runtime.nodes.func.LLVMInvokeNode) LLVMUserException(com.oracle.truffle.llvm.runtime.except.LLVMUserException) LLVMBasicBlockNode(com.oracle.truffle.llvm.runtime.nodes.base.LLVMBasicBlockNode) ExplodeLoop(com.oracle.truffle.api.nodes.ExplodeLoop)

Aggregations

ExplodeLoop (com.oracle.truffle.api.nodes.ExplodeLoop)2 LLVMUserException (com.oracle.truffle.llvm.runtime.except.LLVMUserException)2 LLVMControlFlowNode (com.oracle.truffle.llvm.runtime.nodes.api.LLVMControlFlowNode)2 LLVMBasicBlockNode (com.oracle.truffle.llvm.runtime.nodes.base.LLVMBasicBlockNode)2 LLVMInvokeNode (com.oracle.truffle.llvm.runtime.nodes.func.LLVMInvokeNode)2 LLVMResumeNode (com.oracle.truffle.llvm.runtime.nodes.func.LLVMResumeNode)1 LLVMUnreachableNode (com.oracle.truffle.llvm.runtime.nodes.others.LLVMUnreachableNode)1