root/tools/android/findbugs_plugin/src/org/chromium/tools/findbugs/plugin/SynchronizedThisDetector.java

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. visit
  2. sawOpcode

// Copyright (c) 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 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;
        }
    }
}

/* [<][>][^][v][top][bottom][index][help] */