1 kkz      1.1.2.1  // AllCallers.java, created Tue Oct 19 19:34:57 1999 by kkz
  2 cananian 1.1.2.10 // Copyright (C) 1999 Karen K. Zee <kkz@alum.mit.edu>
  3 kkz      1.1.2.1  // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 kkz      1.1.2.1  package harpoon.Analysis;
  5 kkz      1.1.2.1  
  6 salcianu 1.4      import harpoon.Analysis.CallGraph;
  7 salcianu 1.1.2.8  import harpoon.Analysis.Quads.CallGraphImpl;
  8 kkz      1.1.2.1  import harpoon.Analysis.ClassHierarchy;
  9 kkz      1.1.2.1  import harpoon.ClassFile.HClass;
 10 kkz      1.1.2.1  import harpoon.ClassFile.HCode;
 11 kkz      1.1.2.1  import harpoon.ClassFile.HCodeFactory;
 12 kkz      1.1.2.1  import harpoon.ClassFile.HMethod;
 13 kkz      1.1.2.1  import harpoon.Util.Util;
 14 kkz      1.1.2.1  import harpoon.Util.Worklist;
 15 cananian 1.1.2.11 import harpoon.Util.Collections.WorkSet;
 16 kkz      1.1.2.1  import java.util.Set;
 17 kkz      1.1.2.1  import java.util.Hashtable;
 18 kkz      1.1.2.1  import java.util.Iterator;
 19 salcianu 1.1.2.4  import java.util.Collections;
 20 kkz      1.1.2.1  
 21 kkz      1.1.2.1  /**
 22 kkz      1.1.2.2   * <code>AllCallers</code> calculates the transitive closure of the dual
 23 kkz      1.1.2.2   * of the call graph for methods that fulfill a certain condition.
 24 kkz      1.1.2.1   * 
 25 cananian 1.1.2.10  * @author Karen K. Zee <kkz@alum.mit.edu>
 26 cananian 1.5       * @version $Id: AllCallers.java,v 1.5 2004/02/08 03:19:12 cananian Exp $
 27 kkz      1.1.2.1   */
 28 kkz      1.1.2.1  
 29 kkz      1.1.2.1  public class AllCallers {
 30 salcianu 1.3          final Set/*<HMethod>*/ callableMethods;
 31 kkz      1.1.2.1      final Hashtable g;
 32 kkz      1.1.2.1  
 33 kkz      1.1.2.2      /** Creates an <code>AllCallers</code> object using the specified
 34 kkz      1.1.2.1       *  <code>ClassHierarchy</code>. Currently, <code>hcf</code> must be a
 35 kkz      1.1.2.2       *  code factory that generates quad-no-ssa or quad-ssi form because
 36 kkz      1.1.2.3       *  the dual of the call graph is built using <code>CallGraph</code>.
 37 kkz      1.1.2.1       */
 38 kkz      1.1.2.1      public AllCallers(ClassHierarchy ch, HCodeFactory hcf) {
 39 salcianu 1.3              this(new CallGraphImpl(ch, hcf));
 40 bdemsky  1.1.2.5      }
 41 bdemsky  1.1.2.5  
 42 salcianu 1.3          /** Creates an <code>AllCallers</code> object that is the dual of
 43 salcianu 1.3              the callgraph <code>cg</code> (of type
 44 salcianu 1.3              <code>harpoon.Analysis.Quads.CallGraoh</code>). */
 45 salcianu 1.3          public AllCallers(CallGraph cg) {
 46 salcianu 1.3              this.callableMethods = cg.callableMethods();
 47 bdemsky  1.1.2.5          this.g = buildGraph(cg);
 48 kkz      1.1.2.1      }
 49 kkz      1.1.2.1  
 50 kkz      1.1.2.2      /** <code>getCallers</code> returns a <code>Set</code> that contains
 51 kkz      1.1.2.2       *  all indirect and direct callers of callable methods that fulfill 
 52 kkz      1.1.2.2       *  the predicate in the <code>select</code> method of <code>ms</code>.
 53 kkz      1.1.2.2       */
 54 kkz      1.1.2.1      public Set getCallers(MethodSet ms) {
 55 kkz      1.1.2.1          Worklist toadd = new WorkSet();
 56 cananian 1.5              for (Object mO : callableMethods) {
 57 cananian 1.5                  HMethod m = (HMethod) mO;
 58 kkz      1.1.2.1              if (ms.select(m)) {
 59 kkz      1.1.2.1                  toadd.push(m);
 60 kkz      1.1.2.1              }
 61 kkz      1.1.2.1          }
 62 kkz      1.1.2.1          Set retval = new WorkSet();
 63 kkz      1.1.2.1          while(!toadd.isEmpty()) {
 64 kkz      1.1.2.1              HMethod callee = (HMethod)toadd.pull();
 65 kkz      1.1.2.1              retval.add(callee);
 66 kkz      1.1.2.1              if (this.g.containsKey(callee)) {
 67 cananian 1.5                      for (Object callerO : ((WorkSet)this.g.get(callee))) {
 68 cananian 1.5                          HMethod caller = (HMethod) callerO;
 69 kkz      1.1.2.1                      if (!retval.contains(caller))
 70 kkz      1.1.2.1                          toadd.push(caller);
 71 kkz      1.1.2.1                  }
 72 kkz      1.1.2.1              }
 73 kkz      1.1.2.1          }
 74 kkz      1.1.2.1          return retval;
 75 kkz      1.1.2.1      }
 76 kkz      1.1.2.1  
 77 kkz      1.1.2.2      /** <code>MethodSet</code> defines the interface whose method
 78 kkz      1.1.2.2       *  <code>select</code> is used in <code>getCallers</code> as a
 79 kkz      1.1.2.2       *  predicate.
 80 kkz      1.1.2.2       */
 81 kkz      1.1.2.1      public static interface MethodSet {
 82 kkz      1.1.2.1          boolean select(HMethod hm);
 83 kkz      1.1.2.1      }
 84 kkz      1.1.2.1  
 85 kkz      1.1.2.2      /** Builds the dual of the call graph using the 
 86 kkz      1.1.2.2       *  <code>ClassHierarchy</code> and <code>HCodeFactory</code>
 87 kkz      1.1.2.1       *  with which the <code>this</code> object was created.
 88 kkz      1.1.2.2       *  Returns the call graph as a Hashtable.
 89 kkz      1.1.2.1       */
 90 bdemsky  1.1.2.5      private Hashtable buildGraph(CallGraph cg) {
 91 kkz      1.1.2.1          Hashtable ht = new Hashtable();
 92 cananian 1.5              for (Object mO : callableMethods) {
 93 cananian 1.5                  HMethod m = (HMethod) mO;
 94 kkz      1.1.2.1              HMethod[] callees = cg.calls(m);
 95 kkz      1.1.2.1              for (int i = 0; i < callees.length; i++) {
 96 kkz      1.1.2.1                  if (!ht.containsKey(callees[i]))
 97 kkz      1.1.2.1                      ht.put(callees[i], new WorkSet());
 98 kkz      1.1.2.1                  ((WorkSet)ht.get(callees[i])).add(m);
 99 kkz      1.1.2.1              }
100 kkz      1.1.2.1          }
101 kkz      1.1.2.1          return ht;
102 kkz      1.1.2.1      }
103 salcianu 1.1.2.4  
104 salcianu 1.1.2.6      /** Returns all the direct callers of the <code>hm</code> method. */
105 salcianu 1.1.2.6      public HMethod[] directCallers(HMethod hm){
106 salcianu 1.1.2.4          WorkSet wset = (WorkSet)g.get(hm);
107 salcianu 1.1.2.6          if(wset==null) return new HMethod[0];
108 salcianu 1.1.2.7          return (HMethod[]) (wset.toArray(new HMethod[wset.size()]));
109 salcianu 1.1.2.6      }
110 salcianu 1.1.2.6  
111 salcianu 1.1.2.6      /** Returns all the direct callers of the <code>hm</code> method. */
112 salcianu 1.1.2.6      public Set directCallerSet(HMethod hm){
113 salcianu 1.1.2.6          WorkSet wset = (WorkSet)g.get(hm);
114 salcianu 1.1.2.6          if(wset==null) return Collections.EMPTY_SET;
115 salcianu 1.1.2.6          return wset;
116 salcianu 1.1.2.4      }
117 salcianu 1.1.2.4  
118 kkz      1.1.2.1  }
119 bdemsky  1.1.2.5  
120 bdemsky  1.1.2.5  
121 bdemsky  1.1.2.5  
122 bdemsky  1.1.2.5  
123 bdemsky  1.1.2.5  
124 bdemsky  1.1.2.5  
125 cananian 1.2