Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

InterClassAnalysis.java

00001 package edu.ksu.cis.bandera.pdgslicer;
00002 
00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00004  * Bandera, a Java(TM) analysis and transformation toolkit           *
00005  * Copyright (C) 1998, 1999   Hongjun Zheng (zheng@cis.ksu.edu)      *
00006  * All rights reserved.                                              *
00007  *                                                                   *
00008  * This work was done as a project in the SAnToS Laboratory,         *
00009  * Department of Computing and Information Sciences, Kansas State    *
00010  * University, USA (http://www.cis.ksu.edu/santos).                  *
00011  * It is understood that any modification not identified as such is  *
00012  * not covered by the preceding statement.                           *
00013  *                                                                   *
00014  * This work is free software; you can redistribute it and/or        *
00015  * modify it under the terms of the GNU Library General Public       *
00016  * License as published by the Free Software Foundation; either      *
00017  * version 2 of the License, or (at your option) any later version.  *
00018  *                                                                   *
00019  * This work is distributed in the hope that it will be useful,      *
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of    *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *
00022  * Library General Public License for more details.                  *
00023  *                                                                   *
00024  * You should have received a copy of the GNU Library General Public *
00025  * License along with this toolkit; if not, write to the             *
00026  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,      *
00027  * Boston, MA  02111-1307, USA.                                      *
00028  *                                                                   *
00029  * Java is a trademark of Sun Microsystems, Inc.                     *
00030  *                                                                   *
00031  * To submit a bug report, send a comment, or get the latest news on *
00032  * this project and other SAnToS projects, please visit the web-site *
00033  *                http://www.cis.ksu.edu/santos                      *
00034  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00035 
00036 
00037 import ca.mcgill.sable.util.*;
00038 import ca.mcgill.sable.soot.*;
00039 import ca.mcgill.sable.soot.jimple.*;
00040 
00041 import edu.ksu.cis.bandera.pdgslicer.exceptions.*;
00042 
00043 import java.util.Enumeration;
00044 
00045 /**
00046  * This class is for the analysis of ready dependence
00047  * and interference dependence.
00048  */
00049 public class InterClassAnalysis
00050 {
00051   /**
00052    * A list of {@link ClassInfo ClassInfo}.
00053    */
00054   private List classList;
00055 
00056   /**
00057    * This constructor calls
00058    * <br> (1) {@link #readyDependence() readyDependenc()}
00059    * <br> (2) {@link #interferenceDependence() interferenceDependence()}.
00060    * <p>
00061    * @param cl a list of {@link ClassInfo ClassInfo}.'
00062    */
00063 public InterClassAnalysis(List cl) {
00064     classList = cl;
00065     readyDependence();
00066     interferenceDependence();
00067 }
00068     /**
00069      * Check (find out) all definitions in one method for each field reference
00070      * in the set <code>interferRefList</code>. And put those definitions
00071      * into the interference map.
00072      * <p>
00073      * @param interferenceMap interference map.
00074      * @param methodInfo method to be checked.
00075      * @param interferRefList a list of {@link DataBox DataBox} 
00076      * represents a reference of field.
00077      */
00078 private void checkOneMdForInsFdsNotInCurrentClass(Map interferenceMap, MethodInfo methodInfo, Set interferRefList) {
00079     SootClass currentModClass = methodInfo.sootClass;
00080     List onInterferDefList = new ArrayList();
00081     onInterferDefList.addAll(methodInfo.MOD.instanceFields);
00082     onInterferDefList.addAll(methodInfo.MOD.otherInsFds);
00083     if (onInterferDefList.isEmpty()) return;
00084     //interference analysis
00085     for (Iterator interRefIt = interferRefList.iterator(); interRefIt.hasNext();) {
00086         DataBox interRefBox = (DataBox) interRefIt.next();
00087         Stmt interferStmt = (Stmt) interRefBox.getInterferStmt();
00088         Set interferVars = (Set) interRefBox.getInterferVars();
00089         for (Iterator insFdIt = interferVars.iterator(); insFdIt.hasNext();) {
00090             InstanceFieldRef refField = (InstanceFieldRef) insFdIt.next();
00091             SootClass decClass = refField.getField().getDeclaringClass();
00092             //if (!decClass.equals(currentModClass)) continue;
00093             for (Iterator onInterDefIt = onInterferDefList.iterator(); onInterDefIt.hasNext();) {
00094                 DataBox onInterDefBox = (DataBox) onInterDefIt.next();
00095                 Set onInterVars = onInterDefBox.getInterferVars();
00096                 Set actualInterVars = containsField(onInterVars, refField.getField());
00097                 if (!actualInterVars.isEmpty()) {
00098                     //put dependent relation to the interferenceMap
00099                     Stmt onStmt = (Stmt) onInterDefBox.getInterferStmt();
00100                     InterferStmt onInterStmt = new InterferStmt(methodInfo, onStmt, actualInterVars);
00101                     List interferList = (List) interferenceMap.get(interferStmt);
00102                     interferList.add(onInterStmt);
00103                 }
00104             }
00105         }
00106     }
00107 }
00108     /**
00109      * Check all definitions in one method such that define values which
00110      * are used in an element of <code>interferRefList</code>. And put those 
00111      * definitions intp interference map.
00112      * <p> 
00113      * @param interferenceMap interference map from {@link Stmt Stmt} to
00114      * a {@link List List} of {@link InterferStmt InterferStmt}.
00115      * @param methodInfo method be checked.
00116      * @param interferRefList a list of {@link DataBox DataBox} which represents
00117      * a reference of field.
00118      * @param havaInstanceField control if the check will include instance field references.
00119      */  
00120 private void checkOneMethod(Map interferenceMap, MethodInfo methodInfo, Set interferRefList, boolean haveInstanceField) {
00121     Set staticDefList = methodInfo.MOD.staticFields;
00122     List onInterferDefList = new ArrayList();
00123     onInterferDefList.addAll(staticDefList);
00124     if (haveInstanceField) 
00125         onInterferDefList.addAll(methodInfo.MOD.instanceFields);
00126         if (onInterferDefList.isEmpty()) return;
00127     //interference analysis
00128     for (Iterator interRefIt = interferRefList.iterator(); interRefIt.hasNext();) {
00129         DataBox interRefBox = (DataBox) interRefIt.next();
00130         Stmt interferStmt = (Stmt) interRefBox.getInterferStmt();
00131         Set interferRefs = (Set) interRefBox.getInterferVars();
00132         Set interferVars = BuildPDG.fieldRefToSootField(interferRefs);
00133         for (Iterator onInterDefIt = onInterferDefList.iterator(); onInterDefIt.hasNext();) {
00134             DataBox onInterDefBox = (DataBox) onInterDefIt.next();
00135             Set onInterRefs = onInterDefBox.getInterferVars();
00136             Set onInterVars = BuildPDG.fieldRefToSootField(onInterRefs);
00137             Set actualInterVars = SetUtil.setIntersection(interferVars, onInterVars);
00138             if (!actualInterVars.isEmpty()) {
00139                 //put dependent relation to the interferenceMap
00140                 Stmt onStmt = (Stmt) onInterDefBox.getInterferStmt();
00141                 InterferStmt onInterStmt = new InterferStmt(methodInfo, onStmt, actualInterVars);
00142                 List interferList = (List) interferenceMap.get(interferStmt);
00143                 interferList.add(onInterStmt);
00144             }
00145         }
00146     }
00147 }
00148 /**
00149  * Get all field references from a set with the given field <code>sf</code>.
00150  * <p>
00151  * @return a set of {@link InstanceFieldRef InstanceFieldRef}.
00152  * @param insFdSet a set of {@link InstanceFieldRef InstanceFieldRef}.
00153  * @param sf a sootfield.
00154  */
00155 private Set containsField(Set insFdSet, SootField sf) {
00156     Set conSet = new ArraySet();
00157     for (Iterator fdIt = insFdSet.iterator(); fdIt.hasNext();) {
00158         InstanceFieldRef insFd = (InstanceFieldRef) fdIt.next();
00159         SootField fd = insFd.getField();
00160         if (sf.equals(fd)) {
00161             conSet.add(insFd);
00162             return conSet;
00163         }
00164     }
00165     return conSet;
00166 }
00167   /**
00168    * Initialize interference map with given set.
00169    * <p>
00170    * @param fieldRefList a set of field reference {@link DataBox DataBox}.
00171    * @param interfMap interference map to be initialized.
00172    */
00173 private void initInterferenceMap(Set fieldRefList, Map interfMap) {
00174     for (Iterator interStmtIt = fieldRefList.iterator(); interStmtIt.hasNext();) {
00175         DataBox stmtBox = (DataBox) interStmtIt.next();
00176         Stmt stmt = stmtBox.getInterferStmt();
00177         interfMap.put(stmt, new ArrayList());
00178     }
00179 }
00180 /**
00181    * Analyse interference dependence for each method by calling
00182    * {@link #interferForMethod(MethodInfo) interferForMethod()}.
00183    */
00184 private void interferenceDependence() {
00185     Map sootMethodInfoMap = Slicer.sootMethodInfoMap;
00186     for (Iterator mdIt = sootMethodInfoMap.keySet().iterator(); mdIt.hasNext();) {
00187         SootMethod sootMethod = (SootMethod) mdIt.next();
00188 
00189         MethodInfo methodInfo = (MethodInfo) sootMethodInfoMap.get(sootMethod);
00190         if (methodInfo == null)
00191             continue;
00192         BuildPDG methodPDG = methodInfo.methodPDG;
00193 
00194         //stmt(ref) to interClassStmt(def on share variable) list map
00195         Map interferenceMap = interferForMethod(methodInfo);
00196         methodPDG.setInterferenceMap(interferenceMap);
00197     }
00198 }
00199 /**
00200    * Analyse intereference dependence for one method by calling
00201    * <br> (1) {@link #initInterferenceMap(Set,Map) initInterferenceMap()};
00202    * <br> (2) {@link #checkOneMethod(Map,MethodInfo,Set, boolean) checkOneMethod()};
00203    * checkOneMethodForStaticBasedFd()};
00204    * <br> (4) {@link #checkOneMdForInsFdsNotInCurrentClass(Map,MethodInfo,Set)
00205    * checkOneMdForInsFdsNotInCurrentClss()};
00206    * <br> (5) {@link #lookupInterferDefStmt(ClassInfo,Map,MethodInfo)
00207    * lookupInterferDefStmt()}.
00208    * <p>
00209    * @param currentMethod current method.
00210    * @return a map of interference dependence from
00211    * {@link Stmt Stmt} to a {@link List List} of {@link InterferStmt InterferStmt}.
00212    */
00213 private Map interferForMethod(MethodInfo currentMethod) {
00214     Set staticFdRefList = currentMethod.REF.staticFields;
00215 
00216     Set instanceFdRefList = currentMethod.REF.instanceFields;
00217     Set otherInsFdsRefList = currentMethod.REF.otherInsFds;
00218     Map interferenceMap = new HashMap();
00219 
00220     //in current, we put all the statement into the map, in the future
00221     //we will only put the statement that has interference dependence
00222     //this will save memory a lot.
00223 
00224     //initialization of interference Map to empty list
00225     initInterferenceMap(instanceFdRefList, interferenceMap);
00226     initInterferenceMap(staticFdRefList, interferenceMap);
00227 
00228     initInterferenceMap(otherInsFdsRefList, interferenceMap);
00229 
00230     //lookup all the statement in stmtList such that use some shared
00231     //variable, in current stage we consider all the static reference
00232     //variable as possible shared variable
00233 
00234     for (Iterator classIter = classList.iterator(); classIter.hasNext();) {
00235         ClassInfo classInfo = (ClassInfo) classIter.next();
00236         if (!classInfo.sootClass.equals(currentMethod.sootClass)) {
00237             for (Iterator methodIt = classInfo.methodsInfoList.iterator(); methodIt.hasNext();) {
00238                 MethodInfo methodInfo = (MethodInfo) methodIt.next();
00239                 checkOneMethod(interferenceMap, methodInfo, instanceFdRefList, true);
00240                 checkOneMethod(interferenceMap, methodInfo, staticFdRefList, false);
00241 
00242                 checkOneMdForInsFdsNotInCurrentClass(interferenceMap, methodInfo, otherInsFdsRefList);
00243             }
00244         } else {
00245             lookupInterferDefStmt(classInfo, interferenceMap, currentMethod);
00246         }
00247     }
00248     return interferenceMap;
00249 }
00250 /**
00251  * Find out all definitions in curren class for each use of field reference in 
00252  * current method. And put those definitions into interference map.
00253  * <p>
00254  * @param classInfo current class.
00255  * @param interferenceMap interference map.
00256  * @param currentMdInfo current method.
00257  */
00258 private void lookupInterferDefStmt(ClassInfo classInfo, Map interferenceMap, MethodInfo currentMdInfo) {
00259     String className = classInfo.sootClass.getName();
00260     Set staticFdRefList = currentMdInfo.REF.staticFields;
00261     Set instanceFdRefList = currentMdInfo.REF.instanceFields;
00262     Set otherInsFdsRefList = currentMdInfo.REF.otherInsFds;
00263     LockAnalysis lockAnaOfCurrentMd = currentMdInfo.methodPDG.getLockAnalysis();
00264     boolean initiated = false;
00265     boolean haveInstanceFd = false;
00266     for (Iterator methodIt = classInfo.methodsInfoList.iterator(); methodIt.hasNext();) {
00267         MethodInfo methodInfo = (MethodInfo) methodIt.next();
00268         if (methodInfo.equals(currentMdInfo))
00269             continue;
00270         haveInstanceFd = false;
00271         Set interferRefList = new ArraySet();
00272         interferRefList.addAll(staticFdRefList);
00273         LockAnalysis lockAnaOfDefMd = methodInfo.methodPDG.getLockAnalysis();
00274         if (methodInfo.sootMethod.getName().equals("<init>") || methodInfo.sootMethod.getName().equals("<clinit>")) {
00275             interferRefList.addAll(instanceFdRefList);
00276             haveInstanceFd = true;
00277             /*
00278             if (!initiated) {
00279                 initInterferenceMap(instanceFdRefList, interferenceMap);
00280                 initiated = true;
00281             }
00282             */
00283         } else {
00284             //if ((lockAnaOfCurrentMd != null) && (lockAnaOfDefMd != null)) {
00285             //if (lockAnaOfCurrentMd.mutualLock(lockAnaOfDefMd)) {
00286             //add instance field to interferRefList and onInterferDefList
00287 
00288             interferRefList.addAll(instanceFdRefList);
00289             haveInstanceFd = true;
00290             /*
00291             if (!initiated) {
00292                 initInterferenceMap(instanceFdRefList, interferenceMap);
00293                 initiated = true;
00294             }
00295             */
00296             //}
00297         }
00298         if (!haveInstanceFd)
00299             checkOneMethod(interferenceMap, methodInfo, staticFdRefList, haveInstanceFd);
00300         else {
00301             checkOneMethod(interferenceMap, methodInfo, interferRefList, haveInstanceFd);
00302         }
00303         checkOneMdForInsFdsNotInCurrentClass(interferenceMap, methodInfo, otherInsFdsRefList);
00304     }
00305 }
00306   /**
00307    * Look up all ready dependence from a list of method starting from current method
00308    * with lock pair list and wait statement list.
00309    * <br> There are two kinds of ready dependences: entermonitor statement in one method may
00310    * be ready dependent on exitmonitor statement in other method, if they are associated with
00311    * the same lock; wait statement in one method may be ready dependent on notify or notifyAll
00312    * statement in other method, if they are associated with the same lock.
00313    * <p>
00314    * @param readyMap map for ready dependence.
00315    * @param methodsList a list of {@link MethodInfo MethodInfo}.
00316    * @param currentMethodInfo current method.
00317    * @param lockPairList lock pair list.
00318    * @param waitStmtList wait statement list.
00319    */
00320 private void lookupReadyDependStmt(Map readyMap, List methodsList, MethodInfo currentMethodInfo, List lockPairList, List waitStmtList) {
00321     for (Iterator methodIt = methodsList.iterator(); methodIt.hasNext();) {
00322         MethodInfo methodInfo = (MethodInfo) methodIt.next();
00323         if (currentMethodInfo.equals(methodInfo))
00324             continue;
00325         BuildPDG methodPDG = methodInfo.methodPDG;
00326         LockAnalysis lockAnalysis = methodPDG.getLockAnalysis();
00327         if (lockAnalysis == null)
00328             continue;
00329         List onLockPairList = lockAnalysis.getLockPairList();
00330         List notifyStmtList = lockAnalysis.getNotifyStmtList();
00331         //lock analysis
00332         for (Iterator lockPairIt = lockPairList.iterator(); lockPairIt.hasNext();) {
00333             MonitorPair monitorPair = (MonitorPair) lockPairIt.next();
00334             Value lockValue = monitorPair.getLock();
00335             Stmt enterStmt = (Stmt) monitorPair.getEnterMonitor();
00336             for (Iterator onLockPairIt = onLockPairList.iterator(); onLockPairIt.hasNext();) {
00337                 MonitorPair onMonitorPair = (MonitorPair) onLockPairIt.next();
00338                 Value onLockValue = onMonitorPair.getLock();
00339                 if (BuildPDG.mayPointToTheSameRef(lockValue, onLockValue, currentMethodInfo.sootMethod, methodInfo.sootMethod)) {
00340                     //put dependent relation to the readyMap
00341                     for (Iterator exitIt = onMonitorPair.getExitMonitors().iterator(); exitIt.hasNext();) {
00342                         Stmt exitStmt = (Stmt) exitIt.next();
00343                         ReadyDependStmt onExitStmt = new ReadyDependStmt(methodInfo, exitStmt);
00344                         List readyList = (List) readyMap.get(enterStmt);
00345                         readyList.add(onExitStmt);
00346                     }
00347                 }
00348             }
00349         }
00350 
00351         //notifyStmt looking up
00352 
00353         for (Iterator waitIt = waitStmtList.iterator(); waitIt.hasNext();) {
00354             SynchroStmt synStmt = (SynchroStmt) waitIt.next();
00355             Value lockValue = synStmt.getLock();
00356             Stmt waitStmt = synStmt.getWaitNotify();
00357             for (Iterator notifyStmtIt = notifyStmtList.iterator(); notifyStmtIt.hasNext();) {
00358                 SynchroStmt onSynStmt = (SynchroStmt) notifyStmtIt.next();
00359                 Value onLockValue = onSynStmt.getLock();
00360                 if (BuildPDG.mayPointToTheSameRef(lockValue, onLockValue, currentMethodInfo.sootMethod, methodInfo.sootMethod)) {
00361                     //put dependent relation to the readyMap
00362                     Stmt notifyStmt = onSynStmt.getWaitNotify();
00363                     ReadyDependStmt onNotifyStmt = new ReadyDependStmt(methodInfo, notifyStmt);
00364                     List readyList = (List) readyMap.get(waitStmt);
00365                     readyList.add(onNotifyStmt);
00366                 }
00367             }
00368         }
00369     }
00370 }
00371   /**
00372    * Analyse ready dependence for each method in the class list 
00373    * by calling {@link #readyForMethod(MethodInfo,List,List) readyForMethod()}.
00374    */
00375 private void readyDependence() {
00376     Map sootMethodInfoMap = Slicer.sootMethodInfoMap;
00377     for (Iterator mdIt = sootMethodInfoMap.keySet().iterator(); mdIt.hasNext();) {
00378         SootMethod sootMethod = (SootMethod) mdIt.next();
00379         MethodInfo methodInfo = (MethodInfo) sootMethodInfoMap.get(sootMethod);
00380         if (methodInfo == null) continue;
00381         BuildPDG methodPDG = methodInfo.methodPDG;
00382         LockAnalysis lockAnalysis = methodPDG.getLockAnalysis();
00383         if (lockAnalysis == null) {
00384             methodPDG.setReadyDependMap(null);
00385             continue;
00386         }
00387         List lockPairList = lockAnalysis.getLockPairList();
00388         List waitStmtList = lockAnalysis.getWaitStmtList();
00389         Map readyMap = readyForMethod(methodInfo, lockPairList, waitStmtList);
00390         methodPDG.setReadyDependMap(readyMap);
00391     }
00392 }
00393 //we assume that all relevant classes are diffrent on their name at least
00394 /*this method is to search for, in all method of other than currentclass, exitmonitor statement and notify (notifyAll) statement which are the same lock with the lock in lockPairList or waitStmtList*/
00395   /**
00396    * Analyse ready dependence for one method by calling
00397    * {@link #lookupReadyDependStmt(Map, List MethodInfo,List,List) 
00398    * lookupReadyDependStmt()}.
00399    * <p>
00400    * @param currentMethod current method.
00401    * @param lockPairList lock pair list of current method.
00402    * @param waitStmtList wait statement list of current method.
00403    * @return a of ready dependence from {@link Stmt Stmt} to
00404    * a {@link List List} of {@link ReadyDependStmt ReadyDependStmt}.
00405    */
00406 private Map readyForMethod(MethodInfo currentMethod, List lockPairList, List waitStmtList) {
00407     Map readyMap = new HashMap();
00408 
00409     //initialization of readyMap to empty list
00410 
00411     for (Iterator lockIt = lockPairList.iterator(); lockIt.hasNext();) {
00412         MonitorPair mp = (MonitorPair) lockIt.next();
00413         Stmt mpStmt = (Stmt) mp.getEnterMonitor();
00414         readyMap.put(mpStmt, new ArrayList());
00415     }
00416     for (Iterator waitIt = waitStmtList.iterator(); waitIt.hasNext();) {
00417         SynchroStmt synStmt = (SynchroStmt) waitIt.next();
00418         Stmt waitStmt = synStmt.getWaitNotify();
00419         readyMap.put(waitStmt, new ArrayList());
00420     }
00421     for (Iterator classIter = classList.iterator(); classIter.hasNext();) {
00422         ClassInfo classInfo = (ClassInfo) classIter.next();
00423         lookupReadyDependStmt(readyMap, classInfo.methodsInfoList, currentMethod, lockPairList, waitStmtList);
00424     }
00425     return readyMap;
00426 }
00427 }

Generated at Thu Feb 7 06:47:47 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001