reduces the end pc based on the optional LocalVariableTable's exception
register scope

@param infos the list of active catch blocks
@param pc    the current pc
@param seen  the currently parsed opcode
971293
private void updateEndPCsOnCatchRegScope(List<CatchInfo> infos, int pc, int seen) {
        if (lvt != null) {
            for (CatchInfo ci : infos) {
                if ((ci.getStart() == pc) && OpcodeUtils.isAStore(seen)) {
                    int exReg = RegisterUtils.getAStoreReg(this, seen);
                    LocalVariable lv = lvt.getLocalVariable(exReg, pc + 1);
                    if (lv != null) {
                        ci.setFinish(lv.getStartPC() + lv.getLength());
                    }
                    break;
                }
            }
        }
    }
1252227
@Override
    public void sawOpcode(int seen) {
        if (seen == Const.INVOKEINTERFACE) {
            String clsName = getClassConstantOperand();
            String methodName = getNameConstantOperand();

            if (queryClasses.contains(clsName) && queryMethods.contains(methodName)) {
                queryLocations.add(Integer.valueOf(getPC()));
            }
        } else if (OpcodeUtils.isBranch(seen)) {
            int branchTarget = getBranchTarget();
            int pc = getPC();
            if (branchTarget < pc) {
                loops.add(new LoopLocation(branchTarget, pc));
            }
        }
    }
381132
private static Set<String> findPossibleCatchSignatures(List<CatchInfo> infos, int pc) {
        Set<String> catchTypes = new HashSet<>(6);
        ListIterator<CatchInfo> it = infos.listIterator(infos.size());
        while (it.hasPrevious()) {
            CatchInfo ci = it.previous();
            if ((pc >= ci.getStart()) && (pc < ci.getFinish())) {
                catchTypes.add(ci.getSignature());
            } else {
                break;
            }
        }

        return catchTypes;
    }
595207
@Override
    public void sawOpcode(int seen) {
        try {
            stack.precomputation(this);

            if (seen == Const.INVOKEINTERFACE) {
                processInvokeInterface();

            } else if (seen == Const.INVOKESPECIAL) {
                processInvokeSpecial();
            }
        } finally {
            stack.sawOpcode(this, seen);
        }
    }
1215066
@Override
    public void sawOpcode(final int seen) {

        try {
            stack.precomputation(this);

            if (OpcodeUtils.isInvoke(seen)) {
                String methodSig = getSigConstantOperand();
                List<String> parmTypes = SignatureUtils.getParameterSignatures(methodSig);
                int stackDepth = stack.getStackDepth();
                if (stackDepth >= parmTypes.size()) {
                    for (int i = 0; i < parmTypes.size(); i++) {
                        OpcodeStack.Item itm = stack.getStackItem(i);
                        int reg = itm.getRegisterNumber();
                        removeUselessDefiners(parmTypes.get(parmTypes.size() - i - 1), reg);
                    }
                }

                if ((seen != Const.INVOKESPECIAL) && (seen != Const.INVOKESTATIC)) {
                    if (stackDepth > parmTypes.size()) {
                        OpcodeStack.Item itm = stack.getStackItem(parmTypes.size());
                        int reg = itm.getRegisterNumber();
                        int parm = reg;
                        if (!methodIsStatic) {
                            parm--;
                        }
                        if ((parm >= 0) && (parm < parmCount)) {
                            removeUselessDefiners(reg);
                        }
                    } else {
                        parameterDefiners.clear();
                    }
                }
            } else if ((seen == Const.PUTFIELD) || (seen == Const.GETFIELD) || (seen == Const.PUTSTATIC)
                    || (seen == Const.GETSTATIC) || OpcodeUtils.isAStore(seen)) {
                // Don't check parameters that are aliased
                if (stack.getStackDepth() > 0) {
                    OpcodeStack.Item itm = stack.getStackItem(0);
                    int reg = itm.getRegisterNumber();
                    int parm = reg;
                    if (!methodIsStatic) {
                        parm--;
                    }
                    if ((parm >= 0) && (parm < parmCount)) {
                        parameterDefiners.remove(Integer.valueOf(reg));
                    }
                } else {
                    parameterDefiners.clear();
                }

                if ((seen == Const.GETFIELD) || (seen == Const.PUTFIELD)) {
                    if (stack.getStackDepth() > 1) {
                        OpcodeStack.Item itm = stack.getStackItem(1);
                        int reg = itm.getRegisterNumber();
                        int parm = reg;
                        if (!methodIsStatic) {
                            parm--;
                        }
                        if ((parm >= 0) && (parm < parmCount)) {
                            parameterDefiners.remove(Integer.valueOf(reg));
                        }
                    } else {
                        parameterDefiners.clear();
                    }
                }

            } else if (OpcodeUtils.isALoad(seen)) {
                int reg = RegisterUtils.getALoadReg(this, seen);

                int parm = reg;
                if (!methodIsStatic) {
                    parm--;
                }
                if ((parm >= 0) && (parm < parmCount)) {
                    usedParameters.set(reg);
                }
            } else if (seen == Const.AASTORE) {
                // Don't check parameters that are stored in
                if (stack.getStackDepth() >= 3) {
                    OpcodeStack.Item itm = stack.getStackItem(0);
                    int reg = itm.getRegisterNumber();
                    int parm = reg;
                    if (!methodIsStatic) {
                        parm--;
                    }
                    if ((parm >= 0) && (parm < parmCount)) {
                        parameterDefiners.remove(Integer.valueOf(reg));
                    }
                } else {
                    parameterDefiners.clear();
                }
            } else if (seen == Const.ARETURN) {
                if (stack.getStackDepth() >= 1) {
                    OpcodeStack.Item item = stack.getStackItem(0);
                    int reg = item.getRegisterNumber();
                    int parm = reg;
                    if (!methodIsStatic) {
                        parm--;
                    }

                    if ((parm >= 0) && (parm < parmCount)) {
                        parameterDefiners.remove(Integer.valueOf(reg));
                    }
                } else {
                    parameterDefiners.clear();
                }
            }

            if (parameterDefiners.isEmpty()) {
                throw new StopOpcodeParsingException();
            }
        } finally {
            stack.sawOpcode(this, seen);
        }
    }
1004364
@Override
    public void sawOpcode(int seen) {
        try {
            stack.precomputation(this);

            if ((seen == Const.ARETURN) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item itm = stack.getStackItem(0);
                if (!itm.isNull()) {
                    returnTypes.put(itm.getJavaClass(), Integer.valueOf(getPC()));
                }
            }
        } catch (ClassNotFoundException cnfe) {
            bugReporter.reportMissingClass(cnfe);
        } finally {
            stack.sawOpcode(this, seen);
        }
    }
1139135
@Override
    public void sawOpcode(int seen) {
        try {
            stack.precomputation(this);

            switch (state) {
                case SAW_NOTHING:
                    if (seen == Const.ICONST_0) {
                        state = State.SAW_CONSTANT_0;
                    } else if ((seen >= Const.ICONST_1) && (seen <= Const.ICONST_5)) {
                        state = State.SAW_CONSTANT;
                    } else if ((seen == Const.LDC) || (seen == Const.LDC_W)) {
                        Constant c = getConstantRefOperand();
                        if (c instanceof ConstantInteger) {
                            state = State.SAW_CONSTANT;
                        }
                    }
                break;

                case SAW_CONSTANT_0:
                case SAW_CONSTANT:
                    switch (seen) {
                        case Const.AALOAD:
                            if ("main".equals(this.getMethodName())) {
                                break;
                            }
                            //$FALL-THROUGH$
                        case Const.IALOAD:
                        case Const.LALOAD:
                        case Const.FALOAD:
                        case Const.DALOAD:
                            // case BALOAD: byte and char indexing seems prevalent, and
                            // case CALOAD: usually harmless so ignore
                        case Const.SALOAD:
                            if (stack.getStackDepth() > 1) {
                                OpcodeStack.Item item = stack.getStackItem(1);
                                if (!isArrayFromUbiquitousMethod(item)) {
                                    if (state == State.SAW_CONSTANT_0) {
                                        iConst0Looped.set(getPC());
                                    } else {
                                        bugReporter.reportBug(new BugInstance(this, BugType.CLI_CONSTANT_LIST_INDEX.name(), NORMAL_PRIORITY).addClass(this)
                                                .addMethod(this).addSourceLine(this));
                                    }
                                }
                            }
                        break;

                        case Const.INVOKEVIRTUAL:
                            if (Values.SLASHED_JAVA_UTIL_LIST.equals(getClassConstantOperand())) {
                                String methodName = getNameConstantOperand();
                                if ("get".equals(methodName)) {
                                    if (state == State.SAW_CONSTANT_0) {
                                        iConst0Looped.set(getPC());
                                    } else {
                                        bugReporter.reportBug(new BugInstance(this, BugType.CLI_CONSTANT_LIST_INDEX.name(), NORMAL_PRIORITY).addClass(this)
                                                .addMethod(this).addSourceLine(this));
                                    }
                                }
                            }
                        break;
                        default:
                        break;
                    }
                    state = State.SAW_NOTHING;
                break;
            }

            if (((seen >= Const.IFEQ) && (seen <= Const.GOTO)) || (seen == Const.GOTO_W)) {
                int branchTarget = this.getBranchTarget();
                for (int bugPC = iConst0Looped.nextSetBit(0); bugPC >= 0; bugPC = iConst0Looped.nextSetBit(bugPC + 1)) {
                    if (branchTarget < bugPC) {
                        if ((bugPC - branchTarget) < max_iConst0LoopDistance) {
                            bugReporter.reportBug(new BugInstance(this, BugType.CLI_CONSTANT_LIST_INDEX.name(), NORMAL_PRIORITY).addClass(this).addMethod(this)
                                    .addSourceLine(this, bugPC));
                        }
                        iConst0Looped.clear(bugPC);
                    }
                }
            }
        } finally {
            stack.sawOpcode(this, seen);
        }
    }
796411
@Override
    public void sawOpcode(int seen) {
        Integer size = null;
        boolean sizeSet = false;
        try {
            stack.precomputation(this);

            switch (seen) {
                case Const.ICONST_0:
                case Const.ICONST_1:
                case Const.ICONST_2:
                case Const.ICONST_3:
                case Const.ICONST_4:
                case Const.ICONST_5:
                    size = Integer.valueOf(seen - Const.ICONST_0);
                    sizeSet = true;
                break;

                case Const.ILOAD:
                case Const.ILOAD_0:
                case Const.ILOAD_1:
                case Const.ILOAD_2:
                case Const.ILOAD_3: {
                    int reg = RegisterUtils.getLoadReg(this, seen);
                    if (modifyRegs.get(reg)) {
                        modifyRegs.clear(reg);
                        sizeSet = true;
                    }
                }
                break;

                case Const.BIPUSH:
                case Const.SIPUSH:
                    size = Integer.valueOf(getIntConstant());
                    sizeSet = true;
                break;

                case Const.IINC:
                    modifyRegs.set(getRegisterOperand());
                break;

                case Const.IADD:
                case Const.ISUB:
                case Const.IMUL:
                case Const.IDIV:
                case Const.F2I:
                case Const.D2I:
                case Const.L2I:
                    sizeSet = true;
                break;

                case Const.ISTORE:
                case Const.ISTORE_0:
                case Const.ISTORE_1:
                case Const.ISTORE_2:
                case Const.ISTORE_3:
                    if (stack.getStackDepth() > 0) {
                        OpcodeStack.Item item = stack.getStackItem(0);
                        if (item.getUserValue() == null) {
                            modifyRegs.set(getRegisterOperand());
                        }
                    }
                break;

                case Const.LDC:
                    Constant c = getConstantRefOperand();
                    if (c instanceof ConstantInteger) {
                        size = Integer.valueOf(((ConstantInteger) c).getBytes());
                        sizeSet = true;
                    }
                break;

                case Const.NEWARRAY:
                case Const.ANEWARRAY:
                    if (stack.getStackDepth() >= 1) {
                        OpcodeStack.Item item = stack.getStackItem(0);
                        size = (Integer) item.getUserValue();
                        sizeSet = true;
                    }
                break;

                case Const.IASTORE:
                case Const.LASTORE:
                case Const.FASTORE:
                case Const.DASTORE:
                case Const.AASTORE:
                case Const.BASTORE:
                case Const.CASTORE:
                case Const.SASTORE:
                    processArrayStore();
                break;

                case Const.IALOAD:
                case Const.LALOAD:
                case Const.FALOAD:
                case Const.DALOAD:
                case Const.AALOAD:
                case Const.BALOAD:
                case Const.CALOAD:
                case Const.SALOAD:
                    processArrayLoad();
                break;

                case Const.ASTORE_0:
                case Const.ASTORE_1:
                case Const.ASTORE_2:
                case Const.ASTORE_3:
                case Const.ASTORE:
                    if (stack.getStackDepth() > 0) {
                        OpcodeStack.Item value = stack.getStackItem(0);
                        if (!value.isNull()) {
                            initializedRegs.set(getRegisterOperand());
                        }
                    } else {
                        initializedRegs.set(getRegisterOperand());
                    }
                break;

                case Const.IFEQ:
                case Const.IFNE:
                case Const.IFLT:
                case Const.IFGE:
                case Const.IFGT:
                case Const.IFLE:
                case Const.IF_ICMPEQ:
                case Const.IF_ICMPNE:
                case Const.IF_ICMPLT:
                case Const.IF_ICMPGE:
                case Const.IF_ICMPGT:
                case Const.IF_ICMPLE:
                case Const.IF_ACMPEQ:
                case Const.IF_ACMPNE:
                case Const.GOTO:
                case Const.GOTO_W:
                    int branchTarget = getBranchTarget();
                    Iterator<Map.Entry<Integer, Integer>> it = nullStoreToLocation.entrySet().iterator();
                    while (it.hasNext()) {
                        Map.Entry<Integer, Integer> entry = it.next();
                        int pc = entry.getValue().intValue();
                        if ((branchTarget < pc) && initializedRegs.get(entry.getKey().intValue())) {
                            it.remove();
                        }
                    }
                break;
            }

        } finally {
            stack.sawOpcode(this, seen);
            if (sizeSet && (stack.getStackDepth() >= 1)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                item.setUserValue(size);
            }
        }
    }
388071
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "SF_SWITCH_FALLTHROUGH", justification = "This fall-through is deliberate and documented")
    @Override
    public void sawOpcode(int seen) {
        Object userObject = null;

        // saving and restoring the userobject of the top item, works around a
        // bug in Findbugs proper
        if (stack.getStackDepth() > 0) {
            userObject = stack.getStackItem(0).getUserValue();
        }
        stack.precomputation(this);
        if (stack.getStackDepth() > 0) {
            stack.getStackItem(0).setUserValue(userObject);
            userObject = null;
        }

        try {
            switch (seen) {
                case Const.INVOKESPECIAL:
                userObject = sawInvokeSpecial(userObject);
                break;
                case Const.INVOKEINTERFACE:
                case Const.INVOKEVIRTUAL:
                sawInvokeInterfaceVirtual();
                break;
                case Const.INVOKESTATIC:
                userObject = sawInvokeStatic(userObject);
                //$FALL-THROUGH$
                case Const.INVOKEDYNAMIC:
                processMethodParms();
                break;
                case Const.ARETURN:
                if (stack.getStackDepth() > 0) {
                    OpcodeStack.Item item = stack.getStackItem(0);
                    clearUserValue(item);
                } else {
                    // bad findbugs bug, which clears the stack after an ALOAD, in some cases
                    int prevOp = getPrevOpcode(1);
                    if (OpcodeUtils.isALoad(prevOp)) {
                        localSpecialObjects.clear();
                    }
                }
                break;

                case Const.ASTORE_0:
                case Const.ASTORE_1:
                case Const.ASTORE_2:
                case Const.ASTORE_3:
                case Const.ASTORE:
                sawAStore(seen);
                break;

                case Const.ALOAD_0:
                case Const.ALOAD_1:
                case Const.ALOAD_2:
                case Const.ALOAD_3:
                case Const.ALOAD:
                userObject = sawLoad(seen, userObject);
                break;

                case Const.AASTORE:
                if (stack.getStackDepth() >= 3) {
                    OpcodeStack.Item item = stack.getStackItem(0);
                    clearUserValue(item);
                }
                break;

                case Const.PUTFIELD:
                sawPutField();
                break;

                case Const.GETFIELD:
                userObject = sawGetField(userObject);
                break;

                case Const.PUTSTATIC:
                sawPutStatic();
                break;

                case Const.GETSTATIC:
                userObject = sawGetStatic(userObject);
                break;

                case Const.GOTO:
                case Const.IFNULL:
                case Const.IFNONNULL:
                if (stack.getStackDepth() > 0) {
                    OpcodeStack.Item item = stack.getStackItem(0);
                    Object uo = item.getUserValue();
                    if ((uo != null) && !(uo instanceof Boolean)) {
                        clearUserValue(item);
                    }
                    sawTernary = true;
                }
                break;
            default:
                break;
            }
        } finally {
            TernaryPatcher.pre(stack, seen);
            stack.sawOpcode(this, seen);
            TernaryPatcher.post(stack, seen);
            if ((userObject != null) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                item.setUserValue(userObject);
            }
            if (sawTernary) {
                handleTernary(seen);
            }
        }
    }
384726
@Override
    public void sawOpcode(int seen) {
        try {
            stack.precomputation(this);

            if (unsafeCallOccurred && OpcodeUtils.isAStore(seen)) {
                int storeReg = RegisterUtils.getAStoreReg(this, seen);
                if (storeReg >= 0) {
                    unsafeAliases.set(storeReg);
                }
            }

            if ((seen == Const.INVOKEVIRTUAL) || (seen == Const.INVOKESPECIAL) || (seen == Const.INVOKEINTERFACE) || (seen == Const.INVOKEDYNAMIC)) {
                String methodSig = getSigConstantOperand();

                MethodInfo mi = Statistics.getStatistics().getMethodStatistics(getClassConstantOperand(), getNameConstantOperand(), methodSig);
                if (mi.getModifiesState()) {
                    unsafeCallOccurred = true;
                } else {
                    if (!Values.SIG_VOID.equals(SignatureUtils.getReturnSignature(methodSig))) {
                        int parmCount = SignatureUtils.getNumParameters(methodSig);
                        if (stack.getStackDepth() > parmCount) {
                            OpcodeStack.Item itm = stack.getStackItem(parmCount);
                            unsafeCallOccurred = unsafeAliases.get(itm.getRegisterNumber());
                        } else {
                            unsafeCallOccurred = false;
                        }
                    } else {
                        unsafeCallOccurred = false;
                    }
                }
            } else if (seen == Const.INVOKESTATIC) {
                unsafeCallOccurred = getDottedClassConstantOperand().equals(this.getClassContext().getJavaClass().getClassName());
            } else if (((seen >= Const.IFEQ) && (seen <= Const.GOTO)) || (seen == Const.GOTO_W)) {
                Integer from = Integer.valueOf(getPC());
                Integer to = Integer.valueOf(getBranchTarget());
                branchInfo.put(from, to);
                unsafeCallOccurred = false;
            } else {
                unsafeCallOccurred = false;
            }

            if (seen == Const.MONITORENTER) {
                if (syncPC < 0) {
                    syncPC = getPC();
                    if (stack.getStackDepth() > 0) {
                        OpcodeStack.Item itm = stack.getStackItem(0);
                        int monitorReg = itm.getRegisterNumber();
                        if (monitorReg >= 0) {
                            unsafeAliases.set(monitorReg);
                        }
                    }
                }
            } else if (seen == Const.MONITOREXIT) {
                syncPC = -1;
            } else if (syncPC >= 0) {
                processSyncBlockInstruction(seen);
            }
        } finally {
            stack.sawOpcode(this, seen);
        }
    }
635270
@Override
    public void sawOpcode(int seen) {
        boolean processed = false;
        Iterator<IfStatement> isi = ifStatements.iterator();
        while (isi.hasNext()) {
            IfStatement.Action action = isi.next().processOpcode(this, bugReporter, seen);
            if (action == IfStatement.Action.REMOVE_ACTION) {
                isi.remove();
            } else if (action == IfStatement.Action.PROCESSED_ACTION) {
                processed = true;
            }
        }

        if (!processed && OpcodeUtils.isALoad(seen)) {
            IfStatement is = new IfStatement(this, seen);
            ifStatements.add(is);
        }
    }
311899
@Override
    public void sawOpcode(int seen) {
        try {
            switch (state) {
                case SAW_NOTHING:
                    sawOpcodeAfterNothing(seen);
                break;

                case SAW_EQUALS:
                    sawOpcodeAfterEquals(seen);
                break;

                case SAW_IFEQ:
                    sawOpcodeAfterBranch(seen);
                break;
            }

            processLoad(seen);
            processLoop(seen);
        } finally {
            stack.sawOpcode(this, seen);
        }

    }
958838
@Override
    public void sawOpcode(int seen) {
        try {
            if ((seen == Const.ATHROW) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                if ("Ljava/lang/CloneNotSupportedException;".equals(item.getSignature())) {
                    throwsCNFE = true;
                }
            }
        } finally {
            stack.sawOpcode(this, seen);
        }
    }
1230272
@Override
    public void sawOpcode(int seen) {
        ImmutabilityType imType = null;

        try {
            stack.precomputation(this);

            switch (seen) {
                case Const.INVOKESTATIC:
                case Const.INVOKEINTERFACE:
                case Const.INVOKESPECIAL:
                case Const.INVOKEVIRTUAL: {
                    String className = getClassConstantOperand();
                    String methodName = getNameConstantOperand();
                    String signature = getSigConstantOperand();

                    MethodInfo mi = Statistics.getStatistics().getMethodStatistics(className, methodName, signature);
                    imType = mi.getImmutabilityType();

                    if (seen == Const.INVOKEINTERFACE) {
                        Integer collectionOffset = MODIFYING_METHODS.get(new QMethod(methodName, signature));
                        if ((collectionOffset != null) && CollectionUtils.isListSetMap(className) && (stack.getStackDepth() > collectionOffset.intValue())) {
                            OpcodeStack.Item item = stack.getStackItem(collectionOffset.intValue());
                            ImmutabilityType type = (ImmutabilityType) item.getUserValue();

                            if ((type == ImmutabilityType.IMMUTABLE)
                                    || ((type == ImmutabilityType.POSSIBLY_IMMUTABLE) && (reportedType != ImmutabilityType.POSSIBLY_IMMUTABLE))) {
                                bugReporter.reportBug(new BugInstance(this, BugType.MUC_MODIFYING_UNMODIFIABLE_COLLECTION.name(),
                                        (type == ImmutabilityType.IMMUTABLE) ? HIGH_PRIORITY : NORMAL_PRIORITY).addClass(this).addMethod(this)
                                                .addSourceLine(this));
                                if (type == ImmutabilityType.IMMUTABLE) {
                                    throw new StopOpcodeParsingException();
                                }

                                reportedType = type;
                            }
                        }
                    }
                }
                break;
                default:
                break;
            }
        } catch (ClassNotFoundException cnfe) {
            bugReporter.reportMissingClass(cnfe);
        } finally {
            stack.sawOpcode(this, seen);
            if ((imType != null) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                item.setUserValue(imType);
            }

        }
    }
194587
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "CLI_CONSTANT_LIST_INDEX", justification = "Constrained by FindBugs API")
    @Override
    public void sawOpcode(int seen) {

        PSCUserValue userValue = null;
        boolean sawAlloc = false;

        try {
            stack.precomputation(this);

            switch (seen) {
                case Const.INVOKESPECIAL:
                    String clsName = getClassConstantOperand();
                    if (PRESIZEABLE_COLLECTIONS.contains(clsName)) {
                        String methodName = getNameConstantOperand();
                        if (Values.CONSTRUCTOR.equals(methodName)) {
                            String signature = getSigConstantOperand();
                            if (SignatureBuilder.SIG_VOID_TO_VOID.equals(signature)) {
                                userValue = new PSCUserValue(Integer.valueOf(nextAllocNumber++));
                                sawAlloc = true;
                            } else if (guavaOnPath && (stack.getStackDepth() > 0)) {
                                FQMethod fqMethod = new FQMethod(clsName, methodName, signature);
                                if (HASHMAP_SIZED_CTOR.equals(fqMethod) || HASHSET_SIZED_CTOR.equals(fqMethod)) {
                                    OpcodeStack.Item itm = stack.getStackItem(0);
                                    XMethod xm = itm.getReturnValueOf();
                                    if ((xm != null) && "size".equals(xm.getMethodDescriptor().getName())) {
                                        bugReporter.reportBug(new BugInstance(this, BugType.PSC_SUBOPTIMAL_COLLECTION_SIZING.name(), NORMAL_PRIORITY)
                                                .addClass(this).addMethod(this).addSourceLine(this));
                                    }
                                }
                            }
                        }
                    }
                break;

                case Const.INVOKEINTERFACE:
                    String methodName = getNameConstantOperand();

                    if (ITERATOR_METHOD.equals(new QMethod(methodName, getSigConstantOperand()))) {
                        if (stack.getStackDepth() > 0) {
                            OpcodeStack.Item itm = stack.getStackItem(0);
                            userValue = isSizedSource(itm);
                        }
                    } else if (ITERATOR_HASNEXT.equals(new FQMethod(getClassConstantOperand(), methodName, getSigConstantOperand()))) {
                        if (stack.getStackDepth() > 0) {
                            OpcodeStack.Item itm = stack.getStackItem(0);
                            userValue = (PSCUserValue) itm.getUserValue();
                        }
                    } else if ("add".equals(methodName) || "addAll".equals(methodName)) {
                        String signature = getSigConstantOperand();
                        int numArguments = SignatureUtils.getNumParameters(signature);
                        if ((numArguments == 1) && (stack.getStackDepth() > 1)) {
                            OpcodeStack.Item item = stack.getStackItem(1);
                            PSCUserValue uv = (PSCUserValue) item.getUserValue();
                            if (uv != null) {
                                Integer allocNum = uv.getAllocationNumber();
                                if (allocNum != null) {
                                    if ("addAll".equals(methodName)) {
                                        allocToAddPCs.remove(allocNum);
                                    } else {
                                        List<Integer> lines = allocToAddPCs.get(allocNum);
                                        if (lines == null) {
                                            lines = new ArrayList<>();
                                            allocToAddPCs.put(allocNum, lines);
                                        }
                                        lines.add(Integer.valueOf(getPC()));
                                    }
                                }
                            }
                        }
                    } else if ("put".equals(methodName) || "putAll".equals(methodName)) {
                        String signature = getSigConstantOperand();
                        int numArguments = SignatureUtils.getNumParameters(signature);
                        if ((numArguments == 2) && (stack.getStackDepth() > 2)) {
                            OpcodeStack.Item item = stack.getStackItem(2);
                            PSCUserValue uv = (PSCUserValue) item.getUserValue();
                            if (uv != null) {
                                Integer allocNum = uv.getAllocationNumber();
                                if (allocNum != null) {
                                    if ("putAll".equals(methodName)) {
                                        allocToAddPCs.remove(allocNum);
                                    } else {
                                        List<Integer> lines = allocToAddPCs.get(allocNum);
                                        if (lines == null) {
                                            lines = new ArrayList<>();
                                            allocToAddPCs.put(allocNum, lines);
                                        }
                                        lines.add(Integer.valueOf(getPC()));
                                    }
                                }
                            }
                        }
                    }
                break;

                case Const.INVOKESTATIC:
                    FQMethod fqm = new FQMethod(getClassConstantOperand(), getNameConstantOperand(), getSigConstantOperand());
                    if (STATIC_COLLECTION_FACTORIES.contains(fqm)) {
                        userValue = new PSCUserValue(Integer.valueOf(nextAllocNumber++));
                        sawAlloc = true;
                    }
                break;

                case Const.LOOKUPSWITCH:
                case Const.TABLESWITCH:
                    int[] offsets = getSwitchOffsets();
                    if (offsets.length >= 2) {
                        int pc = getPC();
                        int thisOffset = pc + offsets[0];
                        for (int o = 0; o < (offsets.length - 1); o++) {
                            int nextOffset = offsets[o + 1] + pc;
                            CodeRange db = new CodeRange(thisOffset, nextOffset, false);
                            optionalRanges.add(db);
                            thisOffset = nextOffset;
                        }
                    }
                break;

                case Const.IFEQ:
                case Const.IFNE:
                case Const.IFLT:
                case Const.IFLE:
                case Const.IF_ICMPEQ:
                case Const.IF_ICMPNE:
                case Const.IF_ICMPLT:
                case Const.IF_ICMPGE:
                case Const.IF_ICMPGT:
                case Const.IF_ICMPLE:
                case Const.IF_ACMPEQ:
                case Const.IF_ACMPNE:
                case Const.GOTO:
                case Const.GOTO_W:
                    if (getBranchOffset() < 0) {

                        if (branchBasedOnUnsizedObject(seen)) {
                            break;
                        }

                        int target = getBranchTarget();
                        Iterator<Map.Entry<Integer, List<Integer>>> it = allocToAddPCs.entrySet().iterator();
                        while (it.hasNext()) {
                            Map.Entry<Integer, List<Integer>> entry = it.next();
                            Integer allocLoc = allocLocation.get(entry.getKey());
                            if ((allocLoc != null) && (allocLoc.intValue() < target)) {
                                List<Integer> pcs = entry.getValue();
                                for (int pc : pcs) {
                                    if (pc > target) {
                                        if (hasSinglePossiblySizedBranch(allocLoc.intValue(), pc)) {
                                            bugReporter.reportBug(new BugInstance(this, BugType.PSC_PRESIZE_COLLECTIONS.name(), NORMAL_PRIORITY).addClass(this)
                                                    .addMethod(this).addSourceLine(this, pc));
                                            it.remove();
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    } else {
                        CodeRange db = new CodeRange(getPC(), getBranchTarget(), !branchBasedOnUnsizedObject(seen));
                        optionalRanges.add(db);
                    }
                break;

                case Const.IFNULL:
                case Const.IFNONNULL:
                case Const.IFGE:
                case Const.IFGT:
                    // null check and >, >= branches are hard to presize
                    if (getBranchOffset() > 0) {
                        CodeRange db = new CodeRange(getPC(), getBranchTarget(), false);
                        optionalRanges.add(db);
                    }
                break;

                case Const.ASTORE:
                case Const.ASTORE_0:
                case Const.ASTORE_1:
                case Const.ASTORE_2:
                case Const.ASTORE_3: {
                    if (stack.getStackDepth() > 0) {
                        PSCUserValue uv = (PSCUserValue) stack.getStackItem(0).getUserValue();
                        if (uv != null) {
                            storeToUserValue.put(getRegisterOperand(), uv);
                        }
                    }
                }
                break;

                case Const.ALOAD:
                case Const.ALOAD_0:
                case Const.ALOAD_1:
                case Const.ALOAD_2:
                case Const.ALOAD_3: {
                    userValue = storeToUserValue.get(getRegisterOperand());
                }
                break;

                case Const.PUTFIELD: {
                    if (stack.getStackDepth() > 0) {
                        PSCUserValue uv = (PSCUserValue) stack.getStackItem(0).getUserValue();
                        if (uv != null) {
                            storeToUserValue.put(getNameConstantOperand(), uv);
                        }
                    }
                }
                break;

                case Const.GETFIELD: {
                    userValue = storeToUserValue.get(getNameConstantOperand());
                }
                break;

            }
        } finally {
            stack.sawOpcode(this, seen);
            if ((userValue != null) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                item.setUserValue(userValue);
                if (sawAlloc) {
                    allocLocation.put(userValue.getAllocationNumber(), Integer.valueOf(getPC()));
                }
            }
        }
    }
42718
@Override
    public void sawOpcode(int seen) {
        try {
            stack.precomputation(this);

            if (seen == Const.INVOKEVIRTUAL) {
                String clsName = getClassConstantOperand();
                if ("java/io/ObjectOutputStream".equals(clsName)) {
                    String name = getNameConstantOperand();
                    if ("writeObject".equals(name) && (stack.getStackDepth() > 0)) {
                        OpcodeStack.Item item = stack.getStackItem(0);
                        JavaClass cls = item.getJavaClass();

                        if ((cls != null) && (cls.getClassName().indexOf(Values.INNER_CLASS_SEPARATOR) >= 0) && hasOuterClassSyntheticReference(cls)) {
                            bugReporter.reportBug(new BugInstance(this, BugType.PUS_POSSIBLE_UNSUSPECTED_SERIALIZATION.name(), NORMAL_PRIORITY).addClass(this)
                                    .addMethod(this).addSourceLine(this));
                        }
                    }
                }
            }
        } catch (ClassNotFoundException cnfe) {
            bugReporter.reportMissingClass(cnfe);
        } finally {
            stack.sawOpcode(this, seen);
        }
    }
17166
@Override
    public void sawOpcode(int seen) {
        String attributeName = null;
        boolean sawGetAttribute = false;
        try {
            stack.precomputation(this);

            if (seen == Const.INVOKEINTERFACE) {
                String clsName = getClassConstantOperand();
                if ("javax/servlet/http/HttpSession".equals(clsName)) {
                    String methodName = getNameConstantOperand();
                    if ("getAttribute".equals(methodName)) {
                        if (stack.getStackDepth() > 0) {
                            OpcodeStack.Item item = stack.getStackItem(0);
                            Object con = item.getConstant();
                            if (con instanceof String) {
                                attributeName = (String) con;
                                sawGetAttribute = true;
                            }
                        }
                    } else if ("setAttribute".equals(methodName) && (stack.getStackDepth() > 1)) {
                        OpcodeStack.Item item = stack.getStackItem(1);
                        Object con = item.getConstant();
                        if (con instanceof String) {
                            attributeName = (String) con;
                            changedAttributes.remove(attributeName);
                        }
                    }
                }
            } else if (OpcodeUtils.isALoad(seen)) {
                int reg = RegisterUtils.getALoadReg(this, seen);
                attributeName = savedAttributes.get(Integer.valueOf(reg));
                sawGetAttribute = attributeName != null;
            } else if ((((seen >= Const.ASTORE_0) && (seen <= Const.ASTORE_3)) || (seen == Const.ASTORE)) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                attributeName = (String) item.getUserValue();
                int reg = RegisterUtils.getAStoreReg(this, seen);
                savedAttributes.put(Integer.valueOf(reg), attributeName);
            }

            if ((seen == Const.INVOKEINTERFACE) || (seen == Const.INVOKEVIRTUAL)) {
                String methodName = getNameConstantOperand();
                Matcher m = modifyingNames.matcher(methodName);
                if (m.matches()) {
                    String signature = getSigConstantOperand();
                    int numArgs = SignatureUtils.getNumParameters(signature);
                    if (stack.getStackDepth() > numArgs) {
                        OpcodeStack.Item item = stack.getStackItem(numArgs);
                        attributeName = (String) item.getUserValue();
                        if (attributeName != null) {
                            changedAttributes.put(attributeName, Integer.valueOf(getPC()));
                        }
                    }
                }
            } else if ((seen >= Const.IASTORE) && (seen <= Const.SASTORE) && (stack.getStackDepth() > 2)) {
                OpcodeStack.Item item = stack.getStackItem(2);
                attributeName = (String) item.getUserValue();
                if (attributeName != null) {
                    changedAttributes.put(attributeName, Integer.valueOf(getPC()));
                }
            }
        } finally {
            TernaryPatcher.pre(stack, seen);
            stack.sawOpcode(this, seen);
            TernaryPatcher.post(stack, seen);
            if (sawGetAttribute && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                item.setUserValue(attributeName);
            }
        }
    }