use of com.mebigfatguy.fbcontrib.utils.FQMethod in project fb-contrib by mebigfatguy.
the class PresizeCollections method sawOpcode.
/**
* implements the visitor to look for creation of collections that are then populated with a known number of elements usually based on another collection,
* but the new collection is not presized.
*
* @param seen
* the opcode of the currently parsed instruction
*/
@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());
}
}
} 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()));
}
}
}
}
use of com.mebigfatguy.fbcontrib.utils.FQMethod in project fb-contrib by mebigfatguy.
the class PresizeCollections method branchBasedOnUnsizedObject.
/**
* returns if the conditional is based on a method call from an object that has no sizing to determine what presize should be. it's possible the correct
* implementation should just return true, if <code>if ((seen != IFNE) || (stack.getStackDepth() == 0))</code>
*
* @param seen
* the current visited opcode
* @return whether this conditional is based on a unsized object
*/
private boolean branchBasedOnUnsizedObject(int seen) {
if ((seen == Const.IF_ACMPEQ) || (seen == Const.IF_ACMPNE)) {
return true;
}
if ((seen != Const.IFNE) || (stack.getStackDepth() == 0)) {
return false;
}
OpcodeStack.Item itm = stack.getStackItem(0);
XMethod xm = itm.getReturnValueOf();
if (xm == null) {
return false;
}
FQMethod fqm = new FQMethod(xm.getClassName().replace('.', '/'), xm.getName(), xm.getSignature());
if (ITERATOR_HASNEXT.equals(fqm)) {
PSCUserValue uv = (PSCUserValue) itm.getUserValue();
if (uv == null) {
return true;
}
return !uv.hasSizedSource();
}
return UNSIZED_SOURCES.contains(fqm);
}
use of com.mebigfatguy.fbcontrib.utils.FQMethod in project fb-contrib by mebigfatguy.
the class UseCharacterParameterizedMethod method sawOpcode.
/**
* implements the visitor to look for method calls that pass a constant string as a parameter when the string is only one character long, and there is an
* alternate method passing a character.
*/
@Override
public void sawOpcode(int seen) {
try {
stack.precomputation(this);
if ((seen == Const.INVOKEVIRTUAL) || (seen == Const.INVOKEINTERFACE)) {
FQMethod key = new FQMethod(getClassConstantOperand(), getNameConstantOperand(), getSigConstantOperand());
Object posObject = characterMethods.get(key);
if (posObject instanceof Integer) {
if (checkSingleParamMethod(((Integer) posObject).intValue()) && !isInlineAppend(key)) {
reportBug();
}
} else if ((posObject instanceof IntPair) && checkDoubleParamMethod((IntPair) posObject)) {
reportBug();
}
} else if (seen == Const.DUP) {
if (stack.getStackDepth() > 0) {
OpcodeStack.Item itm = stack.getStackItem(0);
String duppedSig = itm.getSignature();
if ("Ljava/lang/StringBuilder;".equals(duppedSig) || "Ljava/lang/StringBuffer;".equals(duppedSig)) {
itm.setUserValue(UCPMUserValue.INLINE);
}
}
} else if ((seen == Const.PUTFIELD) || (((seen == Const.PUTSTATIC) || OpcodeUtils.isAStore(seen)) && (stack.getStackDepth() > 0))) {
OpcodeStack.Item itm = stack.getStackItem(0);
itm.setUserValue(null);
}
} finally {
UCPMUserValue uv = callHasInline(seen);
stack.sawOpcode(this, seen);
if ((uv == UCPMUserValue.INLINE) && (stack.getStackDepth() > 0)) {
OpcodeStack.Item itm = stack.getStackItem(0);
itm.setUserValue(uv);
}
}
}
use of com.mebigfatguy.fbcontrib.utils.FQMethod in project fb-contrib by mebigfatguy.
the class UnnecessaryApiConversion method sawOpcode.
@Override
public void sawOpcode(int seen) {
try {
switch(seen) {
case INVOKEVIRTUAL:
FQMethod conversionMethod = new FQMethod(getClassConstantOperand(), getNameConstantOperand(), getSigConstantOperand());
LegacyInfo legacyInfo = conversions.get(conversionMethod);
if ((legacyInfo != null) && (stack.getStackDepth() > 0)) {
OpcodeStack.Item itm = stack.getStackItem(0);
XMethod xm = itm.getReturnValueOf();
if ((xm != null) && (xm.getName().equals(legacyInfo.methodName) && (xm.getClassName().equals(conversionMethod.getClassName().replace('/', '.'))))) {
bugReporter.reportBug(new BugInstance(this, legacyInfo.bugType.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
}
}
break;
default:
break;
}
} finally {
stack.sawOpcode(this, seen);
}
}
use of com.mebigfatguy.fbcontrib.utils.FQMethod in project fb-contrib by mebigfatguy.
the class StringifiedTypes method sawOpcode.
@Override
public void sawOpcode(int seen) {
String userValue = null;
int[] checkParms = null;
try {
stack.precomputation(this);
int stackDepth = stack.getStackDepth();
switch(seen) {
case Const.INVOKEVIRTUAL:
{
String clsName = getClassConstantOperand();
String methodName = getNameConstantOperand();
String sig = getSigConstantOperand();
boolean isStringBuilder = SignatureUtils.isPlainStringConvertableClass(clsName);
if (Values.TOSTRING.equals(methodName) && SignatureBuilder.SIG_VOID_TO_STRING.equals(sig)) {
if (isStringBuilder) {
if (stackDepth > 0) {
OpcodeStack.Item item = stack.getStackItem(0);
userValue = (String) item.getUserValue();
}
} else {
userValue = Values.TOSTRING;
}
} else if (isStringBuilder) {
if ("append".equals(methodName)) {
if (stackDepth > 0) {
OpcodeStack.Item item = stack.getStackItem(0);
userValue = (String) item.getUserValue();
if ((userValue == null) && !Values.SIG_JAVA_LANG_STRING.equals(item.getSignature())) {
userValue = Values.TOSTRING;
if (stackDepth > 1) {
item = stack.getStackItem(1);
int reg = item.getRegisterNumber();
if (reg >= 0) {
toStringStringBuilders.set(reg);
}
}
}
}
} else if ((stackDepth > 1) && "setLength".equals(methodName)) {
OpcodeStack.Item item = stack.getStackItem(1);
item.setUserValue(null);
int reg = item.getRegisterNumber();
if (reg >= 0) {
toStringStringBuilders.clear(reg);
}
}
} else if (Values.SLASHED_JAVA_LANG_STRING.equals(clsName)) {
Integer priority = STRING_PARSE_METHODS.get(methodName);
if (priority != null) {
int numParameters = SignatureUtils.getNumParameters(sig);
if (stackDepth > numParameters) {
OpcodeStack.Item item = stack.getStackItem(numParameters);
if ((item.getXField() != null) || FROM_FIELD.equals(item.getUserValue())) {
bugReporter.reportBug(new BugInstance(this, BugType.STT_STRING_PARSING_A_FIELD.name(), priority.intValue()).addClass(this).addMethod(this).addSourceLine(this));
}
}
}
}
}
break;
case Const.INVOKEINTERFACE:
{
String clsName = getClassConstantOperand();
String methodName = getNameConstantOperand();
String sig = getSigConstantOperand();
int numParameters = SignatureUtils.getNumParameters(sig);
if (stackDepth > numParameters) {
FQMethod cm = new FQMethod(clsName, methodName, sig);
checkParms = COLLECTION_PARMS.get(cm);
if (checkParms != null) {
OpcodeStack.Item item = stack.getStackItem(numParameters);
if (item.getXField() == null) {
if (MAP_PUT.equals(cm)) {
OpcodeStack.Item itm = stack.getStackItem(1);
XMethod xm = itm.getReturnValueOf();
if (xm != null) {
if (Values.DOTTED_JAVA_LANG_STRINGBUILDER.equals(xm.getClassName())) {
bugReporter.reportBug(new BugInstance(this, BugType.STT_TOSTRING_MAP_KEYING.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
}
}
}
} else {
for (int parm : checkParms) {
if ((parm >= 0) && Values.TOSTRING.equals(stack.getStackItem(parm).getUserValue())) {
bugReporter.reportBug(new BugInstance(this, BugType.STT_TOSTRING_STORED_IN_FIELD.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
break;
}
}
}
}
}
}
break;
case Const.PUTFIELD:
if (stackDepth > 0) {
OpcodeStack.Item item = stack.getStackItem(0);
if (Values.TOSTRING.equals(item.getUserValue())) {
bugReporter.reportBug(new BugInstance(this, BugType.STT_TOSTRING_STORED_IN_FIELD.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
}
}
break;
case Const.ALOAD:
case Const.ALOAD_0:
case Const.ALOAD_1:
case Const.ALOAD_2:
case Const.ALOAD_3:
{
int reg = RegisterUtils.getALoadReg(this, seen);
if (toStringStringBuilders.get(reg)) {
userValue = Values.TOSTRING;
}
}
break;
case Const.ASTORE:
case Const.ASTORE_0:
case Const.ASTORE_1:
case Const.ASTORE_2:
case Const.ASTORE_3:
{
int reg = RegisterUtils.getAStoreReg(this, seen);
toStringStringBuilders.clear(reg);
}
break;
default:
break;
}
} finally {
stack.sawOpcode(this, seen);
if ((userValue != null) && (stack.getStackDepth() > 0)) {
OpcodeStack.Item item = stack.getStackItem(0);
item.setUserValue(userValue);
}
if ((checkParms != null) && (checkParms[0] == -1) && (stack.getStackDepth() > 0)) {
OpcodeStack.Item item = stack.getStackItem(0);
item.setUserValue(FROM_FIELD);
}
}
}
Aggregations