Package com.mebigfatguy.fbcontrib.detect
Class BloatedAssignmentScope
- java.lang.Object
-
- edu.umd.cs.findbugs.visitclass.BetterVisitor
-
- edu.umd.cs.findbugs.visitclass.PreorderVisitor
-
- edu.umd.cs.findbugs.visitclass.AnnotationVisitor
-
- edu.umd.cs.findbugs.visitclass.DismantleBytecode
-
- edu.umd.cs.findbugs.BytecodeScanningDetector
-
- com.mebigfatguy.fbcontrib.detect.BloatedAssignmentScope
-
- All Implemented Interfaces:
edu.umd.cs.findbugs.Detector
,edu.umd.cs.findbugs.Priorities
,edu.umd.cs.findbugs.visitclass.Constants2
,org.apache.bcel.classfile.Visitor
,org.apache.bcel.Constants
@CustomUserValue public class BloatedAssignmentScope extends edu.umd.cs.findbugs.BytecodeScanningDetector
looks for variable assignments at a scope larger than its use. In this case, the assignment can be pushed down into the smaller scope to reduce the performance impact of that assignment.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description private class
BloatedAssignmentScope.ScopeBlock
holds the description of a scope { } block, be it a for, if, while block(package private) static class
BloatedAssignmentScope.UserObject
represents the source of an assignment to a variable, which could be a method call or a field
-
Field Summary
Fields Modifier and Type Field Description (package private) edu.umd.cs.findbugs.BugReporter
bugReporter
private java.util.BitSet
catchHandlers
private static java.util.Set<java.lang.String>
dangerousAssignmentClassSources
private static java.util.Set<java.util.regex.Pattern>
dangerousAssignmentMethodPatterns
private static java.util.Set<FQMethod>
dangerousAssignmentMethodSources
private static java.util.Set<java.lang.String>
dangerousStoreClassSigs
private boolean
dontReport
private java.util.BitSet
ignoreRegs
private java.util.List<java.lang.Integer>
monitorSyncPCs
private BloatedAssignmentScope.ScopeBlock
rootScopeBlock
private boolean
sawDup
private boolean
sawNull
private edu.umd.cs.findbugs.OpcodeStack
stack
private java.util.BitSet
switchTargets
private java.util.BitSet
tryBlocks
-
Fields inherited from class edu.umd.cs.findbugs.visitclass.DismantleBytecode
codeBytes, lineNumberTable, M_BR, M_CP, M_INT, M_PAD, M_R, M_UINT
-
Fields inherited from interface org.apache.bcel.Constants
AALOAD, AASTORE, ACC_ABSTRACT, ACC_ANNOTATION, ACC_BRIDGE, ACC_ENUM, ACC_FINAL, ACC_INTERFACE, ACC_NATIVE, ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC, ACC_STATIC, ACC_STRICT, ACC_SUPER, ACC_SYNCHRONIZED, ACC_SYNTHETIC, ACC_SYPER, ACC_TRANSIENT, ACC_VARARGS, ACC_VOLATILE, ACCESS_NAMES, ACONST_NULL, ALOAD, ALOAD_0, ALOAD_1, ALOAD_2, ALOAD_3, ANEWARRAY, ANEWARRAY_QUICK, APPEND_FRAME, APPEND_FRAME_MAX, ARETURN, ARRAYLENGTH, ASTORE, ASTORE_0, ASTORE_1, ASTORE_2, ASTORE_3, ATHROW, ATTR_ANNOTATION_DEFAULT, ATTR_CODE, ATTR_CONSTANT_VALUE, ATTR_DEPRECATED, ATTR_ENCLOSING_METHOD, ATTR_EXCEPTIONS, ATTR_INNER_CLASSES, ATTR_LINE_NUMBER_TABLE, ATTR_LOCAL_VARIABLE_TABLE, ATTR_LOCAL_VARIABLE_TYPE_TABLE, ATTR_PMG, ATTR_RUNTIME_VISIBLE_ANNOTATIONS, ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, ATTR_RUNTIMEIN_VISIBLE_ANNOTATIONS, ATTR_RUNTIMEIN_VISIBLE_PARAMETER_ANNOTATIONS, ATTR_SIGNATURE, ATTR_SOURCE_FILE, ATTR_STACK_MAP, ATTR_STACK_MAP_TABLE, ATTR_SYNTHETIC, ATTR_UNKNOWN, ATTRIBUTE_NAMES, BALOAD, BASTORE, BIPUSH, BREAKPOINT, CALOAD, CASTORE, CHECKCAST, CHECKCAST_QUICK, CHOP_FRAME, CHOP_FRAME_MAX, CLASS_TYPE_NAMES, CONSTANT_Class, CONSTANT_Double, CONSTANT_Fieldref, CONSTANT_Float, CONSTANT_Integer, CONSTANT_InterfaceMethodref, CONSTANT_InvokeDynamic, CONSTANT_Long, CONSTANT_MethodHandle, CONSTANT_Methodref, CONSTANT_MethodType, CONSTANT_NameAndType, CONSTANT_NAMES, CONSTANT_String, CONSTANT_Utf8, CONSTRUCTOR_NAME, CONSUME_STACK, D2F, D2I, D2L, DADD, DALOAD, DASTORE, DCMPG, DCMPL, DCONST_0, DCONST_1, DDIV, DLOAD, DLOAD_0, DLOAD_1, DLOAD_2, DLOAD_3, DMUL, DNEG, DREM, DRETURN, DSTORE, DSTORE_0, DSTORE_1, DSTORE_2, DSTORE_3, DSUB, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, F2D, F2I, F2L, FADD, FALOAD, FASTORE, FCMPG, FCMPL, FCONST_0, FCONST_1, FCONST_2, FDIV, FLOAD, FLOAD_0, FLOAD_1, FLOAD_2, FLOAD_3, FMUL, FNEG, FREM, FRETURN, FSTORE, FSTORE_0, FSTORE_1, FSTORE_2, FSTORE_3, FSUB, FULL_FRAME, GETFIELD, GETFIELD_QUICK, GETFIELD_QUICK_W, GETFIELD2_QUICK, GETSTATIC, GETSTATIC_QUICK, GETSTATIC2_QUICK, GOTO, GOTO_W, I2B, I2C, I2D, I2F, I2L, I2S, IADD, IALOAD, IAND, IASTORE, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5, ICONST_M1, IDIV, IF_ACMPEQ, IF_ACMPNE, IF_ICMPEQ, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ICMPLT, IF_ICMPNE, IFEQ, IFGE, IFGT, IFLE, IFLT, IFNE, IFNONNULL, IFNULL, IINC, ILLEGAL_OPCODE, ILLEGAL_TYPE, ILOAD, ILOAD_0, ILOAD_1, ILOAD_2, ILOAD_3, IMPDEP1, IMPDEP2, IMUL, INEG, INSTANCEOF, INSTANCEOF_QUICK, INT2BYTE, INT2CHAR, INT2SHORT, INTERFACES_IMPLEMENTED_BY_ARRAYS, INVOKEDYNAMIC, INVOKEINTERFACE, INVOKEINTERFACE_QUICK, INVOKENONVIRTUAL, INVOKENONVIRTUAL_QUICK, INVOKESPECIAL, INVOKESTATIC, INVOKESTATIC_QUICK, INVOKESUPER_QUICK, INVOKEVIRTUAL, INVOKEVIRTUAL_QUICK, INVOKEVIRTUAL_QUICK_W, INVOKEVIRTUALOBJECT_QUICK, IOR, IREM, IRETURN, ISHL, ISHR, ISTORE, ISTORE_0, ISTORE_1, ISTORE_2, ISTORE_3, ISUB, ITEM_Bogus, ITEM_Double, ITEM_Float, ITEM_InitObject, ITEM_Integer, ITEM_Long, ITEM_NAMES, ITEM_NewObject, ITEM_Null, ITEM_Object, IUSHR, IXOR, JSR, JSR_W, KNOWN_ATTRIBUTES, L2D, L2F, L2I, LADD, LALOAD, LAND, LASTORE, LCMP, LCONST_0, LCONST_1, LDC, LDC_QUICK, LDC_W, LDC_W_QUICK, LDC2_W, LDC2_W_QUICK, LDIV, LLOAD, LLOAD_0, LLOAD_1, LLOAD_2, LLOAD_3, LMUL, LNEG, LOOKUPSWITCH, LOR, LREM, LRETURN, LSHL, LSHR, LSTORE, LSTORE_0, LSTORE_1, LSTORE_2, LSTORE_3, LSUB, LUSHR, LXOR, MAJOR, MAJOR_1_1, MAJOR_1_2, MAJOR_1_3, MAJOR_1_4, MAJOR_1_5, MAJOR_1_6, MAJOR_1_7, MAJOR_1_8, MAX_ACC_FLAG, MAX_BYTE, MAX_CODE_SIZE, MAX_CP_ENTRIES, MAX_SHORT, MINOR, MINOR_1_1, MINOR_1_2, MINOR_1_3, MINOR_1_4, MINOR_1_5, MINOR_1_6, MINOR_1_7, MINOR_1_8, MONITORENTER, MONITOREXIT, MULTIANEWARRAY, MULTIANEWARRAY_QUICK, NEW, NEW_QUICK, NEWARRAY, NO_OF_OPERANDS, NOP, OPCODE_NAMES, POP, POP2, PRODUCE_STACK, PUSH, PUTFIELD, PUTFIELD_QUICK, PUTFIELD_QUICK_W, PUTFIELD2_QUICK, PUTSTATIC, PUTSTATIC_QUICK, PUTSTATIC2_QUICK, RESERVED, RET, RETURN, SALOAD, SAME_FRAME, SAME_FRAME_EXTENDED, SAME_FRAME_MAX, SAME_LOCALS_1_STACK_ITEM_FRAME, SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED, SAME_LOCALS_1_STACK_ITEM_FRAME_MAX, SASTORE, SHORT_TYPE_NAMES, SIPUSH, STATIC_INITIALIZER_NAME, SWAP, SWITCH, T_ADDRESS, T_ARRAY, T_BOOLEAN, T_BYTE, T_CHAR, T_DOUBLE, T_FLOAT, T_INT, T_LONG, T_OBJECT, T_REFERENCE, T_SHORT, T_UNKNOWN, T_VOID, TABLESWITCH, TYPE_NAMES, TYPE_OF_OPERANDS, UNDEFINED, UNPREDICTABLE, WIDE
-
-
Constructor Summary
Constructors Constructor Description BloatedAssignmentScope(edu.umd.cs.findbugs.BugReporter bugReporter)
constructs a BAS detector given the reporter to report bugs on
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description private int
findCatchHandlerFor(int pc)
returns the catch handler for a given try blockprivate BloatedAssignmentScope.ScopeBlock
findPreviousSiblingScopeBlock(BloatedAssignmentScope.ScopeBlock sb)
looks for the ScopeBlock has the same parent as this given one, but precedes it in the list.private BloatedAssignmentScope.ScopeBlock
findScopeBlock(BloatedAssignmentScope.ScopeBlock sb, int pc)
returns the scope block in which this register was assigned, by traversing the scope block treeprivate BloatedAssignmentScope.ScopeBlock
findScopeBlockWithTarget(BloatedAssignmentScope.ScopeBlock sb, int start, int target)
returns an existing scope block that has the same target as the one looked forprivate BloatedAssignmentScope.ScopeBlock
findSynchronizedScopeBlock(BloatedAssignmentScope.ScopeBlock sb, int monitorEnterPC)
finds the scope block that is the active synchronized blockprivate java.lang.Comparable<?>
getCallingObject()
returns either a register number of a field reference of the object that a method is being called on, or null, if it can't be determined.boolean
isRiskyMethodCall()
boolean
isRiskyStoreClass(int reg)
private void
sawBranch(int seen, int pc)
creates a scope block to describe this branch location.private BloatedAssignmentScope.UserObject
sawGetField()
private void
sawIINC(int pc)
processes a register IINC by updating the appropriate scope block to mark this register as being stored in the blockprivate BloatedAssignmentScope.UserObject
sawInstanceCall(int pc)
processes a instance method call to see if that call is modifies state or is otherwise'risky', if so mark the variable(s) associated with the caller as not reportableprivate void
sawLoad(int seen, int pc)
processes a register store by updating the appropriate scope block to mark this register as being read in the blockprivate void
sawMonitorEnter(int pc)
processes a monitor enter call to create a scope blockprivate void
sawMonitorExit(int pc)
processes a monitor exit to set the end of the already created scope blockvoid
sawOpcode(int seen)
implements the visitor to look for variables assigned below the scope in which they are used.private void
sawPutField(int pc)
private BloatedAssignmentScope.UserObject
sawStaticCall()
processes a static call or initializer by checking to see if the call is risky, and returning a OpcodeStack item user value saying so.private void
sawStore(int seen, int pc)
processes a register store by updating the appropriate scope block to mark this register as being stored in the blockprivate void
sawSwitch(int pc)
creates a new scope block for each case statementvoid
visitClassContext(edu.umd.cs.findbugs.ba.ClassContext classContext)
implements the visitor to create and the clear the register to location mapvoid
visitCode(org.apache.bcel.classfile.Code obj)
implements the visitor to reset the register to location map-
Methods inherited from class edu.umd.cs.findbugs.BytecodeScanningDetector
getClassContext, report, shouldVisitCode
-
Methods inherited from class edu.umd.cs.findbugs.visitclass.DismantleBytecode
afterOpcode, areOppositeBranches, atCatchBlock, beforeOpcode, getBranchFallThrough, getBranchOffset, getBranchTarget, getClassConstantOperand, getClassDescriptorOperand, getCodeByte, getConstantRefOperand, getDefaultSwitchOffset, getDottedClassConstantOperand, getFieldDescriptorOperand, getIntConstant, getLongConstant, getMaxPC, getMethodDescriptorOperand, getNameConstantOperand, getNextCodeByte, getNextOpcode, getNextPC, getOpcode, getPC, getPrevOpcode, getRefConstantOperand, getRefFieldIsStatic, getRegisterOperand, getSigConstantOperand, getStringConstantOperand, getSwitchLabels, getSwitchOffsets, getXClassOperand, getXFieldOperand, getXMethodOperand, isBranch, isMethodCall, isRegisterLoad, isRegisterStore, isRegisterStore, isReturn, isShift, isSwitch, isWideOpcode, printOpCode, sawBranchTo, sawClass, sawDouble, sawField, sawFloat, sawIMethod, sawInt, sawLong, sawMethod, sawRegister, sawString, visit
-
Methods inherited from class edu.umd.cs.findbugs.visitclass.AnnotationVisitor
getAnnotationParameterAsString, getAnnotationParameterAsStringArray, visitAnnotation, visitAnnotation, visitParameterAnnotation, visitParameterAnnotation, visitSyntheticParameterAnnotation
-
Methods inherited from class edu.umd.cs.findbugs.visitclass.PreorderVisitor
amVisitingMainMethod, asUnsignedByte, doVisitMethod, getClassDescriptor, getClassName, getCode, getConstantPool, getDottedClassName, getDottedFieldSig, getDottedMethodSig, getDottedSuperclassName, getField, getFieldDescriptor, getFieldIsStatic, getFieldName, getFieldSig, getFullyQualifiedFieldName, getFullyQualifiedMethodName, getMethod, getMethodDescriptor, getMethodName, getMethodSig, getMethodVisitOrder, getNumberArguments, getNumberMethodArguments, getPackageName, getSizeOfSurroundingTryBlock, getSizeOfSurroundingTryBlock, getSourceFile, getStringFromIndex, getSuperclassName, getSurroundingCaughtExceptions, getSurroundingCaughtExceptions, getSurroundingTryBlock, getSurroundingTryBlock, getThisClass, getXClass, getXField, getXMethod, hasInterestingClass, hasInterestingMethod, isVisitMethodsInCallOrder, setupVisitorForClass, setVisitMethodsInCallOrder, shouldVisit, toString, visitAfter, visitAfter, visitAnnotationDefault, visitAnnotationEntry, visitConstantPool, visitEnclosingMethod, visitingField, visitingMethod, visitInnerClasses, visitJavaClass, visitLineNumberTable, visitLocalVariableTable, visitStackMapTable, visitStackMapTableEntry
-
Methods inherited from class edu.umd.cs.findbugs.visitclass.BetterVisitor
clone, report, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visitCodeException, visitConstantClass, visitConstantDouble, visitConstantFieldref, visitConstantFloat, visitConstantInteger, visitConstantInterfaceMethodref, visitConstantLong, visitConstantMethodref, visitConstantNameAndType, visitConstantString, visitConstantUtf8, visitConstantValue, visitDeprecated, visitExceptionTable, visitField, visitInnerClass, visitLineNumber, visitLocalVariable, visitLocalVariableTypeTable, visitMethod, visitSignature, visitSourceFile, visitStackMap, visitStackMapEntry, visitSynthetic, visitUnknown
-
-
-
-
Field Detail
-
dangerousAssignmentClassSources
private static final java.util.Set<java.lang.String> dangerousAssignmentClassSources
-
dangerousAssignmentMethodSources
private static final java.util.Set<FQMethod> dangerousAssignmentMethodSources
-
dangerousAssignmentMethodPatterns
private static final java.util.Set<java.util.regex.Pattern> dangerousAssignmentMethodPatterns
-
dangerousStoreClassSigs
private static final java.util.Set<java.lang.String> dangerousStoreClassSigs
-
bugReporter
edu.umd.cs.findbugs.BugReporter bugReporter
-
stack
private edu.umd.cs.findbugs.OpcodeStack stack
-
ignoreRegs
private java.util.BitSet ignoreRegs
-
rootScopeBlock
private BloatedAssignmentScope.ScopeBlock rootScopeBlock
-
tryBlocks
private java.util.BitSet tryBlocks
-
catchHandlers
private java.util.BitSet catchHandlers
-
switchTargets
private java.util.BitSet switchTargets
-
monitorSyncPCs
private java.util.List<java.lang.Integer> monitorSyncPCs
-
dontReport
private boolean dontReport
-
sawDup
private boolean sawDup
-
sawNull
private boolean sawNull
-
-
Method Detail
-
visitClassContext
public void visitClassContext(edu.umd.cs.findbugs.ba.ClassContext classContext)
implements the visitor to create and the clear the register to location map- Specified by:
visitClassContext
in interfaceedu.umd.cs.findbugs.Detector
- Overrides:
visitClassContext
in classedu.umd.cs.findbugs.BytecodeScanningDetector
- Parameters:
classContext
- the context object of the currently parsed class
-
visitCode
public void visitCode(org.apache.bcel.classfile.Code obj)
implements the visitor to reset the register to location map- Specified by:
visitCode
in interfaceorg.apache.bcel.classfile.Visitor
- Overrides:
visitCode
in classedu.umd.cs.findbugs.visitclass.PreorderVisitor
- Parameters:
obj
- the context object of the currently parsed code block
-
sawOpcode
public void sawOpcode(int seen)
implements the visitor to look for variables assigned below the scope in which they are used.- Overrides:
sawOpcode
in classedu.umd.cs.findbugs.visitclass.DismantleBytecode
- Parameters:
seen
- the opcode of the currently parsed instruction
-
sawStore
private void sawStore(int seen, int pc)
processes a register store by updating the appropriate scope block to mark this register as being stored in the block- Parameters:
seen
- the currently parsed opcodepc
- the current program counter
-
sawIINC
private void sawIINC(int pc)
processes a register IINC by updating the appropriate scope block to mark this register as being stored in the block- Parameters:
pc
- the current program counter
-
sawLoad
private void sawLoad(int seen, int pc)
processes a register store by updating the appropriate scope block to mark this register as being read in the block- Parameters:
seen
- the currently parsed opcodepc
- the current program counter
-
sawBranch
private void sawBranch(int seen, int pc)
creates a scope block to describe this branch location.- Parameters:
seen
- the currently parsed opcodepc
- the current program counter
-
sawSwitch
private void sawSwitch(int pc)
creates a new scope block for each case statement- Parameters:
pc
- the current program counter
-
sawInstanceCall
@Nullable private BloatedAssignmentScope.UserObject sawInstanceCall(int pc)
processes a instance method call to see if that call is modifies state or is otherwise'risky', if so mark the variable(s) associated with the caller as not reportable- Parameters:
pc
- the current program counter- Returns:
- a user object to place on the return value's OpcodeStack item
-
sawStaticCall
@Nullable private BloatedAssignmentScope.UserObject sawStaticCall()
processes a static call or initializer by checking to see if the call is risky, and returning a OpcodeStack item user value saying so.- Returns:
- the user object to place on the OpcodeStack
-
sawGetField
@Nullable private BloatedAssignmentScope.UserObject sawGetField()
-
sawPutField
private void sawPutField(int pc)
-
sawMonitorEnter
private void sawMonitorEnter(int pc)
processes a monitor enter call to create a scope block- Parameters:
pc
- the current program counter
-
sawMonitorExit
private void sawMonitorExit(int pc)
processes a monitor exit to set the end of the already created scope block- Parameters:
pc
- the current program counter
-
getCallingObject
@Nullable private java.lang.Comparable<?> getCallingObject()
returns either a register number of a field reference of the object that a method is being called on, or null, if it can't be determined.- Returns:
- either an Integer for a register, or a String for the field name, or null
-
findScopeBlock
@Nullable private BloatedAssignmentScope.ScopeBlock findScopeBlock(BloatedAssignmentScope.ScopeBlock sb, int pc)
returns the scope block in which this register was assigned, by traversing the scope block tree- Parameters:
sb
- the scope block to start searching inpc
- the current program counter- Returns:
- the scope block or null if not found
-
findScopeBlockWithTarget
private BloatedAssignmentScope.ScopeBlock findScopeBlockWithTarget(BloatedAssignmentScope.ScopeBlock sb, int start, int target)
returns an existing scope block that has the same target as the one looked for- Parameters:
sb
- the scope block to start withstart
- the current pctarget
- the target to look for- Returns:
- the scope block found or null
-
findPreviousSiblingScopeBlock
@Nullable private BloatedAssignmentScope.ScopeBlock findPreviousSiblingScopeBlock(BloatedAssignmentScope.ScopeBlock sb)
looks for the ScopeBlock has the same parent as this given one, but precedes it in the list.- Parameters:
sb
- the scope block to look for the previous scope block- Returns:
- the previous sibling scope block, or null if doesn't exist
-
findSynchronizedScopeBlock
private BloatedAssignmentScope.ScopeBlock findSynchronizedScopeBlock(BloatedAssignmentScope.ScopeBlock sb, int monitorEnterPC)
finds the scope block that is the active synchronized block- Parameters:
sb
- the parent scope block to start withmonitorEnterPC
- the pc where the current synchronized block starts- Returns:
- the scope block
-
findCatchHandlerFor
private int findCatchHandlerFor(int pc)
returns the catch handler for a given try block- Parameters:
pc
- the current instruction- Returns:
- the pc of the handler for this pc if it's the start of a try block, or -1
-
isRiskyMethodCall
public boolean isRiskyMethodCall()
-
isRiskyStoreClass
public boolean isRiskyStoreClass(int reg)
-
-