1 package Analysis.CallGraph;
3 import IR.Flat.FlatMethod;
4 import IR.Flat.FlatNode;
5 import IR.Flat.FlatCall;
8 import IR.ClassDescriptor;
9 import IR.MethodDescriptor;
10 import IR.TypeDescriptor;
12 public class CallGraph {
17 public CallGraph(State state) {
19 methods=new Hashtable();
20 methodmap=new Hashtable();
25 private void buildMethodTable() {
26 //Iterator through classes
27 Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
29 ClassDescriptor cn=(ClassDescriptor)it.next();
30 Iterator methodit=cn.getMethods();
31 //Iterator through methods
32 while(methodit.hasNext()) {
33 MethodDescriptor md=(MethodDescriptor)methodit.next();
34 if (md.isStatic()||md.getReturnType()==null)
36 ClassDescriptor superdesc=cn.getSuperDesc();
37 if (superdesc!=null) {
38 Set possiblematches=superdesc.getMethodTable().getSet(md.getSymbol());
39 boolean foundmatch=false;
40 for(Iterator matchit=possiblematches.iterator();matchit.hasNext();) {
41 MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
42 if (md.matches(matchmd)) {
43 if (!methods.containsKey(matchmd))
44 methods.put(matchmd,new HashSet());
45 ((HashSet)methods.get(matchmd)).add(md);
55 public Set getMethods(MethodDescriptor md, TypeDescriptor type) {
56 return getMethods(md);
59 /** Given a call to MethodDescriptor, lists the methods which
60 could actually be called due to virtual dispatch. */
61 public Set getMethods(MethodDescriptor md) {
62 HashSet ns=new HashSet();
64 Set s=(Set)methods.get(md);
66 for(Iterator it=s.iterator();it.hasNext();) {
67 MethodDescriptor md2=(MethodDescriptor)it.next();
68 ns.addAll(getMethods(md2));
73 /** Given a call to MethodDescriptor, lists the methods which
74 could actually be call by that method. */
75 public Set getMethodCalls(MethodDescriptor md) {
76 HashSet ns=new HashSet();
78 Set s=(Set)methodmap.get(md);
80 for(Iterator it=s.iterator();it.hasNext();) {
81 MethodDescriptor md2=(MethodDescriptor)it.next();
82 ns.addAll(getMethodCalls(md2));
87 private void buildGraph() {
88 Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
90 ClassDescriptor cn=(ClassDescriptor)it.next();
91 Iterator methodit=cn.getMethods();
92 //Iterator through methods
93 while(methodit.hasNext()) {
94 MethodDescriptor md=(MethodDescriptor)methodit.next();
100 private void analyzeMethod(MethodDescriptor md) {
101 FlatMethod fm=state.getMethodFlat(md);
102 HashSet toexplore=new HashSet();
104 HashSet explored=new HashSet();
105 //look at all the nodes in the flat representation
106 while(!toexplore.isEmpty()) {
107 FlatNode fn=(FlatNode)(toexplore.iterator()).next();
108 toexplore.remove(fn);
110 for(int i=0;i<fn.numNext();i++) {
111 FlatNode fnnext=fn.getNext(i);
112 if (!explored.contains(fnnext))
113 toexplore.add(fnnext);
115 if (fn.kind()==FKind.FlatCall) {
116 FlatCall fc=(FlatCall)fn;
117 MethodDescriptor calledmethod=fc.getMethod();
118 Set methodsthatcouldbecalled=fc.getThis()==null?getMethods(calledmethod):
119 getMethods(calledmethod, fc.getThis().getType());
120 if (!methodmap.containsKey(md))
121 methodmap.put(md,new HashSet());
122 ((HashSet)methodmap.get(md)).addAll(methodsthatcouldbecalled);