1 marinov  1.1.2.1  // TypeInfo.java, created Thu Sep 10 14:58:21 1998 by cananian
  2 marinov  1.1.2.1  // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.edu>
  3 marinov  1.1.2.1  // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 marinov  1.1.2.1  package harpoon.Analysis.TypeInference;
  5 marinov  1.1.2.1  
  6 marinov  1.1.2.1  import harpoon.Analysis.Maps.UseDefMap;
  7 marinov  1.1.2.1  import harpoon.Analysis.UseDef;
  8 cananian 1.1.2.14 import harpoon.ClassFile.HClass;
  9 cananian 1.1.2.14 import harpoon.ClassFile.HCodeFactory;
 10 cananian 1.1.2.14 import harpoon.ClassFile.HCodeElement;
 11 cananian 1.1.2.14 import harpoon.ClassFile.HMethod;
 12 cananian 1.1.2.16 import harpoon.ClassFile.Linker;
 13 cananian 1.1.2.14 import harpoon.IR.Quads.Quad;
 14 cananian 1.1.2.14 import harpoon.IR.Quads.QuadSSI;
 15 cananian 1.1.2.14 import harpoon.IR.Quads.QuadVisitor;
 16 cananian 1.1.2.14 import harpoon.IR.Quads.AGET;
 17 cananian 1.1.2.14 import harpoon.IR.Quads.ANEW;
 18 cananian 1.1.2.14 import harpoon.IR.Quads.ALENGTH;
 19 cananian 1.1.2.14 import harpoon.IR.Quads.ARRAYINIT;
 20 cananian 1.1.2.14 import harpoon.IR.Quads.ASET;
 21 cananian 1.1.2.14 import harpoon.IR.Quads.CALL;
 22 cananian 1.1.2.14 import harpoon.IR.Quads.CJMP;
 23 cananian 1.1.2.14 import harpoon.IR.Quads.COMPONENTOF;
 24 cananian 1.1.2.14 import harpoon.IR.Quads.CONST;
 25 cananian 1.1.2.14 import harpoon.IR.Quads.DEBUG;
 26 cananian 1.1.2.14 import harpoon.IR.Quads.GET;
 27 cananian 1.1.2.14 import harpoon.IR.Quads.FOOTER;
 28 cananian 1.1.2.14 import harpoon.IR.Quads.HANDLER;
 29 cananian 1.1.2.14 import harpoon.IR.Quads.HEADER;
 30 cananian 1.1.2.14 import harpoon.IR.Quads.INSTANCEOF;
 31 cananian 1.1.2.14 import harpoon.IR.Quads.LABEL;
 32 cananian 1.1.2.14 import harpoon.IR.Quads.METHOD;
 33 cananian 1.1.2.14 import harpoon.IR.Quads.MONITORENTER;
 34 cananian 1.1.2.14 import harpoon.IR.Quads.MONITOREXIT;
 35 cananian 1.1.2.14 import harpoon.IR.Quads.MOVE;
 36 cananian 1.1.2.14 import harpoon.IR.Quads.NEW;
 37 cananian 1.1.2.14 import harpoon.IR.Quads.NOP;
 38 cananian 1.1.2.14 import harpoon.IR.Quads.OPER;
 39 cananian 1.1.2.14 import harpoon.IR.Quads.PHI;
 40 cananian 1.1.2.14 import harpoon.IR.Quads.RETURN;
 41 cananian 1.1.2.14 import harpoon.IR.Quads.SET;
 42 cananian 1.1.2.14 import harpoon.IR.Quads.SIGMA;
 43 cananian 1.1.2.14 import harpoon.IR.Quads.SWITCH;
 44 cananian 1.1.2.14 import harpoon.IR.Quads.THROW;
 45 cananian 1.1.2.14 import harpoon.IR.Quads.TYPECAST;
 46 marinov  1.1.2.1  import harpoon.Util.Util;
 47 cananian 1.1.2.14 import harpoon.Temp.Temp;
 48 marinov  1.1.2.1  import harpoon.Util.Worklist;
 49 cananian 1.1.2.19 import harpoon.Util.Collections.WorkSet;
 50 cananian 1.5      import java.util.Iterator;
 51 cananian 1.1.2.17 import java.util.HashMap;
 52 cananian 1.1.2.17 import java.util.HashSet;
 53 cananian 1.1.2.17 import java.util.Iterator;
 54 cananian 1.1.2.17 import java.util.Map;
 55 cananian 1.1.2.17 import java.util.Set;
 56 marinov  1.1.2.1  /**
 57 cananian 1.1.2.13  * <code>TypeInfo</code> is a simple type analysis tool for quad-ssi form.
 58 marinov  1.1.2.1   * 
 59 marinov  1.1.2.1   * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 60 cananian 1.6       * @version $Id: IntraProc.java,v 1.6 2004/02/08 03:20:38 cananian Exp $
 61 marinov  1.1.2.1   */
 62 marinov  1.1.2.1  
 63 marinov  1.1.2.1  public class IntraProc {
 64 marinov  1.1.2.1      InterProc environment;
 65 marinov  1.1.2.1      HMethod method;
 66 cananian 1.1.2.13     QuadSSI code;
 67 marinov  1.1.2.1      UseDefMap usedef;
 68 cananian 1.1.2.16     Linker linker;
 69 marinov  1.1.2.1              
 70 marinov  1.1.2.1      SetHClass[] parameterTypes;
 71 marinov  1.1.2.1      SetHClass returnType;
 72 marinov  1.1.2.1      SetHClass exceptionType;
 73 marinov  1.1.2.7      public static boolean exceptionAnalysis = false; // UGLY?! otherwise, running out of memory now
 74 marinov  1.1.2.1      Set callees;
 75 marinov  1.1.2.7      int depth = 0;
 76 marinov  1.1.2.1  
 77 cananian 1.1.2.11     public IntraProc(InterProc e, HMethod m, HCodeFactory hcf) { 
 78 marinov  1.1.2.1          environment = e;
 79 marinov  1.1.2.1          method = m;
 80 cananian 1.1.2.16         linker = m.getDeclaringClass().getLinker();
 81 cananian 1.1.2.13         code = (QuadSSI)hcf.convert(m);
 82 marinov  1.1.2.1          usedef = new UseDef();
 83 marinov  1.1.2.1          parameterTypes = new SetHClass[m.getParameterTypes().length+(m.isStatic()?0:1)];
 84 marinov  1.1.2.1          for (int i=0; i<parameterTypes.length; i++)
 85 marinov  1.1.2.1              parameterTypes[i] = new SetHClass();
 86 marinov  1.1.2.1          returnType = new SetHClass();
 87 marinov  1.1.2.1          exceptionType = new SetHClass();
 88 pnkfelix 1.1.2.12         callees = new HashSet();
 89 marinov  1.1.2.1      }
 90 marinov  1.1.2.1  
 91 marinov  1.1.2.1      SetHClass getReturnType() { return returnType.copy(); }
 92 marinov  1.1.2.1      SetHClass getExceptionType() { return exceptionType.copy(); }
 93 marinov  1.1.2.1  
 94 marinov  1.1.2.7      void addCallee(IntraProc i) { 
 95 cananian 1.1.2.17         callees.add(i); 
 96 marinov  1.1.2.7          int d = i.depth+1; 
 97 marinov  1.1.2.7          if (d>depth) depth = d;
 98 marinov  1.1.2.7      }
 99 marinov  1.1.2.1      boolean addParameters(SetHClass[] p) {
100 marinov  1.1.2.1          boolean changed = false;
101 marinov  1.1.2.1          for (int i=0; i<p.length; i++)
102 marinov  1.1.2.1              if (parameterTypes[i].union(p[i])) changed = true;
103 marinov  1.1.2.1          return changed;
104 marinov  1.1.2.1      }    
105 marinov  1.1.2.1  
106 marinov  1.1.2.1      HMethod[] possibleMethods(HMethod m, SetHClass[] p) {
107 marinov  1.1.2.1          if (m.isStatic()) return new HMethod[]{ m };
108 marinov  1.1.2.8          if (p[0]==null) return new HMethod[0];
109 pnkfelix 1.1.2.12         Set sm = new HashSet();
110 cananian 1.6              for (Object cO : p[0]) {
111 cananian 1.6                  HClass c = (HClass) cO;
112 marinov  1.1.2.1              boolean notDone = true;
113 marinov  1.1.2.1              HMethod nm = null;
114 marinov  1.1.2.1              do {
115 marinov  1.1.2.1                  try {
116 marinov  1.1.2.1                      nm = c.getDeclaredMethod(m.getName(),
117 marinov  1.1.2.1                                               m.getDescriptor());
118 marinov  1.1.2.1                          notDone = false;
119 marinov  1.1.2.1                  } catch (NoSuchMethodError n) { 
120 marinov  1.1.2.1                      c = c.getSuperclass();
121 marinov  1.1.2.1                  }
122 marinov  1.1.2.1              } while (notDone&&(c!=null));
123 marinov  1.1.2.8              while ((c!=m.getDeclaringClass())&&(c!=null)) c=c.getSuperclass();
124 cananian 1.1.2.17             if (c!=null) sm.add(nm);
125 marinov  1.1.2.1          }
126 cananian 1.1.2.17         return (HMethod[]) sm.toArray(new HMethod[sm.size()]);
127 marinov  1.1.2.1      }
128 marinov  1.1.2.4      
129 marinov  1.1.2.4      void nativeMethods() {
130 marinov  1.1.2.4          if (method.getDeclaringClass().getName().equals("java.lang.System")) {
131 marinov  1.1.2.4              if (method.getName().equals("setIn0"))
132 cananian 1.1.2.16                 environment.mergeType(linker.forName("java.lang.System").getDeclaredField("in"), parameterTypes[0]);
133 marinov  1.1.2.4              else if (method.getName().equals("setOut0"))
134 cananian 1.1.2.16                 environment.mergeType(linker.forName("java.lang.System").getDeclaredField("out"), parameterTypes[0]);
135 marinov  1.1.2.4              else if (method.getName().equals("setErr0"))
136 cananian 1.1.2.16                 environment.mergeType(linker.forName("java.lang.System").getDeclaredField("err"), parameterTypes[0]);
137 marinov  1.1.2.4          }
138 marinov  1.1.2.4          returnType = environment.cone(method.getReturnType());
139 marinov  1.1.2.7          if (exceptionAnalysis) // UGLY?! otherwise, running out of memory now
140 cananian 1.1.2.16             exceptionType = environment.cone(linker.forClass(Throwable.class));
141 marinov  1.1.2.4      } 
142 marinov  1.1.2.1  
143 marinov  1.1.2.1      boolean outputChanged;
144 marinov  1.1.2.1      void analyze() {
145 marinov  1.1.2.8          /* added to try to save some memory */
146 marinov  1.1.2.8          boolean noCache;
147 cananian 1.1.2.17         if (map==null) { map = new HashMap(); noCache = true; }
148 marinov  1.1.2.8          else noCache = false;
149 marinov  1.1.2.8          //OUTPUT
150 marinov  1.1.2.8          long TTT=System.currentTimeMillis();
151 marinov  1.1.2.8          if (noCache) 
152 marinov  1.1.2.8              System.out.print("[analyzed " + method.getDeclaringClass() + " " + method.getName() + " in ");
153 marinov  1.1.2.8          //OUTPUT
154 marinov  1.1.2.1          //DEBUG
155 marinov  1.1.2.1          //if (method.getName().equals("t")) {
156 marinov  1.1.2.1          //System.out.print("   analyzing " + method.getDeclaringClass() + " " + method.getName());
157 marinov  1.1.2.1          //HClass[] II = method.getParameterTypes();
158 marinov  1.1.2.1          //for (int ii=0; ii<II.length; ii++)
159 marinov  1.1.2.1          //    System.out.print(" " + II[ii]);
160 marinov  1.1.2.1          //System.out.println("");
161 marinov  1.1.2.1          //    for (int ii=0; ii<parameterTypes.length; ii++)
162 marinov  1.1.2.1          //    System.out.println("i" + ii + "= " + parameterTypes[ii]);
163 marinov  1.1.2.1          //    System.out.println("r = " + returnType);
164 marinov  1.1.2.1          //    System.out.println("e = " + exceptionType);
165 marinov  1.1.2.1          //}
166 marinov  1.1.2.1          //DEBUG
167 marinov  1.1.2.6          /* "regular" calculation */
168 marinov  1.1.2.1          outputChanged = false;
169 marinov  1.1.2.4          if (code==null) // native or unanalyzable method
170 marinov  1.1.2.4              nativeMethods();
171 marinov  1.1.2.4          else {
172 marinov  1.1.2.1              Quad ql[] = (Quad[]) code.getElements();
173 cananian 1.1.2.17             WorkSet worklist = new WorkSet(); // use as FIFO
174 marinov  1.1.2.1              for (int i=0; i<ql.length; i++)
175 cananian 1.1.2.17                 worklist.add(ql[i]);
176 marinov  1.1.2.1              
177 marinov  1.1.2.1              // hack to handle typecasting:
178 marinov  1.1.2.1              //  keep track of booleans defined by instanceof's and acmpeq's.
179 cananian 1.1.2.17             Map checkcast = new HashMap();
180 marinov  1.1.2.1              for (int i=0; i<ql.length; i++)
181 marinov  1.1.2.1                  if (ql[i] instanceof INSTANCEOF ||
182 marinov  1.1.2.1                      ql[i] instanceof OPER)
183 marinov  1.1.2.1                      checkcast.put(ql[i].def()[0], ql[i]);
184 marinov  1.1.2.1              
185 marinov  1.1.2.1              TypeInfoVisitor tiv = new TypeInfoVisitor(checkcast);
186 marinov  1.1.2.1              while(!worklist.isEmpty()) {
187 cananian 1.1.2.17                 Quad q = (Quad) worklist.removeFirst(); // use as fifo
188 marinov  1.1.2.1                  tiv.modified = false;
189 cananian 1.1.2.15                 q.accept(tiv);
190 marinov  1.1.2.1                  if (tiv.modified) {
191 marinov  1.1.2.1                      Temp[] d = q.def();
192 marinov  1.1.2.1                      for (int i=0; i<d.length; i++) {
193 marinov  1.1.2.1                          HCodeElement[] u = usedef.useMap(code, d[i]);
194 marinov  1.1.2.1                          for (int j=0; j<u.length; j++) {
195 cananian 1.1.2.17                             worklist.add((Quad)u[j]); // only pushes unique quads.
196 marinov  1.1.2.1                          }
197 marinov  1.1.2.1                      }
198 marinov  1.1.2.1                  }
199 marinov  1.1.2.1              }
200 marinov  1.1.2.1          }
201 marinov  1.1.2.1          //DEBUG
202 marinov  1.1.2.4          //if (method.getName().equals("main")) {
203 marinov  1.1.2.1          //System.out.println("   finished " + method.getDeclaringClass() + " " + method.getName());
204 marinov  1.1.2.1          //    for (int ii=0; ii<parameterTypes.length; ii++)
205 marinov  1.1.2.4          //      System.out.println("i" + ii + "=" + parameterTypes[ii]);
206 marinov  1.1.2.1          //    System.out.println("r = " + returnType);
207 marinov  1.1.2.1          //    System.out.println("e = " + exceptionType);
208 marinov  1.1.2.1          //    System.out.println("changed = " + outputChanged);
209 marinov  1.1.2.1              /*
210 marinov  1.1.2.1              for (Enumeration ee=map.keys(); ee.hasMoreElements(); ) {
211 marinov  1.1.2.4                  Temp t = (Temp)ee.nextElement();
212 marinov  1.1.2.1                  System.out.println(t + "=" + map.get(t));
213 marinov  1.1.2.1              }
214 marinov  1.1.2.1              */
215 marinov  1.1.2.1          //}
216 marinov  1.1.2.1          //DEBUG
217 marinov  1.1.2.1   
218 marinov  1.1.2.6          /* added to try to save some memory */
219 marinov  1.1.2.7          if (noCache) { map = null; if (method.getName().equals("igen")) System.gc(); }
220 marinov  1.1.2.6          /* "regular" calculation */
221 marinov  1.1.2.1          if (outputChanged)
222 cananian 1.1.2.17             for (Iterator it=callees.iterator(); it.hasNext(); )
223 cananian 1.1.2.17                 environment.reanalyze((IntraProc)it.next());
224 marinov  1.1.2.8          //OUTPUT
225 marinov  1.1.2.8          if (noCache) 
226 marinov  1.1.2.8              System.out.println((System.currentTimeMillis()-TTT) + "ms]");
227 marinov  1.1.2.8          //OUTPUT
228 marinov  1.1.2.1      }
229 marinov  1.1.2.1  
230 marinov  1.1.2.1      HMethod[] calls() {
231 cananian 1.1.2.17         if (map==null) { map = new HashMap(); analyze(); }
232 pnkfelix 1.1.2.12         Set r = new HashSet();
233 cananian 1.5              for (Iterator e = code.getElementsI(); e.hasNext(); ) {
234 cananian 1.5                  Quad qq = (Quad) e.next();
235 marinov  1.1.2.1              if (!(qq instanceof CALL)) continue;
236 marinov  1.1.2.1              CALL q = (CALL) qq;
237 cananian 1.1.2.9              SetHClass[] paramTypes = new SetHClass[q.paramsLength()];
238 cananian 1.1.2.9              for (int i=0; i<q.paramsLength(); i++) {
239 cananian 1.1.2.9                  SetHClass s = (SetHClass)map.get(q.params(i));
240 cananian 1.3.2.1                  //assert s!=null;
241 marinov  1.1.2.2                  paramTypes[i] = s;
242 marinov  1.1.2.1              }
243 marinov  1.1.2.1              HMethod[] m;
244 cananian 1.1.2.9              if (!q.isVirtual()) m = new HMethod[]{ q.method() };
245 cananian 1.1.2.9              else m = possibleMethods(q.method(), paramTypes);
246 marinov  1.1.2.1              for (int i=0; i<m.length; i++)
247 cananian 1.1.2.17                 r.add(m[i]);
248 marinov  1.1.2.1          }
249 marinov  1.1.2.6          map = null;
250 cananian 1.1.2.17         return (HMethod[]) r.toArray(new HMethod[r.size()]);
251 marinov  1.1.2.5      }
252 marinov  1.1.2.5  
253 marinov  1.1.2.8      HMethod[] calls(CALL cs, boolean last) {
254 cananian 1.1.2.17         if (map==null) { map = new HashMap(); analyze(); }
255 pnkfelix 1.1.2.12         Set r = new HashSet();
256 cananian 1.1.2.9          SetHClass[] paramTypes = new SetHClass[cs.paramsLength()];
257 cananian 1.1.2.9          for (int i=0; i<cs.paramsLength(); i++) {
258 cananian 1.1.2.9              SetHClass s = (SetHClass)map.get(cs.params(i));
259 cananian 1.3.2.1              //assert s!=null;
260 marinov  1.1.2.5              paramTypes[i] = s;
261 marinov  1.1.2.5          }
262 marinov  1.1.2.5          HMethod[] m;
263 cananian 1.1.2.9          if (!cs.isVirtual()) m = new HMethod[]{ cs.method() };
264 cananian 1.1.2.9          else m = possibleMethods(cs.method(), paramTypes);
265 marinov  1.1.2.5          for (int i=0; i<m.length; i++)
266 cananian 1.1.2.17             r.add(m[i]);
267 marinov  1.1.2.8          if (last) map = null;
268 cananian 1.1.2.17         return (HMethod[]) r.toArray(new HMethod[r.size()]);
269 marinov  1.1.2.1      }
270 marinov  1.1.2.1  
271 marinov  1.1.2.6      SetHClass getTempType(Temp t) { 
272 cananian 1.1.2.17         if (map==null) { map = new HashMap(); analyze(); }
273 marinov  1.1.2.6          SetHClass s = (SetHClass)map.get(t);
274 marinov  1.1.2.6          map = null;
275 marinov  1.1.2.6          return s;
276 marinov  1.1.2.6      }
277 marinov  1.1.2.1  
278 cananian 1.1.2.17     Map map = null;
279 marinov  1.1.2.1      class TypeInfoVisitor extends QuadVisitor {
280 marinov  1.1.2.1          boolean modified = false;
281 cananian 1.1.2.17         Map checkcast;
282 cananian 1.1.2.17         TypeInfoVisitor(Map checkcast) { this.checkcast = checkcast; }
283 marinov  1.1.2.1  
284 marinov  1.1.2.1          public void visit(Quad q) { modified = false; }
285 marinov  1.1.2.1  
286 marinov  1.1.2.1          public void visit(AGET q) {
287 cananian 1.1.2.9              SetHClass t = (SetHClass)map.get(q.objectref());
288 marinov  1.1.2.1              if (t==null) { modified=false; return; }
289 cananian 1.1.2.9              modified = merge(q.dst(), t.getComponentType());
290 marinov  1.1.2.1              return;
291 marinov  1.1.2.1          }
292 marinov  1.1.2.1          public void visit(ALENGTH q) {
293 cananian 1.1.2.9              modified = merge(q.dst(), HClass.Int);
294 marinov  1.1.2.1          }
295 marinov  1.1.2.1          public void visit(ANEW q) {
296 cananian 1.1.2.9              modified = merge(q.dst(), environment.cone(q.hclass()));
297 marinov  1.1.2.1          }
298 marinov  1.1.2.1          public void visit(ASET q) {
299 marinov  1.1.2.1              /* ??? additional precision could be gained
300 marinov  1.1.2.1               */
301 marinov  1.1.2.1              modified = false;
302 marinov  1.1.2.1          }
303 marinov  1.1.2.1          public void visit(CALL q) {
304 marinov  1.1.2.1              boolean r = false;
305 cananian 1.1.2.9              SetHClass[] paramTypes = new SetHClass[q.paramsLength()];
306 cananian 1.1.2.9              for (int i=0; i<q.paramsLength(); i++) {
307 cananian 1.1.2.9                  SetHClass s = (SetHClass)map.get(q.params(i));
308 marinov  1.1.2.1                  if (s==null) { modified = false; return; }
309 marinov  1.1.2.2                  paramTypes[i] = s;
310 marinov  1.1.2.1              }
311 marinov  1.1.2.1              HMethod[] m;
312 cananian 1.1.2.9              if (!q.isVirtual()) m = new HMethod[]{ q.method() };
313 cananian 1.1.2.9              else m = possibleMethods(q.method(), paramTypes);
314 marinov  1.1.2.1              for (int i=0; i<m.length; i++) {
315 marinov  1.1.2.1                  IntraProc p = environment.getIntra(IntraProc.this, m[i], paramTypes);
316 cananian 1.1.2.9                  boolean r1 = (q.retval()==null) ? false : merge(q.retval(), p.getReturnType());
317 cananian 1.1.2.9                  boolean r2 = merge(q.retex(), p.getExceptionType());
318 marinov  1.1.2.1                  r = r || r1 || r2;
319 marinov  1.1.2.1              }
320 marinov  1.1.2.1              modified = r;
321 marinov  1.1.2.1          }
322 marinov  1.1.2.1          public void visit(COMPONENTOF q) {
323 cananian 1.1.2.9              modified = merge(q.dst(), HClass.Boolean);
324 marinov  1.1.2.1          }
325 marinov  1.1.2.1          public void visit(CONST q) {
326 cananian 1.1.2.9              modified = merge(q.dst(), q.type());
327 marinov  1.1.2.1          }
328 marinov  1.1.2.1          public void visit(GET q) {
329 cananian 1.1.2.9              modified = merge(q.dst(), environment.getType(q.field(), IntraProc.this));
330 marinov  1.1.2.1          }   
331 marinov  1.1.2.1          public void visit(SET q) {
332 cananian 1.1.2.9              SetHClass t = (SetHClass)map.get(q.src());
333 marinov  1.1.2.1              if (t==null) { modified = false; return; }
334 cananian 1.1.2.9              environment.mergeType(q.field(), t);
335 marinov  1.1.2.1              modified = false;
336 marinov  1.1.2.1          }
337 marinov  1.1.2.1          public void visit(INSTANCEOF q) {
338 cananian 1.1.2.9              modified = merge(q.dst(), HClass.Boolean);
339 marinov  1.1.2.1          }
340 cananian 1.1.2.10         public void visit(METHOD q) {
341 marinov  1.1.2.1              boolean r = false;
342 cananian 1.1.2.9              for (int i=0; i<q.paramsLength(); i++)
343 cananian 1.1.2.9                  if (merge(q.params(i), parameterTypes[i])) 
344 marinov  1.1.2.1                      r = true;
345 marinov  1.1.2.1              modified = r;
346 marinov  1.1.2.1          }
347 marinov  1.1.2.1          public void visit(MOVE q) {
348 cananian 1.1.2.9              SetHClass t = (SetHClass)map.get(q.src());
349 marinov  1.1.2.1              if (t==null) { modified = false; return; }
350 cananian 1.1.2.9              modified = move(q.dst(), t);
351 marinov  1.1.2.1          }
352 marinov  1.1.2.1          public void visit(NEW q) {
353 cananian 1.1.2.9              modified = merge(q.dst(), q.hclass());
354 marinov  1.1.2.1          }
355 marinov  1.1.2.1          public void visit(OPER q) {
356 cananian 1.1.2.9              modified = merge(q.dst(), q.evalType());
357 marinov  1.1.2.1          }
358 marinov  1.1.2.1          public void visit(PHI q) {
359 marinov  1.1.2.1              boolean r = false;
360 cananian 1.1.2.9              for (int i=0; i<q.numPhis(); i++)
361 cananian 1.1.2.9                  for (int j=0; j<q.arity(); j++) {
362 cananian 1.1.2.9                      if (q.src(i,j)==null) continue;
363 cananian 1.1.2.9                      SetHClass t = (SetHClass)map.get(q.src(i,j));
364 marinov  1.1.2.1                      if (t==null) continue;
365 cananian 1.1.2.9                      if (merge(q.dst(i), t))
366 marinov  1.1.2.1                          r = true;
367 marinov  1.1.2.1                  }
368 marinov  1.1.2.1              modified = r;
369 marinov  1.1.2.1          }
370 marinov  1.1.2.1          public void visit(SIGMA q) {
371 marinov  1.1.2.1              boolean r = false;
372 cananian 1.1.2.9              for (int i=0; i<q.numSigmas(); i++) {
373 cananian 1.1.2.9                  if (q.src(i)==null) continue;
374 cananian 1.1.2.9                  SetHClass t = (SetHClass)map.get(q.src(i));
375 marinov  1.1.2.1                  if (t==null) continue;
376 cananian 1.1.2.9                  for (int j=0; j<q.arity(); j++)
377 cananian 1.1.2.9                      if (move(q.dst(i,j), t))
378 marinov  1.1.2.1                          r = true;
379 marinov  1.1.2.1              }
380 marinov  1.1.2.1              modified = r;
381 marinov  1.1.2.1          }
382 marinov  1.1.2.1          /* ??? additional precision could be gained
383 marinov  1.1.2.1             public void visit(CJMP q) {
384 marinov  1.1.2.1             modified = false;
385 cananian 1.1.2.18             }
386 cananian 1.1.2.18             public void visit(TYPESWITCH q) {
387 cananian 1.1.2.18             modified = false;
388 marinov  1.1.2.1              }
389 marinov  1.1.2.1          */
390 marinov  1.1.2.1          public void visit(RETURN q) {
391 cananian 1.1.2.9              if (q.retval()!=null) {
392 cananian 1.1.2.9                  SetHClass s = (SetHClass)map.get(q.retval());
393 marinov  1.1.2.1                  if (s!=null)
394 marinov  1.1.2.1                      outputChanged = returnType.union(s) || outputChanged;
395 marinov  1.1.2.1              }
396 marinov  1.1.2.1              modified = false;
397 marinov  1.1.2.1          }
398 marinov  1.1.2.1          public void visit(THROW q) {
399 cananian 1.1.2.9              SetHClass s = (SetHClass)map.get(q.throwable());
400 marinov  1.1.2.1              if (s!=null)
401 marinov  1.1.2.7                  if (exceptionAnalysis) // UGLY?! otherwise, running out of memory now
402 marinov  1.1.2.7                      outputChanged = exceptionType.union(s) || outputChanged;
403 marinov  1.1.2.1              modified = false;
404 marinov  1.1.2.1          }
405 marinov  1.1.2.1      }
406 marinov  1.1.2.1  
407 marinov  1.1.2.7      boolean move(Temp t, SetHClass newType) {
408 marinov  1.1.2.7          SetHClass oldType = (SetHClass)map.get(t);
409 marinov  1.1.2.7          if (oldType==null) { 
410 marinov  1.1.2.7              map.put(t, newType); 
411 marinov  1.1.2.7              return true;
412 marinov  1.1.2.7          }
413 marinov  1.1.2.7          // if the merged value is different from the old value, update...
414 marinov  1.1.2.7          if (oldType.union(newType)) {
415 marinov  1.1.2.7              map.put(t, oldType);
416 marinov  1.1.2.7              return true;
417 marinov  1.1.2.7          } else return false;
418 marinov  1.1.2.7      }
419 marinov  1.1.2.7  
420 marinov  1.1.2.1      boolean merge(Temp t, SetHClass newType) {
421 marinov  1.1.2.1          SetHClass oldType = (SetHClass)map.get(t);
422 marinov  1.1.2.1          if (oldType==null) { 
423 marinov  1.1.2.1              map.put(t, newType.copy()); 
424 marinov  1.1.2.1              return true;
425 marinov  1.1.2.1          }
426 marinov  1.1.2.1          // if the merged value is different from the old value, update...
427 marinov  1.1.2.1          if (oldType.union(newType)) {
428 marinov  1.1.2.1              map.put(t, oldType);
429 marinov  1.1.2.1              return true;
430 marinov  1.1.2.1          } else return false;
431 marinov  1.1.2.1      }
432 marinov  1.1.2.1      
433 marinov  1.1.2.1      boolean merge(Temp t, HClass c) { return merge(t, new SetHClass(c)); }
434 marinov  1.1.2.7  
435 marinov  1.1.2.7      public String toString() {
436 marinov  1.1.2.7          StringBuffer s = new StringBuffer();
437 marinov  1.1.2.7          s.append(method.getDeclaringClass() + " " + method.getName() + " ");
438 marinov  1.1.2.7          for (int i=0; i<parameterTypes.length; i++)
439 marinov  1.1.2.7              s.append(parameterTypes[i] + " ");
440 marinov  1.1.2.7          s.append(returnType);
441 marinov  1.1.2.7          return s.toString();
442 marinov  1.1.2.7      }
443 marinov  1.1.2.1  
444 cananian 1.2      }