edu.ksu.cis.indus.staticanalyses.concurrency.escape.LockAcquisitionBasedEquivalence.java Source code

Java tutorial

Introduction

Here is the source code for edu.ksu.cis.indus.staticanalyses.concurrency.escape.LockAcquisitionBasedEquivalence.java

Source

/*******************************************************************************
 * Indus, a program analysis and transformation toolkit for Java.
 * Copyright (c) 2001, 2007 Venkatesh Prasad Ranganath
 * 
 * All rights reserved.  This program and the accompanying materials are made 
 * available under the terms of the Eclipse Public License v1.0 which accompanies 
 * the distribution containing this program, and is available at 
 * http://www.opensource.org/licenses/eclipse-1.0.php.
 * 
 * For questions about the license, copyright, and software, contact 
 *    Venkatesh Prasad Ranganath at venkateshprasad.ranganath@gmail.com
 *                                 
 * This software was developed by Venkatesh Prasad Ranganath in SAnToS Laboratory 
 * at Kansas State University.
 *******************************************************************************/

package edu.ksu.cis.indus.staticanalyses.concurrency.escape;

import edu.ksu.cis.indus.common.collections.MapUtils;
import edu.ksu.cis.indus.common.datastructures.Pair;
import edu.ksu.cis.indus.common.soot.Util;
import edu.ksu.cis.indus.interfaces.ICallGraphInfo;
import edu.ksu.cis.indus.interfaces.IEscapeInfo;
import edu.ksu.cis.indus.processing.AbstractProcessor;
import edu.ksu.cis.indus.processing.Context;
import edu.ksu.cis.indus.processing.ProcessingController;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.lang.builder.ToStringBuilder;

import soot.Local;
import soot.SootMethod;
import soot.jimple.EnterMonitorStmt;
import soot.jimple.InvokeStmt;
import soot.jimple.Stmt;
import soot.jimple.VirtualInvokeExpr;

/**
 * This class calculates equivalence classes of locking statements that may acquire same locks. In simple words, two lock
 * acquisition statements (enter-monitor or synchronized method invocation) belong to the same equivalence class if they may
 * acquire the lock on the same object.
 * 
 * @author <a href="http://www.cis.ksu.edu/~rvprasad">Venkatesh Prasad Ranganath</a>
 * @author $Author: rvprasad $
 * @version $Revision: 1.7 $ $Date: 2007/02/10 19:07:04 $
 */
public class LockAcquisitionBasedEquivalence extends AbstractProcessor {

    /**
     * This provides the call graph.
     */
    private ICallGraphInfo cgi;

    /**
     * This is a collection of enter monitor statements.
     */
    private final Collection<Pair<EnterMonitorStmt, SootMethod>> enterMonitorStmts;

    /**
     * This is a collection of invocation statements.
     */
    private final Collection<Pair<InvokeStmt, SootMethod>> invokeStmts;

    /**
     * This provides locking information.
     */
    private final IEscapeInfo locking;

    /**
     * This maps a lock acquisition statement to the collection of lock acquisition statements that are in the same
     * equivalence class as the key.
     * 
     * @invariant locking2lockings.oclIsKindOf(Map(Pair(Stmt, SootMethod), Collection(Pair(Stmt, SootMethod))))
     * @invariant locking2lockings.keySet()->forall(o | o.getFirst().oclIsKindOf(EnterMonitorStmt) or
     *            o.getFirst().containsInvokeExpr())
     */
    private final Map<Pair<? extends Stmt, SootMethod>, Collection<Pair<? extends Stmt, SootMethod>>> locking2lockings;

    /**
     * Creates a new LockAcquisitionBasedEquivalence object.
     * 
     * @param escapeInfo to be used.
     * @param callgraph to be used.
     * @pre escapeInfo != null and callgraph != null
     */
    public LockAcquisitionBasedEquivalence(final IEscapeInfo escapeInfo, final ICallGraphInfo callgraph) {
        locking = escapeInfo;
        cgi = callgraph;
        locking2lockings = new HashMap<Pair<? extends Stmt, SootMethod>, Collection<Pair<? extends Stmt, SootMethod>>>();
        enterMonitorStmts = new HashSet<Pair<EnterMonitorStmt, SootMethod>>();
        invokeStmts = new HashSet<Pair<InvokeStmt, SootMethod>>();
    }

    /**
     * @see edu.ksu.cis.indus.processing.IProcessor#callback(soot.SootMethod)
     */
    @Override
    public void callback(final SootMethod method) {
        if (method.isSynchronized()) {
            final Pair<EnterMonitorStmt, SootMethod> _p = new Pair<EnterMonitorStmt, SootMethod>(null, method);
            enterMonitorStmts.add(_p);
            processLocal(null, method, _p);
        }
    }

    /**
     * @see edu.ksu.cis.indus.processing.IProcessor#callback(soot.jimple.Stmt, Context)
     */
    @Override
    public void callback(final Stmt stmt, final Context context) {
        final SootMethod _method = context.getCurrentMethod();

        if (stmt instanceof InvokeStmt) {
            if (Util.isWaitInvocation((InvokeStmt) stmt, _method, cgi)) {
                final InvokeStmt _s = (InvokeStmt) stmt;
                final Pair<InvokeStmt, SootMethod> _p = new Pair<InvokeStmt, SootMethod>(_s, _method);
                final Local _l = (Local) ((VirtualInvokeExpr) _s.getInvokeExpr()).getBase();
                invokeStmts.add(_p);
                processLocal(_l, _method, _p);
            }
        } else {
            final EnterMonitorStmt _n = (EnterMonitorStmt) stmt;
            final Pair<EnterMonitorStmt, SootMethod> _p = new Pair<EnterMonitorStmt, SootMethod>(_n, _method);
            final Local _l = (Local) _n.getOp();
            enterMonitorStmts.add(_p);
            processLocal(_l, _method, _p);
        }
    }

    /**
     * @see edu.ksu.cis.indus.processing.AbstractProcessor#consolidate()
     */
    @Override
    public void consolidate() {
        super.consolidate();
        enterMonitorStmts.clear();
        invokeStmts.clear();
    }

    /**
     * Retrieves the lock acquisitions that belong to the same equivalence class as the given lock acquisition.
     * 
     * @param pair of interest.
     * @return a collection of lock acquisition.
     * @pre pair.oclIsKindOf(Pair(InvokeStmt, SootMethod)) or pair.oclIsKindOf(Pair(EnterMonitorStmt, SootMethod))
     * @post result != null
     * @post
     * @post result->forall(o | o.oclIsKindOf(Pair(InvokeStmt, SootMethod)) or o.oclIsKindOf(Pair(EnterMonitorStmt,
     *       SootMethod)))
     */
    public Collection<Pair<? extends Stmt, SootMethod>> getLockAcquisitionsInEquivalenceClassOf(
            final Pair<Stmt, SootMethod> pair) {
        return Collections.unmodifiableCollection(MapUtils.getEmptyCollectionFromMap(locking2lockings, pair));
    }

    /**
     * Retrieves the lock acquisitions that belong to a non-singleton equivalence class.
     * 
     * @return a collection of lock acquisition.
     * @post result != null
     * @post result->forall(o | o.oclIsKindOf(Pair(InvokeStmt, SootMethod)) or o.oclIsKindOf(Pair(EnterMonitorStmt,
     *       SootMethod)))
     */
    public Collection<Pair<? extends Stmt, SootMethod>> getLockAcquisitionsInNonSingletonEquivalenceClass() {
        final Collection<Pair<? extends Stmt, SootMethod>> _r = new HashSet<Pair<? extends Stmt, SootMethod>>();
        final Iterator<Map.Entry<Pair<? extends Stmt, SootMethod>, Collection<Pair<? extends Stmt, SootMethod>>>> _i;
        _i = locking2lockings.entrySet().iterator();
        final int _iEnd = locking2lockings.entrySet().size();
        for (int _iIndex = 0; _iIndex < _iEnd; _iIndex++) {
            final Map.Entry<Pair<? extends Stmt, SootMethod>, Collection<Pair<? extends Stmt, SootMethod>>> _e = _i
                    .next();
            if (_e.getValue().size() > 1) {
                _r.add(_e.getKey());
            }
        }
        return _r;
    }

    /**
     * @see edu.ksu.cis.indus.processing.IProcessor#hookup(ProcessingController)
     */
    public void hookup(final ProcessingController ppc) {
        ppc.register(EnterMonitorStmt.class, this);
        ppc.register(InvokeStmt.class, this);
        ppc.register(this);
    }

    /**
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return new ToStringBuilder(this).appendSuper(super.toString())
                .append("monitorStmts", this.enterMonitorStmts).append("invokeStmts", this.invokeStmts)
                .append("locking2lockings", this.locking2lockings).toString();
    }

    /**
     * @see edu.ksu.cis.indus.processing.IProcessor#unhook(ProcessingController)
     */
    public void unhook(final ProcessingController ppc) {
        ppc.unregister(EnterMonitorStmt.class, this);
        ppc.unregister(InvokeStmt.class, this);
        ppc.unregister(this);
    }

    /**
     * Processes the given local in the given method to calculate if it is related to the given lock acquisition.
     * 
     * @param local of interest.
     * @param method in which <code>local</code> occurs.
     * @param p is a lock acquisition.
     * @pre method != null and p != null
     */
    private void processLocal(final Local local, final SootMethod method,
            final Pair<? extends Stmt, SootMethod> p) {
        final Iterator<Pair<InvokeStmt, SootMethod>> _i = invokeStmts.iterator();
        final int _iEnd = invokeStmts.size();

        for (int _iIndex = 0; _iIndex < _iEnd; _iIndex++) {
            final Pair<InvokeStmt, SootMethod> _p2 = _i.next();
            final InvokeStmt _s = _p2.getFirst();
            final SootMethod _sm = _p2.getSecond();
            final Local _l2 = _s == null ? null : (Local) ((VirtualInvokeExpr) _s.getInvokeExpr()).getBase();

            if (locking.areCoupledViaLocking(local, method, _l2, _sm)) {
                MapUtils.putIntoSetInMap(locking2lockings, _p2, p);
                MapUtils.putIntoSetInMap(locking2lockings, p, _p2);
            }
        }

        final Iterator<Pair<EnterMonitorStmt, SootMethod>> _j = enterMonitorStmts.iterator();
        final int _jEnd = enterMonitorStmts.size();

        for (int _jIndex = 0; _jIndex < _jEnd; _jIndex++) {
            final Pair<EnterMonitorStmt, SootMethod> _p2 = _j.next();
            final EnterMonitorStmt _s = _p2.getFirst();
            final SootMethod _sm = _p2.getSecond();
            final Local _l2 = _s == null ? null : (Local) _s.getOp();

            if (locking.areCoupledViaLocking(local, method, _l2, _sm)) {
                MapUtils.putIntoSetInMap(locking2lockings, _p2, p);
                MapUtils.putIntoSetInMap(locking2lockings, p, _p2);
            }
        }
    }
}

// End of File