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

Java tutorial

Introduction

Here is the source code for edu.ksu.cis.indus.staticanalyses.concurrency.escape.SharedWriteBasedEquivalence.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.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.SootField;
import soot.SootMethod;
import soot.ValueBox;
import soot.jimple.AssignStmt;
import soot.jimple.DefinitionStmt;
import soot.jimple.FieldRef;
import soot.jimple.InstanceFieldRef;
import soot.jimple.StaticFieldRef;
import soot.jimple.Stmt;

/**
 * This class contains the logic to calculate equivalence classes of shared-write statements in the system. Two shared-write
 * statement belong to the same equivalence class if they may write to the same field/array cell.
 * 
 * @author <a href="http://www.cis.ksu.edu/~rvprasad">Venkatesh Prasad Ranganath</a>
 * @author $Author: rvprasad $
 * @version $Revision: 1.8 $ $Date: 2007/02/10 19:07:04 $
 */
public class SharedWriteBasedEquivalence extends AbstractProcessor {

    /**
     * This is the collection of definition statements involving array reference or field reference.
     * 
     * @invariant defStmts->forall(o | o.containsArrayRef() or o.containsFieldRef())
     */
    private final Collection<Pair<AssignStmt, SootMethod>> defStmts;

    /**
     * This provides escape information.
     */
    private final IEscapeInfo einfo;

    /**
     * This maps a shared write statement to the collection of shared write statements that are in the same equivalence class
     * as the key.
     * 
     * @invariant write2writes.keySet()->forall(o | o.getFirst().getLeftOp().oclIsKindOf(ArrayRef) or
     *            o.getFirst().getLeftOp().oclIsKindOf(StaticFieldRef) or
     *            o.getFirst().getLeftOp().oclIsKindOf(InstanceFieldRef))
     */
    private final Map<Pair<AssignStmt, SootMethod>, Collection<Pair<AssignStmt, SootMethod>>> write2writes;

    /**
     * Creates an instance of this class.
     * 
     * @param escapeInfo to be used.
     */
    public SharedWriteBasedEquivalence(final IEscapeInfo escapeInfo) {
        einfo = escapeInfo;
        write2writes = new HashMap<Pair<AssignStmt, SootMethod>, Collection<Pair<AssignStmt, SootMethod>>>();
        defStmts = new HashSet<Pair<AssignStmt, SootMethod>>();
    }

    /**
     * {@inheritDoc}
     * 
     * @see edu.ksu.cis.indus.processing.AbstractProcessor#callback(soot.ValueBox, edu.ksu.cis.indus.processing.Context)
     */
    @Override
    public void callback(final ValueBox vBox, final Context context) {
        final Stmt _stmt = context.getStmt();

        if (((AssignStmt) _stmt).getLeftOpBox() == vBox) {
            final SootMethod _currentMethod = context.getCurrentMethod();
            final Pair<AssignStmt, SootMethod> _pair = new Pair<AssignStmt, SootMethod>((AssignStmt) _stmt,
                    _currentMethod);
            defStmts.add(_pair);
        }
    }

    /**
     * Calculates write-write based dependence.
     */
    @Override
    public void consolidate() {
        final Iterator<Pair<AssignStmt, SootMethod>> _i = defStmts.iterator();
        final int _iEnd = defStmts.size();

        for (int _iIndex = 0; _iIndex < _iEnd; _iIndex++) {
            final Pair<AssignStmt, SootMethod> _p1 = _i.next();
            final DefinitionStmt _s1 = _p1.getFirst();
            final SootMethod _m1 = _p1.getSecond();
            final Iterator<Pair<AssignStmt, SootMethod>> _j = defStmts.iterator();

            for (int _jIndex = 0; _jIndex < _iEnd; _jIndex++) {
                final Pair<AssignStmt, SootMethod> _p2 = _j.next();
                final DefinitionStmt _s2 = _p2.getFirst();
                final SootMethod _m2 = _p2.getSecond();

                if (writeWriteExecutionDependence(_s1, _m1, _s2, _m2)) {
                    MapUtils.putIntoSetInMap(write2writes, _p1, _p2);
                    MapUtils.putIntoSetInMap(write2writes, _p2, _p1);
                }
            }
        }

        defStmts.clear();
    }

    /**
     * Retrieves the shared writes that belong to the same equivalence class as the given shared write.
     * 
     * @param pair of interest.
     * @return a collection of lock acquisition.
     * @pre pair.getFirst().getLeftOp().oclIsKindOf(InstanceFieldRef) or
     *      pair.getFirst().getLeftOp().oclIsKindOf(StaticFieldRef) or pair.getFirst().getLeftOp().oclIsKindOf(ArrayRef)
     * @post result != null
     * @post result->forall(o |
     */
    public Collection<Pair<AssignStmt, SootMethod>> getSharedWritesInEquivalenceClassOf(
            final Pair<AssignStmt, SootMethod> pair) {
        return Collections.unmodifiableCollection(MapUtils.queryCollection(write2writes, pair));
    }

    /**
     * Retrieves the shared writes that belong to a non-singleton equivalence class.
     * 
     * @return a collection of lock acquisition.
     * @post result.getFirst().oclIsKindOf(AssignStmt)
     * @post result.getFirst().getLeftOp().oclIsKindOf(InstanceFieldRef) or
     *       result.getFirst().getLeftOp().oclIsKindOf(StaticFieldRef) or result.getFirst().getLeftOp().oclIsKindOf(ArrayRef)
     * @post result != null
     */
    public Collection<Pair<AssignStmt, SootMethod>> getSharedWritesInNonSingletonEquivalenceClass() {
        return Collections.unmodifiableCollection(write2writes.keySet());
    }

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

    /**
     * {@inheritDoc}
     * 
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return new ToStringBuilder(this).append("defStmts", defStmts).append("write2writes", write2writes)
                .toString();
    }

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

    /**
     * Checks if the given definition statements are dependent based on the fact that they may update the same field on an
     * object or the same cell of an array.
     * 
     * @param s1 is one statement of interest.
     * @param m1 is the method containing <code>s1</code>.
     * @param s2 is the second statement of interest.
     * @param m2 is the method containing <code>s2</code>.
     * @return <code>true</code> if both <code>s1</code> and <code>s2</code> contain either array/field ref in the
     *         l-position; <code>false</code>, otherwise.
     * @pre s1 != null and m1 != null and s2 != null and m2 != null
     */
    private boolean writeWriteExecutionDependence(final DefinitionStmt s1, final SootMethod m1,
            final DefinitionStmt s2, final SootMethod m2) {
        boolean _result = false;

        if (s1.containsArrayRef() && s2.containsArrayRef()) {
            _result = einfo.fieldAccessShared(s1.getArrayRef().getBase(), m1, s2.getArrayRef().getBase(), m2,
                    IEscapeInfo.WRITE_WRITE_SHARED_ACCESS);
        } else if (s1.containsFieldRef() && s2.containsFieldRef()) {
            final FieldRef _fieldRef2 = s2.getFieldRef();
            final FieldRef _fieldRef1 = s1.getFieldRef();
            final SootField _field1 = _fieldRef1.getField();

            if (_field1.equals(_fieldRef2.getField())) {
                if (_fieldRef1 instanceof InstanceFieldRef && _fieldRef2 instanceof InstanceFieldRef) {
                    _result = einfo.fieldAccessShared(((InstanceFieldRef) _fieldRef1).getBase(), m1,
                            ((InstanceFieldRef) _fieldRef2).getBase(), m2, IEscapeInfo.WRITE_WRITE_SHARED_ACCESS);
                } else if (_fieldRef1 instanceof StaticFieldRef && _fieldRef2 instanceof StaticFieldRef) {
                    _result = !EquivalenceClassBasedEscapeAnalysis.canHaveAliasSet(_field1.getType())
                            || einfo.fieldAccessShared(_fieldRef1, m1, _fieldRef2, m2,
                                    IEscapeInfo.WRITE_WRITE_SHARED_ACCESS);
                }
            }
        }
        return _result;
    }
}

// End of File