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

Fields.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.pdgslicer.exceptions.*;
00041 /**
00042  * This class is for grouping use and definition of field references
00043  * in one method.
00044  */
00045 public class Fields {
00046   /**
00047    * A set of {@link DataBox DataBox} for static field reference.
00048    * One <code>DataBox</code> means a set of static field references
00049    * used or defined by a statement.
00050    */
00051     Set staticFields;
00052   /**
00053    * A set of {@link DataBox DataBox} for instance field references 
00054    * which are declared in current class.
00055    */
00056     Set instanceFields; //class fields -- public fields
00057   /** 
00058    * A set of {@link DataBox DataBox} for parameter field references.
00059    * <p>
00060    * @see IndexMaps#isParaField(InstanceFieldRef,Stmt).
00061    */
00062     Set paraFields;
00063   /**
00064    * A set of {@link DataBox DataBox} for other instance field references
00065    * which are declared in other class rather than current class.
00066    */   
00067     Set otherInsFds;
00068 
00069   /**
00070    * Initialize {@link #staticFields staticFields},
00071    * {@link #instanceFields instanceFields}, and 
00072    * {@link #paraFields paraFields} to <code>null</code>.
00073    */
00074   public Fields()
00075     {
00076       staticFields = null;
00077       instanceFields = null;
00078       paraFields = null;
00079     }
00080   /**
00081    * Get the index of parameter, if the base value of given instance
00082    * field reference <code>insFieldRef</code> is a parameter or a local
00083    * copy of a parameter.
00084    * <p>
00085    * @param insFieldRef query instance field reference.
00086    * @param paraLocals local variables for all parameters.
00087    * @param simpleLocalCopiesInCalledMd simple local copies graph for the method
00088    * where <code>insFieldRef</code> is used or defined.
00089    * @param interStmt the statement which use or define <code>insFieldRef</code>.
00090    * @return the index of the parameter which is base value of 
00091    * <code>insFieldRef</code>.
00092    * @throws BaseValueNonLocalException if the base value of <code>insFieldRef</code>
00093    * is not a local variable.
00094    * @throws NoParaFieldFoundException if can not find a parameter corresponding to
00095    * the base value of <code>insFieldRef</code>.
00096    */
00097 static int getParaIndex(InstanceFieldRef insFieldRef, Local[] paraLocals, SimpleLocalCopies simpleLocalCopiesInCalledMd, Stmt interStmt) {
00098     //determin the base using the parameter binding function
00099     Value base = insFieldRef.getBase();
00100     if (!(base instanceof Local))
00101         throw new BaseValueNonLocalException("parameter instance field reference should be local variable");
00102     Local paraLocal = (Local) base;
00103     int paraIndex = -1;
00104 
00105     //determine the index of paraLocal
00106     for (int j = 0; j < paraLocals.length; j++) {
00107         if (paraLocal.equals(paraLocals[j])) {
00108             paraIndex = j;
00109             break;
00110         } else
00111             if (simpleLocalCopiesInCalledMd.isLocalCopyOfBefore(paraLocal, paraLocals[j], interStmt)) {
00112                 paraIndex = j;
00113                 break;
00114             }
00115     }
00116     if (paraIndex == -1)
00117         throw new NoParaFieldFoundException("Parameter instance field reference should be found in the paraLocals array");
00118     return paraIndex;
00119 }
00120 /**
00121  * Insert the method's description here.
00122  * Creation date: (6/18/2001 11:36:41 AM)
00123  * @return boolean
00124  * @param value ca.mcgill.sable.soot.jimple.Value
00125  */
00126 static boolean isThisRef(SootMethod enclosingMethod, Value base, Stmt thisRefStmt) {
00127     if (thisRefStmt==null) return false;
00128     Set refSet = Slicer.BOFA_Analysis.referenceValueSet(base, enclosingMethod);
00129     if (refSet.contains(thisRefStmt))
00130         return true;
00131     return false;
00132 }
00133 /**
00134    * Merge fields information of called method into current fields information
00135    * of current method in terms of one method call.
00136    * <p>
00137    * @param fields all fields information for called method.
00138    * @param site one call site in current method body.
00139    * @param methodInfo method information of current method.
00140    * @param calledMdInfo method information of called method.
00141    */
00142 public void merge(Fields fields, CallSite site, MethodInfo methodInfo, MethodInfo calledMdInfo) {
00143     //methodInfo for calling method, not for called method 
00144 
00145     Set newStaticFields = new ArraySet();
00146     Set staticFdInCalledMd = fields.staticFields;
00147     for (Iterator i = staticFdInCalledMd.iterator(); i.hasNext();) {
00148         DataBox dbx = (DataBox) i.next();
00149         Set staticFdSet = dbx.getInterferVars();
00150         DataBox newdbx = new DataBox(site.callStmt, staticFdSet);
00151         if (!this.staticFields.contains(newdbx))
00152             newStaticFields.add(newdbx);
00153     }
00154     this.staticFields.addAll(newStaticFields);
00155     Set newInstanceFields = new ArraySet();
00156     newInstanceFields.addAll(this.instanceFields);
00157 
00158     //constructing newLocalFields
00159     //including that instanceFields of the other method with the name
00160     //changed to call object
00161     //need to know the base of call method here
00162 
00163     Value base = null;
00164     NonStaticInvokeExpr nonStaticInvokeExpr = null;
00165     boolean nonStaticInvoke = false;
00166     InvokeExpr invokeExpr = site.invokeExpr;
00167     if (invokeExpr instanceof NonStaticInvokeExpr) {
00168         nonStaticInvokeExpr = (NonStaticInvokeExpr) invokeExpr;
00169         base = nonStaticInvokeExpr.getBase();
00170         nonStaticInvoke = true;
00171     } else {
00172         //System.out.println("We don't process static invoke at this moment");
00173     }
00174     Set insFdAtCallSite = new ArraySet();
00175     if (nonStaticInvoke) {
00176         //decide if base is the local copy of this
00177 
00178 
00179         Set insFdInCallee = fields.instanceFields;
00180         for (Iterator i = insFdInCallee.iterator(); i.hasNext();) {
00181             DataBox insFdBox = (DataBox) i.next();
00182             Set insFields = insFdBox.getInterferVars();
00183             insFdAtCallSite.addAll(BuildPDG.cloneAndChangeBase(insFields, base));
00184         }
00185     }
00186     this.instanceFields = newInstanceFields;
00187     Set newParaFields = new ArraySet();
00188     newParaFields.addAll(this.paraFields);
00189     Set paraFieldsAtThisSite = new ArraySet();
00190     Set otherInsFdAtThisSite = new ArraySet();
00191     Set newOtherInsFd = new ArraySet();
00192     newOtherInsFd.addAll(this.otherInsFds);
00193 
00194     //filter out parameter fields at this call site, from instance
00195     //field at this site
00196     if (insFdAtCallSite != null) {
00197         for (Iterator i = insFdAtCallSite.iterator(); i.hasNext();) {
00198             InstanceFieldRef insFd = (InstanceFieldRef) i.next();
00199             if (methodInfo.indexMaps.isParaField(insFd, site.callStmt))
00200                 paraFieldsAtThisSite.add(insFd);
00201         }
00202     }
00203     Set paraFieldsAfterChangeBase = parametersLocalize(calledMdInfo, fields, invokeExpr);
00204 
00205     //determine if paraFieldsAfterChangeBase are paraFields in current md
00206 
00207     for (Iterator jj = paraFieldsAfterChangeBase.iterator(); jj.hasNext();) {
00208         InstanceFieldRef paraFieldCalled = (InstanceFieldRef) jj.next();
00209         if (methodInfo.indexMaps.isParaField(paraFieldCalled, site.callStmt))
00210             paraFieldsAtThisSite.add(paraFieldCalled);
00211         else
00212             if (Fields.isThisRef(methodInfo.sootMethod, paraFieldCalled.getBase(), methodInfo.indexMaps.getThisRefStmt()))
00213                 insFdAtCallSite.add(paraFieldCalled);
00214             else
00215                 otherInsFdAtThisSite.add(paraFieldCalled);
00216     }
00217     if (paraFieldsAtThisSite.size() != 0) {
00218         DataBox newdbx = new DataBox(site.callStmt, paraFieldsAtThisSite);
00219         newParaFields.add(newdbx);
00220     }
00221     this.paraFields = newParaFields;
00222     if (!insFdAtCallSite.isEmpty()) {
00223         DataBox newdbx = new DataBox(site.callStmt, insFdAtCallSite);
00224         newInstanceFields.add(newdbx);
00225     }
00226     this.instanceFields = newInstanceFields;
00227     if (!otherInsFdAtThisSite.isEmpty()) {
00228         DataBox newdbx = new DataBox(site.callStmt, otherInsFdAtThisSite);
00229         newOtherInsFd.add(newdbx);
00230     }
00231     this.otherInsFds = newOtherInsFd;
00232 }
00233   public boolean noFieldsInMethod()
00234     {
00235       return (staticFields.size()==0 && instanceFields.size()==0 &&
00236           paraFields.size() == 0 );
00237       //&& localFields.size() == 0);
00238     }
00239   public boolean noInstanceFieldsInMethod()
00240     {
00241       return instanceFields.size()==0;
00242     }
00243   public boolean noParaFields()
00244     {
00245       return paraFields.size() == 0;
00246     }
00247   public boolean noStaticFieldsInMethod()
00248     {
00249       return staticFields.size()==0;
00250     }
00251   /** 
00252    * Implement binding function of parameters.
00253    * <br>For example, given an invoke expression like
00254    * <code> obj.calledMethod(actualArg1, acutalArg2);</code>,
00255    * and the method <code>calledMethod(formalArg1, formalArg2){...}</code>,
00256    * there are some parameter fields in the body of <code>calledMethod</code> such like
00257    * <code>formalArg1.fd1, formalArg2.fd2</code> etc. To count (merge) those fields into
00258    * those of current method, it is necessary to change those <code>formalArg</code>
00259    * base value into <code>actualArg</code> value.
00260    * <p>
00261    * @param calledMdInfo method information of called method.
00262    * @param fields fields information of called method
00263    * @param invokeExpr invoke (called method) expression in current method.
00264    * @return a {@link Set Set} of {@link InstanceFieldRef InstanceFieldRef} which is 
00265    * changed base value from <code>formalArg</code> to <code>actualArg</code>.
00266    */
00267 static Set parametersLocalize(MethodInfo calledMdInfo, Fields fields, InvokeExpr invokeExpr) {
00268     SimpleLocalCopies simpleLocalCopiesInCalledMd = new SimpleLocalCopies((CompleteStmtGraph) calledMdInfo.indexMaps.getStmtGraph());
00269     Local paraLocals[] = calledMdInfo.indexMaps.getParaLocalSet();
00270     Set paraFieldsInCalledMd = fields.paraFields;
00271     Set paraFieldsAfterChangeBase = new ArraySet();
00272     for (Iterator i = paraFieldsInCalledMd.iterator(); i.hasNext();) {
00273         DataBox insFieldRefBox = (DataBox) i.next();
00274         Set insFieldRefs = insFieldRefBox.getInterferVars();
00275         for (Iterator k = insFieldRefs.iterator(); k.hasNext();) {
00276             Object element = (Object) k.next();
00277             if (element instanceof Local)
00278                 continue;
00279             InstanceFieldRef insFieldRef = (InstanceFieldRef) element;
00280 
00281             //parameter index in caller method
00282             int paraIndex = getParaIndex(insFieldRef, paraLocals, simpleLocalCopiesInCalledMd, insFieldRefBox.getInterferStmt());
00283             InstanceFieldRef newInsFieldRef = Jimple.v().newInstanceFieldRef(invokeExpr.getArg(paraIndex), insFieldRef.getField());
00284             paraFieldsAfterChangeBase.add(newInsFieldRef);
00285         }
00286     }
00287     return paraFieldsAfterChangeBase;
00288 }
00289   public String toString()
00290     {
00291       return "\nStaticFields: " + staticFields + "\n" + 
00292     "instanceFields: " + instanceFields + "\n" +
00293     "paraFields: " + paraFields;
00294     }
00295 }

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