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