1 salcianu 1.1.2.1 // CallGraphImpl.java, created Sun Oct 11 12:56:36 1998 by cananian
  2 salcianu 1.1.2.1 // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.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.Quads;
  5 salcianu 1.1.2.1 
  6 salcianu 1.1.2.1 import harpoon.Analysis.ClassHierarchy;
  7 salcianu 1.1.2.1 import harpoon.ClassFile.HClass;
  8 salcianu 1.1.2.1 import harpoon.ClassFile.HCode;
  9 salcianu 1.1.2.1 import harpoon.ClassFile.HCodeFactory;
 10 salcianu 1.1.2.1 import harpoon.ClassFile.HMethod;
 11 salcianu 1.1.2.1 import harpoon.IR.Quads.Quad;
 12 salcianu 1.6     import harpoon.IR.Quads.QuadKind;
 13 salcianu 1.1.2.1 import harpoon.IR.Quads.CALL;
 14 salcianu 1.6     import harpoon.IR.Quads.Code;
 15 salcianu 1.1.2.1 import harpoon.Util.Util;
 16 cananian 1.11    import net.cscott.jutil.WorkSet;
 17 salcianu 1.1.2.1 
 18 salcianu 1.1.2.1 import java.util.Arrays;
 19 salcianu 1.1.2.1 import java.util.HashMap;
 20 salcianu 1.1.2.1 import java.util.HashSet;
 21 salcianu 1.1.2.1 import java.util.Iterator;
 22 salcianu 1.1.2.1 import java.util.Map;
 23 salcianu 1.1.2.1 import java.util.Set;
 24 salcianu 1.1.2.1 
 25 salcianu 1.1.2.1 /**
 26 salcianu 1.1.2.1  * <code>CallGraphImpl</code> constructs a simple directed call graph.
 27 salcianu 1.1.2.1  This is the most conservative implementation of <code>CallGraph</code>.
 28 salcianu 1.1.2.1  * 
 29 salcianu 1.1.2.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 30 cananian 1.11     * @version $Id: CallGraphImpl.java,v 1.11 2004/02/08 01:53:14 cananian Exp $
 31 salcianu 1.1.2.1  */
 32 salcianu 1.6     public class CallGraphImpl extends AbstrCallGraph  {
 33 salcianu 1.1.2.1     final ClassHierarchy ch;
 34 salcianu 1.1.2.1     /** Creates a <code>CallGraph</code> using the specified 
 35 salcianu 1.1.2.1      *  <code>ClassHierarchy</code>. <code>hcf</code> must be a code
 36 salcianu 1.1.2.1      *  factory that generates quad-ssi or quad-no-ssa form. */
 37 salcianu 1.1.2.1     public CallGraphImpl(ClassHierarchy ch, HCodeFactory hcf) {
 38 salcianu 1.1.2.1         // this is maybe a little too draconian
 39 salcianu 1.8             assert (hcf.getCodeName().equals(harpoon.IR.Quads.QuadSSI.codename) ||
 40 salcianu 1.8                 hcf.getCodeName().equals(harpoon.IR.Quads.QuadSSA.codename) ||
 41 salcianu 1.8                 hcf.getCodeName().equals(harpoon.IR.Quads.QuadNoSSA.codename));
 42 salcianu 1.1.2.1         this.ch = ch;
 43 salcianu 1.1.2.1         this.hcf = hcf;
 44 salcianu 1.1.2.1     }
 45 salcianu 1.1.2.1     
 46 salcianu 1.1.2.1     /** Return a list of all possible methods called by this method. */
 47 salcianu 1.1.2.1     public HMethod[] calls(final HMethod m) {
 48 cananian 1.9             HMethod[] retval = cache.get(m);
 49 salcianu 1.1.2.1         if (retval==null) {
 50 cananian 1.9                 final Set<HMethod> s = new HashSet<HMethod>();
 51 cananian 1.9                 final HCode<Quad> hc = hcf.convert(m);
 52 salcianu 1.1.2.1             if (hc==null) { cache.put(m,new HMethod[0]); return calls(m); }
 53 cananian 1.9                 for (Iterator<Quad> it = hc.getElementsI(); it.hasNext(); ) {
 54 cananian 1.9                     Quad q = it.next();
 55 salcianu 1.1.2.1                 if (!(q instanceof CALL)) continue;
 56 salcianu 1.1.2.1                 HMethod cm = ((CALL)q).method();
 57 salcianu 1.1.2.1                 if (s.contains(cm)) continue; // duplicate.
 58 salcianu 1.1.2.1                 s.addAll(Arrays.asList(calls(m, (CALL)q)));
 59 salcianu 1.1.2.1             }
 60 salcianu 1.1.2.1             // finally, copy result vector to retval array.
 61 salcianu 1.1.2.1             retval = (HMethod[]) s.toArray(new HMethod[s.size()]);
 62 salcianu 1.1.2.1             // and cache result.
 63 salcianu 1.1.2.1             cache.put(m, retval);
 64 salcianu 1.1.2.1         }
 65 salcianu 1.1.2.1         return retval;
 66 salcianu 1.1.2.1     }
 67 cananian 1.9         final private Map<HMethod,HMethod[]> cache =
 68 cananian 1.9             new HashMap<HMethod,HMethod[]>();
 69 salcianu 1.1.2.1 
 70 salcianu 1.4         /** Return an array containing all possible methods called by this
 71 salcianu 1.4          *  method at a particular call site. */
 72 salcianu 1.1.2.1     public HMethod[] calls(final HMethod m, final CALL cs) {
 73 salcianu 1.1.2.1         HMethod cm = cs.method();
 74 salcianu 1.1.2.1         // for 'special' invocations, we know the method exactly.
 75 salcianu 1.1.2.1         if ((!cs.isVirtual()) || cs.isStatic()) return new HMethod[]{ cm };
 76 cananian 1.9             final Set<HMethod> s = new HashSet<HMethod>();
 77 salcianu 1.1.2.1         // all methods of children of this class are reachable.
 78 cananian 1.9             WorkSet<HClass> W = new WorkSet<HClass>();
 79 salcianu 1.1.2.1         W.add(cm.getDeclaringClass());
 80 salcianu 1.1.2.1         while (!W.isEmpty()) {
 81 cananian 1.9                 HClass c = W.pop();
 82 salcianu 1.1.2.1             // if this class can be instatiated, then its
 83 salcianu 1.1.2.1             // implementation of the method should be added to the set.
 84 salcianu 1.1.2.1             if (ch.instantiatedClasses().contains(c))
 85 salcianu 1.1.2.1                 try {
 86 salcianu 1.1.2.1                     s.add(c.getMethod(cm.getName(),
 87 salcianu 1.1.2.1                                       cm.getDescriptor()));
 88 salcianu 1.1.2.1                 } catch (NoSuchMethodError nsme) { }
 89 salcianu 1.1.2.1             // recurse through all children of this method's class.
 90 cananian 1.9                 for (Iterator<HClass> it=ch.children(c).iterator(); it.hasNext(); )
 91 salcianu 1.1.2.1                 W.add(it.next());
 92 salcianu 1.1.2.1         }
 93 salcianu 1.1.2.1         // finally, copy result vector to retval array.
 94 salcianu 1.1.2.1         return (HMethod[]) s.toArray(new HMethod[s.size()]);
 95 salcianu 1.1.2.1     }
 96 salcianu 1.1.2.2 
 97 salcianu 1.1.2.2     /** Returns the set of all the methods that can be called in the 
 98 salcianu 1.1.2.2         execution of the program. */
 99 cananian 1.9         public Set<HMethod> callableMethods(){
100 salcianu 1.1.2.2         return ch.callableMethods();
101 salcianu 1.1.2.2     }
102 cananian 1.2     }