Search in sources :

Example 1 with Edge

use of com.intellij.codeInspection.bytecodeAnalysis.asm.ControlFlowGraph.Edge in project intellij-community by JetBrains.

the class RichControlFlow method reducible.

// Tarjan. Testing flow graph reducibility.
// Journal of Computer and System Sciences 9.3 (1974): 355-365.
public boolean reducible() {
    if (dfsTree.back.isEmpty()) {
        return true;
    }
    int size = controlFlow.transitions.length;
    boolean[] loopEnters = dfsTree.loopEnters;
    TIntHashSet[] cycleIncomings = new TIntHashSet[size];
    // really this may be array, since dfs already ensures no duplicates
    TIntArrayList[] nonCycleIncomings = new TIntArrayList[size];
    int[] collapsedTo = new int[size];
    int[] queue = new int[size];
    int top;
    for (int i = 0; i < size; i++) {
        if (loopEnters[i]) {
            cycleIncomings[i] = new TIntHashSet();
        }
        nonCycleIncomings[i] = new TIntArrayList();
        collapsedTo[i] = i;
    }
    // from whom back connections
    for (Edge edge : dfsTree.back) {
        cycleIncomings[edge.to].add(edge.from);
    }
    // from whom ordinary connections
    for (Edge edge : dfsTree.nonBack) {
        nonCycleIncomings[edge.to].add(edge.from);
    }
    for (int w = size - 1; w >= 0; w--) {
        top = 0;
        // NB - it is modified later!
        TIntHashSet p = cycleIncomings[w];
        if (p == null) {
            continue;
        }
        TIntIterator iter = p.iterator();
        while (iter.hasNext()) {
            queue[top++] = iter.next();
        }
        while (top > 0) {
            int x = queue[--top];
            TIntArrayList incoming = nonCycleIncomings[x];
            for (int i = 0; i < incoming.size(); i++) {
                int y1 = collapsedTo[incoming.getQuick(i)];
                if (!dfsTree.isDescendant(y1, w)) {
                    return false;
                }
                if (y1 != w && p.add(y1)) {
                    queue[top++] = y1;
                }
            }
        }
        iter = p.iterator();
        while (iter.hasNext()) {
            collapsedTo[iter.next()] = w;
        }
    }
    return true;
}
Also used : TIntIterator(gnu.trove.TIntIterator) Edge(com.intellij.codeInspection.bytecodeAnalysis.asm.ControlFlowGraph.Edge) TIntHashSet(gnu.trove.TIntHashSet) TIntArrayList(gnu.trove.TIntArrayList)

Example 2 with Edge

use of com.intellij.codeInspection.bytecodeAnalysis.asm.ControlFlowGraph.Edge in project intellij-community by JetBrains.

the class InOutInterpreter method processState.

void processState(State state) throws AnalyzerException {
    Conf preConf = state.conf;
    int insnIndex = preConf.insnIndex;
    boolean loopEnter = dfsTree.loopEnters[insnIndex];
    Conf conf = loopEnter ? generalize(preConf) : preConf;
    List<Conf> history = state.history;
    boolean taken = state.taken;
    Frame<BasicValue> frame = conf.frame;
    AbstractInsnNode insnNode = methodNode.instructions.get(insnIndex);
    List<Conf> nextHistory = loopEnter ? append(history, conf) : history;
    Frame<BasicValue> nextFrame = execute(frame, insnNode);
    addComputed(insnIndex, state);
    if (interpreter.deReferenced) {
        return;
    }
    int opcode = insnNode.getOpcode();
    switch(opcode) {
        case ARETURN:
        case IRETURN:
        case LRETURN:
        case FRETURN:
        case DRETURN:
        case RETURN:
            BasicValue stackTop = popValue(frame);
            Result subResult;
            if (FalseValue == stackTop) {
                subResult = new Final(Value.False);
            } else if (TrueValue == stackTop) {
                subResult = new Final(Value.True);
            } else if (NullValue == stackTop) {
                subResult = new Final(Value.Null);
            } else if (stackTop instanceof NotNullValue) {
                subResult = new Final(Value.NotNull);
            } else if (stackTop instanceof ParamValue) {
                subResult = new Final(inValue);
            } else if (stackTop instanceof CallResultValue) {
                Set<Key> keys = ((CallResultValue) stackTop).inters;
                subResult = new Pending(Collections.singleton(new Product(Value.Top, keys)));
            } else {
                earlyResult = new Final(Value.Top);
                return;
            }
            internalResult = resultUtil.join(internalResult, subResult);
            if (internalResult instanceof Final && ((Final) internalResult).value == Value.Top) {
                earlyResult = internalResult;
            }
            return;
        case ATHROW:
            return;
        default:
    }
    if (opcode == IFNONNULL && popValue(frame) instanceof ParamValue) {
        int nextInsnIndex = inValue == Value.Null ? insnIndex + 1 : methodNode.instructions.indexOf(((JumpInsnNode) insnNode).label);
        State nextState = new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false);
        pendingPush(nextState);
        return;
    }
    if (opcode == IFNULL && popValue(frame) instanceof ParamValue) {
        int nextInsnIndex = inValue == Value.NotNull ? insnIndex + 1 : methodNode.instructions.indexOf(((JumpInsnNode) insnNode).label);
        State nextState = new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false);
        pendingPush(nextState);
        return;
    }
    if (opcode == IFEQ && popValue(frame) == InstanceOfCheckValue && inValue == Value.Null) {
        int nextInsnIndex = methodNode.instructions.indexOf(((JumpInsnNode) insnNode).label);
        State nextState = new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false);
        pendingPush(nextState);
        return;
    }
    if (opcode == IFNE && popValue(frame) == InstanceOfCheckValue && inValue == Value.Null) {
        int nextInsnIndex = insnIndex + 1;
        State nextState = new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false);
        pendingPush(nextState);
        return;
    }
    // general case
    for (int nextInsnIndex : controlFlow.transitions[insnIndex]) {
        Frame<BasicValue> nextFrame1 = nextFrame;
        if (controlFlow.errors[nextInsnIndex] && controlFlow.errorTransitions.contains(new Edge(insnIndex, nextInsnIndex))) {
            nextFrame1 = new Frame<>(frame);
            nextFrame1.clearStack();
            nextFrame1.push(ASMUtils.THROWABLE_VALUE);
        }
        pendingPush(new State(++id, new Conf(nextInsnIndex, nextFrame1), nextHistory, taken, false));
    }
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) BasicValue(org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue) Edge(com.intellij.codeInspection.bytecodeAnalysis.asm.ControlFlowGraph.Edge)

Example 3 with Edge

use of com.intellij.codeInspection.bytecodeAnalysis.asm.ControlFlowGraph.Edge in project intellij-community by JetBrains.

the class NullableInterpreter method processState.

private void processState(State state) throws AnalyzerException {
    Conf conf = state.conf;
    int insnIndex = conf.insnIndex;
    List<Conf> history = state.history;
    boolean taken = state.taken;
    Frame<BasicValue> frame = conf.frame;
    AbstractInsnNode insnNode = methodNode.instructions.get(insnIndex);
    List<Conf> nextHistory = dfsTree.loopEnters[insnIndex] ? append(history, conf) : history;
    addComputed(insnIndex, state);
    execute(frame, insnNode, taken);
    if (subResult == NPE || top) {
        earlyResult = NPE;
        return;
    }
    if (subResult instanceof ConditionalNPE) {
        myResult = combineNullable(myResult, subResult);
    }
    int opcode = insnNode.getOpcode();
    switch(opcode) {
        case ARETURN:
            if (popValue(frame) instanceof ParamValue) {
                earlyResult = NPE;
            }
            return;
        case IRETURN:
        case LRETURN:
        case FRETURN:
        case DRETURN:
        case RETURN:
            return;
        default:
    }
    if (opcode == ATHROW) {
        if (taken) {
            earlyResult = NPE;
        }
        return;
    }
    if (opcode == IFNONNULL && popValue(frame) instanceof ParamValue) {
        int nextInsnIndex = insnIndex + 1;
        pendingPush(new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false));
        return;
    }
    if (opcode == IFNULL && popValue(frame) instanceof ParamValue) {
        int nextInsnIndex = methodNode.instructions.indexOf(((JumpInsnNode) insnNode).label);
        pendingPush(new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false));
        return;
    }
    if (opcode == IFEQ && popValue(frame) == InstanceOfCheckValue) {
        int nextInsnIndex = methodNode.instructions.indexOf(((JumpInsnNode) insnNode).label);
        pendingPush(new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false));
        return;
    }
    if (opcode == IFNE && popValue(frame) == InstanceOfCheckValue) {
        int nextInsnIndex = insnIndex + 1;
        pendingPush(new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false));
        return;
    }
    // general case
    for (int nextInsnIndex : controlFlow.transitions[insnIndex]) {
        Frame<BasicValue> nextFrame1 = nextFrame;
        if (controlFlow.errors[nextInsnIndex] && controlFlow.errorTransitions.contains(new Edge(insnIndex, nextInsnIndex))) {
            nextFrame1 = new Frame<>(frame);
            nextFrame1.clearStack();
            nextFrame1.push(ASMUtils.THROWABLE_VALUE);
        }
        pendingPush(new State(++id, new Conf(nextInsnIndex, nextFrame1), nextHistory, taken, false));
    }
}
Also used : AbstractInsnNode(org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode) Edge(com.intellij.codeInspection.bytecodeAnalysis.asm.ControlFlowGraph.Edge) BasicValue(org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue)

Example 4 with Edge

use of com.intellij.codeInspection.bytecodeAnalysis.asm.ControlFlowGraph.Edge in project intellij-community by JetBrains.

the class LiteControlFlowBuilder method newControlFlowExceptionEdge.

@Override
protected final boolean newControlFlowExceptionEdge(int insn, int successor) {
    if (!transitions[insn].contains(successor)) {
        transitions[insn].add(successor);
        edgeCount++;
        errorTransitions.add(new Edge(insn, successor));
        errors[successor] = true;
    }
    return true;
}
Also used : Edge(com.intellij.codeInspection.bytecodeAnalysis.asm.ControlFlowGraph.Edge)

Example 5 with Edge

use of com.intellij.codeInspection.bytecodeAnalysis.asm.ControlFlowGraph.Edge in project intellij-community by JetBrains.

the class DFSTree method build.

// Graphs: Theory and Algorithms. by K. Thulasiraman , M. N. S. Swamy (1992)
// 11.7.2 DFS of a directed graph
public static DFSTree build(int[][] transitions, int edgeCount) {
    HashSet<Edge> nonBack = new HashSet<>();
    HashSet<Edge> back = new HashSet<>();
    boolean[] marked = new boolean[transitions.length];
    boolean[] scanned = new boolean[transitions.length];
    int[] preOrder = new int[transitions.length];
    int[] postOrder = new int[transitions.length];
    int entered = 0;
    int completed = 0;
    boolean[] loopEnters = new boolean[transitions.length];
    // enter 0
    entered++;
    preOrder[0] = entered;
    marked[0] = true;
    boolean[] stackFlag = new boolean[edgeCount * 2 + 1];
    int[] stackFrom = new int[edgeCount * 2 + 1];
    int[] stackTo = new int[edgeCount * 2 + 1];
    int top = 0;
    // stack.push(new MarkScanned(0));
    stackFlag[top] = true;
    stackTo[top] = 0;
    top++;
    for (int to : transitions[0]) {
        //stack.push(new ExamineEdge(0, to));
        stackFlag[top] = false;
        stackFrom[top] = 0;
        stackTo[top] = to;
        top++;
    }
    while (top > 0) {
        top--;
        // markScanned
        if (stackFlag[top]) {
            completed++;
            postOrder[stackTo[top]] = completed;
            scanned[stackTo[top]] = true;
        } else {
            //ExamineEdge examineEdgeAction = (ExamineEdge) action;
            int from = stackFrom[top];
            int to = stackTo[top];
            if (!marked[to]) {
                nonBack.add(new Edge(from, to));
                // enter to
                entered++;
                preOrder[to] = entered;
                marked[to] = true;
                //stack.push(new MarkScanned(to));
                stackFlag[top] = true;
                stackTo[top] = to;
                top++;
                for (int to1 : transitions[to]) {
                    //stack.push(new ExamineEdge(to, to1));
                    stackFlag[top] = false;
                    stackFrom[top] = to;
                    stackTo[top] = to1;
                    top++;
                }
            } else if (preOrder[to] > preOrder[from]) {
                nonBack.add(new Edge(from, to));
            } else if (preOrder[to] < preOrder[from] && !scanned[to]) {
                back.add(new Edge(from, to));
                loopEnters[to] = true;
            } else {
                nonBack.add(new Edge(from, to));
            }
        }
    }
    return new DFSTree(preOrder, postOrder, nonBack, back, loopEnters);
}
Also used : Edge(com.intellij.codeInspection.bytecodeAnalysis.asm.ControlFlowGraph.Edge) HashSet(java.util.HashSet)

Aggregations

Edge (com.intellij.codeInspection.bytecodeAnalysis.asm.ControlFlowGraph.Edge)5 HashSet (java.util.HashSet)2 BasicValue (org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue)2 TIntArrayList (gnu.trove.TIntArrayList)1 TIntHashSet (gnu.trove.TIntHashSet)1 TIntIterator (gnu.trove.TIntIterator)1 Set (java.util.Set)1 AbstractInsnNode (org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode)1