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 }