VisibleForTesting
519549
Optional<String> writeTimer(Timer timer) {
        return Optional.of(writeDocument(timer, builder -> {
            builder.append(",\"count\":").append(timer.count());
            builder.append(",\"sum\":").append(timer.totalTime(getBaseTimeUnit()));
            builder.append(",\"mean\":").append(timer.mean(getBaseTimeUnit()));
            builder.append(",\"max\":").append(timer.max(getBaseTimeUnit()));
        }));
    }
505589
@Override
    @SuppressWarnings("unchecked")
    public void sawOpcode(int seen) {
        String ldcClassName = null;
        String seenMethodName = null;
        boolean seenToString = false;
        boolean seenFormatterLogger = false;
        int exMessageReg = -1;
        Integer arraySize = null;
        boolean simpleFormat = false;

        try {
            stack.precomputation(this);

            if ((seen == Const.LDC) || (seen == Const.LDC_W)) {
                Constant c = getConstantRefOperand();
                if (c instanceof ConstantClass) {
                    ConstantPool pool = getConstantPool();
                    ldcClassName = ((ConstantUtf8) pool.getConstant(((ConstantClass) c).getNameIndex())).getBytes();
                }
            } else if (seen == Const.INVOKESTATIC) {
                lookForSuspectClasses();

                String clsName = getClassConstantOperand();
                String methodName = getNameConstantOperand();
                if (Values.SLASHED_JAVA_LANG_STRING.equals(clsName) && "format".equals(methodName) && (stack.getStackDepth() >= 2)) {
                    String format = (String) stack.getStackItem(1).getConstant();
                    if (format != null) {
                        Matcher m = NON_SIMPLE_FORMAT.matcher(format);
                        if (!m.matches()) {
                            simpleFormat = true;
                        }
                    }
                } else if ("getFormatterLogger".equals(methodName) && LOG4J2_LOGMANAGER.equals(clsName)) {
                    seenFormatterLogger = true;
                }
            } else if (((seen == Const.INVOKEVIRTUAL) || (seen == Const.INVOKEINTERFACE)) && (throwableClass != null)) {
                String mthName = getNameConstantOperand();
                if ("getName".equals(mthName)) {
                    if (stack.getStackDepth() >= 1) {
                        // Foo.class.getName() is being called, so we pass the
                        // name of the class to the current top of the stack
                        // (the name of the class is currently on the top of the
                        // stack, but won't be on the stack at all next opcode)
                        Item stackItem = stack.getStackItem(0);
                        LOUserValue<String> uv = (LOUserValue<String>) stackItem.getUserValue();
                        if ((uv != null) && (uv.getType() == LOUserValue.LOType.CLASS_NAME)) {
                            ldcClassName = uv.getValue();
                        }
                    }
                } else if ("getMessage".equals(mthName)) {
                    String callingClsName = getClassConstantOperand();
                    JavaClass cls = Repository.lookupClass(callingClsName);
                    if (cls.instanceOf(throwableClass) && (stack.getStackDepth() > 0)) {
                        OpcodeStack.Item exItem = stack.getStackItem(0);
                        exMessageReg = exItem.getRegisterNumber();
                    }
                } else if (LOGGER_METHODS.contains(mthName)) {
                    checkForProblemsWithLoggerMethods();
                } else if (Values.TOSTRING.equals(mthName) && SignatureBuilder.SIG_VOID_TO_STRING.equals(getSigConstantOperand())) {
                    String callingClsName = getClassConstantOperand();
                    if (SignatureUtils.isPlainStringConvertableClass(callingClsName) && (stack.getStackDepth() > 0)) {
                        OpcodeStack.Item item = stack.getStackItem(0);
                        // if the stringbuilder was previously stored, don't report it
                        if (item.getRegisterNumber() < 0) {
                            seenMethodName = mthName;
                        }
                    }

                    if (seenMethodName == null) {
                        seenToString = true;
                    }
                }
            } else if (seen == Const.INVOKESPECIAL) {
                checkForLoggerParam();
            } else if (seen == Const.ANEWARRAY) {
                if (stack.getStackDepth() > 0) {
                    OpcodeStack.Item sizeItem = stack.getStackItem(0);
                    Object con = sizeItem.getConstant();
                    if (con instanceof Integer) {
                        arraySize = (Integer) con;
                    }
                }
            } else if (seen == Const.AASTORE) {
                if (stack.getStackDepth() >= 3) {
                    OpcodeStack.Item arrayItem = stack.getStackItem(2);
                    LOUserValue<Integer> uv = (LOUserValue<Integer>) arrayItem.getUserValue();
                    if ((uv != null) && (uv.getType() == LOUserValue.LOType.ARRAY_SIZE)) {
                        Integer size = uv.getValue();
                        if ((size != null) && (size.intValue() > 0) && hasExceptionOnStack()) {
                            arrayItem.setUserValue(new LOUserValue<>(LOUserValue.LOType.ARRAY_SIZE, Integer.valueOf(-size.intValue())));
                        }
                    }
                }
            } else if (seen == Const.PUTSTATIC) {
                OpcodeStack.Item itm = stack.getStackItem(0);
                if (isStaticInitializer && isNonPrivateLogField(getClassConstantOperand(), getNameConstantOperand(), getSigConstantOperand())) {
                    XMethod m = itm.getReturnValueOf();
                    if ((m != null) && isLoggerWithClassParm(m)) {
                        bugReporter.reportBug(new BugInstance(this, BugType.LO_NON_PRIVATE_STATIC_LOGGER.name(), NORMAL_PRIORITY).addClass(this).addMethod(this)
                                .addSourceLine(this));
                    }
                }

                LOUserValue<Void> loggerUV = (LOUserValue<Void>) itm.getUserValue();
                if ((loggerUV != null) && (loggerUV.getType() == LOUserValue.LOType.FORMATTER_LOGGER)) {
                    formatterLoggers.add(getNameConstantOperand());
                }
            } else if (seen == Const.GETSTATIC) {
                if (formatterLoggers.contains(getNameConstantOperand())) {
                    seenFormatterLogger = true;
                }
            } else if (OpcodeUtils.isAStore(seen) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                LOUserValue<String> uv = (LOUserValue<String>) item.getUserValue();
                if (uv != null) {
                    if (((uv.getType() == LOUserValue.LOType.METHOD_NAME) && Values.TOSTRING.equals(uv.getValue()))
                            || (uv.getType() == LOUserValue.LOType.SIMPLE_FORMAT) || (uv.getType() == LOUserValue.LOType.TOSTRING)) {
                        item.setUserValue(new LOUserValue<>(LOUserValue.LOType.NULL, null));
                    }
                }
            }
        } catch (ClassNotFoundException cnfe) {
            bugReporter.reportMissingClass(cnfe);
        } finally {
            TernaryPatcher.pre(stack, seen);
            stack.sawOpcode(this, seen);
            TernaryPatcher.post(stack, seen);

            if (stack.getStackDepth() > 0) {
                OpcodeStack.Item item = stack.getStackItem(0);
                if (ldcClassName != null) {
                    item.setUserValue(new LOUserValue<>(LOUserValue.LOType.CLASS_NAME, ldcClassName));
                } else if (seenMethodName != null) {
                    item.setUserValue(new LOUserValue<>(LOUserValue.LOType.METHOD_NAME, seenMethodName));
                } else if (exMessageReg >= 0) {
                    item.setUserValue(new LOUserValue<>(LOUserValue.LOType.MESSAGE_REG, Integer.valueOf(exMessageReg)));
                } else if (arraySize != null) {
                    item.setUserValue(new LOUserValue<>(LOUserValue.LOType.ARRAY_SIZE, arraySize));
                } else if (simpleFormat) {
                    item.setUserValue(new LOUserValue<>(LOUserValue.LOType.SIMPLE_FORMAT, Boolean.TRUE));
                } else if (seenToString) {
                    item.setUserValue(new LOUserValue<>(LOUserValue.LOType.TOSTRING, null));
                } else if (seenFormatterLogger) {
                    item.setUserValue(new LOUserValue<>(LOUserValue.LOType.FORMATTER_LOGGER, null));
                }
            }
        }
    }
1213798
@Override
    public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
        return visitorHelper.addAnnotation(cachedType, cachedType.getTypeDescriptor(), SignatureHelper.getType(desc));
    }
517443
@Override
    public void sawOpcode(int seen) {
        try {
            stack.precomputation(this);

            if (seen == Const.INVOKEVIRTUAL) {
                checkForTailRecursion();
            }
        } finally {
            stack.sawOpcode(this, seen);
        }
    }
630229
@Override
    public void sawOpcode(int seen) {
        if (seenReturn && seenTransferOfControl && seenStateChange) {
            return;
        }

        if (DEBUG) {
            System.out.println(stack);
            System.out.println(getPC() + " : " + Const.getOpcodeName(seen));
        }

        if ((seen == Const.INVOKEVIRTUAL || seen == Const.INVOKEINTERFACE) && "add".equals(getNameConstantOperand())
                && "(Ljava/lang/Object;)Z".equals(getSigConstantOperand()) && stack.getStackDepth() >= 2) {
            OpcodeStack.Item it0 = stack.getStackItem(0);
            int r0 = it0.getRegisterNumber();
            OpcodeStack.Item it1 = stack.getStackItem(1);
            int r1 = it1.getRegisterNumber();
            if (r0 == r1 && r0 > 0) {
                bugReporter.reportBug(new BugInstance(this, "IL_CONTAINER_ADDED_TO_ITSELF", NORMAL_PRIORITY).addClassAndMethod(
                        this).addSourceLine(this));
            }
        }

        if ((seen == Const.INVOKEVIRTUAL || seen == Const.INVOKESPECIAL || seen == Const.INVOKEINTERFACE || seen == Const.INVOKESTATIC)
                && getNameConstantOperand().equals(getMethodName())
                && getSigConstantOperand().equals(getMethodSig())
                && (seen == Const.INVOKESTATIC) == getMethod().isStatic()
                && (seen == Const.INVOKESPECIAL) == (getMethod().isPrivate() && !getMethod().isStatic() || Const.CONSTRUCTOR_NAME.equals(getMethodName()))) {
            Type arguments[] = getMethod().getArgumentTypes();
            // stack.getStackDepth() >= parameters
            int parameters = arguments.length;
            if (!getMethod().isStatic()) {
                parameters++;
            }
            XMethod xMethod = XFactory.createReferencedXMethod(this);
            if (DEBUG) {
                System.out.println("IL: Checking...");
                System.out.println(xMethod);
                System.out.println("vs. " + getClassName() + "." + getMethodName() + " : " + getMethodSig());

            }
            if (xMethod.getClassName().replace('.', '/').equals(getClassName()) || seen == Const.INVOKEINTERFACE) {
                // Invocation of same method
                // Now need to see if parameters are the same
                int firstParameter = 0;
                if (Const.CONSTRUCTOR_NAME.equals(getMethodName())) {
                    firstParameter = 1;
                }

                // match1 should be true if it is any call to the exact same
                // method
                // and no state has been change.
                // if match1 is true, the method may not always perform
                // a recursive infinite loop, but this particular method call is
                // an infinite
                // recursive loop

                boolean match1 = !seenStateChange;
                for (int i = firstParameter; match1 && i < parameters; i++) {
                    OpcodeStack.Item it = stack.getStackItem(parameters - 1 - i);
                    if (!it.isInitialParameter() || it.getRegisterNumber() != i) {
                        match1 = false;
                    }
                }

                boolean sameMethod = seen == Const.INVOKESTATIC || Const.CONSTRUCTOR_NAME.equals(getNameConstantOperand());
                if (!sameMethod) {
                    // Have to check if first parmeter is the same
                    // know there must be a this argument
                    if (DEBUG) {
                        System.out.println("Stack is " + stack);
                    }
                    OpcodeStack.Item p = stack.getStackItem(parameters - 1);
                    if (DEBUG) {
                        System.out.println("parameters = " + parameters + ", Item is " + p);
                    }
                    String sig = p.getSignature();
                    sameMethod = p.isInitialParameter() && p.getRegisterNumber() == 0 && sig.equals("L" + getClassName() + ";");

                }

                // match2 and match3 are two different ways of seeing if the
                // call site
                // postdominates the method entry.

                // technically, we use (!seenTransferOfControl || !seenReturn &&
                // largestBranchTarget < getPC())
                // as a check that the call site postdominates the method entry.
                // If those are true,
                // and sameMethod is true, we have a guaranteed IL.

                boolean match2 = sameMethod && !seenTransferOfControl;
                boolean match3 = sameMethod && !seenReturn && largestBranchTarget < getPC();
                if (match1 || match2 || match3) {
                    if (DEBUG) {
                        System.out.println("IL: " + sameMethod + " " + match1 + " " + match2 + " " + match3);
                    }
                    //                    int priority = HIGH_PRIORITY;
                    //                    if (!match1 && !match2 && seenThrow)
                    //                        priority = NORMAL_PRIORITY;
                    //                    if (seen == Const.INVOKEINTERFACE)
                    //                        priority = NORMAL_PRIORITY;
                    bugReporter.reportBug(new BugInstance(this, "IL_INFINITE_RECURSIVE_LOOP", HIGH_PRIORITY).addClassAndMethod(
                            this).addSourceLine(this));
                }
            }
        }

        switch (seen) {
        case Const.ARETURN:
        case Const.IRETURN:
        case Const.LRETURN:
        case Const.RETURN:
        case Const.DRETURN:
        case Const.FRETURN:
            seenReturn = true;
            seenTransferOfControl = true;
            break;
        case Const.ATHROW:
            //            seenThrow = true;
            seenTransferOfControl = true;
            break;
        case Const.PUTSTATIC:
        case Const.PUTFIELD:
        case Const.IASTORE:
        case Const.AASTORE:
        case Const.DASTORE:
        case Const.FASTORE:
        case Const.LASTORE:
        case Const.SASTORE:
        case Const.CASTORE:
        case Const.BASTORE:
            seenStateChange = true;
            break;
        case Const.INVOKEVIRTUAL:
        case Const.INVOKESPECIAL:
        case Const.INVOKEINTERFACE:
        case Const.INVOKESTATIC:
            if ("print".equals(getNameConstantOperand()) || "println".equals(getNameConstantOperand())
                    || "log".equals(getNameConstantOperand()) || "toString".equals(getNameConstantOperand())) {
                break;
            }
            seenStateChange = true;
            break;
        default:
            break;
        }
    }
325544
@Override
    public void sawOpcode(int seen) {
        boolean sawCreate = false;
        Integer itemPC = null;

        try {
            stack.precomputation(this);

            if (seen == Const.INVOKEINTERFACE) {
                String className = getClassConstantOperand();
                String methodInfo = getNameConstantOperand() + ':' + getSigConstantOperand();
                if ("org/w3c/dom/Document".equals(className) && domCreationMethods.contains(methodInfo)) {
                    sawCreate = true;
                    itemPC = Integer.valueOf(getPC());
                }
            } else if (OpcodeUtils.isAStore(seen)) {
                Integer pc = findDOMNodeCreationPoint(0);
                int reg = RegisterUtils.getAStoreReg(this, seen);
                if (pc != null) {
                    nodeStores.put(Integer.valueOf(reg), pc);
                } else {
                    nodeStores.remove(Integer.valueOf(reg));
                }
            } else if (seen == Const.PUTFIELD) {
                // Stores to member variables are assumed ok
                findDOMNodeCreationPoint(0);
            } else if (OpcodeUtils.isALoad(seen)) {
                int reg = RegisterUtils.getALoadReg(this, seen);
                itemPC = nodeStores.get(Integer.valueOf(reg));
                if (itemPC != null) {
                    sawCreate = true;
                }
            } else if ((seen == Const.ARETURN) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item itm = stack.getStackItem(0);
                int reg = itm.getRegisterNumber();
                nodeCreations.remove(itm);
                nodeStores.remove(Integer.valueOf(reg));
            }

            if (!sawCreate
                    && ((seen == Const.INVOKEINTERFACE) || (seen == Const.INVOKEVIRTUAL) || (seen == Const.INVOKESTATIC) || (seen == Const.INVOKESPECIAL))) {
                String methodSig = getSigConstantOperand();
                int argCount = SignatureUtils.getNumParameters(methodSig);
                if (stack.getStackDepth() >= argCount) {
                    for (int a = 0; a < argCount; a++) {
                        OpcodeStack.Item itm = stack.getStackItem(a);
                        if (nodeCreations.containsKey(itm)) {
                            int reg = itm.getRegisterNumber();
                            nodeCreations.remove(itm);
                            nodeStores.remove(Integer.valueOf(reg));
                        }
                    }
                    if ((seen != Const.INVOKESTATIC) && (stack.getStackDepth() > argCount)) {
                        nodeCreations.remove(stack.getStackItem(argCount));
                    }
                }
            }
        } finally {
            stack.sawOpcode(this, seen);
            if (sawCreate && (stack.getStackDepth() > 0)) {
                nodeCreations.put(stack.getStackItem(0), itemPC);
            }
        }
    }
678983
public void accept(final MethodVisitor mv, boolean visible) {
        Label[] start = new Label[this.start.size()];
        Label[] end = new Label[this.end.size()];
        int[] index = new int[this.index.size()];
        for (int i = 0; i < start.length; ++i) {
            start[i] = this.start.get(i).getLabel();
            end[i] = this.end.get(i).getLabel();
            index[i] = this.index.get(i);
        }
        accept(mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
                index, desc, true));
    }
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);
        }
    }
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));
            }
        }
    }
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.";
        }
      }
    };
  }
657754
@Override
  public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
    classInfo.checkTypeQueryAnnotation(desc);
    return super.visitAnnotation(desc, visible);
  }
1239414
@Override
    public void sawOpcode(final int seen) {
        try {
            stack.precomputation(this);

            BitSet regs = localScopeEnds.remove(Integer.valueOf(getPC()));
            if (regs != null) {
                int i = regs.nextSetBit(0);
                while (i >= 0) {
                    localCollections.remove(i);
                    localSourceLineAnnotations.remove(i);
                    i = regs.nextSetBit(i + 1);
                }
            }
            if (seen == Const.INVOKEINTERFACE) {
                String className = getClassConstantOperand();
                if (COLLECTION_CLASSES.contains(className)) {
                    String methodName = getNameConstantOperand();
                    String methodSig = getSigConstantOperand();
                    if ("add".equals(methodName) && SignatureBuilder.SIG_OBJECT_TO_BOOLEAN.equals(methodSig)) {
                        if (stack.getStackDepth() > 1) {
                            OpcodeStack.Item colItm = stack.getStackItem(1);
                            OpcodeStack.Item addItm = stack.getStackItem(0);
                            checkAdd(colItm, addItm);
                        }
                    } else if (("put".equals(methodName) && SignatureBuilder.SIG_TWO_OBJECTS_TO_OBJECT.equals(methodSig)) && (stack.getStackDepth() > 2)) {
                        // For maps, just check the keys
                        OpcodeStack.Item colItm = stack.getStackItem(2);
                        OpcodeStack.Item addItm = stack.getStackItem(1);
                        checkAdd(colItm, addItm);
                    }
                }
            } else if (seen == Const.AASTORE) {
                if (stack.getStackDepth() > 2) {
                    OpcodeStack.Item arrayItm = stack.getStackItem(2);
                    OpcodeStack.Item addItm = stack.getStackItem(0);
                    checkAdd(arrayItm, addItm);
                }
            } else if (OpcodeUtils.isAStore(seen)) {
                Integer reg = Integer.valueOf(RegisterUtils.getAStoreReg(this, seen));
                localCollections.remove(reg);
                localSourceLineAnnotations.remove(reg);
            }
        } catch (ClassNotFoundException cnfe) {
            bugReporter.reportMissingClass(cnfe);
        } 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);
            }
        }
    }
715349
@Override
    public void sawOpcode(int seen) {
        switch (state) {
            case SEEN_NOTHING:
                if ((seen == Const.INVOKEINTERFACE) || (seen == Const.INVOKEVIRTUAL)) {
                    String sig = getSigConstantOperand();
                    String returnSig = SignatureUtils.getReturnSignature(sig);
                    if (returnSig.startsWith(Values.SIG_QUALIFIED_CLASS_PREFIX)) {
                        String clsName = getClassConstantOperand();
                        if (!Values.SLASHED_JAVA_LANG_OBJECT.equals(clsName) && !Values.SLASHED_JAVA_LANG_CLASS.equals(clsName)) {
                            returnType = SignatureUtils.trimSignature(returnSig);
                            invokePC = getPC();
                            state = State.SEEN_INVOKE;
                        }
                    }
                }
            break;

            case SEEN_INVOKE:
                if (seen == Const.POP) {
                    state = State.SEEN_POP;
                } else {
                    state = State.SEEN_NOTHING;
                    returnType = null;
                }
            break;

            case SEEN_POP:
                if (((seen >= Const.ACONST_NULL) && (seen <= Const.DCONST_1)) || (seen == Const.GETFIELD)) {
                    state = State.SEEN_POP;
                } else if ((seen == Const.INVOKESTATIC) || (seen == Const.GETSTATIC)) {
                    if (getClassConstantOperand().equals(returnType) && (lnTable.getSourceLine(invokePC) == lnTable.getSourceLine(getPC()))) {
                        bugReporter.reportBug(new BugInstance(this, BugType.NIR_NEEDLESS_INSTANCE_RETRIEVAL.name(), NORMAL_PRIORITY).addClass(this)
                                .addMethod(this).addSourceLine(this));
                    }
                    state = State.SEEN_NOTHING;
                    returnType = null;
                } else {
                    state = State.SEEN_NOTHING;
                    returnType = null;
                }
            break;

            default:
                state = State.SEEN_NOTHING;
                returnType = null;
            break;
        }
    }
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()));
                }
            }
        }
    }
735711
@Override
    public void sawOpcode(int seen) {
        if (seen == Const.INVOKEVIRTUAL) {
            if ("equals".equals(getNameConstantOperand()) && "(Ljava/lang/Object;)Z".equals(getSigConstantOperand())) {
                OpcodeStack.Item item = stack.getStackItem(1);
                ClassDescriptor c = DescriptorFactory.createClassDescriptorFromSignature(item.getSignature());
                check(c);

            } else if ("java/lang/Class".equals(getClassConstantOperand())
                    && ("isInstance".equals(getNameConstantOperand()) || "cast".equals(getNameConstantOperand()))) {
                OpcodeStack.Item item = stack.getStackItem(1);
                if ("Ljava/lang/Class;".equals(item.getSignature())) {
                    Object value = item.getConstant();
                    if (value instanceof String) {
                        ClassDescriptor c = DescriptorFactory.createClassDescriptor((String) value);
                        check(c);
                    }
                }

            }

        } else if (seen == Const.INSTANCEOF || seen == Const.CHECKCAST) {
            check(getClassDescriptorOperand());
        }

    }
288403
@Override
    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String exceptions[]) {
        // skip static initializers
        if (name.equals("<clinit>")) {
            return null;
        }

        MethodInfoImpl methodInfo = new MethodInfoImpl(name, desc, exceptions, access, classInfo);

        if (name.equals("<init>")) {
            constructorInfos.add(methodInfo);
        } else {
            methodInfos.add(methodInfo);
        }

        if (logParms != null) {
            logParms[1] = name;
            logParms[2] = methodInfo.getHashText();
        }

        methodVisitor.setMethodInfo(methodInfo);
        return methodVisitor;
    }