blob: 9a4e5e12226c769ef60fdedf165b7999fbfad2aa [file] [log] [blame]
// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.tools.findbugs.plugin;
import org.apache.bcel.classfile.Code;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
/**
* This class detects the synchronized(this).
*
* The pattern of byte code of synchronized(this) is
* aload_0 # Load the 'this' pointer on top of stack
* dup # Duplicate the 'this' pointer
* astore_x # Store this for late use, it might be astore.
* monitorenter
*/
public class SynchronizedThisDetector extends OpcodeStackDetector {
private static final int PATTERN[] = {ALOAD_0, DUP, 0xff, 0xff, MONITORENTER};
private int mStep = 0;
private BugReporter mBugReporter;
public SynchronizedThisDetector(BugReporter bugReporter) {
mBugReporter = bugReporter;
}
@Override
public void visit(Code code) {
mStep = 0;
super.visit(code);
}
@Override
public void sawOpcode(int seen) {
if (PATTERN[mStep] == seen) {
mStep++;
if (mStep == PATTERN.length) {
mBugReporter.reportBug(new BugInstance(this, "CHROMIUM_SYNCHRONIZED_THIS",
NORMAL_PRIORITY)
.addClassAndMethod(this)
.addSourceLine(this));
mStep = 0;
return;
}
} else if (mStep == 2) {
// This could be astore_x
switch (seen) {
case ASTORE_0:
case ASTORE_1:
case ASTORE_2:
case ASTORE_3:
mStep += 2;
break;
case ASTORE:
mStep++;
break;
default:
mStep = 0;
break;
}
} else if (mStep == 3) {
// Could be any byte following the ASTORE.
mStep++;
} else {
mStep = 0;
}
}
}