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

PostProcessOnAnnotation.java

00001 package edu.ksu.cis.bandera.pdgslicer;
00002 
00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00004  * Bandera, a Java(TM) analysis and transformation toolkit           *
00005  * Copyright (C) 1998, 1999   Hongjun Zheng (zheng@cis.ksu.edu)      *
00006  * All rights reserved.                                              *
00007  *                                                                   *
00008  * This work was done as a project in the SAnToS Laboratory,         *
00009  * Department of Computing and Information Sciences, Kansas State    *
00010  * University, USA (http://www.cis.ksu.edu/santos).                  *
00011  * It is understood that any modification not identified as such is  *
00012  * not covered by the preceding statement.                           *
00013  *                                                                   *
00014  * This work is free software; you can redistribute it and/or        *
00015  * modify it under the terms of the GNU Library General Public       *
00016  * License as published by the Free Software Foundation; either      *
00017  * version 2 of the License, or (at your option) any later version.  *
00018  *                                                                   *
00019  * This work is distributed in the hope that it will be useful,      *
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of    *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *
00022  * Library General Public License for more details.                  *
00023  *                                                                   *
00024  * You should have received a copy of the GNU Library General Public *
00025  * License along with this toolkit; if not, write to the             *
00026  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,      *
00027  * Boston, MA  02111-1307, USA.                                      *
00028  *                                                                   *
00029  * Java is a trademark of Sun Microsystems, Inc.                     *
00030  *                                                                   *
00031  * To submit a bug report, send a comment, or get the latest news on *
00032  * this project and other SAnToS projects, please visit the web-site *
00033  *                http://www.cis.ksu.edu/santos                      *
00034  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00035 
00036 
00037 import ca.mcgill.sable.util.*;
00038 import ca.mcgill.sable.soot.*;
00039 import ca.mcgill.sable.soot.jimple.*;
00040 import edu.ksu.cis.bandera.pdgslicer.exceptions.*;
00041 import edu.ksu.cis.bandera.annotation.*;
00042 import java.io.*;
00043 import java.util.Enumeration;
00044 import java.util.Vector;
00045 import java.util.BitSet;
00046 import edu.ksu.cis.bandera.jjjc.symboltable.Name;
00047 import edu.ksu.cis.bandera.jjjc.symboltable.Package;
00048 /**
00049  * This class is for constructing residual program for
00050  * each sliced class and method.
00051  */
00052 public class PostProcessOnAnnotation {
00053     /*
00054     public final static int UNTOUCHED = -1;
00055     private final static int UNREACHABLE = -2;
00056     private final static int REMAINED = 0;
00057     private final static int SLICED = 1;
00058     private final static int STMT_RETURN_TO_VOID = 2;
00059     private final static int STMT_PARAMETER_CHANGED = 3;
00060     private final static int MD_DEC_RETURN_TO_VOID = 4;
00061     private final static int MD_DEC_PARAMETER_CHANGED = 5;
00062     private final static int LOCAL_DEC_CHANGED = 6;
00063     */
00064     private Map modifiedSootMethodToRemovableLocals = new HashMap();
00065     private Set removableSootMethods = new ArraySet();
00066     private Set unreachableSootMethods = new ArraySet();
00067     private Set unreachableSootClasses = Slicer.unreachableClasses;
00068     private Set removableSootFields = new ArraySet();
00069     private Set parameterModifiedSootMethods = new ArraySet();
00070     /**
00071        * A list of {@link ClassInfo ClassInfo} for each class.
00072        */
00073     private List classList;
00074     /**
00075        * A list of {@link ClassInfo ClassInfo} which is sliced away.
00076        */
00077     private Set removableSootClasses = new ArraySet(); //it's including unreachable sootclasses
00078     /**
00079        * A list of {@link SootMethod SootMethod} such that
00080        * return value should be changed to return void due to
00081        * the irrelevance of return value.
00082        */
00083     private List changeReturnTypeToVoidMds = new ArrayList();
00084     /** 
00085        * A set of {@link Value Value} which is relevant in 
00086        * the residual program.
00087        */
00088     private Set relevantFields = new ArraySet();
00089     private Set relevantExceptionClassNames = new ArraySet();
00090     private AnnotationManager cfanns = null;
00091 /**
00092    * @param ct a list of {@link ClassInfo ClassInfo}.
00093    * @param cfs annotation manager.
00094    */
00095 public PostProcessOnAnnotation(List ct, AnnotationManager cfs) {
00096     classList = ct;
00097     cfanns = cfs;
00098 }
00099 /**
00100  * Add all statements in <code>catch</code> block into
00101  * a set <code>removedSet</code> except for those
00102  * in the given slice set.
00103  * <p>
00104  * @param removedSet a set of {@link Stmt Stmt} which is
00105  * the result of this method.
00106  * @param catches a vector of {@link Annotation Annotation}
00107  * which is that of catch clause.
00108  * @param stmtList statement list for indexing.
00109  * @param linePropList a set of {@link Stmt Stmt} which
00110  * is slice point.
00111  * @param slcSet slice set indexed in a BitSet.
00112  */
00113 private void addCatchesToRemovedSet(Set removedSet, Vector catches, StmtList stmtList, Set linePropList, BitSet slcSet) {
00114     for (Enumeration e2 = catches.elements(); e2.hasMoreElements();) {
00115         Annotation catchClauseCFANN = (Annotation) e2.nextElement();
00116         Stmt trapStmts[] = catchClauseCFANN.getStatements();
00117         for (int i = 0; i < trapStmts.length; i++) {
00118             Stmt stmt = trapStmts[i];
00119             int stmtIndex = stmtList.indexOf(trapStmts[i]);
00120             if (linePropList.contains(stmt))
00121                 continue;
00122             removedSet.add(stmt);
00123             if (slcSet.get(stmtIndex))
00124                 slcSet.set(stmtIndex);
00125         }
00126     }
00127 }
00128 /**
00129  * Add all statements in catch blocks into the given slice set.
00130  * <p>
00131  * @param slcSet slice set indexed in a BitSet.
00132  * @param catches a vector of {@link Annotation Annotation}.
00133  * @param stmtList statement list for indexing.
00134  */
00135 private void addCatchesToSliceSet(BitSet slcSet, Vector catches, StmtList stmtList) {
00136     for (Enumeration e2 = catches.elements(); e2.hasMoreElements();) {
00137         Annotation catchClauseCFANN = (Annotation) e2.nextElement();
00138         Stmt trapStmts[] = catchClauseCFANN.getStatements();
00139         for (int i = 0; i < trapStmts.length; i++) {
00140             slcSet.set(stmtList.indexOf(trapStmts[i]));
00141             if (i == 0) {
00142                 Stmt caughtStmt = trapStmts[0];
00143                 if (caughtStmt instanceof IdentityStmt) {
00144                     IdentityStmt idCaughtStmt = (IdentityStmt) caughtStmt;
00145                     Value leftOp = idCaughtStmt.getLeftOp();
00146                     Value rightOp = idCaughtStmt.getRightOp();
00147                     if (leftOp instanceof Local) {
00148                         Local leftOpValue = (Local) leftOp;
00149                         Type valueType = leftOpValue.getType();
00150                         String exceptionName = valueType.toString();
00151                         if (!exceptionName.startsWith("java.lang."))
00152                         this.relevantExceptionClassNames.add(exceptionName);
00153                         //System.out.println("left value type: " + valueType);
00154                     }
00155                     /*
00156                     if (rightOp instanceof CaughtExceptionRef) {
00157                         CaughtExceptionRef rightOpEx = (CaughtExceptionRef) rightOp;
00158                         Type caughtType = rightOpEx.getType();
00159                         //System.out.println("Caught tyep: " + caughtType);
00160                     }
00161                     */
00162                 }
00163             }
00164         }
00165     }
00166 }
00167 private boolean buildNewInvokeExpr(InvokeExpr invokeExpr) {
00168     SootMethod invokedMethod = invokeExpr.getMethod();
00169     if (parameterModifiedSootMethods.contains(invokedMethod))
00170         return true;
00171     return false;
00172 }
00173   /**
00174    * Process parameters of a call site in slice. Change parameters of an invoke expression
00175    * in terms of changes in called method.
00176    * <p>
00177    * @param callSiteIndexMap a map from {@link Stmt Stmt} to {@link CallSite CallSite}.
00178    * @param callSiteMap a map from {@link CallSite CallSite} to {@link SootMethod SootMethod}.
00179    * @param stmt a statement with an invoke expression.
00180    * <p>
00181    * @see {#buildNewInvokeExpr(InvokeExpr)}
00182    */
00183 private void callSiteInSlice(Map callSiteIndexMap, Map callSiteMap, Stmt stmt) {
00184     CallSite callSite = (CallSite) callSiteIndexMap.get(stmt);
00185     SootMethod callee = (SootMethod) callSiteMap.get(callSite);
00186     MethodInfo calleeMdInfo = (MethodInfo) Slicer.sootMethodInfoMap.get(callee);
00187     if (calleeMdInfo == null) return;
00188     if (calleeMdInfo.sCriterion == null) {
00189     } else {
00190         LinkedList keepedParaOriginalIndex = getKeepedParaOriginalIndex(calleeMdInfo);
00191         InvokeExpr invokeExpr = callSite.invokeExpr;
00192         int argCount = invokeExpr.getArgCount();
00193         LinkedList keepedParameters = new LinkedList();
00194         for (int i = 0; i < argCount; i++) {
00195             Value arg = invokeExpr.getArg(i);
00196             if (keepedParaOriginalIndex.contains(new Integer(i)))
00197                 keepedParameters.addLast(arg);
00198         }
00199         /*
00200         if (keepedParameters.size() < argCount) {
00201             for (int i = 0; i < keepedParameters.size(); i++)
00202                 invokeExpr.setArg(i, (Value) keepedParameters.get(i));
00203         }
00204         */
00205     }
00206 }
00207 /**
00208  * See if all statements in an array of statement are not in a slice set.
00209  * <p>
00210  * @return <code>true</code> if all statements in the array are not in the slice set,
00211  * <code>false</code> otherwise.
00212  * @param bodyStmts an array of statement.
00213  * @param sliceSet slice set.
00214  * @param stmtList statement list for indexing.
00215  */
00216 private boolean emptyBody(Stmt[] bodyStmts, BitSet sliceSet, StmtList stmtList) {
00217     for (int i = 0; i < bodyStmts.length; i++) {
00218         if (sliceSet.get(stmtList.indexOf(bodyStmts[i])))
00219             return false;
00220     }
00221     return true;
00222 }
00223 /**
00224  * See if all statements in a set of statement are not in a slice set.
00225  * <p>
00226  * @return <code>true</code> if all statements in the set are not in the slice set,
00227  * <code>false</code> otherwise.
00228  * @param bodyStmts a set of statement.
00229  * @param sliceSet slice set.
00230  * @param stmtList statement list for indexing.
00231  */
00232 private boolean emptyBody(Set bodyStmts, BitSet sliceSet, StmtList stmtList) {
00233     for (Iterator i = bodyStmts.iterator(); i.hasNext();) {
00234         Stmt stmt = (Stmt) i.next();
00235         if (sliceSet.get(stmtList.indexOf(stmt)))
00236             return false;
00237     }
00238     return true;
00239 }
00240 /**
00241  * Collect soot fields from a set of field references.
00242  * <p>
00243  * @param fieldRefSet a set of {@link FieldRef FieldRef}.
00244  * @return a set of {@link SootField SootField}.
00245  */
00246 private Set fieldRefToField(Set fieldRefSet) {
00247     Set fieldSet = new ArraySet();
00248     for (Iterator refIt = fieldRefSet.iterator(); refIt.hasNext();)
00249         fieldSet.add(((FieldRef) refIt.next()).getField());
00250     return fieldSet;
00251 }
00252 //filering from used variable instead of relevant variabls
00253 /**
00254    * Collect all {@link FieldRef FieldRef} from a set of {@link Value Value}
00255    * into the field {@link #relevantFields relevantFields}.
00256    * <p>
00257    * @param variableSet a set of {@link Value Value}.
00258    */
00259 private void filterOutFields(Set variableSet) {
00260     for (Iterator kk = variableSet.iterator(); kk.hasNext();) {
00261         Value loc = (Value) kk.next();
00262         if (loc instanceof FieldRef)
00263             relevantFields.add(loc);
00264     }
00265 }
00266 /**
00267  * Insert the method's description here.
00268  * Creation date: (00-12-7 10:58:43)
00269  * @return ca.mcgill.sable.util.Set
00270  * @param packageName java.lang.String
00271  */
00272 private Set getAllClassesFor(Package pckg) {
00273     Set classes = new ArraySet();
00274     for (Iterator classIt = classList.iterator(); classIt.hasNext();) {
00275         SootClass sootClass = ((ClassInfo) classIt.next()).sootClass;
00276         Name cName = new Name(sootClass.getName());
00277         if (cName.getSuperName().equals(pckg.getName()))
00278             classes.add(sootClass);
00279     }
00280     return classes;
00281 }
00282 /**
00283  * Insert the method's description here.
00284  * Creation date: (00-12-7 10:42:45)
00285  * @return ca.mcgill.sable.util.Set
00286  */
00287 private Set getAllPackages() {
00288     Set packages = new ArraySet();
00289     for (Iterator classIt = classList.iterator(); classIt.hasNext();) {
00290         SootClass sootClass = ((ClassInfo) classIt.next()).sootClass;
00291         Name pn = new Name(sootClass.getName()).getSuperName();
00292         Package pk = null;
00293         try {
00294             pk = Package.getPackage(pn);
00295         } catch (Exception e) {
00296         }
00297         if (pk != null)
00298             packages.add(pk);
00299     }
00300     return packages;
00301 }
00302   /**
00303    * Get all {@link Value Value} used/defined in a method body.
00304    * <p>
00305    * @param mdInfo query method.
00306    * @return a set {@link Value Value}
00307    */
00308 private Set getAllVarsOf(MethodInfo mdInfo) {
00309     StmtList originalStmtList = mdInfo.originalStmtList;
00310     Set allVars = new ArraySet();
00311     for (int i = 0; i < originalStmtList.size(); i++) {
00312         Stmt stmt = (Stmt) originalStmtList.get(i);
00313         allVars.addAll(PostProcess.allVarsOf(stmt));
00314     }
00315     return allVars;
00316 }
00317 /**
00318  * Insert the method's description here.
00319  * Creation date: (00-12-6 15:23:43)
00320  * @return ca.mcgill.sable.util.Set
00321  */
00322 private Set getCurrentResidualClasses() {
00323     Set classSet = new ArraySet();
00324     for (Iterator classIt = classList.iterator(); classIt.hasNext();) {
00325         SootClass sootClass = ((ClassInfo) classIt.next()).sootClass;
00326         if (!removableSootClasses.contains(sootClass))
00327             classSet.add(sootClass);
00328     }
00329     return classSet;
00330 }
00331   /**
00332    * Get residual parameters for a method.
00333    * <p>
00334    * @param mdInfo query method.
00335    * @return a {@link LinkedList LinkedList} of Integer which
00336    * is the index of parameter.
00337    */
00338 private LinkedList getKeepedParaOriginalIndex(MethodInfo mdInfo) {
00339     Local paraLocals[] = mdInfo.indexMaps.getParaLocalSet();
00340     Map relevantVars = mdInfo.sCriterion.relVarMap();
00341     Set relLocs = PostProcess.getRelevantLocals(mdInfo.originalStmtList, mdInfo.sliceSet, relevantVars);
00342     LinkedList keepedParaOriginalIndex = new LinkedList();
00343     for (int i = 0; i < paraLocals.length; i++) {
00344         Local paraLocal = paraLocals[i];
00345         if (relLocs.contains(paraLocal)) {
00346             keepedParaOriginalIndex.addLast(new Integer(i));
00347         }
00348     }
00349     return keepedParaOriginalIndex;
00350 }
00351 /**
00352  * Insert the method's description here.
00353  * Creation date: (00-12-7 10:13:23)
00354  * @return ca.mcgill.sable.util.Set
00355  */
00356 public Set getModifiedPackages() {
00357     Set packages = new ArraySet();
00358     Set removablePackages = getRemovablePackages();
00359     Set modifiedSootClasses = getModifiedSootClasses();
00360     for (Iterator pIt = getAllPackages().iterator(); pIt.hasNext();) {
00361         Package pck = (Package) pIt.next();
00362         if (removablePackages.contains(pck))
00363             continue;
00364         for (Iterator classIt = getAllClassesFor(pck).iterator(); classIt.hasNext();) {
00365             SootClass sootClass = (SootClass) classIt.next();
00366             if (this.removableSootClasses.contains(sootClass) || modifiedSootClasses.contains(sootClass)) {
00367                 packages.add(pck);
00368                 break;
00369             }
00370         }
00371     }
00372     return packages;
00373 }
00374 /**
00375  * Insert the method's description here.
00376  * Creation date: (00-12-7 10:12:44)
00377  * @return ca.mcgill.sable.util.Set
00378  */
00379 public Set getModifiedSootClasses() {
00380     Set modifiedClasses = new ArraySet();
00381     Set modifiedSootMethods = this.getModifiedSootMethods();
00382     for (Iterator classIt = classList.iterator(); classIt.hasNext();) {
00383         SootClass sootClass = ((ClassInfo) classIt.next()).sootClass;
00384         if (this.removableSootClasses.contains(sootClass))
00385             continue;
00386         for (Iterator mdIt = sootClass.getMethods().iterator(); mdIt.hasNext();) {
00387             SootMethod sm = (SootMethod) mdIt.next();
00388             if (this.removableSootMethods.contains(sm) || this.unreachableSootMethods.contains(sm) || modifiedSootMethods.contains(sm))
00389                 modifiedClasses.add(sootClass);
00390         }
00391     }
00392     return modifiedClasses;
00393 }
00394 /**
00395  * Insert the method's description here.
00396  * Creation date: (00-12-6 16:55:43)
00397  * @return ca.mcgill.sable.util.Set
00398  */
00399 public Set getModifiedSootMethods() {
00400     return modifiedSootMethodToRemovableLocals.keySet();
00401 }
00402 /**
00403  * Insert the method's description here.
00404  * Creation date: (00-12-18 11:54:07)
00405  * @return ca.mcgill.sable.util.Set
00406  */
00407 public Set getParameterModifiedMethods() {
00408     return parameterModifiedSootMethods;
00409 }
00410 /**
00411  * Insert the method's description here.
00412  * Creation date: (00-12-6 15:38:21)
00413  * @return ca.mcgill.sable.util.Set
00414  * @param sm ca.mcgill.sable.soot.SootMethod
00415  */
00416 public Set getRemovableLocals(SootMethod sm) {
00417     return (ArraySet) modifiedSootMethodToRemovableLocals.get(sm);
00418 }
00419 /**
00420  * Insert the method's description here.
00421  * Creation date: (00-12-7 10:13:55)
00422  * @return ca.mcgill.sable.util.Set
00423  */
00424 public Set getRemovablePackages() {
00425     Set packages = new ArraySet();
00426     for (Iterator pIt = getAllPackages().iterator(); pIt.hasNext();) {
00427         Package pck = (Package) pIt.next();
00428         boolean removable = true;
00429         for (Iterator classIt = getAllClassesFor(pck).iterator(); classIt.hasNext();) {
00430             SootClass sootClass = (SootClass) classIt.next();
00431             if (!this.removableSootClasses.contains(sootClass)) {
00432                 removable = false;
00433                 break;
00434             }
00435         }
00436         if (removable)
00437             packages.add(pck);
00438     }
00439     return packages;
00440 }
00441 /**
00442  * Insert the method's description here.
00443  * Creation date: (00-12-6 17:10:18)
00444  * @return ca.mcgill.sable.util.Set
00445  */
00446 public Set getRemovableSootClasses() {
00447     return removableSootClasses;
00448 }
00449 /**
00450  * Insert the method's description here.
00451  * Creation date: (00-12-6 15:33:00)
00452  * @return ca.mcgill.sable.util.Set
00453  */
00454 public Set getRemovableSootFields() {
00455     return removableSootFields;
00456 }
00457 /**
00458  * Insert the method's description here.
00459  * Creation date: (00-12-6 15:27:28)
00460  * @return ca.mcgill.sable.util.Set
00461  */
00462 public Set getRemovableSootMethods() {
00463     return removableSootMethods;
00464 }
00465   /**
00466    * Get all trap hanlders from jimple body.
00467    * <p>
00468    * @param jimpBody jimple body
00469    * @return a set of {@link Stmt Stmt} which is trap handler.
00470    */
00471 private Set getTrapHandlers(JimpleBody jimpBody) {
00472     Set trapsHandlerSet = new ArraySet();
00473     Iterator trapIt = jimpBody.getTraps().iterator();
00474     while (trapIt.hasNext()) {
00475         Trap trap = (Trap) trapIt.next();
00476         Stmt handler = (Stmt) trap.getHandlerUnit();
00477         trapsHandlerSet.add(handler);
00478     }
00479     return trapsHandlerSet;
00480 }
00481 /**
00482  * Insert the method's description here.
00483  * Creation date: (00-12-6 15:32:10)
00484  * @return ca.mcgill.sable.util.Set
00485  */
00486 public Set getUnreachableSootClasses() {
00487     return unreachableSootClasses;
00488 }
00489 /**
00490  * Insert the method's description here.
00491  * Creation date: (00-12-6 15:31:31)
00492  * @return ca.mcgill.sable.util.Set
00493  */
00494 public Set getUnreachableSootMethods() {
00495     return unreachableSootMethods;
00496 }
00497 /**
00498  * Insert the method's description here.
00499  * Creation date: (00-12-6 14:54:27)
00500  * @return ca.mcgill.sable.util.Set
00501  * @param jimpleBody ca.mcgill.sable.soot.jimple.JimpleBody
00502  */
00503 private Set getUnusedLocals(MethodInfo mdInfo) {
00504     StmtList stmtList = mdInfo.stmtList;
00505     Set removedStmt = mdInfo.removedStmt;
00506     JimpleBody listBody = (JimpleBody) mdInfo.sootMethod.getBody(Jimple.v());
00507     Set unusedLocals = new ArraySet();
00508     // Set all locals as unused
00509     unusedLocals.addAll(listBody.getLocals());
00510 
00511     // Traverse statements noting all the uses
00512     {
00513         Iterator stmtIt = stmtList.iterator();
00514         while (stmtIt.hasNext()) {
00515             Stmt s = (Stmt) stmtIt.next();
00516             if (removedStmt.contains(s))
00517                 continue;
00518             // Remove all locals in defBoxes from unusedLocals
00519             {
00520                 Iterator boxIt = s.getDefBoxes().iterator();
00521                 while (boxIt.hasNext()) {
00522                     Value value = ((ValueBox) boxIt.next()).getValue();
00523                     if (value instanceof Local && unusedLocals.contains(value))
00524                         unusedLocals.remove(value);
00525                 }
00526             }
00527 
00528             // Remove all locals in useBoxes from unusedLocals
00529             {
00530                 Iterator boxIt = s.getUseBoxes().iterator();
00531                 while (boxIt.hasNext()) {
00532                     Value value = ((ValueBox) boxIt.next()).getValue();
00533                     if (value instanceof Local && unusedLocals.contains(value))
00534                         unusedLocals.remove(value);
00535                 }
00536             }
00537         }
00538     }
00539     return unusedLocals;
00540 }
00541 /**
00542  * Insert the method's description here.
00543  * Creation date: (00-12-7 18:06:38)
00544  */
00545 private void initializeMdInfoAndAnnotation() {
00546     for (Iterator classIt = classList.iterator(); classIt.hasNext();) {
00547         ClassInfo classInfo = (ClassInfo) classIt.next();
00548         if (Slicer.unreachableClasses.contains(classInfo.sootClass))
00549             continue;
00550         if (Slicer.isObjectClass(classInfo.sootClass))
00551             continue;
00552         List mdList = classInfo.methodsInfoList;
00553         for (Iterator mdIt = mdList.iterator(); mdIt.hasNext();) {
00554             MethodInfo mdInfo = (MethodInfo) mdIt.next();
00555             mdInfo.removedStmt = new ArraySet();
00556             Annotation annForSm = cfanns.getAnnotation(mdInfo.sootClass, mdInfo.sootMethod);
00557             Vector currentCFANNs = annForSm.getAllAnnotations(true);
00558             for (Enumeration annEnum = currentCFANNs.elements(); annEnum.hasMoreElements();) {
00559                 Annotation cfann = (Annotation) annEnum.nextElement();
00560                 cfann.initializeState();
00561             }
00562         }
00563     }
00564 }
00565 /**
00566  * Insert the method's description here.
00567  * Creation date: (00-11-14 11:18:28)
00568  * @return boolean
00569  * @param superClass ca.mcgill.sable.soot.SootClass
00570  * @param sm ca.mcgill.sable.soot.SootMethod
00571  */
00572 private boolean isImplementingOneAbstractMd(SootClass superClass, SootMethod sm) {
00573     int modifiers = superClass.getModifiers();
00574     if (!Modifier.isAbstract(modifiers))
00575         return false;
00576     SootMethod abstractMd = null;
00577     try {
00578         abstractMd = superClass.getMethod(sm.getName(), sm.getParameterTypes(), sm.getReturnType());
00579     } catch (ca.mcgill.sable.soot.NoSuchMethodException nse) {
00580         return false;
00581     }
00582     modifiers = abstractMd.getModifiers();
00583     if (Modifier.isAbstract(modifiers))
00584         return true;
00585     return false;
00586 }
00587 /**
00588  * Insert the method's description here.
00589  * Creation date: (00-11-14 10:59:21)
00590  * @return boolean
00591  * @param sm ca.mcgill.sable.soot.SootMethod
00592  */
00593 private boolean isImplementingOneAbstractMd(SootMethod sm) {
00594     boolean isImplementingMd = false;
00595     SootClass declaringClass = sm.getDeclaringClass();
00596     while (declaringClass.hasSuperClass()) {
00597         SootClass superClass = declaringClass.getSuperClass();
00598         isImplementingMd = isImplementingOneAbstractMd(superClass, sm);
00599         if (isImplementingMd)
00600             return isImplementingMd;
00601         declaringClass = superClass;
00602     }
00603     for (Iterator interfaceIt = declaringClass.getInterfaces().iterator(); interfaceIt.hasNext();) {
00604         SootClass interfaceClass = (SootClass) interfaceIt.next();
00605         isImplementingMd = isImplementingOneInterfaceMd(interfaceClass, sm);
00606         if (isImplementingMd)
00607             return isImplementingMd;
00608         while (interfaceClass.hasSuperClass()) {
00609             SootClass superClass = interfaceClass.getSuperClass();
00610             isImplementingMd = isImplementingOneInterfaceMd(interfaceClass, sm);
00611             if (isImplementingMd)
00612                 return isImplementingMd;
00613         }
00614     }
00615     return isImplementingMd;
00616 }
00617 /**
00618  * Insert the method's description here.
00619  * Creation date: (00-11-14 11:29:00)
00620  * @return boolean
00621  * @param interfaceClas ca.mcgill.sable.soot.SootClass
00622  * @param sm ca.mcgill.sable.soot.SootMethod
00623  */
00624 private boolean isImplementingOneInterfaceMd(SootClass interfaceClass, SootMethod sm) {
00625     int modifiers = interfaceClass.getModifiers();
00626     if (!Modifier.isInterface(modifiers))
00627         return false;
00628     try {
00629         SootMethod abstractMd = interfaceClass.getMethod(sm.getName(), sm.getParameterTypes(), sm.getReturnType());
00630     } catch (ca.mcgill.sable.soot.NoSuchMethodException nse) {
00631         return false;
00632     }
00633     return true;
00634 }
00635   /**
00636    * See if a given modifier is public and static.
00637    * <p>
00638    * @param modifier modifier.
00639    * @return boolean.
00640    */
00641   private boolean isPublicAndStatic(int modifier)
00642     {
00643       if (Modifier.isPublic(modifier) && 
00644       Modifier.isStatic(modifier)) 
00645     return true;
00646       else return false;
00647     }
00648   /**
00649    * Keep all parameters for <code>main</code> method, even those parameters are irrelevant.
00650    * <p>
00651    * @param mdInfo query method.
00652    * @param relevantVars relevant variables map.
00653    * @param stmtList statement list
00654    * @param sliceSet slice set.
00655    */
00656 private void keepParasOfMainMd(MethodInfo mdInfo, Map relevantVars, StmtList stmtList, BitSet sliceSet) {
00657     //to see if there is main method and then keep all parameter identity statement.
00658 
00659     if (mdInfo.sootMethod.getName().equals("main") && isPublicAndStatic(mdInfo.sootMethod.getModifiers())) {
00660         Stmt[] paraIds = mdInfo.indexMaps.getParaIdentityStmts();
00661 
00662         //add all parameter identitise into slice set of main method
00663         for (int ids = 0; ids < paraIds.length; ids++) {
00664             int idIndex = stmtList.indexOf(paraIds[ids]);
00665             sliceSet.set(idIndex);
00666             relevantVars.put(paraIds[ids], SlicingMethod.allLocalVarsOf(paraIds[ids]));
00667         }
00668     }
00669 }
00670 /**
00671  * Insert the method's description here.
00672  * Creation date: (00-11-14 13:21:07)
00673  * @param sm ca.mcgill.sable.soot.SootMethod
00674  */
00675 private void makeMethodEmpty(MethodInfo methodInfo, Annotation annForSm) {
00676     if (methodInfo == null)
00677         return;
00678     IndexMaps indexMaps = methodInfo.indexMaps;
00679     Set removableStmts = new ArraySet();
00680     Set keepStmts = new ArraySet();
00681     int thisRefStmtIndex = indexMaps.getThisRefStmtIndex().intValue();
00682     Stmt thisRefStmt = (Stmt) methodInfo.stmtList.get(thisRefStmtIndex);
00683     Stmt[] paraIdentities = indexMaps.getParaIdentityStmts();
00684     //extract return statement and assignment to $ret
00685     Stmt returnStmt = null;
00686     Stmt ret$Stmt = null;
00687     Object[] returnAnns = indexMaps.getReturnAnnotations().toArray();
00688     if (returnAnns.length > 0) {
00689         Stmt[] returnStmts = ((Annotation) returnAnns[0]).getStatements();
00690         Type returnType = methodInfo.sootMethod.getReturnType();
00691         if (returnType instanceof VoidType) {
00692             for (int i = 0; i < returnStmts.length; i++) {
00693                 if (returnStmts[i] instanceof ReturnVoidStmt) {
00694                     returnStmt = returnStmts[i];
00695                     break;
00696                 }
00697             }
00698         } else
00699             for (int i = 0; i < returnStmts.length; i++) {
00700                 if (returnStmts[i] instanceof ReturnStmt)
00701                     returnStmt = returnStmts[i];
00702                 else
00703                     if (returnStmts[i] instanceof AssignStmt) {
00704                         Value leftOp = ((AssignStmt) returnStmts[i]).getLeftOp();
00705                         if (leftOp instanceof Local)
00706                             if (((Local) leftOp).getName().equals("$ret"))
00707                                 ret$Stmt = returnStmts[i];
00708                     }
00709             }
00710     }
00711     // calculate keeped statement set
00712     keepStmts.add(thisRefStmt);
00713     if (returnStmt != null)
00714         keepStmts.add(returnStmt);
00715     if (ret$Stmt != null)
00716         keepStmts.add(ret$Stmt);
00717     for (int i = 0; i < paraIdentities.length; i++)
00718         keepStmts.add(paraIdentities[i]);
00719     //calculate removable statements
00720     for (Iterator stmtIt = methodInfo.stmtList.iterator(); stmtIt.hasNext();) {
00721         Stmt stmt = (Stmt) stmtIt.next();
00722         if (!keepStmts.contains(stmt))
00723             removableStmts.add(stmt);
00724     }
00725     //remove statement from annotation
00726     for (Iterator stmtIt = removableStmts.iterator(); stmtIt.hasNext();) {
00727         try {
00728             Stmt sss = (Stmt) stmtIt.next();
00729             annForSm.removeStmtByMark(sss);
00730             methodInfo.removedStmt.add(sss);
00731         } catch (Exception e) {
00732         }
00733     }
00734     /*
00735     //remove statement from statement list
00736     if (!removableStmts.isEmpty())
00737     for (Iterator stmtIt = removableStmts.iterator(); stmtIt.hasNext();)
00738     methodInfo.stmtList.remove(stmtIt.next());
00739     */
00740     //change assignment statement $ret=value into $ret=null;
00741     if (ret$Stmt != null) {
00742         NullConstant nullCons = NullConstant.v();
00743         Value leftOp = ((AssignStmt) ret$Stmt).getLeftOp();
00744         AssignStmt newRetAssign = Jimple.v().newAssignStmt(leftOp, nullCons);
00745         //int k = methodInfo.stmtList.indexOf(ret$Stmt);
00746         //methodInfo.stmtList.remove(k);
00747         try {
00748             //cfanns.putInlineStmt(newRetAssign, ret$Stmt, methodInfo.sootMethod);
00749             annForSm.replaceStmtByMark(ret$Stmt, newRetAssign);
00750         } catch (Exception e) {
00751         }
00752         //methodInfo.stmtList.add(k, newRetAssign);
00753     }
00754 }
00755 /**
00756    * Construct residual method.
00757    * <p>
00758    * @param mdInfo method to be constructed.
00759    */
00760 private boolean modifyMethod(MethodInfo mdInfo) {
00761     boolean modified = false;
00762     JimpleBody jimpBody = (JimpleBody) mdInfo.sootMethod.getBody(Jimple.v());
00763     StmtList stmtList = mdInfo.stmtList;
00764     StmtList stmtListClone = mdInfo.originalStmtList;
00765     BitSet sliceSet = mdInfo.sliceSet;
00766     int stmtListSize = stmtListClone.size();
00767     Integer thisRefIndex = mdInfo.indexMaps.getThisRefStmtIndex();
00768     Integer specialInvokeIndex = null;
00769 
00770     //add for every instance method this reference stmt to initSliceSet required by Robby 1/7/2000
00771 
00772     if (thisRefIndex != null)
00773         sliceSet.set(thisRefIndex.intValue());
00774     BuildPDG pdg = mdInfo.methodPDG;
00775     Map relevantVars = mdInfo.sCriterion.relVarMap();
00776     Map callSiteMap = mdInfo.indexMaps.getCallSiteMap();
00777     Map callSiteIndexMap = SlicingMethod.callSiteIndex(callSiteMap);
00778     BitSet stmtIndexToNop = new BitSet(stmtListSize);
00779     BitSet removedStmtIndexSet = new BitSet(stmtListSize);
00780     StmtGraph sg = mdInfo.indexMaps.getStmtGraph();
00781     Set trapsHandlerSet = getTrapHandlers(jimpBody);
00782     SootMethod sm = mdInfo.sootMethod;
00783     SootClass sootClass = mdInfo.sootClass;
00784     Annotation annForSm = cfanns.getAnnotation(sootClass, sm);
00785     Vector currentCFANNs = annForSm.getAllAnnotations(true);
00786     keepParasOfMainMd(mdInfo, relevantVars, stmtList, sliceSet);
00787     Set removedStmtByEmptyBlock = new ArraySet();
00788     removeEmptyBlock(mdInfo, removedStmtByEmptyBlock, currentCFANNs, stmtList, jimpBody);
00789 
00790     //get relevant variables from sliceSet
00791     Set relLocs = PostProcess.getRelevantLocals(stmtList, sliceSet, relevantVars);
00792     boolean changedReturnToVoid = false;
00793     //operating on stmtList, using stmtListClone to index
00794     for (int k = 0; k < stmtList.size(); k++) {
00795         Stmt stmt = (Stmt) stmtList.get(k);
00796         int stmtIndex = stmtListClone.indexOf(stmt);
00797         if (sliceSet.get(stmtIndex)) {
00798             if (thisRefIndex != null) {
00799                 if (stmtIndex == thisRefIndex.intValue())
00800                     continue;
00801             }
00802             if (specialInvokeIndex != null) {
00803                 if (stmtIndex == specialInvokeIndex.intValue())
00804                     continue;
00805             }
00806             if (stmt instanceof ReturnStmt) {
00807 
00808                 //at this moment we only consider the return value is just
00809                 //a local variable
00810                 Value retVal = ((ReturnStmt) stmt).getReturnValue();
00811                 if (!(retVal instanceof Local)) {
00812                     if (changedReturnToVoid) {
00813                         //change return stmt to return void stmt
00814 
00815                         Stmt s = (Stmt) stmtList.get(k);
00816                         ReturnVoidStmt rtvs = Jimple.v().newReturnVoidStmt();
00817                         try {
00818                             annForSm.replaceStmtByMark(s, rtvs);
00819                             modified = true;
00820                         } catch (Exception e) {
00821                         }
00822 
00823 
00824                         //change return type of the method into void
00825                         changeReturnTypeToVoidMds.add(mdInfo.sootMethod);
00826                     }
00827                 } else
00828                     if (retVal instanceof Local) {
00829                         if (relLocs.contains(retVal)) {
00830                         } else {
00831                             //change return stmt to return void stmt
00832 
00833                             Stmt s = (Stmt) stmtList.get(k);
00834                             ReturnVoidStmt rtvs = Jimple.v().newReturnVoidStmt();
00835                             try {
00836                                 annForSm.replaceStmtByMark(s, rtvs);
00837                                 modified = true;
00838                             } catch (Exception e) {
00839                             }
00840 
00841 
00842                             //change return type of the method into void
00843                             changeReturnTypeToVoidMds.add(mdInfo.sootMethod);
00844                             changedReturnToVoid = true;
00845                         }
00846                     }
00847                     //previous part is for method need to change return value to return void.
00848             } else
00849                 if (trapsHandlerSet.contains(stmt)) {
00850                 } else
00851                     if (callSiteIndexMap.containsKey(stmt)) {
00852                         callSiteInSlice(callSiteIndexMap, callSiteMap, stmt);
00853                     } else {
00854                         Set allRefVariablesInStmt = SlicingMethod.refVarsOf(stmt);
00855                         //Set allVariablesInStmt = allLocalVarsOf(stmt, sg);        
00856                         //if (SetUtil.setIntersection(allVariablesInStmt, relLocs).size() !=0 
00857                         if (relLocs.containsAll(allRefVariablesInStmt) || (stmt instanceof ThrowStmt) || (stmt instanceof ReturnVoidStmt)) {
00858                         } else {
00859 
00860                             //it must be a line proposition without relvant variables
00861                             //we can change it to nop
00862                             //and can not be removed after refining
00863 
00864                             //the line proposition can be checked in slicing stage, and let them be not in initial slice set, the problem is that if there is some statement on which the line propostion control depend on , so we decide to omit the line proposition statement and change it into nops
00865 
00866                             stmtIndexToNop.set(stmtIndex);
00867                             Stmt nopStmt = Jimple.v().newNopStmt();
00868                             //Stmt s = (Stmt) stmtList.remove(k);
00869                             Stmt s = (Stmt) stmtList.get(k);
00870                             try {
00871                                 annForSm.replaceStmtByMark(s, nopStmt);
00872                                 modified = true;
00873                             } catch (Exception e) {
00874                             }
00875                         }
00876                     }
00877         } else {
00878             //stmt not in slice
00879             if ((stmt instanceof GotoStmt) && !removedStmtByEmptyBlock.contains(stmt)) {
00880             } else
00881                 if (stmt instanceof ReturnStmt) {
00882 
00883                     //at this moment we only consider the return value is just
00884                     //a local variable
00885                     Value retVal = ((ReturnStmt) stmt).getReturnValue();
00886                     if (retVal instanceof Local) {
00887                         if (!relLocs.contains(retVal)) {
00888 
00889                             //change return stmt to return void stmt
00890 
00891                             Stmt s = (Stmt) stmtList.get(k);
00892                             ReturnVoidStmt rtvs = Jimple.v().newReturnVoidStmt();
00893                             try {
00894                                 annForSm.replaceStmtByMark(s, rtvs);
00895                                 modified = true;
00896                             } catch (Exception e) {
00897                             }
00898 
00899                             //change return type of the method into void
00900                             changeReturnTypeToVoidMds.add(mdInfo.sootMethod);
00901                         }
00902                     }
00903                 } else
00904                     if ((stmt instanceof ReturnVoidStmt) || (stmt instanceof RetStmt)) {
00905                     } else {
00906                         //change current stmt into nop if debug
00907                         //remove current stmt from stmtList
00908                         try {
00909                             annForSm.removeStmtByMark((Stmt) stmtList.get(k));
00910                             mdInfo.removedStmt.add(stmtList.get(k));
00911                             modified = true;
00912                         } catch (Exception e) {
00913                         }
00914                         removedStmtIndexSet.set(stmtIndex);
00915                     }
00916         }
00917     }
00918     Set useAndDefVarsInSlice = PostProcess.getAllVarsOf(stmtListClone, SetUtil.bitSetAndNot(sliceSet, stmtIndexToNop));
00919 
00920     //filering from used variable instead of relevant variabls
00921     filterOutFields(useAndDefVarsInSlice);
00922     return modified;
00923 }
00924 /**
00925  * Insert the method's description here.
00926  * Creation date: (00-11-10 9:18:31)
00927  */
00928 private void relevantExceptionClasses() {
00929     Set relevantExceptionClassInfo = new ArraySet();
00930     if (relevantExceptionClassNames.isEmpty())
00931         return;
00932     for (Iterator classIt = classList.iterator(); classIt.hasNext();) {
00933         ClassInfo classInfo = (ClassInfo) classIt.next();
00934         String className = classInfo.sootClass.getName();
00935         if (this.relevantExceptionClassNames.contains(className))
00936             relevantExceptionClassInfo.add(classInfo);
00937     }
00938     for (Iterator classIt = relevantExceptionClassInfo.iterator(); classIt.hasNext();) {
00939         ClassInfo classInfo = (ClassInfo) classIt.next();
00940         if (this.removableSootClasses.contains(classInfo.sootClass))
00941             this.removableSootClasses.remove(classInfo.sootClass);
00942     }
00943 }
00944 /**
00945    * Filter out the classes such that there is no method left in the class, but there are
00946    * some fields are relevant, i.e., accessible by other relvant classes. So those classes
00947    * are not removable.
00948    */
00949 private void relevantFDClass() {
00950     Set restoredClasses = new ArraySet();
00951     for (Iterator listIt = removableSootClasses.iterator(); listIt.hasNext();) {
00952         SootClass sootClass = (SootClass) listIt.next();
00953         if (Slicer.isObjectClass(sootClass))
00954             continue;
00955         for (Iterator i = relevantFields.iterator(); i.hasNext();) {
00956             FieldRef oneField = (FieldRef) i.next();
00957             SootClass declareClass = oneField.getField().getDeclaringClass();
00958             if (sootClass.equals(declareClass))
00959                 restoredClasses.add(sootClass);
00960         }
00961     }
00962     removableSootClasses.removeAll(restoredClasses);
00963 }
00964 /**
00965  * Insert the method's description here.
00966  * Creation date: (00-12-6 15:16:27)
00967  */
00968 private void relevantInterfaceAndSuperClasses() {
00969     Set currentResidualClasses = getCurrentResidualClasses();
00970     Set unremovableClasses = new ArraySet();
00971     for (Iterator classIt = removableSootClasses.iterator(); classIt.hasNext();) {
00972         SootClass sootClass = (SootClass) classIt.next();
00973         if (!Slicer.isRemovableClass(sootClass, currentResidualClasses))
00974             unremovableClasses.add(sootClass);
00975     }
00976     if (!unremovableClasses.isEmpty())
00977         removableSootClasses.removeAll(unremovableClasses);
00978 }
00979   /**
00980    * Remove all empty block in one method. 
00981    * It's including: <code> removeEmptyLock, removeEmeptyTry, removeEmptyTryFinally, 
00982    * removeEmptyConditionalBlock</code>.
00983    * <p>
00984    * @param mdInfo query method.
00985    * @param rmedStmtByEmptBlck a set of statement removed.
00986    * @param currentCFANNS a vector of annotations need to be analysed.
00987    * @param stmtList statement list.
00988    */
00989 private void removeEmptyBlock(MethodInfo mdInfo, Set rmedStmtByEmptBlck, Vector currentCFANNs, StmtList stmtList, JimpleBody jimpleBody) {
00990     //remove empty lock pair: entermonitor and exitmonitor
00991     BitSet sliceSet = mdInfo.sliceSet;
00992     {
00993         LockAnalysis lockAna = mdInfo.methodPDG.getLockAnalysis();
00994         if (lockAna != null)
00995             removeEmptyLock(lockAna.getLockPairList(), sliceSet, mdInfo.sCriterion.getSlicePoints(), rmedStmtByEmptBlck, stmtList);
00996     }
00997     removeEmptyTry(currentCFANNs, sliceSet, mdInfo.sCriterion.getSlicePoints(), rmedStmtByEmptBlck,stmtList, jimpleBody);
00998     removeEmptyTryFinally(currentCFANNs, sliceSet, mdInfo.sCriterion.getSlicePoints(), rmedStmtByEmptBlck, stmtList, jimpleBody);
00999     removeEmptyConditionalBlock(currentCFANNs, sliceSet, mdInfo.sCriterion.getSlicePoints(), rmedStmtByEmptBlck, stmtList);
01000 
01001     //including removing empty sequential block   
01002 }
01003   /**
01004    * Remove empty conditional block.
01005    * <p>
01006    * @param currentCfanns a vector of annotations need to be analysed.
01007    * @param slcSet slice set.
01008    * @param linePropList a set of statement.
01009    * @param removedStmtByEmptyB removed statements.
01010    * @param stmtList statement list.
01011    */
01012 private void removeEmptyConditionalBlock(Vector currentCfanns, BitSet slcSet, Set linePropList, Set removedStmtByEmptyB, StmtList stmtList) {
01013     for (Enumeration e = currentCfanns.elements(); e.hasMoreElements();) {
01014         Annotation cfann = (Annotation) e.nextElement();
01015         if (cfann instanceof ConditionalAnnotation) {
01016             ConditionalAnnotation conditionalStmtAnn = (ConditionalAnnotation) cfann;
01017             Set condStmts = new ArraySet(conditionalStmtAnn.getStatements());
01018             Set bodyStmts = new ArraySet();
01019             bodyStmts.addAll(condStmts);
01020             Set testStmts = new ArraySet(conditionalStmtAnn.getTestStatements());
01021             bodyStmts.removeAll(testStmts);
01022             if (emptyBody(bodyStmts, slcSet, stmtList)) {
01023                 for (Iterator i = condStmts.iterator(); i.hasNext();) {
01024                     Stmt stmt = (Stmt) i.next();
01025                     if (linePropList.contains(stmt))
01026                         continue;
01027                     removedStmtByEmptyB.add(stmt);
01028                 }
01029             }
01030         } //end of if instanceof IfStmtAnnotation
01031         else
01032             if (cfann instanceof ControlFlowAnnotation) {
01033                 ControlFlowAnnotation controlFlowStmtAnn = (ControlFlowAnnotation) cfann;
01034                 Stmt bodyStmts[] = controlFlowStmtAnn.getBlockAnnotation().getStatements();
01035                 if (emptyBody(bodyStmts, slcSet, stmtList)) {
01036                     bodyStmts = controlFlowStmtAnn.getStatements();
01037                     for (int i = 0; i < bodyStmts.length; i++) {
01038                         Stmt stmt = bodyStmts[i];
01039                         if (linePropList.contains(stmt))
01040                             continue;
01041                         removedStmtByEmptyB.add(stmt);
01042                     }
01043                 }
01044             }
01045 
01046             /*
01047               else if ((cfann instanceof SequentialAnnotation)
01048                && (!(cfann instanceof BreakStmtAnnotation)))
01049                 {
01050                   SequentialAnnotation sequentialAnn = 
01051             (SequentialAnnotation) cfann;
01052                   Stmt bodyStmts[] = sequentialAnn.getStatements();
01053             
01054                   //printout the bodyStmts[] for debug
01055                   System.out.println("Print out the bodyStmts");
01056                   for (int ss=0; ss<bodyStmts.length; ss++)
01057             {
01058               System.out.println(bodyStmts[ss]);
01059             }
01060             
01061                   System.out.println("SliceSet: " + slcSet);
01062                   System.out.println("emptyBody? " + emptyBody(bodyStmts, slcSet, stmtToIndex));
01063             
01064                   if (emptyBody(bodyStmts, slcSet, stmtToIndex))
01065             {
01066               // bodyStmts = sequentialAnn.getStatements(); 
01067               for (int i=0; i<bodyStmts.length; i++)
01068                 {
01069                   Index stmtIndex = (Index) stmtToIndex.get(bodyStmts[i]);
01070                   if (linePropList.contains(stmtIndex)) continue;
01071             
01072                   removedStmtByEmptyB.addElemToSet(stmtIndex);
01073                  
01074                   //if (slcSet.contains(stmtIndex))
01075                   //slcSet.remove(stmtIndex);
01076                   
01077                 }
01078             System.out.println("since SequentialAnn: " +removedStmtByEmptyB);      
01079             }   
01080                 }
01081               */
01082 
01083     } //end of for enumeration
01084 }
01085   /**
01086    * Remove empty lock.
01087    * <p>
01088    * @param lockPairList a list of {@link LockPair LockPair}.
01089    * @param slcSet slice set.
01090    * @param linePropList a set of statement.
01091    * @param removedStmtByEmptyB removed statements.
01092    * @param stmtList statement list.
01093    */
01094 private void removeEmptyLock(List lockPairList, BitSet slcSet, Set linePropList, Set removedStmtByEmptyB, StmtList stmtList) {
01095     for (Iterator lockPairIt = lockPairList.iterator(); lockPairIt.hasNext();) {
01096         MonitorPair lockPair = (MonitorPair) lockPairIt.next();
01097         Stmt monitorStmt = (Stmt) lockPair.getEnterMonitor();
01098         Annotation synchroBodyAnn = lockPair.getSynchroBodyAnn();
01099         Stmt bodyStmts[] = synchroBodyAnn.getStatements();
01100         if (emptyBody(bodyStmts, slcSet, stmtList)) {
01101             //remove all stmt between monitor (synchronized stmt)
01102             monitorStmt = lockPair.getEndSynchroStmt();
01103             int exitIndex = stmtList.indexOf(monitorStmt);
01104             monitorStmt = lockPair.getBeginSynchroStmt();
01105             int enterIndex = stmtList.indexOf(monitorStmt);
01106             for (int i = enterIndex; i <= exitIndex; i++) {
01107                 Stmt stmt = (Stmt) stmtList.get(i);
01108                 if (linePropList.contains(stmt))
01109                     continue;
01110                 removedStmtByEmptyB.add(stmt);
01111                 if (slcSet.get(i)) {
01112                     slcSet.clear(i);
01113                 }
01114             }
01115         } else
01116             
01117             //not empty, add exception handling into slice set
01118             {
01119             Annotation catchCFANN = lockPair.getCatchAnn();
01120             Stmt catchStmts[] = catchCFANN.getStatements();
01121             for (int i = 0; i < catchStmts.length; i++) {
01122                 slcSet.set(stmtList.indexOf(catchStmts[i]));
01123             }
01124         }
01125     }
01126 }
01127 /**
01128    * Remove empty try block.
01129    * <p>
01130    * @param currentCfanns a vector of annotations need to be analysed.
01131    * @param slcSet slice set.
01132    * @param linePropList a set of statement.
01133    * @param removedStmtByEmptyB removed statements.
01134    * @param stmtList statement list.
01135    */
01136 private void removeEmptyTry(Vector currentCfanns, BitSet slcSet, Set linePropList, Set removedStmtByEmptyB, StmtList stmtList, JimpleBody jimpleBody) {
01137     for (Enumeration e = currentCfanns.elements(); e.hasMoreElements();) {
01138         Annotation cfann = (Annotation) e.nextElement();
01139         if (cfann instanceof TryStmtAnnotation) {
01140             TryStmtAnnotation tryCFANN = (TryStmtAnnotation) cfann;
01141             Annotation tryBody = tryCFANN.getBlockAnnotation();
01142             Stmt bodyStmts[] = tryBody.getStatements();
01143 
01144             //to see if the sliceset includes any statements in bodyStms
01145 
01146             if (emptyBody(bodyStmts, slcSet, stmtList)) {
01147                 Stmt allBodyStmts[] = tryCFANN.getStatements();
01148                 for (int i = 0; i < allBodyStmts.length; i++) {
01149                     Stmt stmt = allBodyStmts[i];
01150                     int stmtIndex = stmtList.indexOf(stmt);
01151                     if (linePropList.contains(stmt))
01152                         continue;
01153                     removedStmtByEmptyB.add(stmt);
01154                     if (slcSet.get(stmtIndex))
01155                         slcSet.clear(stmtIndex);
01156                 }
01157                 addCatchesToRemovedSet(removedStmtByEmptyB, tryCFANN.getCatchClauses(), stmtList, linePropList, slcSet);
01158                 //remove all traps about this body
01159                 //removeTrapsOf(bodyStmts,jimpleBody);
01160             } else {
01161 
01162                 //add exception handling into slice set
01163                 //System.out.println("add catch of try");
01164                 Vector catches = tryCFANN.getCatchClauses();
01165                 addCatchesToSliceSet(slcSet, catches, stmtList);
01166             }
01167         }
01168     }
01169 }
01170   /**
01171    * Remove empty try finally block.
01172    * <p>
01173    * @param currentCfanns a vector of annotations need to be analysed.
01174    * @param slcSet slice set.
01175    * @param linePropList a set of statement.
01176    * @param removedStmtByEmptyB removed statements.
01177    * @param stmtList statement list.
01178    */
01179 private void removeEmptyTryFinally(Vector currentCfanns, BitSet slcSet, Set linePropList, Set removedStmtByEmptyB, StmtList stmtList, JimpleBody jimpleBody) {
01180     for (Enumeration e = currentCfanns.elements(); e.hasMoreElements();) {
01181         Annotation cfann = (Annotation) e.nextElement();
01182 
01183 
01184         if (cfann instanceof TryFinallyStmtAnnotation) {
01185 
01186             TryFinallyStmtAnnotation tryFinallyCFANN = (TryFinallyStmtAnnotation) cfann;
01187             Annotation tryBody = tryFinallyCFANN.getBlockAnnotation();
01188             Stmt bodyStmts[] = tryBody.getStatements();
01189 
01190             //to see if the sliceset includes any statements in bodyStms
01191 
01192             if (emptyBody(bodyStmts, slcSet, stmtList)) {
01193                 for (int i = 0; i < bodyStmts.length; i++) {
01194                     Stmt stmt = bodyStmts[i];
01195                     int stmtIndex = stmtList.indexOf(stmt);
01196                     if (linePropList.contains(stmt))
01197                         continue;
01198                     removedStmtByEmptyB.add(stmt);
01199                     if (slcSet.get(stmtIndex))
01200                         slcSet.clear(stmtIndex);
01201                 }
01202                 addCatchesToRemovedSet(removedStmtByEmptyB, tryFinallyCFANN.getCatchClauses(), stmtList, linePropList, slcSet);
01203             } else
01204                 //add exception handling into slice set
01205                 {
01206                 //System.out.println("add catch of try");
01207                 Vector catches = tryFinallyCFANN.getCatchClauses();
01208                 addCatchesToSliceSet(slcSet, catches, stmtList);
01209             }
01210 
01211             // the fianlly part of the try statement should be included in the slice set, whether the body of the try is empty or not
01212             bodyStmts = tryFinallyCFANN.getFinallyAnnotation().getStatements();
01213             for (int i = 0; i < bodyStmts.length; i++)
01214                 slcSet.set(stmtList.indexOf(bodyStmts[i]));
01215             bodyStmts = tryFinallyCFANN.getFinallyExceptionAnnotation().getStatements();
01216             for (int i = 0; i < bodyStmts.length; i++)
01217                 slcSet.set(stmtList.indexOf(bodyStmts[i]));
01218         }
01219     }
01220 }
01221 /**
01222  * Insert the method's description here.
01223  * Creation date: (00-12-20 13:56:57)
01224  * @param sootClass ca.mcgill.sable.soot.SootClass
01225  * @param sootField ca.mcgill.sable.soot.SootField
01226  */
01227 private void removeFieldInClinit(SootClass sootClass, SootField sootField) {
01228     if (!sootClass.declaresMethod("<clinit>"))
01229         return;
01230     SootMethod sootMethod = sootClass.getMethod("<clinit>");
01231     JimpleBody jimpleBody = (JimpleBody) sootMethod.getBody(Jimple.v());
01232     StmtList stmtList = jimpleBody.getStmtList();
01233     Set removableStmts = new ArraySet();
01234     for (Iterator stmtIt = stmtList.iterator(); stmtIt.hasNext();) {
01235         Stmt stmt = (Stmt) stmtIt.next();
01236         if (stmt instanceof AssignStmt) {
01237             Value leftValue = ((AssignStmt) stmt).getLeftOp();
01238             if (leftValue instanceof FieldRef) {
01239                 SootField leftField = ((FieldRef) leftValue).getField();
01240                 if (leftField.equals(sootField))
01241                     removableStmts.add(stmt);
01242             }
01243         }
01244     }
01245     if (removableStmts.isEmpty())
01246         return;
01247     Annotation annForSm = cfanns.getAnnotation(sootClass, sootMethod);
01248     for (Iterator stmtIt = removableStmts.iterator(); stmtIt.hasNext();) {
01249         Stmt stmt = (Stmt) stmtIt.next();
01250         stmtList.remove(stmt);
01251         try {
01252             annForSm.removeStmtByMark(stmt);
01253         } catch (Exception e) {
01254         }
01255     }
01256 }
01257 // remove irrelevant fields in terms of relevant fields
01258 /**
01259    * Remove irrelevant fileds for a class.
01260    * <p>
01261    * @param classInfo query class.
01262    */
01263 private void removeIrrelevantFields(ClassInfo classInfo) {
01264     SootClass sootClass = classInfo.sootClass;
01265     List fields = sootClass.getFields();
01266     Set relevantSootFields = fieldRefToField(relevantFields);
01267     removableSootFields = new ArraySet();
01268     for (Iterator fieldsIt = fields.iterator(); fieldsIt.hasNext();) {
01269         SootField sootField = (SootField) fieldsIt.next();
01270         if (!relevantSootFields.contains(sootField)) {
01271             removableSootFields.add(sootField);
01272             removeFieldInClinit(sootClass, sootField);
01273         }
01274     }
01275 }
01276 /**
01277    * Construct residual classes.
01278    */
01279 public void resClassCons() {
01280     initializeMdInfoAndAnnotation();
01281     Map removableMdMap = new HashMap();
01282     for (Iterator classIt = classList.iterator(); classIt.hasNext();) {
01283         ClassInfo classInfo = (ClassInfo) classIt.next();
01284         if (Slicer.unreachableClasses.contains(classInfo.sootClass)) {
01285             removableSootClasses.add(classInfo.sootClass);
01286             continue;
01287         }
01288         if (Slicer.isObjectClass(classInfo.sootClass))
01289             continue;
01290         List mdList = classInfo.methodsInfoList;
01291         MethodInfo initMethodInfo = null;
01292         List removableMethods = new ArrayList();
01293         boolean containsStartMethod = false;
01294         for (Iterator mdIt = mdList.iterator(); mdIt.hasNext();) {
01295             MethodInfo mdInfo = (MethodInfo) mdIt.next();
01296             /*
01297             if (mdInfo.sootClass.getName().equals("Thread") && mdInfo.sootMethod.getName().equals("stopChargingCPUTime")) {
01298             System.out.println("for debug");
01299             }
01300             */
01301             if (mdInfo.sliceSet == null) {
01302                 if (mdInfo.sootMethod.getName().equals("<init>")) {
01303                     SootMethod sm = mdInfo.sootMethod;
01304                     if (sm.getParameterCount() == 0) {
01305                         initMethodInfo = mdInfo;
01306                     }
01307                     removableMethods.add(mdInfo);
01308                 } else
01309                     if (Modifier.isAbstract(mdInfo.sootMethod.getModifiers())) {
01310                     }
01311                     // this else is for the abpstest examples, and will be 
01312                     // eliminated finally
01313                     else
01314                         if (mdInfo.sootMethod.getName().equals("start")) {
01315                             containsStartMethod = true;
01316                         } else
01317                             removableMethods.add(mdInfo);
01318             } else {
01319                 boolean modified = modifyMethod(mdInfo);
01320                 if (modified)
01321                     modifiedSootMethodToRemovableLocals.put(mdInfo.sootMethod, new ArraySet());
01322             }
01323         }
01324         if (removableMethods.size() != 0) {
01325             if (removableMethods.size() == mdList.size() || (removableMethods.size() == (mdList.size() - 1) && containsStartMethod)) {
01326                 removableSootClasses.add(classInfo.sootClass);
01327             } else {
01328                 if (initMethodInfo != null) {
01329                     Set varsOfInit = getAllVarsOf(initMethodInfo);
01330                     filterOutFields(varsOfInit);
01331                     removableMethods.remove(initMethodInfo);
01332                 }
01333                 Set implementingMethods = new ArraySet();
01334                 for (Iterator mdInfoIt = removableMethods.iterator(); mdInfoIt.hasNext();) {
01335                     MethodInfo rmvableMdInfo = (MethodInfo) mdInfoIt.next();
01336                     SootMethod rmvableMd = rmvableMdInfo.sootMethod;
01337                     if (isImplementingOneAbstractMd(rmvableMd)) {
01338                         implementingMethods.add(rmvableMdInfo);
01339                         Annotation annForSm = cfanns.getAnnotation(rmvableMd.getDeclaringClass(), rmvableMd);
01340                         makeMethodEmpty(rmvableMdInfo, annForSm);
01341                         modifiedSootMethodToRemovableLocals.put(rmvableMdInfo.sootMethod, new ArraySet());
01342                     }
01343                 }
01344                 if (!implementingMethods.isEmpty())
01345                     removableMethods.removeAll(implementingMethods);
01346             }
01347         }
01348 
01349         //put removable methods list into the map
01350         removableMdMap.put(classInfo.sootClass, removableMethods);
01351     }
01352 
01353     //check relevantField and removableClassses to see if there
01354     //are any relevant fields is in one class (CLS) which is in 
01355     //removableClasses, where all methods in CLS are going to be
01356     //removed, but the fields are relevant maybe for other class.
01357 
01358 
01359     relevantFDClass();
01360     relevantExceptionClasses();
01361     rmMethodAndClass(removableMdMap);
01362     
01363     rmIrrelevantFds();
01364     rmIrrelevantParasForMd();
01365     rmIrrelevantParasForInvoke();
01366     rmUnusedLocals();
01367     relevantInterfaceAndSuperClasses();
01368 }
01369 /**
01370    * Construct residual parameter for a given method.
01371    * <p>
01372    * @param mdInfo query method.
01373    */
01374 private void residualParameters(MethodInfo mdInfo) {
01375     SootMethod sootMethod = mdInfo.sootMethod;
01376     StmtList stmtList = mdInfo.originalStmtList; //should use the original stmtList
01377     Annotation annForSm = cfanns.getAnnotation(mdInfo.sootClass, mdInfo.sootMethod);
01378     StmtList slicedStmtList = mdInfo.stmtList;
01379     List parameterTypes = sootMethod.getParameterTypes();
01380     Local paraLocals[] = mdInfo.indexMaps.getParaLocalSet();
01381     Stmt paraIdStmt[] = mdInfo.indexMaps.getParaIdentityStmts();
01382     BitSet sliceSet = mdInfo.sliceSet;
01383     Map relevantVars = mdInfo.sCriterion.relVarMap();
01384     Set relLocs = PostProcess.getAllVarsOf(stmtList, sliceSet);
01385     Set removableParas = new ArraySet();
01386     LinkedList keepedParaOriginalIndex = new LinkedList();
01387     for (int i = 0; i < paraLocals.length; i++) {
01388         Local paraLocal = paraLocals[i];
01389         if (!relLocs.contains(paraLocal)) {
01390             removableParas.add(parameterTypes.get(i));
01391         } else {
01392             keepedParaOriginalIndex.addLast(new Integer(i));
01393         }
01394     }
01395     for (Iterator i = removableParas.iterator(); i.hasNext();) {
01396         Object type = (Object) i.next();
01397     }
01398     if (removableParas.size() > 0) {
01399         parameterModifiedSootMethods.add(sootMethod);
01400         //change parameter index
01401         for (int i = 0; i < keepedParaOriginalIndex.size(); i++) {
01402             int originalParaIndex = ((Integer) keepedParaOriginalIndex.get(i)).intValue();
01403             if (originalParaIndex == i)
01404                 continue;
01405             Stmt stmtForThisPara = paraIdStmt[originalParaIndex];
01406             if (!(stmtForThisPara instanceof IdentityStmt))
01407                 throw new NonIdParaAssignmentException("parameter assignment should be identity statement");
01408             IdentityStmt idStmtForThisPara = (IdentityStmt) stmtForThisPara;
01409             ParameterRef newParameterRef = Jimple.v().newParameterRef(sootMethod, i);
01410             IdentityStmt newIdStmt = Jimple.v().newIdentityStmt(idStmtForThisPara.getLeftOp(), newParameterRef);
01411 
01412             //change original id stmt to new id stmt
01413             int indexOfIdStmt = slicedStmtList.indexOf(stmtForThisPara);
01414             try {
01415                 annForSm.replaceStmtByMark(idStmtForThisPara, newIdStmt);
01416                 modifiedSootMethodToRemovableLocals.put(mdInfo.sootMethod, new ArraySet());
01417             } catch (Exception e) {
01418             }
01419         }
01420     }
01421 }
01422 /**
01423    * Remove irrelevant fields in every classes.
01424    */
01425 private void rmIrrelevantFds() {
01426     //remove irrelevant fields
01427     for (Iterator classIt = classList.iterator(); classIt.hasNext();) {
01428         ClassInfo classInfo = (ClassInfo) classIt.next();
01429         if (//keepingClasses.contains(classInfo) ||
01430             Slicer.isObjectClass(classInfo.sootClass) || removableSootClasses.contains(classInfo.sootClass)) {
01431         } else
01432             removeIrrelevantFields(classInfo);
01433     }
01434 }
01435 /**
01436    * Remove irrelevant parameters for invoke expression.
01437    */
01438 private void rmIrrelevantParasForInvoke() {
01439     //remove irrelevant actual parameters for every invokeExpr 
01440     for (Iterator classIt = classList.iterator(); classIt.hasNext();) {
01441         ClassInfo classInfo = (ClassInfo) classIt.next();
01442         if (Slicer.isObjectClass(classInfo.sootClass) || removableSootClasses.contains(classInfo.sootClass))
01443             continue;
01444         for (Iterator mdIt = classInfo.methodsInfoList.iterator(); mdIt.hasNext();) {
01445             MethodInfo mdInfo = (MethodInfo) mdIt.next();
01446             if (mdInfo.sliceSet != null)
01447                 rmParasOfInvokeExpr(mdInfo);
01448         }
01449     }
01450 }
01451 /**
01452    * Remove irrelevant parameters for method declaration.
01453    */
01454 private void rmIrrelevantParasForMd() {
01455     //remove irrelevant parameters for method declaration
01456     Iterator classIt = classList.iterator();
01457     while (classIt.hasNext()) {
01458         ClassInfo classInfo = (ClassInfo) classIt.next();
01459         if (Slicer.isObjectClass(classInfo.sootClass) || removableSootClasses.contains(classInfo.sootClass))
01460             continue;
01461         List mdList = classInfo.methodsInfoList;
01462         Iterator mdIt = mdList.iterator();
01463         while (mdIt.hasNext()) {
01464             MethodInfo mdInfo = (MethodInfo) mdIt.next();
01465             if (mdInfo.sliceSet == null)
01466                 continue;
01467             if (mdInfo.sootMethod.getName().equals("main")) {
01468             } else
01469                 residualParameters(mdInfo);
01470         }
01471     }
01472 }
01473 /**
01474    * Remove methods and classes in terms of given removable method map.
01475    * <p>
01476    * @param removableMdMap a map from {@link SootClass SootClass} to 
01477    * a {@link List List} of {@link SootMethod SootMethod}.
01478    */
01479 private void rmMethodAndClass(Map removableMdMap) {
01480     //remove method from sootClass
01481 
01482     for (Iterator classIt = removableMdMap.keySet().iterator(); classIt.hasNext();) {
01483         SootClass sootClass = (SootClass) classIt.next();
01484         List removableMethods = (List) removableMdMap.get(sootClass);
01485         for (int i = 0; i < removableMethods.size(); i++) {
01486             MethodInfo rmvableMdInfo = (MethodInfo) removableMethods.get(i);
01487             removableSootMethods.add(rmvableMdInfo.sootMethod);
01488         }
01489         for (Iterator mdIt = sootClass.getMethods().iterator(); mdIt.hasNext();) {
01490             SootMethod md = (SootMethod) mdIt.next();
01491             if (!Slicer.reachableMethods.contains(md))
01492                 unreachableSootMethods.add(md);
01493         }
01494     }
01495 }
01496 /**
01497    * Remove irrelevant parameters of invoke expressions in a given method.
01498    * <p>
01499    * @param mdInfo query method.
01500    */
01501 private void rmParasOfInvokeExpr(MethodInfo mdInfo) {
01502     StmtList originalStmtList = mdInfo.originalStmtList; //should use the original stmtList
01503     StmtList stmtList = mdInfo.stmtList;
01504     Map callSiteMap = mdInfo.indexMaps.getCallSiteMap();
01505     Map callSiteIndexMap = SlicingMethod.callSiteIndex(callSiteMap);
01506     BitSet sliceSet = mdInfo.sliceSet;
01507     Annotation annForSm = cfanns.getAnnotation(mdInfo.sootClass, mdInfo.sootMethod);
01508     for (Iterator siteIt = callSiteIndexMap.keySet().iterator(); siteIt.hasNext();) {
01509         Stmt callStmt = (Stmt) siteIt.next();
01510         if (!sliceSet.get(originalStmtList.indexOf(callStmt)))
01511             continue;
01512         if (callStmt instanceof InvokeStmt) {
01513             InvokeStmt invokeStmt = (InvokeStmt) callStmt;
01514             InvokeExpr invokeExpr = (InvokeExpr) invokeStmt.getInvokeExpr();
01515             boolean paraChanged = buildNewInvokeExpr(invokeExpr);
01516             if (paraChanged) {
01517                 try {
01518                     annForSm.replaceStmtByMark(invokeStmt, invokeStmt);
01519                     modifiedSootMethodToRemovableLocals.put(mdInfo.sootMethod, new ArraySet());
01520                 } catch (Exception e) {
01521                 }
01522             }
01523         } else
01524             if (callStmt instanceof AssignStmt) {
01525                 AssignStmt assignCallStmt = (AssignStmt) callStmt;
01526                 Value rightOp = assignCallStmt.getRightOp();
01527                 if (rightOp instanceof InvokeExpr) {
01528                     boolean paraChanged = buildNewInvokeExpr((InvokeExpr) rightOp);
01529                     SootMethod invokedMd = ((InvokeExpr) rightOp).getMethod();
01530                     if (changeReturnTypeToVoidMds.contains(invokedMd)) {
01531                         int indexOfCallStmt = stmtList.indexOf(callStmt);
01532                         //InvokeStmt newInvokeStmt = Jimple.v().newInvokeStmt(newInvokeExpr);
01533                         try {
01534                             annForSm.replaceStmtByMark(callStmt, callStmt);
01535                             modifiedSootMethodToRemovableLocals.put(mdInfo.sootMethod, new ArraySet());
01536                         } catch (Exception e) {
01537                         }
01538                     } else {
01539                         if (paraChanged) {
01540                             try {
01541                                 annForSm.replaceStmtByMark(callStmt, callStmt);
01542                                 modifiedSootMethodToRemovableLocals.put(mdInfo.sootMethod, new ArraySet());
01543                             } catch (Exception e) {
01544                             }
01545                         }
01546                     }
01547                 } else {
01548                     System.out.println("rightOp is not invokeExpr");
01549                 }
01550             } else {
01551                 System.out.println("callStmt is not invokeStmt nor DefinitionStmt");
01552             }
01553     }
01554 }
01555 /**
01556    * Remove irrelevant parameters for invoke expression.
01557    */
01558 private void rmUnusedLocals() {
01559     //remove irrelevant actual parameters for every invokeExpr 
01560     for (Iterator classIt = classList.iterator(); classIt.hasNext();) {
01561         ClassInfo classInfo = (ClassInfo) classIt.next();
01562         if (Slicer.isObjectClass(classInfo.sootClass) || removableSootClasses.contains(classInfo.sootClass))
01563             continue;
01564         for (Iterator mdIt = classInfo.methodsInfoList.iterator(); mdIt.hasNext();) {
01565             MethodInfo mdInfo = (MethodInfo) mdIt.next();
01566             Set unusedLocals = getUnusedLocals(mdInfo);
01567             if (!unusedLocals.isEmpty())
01568                 modifiedSootMethodToRemovableLocals.put(mdInfo.sootMethod, unusedLocals);
01569         }
01570     }
01571 }
01572 }

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