1 19 20 package edu.umd.cs.findbugs.detect; 21 22 23 import edu.umd.cs.findbugs.*; 24 25 import org.apache.bcel.classfile.Method; 26 27 public class FindSpinLoop extends BytecodeScanningDetector implements StatelessDetector { 28 private static final boolean DEBUG = SystemProperties.getBoolean("findspinloop.debug"); 29 30 int stage = 0; 31 int start; 32 private BugReporter bugReporter; 33 private FieldAnnotation lastFieldSeen; 34 35 public FindSpinLoop(BugReporter bugReporter) { 36 this.bugReporter = bugReporter; 37 } 38 39 40 41 @Override 42 public void visit(Method obj) { 43 if (DEBUG) System.out.println("Saw " + getFullyQualifiedMethodName()); 44 stage = 0; 45 } 46 47 @Override 48 public void sawOpcode(int seen) { 49 50 switch (seen) { 52 case ALOAD_0: 53 case ALOAD_1: 54 case ALOAD_2: 55 case ALOAD_3: 56 case ALOAD: 57 if (DEBUG) System.out.println(" ALOAD at PC " + getPC()); 58 start = getPC(); 59 stage = 1; 60 break; 61 case GETSTATIC: 62 if (DEBUG) System.out.println(" getfield in stage " + stage); 63 lastFieldSeen = FieldAnnotation.fromReferencedField(this); 64 start = getPC(); 65 stage = 2; 66 break; 67 case GETFIELD: 68 if (DEBUG) System.out.println(" getfield in stage " + stage); 69 lastFieldSeen = FieldAnnotation.fromReferencedField(this); 70 if (stage == 1 || stage == 2 ) { 71 stage = 2; 72 } else 73 stage = 0; 74 break; 75 case GOTO: 76 case IFNE: 77 case IFEQ: 78 case IFNULL: 79 case IFNONNULL: 80 if (DEBUG) System.out.println(" conditional branch in stage " + stage + " to " + getBranchTarget()); 81 if (stage == 2 && getBranchTarget() == start) { 82 bugReporter.reportBug(new BugInstance(this, "SP_SPIN_ON_FIELD", NORMAL_PRIORITY) 83 .addClassAndMethod(this) 84 .addReferencedField(lastFieldSeen) 85 .addSourceLine(this, start) 86 ); 87 stage = 0; 88 } else if (getBranchTarget() < getPC()) 89 stage = 0; 90 break; 91 default: 92 stage = 0; 93 break; 94 } 95 96 } 97 } 98 | Popular Tags |