001: /*
002: * FindBugs - Find bugs in Java programs
003: * Copyright (C) 2003-2005 University of Maryland
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019:
020: package edu.umd.cs.findbugs.detect;
021:
022: import org.apache.bcel.classfile.Method;
023:
024: import edu.umd.cs.findbugs.BugInstance;
025: import edu.umd.cs.findbugs.BugReporter;
026: import edu.umd.cs.findbugs.BytecodeScanningDetector;
027: import edu.umd.cs.findbugs.FieldAnnotation;
028: import edu.umd.cs.findbugs.StatelessDetector;
029: import edu.umd.cs.findbugs.SystemProperties;
030:
031: public class FindSpinLoop extends BytecodeScanningDetector implements
032: StatelessDetector {
033: private static final boolean DEBUG = SystemProperties
034: .getBoolean("findspinloop.debug");
035:
036: int stage = 0;
037: int start;
038: private BugReporter bugReporter;
039: private FieldAnnotation lastFieldSeen;
040:
041: public FindSpinLoop(BugReporter bugReporter) {
042: this .bugReporter = bugReporter;
043: }
044:
045: @Override
046: public void visit(Method obj) {
047: if (DEBUG)
048: System.out.println("Saw " + getFullyQualifiedMethodName());
049: stage = 0;
050: }
051:
052: @Override
053: public void sawOpcode(int seen) {
054:
055: // System.out.println("PC: " + PC + ", stage: " + stage1);
056: switch (seen) {
057: case ALOAD_0:
058: case ALOAD_1:
059: case ALOAD_2:
060: case ALOAD_3:
061: case ALOAD:
062: if (DEBUG)
063: System.out.println(" ALOAD at PC " + getPC());
064: start = getPC();
065: stage = 1;
066: break;
067: case GETSTATIC:
068: if (DEBUG)
069: System.out.println(" getfield in stage " + stage);
070: lastFieldSeen = FieldAnnotation.fromReferencedField(this );
071: start = getPC();
072: stage = 2;
073: break;
074: case GETFIELD:
075: if (DEBUG)
076: System.out.println(" getfield in stage " + stage);
077: lastFieldSeen = FieldAnnotation.fromReferencedField(this );
078: if (stage == 1 || stage == 2) {
079: stage = 2;
080: } else
081: stage = 0;
082: break;
083: case GOTO:
084: case IFNE:
085: case IFEQ:
086: case IFNULL:
087: case IFNONNULL:
088: if (DEBUG)
089: System.out.println(" conditional branch in stage "
090: + stage + " to " + getBranchTarget());
091: if (stage == 2 && getBranchTarget() == start) {
092: bugReporter.reportBug(new BugInstance(this ,
093: "SP_SPIN_ON_FIELD", NORMAL_PRIORITY)
094: .addClassAndMethod(this ).addReferencedField(
095: lastFieldSeen).addSourceLine(this ,
096: start));
097: stage = 0;
098: } else if (getBranchTarget() < getPC())
099: stage = 0;
100: break;
101: default:
102: stage = 0;
103: break;
104: }
105:
106: }
107: }
|