1 salcianu 1.1.2.1 // MetaAllCallers.java, created Sun Mar 12 22:30:17 2000 by salcianu
  2 cananian 1.1.2.6 // Copyright (C) 2000 Alexandru SALCIANU <salcianu@retezat.lcs.mit.edu>
  3 salcianu 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 salcianu 1.1.2.1 package harpoon.Analysis.MetaMethods;
  5 salcianu 1.1.2.1 
  6 salcianu 1.1.2.1 import java.util.Iterator;
  7 salcianu 1.1.2.1 import java.util.Set;
  8 salcianu 1.1.2.2 import java.util.HashSet;
  9 salcianu 1.1.2.1 import java.util.Map;
 10 salcianu 1.1.2.1 import java.util.HashMap;
 11 salcianu 1.1.2.2 import harpoon.Analysis.PointerAnalysis.PAWorkList;
 12 salcianu 1.1.2.1 
 13 salcianu 1.1.2.4 import harpoon.Util.DataStructs.Relation;
 14 salcianu 1.1.2.4 import harpoon.Util.DataStructs.LightRelation;
 15 salcianu 1.1.2.1 
 16 salcianu 1.1.2.5 import harpoon.Util.Util;
 17 salcianu 1.1.2.5 
 18 salcianu 1.1.2.1 /**
 19 salcianu 1.1.2.1  * <code>MetaAllCallers</code> is the dual of <code>MetaCallGraph</code>.
 20 salcianu 1.1.2.1  It computes the callers (<code>MetaMethod</code>s) of each meta-method from the
 21 salcianu 1.1.2.1  program. Note that the bulk of the computation is done in 
 22 salcianu 1.1.2.1  <code>MetaCallGraph</code>, this class just inverts the edges of a
 23 salcianu 1.1.2.1  precomputed graph.
 24 salcianu 1.1.2.1  * 
 25 cananian 1.1.2.6  * @author  Alexandru SALCIANU <salcianu@retezat.lcs.mit.edu>
 26 cananian 1.5      * @version $Id: MetaAllCallers.java,v 1.5 2004/02/08 03:19:57 cananian Exp $
 27 salcianu 1.1.2.1  */
 28 salcianu 1.1.2.3 public class MetaAllCallers implements java.io.Serializable {
 29 salcianu 1.1.2.1 
 30 salcianu 1.1.2.1     /** Creates a <code>MetaAllCallers</code>. Receives as parameter
 31 salcianu 1.1.2.1         the <code>MetaCallGraph</code> which computes the possible callees
 32 salcianu 1.1.2.1         of each meta-method. */
 33 salcianu 1.1.2.1     public MetaAllCallers(MetaCallGraph mcg) {
 34 salcianu 1.1.2.1         process(mcg);
 35 salcianu 1.1.2.1     }
 36 salcianu 1.1.2.1 
 37 salcianu 1.1.2.1     // Map<MetaMethod,MetaMethod[]>
 38 salcianu 1.1.2.1     private Map callers_cmpct = null;
 39 salcianu 1.1.2.1 
 40 salcianu 1.1.2.1     private final MetaMethod[] empty_array = new MetaMethod[0];
 41 salcianu 1.1.2.1 
 42 salcianu 1.1.2.1     /** Returns the callers of the meta method <code>mm_callee</code>.
 43 salcianu 1.1.2.1         The returned set is a set of <code>MetaMethod</code>s. */
 44 salcianu 1.1.2.1     public  MetaMethod[] getCallers(MetaMethod mm_callee){
 45 salcianu 1.1.2.1         MetaMethod[] retval = (MetaMethod[]) callers_cmpct.get(mm_callee);
 46 salcianu 1.1.2.1         if(retval == null)
 47 salcianu 1.1.2.1             retval = empty_array;
 48 salcianu 1.1.2.1         return retval;
 49 salcianu 1.1.2.2     }
 50 salcianu 1.1.2.2 
 51 salcianu 1.1.2.2     /** Returns the meta-methods that transitively call the meta-method
 52 salcianu 1.1.2.2         <code>mm_callee</code>. Simply the transitive closure of 
 53 salcianu 1.1.2.2         <code>getCallers</code>. */
 54 salcianu 1.1.2.2     public MetaMethod[] getTransCallers(MetaMethod mm_callee){
 55 salcianu 1.1.2.2         Set callers  = new HashSet();
 56 salcianu 1.1.2.2         PAWorkList W = new PAWorkList();
 57 salcianu 1.1.2.2         W.add(mm_callee);
 58 salcianu 1.1.2.2         while(!W.isEmpty()){
 59 salcianu 1.1.2.2             MetaMethod mm_work = (MetaMethod) W.remove();
 60 salcianu 1.1.2.2             MetaMethod[] dc = getCallers(mm_work);
 61 salcianu 1.1.2.2             for(int i = 0; i < dc.length; i++)
 62 salcianu 1.1.2.2                 if(callers.add(dc[i])) W.add(dc[i]);
 63 salcianu 1.1.2.2         }
 64 salcianu 1.1.2.2         return (MetaMethod[]) callers.toArray(new MetaMethod[callers.size()]);
 65 salcianu 1.1.2.1     }
 66 salcianu 1.1.2.1 
 67 salcianu 1.1.2.1     // fills the relation callers, by simply inverting the information
 68 salcianu 1.1.2.1     // from the attached MetaCallGraph.
 69 salcianu 1.1.2.1     private void process(MetaCallGraph mcg){
 70 salcianu 1.1.2.1         // keeps the callers of each meta-method
 71 salcianu 1.1.2.1         // Relation<MetaMethod mm_callee, MetaMethod mm_caller>.
 72 salcianu 1.1.2.4         Relation callers = new LightRelation();
 73 salcianu 1.1.2.1 
 74 cananian 1.5             for (Object mm_callerO : mcg.getAllMetaMethods()){
 75 cananian 1.5                 MetaMethod mm_caller = (MetaMethod) mm_callerO;
 76 salcianu 1.1.2.1             MetaMethod[] mms = mcg.getCallees(mm_caller);
 77 salcianu 1.1.2.1             for(int i = 0 ; i < mms.length ; i++){
 78 salcianu 1.1.2.1                 MetaMethod mm_callee = mms[i];
 79 cananian 1.3.2.1                 assert (mm_caller != null) && (mm_callee != null) : "mm_caller = " + mm_caller +
 80 cananian 1.3.2.1                             "i = " + i + "/" + mms.length;
 81 salcianu 1.1.2.5                 callers.add(mm_callee, mm_caller);
 82 salcianu 1.1.2.1             }
 83 salcianu 1.1.2.1         }
 84 salcianu 1.1.2.1 
 85 salcianu 1.1.2.1         compact(callers);
 86 salcianu 1.1.2.1         callers = null; // enable the GC
 87 salcianu 1.1.2.1     }
 88 salcianu 1.1.2.1 
 89 salcianu 1.1.2.1     // Converts the information from the big format (Relation) into a smaller
 90 salcianu 1.1.2.1     // one (array based)
 91 salcianu 1.1.2.1     private void compact(Relation callers){
 92 salcianu 1.1.2.1         callers_cmpct = new HashMap();
 93 cananian 1.5             for(Object mmO : callers.keys()){
 94 cananian 1.5                 MetaMethod mm = (MetaMethod) mmO;
 95 salcianu 1.1.2.4             Set set = callers.getValues(mm);
 96 salcianu 1.1.2.1             MetaMethod[] mms = 
 97 salcianu 1.1.2.1                 (MetaMethod[]) set.toArray(new MetaMethod[set.size()]);
 98 salcianu 1.1.2.1             callers_cmpct.put(mm,mms);
 99 salcianu 1.1.2.1         }
100 salcianu 1.1.2.1     }
101 salcianu 1.1.2.1 
102 cananian 1.2     }