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

MethodCallAnalysis.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.soot.jimple.*;
00038 import ca.mcgill.sable.soot.*;
00039 import ca.mcgill.sable.util.*;
00040 import edu.ksu.cis.bandera.annotation.*;
00041 import java.util.BitSet;
00042 /**
00043  * This class is for analysis of method calls including:
00044  * <br> (1) Build reverse direction call graph (given a method, we can know
00045  * which methods call that) based on call site map:
00046  * {@link #buildCallMeSiteMap() buildCallMeSiteMap()}.
00047  * <br> (2) Build PDG for each method:
00048  * {@link #buildMethodPDG(AnnotationManager) buildMethodPDG()}.
00049  * <br> (3) Collect and calculate MOD/REF information for each method:
00050  * {@link #MODREFAnalysis() MODREFAnalysis()}.
00051  */
00052 public class MethodCallAnalysis {
00053     static Set directReadyForWaitCallSites;
00054 public MethodCallAnalysis() {
00055   //directReadyForWaitCallSites = new ArraySet();
00056     Map callMeSiteMap = buildCallMeSiteMap();
00057     distributeToMdInfo(callMeSiteMap);
00058 }
00059 //to determine that all the called method has been calculated
00060   /**
00061    * See if all call sites in given method have been processed
00062    * according to a set of sootMethods that have been processed.
00063    * <p>
00064    * @sm sootMethod to be analysed.
00065    * @callSiteMap call site map from {@link CallSite CallSite}
00066    * to {@link SootMethod SootMethod}.
00067    * @param caledMdSet a set of {@link SootMethod SootMethod} which
00068    * has been processed.
00069    * @return <code>true</code> if all call sites have been processed, 
00070    * <code>false</code> otherwise.
00071    */
00072 static  boolean allCalculated(SootMethod sm, Map callSiteMap, Set caledMdSet) {
00073     for (Iterator siteIt = callSiteMap.keySet().iterator(); siteIt.hasNext();) {
00074         CallSite site = (CallSite) siteIt.next();
00075         SootMethod calledMd = (SootMethod) callSiteMap.get(site);
00076         // the condition (calledMd==sm) is for the recursive call
00077         if (caledMdSet.contains(calledMd) || calledMd==sm)
00078             continue;
00079         else if (Slicer.sootMethodInfoMap.get(calledMd) == null)
00080           continue;
00081         
00082         else
00083             return false;
00084     }
00085     return true;
00086 }
00087 /**
00088    * Update the local assignment map {@link IndexMaps#locAssIndex locAssIndex}
00089    * in terms of MOD information in given method information.
00090    * <p>
00091    * @param mdInfo method to be analysed.
00092    */
00093 private void assignmentByMdCall(MethodInfo mdInfo)
00094 //attach the locAssMap
00095 {
00096     StmtList stmtList = mdInfo.originalStmtList;
00097     IndexMaps indexMaps = mdInfo.indexMaps;
00098     Map localAssMap = indexMaps.localAssMap();
00099 
00100     //assignment for static and class global instance field reference
00101     Fields defFields = mdInfo.MOD;
00102     for (Iterator i = defFields.staticFields.iterator(); i.hasNext();) {
00103         DataBox dbx = (DataBox) i.next();
00104         Stmt defStmt = dbx.getInterferStmt();
00105         for (Iterator j = dbx.getInterferVars().iterator(); j.hasNext();) {
00106             Value stcField = (Value) j.next();
00107             BitSet defSet = new BitSet(stmtList.size());
00108             defSet.set(stmtList.indexOf(defStmt));
00109             if (localAssMap.containsKey(stcField))
00110                 defSet.or((BitSet) localAssMap.get(stcField));
00111             localAssMap.put(stcField, defSet);
00112         }
00113     }
00114     for (Iterator i = defFields.instanceFields.iterator(); i.hasNext();) {
00115         DataBox dbx = (DataBox) i.next();
00116         Stmt defStmt = dbx.getInterferStmt();
00117         for (Iterator j = dbx.getInterferVars().iterator(); j.hasNext();) {
00118             InstanceFieldRef insField = (InstanceFieldRef) j.next();
00119             BitSet defSet = new BitSet(stmtList.size());
00120             defSet.set(stmtList.indexOf(defStmt));
00121             if (localAssMap.containsKey(insField))
00122                 defSet.or((BitSet) localAssMap.get(insField));
00123             localAssMap.put(insField, defSet);
00124         }
00125     }
00126 
00127 
00128     //assignment for parameter field 
00129     //and assignment for instance fields definition in called md
00130     Map callSiteMap = mdInfo.indexMaps.getCallSiteMap();
00131     for (Iterator siteIt = callSiteMap.keySet().iterator(); siteIt.hasNext();) {
00132         CallSite site = (CallSite) siteIt.next();
00133         InvokeExpr invokeExpr = site.invokeExpr;
00134         SootMethod calledMd = (SootMethod) callSiteMap.get(site);
00135         MethodInfo calledMdInfo = (MethodInfo) Slicer.sootMethodInfoMap.get(calledMd);
00136         if (calledMdInfo == null)
00137             continue;
00138         defFields = calledMdInfo.MOD;
00139         Stmt callSiteStmt = site.callStmt;
00140         Set defParas = Fields.parametersLocalize(calledMdInfo, defFields, invokeExpr);
00141         Set defInstanceField = new ArraySet();
00142         if (invokeExpr instanceof NonStaticInvokeExpr) {
00143             NonStaticInvokeExpr nsie = (NonStaticInvokeExpr) invokeExpr;
00144 
00145             //modFields: all instanceFieldRef set
00146             Set modFields = SlicingMethod.allMODREFFields(defFields.instanceFields, new ArraySet());
00147             defInstanceField = BuildPDG.cloneAndChangeBase(modFields, nsie.getBase());
00148         }
00149         Set defFieldsAtCallSite = new ArraySet();
00150         defFieldsAtCallSite.addAll(defParas);
00151         defFieldsAtCallSite.addAll(defInstanceField);
00152         for (Iterator i = defFieldsAtCallSite.iterator(); i.hasNext();) {
00153             InstanceFieldRef field = (InstanceFieldRef) i.next();
00154             BitSet defSet = new BitSet(stmtList.size());
00155             defSet.set(stmtList.indexOf(callSiteStmt));
00156             if (localAssMap.containsKey(field))
00157                 defSet.or((BitSet) localAssMap.get(field));
00158             localAssMap.put(field, defSet);
00159         }
00160     }
00161 }
00162   /**
00163    * Build callme site map from call site map which is from 
00164    * {@link CallSite CallSite} to {@link SootMethod SootMethod}.
00165    * <p>
00166    * @return a callme site map which is from {@link SootMethod SootMethod}
00167    * to a {@link Set Set} of {@link CallSite CallSite}. The map means that
00168    * the sootMethod is called by a set of call sites.
00169    */
00170 private Map buildCallMeSiteMap() {
00171     Map callMeSiteMap = new HashMap();
00172     for (Iterator mdIt = Slicer.sootMethodInfoMap.keySet().iterator(); mdIt.hasNext();) {
00173         SootMethod sootMethod = (SootMethod) mdIt.next();
00174         MethodInfo mdInfo = (MethodInfo) Slicer.sootMethodInfoMap.get(sootMethod);
00175         if (mdInfo == null) continue;
00176         Map callSiteMap = mdInfo.indexMaps.getCallSiteMap();
00177         for (Iterator siteIt = callSiteMap.keySet().iterator(); siteIt.hasNext();) {
00178             CallSite site = (CallSite) siteIt.next();
00179             SootMethod calledMd = (SootMethod) callSiteMap.get(site);
00180             Set callMeSet = new ArraySet();
00181             callMeSet.add(site);
00182             if (callMeSiteMap.containsKey(calledMd)) {
00183                 Set prevCallMeSet = (Set) callMeSiteMap.get(calledMd);
00184                 callMeSet.addAll(prevCallMeSet);
00185             }
00186             callMeSiteMap.put(calledMd, callMeSet);
00187         }
00188     }
00189     return callMeSiteMap;
00190 }
00191   /**
00192    * Build PDG for each method including:
00193    * <br> (1) {@link #assignmentByMdCall(MethodInfo) assignmentByMdCall()}.
00194    * <br> (2) {@link BuildPDG#BuildPDG(MethodInfo,AnnotationManager)
00195    * new BuildPDG()}.
00196    * <br> (3) {@link LockAnalysis@LockAnalysis(MethodInfo,AnnotationManager)
00197    * new LockAnalysis()}.
00198    * <br> (4) {@link #collectPossibleReadyDependCallSite(MethodInfo)
00199    * collectPossibleReadyDependCallSite()}.
00200    * <p>
00201    * @param cfanns annotation manager.
00202    */
00203 void buildMethodPDG(AnnotationManager cfanns)
00204 //including lockAnalysis()
00205 // also including parameter fields assignment due to method call
00206 {
00207     for (Iterator mdIt = Slicer.sootMethodInfoMap.keySet().iterator(); mdIt.hasNext();) {
00208         SootMethod sootMethod = (SootMethod) mdIt.next();
00209         MethodInfo mdInfo = (MethodInfo) Slicer.sootMethodInfoMap.get(sootMethod);
00210         if (mdInfo == null) continue;
00211         assignmentByMdCall(mdInfo); //attach the locAssMap
00212 
00213         BuildPDG methodPDG = new BuildPDG(mdInfo, cfanns);
00214         mdInfo.methodPDG = methodPDG;
00215         LockAnalysis lockAnalysis = new LockAnalysis(mdInfo, cfanns);
00216         collectPossibleReadyDependCallSite(mdInfo);
00217     }
00218 }
00219   /**
00220    * Collect all possible ready dependent call sites from given method:
00221    * A set of {@link CallSite CallSite} such that
00222    * inside the called method body there may contain
00223    * some ready dependence.
00224    * <br> Update the field {@link MethodInfo#possibleReadyDependCallSite
00225    * possibleReadyDependCallSite}.
00226    * <p>
00227    * @param mdInfo method to be analysed.
00228    */
00229 private void collectPossibleReadyDependCallSite(MethodInfo mdInfo) {
00230     LockAnalysis lockAnalysis = mdInfo.methodPDG.getLockAnalysis();
00231     if (lockAnalysis == null)
00232         return;
00233     List waitStmtList = lockAnalysis.getWaitStmtList();
00234     if (waitStmtList.size() == 0)
00235         return;
00236     Set whoCallMe = mdInfo.whoCallMe;
00237     if ((whoCallMe == null) || (whoCallMe.size() == 0))
00238         return;
00239     List workSet = new ArrayList();
00240     Set visitedCallSite = new ArraySet();
00241     //this is for the previous version
00242     workSet.addAll(whoCallMe);
00243     while (workSet.size() != 0) {
00244         CallSite callSite = (CallSite) workSet.get(0);
00245         workSet.remove(callSite);
00246         if (visitedCallSite.contains(callSite))
00247             continue;
00248         visitedCallSite.add(callSite);
00249         MethodInfo callerMdInfo = (MethodInfo) Slicer.sootMethodInfoMap.get(callSite.callerSootMethod);
00250         if (callerMdInfo != null){
00251         callerMdInfo.possibleReadyDependCallSite.add(callSite);
00252         }
00253         /*
00254         Set callerWhoCallMe = callerMdInfo.whoCallMe;
00255         if ((callerWhoCallMe == null) || (callerWhoCallMe.size() == 0)) {
00256         } else
00257             workSet.addAll(callerWhoCallMe);
00258         */
00259     }
00260     //this is for current version
00261     for (Iterator siteIt = mdInfo.whoCallMe.iterator(); siteIt.hasNext();) {
00262         CallSite callSite = (CallSite) siteIt.next();
00263         callSite.baseValue = getBaseValueFrom(callSite);
00264         if (callSite.baseValue != null)
00265             MethodCallAnalysis.directReadyForWaitCallSites.add(callSite);
00266     }
00267 }
00268 /**
00269  * Assign value of the field <code>whoCallMe</code> for each 
00270  * {@link MethodInfo MethodInfo} of each method in terms of given 
00271  * callme map.
00272  * <p>
00273  * @param callMeMap callme map which is from {@link SootMethod SootMethod}
00274  * to a {@link Set Set} of {@link CallSite CallSite}.
00275  */
00276 private void distributeToMdInfo(Map callMeMap) {
00277     for (Iterator calledIt = callMeMap.keySet().iterator(); calledIt.hasNext();) {
00278         SootMethod calledMethod = (SootMethod) calledIt.next();
00279         Set callSites = (Set) callMeMap.get(calledMethod);
00280         MethodInfo mdInfo = (MethodInfo) Slicer.sootMethodInfoMap.get(calledMethod);
00281         if (mdInfo != null){
00282         mdInfo.whoCallMe = callSites;
00283         }
00284     }
00285 }
00286 /**
00287  * Get the base value from a call site of a method call.
00288  * <p>
00289  * @return the base value of the method call.
00290  * @param callSite call site.
00291  */
00292 private Value getBaseValueFrom(CallSite callSite) {
00293     Value base = null;
00294     InvokeExpr invoke = callSite.invokeExpr;
00295     if (invoke instanceof NonStaticInvokeExpr)
00296         base = ((NonStaticInvokeExpr) invoke).getBase();
00297     if (base != null) {
00298         MethodInfo callerMdInfo = (MethodInfo) Slicer.sootMethodInfoMap.get(callSite.callerSootMethod);
00299         if (callerMdInfo != null)
00300             return base;
00301     }
00302     return base;
00303 }
00304 /**
00305  * Merge MOD/REF information of callee's into that of caller's.
00306  * <p>
00307  * @param mdInfo method information of caller.
00308  * @param calledMdInfo method information of callee.
00309  * @param site call site.
00310  */
00311 private void mergeFields(MethodInfo mdInfo, MethodInfo calledMdInfo, CallSite site) {
00312     Fields MOD = mdInfo.MOD;
00313     Fields REF = mdInfo.REF;
00314     Fields MODInCalled = calledMdInfo.MOD;
00315     Fields REFInCalled = calledMdInfo.REF;
00316     MOD.merge(MODInCalled, site, mdInfo, calledMdInfo);
00317     REF.merge(REFInCalled, site, mdInfo, calledMdInfo);
00318 }
00319 /**
00320  * Collect and calculate MOD/REF information for each method with
00321  * considering method calls inside a method body.
00322  * <br> Update {@link MethodInfo#MOD MOD} and {@link MethodInfo#REF}
00323  * of each {@link MethodInfo MethodInfo} of each method.
00324  */
00325 void MODREFAnalysis() {
00326     boolean hasNewCalculated = true;
00327     Set calculatedMdSet = new ArraySet();
00328     Map sootMethodInfoMap = Slicer.sootMethodInfoMap;
00329     //calculate the initial calculated method set
00330     for (Iterator mdIt = sootMethodInfoMap.keySet().iterator(); mdIt.hasNext();) {
00331         SootMethod sootMethod = (SootMethod) mdIt.next();
00332         MethodInfo mdInfo = (MethodInfo) sootMethodInfoMap.get(sootMethod);
00333         if (mdInfo== null) continue;
00334         Map callSiteMap = mdInfo.indexMaps.getCallSiteMap();
00335         if (callSiteMap.size() == 0)
00336             calculatedMdSet.add(sootMethod);
00337     }
00338     while (hasNewCalculated) {
00339         hasNewCalculated = false;
00340         for (Iterator mdIt = sootMethodInfoMap.keySet().iterator(); mdIt.hasNext();) {
00341             SootMethod currentMd = (SootMethod) mdIt.next();
00342             MethodInfo mdInfo = (MethodInfo) sootMethodInfoMap.get(currentMd);
00343             if (calculatedMdSet.contains(currentMd))
00344                 continue;
00345             else {
00346                 Map callSiteMap = mdInfo.indexMaps.getCallSiteMap();
00347                 if (allCalculated(mdInfo.sootMethod, callSiteMap, calculatedMdSet)) {
00348                     for (Iterator siteIt = callSiteMap.keySet().iterator(); siteIt.hasNext();) {
00349                         CallSite site = (CallSite) siteIt.next();
00350                         SootMethod calledMd = (SootMethod) callSiteMap.get(site);
00351                         MethodInfo calledMdInfo = (MethodInfo) sootMethodInfoMap.get(calledMd);
00352                         if (calledMdInfo != null)
00353                         mergeFields(mdInfo, calledMdInfo, site);
00354                     }
00355                     calculatedMdSet.add(currentMd);
00356                 } else{
00357                   //System.out.println("method : " + mdInfo.sootMethod);
00358                   hasNewCalculated = true;
00359                 }
00360         }
00361     }
00362 }
00363 }
00364 }

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