Search in sources :

Example 6 with BasicValue

use of org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue in project intellij-community by JetBrains.

the class InOutInterpreter method generalize.

private Conf generalize(Conf conf) {
    Frame<BasicValue> frame = new Frame<>(conf.frame);
    for (int i = generalizeShift; i < frame.getLocals(); i++) {
        BasicValue value = frame.getLocal(i);
        Class<?> valueClass = value.getClass();
        if (valueClass != BasicValue.class && valueClass != ParamValue.class) {
            frame.setLocal(i, new BasicValue(value.getType()));
        }
    }
    BasicValue[] stack = new BasicValue[frame.getStackSize()];
    for (int i = 0; i < frame.getStackSize(); i++) {
        stack[i] = frame.getStack(i);
    }
    frame.clearStack();
    for (BasicValue value : stack) {
        Class<?> valueClass = value.getClass();
        if (valueClass != BasicValue.class && valueClass != ParamValue.class) {
            frame.push(new BasicValue(value.getType()));
        } else {
            frame.push(value);
        }
    }
    return new Conf(conf.insnIndex, frame);
}
Also used : Frame(org.jetbrains.org.objectweb.asm.tree.analysis.Frame) BasicValue(org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue)

Example 7 with BasicValue

use of org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue 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 8 with BasicValue

use of org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue 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 9 with BasicValue

use of org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue in project intellij-community by JetBrains.

the class NullableMethodInterpreter method naryOperation.

@Override
public BasicValue naryOperation(AbstractInsnNode insn, List<? extends BasicValue> values) throws AnalyzerException {
    int opCode = insn.getOpcode();
    switch(opCode) {
        case INVOKESPECIAL:
        case INVOKEINTERFACE:
        case INVOKEVIRTUAL:
            BasicValue receiver = values.get(0);
            if (receiver instanceof Calls) {
                delta = ((Calls) receiver).mergedLabels;
            }
            if (receiver instanceof LabeledNull) {
                nullsDelta = ((LabeledNull) receiver).origins;
            }
            break;
        default:
    }
    switch(opCode) {
        case INVOKESTATIC:
        case INVOKESPECIAL:
        case INVOKEVIRTUAL:
            int insnIndex = insns.indexOf(insn);
            if (origins[insnIndex]) {
                boolean stable = opCode == INVOKESTATIC || opCode == INVOKESPECIAL;
                MethodInsnNode mNode = ((MethodInsnNode) insn);
                Method method = new Method(mNode.owner, mNode.name, mNode.desc);
                int label = 1 << originsMapping[insnIndex];
                if (keys[insnIndex] == null) {
                    keys[insnIndex] = new Key(method, Direction.NullableOut, stable);
                }
                return new Calls(label);
            }
            break;
        default:
    }
    return super.naryOperation(insn, values);
}
Also used : BasicValue(org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue)

Example 10 with BasicValue

use of org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue in project intellij-community by JetBrains.

the class NullableInterpreter method naryOperation.

@Override
public BasicValue naryOperation(AbstractInsnNode insn, List<? extends BasicValue> values) throws AnalyzerException {
    int opcode = insn.getOpcode();
    boolean isStaticInvoke = opcode == INVOKESTATIC;
    int shift = isStaticInvoke ? 0 : 1;
    if ((opcode == INVOKESPECIAL || opcode == INVOKEINTERFACE || opcode == INVOKEVIRTUAL) && values.get(0) instanceof ParamValue) {
        subResult = NPE;
    }
    switch(opcode) {
        case INVOKEINTERFACE:
            if (nullableAnalysis) {
                for (int i = shift; i < values.size(); i++) {
                    if (values.get(i) instanceof ParamValue) {
                        top = true;
                        return super.naryOperation(insn, values);
                    }
                }
            }
            break;
        case INVOKESTATIC:
        case INVOKESPECIAL:
        case INVOKEVIRTUAL:
            boolean stable = opcode == INVOKESTATIC || opcode == INVOKESPECIAL;
            MethodInsnNode methodNode = (MethodInsnNode) insn;
            Method method = new Method(methodNode.owner, methodNode.name, methodNode.desc);
            for (int i = shift; i < values.size(); i++) {
                BasicValue value = values.get(i);
                if (value instanceof ParamValue || (NullValue == value && nullityMask == In.NULLABLE_MASK && "<init>".equals(methodNode.name))) {
                    subResult = combine(subResult, new ConditionalNPE(new Key(method, new In(i - shift, nullityMask), stable)));
                }
            }
            break;
        default:
    }
    return super.naryOperation(insn, values);
}
Also used : In(com.intellij.codeInspection.bytecodeAnalysis.Direction.In) MethodInsnNode(org.jetbrains.org.objectweb.asm.tree.MethodInsnNode) BasicValue(org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue)

Aggregations

BasicValue (org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue)17 Frame (org.jetbrains.org.objectweb.asm.tree.analysis.Frame)5 StrictBasicValue (org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue)4 Type (org.jetbrains.org.objectweb.asm.Type)3 In (com.intellij.codeInspection.bytecodeAnalysis.Direction.In)2 Edge (com.intellij.codeInspection.bytecodeAnalysis.asm.ControlFlowGraph.Edge)2 HashSet (java.util.HashSet)2 InOut (com.intellij.codeInspection.bytecodeAnalysis.Direction.InOut)1 AnalyzerExt (com.intellij.codeInspection.bytecodeAnalysis.asm.AnalyzerExt)1 LiteAnalyzerExt (com.intellij.codeInspection.bytecodeAnalysis.asm.LiteAnalyzerExt)1 SingletonSet (com.intellij.util.SingletonSet)1 HashSet (com.intellij.util.containers.HashSet)1 PrintWriter (java.io.PrintWriter)1 Set (java.util.Set)1 NotNull (org.jetbrains.annotations.NotNull)1 ClassReader (org.jetbrains.org.objectweb.asm.ClassReader)1 AbstractInsnNode (org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode)1 ClassNode (org.jetbrains.org.objectweb.asm.tree.ClassNode)1 MethodInsnNode (org.jetbrains.org.objectweb.asm.tree.MethodInsnNode)1 MethodNode (org.jetbrains.org.objectweb.asm.tree.MethodNode)1