VisibleForTesting
503036
Optional<String> writeSummary(DistributionSummary summary) {
        summary.takeSnapshot();
        return Optional.of(writeDocument(summary, builder -> {
            builder.append(",\"count\":").append(summary.count());
            builder.append(",\"sum\":").append(summary.totalAmount());
            builder.append(",\"mean\":").append(summary.mean());
            builder.append(",\"max\":").append(summary.max());
        }));
    }
735142
@Override
  public MethodVisitor visitMethod(
      final int access,
      final String name,
      final String desc,
      final String signature,
      final String[] exceptions) {
    MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
    return new CodeSizeEvaluator(mv) {
      @Override
      public void visitEnd() {
        super.visitEnd();
        if (getMaxSize() > 64 * 1024) {
          state = State.FAIL_TOO_LONG;
          message = "the method " + name + " was too long.";
        }
      }
    };
  }
152718
@Override
    public void sawOpcode(int seen) {
        try {

            stack.precomputation(this);

            if ((seen == Const.ARETURN) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                if (item.isNull()) {
                    bugReporter.reportBug(new BugInstance(this, BugType.TBP_TRISTATE_BOOLEAN_PATTERN.name(), NORMAL_PRIORITY).addClass(this).addMethod(this)
                            .addSourceLine(this));
                    throw new StopOpcodeParsingException();
                }
            }
        } finally {
            stack.sawOpcode(this, seen);
        }
    }
600806
@Override
    public void sawOpcode(int seen) {
        UserObject uo = null;
        try {
            stack.precomputation(this);

            int pc = getPC();
            if (tryBlocks.get(pc)) {
                ScopeBlock sb = new ScopeBlock(pc, findCatchHandlerFor(pc));
                sb.setTry();
                rootScopeBlock.addChild(sb);
            }

            if (OpcodeUtils.isStore(seen)) {
                sawStore(seen, pc);
            } else if (OpcodeUtils.isLoad(seen)) {
                sawLoad(seen, pc);
            } else if ((seen == Const.INVOKEVIRTUAL) || (seen == Const.INVOKEINTERFACE)) {
                uo = sawInstanceCall(pc);
            } else if ((seen == Const.INVOKESTATIC) || (seen == Const.INVOKESPECIAL)) {
                uo = sawStaticCall();
            } else if (((seen >= Const.IFEQ) && (seen <= Const.GOTO)) || (seen == Const.IFNULL) || (seen == Const.IFNONNULL) || (seen == Const.GOTO_W)) {
                sawBranch(seen, pc);
            } else if (seen == Const.GETFIELD) {
                uo = sawGetField();
            } else if (seen == Const.PUTFIELD) {
                sawPutField(pc);
            } else if (seen == Const.IINC) {
                sawIINC(pc);
            } else if ((seen == Const.TABLESWITCH) || (seen == Const.LOOKUPSWITCH)) {
                sawSwitch(pc);
            } else if (seen == Const.MONITORENTER) {
                sawMonitorEnter(pc);
            } else if (seen == Const.MONITOREXIT) {
                sawMonitorExit(pc);
            }

            sawDup = seen == Const.DUP;
            sawNull = seen == Const.ACONST_NULL;
        } finally {
            TernaryPatcher.pre(stack, seen);
            stack.sawOpcode(this, seen);
            TernaryPatcher.post(stack, seen);
            if ((uo != null) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                item.setUserValue(uo);
            }
        }
    }
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);
        }
    }
311454
@Override
    public void sawOpcode(int seen) {
        if (isInitializer) {
            lookForCustomThreadFactoriesInConstructors(seen);
            return;
        }

        try {
            stack.precomputation(this);

            if ((seen == Const.INVOKEVIRTUAL) || (seen == Const.INVOKEINTERFACE)) {
                processInvoke();
            }
            // TODO Should not include private methods
            else if (seen == Const.ARETURN) {
                removeFieldsThatGetReturned();
            } else if (seen == Const.PUTFIELD) {
                XField f = getXFieldOperand();
                if (f != null) {
                    reportOverwrittenField(f);
                }
            } else if (seen == Const.IFNONNULL) {
                // indicates a null check, which means that we get an exemption
                // until the end of the branch
                OpcodeStack.Item nullCheckItem = stack.getStackItem(0);
                XField fieldWhichWasNullChecked = nullCheckItem.getXField();
                if (fieldWhichWasNullChecked != null) {
                    exemptExecutors.put(fieldWhichWasNullChecked, Integer.valueOf(getPC() + getBranchOffset()));
                }
            }
        } finally {
            stack.sawOpcode(this, seen);
        }
    }
629932
@Override
    public void sawOpcode(int seen) {
        try {
            stack.precomputation(this);

            if (seen == Const.INVOKEVIRTUAL) {
                String clsName = getClassConstantOperand();
                if ("java/util/Properties".equals(clsName)) {
                    String methodName = getNameConstantOperand();
                    if ("put".equals(methodName)) {
                        String sig = getSigConstantOperand();
                        if (SignatureBuilder.SIG_TWO_OBJECTS_TO_OBJECT.equals(sig) && (stack.getStackDepth() >= 3)) {
                            OpcodeStack.Item valueItem = stack.getStackItem(0);
                            String valueSig = valueItem.getSignature();
                            if (Values.SIG_JAVA_LANG_STRING.equals(valueSig)) {
                                bugReporter.reportBug(new BugInstance(this, BugType.IPU_IMPROPER_PROPERTIES_USE_SETPROPERTY.name(), LOW_PRIORITY).addClass(this)
                                        .addMethod(this).addSourceLine(this));
                            } else if (Values.SIG_JAVA_LANG_OBJECT.equals(valueSig)) {
                                bugReporter.reportBug(new BugInstance(this, BugType.IPU_IMPROPER_PROPERTIES_USE_SETPROPERTY.name(), NORMAL_PRIORITY)
                                        .addClass(this).addMethod(this).addSourceLine(this));
                            } else {
                                bugReporter.reportBug(new BugInstance(this, BugType.IPU_IMPROPER_PROPERTIES_USE.name(), NORMAL_PRIORITY).addClass(this)
                                        .addMethod(this).addSourceLine(this));
                            }
                        }
                    }
                }
            }
        } finally {
            stack.sawOpcode(this, seen);
        }
    }
863100
@Override
    public void sawOpcode(int seen) {
        try {
            stack.precomputation(this);

            int pc = getPC();
            CodeException ex = catchHandlerPCs.get(Integer.valueOf(pc));
            if (ex != null) {
                int endPC;
                if ((seen == Const.GOTO) || (seen == Const.GOTO_W)) {
                    endPC = this.getBranchTarget();
                } else {
                    endPC = Integer.MAX_VALUE;
                }
                ConstantPool pool = getConstantPool();
                ConstantClass ccls = (ConstantClass) pool.getConstant(ex.getCatchType());
                String catchSig = ccls.getBytes(pool);
                CatchInfo ci = new CatchInfo(ex.getHandlerPC(), endPC, catchSig);
                catchInfos.add(ci);
            }

            updateEndPCsOnCatchRegScope(catchInfos, pc, seen);
            removeFinishedCatchBlocks(catchInfos, pc);

            if (seen == Const.ATHROW) {
                processThrow();
            } else if ((seen == Const.IRETURN) && isBooleanMethod && !hasValidFalseReturn && (stack.getStackDepth() > 0)) {
                processBooleanReturn();
            }

        } finally {
            stack.sawOpcode(this, seen);
        }
    }
1230602
@Override
    public void sawOpcode(int seen) {
        Units unit = null;
        try {
            stack.precomputation(this);

            switch (seen) {
                case Const.INVOKEVIRTUAL:
                case Const.INVOKEINTERFACE:
                case Const.INVOKESTATIC:
                    unit = processInvoke();
                break;

                case Const.GETSTATIC:
                    String clsName = getClassConstantOperand();
                    if ("java/util/concurrent/TimeUnit".equals(clsName) || "edu/emory/matchcs/backport/java/util/concurrent/TimeUnit".equals(clsName)) {
                        unit = TIMEUNIT_TO_UNITS.get(getNameConstantOperand());
                    }
                break;

                case Const.L2I:
                case Const.I2L:
                    if (stack.getStackDepth() > 0) {
                        OpcodeStack.Item item = stack.getStackItem(0);
                        unit = (Units) item.getUserValue();
                    }
                break;

                case Const.IADD:
                case Const.ISUB:
                case Const.IMUL:
                case Const.IDIV:
                case Const.IREM:
                case Const.LADD:
                case Const.LSUB:
                case Const.LMUL:
                case Const.LDIV:
                case Const.LREM:
                    processArithmetic();
                break;

                default:
                break;
            }
        } finally {
            stack.sawOpcode(this, seen);
            if ((unit != null) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                item.setUserValue(unit);
            }
        }
    }
547114
@Override
    public void sawOpcode(int seen) {
        Integer tosIsSyncColReg = null;
        try {
            stack.precomputation(this);

            if (seen == Const.INVOKESPECIAL) {
                tosIsSyncColReg = checkConstructors();
            } else if (seen == Const.INVOKESTATIC) {
                tosIsSyncColReg = checkStaticCreations();
            } else if ((seen == Const.INVOKEVIRTUAL) || (seen == Const.INVOKEINTERFACE)) {
                tosIsSyncColReg = checkSelfReturningMethods();
            } else if (isAStore(seen)) {
                dealWithStoring(seen);
            } else if (isALoad(seen)) {
                int reg = RegisterUtils.getALoadReg(this, seen);
                RegisterInfo cri = suspectLocals.get(Integer.valueOf(reg));
                if ((cri != null) && !cri.getIgnore()) {
                    tosIsSyncColReg = Integer.valueOf(reg);
                }
            } else if (((seen == Const.PUTFIELD) || (seen == Const.ARETURN)) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                suspectLocals.remove(item.getUserValue());
            }

            if (!suspectLocals.isEmpty()) {
                if (isStandardInvoke(seen)) {
                    String sig = getSigConstantOperand();
                    int argCount = SignatureUtils.getNumParameters(sig);
                    if (stack.getStackDepth() >= argCount) {
                        for (int i = 0; i < argCount; i++) {
                            OpcodeStack.Item item = stack.getStackItem(i);
                            RegisterInfo cri = suspectLocals.get(item.getUserValue());
                            if (cri != null) {
                                if (SignatureUtils.similarPackages(SignatureUtils.getPackageName(SignatureUtils.stripSignature(getClassConstantOperand())),
                                        SignatureUtils.getPackageName(SignatureUtils.stripSignature(this.getClassName())), 2)) {
                                    cri.setPriority(LOW_PRIORITY);
                                } else {
                                    cri.setIgnore();
                                }
                            }
                        }
                    }
                } else if (seen == Const.MONITORENTER) {
                    // Assume if synchronized blocks are used then something
                    // tricky is going on.
                    // There is really no valid reason for this, other than
                    // folks who use
                    // synchronized blocks tend to know what's going on.
                    if (stack.getStackDepth() > 0) {
                        OpcodeStack.Item item = stack.getStackItem(0);
                        suspectLocals.remove(item.getUserValue());
                    }
                } else if ((seen == Const.AASTORE) && (stack.getStackDepth() > 0)) {
                    OpcodeStack.Item item = stack.getStackItem(0);
                    suspectLocals.remove(item.getUserValue());
                }
            }

            reportTroublesomeLocals();
        } finally {
            TernaryPatcher.pre(stack, seen);
            stack.sawOpcode(this, seen);
            TernaryPatcher.post(stack, seen);
            if ((tosIsSyncColReg != null) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                item.setUserValue(tosIsSyncColReg);
            }
        }
    }
191517
@Override
    public void sawOpcode(int seen) {
        // System.out.println(getPC() + " " + Const.getOpcodeName(seen) + " " + state);

        if (stack.getStackDepth() < stackDepth) {
            state = FormatState.NONE;
            stackDepth = 0;
            arguments = null;
        }
        if (seen == Const.ANEWARRAY && stack.getStackDepth() >= 2) {
            Object size = stack.getStackItem(0).getConstant();
            Object formatStr = stack.getStackItem(1).getConstant();
            if (size instanceof Integer && formatStr instanceof String) {
                arguments = new OpcodeStack.Item[(Integer) size];
                this.formatString = (String) formatStr;
                state = FormatState.READY_FOR_FORMAT;
                stackDepth = stack.getStackDepth();
            }
        } else if (state == FormatState.READY_FOR_FORMAT && seen == Const.DUP) {
            state = FormatState.EXPECTING_ASSIGNMENT;
        } else if (state == FormatState.EXPECTING_ASSIGNMENT && stack.getStackDepth() == stackDepth + 3 && seen == Const.AASTORE) {
            Object pos = stack.getStackItem(1).getConstant();
            OpcodeStack.Item value = stack.getStackItem(0);
            if (pos instanceof Integer) {
                int index = (Integer) pos;
                if (index >= 0 && index < arguments.length) {
                    arguments[index] = value;
                    state = FormatState.READY_FOR_FORMAT;
                } else {
                    state = FormatState.NONE;
                }
            } else {
                state = FormatState.NONE;
            }
        } else if (state == FormatState.READY_FOR_FORMAT
                && (seen == Const.INVOKESPECIAL || seen == Const.INVOKEVIRTUAL || seen == Const.INVOKESTATIC || seen == Const.INVOKEINTERFACE)
                && stack.getStackDepth() == stackDepth) {

            String cl = getClassConstantOperand();
            String nm = getNameConstantOperand();
            String sig = getSigConstantOperand();
            XMethod m = getXMethodOperand();
            if ((m == null || m.isVarArgs())
                    && sig.indexOf("Ljava/lang/String;[Ljava/lang/Object;)") >= 0
                    && ("java/util/Formatter".equals(cl) && "format".equals(nm) || "java/lang/String".equals(cl)
                            && "format".equals(nm) || "java/io/PrintStream".equals(cl) && "format".equals(nm)
                            || "java/io/PrintStream".equals(cl) && "printf".equals(nm) || cl.endsWith("Writer")
                            && "format".equals(nm) || cl.endsWith("Writer") && "printf".equals(nm)) || cl.endsWith("Logger")
                            && nm.endsWith("fmt")) {

                if (formatString.indexOf('\n') >= 0) {
                    bugReporter.reportBug(new BugInstance(this, "VA_FORMAT_STRING_USES_NEWLINE", NORMAL_PRIORITY)
                    .addClassAndMethod(this).addCalledMethod(this).addString(formatString)
                    .describe(StringAnnotation.FORMAT_STRING_ROLE).addSourceLine(this));
                }
            }

        }
    }
1147173
@Override
    public void visitAnnotation(Annotations arg0) {
        for (AnnotationEntry ae : arg0.getAnnotationEntries()) {
            boolean runtimeVisible = ae.isRuntimeVisible();
            String name = ClassName.fromFieldSignature(ae.getAnnotationType());
            if (name == null) {
                continue;
            }
            name = ClassName.toDottedClassName(name);
            Map<String, ElementValue> map = new HashMap<>();
            for (ElementValuePair ev : ae.getElementValuePairs()) {
                map.put(ev.getNameString(), ev.getValue());
            }
            visitAnnotation(name, map, runtimeVisible);

        }

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

            if (seen == Const.INVOKEINTERFACE) {
                KeyType type = isKeyAccessMethod(seen);
                if (type != null) {
                    int numParms = SignatureUtils.getNumParameters(getSigConstantOperand());
                    if (stack.getStackDepth() >= numParms) {
                        OpcodeStack.Item item = stack.getStackItem(numParms - 1);
                        String parmName = (String) item.getConstant();
                        if (parmName != null) {
                            String upperParmName = parmName.toUpperCase(Locale.getDefault());
                            Map<String, Map<String, List<SourceInfo>>> typeMap = parmInfo.get(KeyType.PARAMETER);
                            Map<String, List<SourceInfo>> parmCaseInfo = typeMap.get(upperParmName);
                            if (parmCaseInfo == null) {
                                parmCaseInfo = new HashMap<>();
                                typeMap.put(upperParmName, parmCaseInfo);
                            }

                            List<SourceInfo> annotations = parmCaseInfo.get(parmName);
                            if (annotations == null) {
                                annotations = new ArrayList<>();
                                parmCaseInfo.put(parmName, annotations);
                            }

                            annotations.add(new SourceInfo(getClassName(), getMethodName(), getMethodSig(), getMethod().isStatic(),
                                    SourceLineAnnotation.fromVisitedInstruction(getClassContext(), this, getPC())));
                        }
                    }
                }
            }
        } 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);
        }
    }
1272194
@Override
    public void sawOpcode(final int seen) {
        try {
            stack.precomputation(this);

            if (OpcodeUtils.isStandardInvoke(seen)) {
                String calledClass = getDottedClassConstantOperand();

                if (seen == Const.INVOKEINTERFACE) {
                    int parmCount = SignatureUtils.getNumParameters(this.getSigConstantOperand());
                    if (!countClassAccess(parmCount)) {
                        countClassAccess(calledClass);
                    }
                } else {
                    countClassAccess(calledClass);
                }
            } else if (seen == Const.PUTFIELD) {
                countClassAccess(1);
            } else if (seen == Const.GETFIELD) {
                countClassAccess(0);
            } else if ((seen == Const.PUTSTATIC) || (seen == Const.GETSTATIC)) {
                countClassAccess(getDottedClassConstantOperand());
            } else if ((seen == Const.ALOAD_0) && (!methodIsStatic)) {
                countClassAccess(clsName);
            }
        } finally {
            stack.sawOpcode(this, seen);
        }
    }
149108
@Override
    public void sawOpcode(int seen) {
        Comparable<?> regOrField = null;
        Comparable<?> uValue;
        boolean sawAlias = false;
        boolean sawLoad = false;

        try {
            stack.precomputation(this);

            int pc = getPC();
            Iterator<LoopInfo> it = loops.values().iterator();
            while (it.hasNext()) {
                LoopInfo loop = it.next();
                int endPC = loop.getEndPC();
                int loopPC = loop.getAddPC();
                if ((endPC - 3) <= pc) {
                    if (loopPC > 0) {
                        bugReporter.reportBug(new BugInstance(this, BugType.UAA_USE_ADD_ALL.name(), NORMAL_PRIORITY).addClass(this).addMethod(this)
                                .addSourceLine(this, loopPC));
                    }
                    it.remove();
                } else if ((endPC > pc) && (loopPC < (pc - 5)) && (loopPC > 0)) {
                    it.remove();
                }
            }

            if (seen == Const.INVOKEINTERFACE) {
                String methodName = getNameConstantOperand();
                String signature = getSigConstantOperand();
                if ("get".equals(methodName) && SignatureBuilder.SIG_INT_TO_OBJECT.equals(signature)) {
                    if (stack.getStackDepth() > 1) {
                        OpcodeStack.Item itm = stack.getStackItem(1);
                        int reg = isLocalCollection(itm);
                        if (reg >= 0) {
                            regOrField = Integer.valueOf(reg);
                            sawAlias = true;
                        } else {
                            String field = isFieldCollection(itm);
                            if (field != null) {
                                regOrField = field;
                                sawAlias = true;
                            }
                        }
                    }
                } else if ("keySet".equals(methodName) || "values".equals(methodName) || "iterator".equals(methodName) || "next".equals(methodName)
                        || "hasNext".equals(methodName)) {
                    if (stack.getStackDepth() > 0) {
                        OpcodeStack.Item itm = stack.getStackItem(0);
                        int reg = isLocalCollection(itm);
                        if (reg >= 0) {
                            regOrField = Integer.valueOf(reg);
                            sawAlias = true;
                        } else {
                            String field = isFieldCollection(itm);
                            if (field != null) {
                                regOrField = field;
                                sawAlias = true;
                            }
                        }
                    }
                } else if ("add".equals(methodName) && SignatureBuilder.SIG_OBJECT_TO_BOOLEAN.equals(signature) && (stack.getStackDepth() > 1)) {
                    OpcodeStack.Item colItem = stack.getStackItem(1);
                    OpcodeStack.Item valueItem = stack.getStackItem(0);
                    int reg = isLocalCollection(colItem);
                    if (reg >= 0) {
                        regOrField = Integer.valueOf(reg);
                        uValue = (Comparable<?>) valueItem.getUserValue();
                        if (uValue != null) {
                            LoopInfo loop = loops.get(uValue);
                            if ((loop != null) && loop.isInLoop(pc) && (this.getCodeByte(getNextPC()) == Const.POP)) {
                                loop.foundAdd(pc);
                            }
                        }
                    } else {
                        String field = isFieldCollection(colItem);
                        if (field != null) {
                            regOrField = field;
                            uValue = (Comparable<?>) valueItem.getUserValue();
                            if (uValue != null) {
                                LoopInfo loop = loops.get(uValue);
                                if ((loop != null) && loop.isInLoop(pc) && (this.getCodeByte(getNextPC()) == Const.POP)) {
                                    loop.foundAdd(pc);
                                }
                            }
                        }
                    }
                }
            } else if (OpcodeUtils.isIStore(seen) || OpcodeUtils.isAStore(seen)) {
                if (stack.getStackDepth() > 0) {
                    uValue = (Comparable<?>) stack.getStackItem(0).getUserValue();
                    userValues.put(Integer.valueOf(RegisterUtils.getStoreReg(this, seen)), uValue);
                }
            } else if (OpcodeUtils.isILoad(seen) || OpcodeUtils.isALoad(seen)) {
                sawLoad = true;
            } else if (seen == Const.IFEQ) {
                boolean loopFound = false;
                if ((stack.getStackDepth() > 0) && (getBranchOffset() > 0)) {
                    int gotoPos = getBranchTarget() - 3;
                    byte[] code = getCode().getCode();
                    if ((0x00FF & code[gotoPos]) == Const.GOTO) {
                        short brOffset = (short) (0x0FF & code[gotoPos + 1]);
                        brOffset <<= 8;
                        brOffset |= (0x0FF & code[gotoPos + 2]);
                        gotoPos += brOffset;
                        if (gotoPos < pc) {
                            OpcodeStack.Item itm = stack.getStackItem(0);
                            uValue = (Comparable<?>) itm.getUserValue();
                            if (uValue != null) {
                                loops.put(uValue, new LoopInfo(pc, getBranchTarget()));
                            }
                            loopFound = true;
                        }
                    }

                    if (!loopFound) {
                        removeLoop(pc);
                    }
                }
            } else if (isInstanceMethod && (seen == Const.PUTFIELD)) {
                if (stack.getStackDepth() > 1) {
                    OpcodeStack.Item item = stack.getStackItem(1);
                    if (item.getRegisterNumber() == 0) {
                        uValue = (Comparable<?>) stack.getStackItem(0).getUserValue();
                        userValues.put(getNameConstantOperand(), uValue);
                    }
                }
            } else if (isInstanceMethod && (seen == Const.GETFIELD)) {
                if (stack.getStackDepth() > 0) {
                    OpcodeStack.Item item = stack.getStackItem(0);
                    if (item.getRegisterNumber() == 0) {
                        sawLoad = true;
                    }
                }
            } else if (((seen > Const.IFEQ) && (seen <= Const.GOTO)) || (seen == Const.IFNULL) || (seen == Const.IFNONNULL)) {
                removeLoop(pc);
            } else if ((seen == Const.CHECKCAST) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item itm = stack.getStackItem(0);
                uValue = (Comparable<?>) itm.getUserValue();
                if (uValue != null) {
                    regOrField = uValue;
                    sawAlias = true;
                }
            }
        } catch (ClassNotFoundException cnfe) {
            bugReporter.reportMissingClass(cnfe);
        } finally {
            TernaryPatcher.pre(stack, seen);
            stack.sawOpcode(this, seen);
            TernaryPatcher.post(stack, seen);
            if (sawAlias) {
                if (stack.getStackDepth() > 0) {
                    OpcodeStack.Item itm = stack.getStackItem(0);
                    itm.setUserValue(regOrField);
                }
            } else if (sawLoad && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item itm = stack.getStackItem(0);
                int reg = itm.getRegisterNumber();
                if (reg >= 0) {
                    uValue = userValues.get(Integer.valueOf(reg));
                    itm.setUserValue(uValue);
                } else {
                    XField xField = itm.getXField();
                    if (xField != null) {
                        uValue = userValues.get(xField.getName());
                        itm.setUserValue(uValue);
                    }
                }
            }
        }
    }
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));
            }
        }
    }