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

BuildPDG.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 // Build pDG within the body of one method
00037 
00038 import ca.mcgill.sable.util.*;
00039 import ca.mcgill.sable.soot.*;
00040 import ca.mcgill.sable.soot.jimple.*;
00041 import edu.ksu.cis.bandera.pdgslicer.exceptions.*;
00042 import edu.ksu.cis.bandera.annotation.*;
00043 import java.util.BitSet;
00044 import java.util.Enumeration;
00045 import java.util.Vector;
00046 //import java.util.HashSet;
00047 
00048 /**
00049  * A class calculating data-dependence, control-dependence for one method.
00050  * <br>
00051  * This class includes analysis like reaching definitions for local variables and fields, 
00052  * postdominators, immediate postdominators, and control-dependence.
00053  */
00054 public class BuildPDG {
00055     /**
00056      * a list of exit nodes (index) in the method which are stored as BitSet.
00057      */
00058     private BitSet exitNodes;
00059     MethodInfo methodInfo;
00060     /**
00061     * a map from {@link Stmt Stmt} to {@link BitSet BitSet} for postdominators
00062     * of each statement in the method.
00063     */
00064     private Map stmtToPostdoms;
00065     /**
00066     * a map from {@link Stmt Stmt} to {@link Integer Integer} for immediate
00067     * postdominator of each statement in the method.
00068     */
00069     private Map stmtToImmedPostdom;
00070     /**
00071     * statement list of the method.
00072     */
00073     private StmtList stmtList;
00074     private StmtGraph stmtGraph;
00075     private JimpleBody jimpleBody;
00076     /**
00077     * the result of reaching definition analysis for static field references.
00078     */
00079     private BitSet staticReachDef[];
00080     /**
00081     * the result of reaching definition analysis for instance field references.
00082     */
00083     private BitSet instanceReachDef[];
00084     /**
00085     * an instance of {@link LockAnalysis LockAnalysis}.
00086     */
00087     private LockAnalysis lockAnalysis = null;
00088     /**
00089     * a map from {@link Stmt Stmt} to a {@link List List} of
00090     * {@link ReadyDependStmt ReadyDependStmt} for ready dependence of
00091     * each statement in the method.
00092     */
00093     private Map readyDependMap = null;
00094     /**
00095     * a map from {@link Stmt Stmt} to a {@link List List} of
00096     * {@link InterferStmt InterferStmt} for interference dependence of
00097     * each statement in the method.
00098     */
00099     private Map interferenceMap = null;
00100     /**
00101     * a map from {@link CallSite CallSite} to {@link SootMethod SootMethod}
00102     * where SootMethod is called in the CallSite.
00103     */
00104     private Map callSiteMap = null;
00105     /**
00106     * exit nodes without <code>throw</code> statements.
00107     */
00108     private BitSet exitNodesNoThrow;
00109     /** 
00110     * a set of {@link DataBox DataBox}.
00111     */
00112     private Set instanceFieldDefStmtList = new ArraySet(); //instance field ref
00113     /** 
00114     * a set of {@link DataBox DataBox}.
00115     */  
00116     private Set staticFieldDefStmtList = null;
00117     /**
00118        * The map of data dependence: {@link Stmt Stmt} to 
00119        * a {@link ca.mcgill.sable.util.Set Set} of 
00120        * {@link DataBox DataBox}.
00121        */
00122     private Map stmtToDdOn;
00123 
00124     private Integer indefiniteNode = null;
00125 
00126     /******************************************************************/
00127     /**
00128     * The map of control dependence: {@link Stmt Stmt} to {@link BitSet BitSet}.
00129     */
00130     private Map stmtToCdOn;
00131     /**
00132     * The map of divergence dependence from pre-divergence point to reachable statement set (from that point):
00133     * (@link Stmt Stmt} to {@link BitSet BitSet}.
00134     */
00135     private Map divergenceMap;
00136     private AnnotationManager annotationManager = null;
00137   /**
00138    * Build dependency graph for one method in three steps:
00139    * <ul>
00140    * <li> Initialization
00141    * <li> Dominators calculation
00142    * <li> Dependencies calculation
00143    * </ul>
00144    * <p>
00145    * @param mdInfo   method to be analysed.
00146    * @param cfanns   annotation manager.
00147    */
00148   public BuildPDG(MethodInfo mdInfo, AnnotationManager cfanns) {
00149     annotationManager = cfanns;
00150     prepareToBuild(mdInfo);
00151     domination();
00152     dependency();
00153 }
00154 /**
00155  * Insert the method's description here.
00156  * Creation date: (00-11-1 16:22:46)
00157  * This is for control analysis of init method. We assume that return
00158  * statement of init method control dependent on init invoke of its super class.
00159  * For example,
00160  *    public void init(int)
00161  *   {
00162  *       int b, size;
00163  *       Buffer JJJCTEMP$0;
00164  *       Object[] JJJCTEMP$1;
00165  *
00166  *       JJJCTEMP$0 := @this;
00167  *       b := @parameter0;
00168  *       specialinvoke JJJCTEMP$0.[java.lang.Object.init():void]();
00169  *       JJJCTEMP$1 = new Object[b];
00170  *       JJJCTEMP$0.[Buffer.array:Object[]] = JJJCTEMP$1;
00171  *       JJJCTEMP$0.[Buffer.putPtr:int] = 0;
00172  *       JJJCTEMP$0.[Buffer.getPtr:int] = 0;
00173  *       JJJCTEMP$0.[Buffer.usedSlots:int] = 0;
00174  *       return;
00175  *   }
00176  * Then, the return is control dependent on
00177  * specialinvoke JJJCTEMP$0.[java.lang.Object.init():void]();
00178  */
00179 private void cdAnalysisForReturnOfInit() {
00180     BitSet specialInvokeSet = new BitSet(stmtList.size());
00181     for (Iterator si = methodInfo.indexMaps.getSpecialInvokeList().iterator(); si.hasNext();) {
00182         InvokeStmt invoke = (InvokeStmt) si.next();
00183         SpecialInvokeExpr specInvoke = (SpecialInvokeExpr) invoke.getInvokeExpr();
00184         if (methodInfo.indexMaps.getThisRefLocal().equals(specInvoke.getBase())) {
00185             if (specInvoke.getMethod().getName().equals("<init>")) {
00186                 if (methodInfo.sootClass.getSuperClass().equals(specInvoke.getMethod().getDeclaringClass())) {
00187                     int specialInvokeInt = stmtList.indexOf(invoke);
00188                     specialInvokeSet.set(specialInvokeInt);
00189                 } else
00190                     if (methodInfo.sootClass.equals(specInvoke.getMethod().getDeclaringClass())) {
00191                         int specialInvokeInt = stmtList.indexOf(invoke);
00192                         specialInvokeSet.set(specialInvokeInt);
00193                     }
00194             }
00195         }
00196     }
00197     if (SetUtil.emptyBitSet(specialInvokeSet))
00198         throw new SlicerException("Can not find special invoke of super class in method " + methodInfo.sootMethod);
00199     for (int i = 0; i < exitNodesNoThrow.size(); i++) {
00200         if (exitNodesNoThrow.get(i)) {
00201             Stmt exitStmt = (Stmt) stmtList.get(i);
00202             BitSet cdSet = (BitSet) stmtToCdOn.get(exitStmt);
00203             if (cdSet == null)
00204                 cdSet = new BitSet(stmtList.size());
00205             cdSet.or(specialInvokeSet);
00206             stmtToCdOn.put(exitStmt, cdSet);
00207         }
00208     }
00209 }
00210 /**
00211  * Analyse control dependence for statements in <code>catch</code> block.
00212  * <br>
00213  * Store the result in {@link #stmtToCdOn stmtToCdOn}.
00214  * <p>
00215  * Given no any information on exception flow, all statements in <code>catch</code> 
00216  * block are considered control dependent on all statements in <code>try</code> block.
00217  */
00218 private void cdAnalysisForStmtsInCatch() {
00219 
00220     Annotation annForSm = annotationManager.getAnnotation(methodInfo.sootClass, methodInfo.sootMethod);
00221 
00222     Vector currentCFANNs = annForSm.getAllAnnotations(true);
00223 
00224     for (Enumeration e = currentCFANNs.elements(); e.hasMoreElements();) {
00225         Annotation cfann = (Annotation) e.nextElement();
00226         
00227         if (cfann instanceof TryStmtAnnotation) {
00228             TryStmtAnnotation tryAnnotation = (TryStmtAnnotation) cfann;
00229             Annotation blockAnn = tryAnnotation.getBlockAnnotation();
00230             Stmt stmtsInBlock[] = blockAnn.getStatements();
00231             BitSet stmtsInTryBlock = SetUtil.stmtArrayToBitSet(stmtsInBlock, stmtList);
00232             Vector catchClauses = tryAnnotation.getCatchClauses();
00233             
00234             for (Enumeration en = catchClauses.elements(); en.hasMoreElements();) {
00235                 CatchAnnotation catchAnn = (CatchAnnotation) en.nextElement();
00236                 Stmt stmtsInCatch[] = catchAnn.getStatements();
00237                 for (int i = 0; i < stmtsInCatch.length; i++) {
00238                     Stmt branchStmt = stmtsInCatch[i];
00239                     BitSet cdSet = (BitSet) stmtToCdOn.get(branchStmt);
00240                     if (cdSet == null)
00241                         cdSet = new BitSet(stmtList.size());
00242                     cdSet.or(stmtsInTryBlock);
00243                     stmtToCdOn.put(branchStmt, cdSet);
00244                 }
00245             }
00246             
00247         }
00248         
00249     }
00250 }
00251   /**
00252    * Clone and change base value for a set of instance field references.
00253    * <br>
00254    * For example, <code>a.f</code> can be cloned and changed its base value to a new value, 
00255    * saying <code>b</code>. Then <code>a.f</code> will be transformed to a new instance 
00256    * field reference <code>b.f</code>.
00257    * <p>
00258    * @param original   a set of {@link ca.mcgill.sable.soot.jimple.InstanceFieldRef InstanceFieldRef}
00259    * need changing their base values.
00260    * @param base       new base value for those references in <code>original</code>.
00261    * @return           a set of new 
00262    * {@link ca.mcgill.sable.soot.jimple.InstanceFieldRef InstanceFieldRef} with the new base
00263    *  value <code>base</code>.
00264    * Empty set is returned, if <code>original</code> is empty.
00265    */
00266 static Set cloneAndChangeBase(Set original, Value base) {
00267     Set newFields = new ArraySet();
00268     for (Iterator orIt = original.iterator(); orIt.hasNext();) {
00269         InstanceFieldRef insFieldRef = (InstanceFieldRef) orIt.next();
00270         InstanceFieldRef newInsFieldRef = Jimple.v().newInstanceFieldRef(base, insFieldRef.getField());
00271         newFields.add(newInsFieldRef);
00272     }
00273     return newFields;
00274 }
00275   /**
00276    * Collect all statements such that they assign values to instance field references, 
00277    * including all indirect assignments by method calls. 
00278    * <br>Store the result in {@link #instanceFieldDefStmtList instanceFieldDefStmtList}.
00279    */
00280 private void collectInstanceFieldDefStmt() {
00281     /*
00282     for (Iterator stmtIt = stmtList.iterator(); stmtIt.hasNext();) {
00283         Set defInstanceRefs = new ArraySet();
00284         Stmt stmt = (Stmt) stmtIt.next();
00285         for (Iterator defBoxIt = stmt.getDefBoxes().iterator(); defBoxIt.hasNext();) {
00286             Value value = ((ValueBox) defBoxIt.next()).getValue();
00287             if (value instanceof InstanceFieldRef)
00288                 defInstanceRefs.add((InstanceFieldRef) value);
00289         }
00290         if (defInstanceRefs.size() != 0)
00291             instanceFieldDefStmtList.add(new DataBox(stmt, defInstanceRefs));
00292     }
00293     */
00294     Fields MOD = methodInfo.MOD;
00295     Set paraFields = MOD.paraFields;
00296     Set instanceFields = MOD.instanceFields;
00297     Set otherInsFields = MOD.otherInsFds;
00298     instanceFieldDefStmtList.addAll(instanceFields);
00299     instanceFieldDefStmtList.addAll(otherInsFields);
00300     
00301     //begin to add instance references which are in called method
00302     //should collect all the instance reference caused from the parameter
00303     //passing and object passing
00304     //using binding function
00305 /*
00306     for (Iterator siteIt = callSiteMap.keySet().iterator(); siteIt.hasNext();) {
00307         CallSite site = (CallSite) siteIt.next();
00308         SootMethod calledMd = (SootMethod) callSiteMap.get(site);
00309         MethodInfo calledMdInfo = (MethodInfo) Slicer.sootMethodInfoMap.get(calledMd);
00310         if (calledMdInfo == null) continue;
00311         Fields fields = calledMdInfo.MOD;
00312         Set defInstanceRefs = new ArraySet();
00313 
00314         //it is also necessary to decide what if the call is the this
00315         //reference call, because of the object reference will be different
00316         //so it's not a simple union of instanceFields
00317 
00318 
00319         Set instanceFieldsInCalledMd = fields.instanceFields;
00320         Value base = null;
00321         NonStaticInvokeExpr nonStaticInvokeExpr = null;
00322         InvokeExpr invokeExpr = site.invokeExpr;
00323         if (invokeExpr instanceof NonStaticInvokeExpr) {
00324             nonStaticInvokeExpr = (NonStaticInvokeExpr) invokeExpr;
00325             base = nonStaticInvokeExpr.getBase();
00326         } else {
00327                 //System.out.println("We can't process static invoke at this moment");
00328             return;
00329         }
00330         for (Iterator i =instanceFieldsInCalledMd.iterator(); i.hasNext();) {
00331             DataBox insFieldRefBox = (DataBox) i.next();
00332             Set defFields = insFieldRefBox.getInterferVars();
00333             defInstanceRefs.addAll(cloneAndChangeBase(defFields, base));
00334         }
00335 
00336 
00337         //including that paraFields of the other method with the name
00338         //changed to call method's parameters
00339         //need to construct the binding function of parameters
00340 
00341         if (paraFields != null) {
00342             int siteIndex = stmtList.indexOf(site.callStmt);
00343             for (Iterator kk = paraFields.iterator(); kk.hasNext();) {
00344                 DataBox paraFieldRefBox = (DataBox) kk.next();
00345                 Stmt callSite = paraFieldRefBox.getInterferStmt();
00346                 int callSiteIndex = stmtList.indexOf(callSite);
00347                 if (siteIndex == callSiteIndex)
00348                     defInstanceRefs.addAll(paraFieldRefBox.getInterferVars());
00349             }
00350         }
00351         if (defInstanceRefs.size() != 0)
00352             instanceFieldDefStmtList.add(new DataBox(site.callStmt, defInstanceRefs));
00353     }
00354     */
00355 }
00356   /**
00357    * Collect all static field references ever defined in the method.
00358    * <p>
00359    * @return a set of {@link ca.mcgill.sable.soot.jimple.StaticFieldRef StaticFieldRef}.
00360    * Empty set is returned, if there is no static field reference defined.
00361    * @see #staticFieldDefStmtList
00362    */
00363 private Set collectVarsDefined(Set defStmtList) {
00364     Set varsDefined = new ArraySet();
00365     for (Iterator i = defStmtList.iterator(); i.hasNext();) {
00366         DataBox db = (DataBox) i.next();
00367         Set vars = db.getInterferVars();
00368         varsDefined.addAll(vars);
00369     }
00370     return varsDefined;
00371 }
00372   /**
00373    * Compute immediate (post)dominator for each statement in the method.
00374    * <br>
00375    * The alorithm of this method is from the book "Advanced compiler design and implementation"
00376    * by Steven S. Muchnick, 1997
00377    * <p>
00378    * @param stmtToBitSet  a map of {@link ca.mcgill.sable.soot.jimple.Stmt Stmt}
00379    * to {@link java.util.BitSet BitSet} of (post)dominators.
00380    * @return  a map of {@link ca.mcgill.sable.soot.jimple.Stmt Stmt} to 
00381    * {@link java.lang.Integer Integer} of immediate (post)dominator.
00382    * @throws DomOrPostdomNotUniqueException 
00383    * if there are more than one immediate (post)dominators.
00384    */
00385 private Map computeImmedDom(Map stmtToBitSet) {
00386     Map stmtToImmediate = new HashMap(stmtList.size() * 2 + 1, 0.7f);
00387     Iterator keyStmtIt = stmtToBitSet.keySet().iterator();
00388     while (keyStmtIt.hasNext()) {
00389         Stmt keyStmt = (Stmt) keyStmtIt.next();
00390         int keyStmtIndex = stmtList.indexOf(keyStmt);
00391         BitSet doms = (BitSet) stmtToBitSet.get(keyStmt);
00392         BitSet workSet = (BitSet) doms.clone();
00393         workSet.clear(keyStmtIndex);
00394 
00395         //BitSet immediate = new BitSet(stmtList.size());
00396         BitSet immediate = (BitSet) workSet.clone();
00397         for (int i = 0; i < workSet.size(); i++) {
00398             if (workSet.get(i)) {
00399                 BitSet domX = (BitSet) stmtToBitSet.get((Stmt) stmtList.get(i));
00400                 BitSet domX2 = (BitSet) domX.clone();
00401                 domX2.clear(i);
00402                 domX2.and(immediate);
00403                 immediate.xor(domX2);
00404             }
00405         }
00406         int immT = 0;
00407         for (int i = 0; i < immediate.size(); i++) {
00408             if (immediate.get(i)) {
00409                 stmtToImmediate.put(keyStmt, new Integer(i));
00410                 immT++;
00411             }
00412         }
00413         if (immT == 0)
00414             stmtToImmediate.put(keyStmt, IndexMaps.EntryNode);
00415         else
00416             if (immT > 1)
00417                 throw new DomOrPostdomNotUniqueException("immediate dominator and postdominator should be unique or none for statement: " + keyStmt);
00418     }
00419     return stmtToImmediate;
00420 }
00421 /**
00422  * Analyse control dependence for each statement in the method
00423  * <br>
00424  * Store the result in {@link #stmtToCdOn stmtToCdOn}.
00425  * <p>
00426  * The algorithm of this method is from the compiler news group:
00427  * <p>
00428  * From {@link <a href="http://compilers.iecc.com/comparch/article/92-12-065" target="_top">
00429  * comp.compilers</a>}.
00430  * <br> === Begin Algorithm ===
00431  * <p>
00432  * 1. For a given flow node X, let P(X) denote the nodes that post-dominate
00433  * X, along with X itself. Compute P(X) by using any of the standard
00434  * techniques to solve the following backward data flow equations:
00435  * P(X) = X | (P(Y1) & ... & P(Yn)),
00436  * P(Stop) = {}
00437  * where Y1 ... Yn are the successors of X, "|" denotes set union, "&"
00438  * denotes set intersection, and Stop is a unique exit node for the flow
00439  * graph. (This part is pretty much straight out of the red dragon book.)
00440  * <p>
00441  * 2. Assume that each node in the flow graph has no more than 2 successors,
00442  * and that if a node does have 2 successors, one is the "true" successor and
00443  * the other the "false" successor. For a given flow node X, let CD(X)
00444  * denote the nodes that are control dependent on X. If X has fewer than 2
00445  * successors, CD(X) is empty. Otherwise, we can find CD(X) as follows:
00446  * CD(X) = P(X-true) ^ P(X-false)
00447  * where X-true and X-false are respectively the true and false successors,
00448  * and "^" denotes symmetric difference (i.e., A ^ B = (A | B) - (A & B)).
00449  * Furthermore, the edges that should be labelled "true" in the control
00450  * dependence graph are the ones from X to the nodes in CD(X) & P(X-true);
00451  * and "false", the ones to the nodes in CD(X) & P(X-false).
00452  * <p>
00453  * === End Algorithm ===
00454  * <p>
00455  * From {@link <a href="http://compilers.iecc.com/comparch/article/92-12-068" target="_top">
00456  * comp.compilers</a>}.
00457  * <br> It looks like the correct solution for a node X with 3 successors, say A,
00458  * B, and C, would be
00459  * <p>
00460  * CD(X) = (P(A) ^ (P(B) | P(C)))
00461  * | (P(B) ^ (P(A) | P(C)))
00462  * | (P(C) ^ (P(A) | P(B)))
00463  * <p>
00464  * From {@link <a href="http://compilers.iecc.com/comparch/article/92-12-070" target="_top">
00465  * comp.compilers</a>}.
00466  * <br> The general case of more than 2 succesoors is handled like this...
00467  * <br> CD(X) = union(P(S)) - intersection(P(S)), for S in successors(X)
00468  * <br> (This is a much simpler version of another answer I posted earlier)
00469  * <p>
00470  * From {@link <a href="http://compilers.iecc.com/comparch/article/92-12-079" target="_top">
00471  * comp.compilers</a>}.
00472  * <br> This can be simplified (also with less computation) further:
00473  * <br> CD(X) = union(P(S)) - P(X)
00474  * <br> I think it is not difficut to prove that
00475  * <br> {intersection(P(S)), for S in successors(X)}=P(X)
00476  */
00477 private void controlDependAnalysis() {
00478     stmtToCdOn = new HashMap();
00479     for (Iterator stmtIt = stmtList.iterator(); stmtIt.hasNext();) {
00480         Stmt stmt = (Stmt) stmtIt.next();
00481         List succs = removeExceptionCaught(stmtGraph.getSuccsOf(stmt));
00482         if (succs.size() < 2)
00483             continue;
00484         /*
00485         if (succs.size() > 2) {
00486         System.out.println("There are more than 2 successors for stmt: " + stmt);
00487         System.out.println("Successors: " + succs);
00488         System.out.println("We do not deal with more than 2 successors");
00489         continue;
00490         }
00491         */
00492         //Map CDXMap = new HashMap();
00493         Stmt xSuccStmt = (Stmt) succs.get(0);
00494         BitSet PsUnion = (BitSet) postdominatorsOf(xSuccStmt).clone();
00495         for (int i = 1; i < succs.size(); i++) {
00496             xSuccStmt = (Stmt) succs.get(i);
00497             BitSet Ps = (BitSet) postdominatorsOf(xSuccStmt).clone();
00498             PsUnion.or(Ps);
00499         }
00500         BitSet Px = (BitSet) postdominatorsOf(stmt).clone();
00501         PsUnion.xor(Px);
00502         //CDXMap.put(stmt, PsUnion); //stmt controls the stmts in Pxtrue;
00503         // put Pxtrue to stmtToCdOn
00504         for (int i = 0; i < PsUnion.size(); i++) {
00505             if (!PsUnion.get(i))
00506                 continue;
00507             int cdStmtIndex = stmtList.indexOf(stmt);
00508             Stmt branchStmt = (Stmt) stmtList.get(i);
00509             BitSet cdSet = (BitSet) stmtToCdOn.get(branchStmt);
00510             if (cdSet == null)
00511                 cdSet = new BitSet(stmtList.size());
00512             cdSet.set(cdStmtIndex);
00513             stmtToCdOn.put(branchStmt, cdSet);
00514         }
00515     }
00516     //control analysis for stmts in catch: all stmts in catch control depend on
00517     //all stmts in try block.
00518     cdAnalysisForStmtsInCatch();
00519     if (methodInfo.sootMethod.getName().equals("<init>"))
00520         cdAnalysisForReturnOfInit();
00521 }
00522   /**
00523    * Get control dependent predecessors, from {@link #stmtToCdOn stmtToCdOn}, 
00524    * for the statement <code>st</code>.
00525    * <p>
00526    * @param st query statement.
00527    * @return a set of statements represented in indexes with {@link java.util.BitSet BitSet}.
00528    */ 
00529   public BitSet controlNodesOf(Stmt st)
00530     {
00531       return (BitSet) stmtToCdOn.get(st);
00532     }
00533   /**
00534    * Get control dependent successors for the statement <code>stmt</code>.
00535    * <p>
00536    * @param stmt query statement.
00537    * @return a set of {@link ca.mcgill.sable.soot.jimple.Stmt} that are 
00538    * control dependent on <code>stmt</code>. Emtpy set is returned if there is no 
00539    * control dependent successor.
00540    */
00541 public Set controlSuccNodesOf(Stmt stmt) {
00542     Set succNodes = new ArraySet();
00543     int index = stmtList.indexOf(stmt);
00544     for (Iterator stmtIt = stmtToCdOn.keySet().iterator(); stmtIt.hasNext();) {
00545         Stmt controlledStmt = (Stmt) stmtIt.next();
00546         BitSet controlNodes = (BitSet) stmtToCdOn.get(controlledStmt);
00547         if (controlNodes.get(index))
00548             succNodes.add(controlledStmt);
00549     }
00550     return succNodes;
00551 }
00552   /**
00553    * See if there is a DataBox in <code>dataBoxes</code> with a statement <code>stmt</code>.
00554    * <p>
00555    * @param dataBoxes   a set of {@link edu.ksu.cis.bandera.pdgslicer.DataBox DataBox}.
00556    * @param stmt        query statement.
00557    * @return <code>true</code> is returned, if contains. 
00558    * <code>false</code> is returned, if not.
00559    */
00560 private boolean dataBoxesContains(Set dataBoxes, Stmt stmt)
00561     {
00562       for (Iterator boxIt = dataBoxes.iterator(); boxIt.hasNext();)
00563     {
00564       DataBox db = (DataBox) boxIt.next();
00565       if (stmt==db.getStmt()) return true;
00566     }
00567       return false;
00568     }
00569 /*************************************************************/
00570 /**
00571    * Analyse data dependence for each statement in the method. Analysis includes data
00572    * data dependence of instance field references, data dependence of static or static based 
00573    * field references, and data dependence of parameters for method invokes.
00574    * <br>
00575    * Store the result in {@link #stmtToDdOn stmtToDdOn}.
00576    * <p>
00577    * @see #ddForStaticAndInstanceFd()
00578    * @see #ddForParameters()
00579    */
00580 private void dataDependAnalysis() {
00581     stmtToDdOn = new HashMap(stmtList.size() * 2 + 1, 0.7f);
00582     LocalDefs localDefs = new SimpleLocalDefs((CompleteStmtGraph) stmtGraph);
00583     for (Iterator stmtIt = stmtList.iterator(); stmtIt.hasNext();) {
00584         Stmt stmt = (Stmt) stmtIt.next();
00585         Set ddList = new ArraySet();
00586         for (Iterator useBoxIt = stmt.getUseBoxes().iterator(); useBoxIt.hasNext();) {
00587             ValueBox useBox = (ValueBox) useBoxIt.next();
00588             if (useBox.getValue() instanceof Local) {
00589                 Local local = (Local) useBox.getValue();
00590                 List defsOfUse = localDefs.getDefsOfAt(local, stmt);
00591 
00592                 //Need to be refined on this 
00593 
00594                 for (Iterator defsIt = defsOfUse.iterator(); defsIt.hasNext();) {
00595                     Stmt def = (Stmt) defsIt.next();
00596                     Set tempSet = new ArraySet();
00597                     tempSet.add(local);
00598                     DataBox ddBox = new DataBox(def, tempSet);
00599                     ddList.add(ddBox);
00600                 }
00601                 //if local is Arraytype, including all assignments to the component of this array
00602                 //which can reach to stmt into the data depenendece list
00603                 if (local.getType() instanceof ArrayType)
00604                     ddForArray(ddList, stmt, local);
00605             } else
00606                 if (useBox.getValue() instanceof InstanceFieldRef) {
00607                     dataDependOfInstanceFieldRef((InstanceFieldRef) useBox.getValue(), stmt, ddList);
00608                 }
00609         } //end of while
00610 
00611         stmtToDdOn.put(stmt, ddList);
00612     } //end of while
00613 
00614     //add data dependence for static fields and public class instance fields
00615     ddForStaticAndInstanceFd();
00616 
00617     //add data dependence for parafields of every callsite
00618     ddForParameters();
00619 }
00620 /**
00621    * Get data dependences for one instance field reference <code>insfr</code>
00622    * using information on reaching definition of instance field references
00623    * {@link #instanceReachDef intanceReachDef} 
00624    * and {@link #instanceFieldDefStmtList instanceFieldDefStmtList}.
00625    * <br> 
00626    * Store the result in <code>ddList</code>.
00627    * <p>
00628    * @param insfr  query field reference.
00629    * @param stmt   the statement where <code>insfr</code> is used.
00630    * @param ddList a set of {@link edu.ksu.cis.bandera.pdgslicer.DataBox DataBox}.
00631    */
00632 private void dataDependOfInstanceFieldRef(InstanceFieldRef insfr, Stmt stmt, Set ddList) {
00633     Set instanceVarsDefined = collectVarsDefined(instanceFieldDefStmtList);
00634     Set fieldsDefined = fieldRefToSootField(instanceVarsDefined);
00635     if (fieldsDefined.contains(insfr.getField())) {
00636         // reaching definition procedrure of instancefield ref
00637         //BitSet reachIni = instanceReachDef[stmtList.indexOf(stmt)];
00638         Object array[] = instanceFieldDefStmtList.toArray();
00639         for (int mm = 0; mm < array.length; mm++) {
00640             //if (reachIni.get(mm)) 
00641             {
00642                 DataBox db2 = (DataBox) array[mm];
00643                 Set vars = db2.getInterferVars();
00644                 Set fields = fieldRefToSootField(vars);
00645                 if (fields.contains(insfr.getField())) {
00646                     Set fieldReferences = getRefsWithCommonField(vars,insfr.getField());
00647                     Stmt defStmt = db2.getInterferStmt();
00648                     if (defStmt.equals(stmt)) {
00649                         if (SlicingMethod.isCallSite(callSiteMap, stmt) != null) {
00650                         } else {
00651                             //integrate path information here
00652                             if (SlicingMethod.reachableStmtFrom(defStmt, stmtGraph).contains(stmt)) {
00653                                 //integrate never point-to information
00654                                 if (BuildPDG.mayPointToTheSameRef(insfr.getBase(), fieldReferences, methodInfo.sootMethod, methodInfo.sootMethod)) {
00655                                     DataBox ddBox = new DataBox(defStmt, vars);
00656                                     ddList.add(ddBox);
00657                                 }
00658                             }
00659                         }
00660                     } else {
00661                         //integrate path information here
00662                         if (SlicingMethod.reachableStmtFrom(defStmt, stmtGraph).contains(stmt)) {
00663                             //integrate never point-to information
00664                             if (BuildPDG.mayPointToTheSameRef(insfr.getBase(), fieldReferences, methodInfo.sootMethod, methodInfo.sootMethod)) {
00665                                 DataBox ddBox = new DataBox(defStmt, vars);
00666                                 ddList.add(ddBox);
00667                             }
00668                         }
00669                     }
00670                 } // end of if
00671             } //end of if
00672         } //end of for
00673 
00674     } //end of if 
00675 }
00676   /**
00677    * Get data dependences for one static field reference <code>staticVariable</code>
00678    * using information on reaching definition of static field references
00679    * {@link #staticReachDef staticReachDef}
00680    * and {@link #staticFieldDefStmtList staticFieldDefStmtList}.
00681    * <br> 
00682    * Store the result in <code>ddList</code>.
00683    * <p>
00684    * @param staticVariable  query field reference.
00685    * @param stmt   the statement where <code>staticVariable</code> is used.
00686    * @param ddList a set of {@link edu.ksu.cis.bandera.pdgslicer.DataBox DataBox}.
00687    */
00688 private void dataDependOfStaticFieldRef(StaticFieldRef staticVariable, Stmt stmt, Set ddList) {
00689     Set staticVarsDefined = collectVarsDefined(staticFieldDefStmtList);
00690     if (staticVarsDefined.contains(staticVariable)) {
00691         // reaching definition procedrure of staticfield ref
00692         BitSet reachIni = staticReachDef[stmtList.indexOf(stmt)];
00693         Object array[] = staticFieldDefStmtList.toArray();
00694         for (int mm = 0; mm < array.length; mm++) {
00695             if (reachIni.get(mm)) {
00696                 DataBox db2 = (DataBox) array[mm];
00697                 Set vars = db2.getInterferVars();
00698                 if (vars.contains(staticVariable)) {
00699                     Stmt defStmt = db2.getInterferStmt();
00700                     if (defStmt.equals(stmt)) {
00701                         if (SlicingMethod.isCallSite(callSiteMap, stmt) != null) {
00702                         } else {
00703                             DataBox ddBox = new DataBox(defStmt, vars);
00704                             ddList.add(ddBox);
00705                         }
00706                     } else {
00707                         DataBox ddBox = new DataBox(defStmt, vars);
00708                         ddList.add(ddBox);
00709                     }
00710                 } // end of if
00711             } //end of if
00712         } //end of for
00713 
00714     } //end of if 
00715 }
00716   /** 
00717    * Get data dependent predecessors, from {@link #stmtToDdOn stmtToDdOn}
00718    * for the statement <code>st</code>.
00719    * <p>
00720    * @param st   query statement.
00721    * @return     a set of {@link edu.ksu.cis.bandera.pdgslicer.DataBox DataBox}.
00722    */
00723   public Set dataNodesOf(Stmt st)
00724     {
00725       return (Set) stmtToDdOn.get(st);
00726     }
00727   /** 
00728    * Get data dependent successors
00729    * for the statement <code>st</code>.
00730    * <p>
00731    * @param stmt   query statement.
00732    * @return     a set of {@link ca.mcgill.sable.soot.jimple.Stmt Stmt}.
00733    */
00734   public Set dataSuccNodesOf(Stmt stmt)
00735     {
00736       Set succNodes = new ArraySet();
00737       for (Iterator stmtIt = stmtToDdOn.keySet().iterator(); stmtIt.hasNext();)
00738     {
00739       Stmt reachedStmt = (Stmt) stmtIt.next();
00740       Set dataBoxes = (Set) stmtToDdOn.get(reachedStmt);
00741       if (dataBoxesContains(dataBoxes, stmt))
00742         succNodes.add(reachedStmt);
00743     }
00744       return succNodes;
00745     }
00746 /**
00747  * Insert the method's description here.
00748  * Creation date: (7/10/2001 1:52:43 PM)
00749  * @param ddList ca.mcgill.sable.util.Set
00750  * @param stmt ca.mcgill.sable.soot.jimple.Stmt
00751  */
00752 private void ddForArray(Set ddList, Stmt stmt, Local arrayLocal) {
00753     //find all assignments to ArrayRef
00754     Map arrayRefs = new HashMap();
00755     for (Iterator stmtIt = stmtList.iterator(); stmtIt.hasNext();) {
00756         Stmt s = (Stmt) stmtIt.next();
00757         List defList = s.getDefBoxes();
00758         for (Iterator defBoxIt = defList.iterator(); defBoxIt.hasNext();) {
00759             ValueBox defBox = (ValueBox) defBoxIt.next();
00760             Value defValue = defBox.getValue();
00761             if (defValue instanceof ArrayRef) {
00762                 //Value baseValue  = ((ArrayRef) defValue).getBase();
00763                 arrayRefs.put(defValue, s);
00764             }
00765         }
00766     }
00767     //see if any base of arrayRef can point to the same reference as arrayLocal, and can
00768     //reachable from the definition to stmt
00769     for (Iterator keyIt = arrayRefs.keySet().iterator(); keyIt.hasNext();) {
00770         ArrayRef defValue = (ArrayRef) keyIt.next();
00771         Value baseValue = defValue.getBase();
00772         //if the baseValue and the arrayLocal from parameter can point to the same array by BOFA
00773         //rightnow we only consider local
00774         if (baseValue instanceof Local) {
00775             //String arrayLocalString = arrayLocal.toString();
00776             //String baseString = ((Local) baseValue).toString();
00777             //if (arrayLocalString.equals(baseString)) //compare by string for point-to
00778             if (mayPointToTheSameRef(arrayLocal,baseValue, methodInfo.sootMethod, methodInfo.sootMethod))
00779             { //point to the same array
00780                 Stmt defStmt = (Stmt) arrayRefs.get(defValue);
00781                 //see if the defStmt can reach stmt
00782                 if (SlicingMethod.reachableStmtFrom(defStmt, stmtGraph).contains(stmt)) {
00783                     Set vars = new ArraySet();
00784                     vars.add(defValue);
00785                     DataBox ddBox = new DataBox(defStmt, vars);
00786                     ddList.add(ddBox);
00787                 }
00788             }
00789         }
00790     }
00791 }
00792   /**
00793    * Analyse data dependence for parameters (field references) of each call site in the method
00794    * using REF/MOD information.
00795    * <br>
00796    * Store the result in {@link #stmtToDdOn stmtToDdOn}.
00797    */
00798 private void ddForParameters() {
00799     for (Iterator siteIt = callSiteMap.keySet().iterator(); siteIt.hasNext();) {
00800         CallSite site = (CallSite) siteIt.next();
00801         SootMethod calledMd = (SootMethod) callSiteMap.get(site);
00802         MethodInfo calledMdInfo = (MethodInfo) Slicer.sootMethodInfoMap.get(calledMd);
00803         if (calledMdInfo==null) continue;
00804         Fields usedFields = calledMdInfo.REF;
00805         Stmt callSiteStmt = site.callStmt;
00806         int callSiteStmtIndex = stmtList.indexOf(callSiteStmt);
00807         Set ddList = new ArraySet();
00808         Set usingParas = Fields.parametersLocalize(calledMdInfo, usedFields, site.invokeExpr);
00809         for (Iterator i = usingParas.iterator(); i.hasNext();) {
00810             InstanceFieldRef para = (InstanceFieldRef) i.next();
00811             dataDependOfInstanceFieldRef(para, callSiteStmt, ddList);
00812         }
00813         if (ddList.size() == 0)
00814             continue;
00815         if (stmtToDdOn.containsKey(callSiteStmt))
00816             ddList.addAll((Set) stmtToDdOn.get(callSiteStmt));
00817         stmtToDdOn.put(callSiteStmt, ddList);
00818     }
00819 }
00820   /**
00821    * Analyse data dependence for static field, static based field and intance field references
00822    * using REF/MOD information.
00823    * <br>
00824    * Store the result in {@link #stmtToDdOn stmtToDdOn}.
00825    * <p>
00826    * @see #dataDependOfStaticFieldRef(StaticFieldRef,Stmt,Set)
00827    * @see #dataDependOfInstanceFieldRef(InstanceFieldRef,Stmt,Set)
00828    */
00829 private void ddForStaticAndInstanceFd() {
00830     Fields refFields = methodInfo.REF;
00831 
00832     for (Iterator i = refFields.staticFields.iterator(); i.hasNext();) {
00833         DataBox dbx = (DataBox) i.next();
00834         Set ddList = new ArraySet();
00835         Stmt useStmt = dbx.getInterferStmt();
00836         for (Iterator j = dbx.getInterferVars().iterator(); j.hasNext();) {
00837             StaticFieldRef stcField = (StaticFieldRef) j.next();
00838             dataDependOfStaticFieldRef(stcField, useStmt, ddList);
00839         }
00840         if (ddList.size() == 0)
00841             continue;
00842         if (stmtToDdOn.containsKey(useStmt))
00843             ddList.addAll((Set) stmtToDdOn.get(useStmt));
00844         stmtToDdOn.put(useStmt, ddList);
00845     }
00846 
00847     for (Iterator i = refFields.instanceFields.iterator(); i.hasNext();) {
00848         DataBox dbx = (DataBox) i.next();
00849         Set ddList = new ArraySet();
00850         Stmt useStmt = dbx.getInterferStmt();
00851         for (Iterator j = dbx.getInterferVars().iterator(); j.hasNext();) {
00852             InstanceFieldRef insField = (InstanceFieldRef) j.next();
00853             dataDependOfInstanceFieldRef(insField, useStmt, ddList);
00854         }
00855         if (ddList.size() == 0)
00856             continue;
00857         if (stmtToDdOn.containsKey(useStmt))
00858             ddList.addAll((Set) stmtToDdOn.get(useStmt));
00859         stmtToDdOn.put(useStmt, ddList);
00860     }
00861 }
00862 /**
00863    * Get the set of statements that define some mutual static field references
00864    * with the statement <code>staticDefIndex</code> using 
00865    * {@link #staticFieldDefStmtList staticFieldDefStmtList}.
00866    * <p>
00867    * @param staticDefIndex  the index of a statement in 
00868    * {@link #staticFieldDefStmtList staticFieldDefStmtList} which defines
00869    * a static field reference.
00870    * @return a set of {@link java.lang.Integer Integer} which is index of a statement
00871    * in {@link #staticFieldDefStmtList staticFieldDefStmtList}.
00872    * Empty set is returned, if there is no such statement.
00873    */
00874 private Set defsNotPreserves(int staticDefIndex) {
00875     Set defsNotPres = new ArraySet();
00876     Object array[] = staticFieldDefStmtList.toArray();
00877     defsNotPres.add(new Integer(staticDefIndex));
00878     DataBox staticBox = (DataBox) array[staticDefIndex];
00879     Set staticDefs = staticBox.getInterferVars();
00880     for (int i = 0; i < array.length; i++) {
00881         DataBox db = (DataBox) array[i];
00882         Set staticDefs2 = db.getInterferVars();
00883         Set intersectDefs = SetUtil.setIntersection(staticDefs, staticDefs2);
00884         if (intersectDefs.size() != 0) {
00885             boolean hasNoArrayComponent = true;
00886             for (Iterator varIt = intersectDefs.iterator(); varIt.hasNext();) {
00887                 Value staticVar = (Value) varIt.next();
00888                 Type varType = staticVar.getType();
00889                 if (varType instanceof ArrayType) {
00890 
00891                     //to see if the definition is to a component of an array
00892                     Stmt defStmt = db.getStmt();
00893                     List defBoxes = defStmt.getDefBoxes();
00894                     for (Iterator defIt = defBoxes.iterator(); defIt.hasNext();) {
00895                         ValueBox defBox = (ValueBox) defIt.next();
00896                         Value defValue = defBox.getValue();
00897                         if (defValue instanceof ArrayRef)
00898                             hasNoArrayComponent = false;
00899                     }
00900                 }
00901             }
00902             if (hasNoArrayComponent)
00903                 defsNotPres.add(new Integer(i));
00904         }
00905     }
00906     return defsNotPres;
00907 }
00908   /**
00909    * Analyse control and data dependence for the method.
00910    * <p>
00911    * @see #reachingDefOfStaticField()
00912    * @see #reachingDefOfInstanceField()
00913    * @see #controlDependAnalysis()
00914    * @see #dataDependAnalysis()
00915    * @see #specialInvokeDdAnalysis()
00916    */
00917 private void dependency() {
00918     if (staticFieldDefStmtList.size() != 0)
00919         reachingDefOfStaticField();
00920 
00921     if (instanceFieldDefStmtList.size() != 0)
00922         reachingDefOfInstanceField();
00923     controlDependAnalysis();
00924     dataDependAnalysis();
00925 
00926     //add specialinvoke init into data dependent map stmtToDdOn
00927     specialInvokeDdAnalysis();
00928     divergenceDependenceAnalysis();
00929 }
00930 /**
00931  * Insert the method's description here.
00932  * Creation date: (4/20/2001 10:21:10 AM)
00933  */
00934 private void divergenceDependenceAnalysis() {
00935     divergenceMap = new HashMap();
00936     Stmt[] statementsInLoop;
00937     Stmt[] testStatements;
00938     Annotation annForSm = annotationManager.getAnnotation(methodInfo.sootClass, methodInfo.sootMethod);
00939     Vector currentCFANNs = annForSm.getAllAnnotations(true);
00940     for (Enumeration e = currentCFANNs.elements(); e.hasMoreElements();) {
00941         Annotation cfann = (Annotation) e.nextElement();
00942         statementsInLoop = null;
00943         testStatements = null;
00944         if (cfann instanceof DoWhileStmtAnnotation) {
00945             DoWhileStmtAnnotation doWhile = (DoWhileStmtAnnotation) cfann;
00946             statementsInLoop = doWhile.getStatements();
00947             testStatements = doWhile.getTestStatements();
00948         } else
00949             if (cfann instanceof ForStmtAnnotation) {
00950                 ForStmtAnnotation forStmt = (ForStmtAnnotation) cfann;
00951                 statementsInLoop = forStmt.getStatements();
00952                 testStatements = forStmt.getTestStatements();
00953             } else
00954                 if (cfann instanceof WhileStmtAnnotation) {
00955                     WhileStmtAnnotation whileStmt = (WhileStmtAnnotation) cfann;
00956                     statementsInLoop = whileStmt.getStatements();
00957                     testStatements = whileStmt.getTestStatements();
00958                 }
00959         if ((statementsInLoop == null) || (testStatements == null))
00960             continue;
00961         Stmt preDivergencePoint = null;
00962         if (testStatements.length == 0)  //for example "for (;;)" there is no test statement
00963             preDivergencePoint = statementsInLoop[0];
00964         else
00965             preDivergencePoint = getConditionalStmtFrom(testStatements);
00966         Set reachableStmtsFromThePoint = SlicingMethod.reachableStmtSetFrom(preDivergencePoint, stmtGraph);
00967         BitSet reachableBitSet = SetUtil.stmtSetToBitSet(reachableStmtsFromThePoint, stmtList);
00968         BitSet stmtsBitSetInLoop = SetUtil.stmtArrayToBitSet(statementsInLoop, stmtList);
00969         reachableBitSet = SetUtil.bitSetAndNot(reachableBitSet, stmtsBitSetInLoop);
00970         divergenceMap.put(preDivergencePoint, reachableBitSet);
00971     }
00972 }
00973   /**
00974    * Calculate postdominators and immediate postdominators.
00975    * <p>
00976    * @see #postDomAnalysis()
00977    * @see #immediateDominators()
00978    */
00979   private void domination()
00980     {
00981       //dominateAnalysis();
00982       postDomAnalysis();
00983       immediateDominators();
00984     }
00985 /**
00986  * Insert the method's description here.
00987  * Creation date: (6/15/2001 11:02:44 PM)
00988  * @return ca.mcgill.sable.util.Set
00989  * @param refSet ca.mcgill.sable.util.Set
00990  */
00991 public static Set fieldRefToSootField(Set refSet) {
00992     Set sootFieldSet = new ArraySet();
00993     for (Iterator refIt = refSet.iterator(); refIt.hasNext();) {
00994         FieldRef oneRef = (FieldRef) refIt.next();
00995         sootFieldSet.add(oneRef.getField());
00996     }
00997     return sootFieldSet;
00998 }
00999   /**
01000    * Get the map of control dependency.
01001    * <p>
01002    * @return {@link #stmtToCdOn stmtToCdOn}.
01003    */
01004   public Map getCdMap()
01005     {
01006       return stmtToCdOn;
01007     }
01008 /**
01009  * Insert the method's description here.
01010  * Creation date: (4/20/2001 11:25:56 AM)
01011  * @return ca.mcgill.sable.soot.jimple.Stmt
01012  * @param testStmts ca.mcgill.sable.soot.jimple.Stmt[]
01013  */
01014 private Stmt getConditionalStmtFrom(Stmt[] testStmts) {
01015     for (int i = 0; i < testStmts.length; i++) {
01016         if (testStmts[i] instanceof IfStmt)
01017             return testStmts[i];
01018     }
01019     return testStmts[0];
01020 }
01021   /**
01022    * Get the map of data dependency.
01023    * <p>
01024    * @return {@link #stmtToDdOn stmtToDdOn}.
01025    */
01026   public Map getDdMap()
01027     {
01028       return stmtToDdOn;
01029     }
01030 /**
01031  * Insert the method's description here.
01032  * Creation date: (4/20/2001 10:27:38 AM)
01033  * @return ca.mcgill.sable.util.Map
01034  */
01035 Map getDivergenceMap() {
01036     return divergenceMap;
01037 }
01038   /**
01039    * Get all statements in handlers in the method.
01040    * <p>
01041    * @return a set of {@link ca.mcgill.sable.soot.jimple.Stmt Stmt}.
01042    * Empty set is returned, if there is no such statement.
01043    */
01044 private Set getHandlerStmtSet() {
01045     Set stmtSet = new ArraySet();
01046     for (Iterator trapIt = jimpleBody.getTraps().iterator(); trapIt.hasNext();) {
01047         Trap trap = (Trap) trapIt.next();
01048         Stmt handlerStmt = (Stmt) trap.getHandlerUnit();
01049         stmtSet.add(handlerStmt);
01050     }
01051     return stmtSet;
01052 }
01053   /**
01054    * Get the index of statement <code>s</code> from 
01055    * {@link #instanceFieldDefStmtList instanceFieldDefStmtList}.
01056    * <p>
01057    * @return index of <code>s</code>. <code>-1</code> is returned, if
01058    * <code>s</code> is not in <code>instanceFieldDefStmtList</code>.
01059    */
01060    private int getInstanceDefIndexOf(Stmt s)
01061     {
01062       int index = -1;
01063       Object array[] = instanceFieldDefStmtList.toArray();
01064       for (int i = 0; i<array.length; i++)
01065     {
01066       DataBox db = (DataBox) array[i];
01067       Stmt fieldDefStmt = db.getInterferStmt();
01068       if (fieldDefStmt.equals(s)) 
01069         {
01070           index = i;
01071           return index;
01072         }
01073     }
01074 
01075       return index;
01076     }
01077   /**
01078    * Get {@link #instanceFieldDefStmtList instanceFieldDefStmtList}.
01079    * <p>
01080    * @return {@link #instanceFieldDefStmtList instanceFieldDefStmtList}.
01081    */
01082   public Set getInstanceFieldDefStmtList()
01083     {
01084       return instanceFieldDefStmtList;
01085     }
01086   /**
01087    * Get {@link #interferenceMap interferenceMap}.
01088    * <p>
01089    * @return {@link #interferenceMap interferenceMap}.
01090    */
01091   public Map getInterferenceMap()
01092     {
01093       return interferenceMap;
01094     }
01095   /**
01096    * Get {@link #lockAnalysis lockAnalysis}.
01097    * <p>
01098    * @return {@link #lockAnalysis lockAnalysis}.
01099    */
01100   public LockAnalysis getLockAnalysis()
01101     {
01102       return lockAnalysis;
01103     }
01104   /**
01105    * Get {@link #readyDependMap readyDependMap}.
01106    * <p>
01107    * @return {@link #readyDependMap readyDependMap}.
01108    */
01109   public Map getReadyDependMap()
01110     {
01111       return readyDependMap;
01112     }
01113 /**
01114  * Insert the method's description here.
01115  * Creation date: (7/11/2001 3:18:54 PM)
01116  * @return ca.mcgill.sable.util.Set
01117  * @param vars ca.mcgill.sable.util.Set
01118  * @param sootField ca.mcgill.sable.soot.SootField
01119  */
01120 private Set getRefsWithCommonField(Set vars, SootField sootField) {
01121     Set refSet = new ArraySet();
01122     for (Iterator varIt = vars.iterator(); varIt.hasNext();) {
01123         Object var = (Object) varIt.next();
01124         if (var instanceof InstanceFieldRef) {
01125             InstanceFieldRef insVar = (InstanceFieldRef) var;
01126             if (insVar.getField().equals(sootField))
01127                 refSet.add(insVar.getBase());
01128         }
01129     }
01130     return refSet;
01131 }
01132 /**
01133    * Find out the special invoke &lt init &gt statement corresponding to the 
01134    * <code>new</code> expression. For example, there is a fragment of Jimple code like 
01135    * <p>
01136    *       [1] p = new Power;
01137    * <br>
01138    *       [2] specialinvoke p.[Power. &lt init &gt ():void]();
01139    * <br>
01140    *       [3] i = virtualinvoke p.[Power.power(int,int):int](5, 3);
01141    * <p>
01142    * Suppose slice it from statement [3]. Then apparently [3] is data dependent on
01143    * [1] by <code>p</code>. Statement [2] will not be in the slice, 
01144    * since there is no explicit definition in [2]. In fact, [2] is an initialization
01145    * for <code>p</code>. So it can be and should be considered as a definition of 
01146    * <code>p</code>. In other words, [1] and [2] together should be the definition of
01147    * <code>p</code> other than only [1].
01148    * So statement [3] is data dependent on both [1] and [2]. 
01149    * <br>
01150    * However, the traditional data dependence analysis dose not cover this condition,
01151    * since [2] is not a definition statement.
01152    * <p>
01153    * Given a statement with <code>new</code> expression, e.g., [1], this method
01154    * will search out the corresponding special &lt init &gt invoke for it, e.g., [2].
01155    * This method is called by {@link #specialInvokeDdAnalysis() specialInvokeDdAnalysis()}.
01156    * <p>
01157    * @param ddBoxWithNewExpr DataBox which includes a statement with 
01158    * <code>new</code> expression.
01159    * @param typeOfNewExpr type of the new expression.
01160    * @return the corresponding special init invoke.
01161    * @throws NoInitStmtException if can not find the special init invoke for 
01162    * <code>ddBoxWithNewExpr</code>.
01163    */
01164 private Stmt getSpecialInvokeStmtOf(DataBox ddBoxWithNewExpr, SootClass newClass) {
01165     for (Iterator stmtKeyIt = stmtToDdOn.keySet().iterator(); stmtKeyIt.hasNext();) {
01166         Stmt stmtK = (Stmt) stmtKeyIt.next();
01167         if (!(stmtK instanceof InvokeStmt))
01168             continue;
01169         InvokeStmt invokeStmtK = (InvokeStmt) stmtK;
01170         Value invokeExpr = invokeStmtK.getInvokeExpr();
01171         if (!(invokeExpr instanceof SpecialInvokeExpr))
01172             continue;
01173         String methodInvoked = ((InvokeExpr) invokeExpr).getMethod().getName();
01174         if (!methodInvoked.equals("<init>"))
01175             continue;
01176 
01177         //String typeOfInvokeBase =
01178         // ((SpecialInvokeExpr) invokeExpr).getBase().getType().toString();
01179 
01180         SootClass typeOfInvokeBase = ((InvokeExpr) invokeExpr).getMethod().getDeclaringClass();
01181         //if (!typeOfInvokeBase.equals(typeOfNewExpr))
01182         //continue;
01183         if (newClass.equals(typeOfInvokeBase) || newClass.getSuperClass().equals(typeOfInvokeBase)) {
01184             Set specDdBoxes = (Set) stmtToDdOn.get(stmtK);
01185             if (specDdBoxes.contains(ddBoxWithNewExpr))
01186                 return stmtK;
01187         }
01188     }
01189     throw new NoInitStmtException("Can not find the special invoke init statement dependent on " + ddBoxWithNewExpr + "  in getSpecialInvokeStmtOf of BuildPDG.java");
01190 }
01191   /**
01192    * Find out the special invoke &lt init &gt statement corresponding to the 
01193    * <code>new</code> expression. For example, there is a fragment of Jimple code like 
01194    * <p>
01195    *       [1] p = new Power;
01196    * <br>
01197    *       [2] specialinvoke p.[Power. &lt init &gt ():void]();
01198    * <br>
01199    *       [3] i = virtualinvoke p.[Power.power(int,int):int](5, 3);
01200    * <p>
01201    * Suppose slice it from statement [3]. Then apparently [3] is data dependent on
01202    * [1] by <code>p</code>. Statement [2] will not be in the slice, 
01203    * since there is no explicit definition in [2]. In fact, [2] is an initialization
01204    * for <code>p</code>. So it can be and should be considered as a definition of 
01205    * <code>p</code>. In other words, [1] and [2] together should be the definition of
01206    * <code>p</code> other than only [1].
01207    * So statement [3] is data dependent on both [1] and [2]. 
01208    * <br>
01209    * However, the traditional data dependence analysis dose not cover this condition,
01210    * since [2] is not a definition statement.
01211    * <p>
01212    * Given a statement with <code>new</code> expression, e.g., [1], this method
01213    * will search out the corresponding special &lt init &gt invoke for it, e.g., [2].
01214    * This method is called by {@link #specialInvokeDdAnalysis() specialInvokeDdAnalysis()}.
01215    * <p>
01216    * @param ddBoxWithNewExpr DataBox which includes a statement with 
01217    * <code>new</code> expression.
01218    * @param typeOfNewExpr type of the new expression.
01219    * @return the corresponding special init invoke.
01220    * @throws NoInitStmtException if can not find the special init invoke for 
01221    * <code>ddBoxWithNewExpr</code>.
01222    */
01223 private Stmt getSpecialInvokeStmtOf(DataBox ddBoxWithNewExpr, String typeOfNewExpr) {
01224     for (Iterator stmtKeyIt = stmtToDdOn.keySet().iterator(); stmtKeyIt.hasNext();) {
01225         Stmt stmtK = (Stmt) stmtKeyIt.next();
01226         if (!(stmtK instanceof InvokeStmt))
01227             continue;
01228         InvokeStmt invokeStmtK = (InvokeStmt) stmtK;
01229         Value invokeExpr = invokeStmtK.getInvokeExpr();
01230         if (!(invokeExpr instanceof SpecialInvokeExpr))
01231             continue;
01232         String methodInvoked = ((InvokeExpr) invokeExpr).getMethod().getName();
01233         if (!methodInvoked.equals("<init>"))
01234             continue;
01235 
01236         String typeOfInvokeBase =
01237          ((SpecialInvokeExpr) invokeExpr).getBase().getType().toString();
01238 
01239         //SootClass typeOfInvokeBase = ((InvokeExpr) invokeExpr).getMethod().getDeclaringClass();
01240         if (typeOfInvokeBase.equals(typeOfNewExpr))
01241         //if (newClass.equals(typeOfInvokeBase) || newClass.getSuperClass().equals(typeOfInvokeBase))
01242           {
01243             Set specDdBoxes = (Set) stmtToDdOn.get(stmtK);
01244             if (specDdBoxes.contains(ddBoxWithNewExpr))
01245               return stmtK;
01246           }
01247     }
01248     throw new NoInitStmtException("Can not find the special invoke init statement dependent on " + ddBoxWithNewExpr + "  in getSpecialInvokeStmtOf of BuildPDG.java");
01249 }
01250   /**
01251    * Get the index of statement <code>s</code> from 
01252    * {@link #staticFieldDefStmtList staticFieldDefStmtList}
01253    * <p>
01254    * @return index of <code>s</code>. <code>-1</code> is returned, if
01255    * <code>s</code> is not in <code>staticFieldDefStmtList</code>.
01256    */
01257   private int getStaticDefIndexOf(Stmt s)
01258     {
01259       int index = -1;
01260       Object array[] = staticFieldDefStmtList.toArray();
01261       for (int i = 0; i<array.length; i++)
01262     {
01263       DataBox db = (DataBox) array[i];
01264       Stmt fieldDefStmt = db.getInterferStmt();
01265       if (fieldDefStmt.equals(s)) 
01266         {
01267           index = i;
01268           return index;
01269         }
01270     }
01271 
01272       return index;
01273     }
01274   /**
01275    * Compute immediate (post)dominators for {@link #stmtToPostdoms stmtToPostdoms}. 
01276    * <br> This method is only called by {@link #domination() domination()}. 
01277    * <br> The result is stored in {@link #stmtToImmedPostdom stmtToImmedPostdom}.
01278    */
01279 private void immediateDominators() {
01280     //immediate dominator for one node must be unique or none
01281 
01282     stmtToImmedPostdom = computeImmedDom(stmtToPostdoms);
01283 }
01284   /**
01285    * Get immediate postdominator for a statement represented by an index
01286    * <code>stmtIndex</code>, using {@link #stmtToImmedPostdom stmtToImmedPostdom}.
01287    * <p>
01288    * @param stmtIndex index of a statement.
01289    * @return index of the postdominator for <code>stmtIndex</code>.
01290    */
01291   public int immediatePostdominatorOf(int stmtIndex)
01292     {
01293       Stmt stmt = (Stmt) stmtList.get(stmtIndex);
01294       return ((Integer) stmtToImmedPostdom.get(stmt)).intValue();
01295     }
01296   /**
01297    * Get immediate postdominator for a statement
01298    * <code>stmt</code>, using {@link #stmtToImmedPostdom stmtToImmedPostdom}.
01299    * <p>
01300    * @param stmt query statement.
01301    * @return index of the postdominator for <code>stmt</code>.
01302    */
01303   public int immediatePostdominatorOf(Stmt stmt)
01304     {
01305       return ((Integer) stmtToImmedPostdom.get(stmt)).intValue();
01306     }
01307   /**
01308    * Get a back point for the method if there is an indefinite loop in the method.
01309    * <br>
01310    * The back point is, for example,
01311    * <p>
01312    * [1] label-a: stmt1;
01313    * <br>[2]   ..... ;
01314    * <br>..... ;
01315    * <br>[n] goto label-a;
01316    * <p>
01317    * statement [n], assumming that statement [1] to [n] is an indefinite loop.
01318    * <p>
01319    * @param cfanns annotation manager.
01320    * @param mdInfo method information.
01321    * @return the index of back point of an indefinite loop, if any. 
01322    * {@link IndexMaps#specialExitNode IndexMaps.specialExitNode} is returned,
01323    * if there is no such back point.
01324    */
01325 public static Integer indefiniteFrom(AnnotationManager cfanns, MethodInfo mdInfo) {
01326     Annotation annForSm = cfanns.getAnnotation(mdInfo.sootClass, mdInfo.sootMethod);
01327 
01328     //BlockStmtAnnotation blockAnnForSm = (BlockStmtAnnotation) annForSm;
01329     Vector currentCFANNs = annForSm.getAllAnnotations(true);
01330     for (Enumeration e = currentCFANNs.elements(); e.hasMoreElements();) {
01331         Annotation cfann = (Annotation) e.nextElement();
01332         if (cfann instanceof ControlFlowAnnotation) {
01333             ControlFlowAnnotation controlCfann = (ControlFlowAnnotation) cfann;
01334             if (controlCfann.isIndefinite()) {
01335                 Stmt backPointStmt = controlCfann.getBackpointStmt();
01336                 Integer backIndex = new Integer(mdInfo.originalStmtList.indexOf(backPointStmt));
01337                 return backIndex;
01338             }
01339         }
01340     }
01341     return IndexMaps.specialExitNode;
01342 }
01343 //new postDomAnalysis
01344   /**
01345    * Initialize workList and {@link #stmtToPostdoms stmtToPostdoms}
01346    * for postdomination analysis which is done by
01347    * {@link #postDomAnalysis() postDomAnalysis()}.
01348    * <br>This initialization is required by the algorithm in Muchnick book
01349    * "Advanced compiler design and implementation"
01350    * by Steven S. Muchnick, 1997.
01351    * <p>
01352    * @param cfanns annotation manager.
01353    * @return a linked list of {@link Integer Integer} which is the index
01354    * of statement in {@link #stmtList stmtList}.
01355    * @throws NoExitNodeException if can not find out an exit node for the method.
01356    */
01357 private LinkedList initializeWorkList(AnnotationManager cfanns) {
01358     LinkedList workList = new LinkedList();
01359     BitSet postDominators = new BitSet(stmtList.size());
01360     Stmt keyStmt;
01361 
01362     //initialize the exit statement's postdom as itself
01363     //if there is no exit node, that means there must be an
01364     //indefinite loop
01365     if (SetUtil.emptyBitSet(exitNodesNoThrow)) {
01366         indefiniteNode = indefiniteFrom(cfanns, methodInfo);
01367         if (indefiniteNode.equals(IndexMaps.specialExitNode))
01368             throw new NoExitNodeException("Can not find out the exit node or the infinite loop in method " + methodInfo.sootMethod.getName());
01369         workList.addFirst(indefiniteNode);
01370         keyStmt = (Stmt) stmtList.get(indefiniteNode.intValue());
01371         postDominators.set(indefiniteNode.intValue());
01372         stmtToPostdoms.put(keyStmt, postDominators);
01373     } else {
01374         for (int i = 0; i < stmtList.size(); i++) {
01375             if (exitNodes.get(i)) {
01376                 workList.addFirst(new Integer(i));
01377                 keyStmt = (Stmt) stmtList.get(i);
01378                 postDominators = new BitSet(stmtList.size());
01379                 postDominators.set(i);
01380                 stmtToPostdoms.put(keyStmt, postDominators);
01381             }
01382         }
01383         indefiniteNode = IndexMaps.specialExitNode;
01384     }
01385     return workList;
01386 }
01387 /**
01388    * Get the set of statements that define some mutual instance field references
01389    * with the statement <code>instanceDefIndex</code> using 
01390    * {@link #instanceFieldDefStmtList staticFieldDefStmtList}.
01391    * <p>
01392    * @param instanceDefIndex  the index of a statement in 
01393    * {@link #instanceFieldDefStmtList instanceFieldDefStmtList} which defines
01394    * an instance field reference.
01395    * @return a set of {@link java.lang.Integer} which is index of a statement
01396    * in {@link #instanceFieldDefStmtList instanceFieldDefStmtList}.
01397    * Empty set is returned, if there is no such statement.
01398    */
01399 private Set instanceDefsNotPreserves(int instanceDefIndex) {
01400     Set defsNotPres = new ArraySet();
01401     defsNotPres.add(new Integer(instanceDefIndex));
01402     Object array[] = instanceFieldDefStmtList.toArray();
01403     DataBox instanceBox = (DataBox) array[instanceDefIndex];
01404     Set instanceDefs = instanceBox.getInterferVars();
01405     for (int i = 0; i < array.length; i++) {
01406         DataBox db = (DataBox) array[i];
01407         Set instanceDefs2 = db.getInterferVars();
01408         Set intersectDefs = SetUtil.setIntersection(instanceDefs, instanceDefs2);
01409         if (intersectDefs.size() != 0)
01410             defsNotPres.add(new Integer(i));
01411     }
01412     return defsNotPres;
01413 }
01414 /**
01415  * Insert the method's description here.
01416  * Creation date: (7/10/2001 3:13:31 PM)
01417  * @return boolean
01418  * @param v1 ca.mcgill.sable.soot.jimple.Value
01419  * @param v2 ca.mcgill.sable.soot.jimple.Value
01420  * @param enclosingMethod ca.mcgill.sable.soot.SootMethod
01421  */
01422 public static boolean mayPointToTheSameRef(Value v1, Value v2, SootMethod enclosingMethod1, SootMethod enclosingMethod2) {
01423     Collection refValues = Slicer.BOFA_Analysis.referenceValueSet(v1, enclosingMethod1);
01424     Collection refValues2 = Slicer.BOFA_Analysis.referenceValueSet(v2, enclosingMethod2);
01425     //see if there is common element in refValues and refValues2
01426     for (Iterator valueIt = refValues.iterator(); valueIt.hasNext();) {
01427         if (refValues2.contains(valueIt.next()))
01428             return true;
01429     }
01430     return false;
01431 }
01432 /**
01433  * Insert the method's description here.
01434  * Creation date: (7/10/2001 3:13:31 PM)
01435  * @return boolean
01436  * @param v1 ca.mcgill.sable.soot.jimple.Value
01437  * @param v2 ca.mcgill.sable.soot.jimple.Value
01438  * @param enclosingMethod ca.mcgill.sable.soot.SootMethod
01439  */
01440 public static boolean mayPointToTheSameRef(Value v1, Set vs, SootMethod enclosingMethod1, SootMethod enclosingMethod2) {
01441 for (Iterator varIt = vs.iterator(); varIt.hasNext();){
01442     Value v2 = (Value) varIt.next();
01443     boolean mayPointToTheSame = BuildPDG.mayPointToTheSameRef(v1, v2, enclosingMethod1, enclosingMethod2);
01444     if (mayPointToTheSame) return true;
01445 }
01446     return false;
01447 }
01448   /**
01449    * Analyse postdomination for the method.
01450    * <p>
01451    * @see #initializeWorkList(AnnotationManager)
01452    * @see #postdomFixPoint(LinkedList)
01453    */
01454 private void postDomAnalysis() {
01455     LinkedList workList = initializeWorkList(annotationManager);
01456     postdomFixPoint(workList);
01457 }
01458   /**
01459    * Calculate postdominators for each statement in the method starting from
01460    * ininialized <code>workList</code>.
01461    * <br>
01462    * The result is stored in {@link #stmtToPostdoms stmtToPostdoms}.
01463    * <p>
01464    * The alorithm is from the book
01465    * "Advanced compiler design and implementation"
01466    * by Steven S. Muchnick, 1997.
01467    */
01468 private void postdomFixPoint(LinkedList workList) {
01469     boolean change = true;
01470     BitSet postDominators = new BitSet(stmtList.size());
01471     BitSet tempPostdoms = new BitSet(stmtList.size());
01472     Set visitedNode = new ArraySet();
01473 
01474     // Initialize postdoms for other statement as all index set
01475     // but not including exception handling statement
01476 
01477     Set initialWorkList = new ArraySet();
01478     for (int i = 0; i < workList.size(); i++) {
01479         initialWorkList.add((Integer) workList.get(i));
01480     }
01481 
01482     //add start nodes into the worklist 
01483 
01484     workList.addFirst(new Integer(0));
01485     BitSet indexSetWoE = methodInfo.indexMaps.indexSetWithoutExceptionHandling();
01486     for (int i = 0; i < indexSetWoE.size(); i++) {
01487         if (indexSetWoE.get(i))
01488             postDominators.set(i);
01489     }
01490     while (workList.size() != 0) {
01491         Integer nodeIndex = (Integer) workList.removeFirst();
01492         visitedNode.add(nodeIndex);
01493         Stmt nodeStmt = (Stmt) stmtList.get(nodeIndex.intValue());
01494         if (!initialWorkList.contains(nodeIndex))
01495             stmtToPostdoms.put(nodeStmt, postDominators);
01496         List nodeStmtSuccs = stmtGraph.getSuccsOf(nodeStmt);
01497         //List newSuccs = removeExceptionCaught(nodeStmtSuccs);
01498         List newSuccs = nodeStmtSuccs;
01499         for (Iterator succIt = newSuccs.iterator(); succIt.hasNext();) {
01500             Stmt succStmt = (Stmt) succIt.next();
01501             Integer succIndex = new Integer(stmtList.indexOf(succStmt));
01502             if (workList.contains(succIndex) || visitedNode.contains(succIndex)) {
01503             } else
01504                 workList.addLast(succIndex);
01505         }
01506     }
01507     while (change) {
01508         change = false;
01509         workList.clear();
01510         visitedNode.clear();
01511 
01512         //initializing worklist everytime
01513         for (Iterator i = initialWorkList.iterator(); i.hasNext();) {
01514             workList.addFirst((Integer) i.next());
01515         }
01516         while (workList.size() != 0) {
01517             Integer stmtIndex = (Integer) workList.removeFirst();
01518             visitedNode.add(stmtIndex);
01519             Stmt keyStmt = (Stmt) stmtList.get(stmtIndex.intValue());
01520             postDominators = (BitSet) stmtToPostdoms.get(keyStmt);
01521             if (postDominators == null)
01522                 continue;
01523             tempPostdoms = (BitSet) postDominators.clone();
01524             List realSuccs = stmtGraph.getSuccsOf(keyStmt);
01525             List succs = removeExceptionCaught(realSuccs);
01526             for (int i = 0; i < succs.size(); i++) {
01527                 Stmt succStmt = (Stmt) succs.get(i);
01528                 BitSet succDom = (BitSet) stmtToPostdoms.get(succStmt);
01529                 tempPostdoms.and(succDom);
01530             }
01531             tempPostdoms.set(stmtIndex.intValue());
01532             if (!tempPostdoms.equals(postDominators)) {
01533                 change = true;
01534                 stmtToPostdoms.remove(keyStmt);
01535                 stmtToPostdoms.put(keyStmt, tempPostdoms);
01536             }
01537 
01538             //begin to add nodes into workList
01539 
01540 
01541             List preds = stmtGraph.getPredsOf(keyStmt);
01542             for (int i = 0; i < preds.size(); i++) {
01543                 Stmt predStmt = (Stmt) preds.get(i);
01544                 Integer predIndex = new Integer(stmtList.indexOf(predStmt));
01545                 if (workList.contains(predIndex) || visitedNode.contains(predIndex)) {
01546                 } else
01547                     workList.addLast(predIndex);
01548             }
01549         }
01550     }
01551 }
01552 /**
01553  * Get postdominators of a statement represented by the <code>int</code> index in 
01554  * {@link #stmtList stmtList} using {@link #stmtToPostdoms stmtToPostdoms}.
01555  * <p>
01556  * @param index int index of the query statement.
01557  * @return a set of postdominators of <code>index</code>
01558  * represented by {@link BitSet BitSet}.
01559  */
01560 BitSet postdominatorsOf(int index) {
01561     Stmt stmt = (Stmt) stmtList.get(index);
01562     return (BitSet) stmtToPostdoms.get(stmt);
01563 }
01564 /**
01565  * Get postdominators of a statement using {@link #stmtToPostdoms stmtToPostdoms}.
01566  * <p>
01567  * @param stmt query statement.
01568  * @return a set of postdominators of <code>stmt</code>
01569  * represented by {@link BitSet BitSet}.
01570  */
01571 public BitSet postdominatorsOf(Stmt stmt) {
01572     return (BitSet) stmtToPostdoms.get(stmt);
01573 }
01574 /**
01575  * Get postdominators of a statement represented by the Integer index in 
01576  * {@link #stmtList stmtList} using {@link #stmtToPostdoms stmtToPostdoms}.
01577  * <p>
01578  * @param stmtIndex Integer index of the query statement.
01579  * @return a set of postdominators of <code>stmtIndex</code>
01580  * represented by {@link BitSet BitSet}.
01581  */
01582   public BitSet postdominatorsOf(Integer stmtIndex)
01583     {
01584       Stmt stmt = (Stmt) stmtList.get(stmtIndex.intValue());
01585       return (BitSet) stmtToPostdoms.get(stmt);
01586     }
01587 /**
01588  * Insert the method's description here.
01589  * Creation date: (4/20/2001 11:33:42 AM)
01590  * @return java.util.BitSet
01591  * @param stmt ca.mcgill.sable.soot.jimple.Stmt
01592  */
01593 public BitSet preDivergencePointsOf(Stmt stmt) {
01594     int indexOfStmt = stmtList.indexOf(stmt);
01595     BitSet preDivergencePoints = new BitSet(stmtList.size());
01596     for (Iterator keyIt = divergenceMap.keySet().iterator(); keyIt.hasNext();) {
01597         Stmt divergPoint = (Stmt) keyIt.next();
01598         BitSet reachableStmts = (BitSet) divergenceMap.get(divergPoint);
01599         if (reachableStmts.get(indexOfStmt)) {
01600             int indexOfDivergPoint = stmtList.indexOf(divergPoint);
01601             preDivergencePoints.set(indexOfDivergPoint);
01602         }
01603     }
01604     return preDivergencePoints;
01605 }
01606   /** 
01607    * Prepare to analyse data and control dependence.
01608    * <p>
01609    * @param mdInfo method information.
01610    */
01611 private void prepareToBuild(MethodInfo mdInfo) {
01612     methodInfo = mdInfo;
01613     jimpleBody = (JimpleBody) mdInfo.sootMethod.getBody(Jimple.v());
01614     stmtList = mdInfo.originalStmtList;
01615     stmtToPostdoms = new HashMap(stmtList.size() * 2 + 1, 0.7f);
01616     stmtGraph = mdInfo.indexMaps.getStmtGraph();
01617     IndexMaps im = mdInfo.indexMaps;
01618     exitNodes = im.exitNodes();
01619 
01620     exitNodesNoThrow = im.exitNodesWithoutThrow(exitNodes);
01621 
01622     callSiteMap = im.getCallSiteMap();
01623     collectInstanceFieldDefStmt();
01624     staticFieldDefStmtList = mdInfo.MOD.staticFields;
01625 }
01626   /**
01627    * Implement reaching definition for instance field references.
01628    * <br>
01629    * There is no reaching definition analysis for field references in 
01630    * Jimple. It only provides the reaching analysis for simple local variables.
01631    * <br>This method is a modified implementation of Bit Vector algorithm in the book
01632    * "Advanced compiler design and implementation"
01633    * by Steven S. Muchnick, 1997. Page 218.
01634    * <br>
01635    * The result is store in {@link #instanceReachDef instanceReachDef}.
01636    */
01637 
01638 private void reachingDefOfInstanceField() {
01639     //we have to determine the reaching definition of instance fields
01640     //considering the call site information like MOD and REF
01641     //this algorithm is like the reaching definition analysis for 
01642     //static fields
01643     boolean change = true;
01644     int instanceFieldDefSize = instanceFieldDefStmtList.size();
01645     int stmtListSize = stmtList.size();
01646     BitSet reachIn[] = new BitSet[stmtListSize];
01647     BitSet preserve[] = new BitSet[stmtListSize];
01648     BitSet generate[] = new BitSet[stmtListSize];
01649 
01650     //initializing the three array
01651     //the sequence of array is the same as the sequence of index in stmtList
01652     //e.g. reachIn[i] indicate that the reach in set of the statement 
01653     //stmtList.get(i)
01654     for (int i = 0; i < stmtListSize; i++) {
01655         //the sequence of each BitSet is determined by the index sequence
01656         //of statciFieldDefStmt, e.g. reachIn[i].get(3) will get the value
01657         //for the 3rd stmt in staticFieldDefStmt (staticFieldDefStmt.get(3))
01658         reachIn[i] = new BitSet(instanceFieldDefSize);
01659         preserve[i] = new BitSet(instanceFieldDefSize);
01660         generate[i] = new BitSet(instanceFieldDefSize);
01661 
01662         //initializing each element as 00000000
01663         //initializing preserve as 111111
01664         for (int j = 0; j < instanceFieldDefSize; j++) {
01665             reachIn[i].clear(j);
01666             preserve[i].set(j);
01667             generate[i].clear(j);
01668         }
01669     }
01670 
01671     //calculate the preserve[i] and generate[i], those are invariant
01672     for (int i = 0; i < stmtListSize; i++) {
01673         Stmt stmt = (Stmt) stmtList.get(i);
01674         int stmtInInstanceDef = getInstanceDefIndexOf(stmt);
01675         if (stmtInInstanceDef >= 0) {
01676             //stmt is in the staticDefStmtList
01677             generate[i].set(stmtInInstanceDef);
01678 
01679             //collect all the defs which defines that the variable in 
01680             //stmtInStaticDef in to one set
01681             
01682             Set defSet = instanceDefsNotPreserves(stmtInInstanceDef);
01683 
01684             //clear all the preserves such that define the variable in 
01685             //stmtInStaticDef
01686             for (Iterator k = defSet.iterator(); k.hasNext();) {
01687                 int defNotPreserve = ((Integer) k.next()).intValue();
01688                 preserve[i].clear(defNotPreserve);
01689             }
01690             
01691         }
01692     }
01693     while (change) {
01694         change = false;
01695         for (int i = 0; i < stmtListSize; i++) {
01696             Stmt stmt = (Stmt) stmtList.get(i);
01697 
01698             //calculate new reachIn[i], with its all predecessors
01699             BitSet newReachIn = null;
01700             List preds = stmtGraph.getPredsOf(stmt);
01701             for (int ppp = 0; ppp < preds.size(); ppp++) {
01702                 int j=stmtList.indexOf(preds.get(ppp));
01703                 //get preserve of preds j preserve[j]
01704                 //get generate of preds j generate[j]
01705                 BitSet tempReachIn = (BitSet) reachIn[j].clone();
01706                 tempReachIn.and(preserve[j]);
01707                 tempReachIn.or(generate[j]);
01708                 if (ppp == 0)
01709                     newReachIn = (BitSet) tempReachIn.clone();
01710                 else
01711                     newReachIn.or(tempReachIn);
01712             }
01713             if (newReachIn != null)
01714 
01715                 
01716                 //if newReachIn== null, this means
01717                 //that preds.size() == 0
01718                 if (!reachIn[i].equals(newReachIn)) {
01719                     reachIn[i] = newReachIn;
01720                     change = true;
01721                 }
01722         }
01723     }
01724     instanceReachDef = reachIn;
01725 }
01726 //There is no reaching definition analysis for static field reference in 
01727 //Jimple, it only provides this reaching analysis for local variables
01728 //this method is an implementation of Bit Vector algorithm on P218 of the 
01729 //Muchnick book
01730   /**
01731    * Implement reaching definition for static field references.
01732    * <br>
01733    * There is no reaching definition analysis for field references in 
01734    * Jimple. It only provides the reaching analysis for simple local variables.
01735    * <br>This method is a modified implementation of Bit Vector algorithm in the book
01736    * "Advanced compiler design and implementation"
01737    * by Steven S. Muchnick, 1997. Page 218.
01738    * <br>
01739    * The result is store in {@link #staticReachDef staticReachDef}.
01740    */
01741 private void reachingDefOfStaticField() {
01742     boolean change = true;
01743     int staticFieldDefSize = staticFieldDefStmtList.size();
01744     int stmtListSize = stmtList.size();
01745     BitSet reachIn[] = new BitSet[stmtListSize];
01746     BitSet preserve[] = new BitSet[stmtListSize];
01747     BitSet generate[] = new BitSet[stmtListSize];
01748 
01749     //initializing the three array
01750     //the sequence of array is the same as the sequence of index in stmtList
01751     //e.g. reachIn[i] indicate that the reach in set of the statement 
01752     //stmtList.get(i)
01753     for (int i = 0; i < stmtListSize; i++) {
01754         //the sequence of each BitSet is determined by the index sequence
01755         //of statciFieldDefStmt, e.g. reachIn[i].get(3) will get the value
01756         //for the 3rd stmt in staticFieldDefStmt (staticFieldDefStmt.get(3))
01757         reachIn[i] = new BitSet(staticFieldDefSize);
01758         preserve[i] = new BitSet(staticFieldDefSize);
01759         generate[i] = new BitSet(staticFieldDefSize);
01760 
01761         //initializing each element as 00000000
01762         //initializing preserve as 111111
01763         for (int j = 0; j < staticFieldDefSize; j++) {
01764             reachIn[i].clear(j);
01765             preserve[i].set(j);
01766             generate[i].clear(j);
01767         }
01768     }
01769 
01770 
01771     //calculate the preserve[i] and generate[i], those are invariant
01772     for (int i = 0; i < stmtListSize; i++) {
01773         Stmt stmt = (Stmt) stmtList.get(i);
01774         int stmtInStaticDef = getStaticDefIndexOf(stmt);
01775         if (stmtInStaticDef >= 0) {
01776             //stmt is in the staticDefStmtList
01777             generate[i].set(stmtInStaticDef);
01778 
01779             //collect all the defs which defines that the variable in 
01780             //stmtInStaticDef in to one set
01781             Set defSet = defsNotPreserves(stmtInStaticDef);
01782 
01783             //clear all the preserves such that define the variable in 
01784             //stmtInStaticDef
01785             for (Iterator k = defSet.iterator(); k.hasNext();) {
01786                 int defNotPreserve = ((Integer) k.next()).intValue();
01787                 preserve[i].clear(defNotPreserve);
01788             }
01789         }
01790     }
01791     while (change) {
01792         change = false;
01793         for (int i = 0; i < stmtListSize; i++) {
01794             Stmt stmt = (Stmt) stmtList.get(i);
01795 
01796             //calculate new reachIn[i], with its all predecessors
01797             BitSet newReachIn = null;
01798             List preds = stmtGraph.getPredsOf(stmt);
01799             for (int ppp = 0; ppp < preds.size(); ppp++) {
01800                 Stmt predStmt = (Stmt)preds.get(ppp);
01801                 int j= stmtList.indexOf(predStmt);
01802                 //get preserve of preds j preserve[j]
01803                 //get generate of preds j generate[j]
01804                 BitSet tempReachIn = (BitSet) reachIn[j].clone();
01805                 tempReachIn.and(preserve[j]);
01806                 tempReachIn.or(generate[j]);
01807                 if (ppp == 0)
01808                     newReachIn = (BitSet) tempReachIn.clone();
01809                 else
01810                     newReachIn.or(tempReachIn);
01811             }
01812             if (newReachIn != null)
01813                 //if newReachIn== null, this means
01814                 //that preds.size() == 0
01815                 if (!reachIn[i].equals(newReachIn)) {
01816                     reachIn[i] = newReachIn;
01817                     change = true;
01818                 }
01819         }
01820     }
01821     staticReachDef = reachIn;
01822 }
01823   /**
01824    * Remove, from <code>actualSuccs</code>, statements which are in exception handlers.
01825    * <p>
01826    * @param actualSuccs a list of {@link Stmt Stmt}.
01827    * @return a list{@link Stmt Stmt} without statements in any handler.
01828    * @see #getHandlerStmtSet()
01829    */ 
01830 private List removeExceptionCaught(List actualSuccs) {
01831     List newSuccs = new ArrayList();
01832     Set trapHandlerStmtSet = getHandlerStmtSet();
01833     for (Iterator asuccsIt = actualSuccs.iterator(); asuccsIt.hasNext();) {
01834         Stmt succStmt = (Stmt) asuccsIt.next();
01835         if (!trapHandlerStmtSet.contains(succStmt))
01836             newSuccs.add(succStmt);
01837     }
01838     return newSuccs;
01839 }
01840   /** 
01841    * Set {@link #interferenceMap interferenceMap}.
01842    * <p>
01843    * @param iterMap interference map.
01844    */
01845   public void setInterferenceMap(Map iterMap)
01846     {
01847       interferenceMap = iterMap;
01848     }
01849   /**
01850    * Set {@link #lockAnalysis lockAnalysis}.
01851    * <p>
01852    * @param la an instance of LockAnalysis.
01853    */
01854   public void setLockAnalysis(LockAnalysis la)
01855     {
01856       lockAnalysis = la;
01857     }
01858   /** 
01859    * Set {@link #readyDependMap readyDependMap}.
01860    * <p>
01861    * @param rm ready dependent map.
01862    */
01863   public void setReadyDependMap(Map rm)
01864     {
01865       readyDependMap = rm;
01866     }
01867 /**
01868    * Analyse data dependence for special invoke expressions.
01869    * <br>For example, there is a fragment of Jimple code like 
01870    * <p>
01871    *       [1] p = new Power;
01872    * <br>
01873    *       [2] specialinvoke p.[Power. &lt init &gt ():void]();
01874    * <br>
01875    *       [3] i = virtualinvoke p.[Power.power(int,int):int](5, 3);
01876    * <p>
01877    * Suppose slice it from statement [3]. Then apparently [3] is data dependent on
01878    * [1] by <code>p</code>. Statement [2] will not be in the slice, 
01879    * since there is no explicit definition in [2]. In fact, [2] is an initialization
01880    * for <code>p</code>. So it can be and should be considered as a definition of 
01881    * <code>p</code>. In other words, [1] and [2] together should be the definition of
01882    * <code>p</code> other than only [1].
01883    * So statement [3] is data dependent on both [1] and [2]. 
01884    * <br>
01885    * However, the traditional data dependence analysis dose not cover this condition,
01886    * since [2] is not a definition statement.
01887    * <p>
01888    * Given a statement with <code>new</code> expression, e.g., [1], this method
01889    * will search out the corresponding special &lt init &gt invoke for it, e.g., [2].
01890    */
01891 private void specialInvokeDdAnalysis() {
01892     for (Iterator keyIt = stmtToDdOn.keySet().iterator(); keyIt.hasNext();) {
01893         Stmt keyStmt = (Stmt) keyIt.next();
01894         Set ddBoxesInMap = (Set) stmtToDdOn.get(keyStmt);
01895         Set ddBoxes = new ArraySet();
01896         ddBoxes.addAll(ddBoxesInMap);
01897         for (Iterator i = ddBoxes.iterator(); i.hasNext();) {
01898             DataBox ddBox = (DataBox) i.next();
01899             Stmt ddOnStmt = (Stmt) ddBox.getStmt();
01900             if (ddOnStmt instanceof DefinitionStmt) {
01901                 DefinitionStmt defStmt = (DefinitionStmt) ddOnStmt;
01902                 Value rightOp = defStmt.getRightOp();
01903                 if (rightOp instanceof NewExpr) {
01904                     NewExpr newExpr = (NewExpr) rightOp;
01905                     String className = newExpr.getType().toString();
01906                     SootClass newExprType = IndexMaps.lookupSootClassByName(className);
01907                     Stmt specInvoke = null;
01908                     if (newExprType == null)
01909                         specInvoke = getSpecialInvokeStmtOf(ddBox, className);
01910                     //newExpr.getBaseType() it's the same as getType()
01911                     //as far as I know
01912 
01913                     else
01914                         specInvoke = getSpecialInvokeStmtOf(ddBox, newExprType);
01915                     if (specInvoke.equals(keyStmt)) {
01916                     } else {
01917                         DataBox specInvokeDataBox = new DataBox(specInvoke, ddBox.getDependVar());
01918                         //ddBox.getDependVar() must be the definition variable
01919                         //like rn = new Object; and the specInvoke should be data
01920                         //depend on rn
01921 
01922                         //set the dataBox as a invoke init data box
01923                         specInvokeDataBox.setToInvokeInit();
01924                         ddBoxesInMap.add(specInvokeDataBox);
01925                         ddBoxesInMap.remove(ddBox);
01926                         ddBox.setToNewExprStmt();
01927                         ddBoxesInMap.add(ddBox);
01928                     }
01929                 }
01930             } else {
01931             }
01932         }
01933     }
01934 }
01935 /**
01936  * Insert the method's description here.
01937  * Creation date: (4/20/2001 11:33:42 AM)
01938  * @return java.util.BitSet
01939  * @param stmt ca.mcgill.sable.soot.jimple.Stmt
01940  */
01941 public BitSet succDivergencePointsOf(Stmt stmt) {
01942     if (divergenceMap.containsKey(stmt))
01943         return (BitSet) divergenceMap.get(stmt);
01944     else
01945         return null;
01946 }
01947   /*
01948   private boolean stmtNotIn(Stmt s, List defList)
01949     {
01950       boolean returnValue = true;
01951       Iterator listIt = defList.iterator();
01952       while (listIt.hasNext())
01953     {
01954       DataBox fields = (DataBox) listIt.next();
01955       if (s == fields.getInterferStmt())
01956         {
01957           returnValue = false;
01958           break;
01959         }
01960     }
01961       return returnValue;
01962     }
01963   */
01964   public String toString()
01965     {
01966       String pdg = "Stmt to Postdomimators: " + stmtToPostdoms + "\n\n";
01967       pdg += "Stmt to Control Depend nodes: " + stmtToCdOn + "\n\n";
01968       pdg += "Stmt to Data Depend nodes: " + stmtToDdOn + "\n";
01969       return pdg;
01970     }
01971 }

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