1 package joeq.Compiler.Analysis.IPSSA.Apps;
2
3 import java.util.Arrays;
4 import java.util.Collection;
5 import java.util.Collections;
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.Iterator;
9 import java.util.LinkedList;
10 import java.util.Set;
11 import java.io.BufferedReader;
12 import java.io.FileReader;
13 import java.io.IOException;
14 import joeq.Class.PrimordialClassLoader;
15 import joeq.Class.jq_Class;
16 import joeq.Class.jq_InstanceField;
17 import joeq.Class.jq_Method;
18 import joeq.Class.jq_Type;
19 import joeq.Compiler.Quad.CallGraph;
20 import joeq.Compiler.Quad.CodeCache;
21 import joeq.Compiler.Quad.RootedCHACallGraph;
22 import joeq.Main.HostedVM;
23 import jwutil.collections.AppendIterator;
24
25 public class DeclarationDepth {
26 static class DeclarationDepthComputation implements Runnable {
27 private Set _classes;
28 LinkedList worklist = new LinkedList();
29 HashMap values = new HashMap();
30
31 private boolean _verbose = false;
32
33 public DeclarationDepthComputation(Iterator classIter){
34 _classes = new HashSet();
35 Collection roots = new LinkedList();
36
37 while(classIter.hasNext()) {
38 jq_Class c = (jq_Class) jq_Type.parseType((String)classIter.next());
39 c.load();
40 _classes.add(c);
41 roots.addAll(Arrays.asList(c.getDeclaredStaticMethods()));
42 }
43
44 CallGraph cg = new RootedCHACallGraph();
45 cg.setRoots(roots);
46 for(Iterator iter = cg.getAllMethods().iterator(); iter.hasNext(); ) {
47 jq_Class c = ((jq_Method)iter.next()).getDeclaringClass();
48 _classes.add(c);
49 }
50 System.out.println("Processing a total of " + _classes.size() + " class(es)");
51 }
52
53 public static void main(String[] args) {
54 HostedVM.initialize();
55 CodeCache.AlwaysMap = true;
56
57
58
59 Iterator i = null;
60 for (int x=0; x<args.length; ++x) {
61 if (args[x].equals("-file")) {
62 try {
63 BufferedReader br = new BufferedReader(new FileReader(args[++x]));
64 LinkedList list = new LinkedList();
65 for (;;) {
66 String s = br.readLine();
67 if (s == null) break;
68 if (s.length() == 0) continue;
69 if (s.startsWith("%")) continue;
70 if (s.startsWith("#")) continue;
71 list.add(s);
72 }
73 i = new AppendIterator(list.iterator(), i);
74 }catch(IOException e) {
75 e.printStackTrace();
76 System.exit(2);
77 }
78
79 } else
80 if (args[x].endsWith("*")) {
81 i = new AppendIterator(PrimordialClassLoader.loader.listPackage(args[x].substring(0, args[x].length()-1)), i);
82 } else
83 if(args[x].charAt(0) == '-'){
84 System.exit(2);
85 }else {
86 String classname = args[x];
87 i = new AppendIterator(Collections.singleton(classname).iterator(), i);
88 }
89 }
90
91 DeclarationDepthComputation finder = new DeclarationDepthComputation(i);
92 finder.run();
93 }
94
95 public void run() {
96 worklist.addAll(_classes);
97 boolean change = false;
98 int iterCount = 0;
99 do {
100 change = false;
101 for(Iterator iter = worklist.iterator(); iter.hasNext();) {
102 jq_Class c = (jq_Class)iter.next();
103
104 change |= processClass(c);
105 }
106 System.err.println("Done with the worklist, iteration # " + ++iterCount);
107 } while(change && iterCount < 20);
108
109 System.out.println("Results:");
110 for(Iterator iter = values.keySet().iterator(); iter.hasNext(); ) {
111 jq_Class c = (jq_Class) iter.next();
112 Integer i = (Integer) values.get(c);
113 System.out.println(cutto(c.toString(), 45) + " : " + i);
114 }
115 }
116
117 private boolean processClass(jq_Class c) {
118
119 if(values.get(c) == null) values.put(c, new Integer(0));
120 int oldValue = ((Integer)values.get(c)).intValue();
121
122 int newValue = 0;
123 jq_InstanceField[] fields = c.getDeclaredInstanceFields();
124 for(int i = 0; i < fields.length; i++) {
125 jq_InstanceField m = fields[i];
126 if(! (m.getType() instanceof jq_Class) ) continue;
127
128 jq_Class type = (jq_Class) m.getType();
129 if(type == c) continue;
130
131 if(values.get(type) == null) {
132
133 if(newValue < 1) newValue = 1;
134 } else {
135 int d = ((Integer)values.get(type)).intValue();
136 if(d+1 > newValue) newValue = d+1;
137 }
138 }
139 if(newValue != oldValue) {
140 values.put(c, new Integer(newValue));
141 System.err.println("Value for " + c + " changed to " + newValue);
142 return true;
143 } else {
144 return false;
145 }
146 }
147
148 private static String cutto(String string, int to) {
149 return string.length() < to ?
150 string + repeat(" ", to - string.length()) :
151 string.substring(0, to - 3) + "...";
152 }
153 private static String repeat(String string, int to) {
154 StringBuffer result = new StringBuffer();
155 for(int i = 0; i < to; i++) {
156 result.append(string);
157 }
158
159 return result.toString();
160 }
161 }
162 }